Skip to content

Commit

Permalink
Added more compliance with the WebDAV RFC (body checking, errors retu…
Browse files Browse the repository at this point in the history
…rned, etc...)
  • Loading branch information
AdrienCastex committed Jun 9, 2017
1 parent c4dc8db commit 46cbef7
Show file tree
Hide file tree
Showing 28 changed files with 555 additions and 468 deletions.
1 change: 1 addition & 0 deletions lib/server/MethodCallArgs.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export declare class MethodCallArgs {
user: IUser;
protected constructor(server: WebDAVServer, request: http.IncomingMessage, response: http.ServerResponse, exit: () => void, callback: () => void);
static create(server: WebDAVServer, request: http.IncomingMessage, response: http.ServerResponse, callback: (error: Error, mca: MethodCallArgs) => void): void;
noBodyExpected(callback: () => void): void;
checkIfHeader(defaultResource: IResource, callback: () => void): void;
requireCustomPrivilege(privileges: string | string[], resource: IResource, callback: () => void): void;
requirePrivilege(privileges: BasicPrivilege | BasicPrivilege[], resource: IResource, callback: () => void): void;
Expand Down
8 changes: 8 additions & 0 deletions lib/server/MethodCallArgs.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,14 @@ var MethodCallArgs = (function () {
});
});
};
MethodCallArgs.prototype.noBodyExpected = function (callback) {
if (this.server.options.strictMode && this.contentLength !== 0) {
this.setCode(HTTPCodes_1.HTTPCodes.UnsupportedMediaType);
this.exit();
}
else
callback();
};
MethodCallArgs.prototype.checkIfHeader = function (defaultResource, callback) {
var _this = this;
var ifHeader = this.findHeader('If');
Expand Down
1 change: 1 addition & 0 deletions lib/server/WebDAVServerOptions.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export declare class WebDAVServerOptions {
canChunk?: boolean;
hostname?: string;
port?: number;
strictMode?: boolean;
}
export default WebDAVServerOptions;
export declare function setDefaultServerOptions(options: WebDAVServerOptions): WebDAVServerOptions;
1 change: 1 addition & 0 deletions lib/server/WebDAVServerOptions.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ var WebDAVServerOptions = (function () {
this.canChunk = true;
this.hostname = '::';
this.port = 1900;
this.strictMode = false;
}
return WebDAVServerOptions;
}());
Expand Down
154 changes: 78 additions & 76 deletions lib/server/commands/Copy.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,107 +99,109 @@ function copy(arg, source, rDest, destination, callback) {
});
}
function default_1(arg, callback) {
arg.getResource(function (e, source) {
if (e) {
arg.setCode(WebDAVRequest_1.HTTPCodes.NotFound);
callback();
return;
}
arg.checkIfHeader(source, function () {
var overwrite = arg.findHeader('overwrite') !== 'F';
var destination = arg.findHeader('destination');
if (!destination) {
arg.setCode(WebDAVRequest_1.HTTPCodes.BadRequest);
arg.noBodyExpected(function () {
arg.getResource(function (e, source) {
if (e) {
arg.setCode(WebDAVRequest_1.HTTPCodes.NotFound);
callback();
return;
}
destination = destination.substring(destination.indexOf('://') + '://'.length);
destination = destination.substring(destination.indexOf('/'));
destination = new FSManager_1.FSPath(destination);
arg.server.getResourceFromPath(destination.getParent(), function (e, rDest) {
if (e) {
arg.setCode(WebDAVRequest_1.HTTPCodes.InternalServerError);
arg.checkIfHeader(source, function () {
var overwrite = arg.findHeader('overwrite') !== 'F';
var destination = arg.findHeader('destination');
if (!destination) {
arg.setCode(WebDAVRequest_1.HTTPCodes.BadRequest);
callback();
return;
}
arg.requirePrivilege(['canGetType'], source, function () {
arg.requirePrivilege(['canGetChildren'], rDest, function () {
source.type(function (e, type) { return process.nextTick(function () {
if (e) {
arg.setCode(WebDAVRequest_1.HTTPCodes.InternalServerError);
callback();
return;
}
function done(overridded) {
copy(arg, source, rDest, destination, function (e) {
if (e)
arg.setCode(WebDAVRequest_1.HTTPCodes.InternalServerError);
else if (overridded)
arg.setCode(WebDAVRequest_1.HTTPCodes.NoContent);
else
arg.setCode(WebDAVRequest_1.HTTPCodes.Created);
callback();
});
}
var nb = 0;
function go(error, destCollision) {
if (nb <= 0)
return;
if (error) {
nb = -1;
destination = destination.substring(destination.indexOf('://') + '://'.length);
destination = destination.substring(destination.indexOf('/'));
destination = new FSManager_1.FSPath(destination);
arg.server.getResourceFromPath(destination.getParent(), function (e, rDest) {
if (e) {
arg.setCode(WebDAVRequest_1.HTTPCodes.InternalServerError);
callback();
return;
}
arg.requirePrivilege(['canGetType'], source, function () {
arg.requirePrivilege(['canGetChildren'], rDest, function () {
source.type(function (e, type) { return process.nextTick(function () {
if (e) {
arg.setCode(WebDAVRequest_1.HTTPCodes.InternalServerError);
callback();
return;
}
if (destCollision) {
nb = -1;
if (!overwrite) {
function done(overridded) {
copy(arg, source, rDest, destination, function (e) {
if (e)
arg.setCode(WebDAVRequest_1.HTTPCodes.InternalServerError);
else if (overridded)
arg.setCode(WebDAVRequest_1.HTTPCodes.NoContent);
else
arg.setCode(WebDAVRequest_1.HTTPCodes.Created);
callback();
});
}
var nb = 0;
function go(error, destCollision) {
if (nb <= 0)
return;
if (error) {
nb = -1;
arg.setCode(WebDAVRequest_1.HTTPCodes.InternalServerError);
callback();
return;
}
destCollision.type(function (e, destType) { return process.nextTick(function () {
if (e) {
callback(e);
return;
}
if (destType !== type) {
if (destCollision) {
nb = -1;
if (!overwrite) {
arg.setCode(WebDAVRequest_1.HTTPCodes.InternalServerError);
callback();
return;
}
destCollision.delete(function (e) { return process.nextTick(function () {
destCollision.type(function (e, destType) { return process.nextTick(function () {
if (e) {
callback(e);
return;
}
done(true);
if (destType !== type) {
arg.setCode(WebDAVRequest_1.HTTPCodes.InternalServerError);
callback();
return;
}
destCollision.delete(function (e) { return process.nextTick(function () {
if (e) {
callback(e);
return;
}
done(true);
}); });
}); });
}); });
return;
}
--nb;
if (nb === 0) {
done(false);
}
}
rDest.getChildren(function (e, children) { return process.nextTick(function () {
if (e) {
go(e, null);
return;
}
nb += children.length;
if (nb === 0) {
done(false);
return;
return;
}
--nb;
if (nb === 0) {
done(false);
}
}
children.forEach(function (child) {
child.webName(function (e, name) { return process.nextTick(function () {
go(e, name === destination.fileName() ? child : null);
}); });
});
rDest.getChildren(function (e, children) { return process.nextTick(function () {
if (e) {
go(e, null);
return;
}
nb += children.length;
if (nb === 0) {
done(false);
return;
}
children.forEach(function (child) {
child.webName(function (e, name) { return process.nextTick(function () {
go(e, name === destination.fileName() ? child : null);
}); });
});
}); });
}); });
}); });
});
});
});
});
Expand Down
32 changes: 17 additions & 15 deletions lib/server/commands/Delete.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,23 @@
Object.defineProperty(exports, "__esModule", { value: true });
var WebDAVRequest_1 = require("../WebDAVRequest");
function default_1(arg, callback) {
arg.getResource(function (e, r) {
if (e) {
arg.setCode(WebDAVRequest_1.HTTPCodes.NotFound);
callback();
return;
}
arg.checkIfHeader(r, function () {
arg.requirePrivilege(['canDelete'], r, function () {
r.delete(function (e) { return process.nextTick(function () {
if (e)
arg.setCode(WebDAVRequest_1.HTTPCodes.InternalServerError);
else
arg.setCode(WebDAVRequest_1.HTTPCodes.OK);
callback();
}); });
arg.noBodyExpected(function () {
arg.getResource(function (e, r) {
if (e) {
arg.setCode(WebDAVRequest_1.HTTPCodes.NotFound);
callback();
return;
}
arg.checkIfHeader(r, function () {
arg.requirePrivilege(['canDelete'], r, function () {
r.delete(function (e) { return process.nextTick(function () {
if (e)
arg.setCode(WebDAVRequest_1.HTTPCodes.InternalServerError);
else
arg.setCode(WebDAVRequest_1.HTTPCodes.OK);
callback();
}); });
});
});
});
});
Expand Down
42 changes: 22 additions & 20 deletions lib/server/commands/Get.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,28 @@
Object.defineProperty(exports, "__esModule", { value: true });
var WebDAVRequest_1 = require("../WebDAVRequest");
function default_1(arg, callback) {
arg.getResource(function (e, r) {
if (e) {
arg.setCode(WebDAVRequest_1.HTTPCodes.NotFound);
callback();
return;
}
arg.checkIfHeader(r, function () {
var targetSource = arg.findHeader('source', 'F').toUpperCase() === 'T';
arg.requirePrivilege(targetSource ? ['canRead', 'canSource'] : ['canRead'], r, function () {
r.read(targetSource, function (e, rstream) { return process.nextTick(function () {
if (e) {
arg.setCode(WebDAVRequest_1.HTTPCodes.MethodNotAllowed);
callback();
}
else {
arg.setCode(WebDAVRequest_1.HTTPCodes.OK);
rstream.on('end', callback);
rstream.pipe(arg.response);
}
}); });
arg.noBodyExpected(function () {
arg.getResource(function (e, r) {
if (e) {
arg.setCode(WebDAVRequest_1.HTTPCodes.NotFound);
callback();
return;
}
arg.checkIfHeader(r, function () {
var targetSource = arg.findHeader('source', 'F').toUpperCase() === 'T';
arg.requirePrivilege(targetSource ? ['canRead', 'canSource'] : ['canRead'], r, function () {
r.read(targetSource, function (e, rstream) { return process.nextTick(function () {
if (e) {
arg.setCode(WebDAVRequest_1.HTTPCodes.MethodNotAllowed);
callback();
}
else {
arg.setCode(WebDAVRequest_1.HTTPCodes.OK);
rstream.on('end', callback);
rstream.pipe(arg.response);
}
}); });
});
});
});
});
Expand Down
36 changes: 19 additions & 17 deletions lib/server/commands/Head.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,25 @@
Object.defineProperty(exports, "__esModule", { value: true });
var WebDAVRequest_1 = require("../WebDAVRequest");
function default_1(arg, callback) {
arg.getResource(function (e, r) {
if (e) {
arg.setCode(WebDAVRequest_1.HTTPCodes.NotFound);
callback();
return;
}
var targetSource = arg.findHeader('source', 'F').toUpperCase() === 'T';
arg.checkIfHeader(r, function () {
arg.requirePrivilege(targetSource ? ['canRead', 'canSource'] : ['canRead'], r, function () {
r.type(function (e, type) {
if (e)
arg.setCode(WebDAVRequest_1.HTTPCodes.InternalServerError);
else if (!type.isFile)
arg.setCode(WebDAVRequest_1.HTTPCodes.MethodNotAllowed);
else
arg.setCode(WebDAVRequest_1.HTTPCodes.OK);
callback();
arg.noBodyExpected(function () {
arg.getResource(function (e, r) {
if (e) {
arg.setCode(WebDAVRequest_1.HTTPCodes.NotFound);
callback();
return;
}
var targetSource = arg.findHeader('source', 'F').toUpperCase() === 'T';
arg.checkIfHeader(r, function () {
arg.requirePrivilege(targetSource ? ['canRead', 'canSource'] : ['canRead'], r, function () {
r.type(function (e, type) {
if (e)
arg.setCode(WebDAVRequest_1.HTTPCodes.InternalServerError);
else if (!type.isFile)
arg.setCode(WebDAVRequest_1.HTTPCodes.MethodNotAllowed);
else
arg.setCode(WebDAVRequest_1.HTTPCodes.OK);
callback();
});
});
});
});
Expand Down

0 comments on commit 46cbef7

Please sign in to comment.