diff --git a/chrome/content/zotero/xpcom/storage.js b/chrome/content/zotero/xpcom/storage.js index a1771b6c1..4182be1fd 100644 --- a/chrome/content/zotero/xpcom/storage.js +++ b/chrome/content/zotero/xpcom/storage.js @@ -51,6 +51,7 @@ Zotero.Sync.Storage = new function () { this.ERROR_NOT_ALLOWED = -14; this.ERROR_UNKNOWN = -15; this.ERROR_FILE_MISSING_AFTER_UPLOAD = -16; + this.ERROR_NONEXISTENT_FILE_NOT_MISSING = -17; // TEMP this.__defineGetter__("defaultError", function () Zotero.getString('sync.storage.error.default', Zotero.appName)); diff --git a/chrome/content/zotero/xpcom/storage/webdav.js b/chrome/content/zotero/xpcom/storage/webdav.js index a8c13a55f..a35aa9fb0 100644 --- a/chrome/content/zotero/xpcom/storage/webdav.js +++ b/chrome/content/zotero/xpcom/storage/webdav.js @@ -1211,89 +1211,120 @@ Zotero.Sync.Storage.WebDAV = (function () { switch (req.status) { case 207: - // Test if Zotero directory is writable - var testFileURI = uri.clone(); - testFileURI.spec += "zotero-test-file.prop"; - Zotero.HTTP.WebDAV.doPut(testFileURI, " ", function (req) { - Zotero.debug(req.responseText); - Zotero.debug(req.status); - - switch (req.status) { - case 200: - case 201: - case 204: - Zotero.HTTP.doGet( - testFileURI, - function (req) { - Zotero.debug(req.responseText); - Zotero.debug(req.status); - - switch (req.status) { - case 200: - // Delete test file - Zotero.HTTP.WebDAV.doDelete( - testFileURI, - function (req) { - Zotero.debug(req.responseText); - Zotero.debug(req.status); - - switch (req.status) { - case 200: // IIS 5.1 and Sakai return 200 - case 204: - return deferred.resolve([uri, Zotero.Sync.Storage.SUCCESS]); + // Test if missing files return 404s + var missingFileURI = uri.clone(); + missingFileURI.spec += "nonexistent.prop"; + Zotero.HTTP.promise("GET", missingFileURI, { successCodes: [404], debug: true }) + .then(function () { + // Test if Zotero directory is writable + var testFileURI = uri.clone(); + testFileURI.spec += "zotero-test-file.prop"; + Zotero.HTTP.WebDAV.doPut(testFileURI, " ", function (req) { + Zotero.debug(req.responseText); + Zotero.debug(req.status); + + switch (req.status) { + case 200: + case 201: + case 204: + Zotero.HTTP.doGet( + testFileURI, + function (req) { + Zotero.debug(req.responseText); + Zotero.debug(req.status); + + switch (req.status) { + case 200: + // Delete test file + Zotero.HTTP.WebDAV.doDelete( + testFileURI, + function (req) { + Zotero.debug(req.responseText); + Zotero.debug(req.status); - case 401: - return deferred.resolve([uri, Zotero.Sync.Storage.ERROR_AUTH_FAILED]); - - case 403: - return deferred.resolve([uri, Zotero.Sync.Storage.ERROR_FORBIDDEN]); - - default: - return deferred.resolve([uri, Zotero.Sync.Storage.ERROR_UNKNOWN]); + switch (req.status) { + case 200: // IIS 5.1 and Sakai return 200 + case 204: + return deferred.resolve([uri, Zotero.Sync.Storage.SUCCESS]); + + case 401: + return deferred.resolve([uri, Zotero.Sync.Storage.ERROR_AUTH_FAILED]); + + case 403: + return deferred.resolve([uri, Zotero.Sync.Storage.ERROR_FORBIDDEN]); + + default: + return deferred.resolve([uri, Zotero.Sync.Storage.ERROR_UNKNOWN]); + } } - } - ); - return; - - case 401: - return deferred.resolve([uri, Zotero.Sync.Storage.ERROR_AUTH_FAILED]); - - case 403: - return deferred.resolve([uri, Zotero.Sync.Storage.ERROR_FORBIDDEN]); - - // This can happen with cloud storage services - // backed by S3 or other eventually consistent - // data stores. - // - // This can also be from IIS 6+, which is configured - // not to serve .prop files. - // http://support.microsoft.com/kb/326965 - case 404: - return deferred.resolve([uri, Zotero.Sync.Storage.ERROR_FILE_MISSING_AFTER_UPLOAD]); - - case 500: - return deferred.resolve([uri, Zotero.Sync.Storage.ERROR_SERVER_ERROR]); - - default: - return deferred.resolve([uri, Zotero.Sync.Storage.ERROR_UNKNOWN]); + ); + return; + + case 401: + return deferred.resolve([uri, Zotero.Sync.Storage.ERROR_AUTH_FAILED]); + + case 403: + return deferred.resolve([uri, Zotero.Sync.Storage.ERROR_FORBIDDEN]); + + // This can happen with cloud storage services + // backed by S3 or other eventually consistent + // data stores. + // + // This can also be from IIS 6+, which is configured + // not to serve .prop files. + // http://support.microsoft.com/kb/326965 + case 404: + return deferred.resolve([uri, Zotero.Sync.Storage.ERROR_FILE_MISSING_AFTER_UPLOAD]); + + case 500: + return deferred.resolve([uri, Zotero.Sync.Storage.ERROR_SERVER_ERROR]); + + default: + return deferred.resolve([uri, Zotero.Sync.Storage.ERROR_UNKNOWN]); + } } - } - ); - return; - - case 401: - return deferred.resolve([uri, Zotero.Sync.Storage.ERROR_AUTH_FAILED]); - - case 403: - return deferred.resolve([uri, Zotero.Sync.Storage.ERROR_FORBIDDEN]); - - case 500: - return deferred.resolve([uri, Zotero.Sync.Storage.ERROR_SERVER_ERROR]); - - default: - return deferred.resolve([uri, Zotero.Sync.Storage.ERROR_UNKNOWN]); + ); + return; + + case 401: + return deferred.resolve([uri, Zotero.Sync.Storage.ERROR_AUTH_FAILED]); + + case 403: + return deferred.resolve([uri, Zotero.Sync.Storage.ERROR_FORBIDDEN]); + + case 500: + return deferred.resolve([uri, Zotero.Sync.Storage.ERROR_SERVER_ERROR]); + + default: + return deferred.resolve([uri, Zotero.Sync.Storage.ERROR_UNKNOWN]); + } + }); + }) + .catch(function (e) { + if (e instanceof Zotero.HTTP.UnexpectedStatusException) { + if (e.status >= 200 && e.status < 300) { + deferred.resolve([uri, Zotero.Sync.Storage.ERROR_NONEXISTENT_FILE_NOT_MISSING]); + } + else if (e.status == 401) { + deferred.resolve([uri, Zotero.Sync.Storage.ERROR_AUTH_FAILED]); + } + else if (e.status == 403) { + deferred.resolve([uri, Zotero.Sync.Storage.ERROR_FORBIDDEN]); + } + else if (e.status == 500) { + deferred.resolve([uri, Zotero.Sync.Storage.ERROR_SERVER_ERROR]); + } + else { + deferred.resolve([uri, Zotero.Sync.Storage.ERROR_UNKNOWN]); + } } - }); + else { + Zotero.debug(e, 1); + Components.utils.reportError(e); + deferred.resolve([uri, Zotero.Sync.Storage.ERROR_UNKNOWN]); + } + }) + .done(); return; case 400: @@ -1491,6 +1522,11 @@ Zotero.Sync.Storage.WebDAV = (function () { Zotero.getString('sync.storage.error.checkFileSyncSettings') ]); break; + + case Zotero.Sync.Storage.ERROR_NONEXISTENT_FILE_NOT_MISSING: + var errorTitle = Zotero.getString('sync.storage.error.webdav.serverConfig.title'); + var errorMessage = Zotero.getString('sync.storage.error.webdav.nonexistentFileNotMissing'); + break; } if (!skipSuccessMessage) { diff --git a/chrome/locale/en-US/zotero/zotero.properties b/chrome/locale/en-US/zotero/zotero.properties index a14c67c25..7635279f1 100644 --- a/chrome/locale/en-US/zotero/zotero.properties +++ b/chrome/locale/en-US/zotero/zotero.properties @@ -849,6 +849,7 @@ sync.storage.error.webdav.loadURLForMoreInfo = Load your WebDAV URL in the brows sync.storage.error.webdav.seeCertOverrideDocumentation = See the certificate override documentation for more information. sync.storage.error.webdav.loadURL = Load WebDAV URL sync.storage.error.webdav.fileMissingAfterUpload = A potential problem was found with your WebDAV server.\n\nAn uploaded file was not immediately available for download. There may be a short delay between when you upload files and when they become available, particularly if you are using a cloud storage service.\n\nIf Zotero file syncing appears to work normally, you can ignore this message. If you have trouble, please post to the Zotero Forums. +sync.storage.error.webdav.nonexistentFileNotMissing = Your WebDAV server is claiming that a nonexistent file exists. Contact your WebDAV server administrator for assistance. sync.storage.error.webdav.serverConfig.title = WebDAV Server Configuration Error sync.storage.error.webdav.serverConfig = Your WebDAV server returned an internal error.