Merge branch '4.0'
Conflicts: chrome/content/zotero/xpcom/zotero.js install.rdf update.rdf
This commit is contained in:
commit
d8e2007da4
18 changed files with 134 additions and 60 deletions
|
@ -1 +1 @@
|
|||
Subproject commit 67de2bc8f2d22247463b1b84caf9bf0ab100f2fa
|
||||
Subproject commit 5b7a687df6464af87eaacc4088bd136ec1039d1b
|
|
@ -40,7 +40,6 @@
|
|||
onunload="Zotero_Preferences.onUnload()"
|
||||
ondialoghelp="Zotero_Preferences.openHelpLink()"
|
||||
windowtype="zotero:pref"
|
||||
width="620"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
|
||||
<prefpane id="zotero-prefpane-general"
|
||||
|
|
|
@ -33,7 +33,9 @@
|
|||
<prefwindow id="zotero-prefs">
|
||||
<prefpane id="zotero-prefpane-proxies"
|
||||
label="&zotero.preferences.prefpane.proxies;"
|
||||
image="chrome://zotero/skin/prefs-proxies.png" position="6"
|
||||
image="chrome://zotero/skin/prefs-proxies.png"
|
||||
onpaneload="Zotero_Preferences.Proxies.init()"
|
||||
position="6"
|
||||
helpTopic="proxies">
|
||||
<description width="45em" style="font-size: 12px">
|
||||
&zotero.preferences.proxies.desc_before_link;
|
||||
|
|
|
@ -60,7 +60,8 @@
|
|||
|
||||
<separator class="thin"/>
|
||||
|
||||
<label id="pdftools-required" hidden="true"/>
|
||||
<!-- This doesn't wrap without an explicit width -->
|
||||
<label id="pdftools-required" width="45em" hidden="true"/>
|
||||
|
||||
<separator class="thin"/>
|
||||
|
||||
|
@ -70,7 +71,8 @@
|
|||
|
||||
<separator class="thin"/>
|
||||
|
||||
<label id="pdftools-documentation-link" hidden="true"/>
|
||||
<!-- This doesn't wrap without an explicit width -->
|
||||
<label id="pdftools-documentation-link" width="45em" hidden="true"/>
|
||||
|
||||
<separator class="thin"/>
|
||||
|
||||
|
@ -110,6 +112,8 @@
|
|||
</rows>
|
||||
</grid>
|
||||
</groupbox>
|
||||
|
||||
<separator/>
|
||||
</prefpane>
|
||||
|
||||
<script src="preferences_search.js" type="application/javascript;version=1.8"/>
|
||||
|
|
|
@ -43,6 +43,21 @@ Zotero.File = new function(){
|
|||
this.getCharsetFromFile = getCharsetFromFile;
|
||||
this.addCharsetListener = addCharsetListener;
|
||||
|
||||
/**
|
||||
* Encode special characters in file paths that might cause problems,
|
||||
* like # (but preserve slashes or colons)
|
||||
*
|
||||
* @param {String} path File path
|
||||
* @return {String} Encoded file path
|
||||
*/
|
||||
this.encodeFilePath = function(path) {
|
||||
var parts = path.split(/([\\\/:]+)/);
|
||||
// Every other item is the separator
|
||||
for (var i=0, n=parts.length; i<n; i+=2) {
|
||||
parts[i] = encodeURIComponent(parts[i]);
|
||||
}
|
||||
return parts.join('');
|
||||
}
|
||||
|
||||
function getExtension(file){
|
||||
var pos = file.leafName.lastIndexOf('.');
|
||||
|
|
|
@ -41,6 +41,7 @@ Zotero.HTTP = new function() {
|
|||
* <li>debug - Log response text and status code</li>
|
||||
* <li>dontCache - If set, specifies that the request should not be fulfilled from the cache</li>
|
||||
* <li>headers - HTTP headers to include in the request</li>
|
||||
* <li>requestObserver - Callback to receive XMLHttpRequest after open()</li>
|
||||
* <li>responseType - The type of the response. See XHR 2 documentation for legal values</li>
|
||||
* <li>responseCharset - The charset the response should be interpreted as</li>
|
||||
* <li>successCodes - HTTP status codes that are considered successful</li>
|
||||
|
@ -86,12 +87,19 @@ Zotero.HTTP = new function() {
|
|||
});
|
||||
}
|
||||
|
||||
var deferred = Q.defer();
|
||||
|
||||
var xmlhttp = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"]
|
||||
.createInstance();
|
||||
// Prevent certificate/authentication dialogs from popping up
|
||||
xmlhttp.mozBackgroundRequest = true;
|
||||
xmlhttp.open(method, url, true);
|
||||
|
||||
// Pass the request to a callback
|
||||
if (options && options.requestObserver) {
|
||||
options.requestObserver(xmlhttp);
|
||||
}
|
||||
|
||||
if (method == 'PUT') {
|
||||
// Some servers (e.g., Jungle Disk DAV) return a 200 response code
|
||||
// with Content-Length: 0, which triggers a "no element found" error
|
||||
|
@ -128,8 +136,6 @@ Zotero.HTTP = new function() {
|
|||
xmlhttp.setRequestHeader(header, headers[header]);
|
||||
}
|
||||
|
||||
var deferred = Q.defer();
|
||||
|
||||
xmlhttp.onloadend = function() {
|
||||
var status = xmlhttp.status;
|
||||
|
||||
|
|
|
@ -104,9 +104,11 @@ Zotero.Sync.Storage.Queue.prototype.__defineSetter__('finishedRequests', functio
|
|||
var localChanges = this._localChanges;
|
||||
var remoteChanges = this._remoteChanges;
|
||||
var conflicts = this._conflicts.concat();
|
||||
var deferred = this._deferred;
|
||||
this._localChanges = false;
|
||||
this._remoteChanges = false;
|
||||
this._conflicts = [];
|
||||
this._deferred = null;
|
||||
|
||||
if (!this._error) {
|
||||
Zotero.debug("Resolving promise for queue " + this.name);
|
||||
|
@ -114,7 +116,7 @@ Zotero.Sync.Storage.Queue.prototype.__defineSetter__('finishedRequests', functio
|
|||
Zotero.debug(this._remoteChanges);
|
||||
Zotero.debug(this._conflicts);
|
||||
|
||||
this._deferred.resolve({
|
||||
deferred.resolve({
|
||||
libraryID: this.libraryID,
|
||||
type: this.type,
|
||||
localChanges: localChanges,
|
||||
|
@ -128,7 +130,7 @@ Zotero.Sync.Storage.Queue.prototype.__defineSetter__('finishedRequests', functio
|
|||
this._error = false;
|
||||
e.libraryID = this.libraryID;
|
||||
e.type = this.type;
|
||||
this._deferred.reject(e);
|
||||
deferred.reject(e);
|
||||
}
|
||||
|
||||
return;
|
||||
|
@ -368,8 +370,13 @@ Zotero.Sync.Storage.Queue.prototype.addConflict = function (requestName, localDa
|
|||
|
||||
Zotero.Sync.Storage.Queue.prototype.error = function (e) {
|
||||
if (!this._error) {
|
||||
if (this.isRunning()) {
|
||||
this._error = e;
|
||||
}
|
||||
else {
|
||||
Zotero.debug("Queue " + this.name + " was no longer running -- not assigning error", 2);
|
||||
}
|
||||
}
|
||||
Zotero.debug(e, 1);
|
||||
this.stop();
|
||||
}
|
||||
|
|
|
@ -43,6 +43,7 @@ Zotero.Sync.Storage.Request = function (name, callbacks) {
|
|||
|
||||
this._deferred = Q.defer();
|
||||
this._running = false;
|
||||
this._stopping = false;
|
||||
this._percentage = 0;
|
||||
this._remaining = null;
|
||||
this._maxSize = null;
|
||||
|
@ -222,16 +223,16 @@ Zotero.Sync.Storage.Request.prototype.start = function () {
|
|||
// This promise updates localChanges/remoteChanges on the queue
|
||||
self._deferred.resolve(results);
|
||||
})
|
||||
.fail(function (e) {
|
||||
.catch(function (e) {
|
||||
if (self._stopping) {
|
||||
Zotero.debug("Skipping error for stopping request " + self.name);
|
||||
return;
|
||||
}
|
||||
Zotero.debug(self.queue.Type + " request " + self.name + " failed");
|
||||
Zotero.debug(self._deferred);
|
||||
Zotero.debug(self._deferred.promise.isFulfilled());
|
||||
self._deferred.reject(e);
|
||||
Zotero.debug(self._deferred.promise.isFulfilled());
|
||||
Zotero.debug(self._deferred.promise.isRejected());
|
||||
})
|
||||
// Finish the request (and in turn the queue, if this is the last request)
|
||||
.fin(function () {
|
||||
.finally(function () {
|
||||
if (!self._finished) {
|
||||
self._finish();
|
||||
}
|
||||
|
@ -309,6 +310,8 @@ Zotero.Sync.Storage.Request.prototype.onProgress = function (channel, progress,
|
|||
*/
|
||||
Zotero.Sync.Storage.Request.prototype.stop = function () {
|
||||
if (this.channel) {
|
||||
this._stopping = true;
|
||||
|
||||
try {
|
||||
Zotero.debug("Stopping request '" + this.name + "'");
|
||||
this.channel.cancel(0x804b0002); // NS_BINDING_ABORTED
|
||||
|
@ -343,7 +346,7 @@ Zotero.Sync.Storage.Request.prototype._finish = function () {
|
|||
this.queue.updateProgress();
|
||||
}
|
||||
catch (e) {
|
||||
Zotero.debug(e);
|
||||
Zotero.debug(e, 1);
|
||||
Components.utils.reportError(e);
|
||||
this._deferred.reject(e);
|
||||
throw e;
|
||||
|
|
|
@ -42,14 +42,17 @@ Zotero.Sync.Storage.WebDAV = (function () {
|
|||
* @param {Zotero.Item} item
|
||||
* @param {Function} callback Callback f(item, mdate)
|
||||
*/
|
||||
function getStorageModificationTime(item) {
|
||||
var funcName = "Zotero.Sync.Storage.WebDAV.getStorageModificationTime()";
|
||||
|
||||
function getStorageModificationTime(item, request) {
|
||||
var uri = getItemPropertyURI(item);
|
||||
|
||||
return Zotero.HTTP.promise(
|
||||
"GET", uri, { debug: true, successCodes: [200, 300, 404] }
|
||||
)
|
||||
return Zotero.HTTP.promise("GET", uri,
|
||||
{
|
||||
debug: true,
|
||||
successCodes: [200, 300, 404],
|
||||
requestObserver: function (xmlhttp) {
|
||||
request.setChannel(xmlhttp.channel);
|
||||
}
|
||||
})
|
||||
.then(function (req) {
|
||||
checkResponse(req);
|
||||
|
||||
|
@ -113,7 +116,8 @@ Zotero.Sync.Storage.WebDAV = (function () {
|
|||
})
|
||||
.catch(function (e) {
|
||||
if (e instanceof Zotero.HTTP.UnexpectedStatusException) {
|
||||
throw new Error("Unexpected status code " + e.status + " in " + funcName);
|
||||
throw new Error("HTTP " + e.status + " error from WebDAV "
|
||||
+ "server for GET request");
|
||||
}
|
||||
throw e;
|
||||
});
|
||||
|
@ -141,8 +145,9 @@ Zotero.Sync.Storage.WebDAV = (function () {
|
|||
.then(function (req) {
|
||||
return { mtime: mtime, hash: hash };
|
||||
})
|
||||
.fail(function (e) {
|
||||
throw new Error("Unexpected status code " + e.xmlhttp.status);
|
||||
.catch(function (e) {
|
||||
throw new Error("HTTP " + e.xmlhttp.status
|
||||
+ " from WebDAV server for HTTP PUT");
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -163,7 +168,7 @@ Zotero.Sync.Storage.WebDAV = (function () {
|
|||
var request = data.request;
|
||||
var item = Zotero.Sync.Storage.getItemFromRequestName(request.name);
|
||||
|
||||
return getStorageModificationTime(item)
|
||||
return getStorageModificationTime(item, request)
|
||||
.then(function (mdate) {
|
||||
if (!request.isRunning()) {
|
||||
Zotero.debug("Upload request '" + request.name
|
||||
|
@ -320,8 +325,9 @@ Zotero.Sync.Storage.WebDAV = (function () {
|
|||
|
||||
default:
|
||||
Zotero.debug(response);
|
||||
throw ("Unexpected file upload status " + status +
|
||||
" in Zotero.Sync.Storage.WebDAV.onUploadComplete()");
|
||||
throw (Zotero.getString('sync.storage.error.fileUploadFailed') +
|
||||
" " + Zotero.getString('sync.storage.error.checkFileSyncSettings')
|
||||
+ "\n\n" + "HTTP " + status);
|
||||
}
|
||||
|
||||
return setStorageModificationTime(item)
|
||||
|
@ -812,7 +818,7 @@ Zotero.Sync.Storage.WebDAV = (function () {
|
|||
}
|
||||
|
||||
// Retrieve modification time from server to store locally afterwards
|
||||
return getStorageModificationTime(item)
|
||||
return getStorageModificationTime(item, request)
|
||||
.then(function (mdate) {
|
||||
if (!request.isRunning()) {
|
||||
Zotero.debug("Download request '" + request.name
|
||||
|
@ -879,9 +885,8 @@ Zotero.Sync.Storage.WebDAV = (function () {
|
|||
return;
|
||||
}
|
||||
else if (status != 200) {
|
||||
var msg = "Unexpected status code " + status
|
||||
+ " for request " + data.request.name
|
||||
+ " in Zotero.Sync.Storage.WebDAV.downloadFile()";
|
||||
var msg = "HTTP " + status + " from WebDAV server "
|
||||
+ " while downloading file";
|
||||
Zotero.debug(msg, 1);
|
||||
Components.utils.reportError(msg);
|
||||
deferred.reject(Zotero.Sync.Storage.WebDAV.defaultError);
|
||||
|
@ -987,8 +992,8 @@ Zotero.Sync.Storage.WebDAV = (function () {
|
|||
_cachedCredentials = false;
|
||||
}
|
||||
else {
|
||||
throw("Unexpected status code " + e.status + " getting "
|
||||
+ "WebDAV last sync time");
|
||||
throw("HTTP " + e.status + " error from WebDAV server "
|
||||
+ "for GET request");
|
||||
}
|
||||
|
||||
return Q.reject(e);
|
||||
|
@ -1034,8 +1039,9 @@ Zotero.Sync.Storage.WebDAV = (function () {
|
|||
}
|
||||
});
|
||||
})
|
||||
.fail(function (e) {
|
||||
var msg = "Unexpected error code " + req.status + " uploading storage success file";
|
||||
.catch(function (e) {
|
||||
var msg = "HTTP " + req.status + " error from WebDAV server "
|
||||
+ "for PUT request";
|
||||
Zotero.debug(msg, 2);
|
||||
Components.utils.reportError(msg);
|
||||
throw Zotero.Sync.Storage.WebDAV.defaultError;
|
||||
|
@ -1058,8 +1064,8 @@ Zotero.Sync.Storage.WebDAV = (function () {
|
|||
})
|
||||
.fail(function (e) {
|
||||
if (e instanceof Zotero.HTTP.UnexpectedStatusException) {
|
||||
var msg = "Unexpected status code " + e.status + " "
|
||||
+ "for OPTIONS request caching WebDAV credentials";
|
||||
var msg = "HTTP " + e.status + " error from WebDAV server "
|
||||
+ "for OPTIONS request";
|
||||
Zotero.debug(msg, 1);
|
||||
Components.utils.reportError(msg);
|
||||
throw new Error(Zotero.Sync.Storage.WebDAV.defaultErrorRestart);
|
||||
|
|
|
@ -38,10 +38,17 @@ Zotero.Sync.Storage.ZFS = (function () {
|
|||
* @param {Zotero.Item} item
|
||||
* @param {Function} callback Callback f(item, etag)
|
||||
*/
|
||||
function getStorageFileInfo(item) {
|
||||
function getStorageFileInfo(item, request) {
|
||||
var funcName = "Zotero.Sync.Storage.ZFS.getStorageFileInfo()";
|
||||
|
||||
return Zotero.HTTP.promise("GET", getItemInfoURI(item), { successCodes: [200, 404], headers: _headers })
|
||||
return Zotero.HTTP.promise("GET", getItemInfoURI(item),
|
||||
{
|
||||
successCodes: [200, 404],
|
||||
headers: _headers,
|
||||
requestObserver: function (xmlhttp) {
|
||||
request.setChannel(xmlhttp.channel);
|
||||
}
|
||||
})
|
||||
.then(function (req) {
|
||||
if (req.status == 404) {
|
||||
return false;
|
||||
|
@ -72,10 +79,15 @@ Zotero.Sync.Storage.ZFS = (function () {
|
|||
|
||||
return info;
|
||||
})
|
||||
.fail(function (e) {
|
||||
.catch(function (e) {
|
||||
if (e instanceof Zotero.HTTP.UnexpectedStatusException) {
|
||||
if (e.xmlhttp.status == 0) {
|
||||
var msg = "Request cancelled getting storage file info";
|
||||
}
|
||||
else {
|
||||
var msg = "Unexpected status code " + e.xmlhttp.status
|
||||
+ " getting storage file info";
|
||||
}
|
||||
Zotero.debug(msg, 1);
|
||||
Zotero.debug(e.xmlhttp.responseText);
|
||||
Components.utils.reportError(msg);
|
||||
|
@ -102,7 +114,7 @@ Zotero.Sync.Storage.ZFS = (function () {
|
|||
|
||||
var request = data.request;
|
||||
var item = Zotero.Sync.Storage.getItemFromRequestName(request.name);
|
||||
return getStorageFileInfo(item)
|
||||
return getStorageFileInfo(item, request)
|
||||
.then(function (info) {
|
||||
if (request.isFinished()) {
|
||||
Zotero.debug("Upload request '" + request.name
|
||||
|
@ -694,7 +706,7 @@ Zotero.Sync.Storage.ZFS = (function () {
|
|||
}
|
||||
|
||||
// Retrieve file info from server to store locally afterwards
|
||||
return getStorageFileInfo(item)
|
||||
return getStorageFileInfo(item, request)
|
||||
.then(function (info) {
|
||||
if (!request.isRunning()) {
|
||||
Zotero.debug("Download request '" + request.name
|
||||
|
|
|
@ -978,13 +978,28 @@ Zotero.Sync.Runner = new function () {
|
|||
box.appendChild(content);
|
||||
box.appendChild(buttons);
|
||||
|
||||
var desc = doc.createElement('description');
|
||||
// Use of deck and textbox+description here is a hack from
|
||||
// http://www.blackfishsoftware.com/node/47 to make the text
|
||||
// selectable while maintaining the proper width and height
|
||||
var deck = doc.createElement('deck');
|
||||
|
||||
var msg = e.message;
|
||||
/*if (e.fileName) {
|
||||
msg += '\n\nFile: ' + e.fileName + '\nLine: ' + e.lineNumber;
|
||||
}*/
|
||||
|
||||
var textbox = doc.createElement('textbox');
|
||||
textbox.className = 'plain';
|
||||
textbox.setAttribute('multiline', true);
|
||||
textbox.setAttribute('readonly', true);
|
||||
textbox.setAttribute('value', msg);
|
||||
deck.appendChild(textbox);
|
||||
|
||||
var desc = doc.createElement('description');
|
||||
desc.textContent = msg;
|
||||
content.appendChild(desc);
|
||||
deck.appendChild(desc);
|
||||
|
||||
content.appendChild(deck);
|
||||
|
||||
// If not an error and there's no explicit button text, don't show
|
||||
// button to report errors
|
||||
|
|
|
@ -291,10 +291,10 @@ Zotero.Translate.ItemSaver.prototype = {
|
|||
var IOService = Components.classes["@mozilla.org/network/io-service;1"].
|
||||
getService(Components.interfaces.nsIIOService);
|
||||
try {
|
||||
var uri = IOService.newURI(path, "", this._baseURI);
|
||||
var uri = IOService.newURI(Zotero.File.encodeFilePath(path), "", this._baseURI);
|
||||
}
|
||||
catch (e) {
|
||||
var msg = "Error parsing attachment path: " + path;
|
||||
var msg = "Error parsing attachment path: " + path + "\n" + e.message;
|
||||
Zotero.logError(msg);
|
||||
Zotero.debug("Translate: " + msg, 2);
|
||||
return false;
|
||||
|
@ -303,14 +303,14 @@ Zotero.Translate.ItemSaver.prototype = {
|
|||
try {
|
||||
var file = uri.QueryInterface(Components.interfaces.nsIFileURL).file;
|
||||
if (file.path == '/') {
|
||||
var msg = "Error parsing attachment path: " + path;
|
||||
var msg = "Error parsing attachment path: " + path + "\nRoot path returned.";
|
||||
Zotero.logError(msg);
|
||||
Zotero.debug("Translate: " + msg, 2);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
var msg = "Error getting file from attachment path: " + path;
|
||||
var msg = "Error getting file from attachment path: " + path + "\n" + e.message;
|
||||
Zotero.logError(msg);
|
||||
Zotero.debug("Translate: " + msg, 2);
|
||||
return false;
|
||||
|
|
|
@ -278,4 +278,4 @@
|
|||
|
||||
<!ENTITY zotero.downloadManager.label "Save to Zotero">
|
||||
<!ENTITY zotero.downloadManager.saveToLibrary.description "Attachments cannot be saved to the currently selected library. This item will be saved to your library instead.">
|
||||
<!ENTITY zotero.downloadManager.noPDFTools.description "To use this feature, you must first install the PDF tools in the Zotero preferences.">
|
||||
<!ENTITY zotero.downloadManager.noPDFTools.description "To use this feature, you must first install the PDF tools in the Search pane of the Zotero preferences.">
|
||||
|
|
|
@ -258,7 +258,7 @@ pane.item.attachments.count.singular = %S attachment:
|
|||
pane.item.attachments.count.plural = %S attachments:
|
||||
pane.item.attachments.select = Select a File
|
||||
pane.item.attachments.PDF.installTools.title = PDF Tools Not Installed
|
||||
pane.item.attachments.PDF.installTools.text = To use this feature, you must first install the PDF tools in the Zotero preferences.
|
||||
pane.item.attachments.PDF.installTools.text = To use this feature, you must first install the PDF tools in the Search pane of the Zotero preferences.
|
||||
pane.item.attachments.filename = Filename
|
||||
pane.item.noteEditor.clickHere = click here
|
||||
pane.item.tags.count.zero = %S tags:
|
||||
|
@ -822,7 +822,7 @@ sync.storage.error.default = A file sync error occurred. Please try syncing
|
|||
sync.storage.error.defaultRestart = A file sync error occurred. Please restart %S and/or your computer and try syncing again.\n\nIf you receive this message repeatedly, submit an error report and post the Report ID to a new thread in the Zotero Forums.
|
||||
sync.storage.error.serverCouldNotBeReached = The server %S could not be reached.
|
||||
sync.storage.error.permissionDeniedAtAddress = You do not have permission to create a Zotero directory at the following address:
|
||||
sync.storage.error.checkFileSyncSettings = Please check your file sync settings or contact your server administrator.
|
||||
sync.storage.error.checkFileSyncSettings = Please check your file sync settings or contact your WebDAV server administrator.
|
||||
sync.storage.error.verificationFailed = %S verification failed. Verify your file sync settings in the Sync pane of the Zotero preferences.
|
||||
sync.storage.error.fileNotCreated = The file '%S' could not be created in the Zotero 'storage' directory.
|
||||
sync.storage.error.encryptedFilenames = Error creating file '%S'.\n\nSee http://www.zotero.org/support/kb/encrypted_filenames for more information.
|
||||
|
|
|
@ -431,6 +431,10 @@
|
|||
}
|
||||
|
||||
/* Sync error panel */
|
||||
#zotero-sync-error-panel {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.zotero-sync-error-panel-library-name {
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1 +1 @@
|
|||
2013-03-20 06:25:00
|
||||
2013-03-22 05:55:00
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit ed58b9977976ed42cdbaab0f129adb83c287664c
|
||||
Subproject commit f23d8732c02c256423d4fbd6d85f9bca2d5336c2
|
Loading…
Add table
Reference in a new issue