Merged revisions 2989,2994,2996-2999,3001,3003-3004,3007,3010,3012,3015-3016,3026-3029,3036-3038,3040-3041,3046,3048,3050,3052,3054-3055,3057-3058,3066,3069-3073 from 1.0 branch via svnmerge

This commit is contained in:
Dan Stillman 2008-07-22 05:45:32 +00:00
parent 975e81afab
commit 0f71fdbc35
13 changed files with 1473 additions and 326 deletions

View file

@ -148,7 +148,7 @@
], ],
"sk-SK": [ "sk-SK": [
"athelas" "Milan Regec"
], ],
"sl-SI": [ "sl-SI": [

View file

@ -0,0 +1,102 @@
/*
***** BEGIN LICENSE BLOCK *****
Copyright (c) 2006 Center for History and New Media
George Mason University, Fairfax, Virginia, USA
http://chnm.gmu.edu
Licensed under the Educational Community License, Version 1.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.opensource.org/licenses/ecl1.php
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.
***** END LICENSE BLOCK *****
*/
Zotero_Charset_Menu = new function() {
this.populate = populate;
/**
* Populate a character set menu, placing more commonly used character sets
* closer to the top
*
* @param {DOMElement} charsetMenu The menu to populate
* @param {Boolean} showEndian Whether to show endian (e.g., UTF-32) options
**/
function populate(charsetMenu, showEndian) {
var charsetMap = {};
// get charset popup and charset RDF
var charsetPopup = document.createElement("menupopup");
charsetMenu.appendChild(charsetPopup);
var charsetSeparator = document.createElement("menuseparator");
charsetPopup.appendChild(charsetSeparator);
var rdfService = Components.classes["@mozilla.org/rdf/rdf-service;1"].
getService(Components.interfaces.nsIRDFService);
var RDFCU = Components.classes["@mozilla.org/rdf/container-utils;1"].
getService(Components.interfaces.nsIRDFContainerUtils);
var rdfDataSource = rdfService.GetDataSource("rdf:charset-menu");
var rdfName = rdfService.GetResource("http://home.netscape.com/NC-rdf#Name");
var rdfContainer = Components.classes["@mozilla.org/rdf/container;1"].
createInstance(Components.interfaces.nsIRDFContainer);
rdfContainer.Init(rdfDataSource, rdfService.GetResource("NC:EncodersRoot"));
var charsets = rdfContainer.GetElements();
// add charsets to popup in order
while(charsets.hasMoreElements()) {
var charset = charsets.getNext().QueryInterface(Components.interfaces.nsIRDFResource);
var label = rdfDataSource.GetTarget(charset, rdfName, true).
QueryInterface(Components.interfaces.nsIRDFLiteral);
charset = charset.Value;
label = label.Value;
var isUTF16 = charset.length >= 6 && charset.substr(0, 6) == "UTF-16";
// Show UTF-16 element appropriately depending on showEndian
if(isUTF16 && showEndian == (charset == "UTF-16") ||
(!showEndian && charset == "UTF-32LE")) {
continue;
} else if(charset == "x-mac-roman") {
// use the IANA name
value = "macintosh";
} else if(!showEndian && charset == "UTF-32BE") {
label = "Unicode (UTF-32)";
value = "UTF-32";
}
// add element
var itemNode = document.createElement("menuitem");
itemNode.setAttribute("label", label);
itemNode.setAttribute("value", charset);
charsetMap[charset] = itemNode;
if(isUTF16 || (label.length > 7 &&
label.substr(0, 7) == "Western")) {
charsetPopup.insertBefore(itemNode, charsetSeparator);
} else if(charset == "UTF-8") {
var oldFirst = (charsetPopup.firstChild ? charsetPopup.firstChild : null);
charsetPopup.insertBefore(itemNode, oldFirst);
// also add (without BOM) if requested
if(showEndian) {
var itemNode = document.createElement("menuitem");
itemNode.setAttribute("label", Zotero.getString("charset.UTF8withoutBOM"));
itemNode.setAttribute("value", charset+"xBOM");
charsetMap[charset+"xBOM"] = itemNode;
charsetPopup.insertBefore(itemNode, oldFirst);
}
} else {
charsetPopup.appendChild(itemNode);
}
}
return charsetMap;
}
}

View file

@ -26,6 +26,8 @@
// //
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
const OPTION_PREFIX = "export-option-";
// Class to provide options for export // Class to provide options for export
var Zotero_File_Interface_Export = new function() { var Zotero_File_Interface_Export = new function() {
@ -34,6 +36,8 @@ var Zotero_File_Interface_Export = new function() {
this.accept = accept; this.accept = accept;
this.cancel = cancel; this.cancel = cancel;
var _charsets;
/* /*
* add options to export * add options to export
*/ */
@ -46,17 +50,19 @@ var Zotero_File_Interface_Export = new function() {
var translators = window.arguments[0].translators; var translators = window.arguments[0].translators;
var listbox = document.getElementById("format-popup"); // get format popup
var formatPopup = document.getElementById("format-popup");
var formatMenu = document.getElementById("format-menu"); var formatMenu = document.getElementById("format-menu");
var optionsBox = document.getElementById("translator-options"); var optionsBox = document.getElementById("translator-options");
var charsetBox = document.getElementById("charset-box");
var selectedTranslator = Zotero.Prefs.get("export.lastTranslator"); var selectedTranslator = Zotero.Prefs.get("export.lastTranslator");
// add styles to list // add styles to format popup
for(var i in translators) { for(var i in translators) {
var itemNode = document.createElement("menuitem"); var itemNode = document.createElement("menuitem");
itemNode.setAttribute("label", translators[i].label); itemNode.setAttribute("label", translators[i].label);
listbox.appendChild(itemNode); formatPopup.appendChild(itemNode);
// add options // add options
for(var option in translators[i].displayOptions) { for(var option in translators[i].displayOptions) {
@ -73,9 +79,9 @@ var Zotero_File_Interface_Export = new function() {
// it interprets as checkboxes // it interprets as checkboxes
if(typeof(translators[i].displayOptions[option]) == "boolean") { if(typeof(translators[i].displayOptions[option]) == "boolean") {
var checkbox = document.createElement("checkbox"); var checkbox = document.createElement("checkbox");
checkbox.setAttribute("id", "export-option-"+option); checkbox.setAttribute("id", OPTION_PREFIX+option);
checkbox.setAttribute("label", optionLabel); checkbox.setAttribute("label", optionLabel);
optionsBox.appendChild(checkbox); optionsBox.insertBefore(checkbox, charsetBox);
} }
addedOptions[option] = true; addedOptions[option] = true;
@ -93,6 +99,9 @@ var Zotero_File_Interface_Export = new function() {
formatMenu.selectedIndex = 0; formatMenu.selectedIndex = 0;
} }
// from charsetMenu.js
_charsets = Zotero_Charset_Menu.populate(document.getElementById(OPTION_PREFIX+"exportCharset"), true);
updateOptions(Zotero.Prefs.get("export.translatorSettings")); updateOptions(Zotero.Prefs.get("export.translatorSettings"));
} }
@ -105,7 +114,9 @@ var Zotero_File_Interface_Export = new function() {
var translatorOptions = window.arguments[0].translators[index].displayOptions; var translatorOptions = window.arguments[0].translators[index].displayOptions;
if(optionString) { if(optionString) {
var options = optionString.split(","); try {
var options = Zotero.JSON.unserialize(optionString);
} catch(e) {}
} }
var optionsBox = document.getElementById("translator-options"); var optionsBox = document.getElementById("translator-options");
@ -114,8 +125,13 @@ var Zotero_File_Interface_Export = new function() {
for(var i=0; i<optionsBox.childNodes.length; i++) { for(var i=0; i<optionsBox.childNodes.length; i++) {
// loop through options to see which should be enabled // loop through options to see which should be enabled
var node = optionsBox.childNodes[i]; var node = optionsBox.childNodes[i];
var optionName = node.getAttribute("id").toString().substr(14); // skip non-options
if(node.id.length <= OPTION_PREFIX.length
|| node.id.substr(0, OPTION_PREFIX.length) != OPTION_PREFIX) {
continue;
}
var optionName = node.id.substr(OPTION_PREFIX.length);
if(translatorOptions[optionName] != undefined) { if(translatorOptions[optionName] != undefined) {
// option should be enabled // option should be enabled
optionsBox.hidden = undefined; optionsBox.hidden = undefined;
@ -123,9 +139,9 @@ var Zotero_File_Interface_Export = new function() {
var defValue = translatorOptions[optionName]; var defValue = translatorOptions[optionName];
if(typeof(defValue) == "boolean") { if(typeof(defValue) == "boolean") {
if(optionString) { if(options && options[optionName] !== undefined) {
// if there's a saved prefs string, use it // if there's a saved prefs string, use it
var isChecked = options.shift(); var isChecked = options[optionName];
} else { } else {
// use defaults // use defaults
var isChecked = (defValue ? "true" : "false"); var isChecked = (defValue ? "true" : "false");
@ -135,10 +151,25 @@ var Zotero_File_Interface_Export = new function() {
} else { } else {
// option should be disabled and unchecked to prevent confusion // option should be disabled and unchecked to prevent confusion
node.hidden = true; node.hidden = true;
node.setAttribute("checked", "false"); node.checked = false;
} }
} }
// handle charset popup
var charsetMenu = document.getElementById(OPTION_PREFIX+"exportCharset");
if(translatorOptions.exportCharset) {
document.getElementById("charset-box").hidden = undefined;
optionsBox.hidden = undefined;
var charset = "UTF-8xBOM";
if(options && options.exportCharset && _charsets[options.exportCharset]) {
charset = options.exportCharset;
} else if(translatorOptions.exportCharset && _charsets[translatorOptions.exportCharset]) {
charset = translatorOptions.exportCharset;
}
charsetMenu.selectedItem = _charsets[charset];
}
window.sizeToContent(); window.sizeToContent();
} }
@ -158,21 +189,20 @@ var Zotero_File_Interface_Export = new function() {
var optionsAvailable = window.arguments[0].selectedTranslator.displayOptions; var optionsAvailable = window.arguments[0].selectedTranslator.displayOptions;
for(var option in optionsAvailable) { for(var option in optionsAvailable) {
var defValue = optionsAvailable[option]; var defValue = optionsAvailable[option];
var element = document.getElementById("export-option-"+option); var element = document.getElementById(OPTION_PREFIX+option);
if(typeof(defValue) == "boolean") { if(option == "exportCharset") {
if(element.checked == true) { optionsAvailable[option] = element.selectedItem.value;
optionString += ",true"; } else if(typeof(defValue) == "boolean") {
optionsAvailable[option] = true; optionsAvailable[option] = !!element.checked;
} else {
optionString += ",false";
optionsAvailable[option] = false;
}
} }
} }
// save options // save options
if(optionString) optionString = optionString.substr(1); Zotero.debug("EXPORT OPTIONS");
Zotero.debug(optionsAvailable);
optionString = Zotero.JSON.serialize(optionsAvailable);
Zotero.debug(optionString);
Zotero.Prefs.set("export.translatorSettings", optionString); Zotero.Prefs.set("export.translatorSettings", optionString);
} }

View file

@ -1,7 +1,13 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?> <?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<!DOCTYPE window SYSTEM "chrome://zotero/locale/zotero.dtd"> <!DOCTYPE window [
<!ENTITY % zoteroDTD SYSTEM "chrome://zotero/locale/zotero.dtd" >
%zoteroDTD;
<!ENTITY % charsetDTD SYSTEM "chrome://global/locale/charsetOverlay.dtd" >
%charsetDTD;
]>
<dialog xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" <dialog xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
title="&zotero.exportOptions.title;" buttons="cancel,accept" title="&zotero.exportOptions.title;" buttons="cancel,accept"
ondialogaccept="Zotero_File_Interface_Export.accept()" ondialogaccept="Zotero_File_Interface_Export.accept()"
ondialogcancel="Zotero_File_Interface_Export.cancel()" ondialogcancel="Zotero_File_Interface_Export.cancel()"
@ -9,7 +15,15 @@
onload="Zotero_File_Interface_Export.init()"> onload="Zotero_File_Interface_Export.init()">
<script src="include.js"/> <script src="include.js"/>
<script src="charsetMenu.js"/>
<script src="exportOptions.js"/> <script src="exportOptions.js"/>
<script type="application/javascript">
<![CDATA[
var observerService = Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService);
observerService.notifyObservers(null, "charsetmenu-selected", "other");
]]>
</script>
<vbox id="zotero-export-options-container" flex="1"> <vbox id="zotero-export-options-container" flex="1">
<hbox> <hbox>
@ -19,7 +33,13 @@
</menulist> </menulist>
</hbox> </hbox>
<groupbox id="translator-options"> <groupbox id="translator-options">
<caption label="&zotero.exportOptions.translatorOptions.label;"/> <caption id="translator-options-label" label="&zotero.exportOptions.translatorOptions.label;"/>
<vbox id="charset-box" hidden="true">
<separator class="thin"/>
<label value="&zotero.charset.label;:" control="charset-menu"/>
<menulist id="export-option-exportCharset"/>
</vbox>
</groupbox> </groupbox>
</vbox> </vbox>
</dialog> </dialog>

View file

@ -44,7 +44,7 @@ Zotero_File_Exporter.prototype.save = function() {
// present options dialog // present options dialog
var io = {translators:translators} var io = {translators:translators}
window.openDialog("chrome://zotero/content/exportOptions.xul", window.openDialog("chrome://zotero/content/exportOptions.xul",
"_blank", "chrome,modal,centerscreen", io); "_blank", "chrome,modal,centerscreen,resizable=no", io);
if(!io.selectedTranslator) { if(!io.selectedTranslator) {
return false; return false;
} }
@ -209,30 +209,34 @@ var Zotero_File_Interface = new function() {
if (rv == nsIFilePicker.returnOK || rv == nsIFilePicker.returnReplace) { if (rv == nsIFilePicker.returnOK || rv == nsIFilePicker.returnReplace) {
translation.setLocation(fp.file); translation.setLocation(fp.file);
// get translators again, bc now we can check against the file // get translators again, bc now we can check against the file
translation.setHandler("translators", function(obj, item) { _importTranslatorsAvailable(obj, item) });
translators = translation.getTranslators(); translators = translation.getTranslators();
if(translators.length) { }
// create a new collection to take in imported items }
var date = new Date();
_importCollection = Zotero.Collections.add(Zotero.getString("fileInterface.imported")+" "+date.toLocaleString()); function _importTranslatorsAvailable(translation, translators) {
if(translators.length) {
// import items // create a new collection to take in imported items
translation.setTranslator(translators[0]); var date = new Date();
translation.setHandler("collectionDone", _importCollectionDone); _importCollection = Zotero.Collections.add(Zotero.getString("fileInterface.imported")+" "+date.toLocaleString());
translation.setHandler("done", _importDone);
Zotero.UnresponsiveScriptIndicator.disable(); // import items
translation.setTranslator(translators[0]);
// show progress indicator translation.setHandler("collectionDone", _importCollectionDone);
Zotero_File_Interface.Progress.show( translation.setHandler("done", _importDone);
Zotero.getString("fileInterface.itemsImported"), Zotero.UnresponsiveScriptIndicator.disable();
function() {
Zotero.DB.beginTransaction(); // show progress indicator
Zotero_File_Interface.Progress.show(
// translate Zotero.getString("fileInterface.itemsImported"),
translation.translate(); function() {
}); Zotero.DB.beginTransaction();
} else {
window.alert(Zotero.getString("fileInterface.fileFormatUnsupported")); // translate
} translation.translate();
});
} else {
window.alert(Zotero.getString("fileInterface.fileFormatUnsupported"));
} }
} }

View file

@ -410,9 +410,9 @@ var ZoteroPane = new function()
return; return;
} }
// Ignore modifiers other than accel-alt (or accel-shift if useShift is on) // Ignore modifiers other than Ctrl-Alt or Cmd-Shift
if (!((Zotero.isMac ? event.metaKey : event.ctrlKey) && if (!((Zotero.isMac ? event.metaKey : event.ctrlKey) &&
useShift ? event.shiftKey : event.altKey)) { (useShift ? event.shiftKey : event.altKey))) {
return; return;
} }
@ -1400,6 +1400,10 @@ var ZoteroPane = new function()
if (this.itemsView.rowCount>0) { if (this.itemsView.rowCount>0) {
var enable = [m.exportCollection, m.createBibCollection, m.loadReport]; var enable = [m.exportCollection, m.createBibCollection, m.loadReport];
} }
else if (!this.collectionsView.isContainerEmpty(this.collectionsView.selection.currentIndex)) {
var enable = [m.exportCollection];
var disable = [m.createBibCollection, m.loadReport];
}
else else
{ {
var disable = [m.exportCollection, m.createBibCollection, m.loadReport]; var disable = [m.exportCollection, m.createBibCollection, m.loadReport];
@ -2038,13 +2042,15 @@ var ZoteroPane = new function()
var isNative = Zotero.MIME.hasNativeHandler(mimeType, ext); var isNative = Zotero.MIME.hasNativeHandler(mimeType, ext);
var internal = Zotero.MIME.hasInternalHandler(mimeType, ext); var internal = Zotero.MIME.hasInternalHandler(mimeType, ext);
var fileURL = attachment.getLocalFileURL();
if (isNative || if (isNative ||
(internal && !Zotero.Prefs.get('launchNonNativeFiles'))) { (internal && !Zotero.Prefs.get('launchNonNativeFiles'))) {
this.loadURI(fileURL, event, { attachmentID: itemID});
var url = 'zotero://attachment/' + itemID + '/';
this.loadURI(url, event, { attachmentID: itemID});
} }
else { else {
var fileURL = attachment.getLocalFileURL();
// Some platforms don't have nsILocalFile.launch, so we just load it and // Some platforms don't have nsILocalFile.launch, so we just load it and
// let the Firefox external helper app window handle it // let the Firefox external helper app window handle it
try { try {

View file

@ -701,7 +701,7 @@ Zotero.CSL.prototype.formatBibliography = function(itemSet, format) {
if(format == "HTML") { if(format == "HTML") {
var coins = Zotero.OpenURL.createContextObject(item.zoteroItem, "1.0"); var coins = Zotero.OpenURL.createContextObject(item.zoteroItem, "1.0");
var span = (coins ? ' <span class="Z3988" title="'+coins.replace("&", "&amp;", "g")+'"></span>' : ''); var span = (coins ? ' <span class="Z3988" title="'+coins.replace("&", "&amp;", "g")+'">&nbsp;</span>' : '');
if(this.class == "note" && isCitation) { if(this.class == "note" && isCitation) {
output += "<li>"+string+span+"</li>\r\n"; output += "<li>"+string+span+"</li>\r\n";

View file

@ -24,6 +24,18 @@
// Zotero Translate Engine // Zotero Translate Engine
// //
/**
* Set of byte order marks
**/
const BOMs = {
"UTF-8":"\xEF\xBB\xBF",
"UTF-16BE":"\xFE\xFF",
"UTF-16LE":"\xFF\xFE",
"UTF-32BE":"\x00\x00\xFE\xFF",
"UTF-32LE":"\xFF\xFE\x00\x00"
}
/* /*
* Zotero.Translate: a class for translation of Zotero metadata from and to * Zotero.Translate: a class for translation of Zotero metadata from and to
* other formats * other formats
@ -80,6 +92,7 @@
* *
* PRIVATE PROPERTIES: * PRIVATE PROPERTIES:
* *
* _charset - character set
* _numericTypes - possible numeric types as a comma-delimited string * _numericTypes - possible numeric types as a comma-delimited string
* _handlers - handlers for various events (see setHandler) * _handlers - handlers for various events (see setHandler)
* _sandbox - sandbox in which translators will be executed * _sandbox - sandbox in which translators will be executed
@ -92,7 +105,6 @@
* _storage - the stored string to be treated as input * _storage - the stored string to be treated as input
* _storageLength - the length of the stored string * _storageLength - the length of the stored string
* _exportFileDirectory - the directory to which files will be exported * _exportFileDirectory - the directory to which files will be exported
* _hasBOM - whether the given file ready to be imported has a BOM or not
* *
* WEB-ONLY PROPERTIES: * WEB-ONLY PROPERTIES:
* *
@ -105,7 +117,6 @@
* *
* output - export output (if no location has been specified) * output - export output (if no location has been specified)
*/ */
Zotero.Translate = function(type, saveItem) { Zotero.Translate = function(type, saveItem) {
this.type = type; this.type = type;
@ -471,9 +482,6 @@ Zotero.Translate.prototype.getTranslators = function() {
// do not allow simultaneous instances of getTranslators // do not allow simultaneous instances of getTranslators
if(this._translatorSearch) this._translatorSearch.running = false; if(this._translatorSearch) this._translatorSearch.running = false;
// clear BOM
this._hasBOM = null;
if(Zotero.Translate.cache) { if(Zotero.Translate.cache) {
var translators = Zotero.Translate.cache[this.type]; var translators = Zotero.Translate.cache[this.type];
} else { } else {
@ -543,7 +551,6 @@ Zotero.Translate.prototype.translate = function() {
this._IDMap = new Array(); this._IDMap = new Array();
this._complete = false; this._complete = false;
this._itemsDone = false; this._itemsDone = false;
this._hasBOM = null;
if(!this.translator || !this.translator.length) { if(!this.translator || !this.translator.length) {
throw("cannot translate: no translator specified"); throw("cannot translate: no translator specified");
@ -593,8 +600,8 @@ Zotero.Translate.prototype.translate = function() {
* parses translator detect code * parses translator detect code
*/ */
Zotero.Translate.prototype._parseDetectCode = function(translator) { Zotero.Translate.prototype._parseDetectCode = function(translator) {
this.configOptions = new Array(); this.configOptions = {};
this.displayOptions = new Array(); this.displayOptions = {};
if(translator.detectCode) { if(translator.detectCode) {
var detectCode = translator.detectCode; var detectCode = translator.detectCode;
@ -672,7 +679,7 @@ Zotero.Translate.prototype._generateSandbox = function() {
if(this.type == "import") { if(this.type == "import") {
// add routines to add new collections // add routines to add new collections
this._sandbox.Zotero.Collection = Zotero.Translate.GenerateZoteroItemClass(); this._sandbox.Zotero.Collection = Zotero.Translate.GenerateZoteroCollectionClass();
// attach the function to be run when a collection is done // attach the function to be run when a collection is done
this._sandbox.Zotero.Collection.prototype.complete = function() {me._collectionDone(this)}; this._sandbox.Zotero.Collection.prototype.complete = function() {me._collectionDone(this)};
} }
@ -1528,9 +1535,9 @@ Zotero.Translate.prototype._web = function() {
return true; return true;
} }
/* /**
* does the actual search translation * Does the actual search translation
*/ **/
Zotero.Translate.prototype._search = function() { Zotero.Translate.prototype._search = function() {
try { try {
this._sandbox.doSearch(this.search); this._sandbox.doSearch(this.search);
@ -1542,11 +1549,47 @@ Zotero.Translate.prototype._search = function() {
return true; return true;
} }
/* /**
* does the actual import translation * Does the actual import translation
*/ **/
Zotero.Translate.prototype._import = function() { Zotero.Translate.prototype._import = function() {
this._importConfigureIO(); this.waitForCompletion = true;
var me = this;
this._importGetCharacterSet(function(charset) { me._importDoComplete(charset) });
return true;
}
/**
* Sniff file if a real file exists
*
* @param {Function} callback A callback function to be executed after sniffing
**/
Zotero.Translate.prototype._importGetCharacterSet = function(callback) {
if(!this._storage) {
// need to check charset
if(this._charset) {
// have charset already; just go on
callback(this._charset);
} else {
// look for charset
var me = this;
Zotero.File.getCharsetFromFile(this.location, "text/plain",
function(charset) {
me._charset = charset;
callback(charset);
});
}
} else {
callback();
}
}
/**
* Complete import (used as callback after sniffing)
**/
Zotero.Translate.prototype._importDoComplete = function(charset) {
this._importConfigureIO(charset);
try { try {
this._sandbox.doImport(); this._sandbox.doImport();
@ -1558,14 +1601,13 @@ Zotero.Translate.prototype._import = function() {
return false; return false;
} }
} }
this._translationComplete(true);
return true;
} }
/* /*
* sets up import for IO * set up import for IO
*/ */
Zotero.Translate.prototype._importConfigureIO = function() { Zotero.Translate.prototype._importConfigureIO = function(charset) {
if(this._storage) { if(this._storage) {
if(this.configOptions.dataMode && this.configOptions.dataMode == "rdf") { if(this.configOptions.dataMode && this.configOptions.dataMode == "rdf") {
this._rdf = new Object(); this._rdf = new Object();
@ -1622,32 +1664,43 @@ Zotero.Translate.prototype._importConfigureIO = function() {
} }
var filePosition = 0; var filePosition = 0;
var intlStream = this._importDefuseBOM();
if(intlStream) { if(charset) { // if have detected charset
// found a UTF BOM at the beginning of the file; don't allow Zotero.debug("Using detected character set "+charset);
// translator to set the character set // seek past BOM
this._sandbox.Zotero.setCharacterSet = function() {} if(charset.length > 3 && charset.substr(0, 3) == "UTF") {
this._streams.push(intlStream); var BOMLength = this._importGetBOMLength();
} else { this._inputStream.QueryInterface(Components.interfaces.nsISeekableStream)
// allow translator to set charset .seek(Components.interfaces.nsISeekableStream.NS_SEEK_SET, BOMLength);
this._sandbox.Zotero.setCharacterSet = function(charset) {
// seek
if(filePosition != 0) {
me._inputStream.QueryInterface(Components.interfaces.nsISeekableStream)
.seek(Components.interfaces.nsISeekableStream.NS_SEEK_SET, filePosition);
me._inputStream.QueryInterface(Components.interfaces.nsIFileInputStream);
}
intlStream = Components.classes["@mozilla.org/intl/converter-input-stream;1"]
.createInstance(Components.interfaces.nsIConverterInputStream);
try {
intlStream.init(me._inputStream, charset, 65535,
Components.interfaces.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER);
} catch(e) {
throw "Text encoding not supported";
}
me._streams.push(intlStream);
} }
// convert from detected charset
var intlStream = Components.classes["@mozilla.org/intl/converter-input-stream;1"]
.createInstance(Components.interfaces.nsIConverterInputStream);
intlStream.init(this._inputStream, charset, 65535,
Components.interfaces.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER);
me._streams.push(intlStream);
}
// allow translator to set charset
this._sandbox.Zotero.setCharacterSet = function(charset) {
// seek
if(filePosition != 0) {
me._inputStream.QueryInterface(Components.interfaces.nsISeekableStream)
.seek(Components.interfaces.nsISeekableStream.NS_SEEK_SET, filePosition);
me._inputStream.QueryInterface(Components.interfaces.nsIFileInputStream);
}
intlStream = Components.classes["@mozilla.org/intl/converter-input-stream;1"]
.createInstance(Components.interfaces.nsIConverterInputStream);
try {
intlStream.init(me._inputStream, charset, 65535,
Components.interfaces.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER);
} catch(e) {
throw "Text encoding not supported";
}
me._streams.push(intlStream);
} }
var str = new Object(); var str = new Object();
@ -1703,87 +1756,49 @@ Zotero.Translate.prototype._importConfigureIO = function() {
} }
} }
/* /**
* searches for a UTF BOM at the beginning of the input stream. if one is found, * Searches for a UTF BOM at the beginning of the input stream.
* returns an appropriate converter-input-stream for the UTF type, and sets *
* _hasBOM to the UTF type. if one is not found, returns false, and sets * @return The length of the UTF BOM.
* _hasBOM to false to prevent further checking.
*/ */
Zotero.Translate.prototype._importDefuseBOM = function() { Zotero.Translate.prototype._importGetBOMLength = function() {
// if already found not to have a BOM, skip // if not checked for a BOM, open a binary input stream and read
if(this._hasBOM === false) { var binStream = Components.classes["@mozilla.org/binaryinputstream;1"].
return; createInstance(Components.interfaces.nsIBinaryInputStream);
} binStream.setInputStream(this._inputStream);
if(!this._hasBOM) { var possibleBOMs = BOMs;
// if not checked for a BOM, open a binary input stream and read var couldHaveBOM = true;
var binStream = Components.classes["@mozilla.org/binaryinputstream;1"]. var newBOMs, readByte;
createInstance(Components.interfaces.nsIBinaryInputStream);
binStream.setInputStream(this._inputStream); while(couldHaveBOM) {
newBOMs = {};
couldHaveBOM = false;
// read the first byte readByte = binStream.read8();
var byte1 = binStream.read8(); readChar = String.fromCharCode(readByte)
// at the moment, we don't support UTF-32 or UTF-7. while mozilla for(var charset in possibleBOMs) {
// supports these encodings, they add slight additional complexity to if(possibleBOMs[charset][0] == readChar) {
// the function and anyone using them for storing bibliographic metadata if(possibleBOMs[charset].length == 1) {
// is insane. // have checked entire BOM
if(byte1 == 0xEF) { // UTF-8: EF BB BF return BOMs[charset].length;
var byte2 = binStream.read8(); } else {
if(byte2 == 0xBB) { // keep checking
var byte3 = binStream.read8(); newBOMs[charset] = possibleBOMs[charset].substr(1);
if(byte3 == 0xBF) { couldHaveBOM = true;
this._hasBOM = "UTF-8";
} }
} }
} else if(byte1 == 0xFE) { // UTF-16BE: FE FF
var byte2 = binStream.read8();
if(byte2 == 0xFF) {
this._hasBOM = "UTF-16BE";
}
} else if(byte1 == 0xFF) { // UTF-16LE: FF FE
var byte2 = binStream.read8();
if(byte2 == 0xFE) {
this._hasBOM = "UTF16-LE";
}
} }
if(!this._hasBOM) { possibleBOMs = newBOMs;
// seek back to begining of file
this._inputStream.QueryInterface(Components.interfaces.nsISeekableStream)
.seek(Components.interfaces.nsISeekableStream.NS_SEEK_SET, 0);
this._inputStream.QueryInterface(Components.interfaces.nsIFileInputStream);
// say there's no BOM
this._hasBOM = false;
return false;
}
} else {
// if it had a BOM the last time, it has one this time, too. seek to the
// correct position.
if(this._hasBOM == "UTF-8") {
var seekPosition = 3;
} else {
var seekPosition = 2;
}
this._inputStream.QueryInterface(Components.interfaces.nsISeekableStream)
.seek(Components.interfaces.nsISeekableStream.NS_SEEK_SET, seekPosition);
this._inputStream.QueryInterface(Components.interfaces.nsIFileInputStream);
} }
// if we know what kind of BOM it has, generate an input stream return 0;
var intlStream = Components.classes["@mozilla.org/intl/converter-input-stream;1"]
.createInstance(Components.interfaces.nsIConverterInputStream);
intlStream.init(this._inputStream, this._hasBOM, 65535,
Components.interfaces.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER);
return intlStream;
} }
/* /**
* does the actual export, after code has been loaded and parsed * Does the actual export, after code has been loaded and parsed
*/ */
Zotero.Translate.prototype._export = function() { Zotero.Translate.prototype._export = function() {
@ -1793,13 +1808,25 @@ Zotero.Translate.prototype._export = function() {
} else if(this.collection) { } else if(this.collection) {
// get items in this collection // get items in this collection
this._itemsLeft = this.collection.getChildItems(); this._itemsLeft = this.collection.getChildItems();
if(!this._itemsLeft) {
this._itemsLeft = [];
}
if(this.configOptions.getCollections) { if(this.configOptions.getCollections) {
// get child collections // get child collections
this._collectionsLeft = Zotero.getCollections(this.collection.id, true); this._collectionsLeft = Zotero.getCollections(this.collection.id, true);
if(this._collectionsLeft.length) {
// only include parent collection if there are actually children
this._collectionsLeft.unshift(this.collection);
}
// get items in child collections // get items in child collections
for each(var collection in this._collectionsLeft) { for each(var collection in this._collectionsLeft) {
this._itemsLeft = this._itemsLeft.concat(collection.getChildItems()); var childItems = collection.getChildItems();
if(childItems) {
this._itemsLeft = this._itemsLeft.concat(childItems);
}
} }
} }
} else { } else {
@ -1859,8 +1886,9 @@ Zotero.Translate.prototype._export = function() {
return true; return true;
} }
/* /**
* configures IO for export * Configures the output stream for export and adds writing functions to the
* sandbox
*/ */
Zotero.Translate.prototype._exportConfigureIO = function() { Zotero.Translate.prototype._exportConfigureIO = function() {
if(this.location) { if(this.location) {
@ -1888,20 +1916,51 @@ Zotero.Translate.prototype._exportConfigureIO = function() {
} else { } else {
// regular io; write just writes to file // regular io; write just writes to file
var intlStream = null; var intlStream = null;
var writtenToStream = false;
var streamCharset = null;
// allow setting of character sets // allow setting of character sets
this._sandbox.Zotero.setCharacterSet = function(charset) { this._sandbox.Zotero.setCharacterSet = function(charset) {
streamCharset = charset.toUpperCase();
intlStream = Components.classes["@mozilla.org/intl/converter-output-stream;1"] intlStream = Components.classes["@mozilla.org/intl/converter-output-stream;1"]
.createInstance(Components.interfaces.nsIConverterOutputStream); .createInstance(Components.interfaces.nsIConverterOutputStream);
if(charset == "UTF-8xBOM") charset = "UTF-8";
intlStream.init(fStream, charset, 1024, "?".charCodeAt(0)); intlStream.init(fStream, charset, 1024, "?".charCodeAt(0));
}; };
// if exportCharset option was presented to user, use the result
if(this.displayOptions.exportCharset) {
this._sandbox.Zotero.setCharacterSet(this.displayOptions.exportCharset);
}
this._sandbox.Zotero.write = function(data) { this._sandbox.Zotero.write = function(data) {
if(intlStream) { if(streamCharset) {
intlStream.writeString(data); if(!writtenToStream && BOMs[streamCharset]) {
// If stream has not yet been written to, and a UTF type
// has been selected, write the BOM
fStream.write(BOMs[streamCharset], BOMs[streamCharset].length);
}
if(streamCharset == "MACINTOSH") {
// fix buggy Mozilla MacRoman
splitData = data.split(/([\r\n]+)/);
Zotero.debug(splitData);
for(var i=0; i<splitData.length; i+=2) {
// write raw newlines straight to the string
intlStream.writeString(splitData[i]);
if(splitData[i+1]) {
fStream.write(splitData[i+1], splitData[i+1].length);
}
}
return;
} else {
intlStream.writeString(data);
}
} else { } else {
fStream.write(data, data.length); fStream.write(data, data.length);
} }
writtenToStream = true;
}; };
} }
} else { } else {
@ -2235,54 +2294,68 @@ Zotero.Translate.TranslatorSearch.prototype.execute = function() {
this.translate._parseDetectCode(translator); this.translate._parseDetectCode(translator);
if(this.translate.type == "import") { if(this.translate.type == "import") {
try { var me = this;
this.translate._importConfigureIO(); // so it can read this.translate._importGetCharacterSet(function(charset) {
} catch(e) { try {
Zotero.debug("Translate: "+e+' in opening IO for '+translator.label); me.translate._importConfigureIO(charset); // so it can read
this.execute(); } catch(e) {
return; Zotero.debug("Translate: "+e+' in opening IO for '+translator.label);
} me.execute();
} return;
translator.configOptions = this.translate.configOptions;
translator.displayOptions = this.translate.displayOptions;
if((this.translate.type == "web" && this.translate._sandbox.detectWeb) ||
(this.translate.type == "search" && this.translate._sandbox.detectSearch) ||
(this.translate.type == "import" && this.translate._sandbox.detectImport)) {
var returnValue;
this.currentTranslator = translator;
try {
if(this.translate.type == "web") {
returnValue = this.translate._sandbox.detectWeb(this.translate.document, this.translate.location);
} else if(this.translate.type == "search") {
returnValue = this.translate._sandbox.detectSearch(this.translate.search);
} else if(this.translate.type == "import") {
returnValue = this.translate._sandbox.detectImport();
} }
} catch(e) {
this.complete(returnValue, e);
return;
}
Zotero.debug("Translate: executed detectCode for "+translator.label);
if(this.translate.type == "web" && this.translate.waitForCompletion) {
this.asyncMode = true;
// don't immediately execute next me.runDetectCode(translator);
return; });
} else if(returnValue) {
this.processReturnValue(translator, returnValue);
}
} else { } else {
// add translator even though it has no proper detectCode (usually this.runDetectCode(translator);
// export translators, which have options but do nothing with them)
this.addTranslator(translator);
} }
} else {
this.execute();
} }
}
/**
* Sets options and runs detectCode
**/
Zotero.Translate.TranslatorSearch.prototype.runDetectCode = function(translator) {
translator.configOptions = this.translate.configOptions;
translator.displayOptions = this.translate.displayOptions;
if((this.translate.type == "web" && this.translate._sandbox.detectWeb) ||
(this.translate.type == "search" && this.translate._sandbox.detectSearch) ||
(this.translate.type == "import" && this.translate._sandbox.detectImport)) {
var returnValue;
this.currentTranslator = translator;
try {
if(this.translate.type == "web") {
returnValue = this.translate._sandbox.detectWeb(this.translate.document, this.translate.location);
} else if(this.translate.type == "search") {
returnValue = this.translate._sandbox.detectSearch(this.translate.search);
} else if(this.translate.type == "import") {
returnValue = this.translate._sandbox.detectImport();
}
} catch(e) {
this.complete(returnValue, e);
return;
}
Zotero.debug("Translate: executed detectCode for "+translator.label);
if(this.translate.type == "web" && this.translate.waitForCompletion) {
this.asyncMode = true;
// don't immediately execute next
return;
} else if(returnValue) {
this.processReturnValue(translator, returnValue);
}
} else {
// add translator even though it has no proper detectCode (usually
// export translators, which have options but do nothing with them)
this.addTranslator(translator);
}
this.execute(); this.execute();
} }
@ -2382,7 +2455,7 @@ Zotero.Translate.GenerateZoteroItemClass = function() {
*/ */
Zotero.Translate.GenerateZoteroCollectionClass = function() { Zotero.Translate.GenerateZoteroCollectionClass = function() {
var ZoteroCollection = Zotero.Translate.ZoteroCollection = function() {}; var ZoteroCollection = function() {};
return ZoteroCollection; return ZoteroCollection;
} }

View file

@ -41,6 +41,9 @@ Zotero.Utilities.prototype.formatDate = function(date) {
Zotero.Utilities.prototype.strToDate = function(date) { Zotero.Utilities.prototype.strToDate = function(date) {
return Zotero.Date.strToDate(date); return Zotero.Date.strToDate(date);
} }
Zotero.Utilities.prototype.strToISO = function(date) {
return Zotero.Date.strToISO(date);
}
/* /*
* Cleans extraneous punctuation off an author name * Cleans extraneous punctuation off an author name
@ -669,7 +672,19 @@ Zotero.Utilities.HTTP = new function() {
_stateChange(xmlhttp, onDone, responseCharset); _stateChange(xmlhttp, onDone, responseCharset);
}; };
xmlhttp.send(null); // Temporarily set cookieBehavior to 0 for Firefox 3
// https://www.zotero.org/trac/ticket/1070
try {
var prefService = Components.classes["@mozilla.org/preferences-service;1"].
getService(Components.interfaces.nsIPrefBranch);
var cookieBehavior = prefService.getIntPref("network.cookie.cookieBehavior");
prefService.setIntPref("network.cookie.cookieBehavior", 0);
xmlhttp.send(null);
}
finally {
prefService.setIntPref("network.cookie.cookieBehavior", cookieBehavior);
}
return xmlhttp; return xmlhttp;
} }
@ -709,7 +724,19 @@ Zotero.Utilities.HTTP = new function() {
_stateChange(xmlhttp, onDone, responseCharset); _stateChange(xmlhttp, onDone, responseCharset);
}; };
xmlhttp.send(body); // Temporarily set cookieBehavior to 0 for Firefox 3
// https://www.zotero.org/trac/ticket/1070
try {
var prefService = Components.classes["@mozilla.org/preferences-service;1"].
getService(Components.interfaces.nsIPrefBranch);
var cookieBehavior = prefService.getIntPref("network.cookie.cookieBehavior");
prefService.setIntPref("network.cookie.cookieBehavior", 0);
xmlhttp.send(body);
}
finally {
prefService.setIntPref("network.cookie.cookieBehavior", cookieBehavior);
}
return xmlhttp; return xmlhttp;
} }
@ -730,7 +757,19 @@ Zotero.Utilities.HTTP = new function() {
_stateChange(xmlhttp, onDone); _stateChange(xmlhttp, onDone);
}; };
xmlhttp.send(null); // Temporarily set cookieBehavior to 0 for Firefox 3
// https://www.zotero.org/trac/ticket/1070
try {
var prefService = Components.classes["@mozilla.org/preferences-service;1"].
getService(Components.interfaces.nsIPrefBranch);
var cookieBehavior = prefService.getIntPref("network.cookie.cookieBehavior");
prefService.setIntPref("network.cookie.cookieBehavior", 0);
xmlhttp.send(null);
}
finally {
prefService.setIntPref("network.cookie.cookieBehavior", cookieBehavior);
}
return xmlhttp; return xmlhttp;
} }
@ -759,7 +798,19 @@ Zotero.Utilities.HTTP = new function() {
_stateChange(xmlhttp, onDone); _stateChange(xmlhttp, onDone);
}; };
xmlhttp.send(body); // Temporarily set cookieBehavior to 0 for Firefox 3
// https://www.zotero.org/trac/ticket/1070
try {
var prefService = Components.classes["@mozilla.org/preferences-service;1"].
getService(Components.interfaces.nsIPrefBranch);
var cookieBehavior = prefService.getIntPref("network.cookie.cookieBehavior");
prefService.setIntPref("network.cookie.cookieBehavior", 0);
xmlhttp.send(body);
}
finally {
prefService.setIntPref("network.cookie.cookieBehavior", cookieBehavior);
}
return xmlhttp; return xmlhttp;
} }

View file

@ -121,6 +121,10 @@
<!ENTITY zotero.exportOptions.format.label "Format:"> <!ENTITY zotero.exportOptions.format.label "Format:">
<!ENTITY zotero.exportOptions.translatorOptions.label "Translator Options"> <!ENTITY zotero.exportOptions.translatorOptions.label "Translator Options">
<!ENTITY zotero.charset.label "Character Encoding">
<!ENTITY zotero.moreEncodings.label "More Encodings">
<!ENTITY zotero.charset.auto "auto detect">
<!ENTITY zotero.citation.keepSorted.label "Keep Sources Sorted"> <!ENTITY zotero.citation.keepSorted.label "Keep Sources Sorted">
<!ENTITY zotero.citation.page "Page"> <!ENTITY zotero.citation.page "Page">

View file

@ -452,7 +452,7 @@ fulltext.indexState.partial = Partial
exportOptions.exportNotes = Export Notes exportOptions.exportNotes = Export Notes
exportOptions.exportFileData = Export Files exportOptions.exportFileData = Export Files
exportOptions.UTF8 = Export as UTF-8 charset.UTF8withoutBOM = Unicode (UTF-8 without BOM)
date.daySuffixes = st, nd, rd, th date.daySuffixes = st, nd, rd, th
date.abbreviation.year = y date.abbreviation.year = y

View file

@ -619,10 +619,73 @@ function ChromeExtensionHandler() {
}; };
/*
zotero://attachment/[id]/
*/
var AttachmentExtension = new function() {
this.newChannel = newChannel;
function newChannel(uri) {
var ioService = Components.classes["@mozilla.org/network/io-service;1"]
.getService(Components.interfaces.nsIIOService);
var Zotero = Components.classes["@zotero.org/Zotero;1"]
.getService(Components.interfaces.nsISupports)
.wrappedJSObject;
try {
var errorMsg;
var [id, fileName] = uri.path.substr(1).split('/');
if (parseInt(id) != id) {
return _errorChannel("Attachment id not an integer");
}
var item = Zotero.Items.get(id);
if (!item) {
return _errorChannel("Item not found");
}
var file = item.getFile();
if (!file) {
return _errorChannel("File not found");
}
if (fileName) {
file = file.parent;
file.append(fileName);
if (!file.exists()) {
return _errorChannel("File not found");
}
}
var ph = Components.classes["@mozilla.org/network/protocol;1?name=file"].
createInstance(Components.interfaces.nsIFileProtocolHandler);
fileURI = ph.newFileURI(file);
var channel = ioService.newChannelFromURI(fileURI);
return channel;
}
catch (e) {
Zotero.debug(e);
throw (e);
}
}
function _errorChannel(msg) {
var ioService = Components.classes["@mozilla.org/network/io-service;1"]
.getService(Components.interfaces.nsIIOService);
var uriStr = 'data:text/plain,' + encodeURIComponent(msg);
var dataURI = ioService.newURI(uriStr, null, null);
var channel = ioService.newChannelFromURI(dataURI);
return channel;
}
};
/* /*
zotero://select/type/id zotero://select/type/id
*/ */
var SelectExtension = new function(){ var SelectExtension = new function(){
this.newChannel = newChannel; this.newChannel = newChannel;
@ -660,19 +723,17 @@ function ChromeExtensionHandler() {
var ReportExtensionSpec = ZOTERO_SCHEME + "://report" var ReportExtensionSpec = ZOTERO_SCHEME + "://report"
ReportExtensionSpec = ReportExtensionSpec.toLowerCase();
this._extensions[ReportExtensionSpec] = ReportExtension; this._extensions[ReportExtensionSpec] = ReportExtension;
var TimelineExtensionSpec = ZOTERO_SCHEME + "://timeline" var TimelineExtensionSpec = ZOTERO_SCHEME + "://timeline"
TimelineExtensionSpec = TimelineExtensionSpec.toLowerCase();
this._extensions[TimelineExtensionSpec] = TimelineExtension; this._extensions[TimelineExtensionSpec] = TimelineExtension;
var AttachmentExtensionSpec = ZOTERO_SCHEME + "://attachment"
this._extensions[AttachmentExtensionSpec] = AttachmentExtension;
var SelectExtensionSpec = ZOTERO_SCHEME + "://select" var SelectExtensionSpec = ZOTERO_SCHEME + "://select"
SelectExtensionSpec = SelectExtensionSpec.toLowerCase();
this._extensions[SelectExtensionSpec] = SelectExtension; this._extensions[SelectExtensionSpec] = SelectExtension;
} }

File diff suppressed because it is too large Load diff