mirror of
https://github.com/zotero/zotero.git
synced 2026-10-08 03:08:19 +00:00
Use PROPFIND instead of OPTIONS to cache WebDAV credentials
Some WebDAV servers allow unauthenticated OPTIONS requests, so the
Authorization header capturing added in 089701eca8 wouldn't work.
PROPFIND with Depth: 0 reliably requires authentication while only
returning properties of the directory itself.
https://forums.zotero.org/discussion/comment/506993/#Comment_506993
This commit is contained in:
parent
5e82c888b6
commit
eecdd66098
2 changed files with 51 additions and 12 deletions
|
|
@ -253,12 +253,20 @@ Zotero.Sync.Storage.Mode.WebDAV.prototype = {
|
|||
|
||||
Zotero.debug("Caching WebDAV credentials");
|
||||
|
||||
let xmlstr = "<propfind xmlns='DAV:'><prop>"
|
||||
+ "<getcontentlength/>"
|
||||
+ "</prop></propfind>";
|
||||
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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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('<?xml version="1.0" encoding="utf-8"?>'
|
||||
+ '<D:multistatus xmlns:D="DAV:">'
|
||||
+ '<D:response>'
|
||||
+ `<D:href>${path}</D:href>`
|
||||
+ '<D:propstat>'
|
||||
+ '<D:prop><D:getcontentlength/></D:prop>'
|
||||
+ '<D:status>HTTP/1.1 200 OK</D:status>'
|
||||
+ '</D:propstat>'
|
||||
+ '</D:response>'
|
||||
+ '</D:multistatus>');
|
||||
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('<?xml version="1.0" encoding="utf-8"?>'
|
||||
+ '<D:multistatus xmlns:D="DAV:">'
|
||||
+ '<D:response>'
|
||||
+ `<D:href>${davBasePath}zotero/</D:href>`
|
||||
+ '<D:propstat>'
|
||||
+ '<D:prop><D:getcontentlength/></D:prop>'
|
||||
+ '<D:status>HTTP/1.1 200 OK</D:status>'
|
||||
+ '</D:propstat>'
|
||||
+ '</D:response>'
|
||||
+ '</D:multistatus>');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1300,7 +1332,7 @@ describe("Zotero.Sync.Storage.Mode.WebDAV", function () {
|
|||
});
|
||||
|
||||
var results = await controller.purgeOrphanedStorageFiles();
|
||||
assertRequestCount(7);
|
||||
assertRequestCount(8);
|
||||
|
||||
assert.sameMembers(
|
||||
results.deleted,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue