diff --git a/chrome/content/zotero/xpcom/storage/webdav.js b/chrome/content/zotero/xpcom/storage/webdav.js index 876993fd8b..ae5106e818 100644 --- a/chrome/content/zotero/xpcom/storage/webdav.js +++ b/chrome/content/zotero/xpcom/storage/webdav.js @@ -253,12 +253,20 @@ Zotero.Sync.Storage.Mode.WebDAV.prototype = { Zotero.debug("Caching WebDAV credentials"); + let xmlstr = "" + + "" + + ""; try { - var req = await Zotero.HTTP.request( - "OPTIONS", + await Zotero.HTTP.request( + "PROPFIND", this.rootURI, { - successCodes: [200, 204, 404], + body: xmlstr, + headers: { + Depth: 0, + "Content-Type": "text/xml; charset=utf-8" + }, + successCodes: [207, 404], errorDelayIntervals: this.ERROR_DELAY_INTERVALS, errorDelayMax: this.ERROR_DELAY_MAX, onAuthorizationHeader: (authorization) => { @@ -267,7 +275,6 @@ Zotero.Sync.Storage.Mode.WebDAV.prototype = { }, } ); - if (this._channelAuthorization) { Zotero.debug("Authorization header cached"); } @@ -278,7 +285,7 @@ Zotero.Sync.Storage.Mode.WebDAV.prototype = { catch (e) { if (e instanceof Zotero.HTTP.UnexpectedStatusException) { let msg = "HTTP " + e.status + " error from WebDAV server " - + "for OPTIONS request"; + + "for PROPFIND request"; Zotero.logError(msg); throw new Error(this.defaultErrorRestart); } diff --git a/test/tests/webdavTest.js b/test/tests/webdavTest.js index ec9c9a4a79..7705dc6a8a 100644 --- a/test/tests/webdavTest.js +++ b/test/tests/webdavTest.js @@ -60,7 +60,7 @@ describe("Zotero.Sync.Storage.Mode.WebDAV", function () { httpd.registerPathHandler(path, { handle: function (request, response) { - // Always handle OPTIONS with auth (for cacheCredentials calls) + // Always handle OPTIONS with auth (for checkServer calls) if (request.method == 'OPTIONS') { if (!checkAuth(request)) { send401(response); @@ -70,7 +70,29 @@ describe("Zotero.Sync.Storage.Mode.WebDAV", function () { response.setStatusLine(null, 200, "OK"); return; } - + + // Handle PROPFIND with auth (for cacheCredentials() calls) unless a + // custom handler is registered + if (request.method == 'PROPFIND' && !pathHandlers[path]?.PROPFIND) { + if (!checkAuth(request)) { + send401(response); + return; + } + response.setHeader('Content-Type', 'text/xml; charset="utf-8"', false); + response.setStatusLine(null, 207, "Multi-Status"); + response.write('' + + '' + + '' + + `${path}` + + '' + + '' + + 'HTTP/1.1 200 OK' + + '' + + '' + + ''); + return; + } + let methodHandlers = pathHandlers[path]; let methodHandler = methodHandlers && methodHandlers[request.method]; @@ -728,12 +750,12 @@ describe("Zotero.Sync.Storage.Mode.WebDAV", function () { await OS.File.remove(zipPath); - // OPTIONS request to cache credentials + // PROPFIND request to cache credentials httpd.registerPathHandler( `${davBasePath}zotero/`, { handle: function (request, response) { - if (request.method == 'OPTIONS') { + if (request.method == 'PROPFIND') { // Force Basic Auth if (!request.hasHeader('Authorization')) { response.setStatusLine(null, 401, null); @@ -746,8 +768,18 @@ describe("Zotero.Sync.Storage.Mode.WebDAV", function () { return; } response.setHeader('Set-Cookie', 'foo=bar', false); - response.setHeader('DAV', '1', false); - response.setStatusLine(null, 200, "OK"); + response.setHeader('Content-Type', 'text/xml; charset="utf-8"', false); + response.setStatusLine(null, 207, "Multi-Status"); + response.write('' + + '' + + '' + + `${davBasePath}zotero/` + + '' + + '' + + 'HTTP/1.1 200 OK' + + '' + + '' + + ''); } } } @@ -1300,7 +1332,7 @@ describe("Zotero.Sync.Storage.Mode.WebDAV", function () { }); var results = await controller.purgeOrphanedStorageFiles(); - assertRequestCount(7); + assertRequestCount(8); assert.sameMembers( results.deleted,