435 lines
17 KiB
JavaScript
435 lines
17 KiB
JavaScript
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
var RequestContext_1 = require("../RequestContext");
|
|
var WebDAVServerOptions_1 = require("../WebDAVServerOptions");
|
|
var JSCompatibility_1 = require("../../../helper/JSCompatibility");
|
|
var Path_1 = require("../../../manager/v2/Path");
|
|
var Commands_1 = require("../commands/Commands");
|
|
var persistence = require("./Persistence");
|
|
var beforeAfter = require("./BeforeAfter");
|
|
var startStop = require("./StartStop");
|
|
var promise_1 = require("../../../helper/v2/promise");
|
|
var WebDAVServer = /** @class */ (function () {
|
|
function WebDAVServer(options) {
|
|
/**
|
|
* Stop the WebDAV server.
|
|
*/
|
|
this.stop = startStop.stop;
|
|
/**
|
|
* Execute a request as if the HTTP server received it.
|
|
*/
|
|
this.executeRequest = startStop.executeRequest.bind(this);
|
|
/**
|
|
* Load the previous save made by the 'autoSave' system.
|
|
*/
|
|
this.autoLoad = persistence.autoLoad;
|
|
/**
|
|
* Load a state of the resource tree.
|
|
*/
|
|
this.load = persistence.load;
|
|
/**
|
|
* Save the state of the resource tree.
|
|
*/
|
|
this.save = persistence.save;
|
|
this.beforeManagers = [];
|
|
this.afterManagers = [];
|
|
this.methods = {};
|
|
this.options = WebDAVServerOptions_1.setDefaultServerOptions(options);
|
|
this.events = {};
|
|
this.httpAuthentication = this.options.httpAuthentication;
|
|
this.privilegeManager = this.options.privilegeManager;
|
|
this.fileSystems = {
|
|
'/': this.options.rootFileSystem
|
|
};
|
|
// Implement all methods in commands/Commands.ts
|
|
var commands = Commands_1.default;
|
|
for (var k in commands)
|
|
if (k === 'NotImplemented')
|
|
this.onUnknownMethod(new commands[k]());
|
|
else
|
|
this.method(k, new commands[k]());
|
|
}
|
|
WebDAVServer.prototype.isSameFileSystem = function (fs, path, checkByReference) {
|
|
return checkByReference && this.fileSystems[path] === fs || !checkByReference && this.fileSystems[path].serializer().uid() === fs.serializer().uid();
|
|
};
|
|
WebDAVServer.prototype.createExternalContext = function (_options, _callback) {
|
|
return RequestContext_1.ExternalRequestContext.create(this, _options, _callback);
|
|
};
|
|
/**
|
|
* Get the root file system.
|
|
*
|
|
* @returns The root file system
|
|
*/
|
|
WebDAVServer.prototype.rootFileSystem = function () {
|
|
return this.fileSystems['/'];
|
|
};
|
|
/**
|
|
* Get a resource object to manage a resource from its path.
|
|
*
|
|
* @param ctx Context of the request
|
|
* @param path Path of the resource
|
|
*/
|
|
WebDAVServer.prototype.getResourceAsync = function (ctx, path) {
|
|
var _this = this;
|
|
return promise_1.promisifyCall(function (cb) { return _this.getResource(ctx, path, cb); });
|
|
};
|
|
/**
|
|
* Get a resource object to manage a resource from its path.
|
|
*
|
|
* @param ctx Context of the request
|
|
* @param path Path of the resource
|
|
* @param callback Callback containing the requested resource
|
|
*/
|
|
WebDAVServer.prototype.getResource = function (ctx, path, callback) {
|
|
path = new Path_1.Path(path);
|
|
this.getFileSystem(path, function (fs, _, subPath) {
|
|
callback(null, fs.resource(ctx, subPath));
|
|
});
|
|
};
|
|
/**
|
|
* Synchronously get a resource object to manage a resource from its path.
|
|
*
|
|
* @param ctx Context of the request
|
|
* @param path Path of the resource
|
|
* @returns The requested resource
|
|
*/
|
|
WebDAVServer.prototype.getResourceSync = function (ctx, path) {
|
|
path = new Path_1.Path(path);
|
|
var info = this.getFileSystemSync(path);
|
|
return info.fs.resource(ctx, info.subPath);
|
|
};
|
|
WebDAVServer.prototype.setFileSystemAsync = function (path, fs, override) {
|
|
var _this = this;
|
|
return promise_1.promisifyCall(function (cb) { return _this.setFileSystem(path, fs, override, function (successed) { return cb(undefined, successed); }); });
|
|
};
|
|
WebDAVServer.prototype.setFileSystem = function (path, fs, _override, _callback) {
|
|
var override = _callback ? _override : undefined;
|
|
var callback = _callback ? _callback : _override;
|
|
var result = this.setFileSystemSync(path, fs, override);
|
|
if (callback)
|
|
callback(result);
|
|
};
|
|
/**
|
|
* Synchronously map/mount a file system to a path.
|
|
*
|
|
* @param path Path where to mount the file system
|
|
* @param fs File system to mount
|
|
* @param override Define if the mounting can override a previous mounted file system
|
|
* @returns The status of the mounting
|
|
*/
|
|
WebDAVServer.prototype.setFileSystemSync = function (path, fs, override) {
|
|
if (override === void 0) { override = true; }
|
|
var sPath = new Path_1.Path(path).toString();
|
|
if (!override && this.fileSystems[sPath])
|
|
return false;
|
|
this.fileSystems[sPath] = fs;
|
|
return true;
|
|
};
|
|
WebDAVServer.prototype.removeFileSystem = function (fs_path, _checkByReference, _callback) {
|
|
var checkByReference = _callback ? _checkByReference : true;
|
|
var callback = _callback ? _callback : _checkByReference;
|
|
var result = this.removeFileSystemSync(fs_path, checkByReference);
|
|
if (callback)
|
|
callback(result);
|
|
};
|
|
WebDAVServer.prototype.removeFileSystemSync = function (fs_path, checkByReference) {
|
|
if (checkByReference === void 0) { checkByReference = true; }
|
|
var nb = 0;
|
|
if (fs_path.constructor === Path_1.Path || fs_path.constructor === String) {
|
|
var path = new Path_1.Path(fs_path).toString();
|
|
if (this.fileSystems[path] !== undefined) {
|
|
delete this.fileSystems[path];
|
|
nb = 1;
|
|
}
|
|
}
|
|
else {
|
|
var fs = fs_path;
|
|
for (var name_1 in this.fileSystems) {
|
|
if (this.isSameFileSystem(fs, name_1, checkByReference)) {
|
|
delete this.fileSystems[name_1];
|
|
++nb;
|
|
}
|
|
}
|
|
}
|
|
return nb;
|
|
};
|
|
WebDAVServer.prototype.getFileSystemPath = function (fs, _checkByReference, _callback) {
|
|
var checkByReference = _callback ? _checkByReference : undefined;
|
|
var callback = _callback ? _callback : _checkByReference;
|
|
callback(this.getFileSystemPathSync(fs, checkByReference));
|
|
};
|
|
/**
|
|
* Synchronously get the mount path of a file system.
|
|
*
|
|
* @param fs File system
|
|
* @param checkByReference Define if the file system must be matched by reference or by its serializer's UID
|
|
* @returns The mount path of the file system
|
|
*/
|
|
WebDAVServer.prototype.getFileSystemPathSync = function (fs, checkByReference) {
|
|
checkByReference = checkByReference === null || checkByReference === undefined ? true : checkByReference;
|
|
for (var path in this.fileSystems)
|
|
if (this.isSameFileSystem(fs, path, checkByReference))
|
|
return new Path_1.Path(path);
|
|
return null;
|
|
};
|
|
/**
|
|
* Get the list of file systems mounted on or under the parentPath.
|
|
*
|
|
* @param parentPath Path from which list sub file systems
|
|
* @param callback Callback containing the list of file systems found and their mount path
|
|
*/
|
|
WebDAVServer.prototype.getChildFileSystems = function (parentPath, callback) {
|
|
var result = this.getChildFileSystemsSync(parentPath);
|
|
callback(result);
|
|
};
|
|
/**
|
|
* Synchronously get the list of file systems mounted on or under the parentPath.
|
|
*
|
|
* @param parentPath Path from which list sub file systems
|
|
* @returns Object containing the list of file systems found and their mount path
|
|
*/
|
|
WebDAVServer.prototype.getChildFileSystemsSync = function (parentPath) {
|
|
var results = [];
|
|
var seekPath = parentPath.toString(true);
|
|
for (var fsPath in this.fileSystems) {
|
|
var pfsPath = new Path_1.Path(fsPath);
|
|
if (pfsPath.paths.length === parentPath.paths.length + 1 && JSCompatibility_1.startsWith(fsPath, seekPath)) {
|
|
results.push({
|
|
fs: this.fileSystems[fsPath],
|
|
path: pfsPath
|
|
});
|
|
}
|
|
}
|
|
return results;
|
|
};
|
|
/**
|
|
* Get the file system managing the provided path.
|
|
*
|
|
* @param path Requested path
|
|
*/
|
|
WebDAVServer.prototype.getFileSystemAsync = function (path) {
|
|
var _this = this;
|
|
return promise_1.promisifyCall(function (cb) { return _this.getFileSystem(path, function (fs, rootPath, subPath) { return cb(undefined, { fs: fs, rootPath: rootPath, subPath: subPath }); }); });
|
|
};
|
|
/**
|
|
* Get the file system managing the provided path.
|
|
*
|
|
* @param path Requested path
|
|
* @param callback Callback containing the file system, the mount path of the file system and the sub path from the mount path to the requested path
|
|
*/
|
|
WebDAVServer.prototype.getFileSystem = function (path, callback) {
|
|
var result = this.getFileSystemSync(path);
|
|
callback(result.fs, result.rootPath, result.subPath);
|
|
};
|
|
/**
|
|
* Get synchronously the file system managing the provided path.
|
|
*
|
|
* @param path Requested path
|
|
* @returns Object containing the file system, the mount path of the file system and the sub path from the mount path to the requested path
|
|
*/
|
|
WebDAVServer.prototype.getFileSystemSync = function (path) {
|
|
var best = {
|
|
index: 0,
|
|
rootPath: new Path_1.Path('/')
|
|
};
|
|
for (var fsPath in this.fileSystems) {
|
|
var pfsPath = new Path_1.Path(fsPath);
|
|
if (path.paths.length < pfsPath.paths.length)
|
|
continue;
|
|
var value = 0;
|
|
for (; value < pfsPath.paths.length; ++value)
|
|
if (pfsPath.paths[value] !== path.paths[value]) {
|
|
value = -1;
|
|
break;
|
|
}
|
|
if (best.index < value)
|
|
best = {
|
|
index: value,
|
|
rootPath: pfsPath
|
|
};
|
|
if (value === path.paths.length)
|
|
break; // Found the best value possible.
|
|
}
|
|
var subPath = path.clone();
|
|
for (var _i = 0, _a = best.rootPath.paths; _i < _a.length; _i++) {
|
|
var _ = _a[_i];
|
|
subPath.removeRoot();
|
|
}
|
|
return {
|
|
fs: this.fileSystems[best.rootPath.toString()],
|
|
rootPath: best.rootPath,
|
|
subPath: subPath
|
|
};
|
|
};
|
|
/**
|
|
* Action to execute when the requested method is unknown.
|
|
*
|
|
* @param unknownMethod Action to execute
|
|
*/
|
|
WebDAVServer.prototype.onUnknownMethod = function (unknownMethod) {
|
|
this.unknownMethod = unknownMethod;
|
|
};
|
|
WebDAVServer.prototype.listResourcesAsync = function (root) {
|
|
var _this = this;
|
|
return promise_1.promisifyCall(function (cb) { return _this.listResources(root, function (paths) { return cb(undefined, paths); }); });
|
|
};
|
|
WebDAVServer.prototype.listResources = function (_root, _callback) {
|
|
var _this = this;
|
|
var root = new Path_1.Path(Path_1.Path.isPath(_root) ? _root : '/');
|
|
var callback = _callback ? _callback : _root;
|
|
var output = [];
|
|
output.push(root.toString());
|
|
this.getResource(this.createExternalContext(), root, function (e, resource) {
|
|
resource.readDir(true, function (e, files) {
|
|
if (e || files.length === 0)
|
|
return callback(output);
|
|
var nb = files.length;
|
|
files.forEach(function (fileName) {
|
|
var childPath = root.getChildPath(fileName);
|
|
_this.listResources(childPath, function (outputs) {
|
|
outputs.forEach(function (o) { return output.push(o); });
|
|
if (--nb === 0)
|
|
callback(output);
|
|
});
|
|
});
|
|
});
|
|
});
|
|
};
|
|
WebDAVServer.prototype.startAsync = function (port) {
|
|
var _this = this;
|
|
return promise_1.promisifyCall(function (cb) { return _this.start(port, function (server) { return cb(undefined, server); }); });
|
|
};
|
|
WebDAVServer.prototype.start = function (port, callback) {
|
|
startStop.start.bind(this)(port, callback);
|
|
};
|
|
/**
|
|
* Stop the WebDAV server.
|
|
*/
|
|
WebDAVServer.prototype.stopAsync = function () {
|
|
var _this = this;
|
|
return promise_1.promisifyCall(function (cb) { return _this.stop(cb); });
|
|
};
|
|
WebDAVServer.prototype.autoSave = function (options) {
|
|
var fn = persistence.autoSave.bind(this);
|
|
if (options)
|
|
fn(options);
|
|
else if (this.options.autoSave)
|
|
fn(this.options.autoSave);
|
|
};
|
|
/**
|
|
* Force the autoSave system to save when available.
|
|
*/
|
|
WebDAVServer.prototype.forceAutoSave = function () {
|
|
this.autoSavePool.save();
|
|
};
|
|
/**
|
|
* Load the previous save made by the 'autoSave' system.
|
|
*/
|
|
WebDAVServer.prototype.autoLoadAsync = function () {
|
|
var _this = this;
|
|
return promise_1.promisifyCall(function (cb) { return _this.autoLoad(cb); });
|
|
};
|
|
/**
|
|
* Load a state of the resource tree.
|
|
*/
|
|
WebDAVServer.prototype.loadAsync = function (data, serializers) {
|
|
var _this = this;
|
|
return promise_1.promisifyCall(function (cb) { return _this.load(data, serializers, cb); });
|
|
};
|
|
/**
|
|
* Save the state of the resource tree.
|
|
*/
|
|
WebDAVServer.prototype.saveAsync = function () {
|
|
var _this = this;
|
|
return promise_1.promisifyCall(function (cb) { return _this.save(cb); });
|
|
};
|
|
/**
|
|
* Define an action to execute when a HTTP method is requested.
|
|
*
|
|
* @param name Name of the method to bind to
|
|
* @param manager Action to execute when the method is requested
|
|
*/
|
|
WebDAVServer.prototype.method = function (name, manager) {
|
|
this.methods[this.normalizeMethodName(name)] = manager;
|
|
};
|
|
WebDAVServer.prototype.on = function (event, listener) {
|
|
if (!this.events[event])
|
|
this.events[event] = [];
|
|
this.events[event].push(listener);
|
|
return this;
|
|
};
|
|
WebDAVServer.prototype.removeEvent = function (event, listener) {
|
|
if (listener) {
|
|
if (this.events[event]) {
|
|
var eventList = this.events[event];
|
|
for (var index = 0; index < eventList.length; ++index) {
|
|
if (eventList[index] === listener) {
|
|
eventList.splice(index, 1);
|
|
--index;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
delete this.events[event];
|
|
}
|
|
return this;
|
|
};
|
|
/**
|
|
* Trigger an event.
|
|
*
|
|
* @param event Name of the event.
|
|
* @param ctx Context of the event.
|
|
* @param fs File system on which the event happened.
|
|
* @param path Path of the resource on which the event happened.
|
|
*/
|
|
WebDAVServer.prototype.emit = function (event, ctx, fs, path, data) {
|
|
if (!this.events[event])
|
|
return;
|
|
this.events[event].forEach(function (l) { return process.nextTick(function () { return l(ctx, fs, path.constructor === String ? new Path_1.Path(path) : path, data); }); });
|
|
};
|
|
/**
|
|
* Normalize the name of the method.
|
|
*/
|
|
WebDAVServer.prototype.normalizeMethodName = function (method) {
|
|
return method.toLowerCase();
|
|
};
|
|
// Before / After execution
|
|
/**
|
|
* Invoke the BeforeRequest events.
|
|
*
|
|
* @param base Context of the request
|
|
* @param callback Callback to execute when all BeforeRequest events have been executed
|
|
*/
|
|
WebDAVServer.prototype.invokeBeforeRequest = function (base, callback) {
|
|
beforeAfter.invokeBeforeRequest.bind(this)(base, callback);
|
|
};
|
|
/**
|
|
* Invoke the AfterRequest events.
|
|
*
|
|
* @param base Context of the request
|
|
* @param callback Callback to execute when all AfterRequest events have been executed
|
|
*/
|
|
WebDAVServer.prototype.invokeAfterRequest = function (base, callback) {
|
|
beforeAfter.invokeAfterRequest.bind(this)(base, callback);
|
|
};
|
|
/**
|
|
* Action to execute before an operation is executed when a HTTP request is received.
|
|
*
|
|
* @param manager Action to execute
|
|
*/
|
|
WebDAVServer.prototype.beforeRequest = function (manager) {
|
|
this.beforeManagers.push(manager);
|
|
};
|
|
/**
|
|
* Action to execute after an operation is executed when a HTTP request is received.
|
|
*
|
|
* @param manager Action to execute
|
|
*/
|
|
WebDAVServer.prototype.afterRequest = function (manager) {
|
|
this.afterManagers.push(manager);
|
|
};
|
|
return WebDAVServer;
|
|
}());
|
|
exports.WebDAVServer = WebDAVServer;
|