1406 lines
68 KiB
JavaScript
1406 lines
68 KiB
JavaScript
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
var CommonTypes_1 = require("./CommonTypes");
|
|
var stream_1 = require("stream");
|
|
var ContextualFileSystem_1 = require("./ContextualFileSystem");
|
|
var StandardMethods_1 = require("./StandardMethods");
|
|
var LockScope_1 = require("../../../resource/v2/lock/LockScope");
|
|
var LockType_1 = require("../../../resource/v2/lock/LockType");
|
|
var LockKind_1 = require("../../../resource/v2/lock/LockKind");
|
|
var Workflow_1 = require("../../../helper/Workflow");
|
|
var Resource_1 = require("./Resource");
|
|
var Errors_1 = require("../../../Errors");
|
|
var Path_1 = require("../Path");
|
|
var crypto = require("crypto");
|
|
var promise_1 = require("../../../helper/v2/promise");
|
|
var BufferedIsLocked = /** @class */ (function () {
|
|
function BufferedIsLocked(fs, ctx, path) {
|
|
this.fs = fs;
|
|
this.ctx = ctx;
|
|
this.path = path;
|
|
this._isLocked = null;
|
|
}
|
|
BufferedIsLocked.prototype.isLocked = function (callback) {
|
|
var _this = this;
|
|
if (this._isLocked !== null)
|
|
return callback(null, this._isLocked);
|
|
this.fs.isLocked(this.ctx, this.path, function (e, locked) {
|
|
if (e)
|
|
return callback(e);
|
|
_this._isLocked = locked;
|
|
callback(null, locked);
|
|
});
|
|
};
|
|
return BufferedIsLocked;
|
|
}());
|
|
/**
|
|
* File system which manage resources under its mounted path.
|
|
*
|
|
* @see https://github.com/OpenMarshal/npm-WebDAV-Server/wiki/Custom-File-System-%5Bv2%5D
|
|
*/
|
|
var FileSystem = /** @class */ (function () {
|
|
function FileSystem(serializer) {
|
|
this.__serializer = serializer;
|
|
}
|
|
/**
|
|
* Get the serializer.
|
|
*/
|
|
FileSystem.prototype.serializer = function () {
|
|
return this.__serializer;
|
|
};
|
|
/**
|
|
* Defines the serializer to use.
|
|
*
|
|
* @param serializer Serializer to use.
|
|
*/
|
|
FileSystem.prototype.setSerializer = function (serializer) {
|
|
this.__serializer = serializer;
|
|
};
|
|
/**
|
|
* Tell to not serialize this file system.
|
|
*/
|
|
FileSystem.prototype.doNotSerialize = function () {
|
|
this.__serializer = null;
|
|
};
|
|
/**
|
|
* Wrap the file system with the context.
|
|
*
|
|
* @param ctx Context of the operation.
|
|
*/
|
|
FileSystem.prototype.contextualize = function (ctx) {
|
|
return new ContextualFileSystem_1.ContextualFileSystem(this, ctx);
|
|
};
|
|
/**
|
|
* Wrap the file system with the context and a resource path.
|
|
*
|
|
* @param ctx Context of the operation.
|
|
* @param path Path of the resource.
|
|
*/
|
|
FileSystem.prototype.resource = function (ctx, path) {
|
|
return new Resource_1.Resource(path, this, ctx);
|
|
};
|
|
/**
|
|
* Make a fast check if the resource exists.
|
|
* If '_fastExistCheck' is not implemented, this method call 'callback'.
|
|
* If '_fastExistCheck' is implemented and it returns 'false', then the 'errorCallback' is called, otherwise the 'callback' is called.
|
|
*
|
|
* This method will not give a true information, but just an estimate of the existence of a resource.
|
|
*
|
|
* @param ctx Context of the operation.
|
|
* @param _path Path of the resource.
|
|
* @param errorCallback Callback to call when the resource is sure to not exist.
|
|
* @param callback Callback to call when the resource might exists.
|
|
*/
|
|
FileSystem.prototype.fastExistCheckEx = function (ctx, _path, errorCallback, callback) {
|
|
if (!this._fastExistCheck)
|
|
return callback();
|
|
var path = new Path_1.Path(_path);
|
|
this._fastExistCheck(ctx, path, function (exists) {
|
|
if (!exists)
|
|
errorCallback(Errors_1.Errors.ResourceNotFound);
|
|
else
|
|
callback();
|
|
});
|
|
};
|
|
/**
|
|
* Make a fast check if the resource exists.
|
|
* If '_fastExistCheck' is not implemented, this method call 'callback'.
|
|
* If '_fastExistCheck' is implemented and it returns 'false', then the 'callback' is called, otherwise the 'errorCallback' is called.
|
|
*
|
|
* This method will not give a true information, but just an estimate of the existence of a resource.
|
|
*
|
|
* @param ctx Context of the operation.
|
|
* @param _path Path of the resource.
|
|
* @param errorCallback Callback to call when the resource might exists.
|
|
* @param callback Callback to call when the resource is sure to not exist.
|
|
*/
|
|
FileSystem.prototype.fastExistCheckExReverse = function (ctx, _path, errorCallback, callback) {
|
|
if (!this._fastExistCheck)
|
|
return callback();
|
|
var path = new Path_1.Path(_path);
|
|
this._fastExistCheck(ctx, path, function (exists) {
|
|
if (exists)
|
|
errorCallback(Errors_1.Errors.ResourceAlreadyExists);
|
|
else
|
|
callback();
|
|
});
|
|
};
|
|
/**
|
|
* Make a fast check if a resource exists.
|
|
* This method will call '_fastExistCheck' if it is implemented or return 'true'.
|
|
*
|
|
* This method will not give a true information, but just an estimate of the existence of a resource.
|
|
*
|
|
* @param ctx Context of the operation.
|
|
* @param _path Path of the resource.
|
|
* @param callback Returns if the resource exists.
|
|
*/
|
|
FileSystem.prototype.fastExistCheck = function (ctx, _path, callback) {
|
|
if (!this._fastExistCheck)
|
|
return callback(true);
|
|
var path = new Path_1.Path(_path);
|
|
this._fastExistCheck(ctx, path, function (exists) { return callback(!!exists); });
|
|
};
|
|
FileSystem.prototype.createAsync = function (ctx, path, type, createIntermediates) {
|
|
var _this = this;
|
|
return promise_1.promisifyCall(function (cb) { return _this.create(ctx, path, type, createIntermediates, cb); });
|
|
};
|
|
FileSystem.prototype.create = function (ctx, _path, type, _createIntermediates, _callback) {
|
|
var _this = this;
|
|
var createIntermediates = promise_1.ensureValue(_callback ? _createIntermediates : undefined, false);
|
|
var callbackFinal = _callback ? _callback : _createIntermediates;
|
|
var path = new Path_1.Path(_path);
|
|
var callback = function (e) {
|
|
if (!e)
|
|
_this.emit('create', ctx, path, { type: type, createIntermediates: createIntermediates });
|
|
callbackFinal(e);
|
|
};
|
|
if (!this._create)
|
|
return callback(Errors_1.Errors.InvalidOperation);
|
|
this.emit('before-create', ctx, path, { type: type, createIntermediates: createIntermediates });
|
|
issuePrivilegeCheck(this, ctx, path, 'canWrite', callback, function () {
|
|
var go = function () {
|
|
ctx.server.options.storageManager.evaluateCreate(ctx, _this, path, type, function (size) {
|
|
ctx.server.options.storageManager.reserve(ctx, _this, size, function (reserved) {
|
|
if (!reserved)
|
|
return callback(Errors_1.Errors.InsufficientStorage);
|
|
_this._create(path, {
|
|
context: ctx,
|
|
type: type
|
|
}, function (e) {
|
|
if (e)
|
|
ctx.server.options.storageManager.reserve(ctx, _this, -size, function () { return callback(e); });
|
|
else
|
|
callback();
|
|
});
|
|
});
|
|
});
|
|
};
|
|
_this.isLocked(ctx, path, function (e, locked) {
|
|
if (e || locked)
|
|
return callback(locked ? Errors_1.Errors.Locked : e);
|
|
_this.fastExistCheckExReverse(ctx, path, callback, function () {
|
|
_this.type(ctx, path.getParent(), function (e, type) {
|
|
if (e === Errors_1.Errors.ResourceNotFound) {
|
|
if (!createIntermediates)
|
|
return callback(Errors_1.Errors.IntermediateResourceMissing);
|
|
_this.getFullPath(ctx, path, function (e, fullPath) {
|
|
if (e)
|
|
return callback(e);
|
|
fullPath = fullPath.getParent();
|
|
ctx.getResource(fullPath, function (e, r) {
|
|
if (e)
|
|
return callback(e);
|
|
r.create(CommonTypes_1.ResourceType.Directory, true, function (e) {
|
|
if (e && e !== Errors_1.Errors.ResourceAlreadyExists)
|
|
return callback(e);
|
|
go();
|
|
});
|
|
});
|
|
});
|
|
return;
|
|
}
|
|
if (e)
|
|
return callback(e);
|
|
if (!type.isDirectory)
|
|
return callback(Errors_1.Errors.WrongParentTypeForCreation);
|
|
go();
|
|
});
|
|
});
|
|
});
|
|
});
|
|
};
|
|
/**
|
|
* Get the etag of the resource.
|
|
* The default etag, if '_etag' is not implemented, is to hash the last modified date information of the resource and wrap it with quotes.
|
|
*
|
|
* @param ctx Context of the operation.
|
|
* @param _path Path of the resource.
|
|
*/
|
|
FileSystem.prototype.etagAsync = function (ctx, path) {
|
|
var _this = this;
|
|
return promise_1.promisifyCall(function (cb) { return _this.etag(ctx, path, cb); });
|
|
};
|
|
/**
|
|
* Get the etag of the resource.
|
|
* The default etag, if '_etag' is not implemented, is to hash the last modified date information of the resource and wrap it with quotes.
|
|
*
|
|
* @param ctx Context of the operation.
|
|
* @param _path Path of the resource.
|
|
* @param callback Returns the etag of the resource.
|
|
*/
|
|
FileSystem.prototype.etag = function (ctx, _path, callback) {
|
|
var _this = this;
|
|
var path = new Path_1.Path(_path);
|
|
issuePrivilegeCheck(this, ctx, path, 'canReadProperties', callback, function () {
|
|
_this.fastExistCheckEx(ctx, path, callback, function () {
|
|
if (!_this._etag)
|
|
return _this.lastModifiedDate(ctx, path, function (e, date) {
|
|
if (e)
|
|
return callback(e);
|
|
date = FileSystem.neutralizeEmptyDate(date);
|
|
callback(null, '"' + crypto.createHash('md5').update(date.toString()).digest('hex') + '"');
|
|
});
|
|
_this._etag(path, {
|
|
context: ctx
|
|
}, callback);
|
|
});
|
|
});
|
|
};
|
|
FileSystem.prototype.deleteAsync = function (ctx, path, depth) {
|
|
var _this = this;
|
|
return promise_1.promisifyCall(function (cb) { return _this.delete(ctx, path, depth, cb); });
|
|
};
|
|
FileSystem.prototype.delete = function (ctx, _path, _depth, _callback) {
|
|
var _this = this;
|
|
var depth = promise_1.ensureValue(_callback ? _depth : undefined, -1);
|
|
var callbackFinal = _callback ? _callback : _depth;
|
|
var path = new Path_1.Path(_path);
|
|
var callback = function (e) {
|
|
if (!e)
|
|
_this.emit('delete', ctx, path, { depth: depth });
|
|
callbackFinal(e);
|
|
};
|
|
if (!this._delete)
|
|
return callback(Errors_1.Errors.InvalidOperation);
|
|
this.emit('before-delete', ctx, path, { depth: depth });
|
|
issuePrivilegeCheck(this, ctx, path, 'canWrite', callback, function () {
|
|
_this.isLocked(ctx, path, function (e, isLocked) {
|
|
if (e || isLocked)
|
|
return callback(e ? e : Errors_1.Errors.Locked);
|
|
_this.fastExistCheckEx(ctx, path, callback, function () {
|
|
_this.size(ctx, path, function (e, contentSize) {
|
|
contentSize = contentSize || 0;
|
|
_this._delete(path, {
|
|
context: ctx,
|
|
depth: depth
|
|
}, function (e) {
|
|
if (!e) {
|
|
_this.type(ctx, path, function (e, type) {
|
|
ctx.server.options.storageManager.evaluateContent(ctx, _this, contentSize, function (reservedContentSize) {
|
|
ctx.server.options.storageManager.evaluateCreate(ctx, _this, path, type, function (size) {
|
|
ctx.server.options.storageManager.reserve(ctx, _this, -size - reservedContentSize, function () {
|
|
callback();
|
|
});
|
|
});
|
|
});
|
|
});
|
|
}
|
|
else
|
|
callback(e);
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|
|
};
|
|
FileSystem.prototype.openWriteStreamAsync = function (ctx, path, mode, targetSource, estimatedSize) {
|
|
var _this = this;
|
|
return promise_1.promisifyCall(function (cb) { return _this.openWriteStream(ctx, path, mode, targetSource, estimatedSize, function (e, data1, data2) { return cb(e, e ? undefined : { stream: data1, created: data2 }); }); });
|
|
};
|
|
FileSystem.prototype.openWriteStream = function (ctx, _path, _mode, _targetSource, _estimatedSize, _callback) {
|
|
var _this = this;
|
|
var targetSource = false;
|
|
for (var _i = 0, _a = [_mode, _targetSource]; _i < _a.length; _i++) {
|
|
var obj = _a[_i];
|
|
if (obj && obj.constructor === Boolean)
|
|
targetSource = obj;
|
|
}
|
|
var estimatedSize = -1;
|
|
for (var _b = 0, _c = [_mode, _targetSource, _estimatedSize]; _b < _c.length; _b++) {
|
|
var obj = _c[_b];
|
|
if (obj && obj.constructor === Number)
|
|
estimatedSize = obj;
|
|
}
|
|
var callbackFinal;
|
|
for (var _d = 0, _e = [_mode, _targetSource, _estimatedSize, _callback]; _d < _e.length; _d++) {
|
|
var obj = _e[_d];
|
|
if (obj && obj.constructor === Function)
|
|
callbackFinal = obj;
|
|
}
|
|
var mode = _mode && _mode.constructor === String ? _mode : 'mustExist';
|
|
var path = new Path_1.Path(_path);
|
|
var created = false;
|
|
var callback = function (e, stream, created) {
|
|
if (!e)
|
|
_this.emit('openWriteStream', ctx, path, { targetSource: targetSource, mode: mode, estimatedSize: estimatedSize, created: created, stream: stream });
|
|
callbackFinal(e, stream, created);
|
|
};
|
|
if (!this._openWriteStream)
|
|
return callback(Errors_1.Errors.InvalidOperation);
|
|
this.emit('before-openWriteStream', ctx, path, { targetSource: targetSource, mode: mode, estimatedSize: estimatedSize, created: created });
|
|
issuePrivilegeCheck(this, ctx, path, targetSource ? 'canWriteContentSource' : 'canWriteContentTranslated', callback, function () {
|
|
_this.isLocked(ctx, path, function (e, isLocked) {
|
|
if (e || isLocked)
|
|
return callback(e ? e : Errors_1.Errors.Locked);
|
|
var finalGo = function (callback) {
|
|
_this._openWriteStream(path, {
|
|
context: ctx,
|
|
estimatedSize: estimatedSize,
|
|
targetSource: targetSource,
|
|
mode: mode
|
|
}, function (e, wStream) { return callback(e, wStream, created); });
|
|
};
|
|
var go = function (callback) {
|
|
_this.size(ctx, path, true, function (e, size) {
|
|
ctx.server.options.storageManager.evaluateContent(ctx, _this, size, function (sizeStored) {
|
|
if (estimatedSize === undefined || estimatedSize === null || estimatedSize.constructor === Number && estimatedSize <= 0) {
|
|
ctx.server.options.storageManager.available(ctx, _this, function (available) {
|
|
if (available === -1)
|
|
return finalGo(callback);
|
|
if (available === 0)
|
|
return callback(Errors_1.Errors.InsufficientStorage);
|
|
var nb = 0;
|
|
finalGo(function (e, wStream, created) {
|
|
if (e)
|
|
return callback(e, wStream, created);
|
|
var stream = new stream_1.Transform({
|
|
transform: function (chunk, encoding, callback) {
|
|
nb += chunk.length;
|
|
if (nb > available)
|
|
callback(Errors_1.Errors.InsufficientStorage);
|
|
else
|
|
callback(null, chunk, encoding);
|
|
}
|
|
});
|
|
stream.pipe(wStream);
|
|
stream.on('finish', function () {
|
|
ctx.server.options.storageManager.reserve(ctx, _this, nb, function (reserved) {
|
|
if (!reserved)
|
|
stream.emit('error', Errors_1.Errors.InsufficientStorage);
|
|
});
|
|
});
|
|
callback(e, stream, created);
|
|
});
|
|
});
|
|
}
|
|
else {
|
|
ctx.server.options.storageManager.evaluateContent(ctx, _this, estimatedSize, function (estimatedSizeStored) {
|
|
ctx.server.options.storageManager.reserve(ctx, _this, estimatedSizeStored - sizeStored, function (reserved) {
|
|
if (!reserved)
|
|
return callback(Errors_1.Errors.InsufficientStorage);
|
|
finalGo(callback);
|
|
});
|
|
});
|
|
}
|
|
});
|
|
});
|
|
};
|
|
var createAndGo = function (intermediates) {
|
|
_this.create(ctx, path, CommonTypes_1.ResourceType.File, intermediates, function (e) {
|
|
if (e)
|
|
return callback(e);
|
|
created = true;
|
|
go(callback);
|
|
});
|
|
};
|
|
switch (mode) {
|
|
case 'mustExist':
|
|
_this.fastExistCheckEx(ctx, path, callback, function () { return go(callback); });
|
|
break;
|
|
case 'mustCreateIntermediates':
|
|
case 'mustCreate':
|
|
createAndGo(mode === 'mustCreateIntermediates');
|
|
break;
|
|
case 'canCreateIntermediates':
|
|
case 'canCreate':
|
|
go(function (e, wStream) {
|
|
if (e === Errors_1.Errors.ResourceNotFound)
|
|
createAndGo(mode === 'canCreateIntermediates');
|
|
else
|
|
callback(e, wStream);
|
|
});
|
|
break;
|
|
default:
|
|
callback(Errors_1.Errors.IllegalArguments);
|
|
break;
|
|
}
|
|
});
|
|
});
|
|
};
|
|
FileSystem.prototype.openReadStreamAsync = function (ctx, path, targetSource, estimatedSize) {
|
|
var _this = this;
|
|
return promise_1.promisifyCall(function (cb) { return _this.openReadStream(ctx, path, targetSource, estimatedSize, cb); });
|
|
};
|
|
FileSystem.prototype.openReadStream = function (ctx, _path, _targetSource, _estimatedSize, _callback) {
|
|
var _this = this;
|
|
var targetSource = promise_1.ensureValue(_targetSource.constructor === Boolean ? _targetSource : undefined, false);
|
|
var estimatedSize = promise_1.ensureValue(_callback ? _estimatedSize : _estimatedSize ? _targetSource : undefined, -1);
|
|
var callbackFinal = _callback ? _callback : _estimatedSize ? _estimatedSize : _targetSource;
|
|
var path = new Path_1.Path(_path);
|
|
var callback = function (e, stream) {
|
|
if (!e)
|
|
_this.emit('openReadStream', ctx, path, { targetSource: targetSource, estimatedSize: estimatedSize, stream: stream });
|
|
callbackFinal(e, stream);
|
|
};
|
|
this.emit('before-openReadStream', ctx, path, { targetSource: targetSource, estimatedSize: estimatedSize });
|
|
issuePrivilegeCheck(this, ctx, path, targetSource ? 'canReadContentSource' : 'canReadContentTranslated', callback, function () {
|
|
_this.fastExistCheckEx(ctx, path, callback, function () {
|
|
if (!_this._openReadStream)
|
|
return callback(Errors_1.Errors.InvalidOperation);
|
|
_this._openReadStream(path, {
|
|
context: ctx,
|
|
estimatedSize: estimatedSize,
|
|
targetSource: targetSource
|
|
}, callback);
|
|
});
|
|
});
|
|
};
|
|
FileSystem.prototype.moveAsync = function (ctx, pathFrom, pathTo, overwrite) {
|
|
var _this = this;
|
|
return promise_1.promisifyCall(function (cb) { return _this.move(ctx, pathFrom, pathTo, overwrite, cb); });
|
|
};
|
|
FileSystem.prototype.move = function (ctx, _pathFrom, _pathTo, _overwrite, _callback) {
|
|
var _this = this;
|
|
var callbackFinal = _callback ? _callback : _overwrite;
|
|
var overwrite = promise_1.ensureValue(_callback ? _overwrite : undefined, false);
|
|
var pathFrom = new Path_1.Path(_pathFrom);
|
|
var pathTo = new Path_1.Path(_pathTo);
|
|
var callback = function (e, overrided) {
|
|
if (!e)
|
|
_this.emit('move', ctx, pathFrom, { pathFrom: pathFrom, pathTo: pathTo, overwrite: overwrite, overrided: overrided });
|
|
callbackFinal(e, overrided);
|
|
};
|
|
this.emit('before-move', ctx, pathFrom, { pathFrom: pathFrom, pathTo: pathTo, overwrite: overwrite });
|
|
issuePrivilegeCheck(this, ctx, pathFrom, 'canRead', callback, function () {
|
|
issuePrivilegeCheck(_this, ctx, pathTo, 'canWrite', callback, function () {
|
|
_this.isLocked(ctx, pathFrom, function (e, isLocked) {
|
|
if (e || isLocked)
|
|
return callback(e ? e : Errors_1.Errors.Locked);
|
|
_this.isLocked(ctx, pathTo, function (e, isLocked) {
|
|
if (e || isLocked)
|
|
return callback(e ? e : Errors_1.Errors.Locked);
|
|
var go = function () {
|
|
if (_this._move) {
|
|
_this._move(pathFrom, pathTo, {
|
|
context: ctx,
|
|
overwrite: overwrite
|
|
}, callback);
|
|
return;
|
|
}
|
|
StandardMethods_1.StandardMethods.standardMove(ctx, pathFrom, _this, pathTo, _this, overwrite, callback);
|
|
};
|
|
_this.fastExistCheckEx(ctx, pathFrom, callback, function () {
|
|
if (!overwrite)
|
|
_this.fastExistCheckExReverse(ctx, pathTo, callback, go);
|
|
else
|
|
go();
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|
|
};
|
|
FileSystem.prototype.copyAsync = function (ctx, pathFrom, pathTo, overwrite, depth) {
|
|
var _this = this;
|
|
return promise_1.promisifyCall(function (cb) { return _this.copy(ctx, pathFrom, pathTo, overwrite, depth); });
|
|
};
|
|
FileSystem.prototype.copy = function (ctx, _pathFrom, _pathTo, _overwrite, _depth, _callback) {
|
|
var _this = this;
|
|
var overwrite = promise_1.ensureValue(_overwrite.constructor === Boolean ? _overwrite : undefined, false);
|
|
var depth = promise_1.ensureValue(_callback ? _depth : !_depth ? -1 : _overwrite.constructor === Number ? _overwrite : undefined, -1);
|
|
var callbackFinal = _callback ? _callback : _depth ? _depth : _overwrite;
|
|
var pathFrom = new Path_1.Path(_pathFrom);
|
|
var pathTo = new Path_1.Path(_pathTo);
|
|
var callback = function (e, overrided) {
|
|
if (!e)
|
|
_this.emit('copy', ctx, pathFrom, { pathTo: pathTo, overwrite: overwrite, overrided: overrided, depth: depth });
|
|
callbackFinal(e, overrided);
|
|
};
|
|
this.emit('before-copy', ctx, pathFrom, { pathTo: pathTo, overwrite: overwrite, depth: depth });
|
|
issuePrivilegeCheck(this, ctx, pathFrom, 'canRead', callback, function () {
|
|
issuePrivilegeCheck(_this, ctx, pathTo, 'canWrite', callback, function () {
|
|
_this.isLocked(ctx, pathTo, function (e, isLocked) {
|
|
if (e || isLocked)
|
|
return callback(e ? e : Errors_1.Errors.Locked);
|
|
var go = function () {
|
|
if (_this._copy) {
|
|
_this._copy(pathFrom, pathTo, {
|
|
context: ctx,
|
|
depth: depth,
|
|
overwrite: overwrite
|
|
}, callback);
|
|
return;
|
|
}
|
|
StandardMethods_1.StandardMethods.standardCopy(ctx, pathFrom, _this, pathTo, _this, overwrite, depth, callback);
|
|
};
|
|
_this.fastExistCheckEx(ctx, pathFrom, callback, function () {
|
|
if (!overwrite)
|
|
_this.fastExistCheckExReverse(ctx, pathTo, callback, go);
|
|
else
|
|
go();
|
|
});
|
|
});
|
|
});
|
|
});
|
|
};
|
|
FileSystem.prototype.renameAsync = function (ctx, pathFrom, newName, overwrite) {
|
|
var _this = this;
|
|
return promise_1.promisifyCall(function (cb) { return _this.rename(ctx, pathFrom, newName, overwrite, cb); });
|
|
};
|
|
FileSystem.prototype.rename = function (ctx, _pathFrom, newName, _overwrite, _callback) {
|
|
var _this = this;
|
|
var overwrite = promise_1.ensureValue(_callback ? _overwrite : undefined, false);
|
|
var callbackFinal = _callback ? _callback : _overwrite;
|
|
var pathFrom = new Path_1.Path(_pathFrom);
|
|
var callback = function (e, overrided) {
|
|
if (!e)
|
|
_this.emit('rename', ctx, pathFrom, { newName: newName, overrided: overrided });
|
|
callbackFinal(e, overrided);
|
|
};
|
|
this.emit('before-rename', ctx, pathFrom, { newName: newName });
|
|
issuePrivilegeCheck(this, ctx, pathFrom, ['canRead', 'canWrite'], callback, function () {
|
|
_this.isLocked(ctx, pathFrom, function (e, isLocked) {
|
|
if (e || isLocked)
|
|
return callback(e ? e : Errors_1.Errors.Locked);
|
|
if (pathFrom.isRoot()) {
|
|
_this.getFullPath(ctx, function (e, fullPath) {
|
|
if (fullPath.isRoot())
|
|
return callback(Errors_1.Errors.InvalidOperation);
|
|
var newPath = fullPath.getParent().getChildPath(newName);
|
|
issuePrivilegeCheck(_this, ctx, newPath, 'canWrite', callback, function () {
|
|
ctx.server.getFileSystem(newPath, function (fs, _, subPath) {
|
|
var go = function (overwritten) {
|
|
ctx.server.setFileSystem(newPath, _this, function (successed) {
|
|
if (!successed)
|
|
return callback(Errors_1.Errors.InvalidOperation);
|
|
ctx.server.removeFileSystem(fullPath, function () { return callback(null, overwritten); });
|
|
});
|
|
};
|
|
if (!subPath.isRoot()) {
|
|
go(false);
|
|
}
|
|
else if (!overwrite) {
|
|
callback(Errors_1.Errors.ResourceAlreadyExists);
|
|
}
|
|
else {
|
|
ctx.server.removeFileSystem(newPath, function () {
|
|
go(true);
|
|
});
|
|
}
|
|
});
|
|
});
|
|
});
|
|
}
|
|
else {
|
|
_this.fastExistCheckEx(ctx, pathFrom, callback, function () {
|
|
_this.fastExistCheckExReverse(ctx, pathFrom.getParent().getChildPath(newName), callback, function () {
|
|
var newPath = pathFrom.getParent().getChildPath(newName);
|
|
_this.isLocked(ctx, newPath, function (e, isLocked) {
|
|
if (e || isLocked)
|
|
return callback(e ? e : Errors_1.Errors.Locked);
|
|
issuePrivilegeCheck(_this, ctx, newPath, 'canWrite', callback, function () {
|
|
if (_this._rename) {
|
|
_this._rename(pathFrom, newName, {
|
|
context: ctx,
|
|
destinationPath: newPath
|
|
}, callback);
|
|
}
|
|
else {
|
|
_this.move(ctx, pathFrom, pathFrom.getParent().getChildPath(newName), overwrite, callback);
|
|
}
|
|
});
|
|
});
|
|
});
|
|
});
|
|
}
|
|
});
|
|
});
|
|
};
|
|
FileSystem.prototype.mimeTypeAsync = function (ctx, path, targetSource) {
|
|
var _this = this;
|
|
return promise_1.promisifyCall(function (cb) { return _this.mimeType(ctx, path, targetSource, cb); });
|
|
};
|
|
FileSystem.prototype.mimeType = function (ctx, _path, _targetSource, _callback) {
|
|
var _this = this;
|
|
var targetSource = promise_1.ensureValue(_callback ? _targetSource : undefined, true);
|
|
var callback = _callback ? _callback : _targetSource;
|
|
var path = new Path_1.Path(_path);
|
|
issuePrivilegeCheck(this, ctx, path, targetSource ? 'canReadContentSource' : 'canReadContentTranslated', callback, function () {
|
|
_this.fastExistCheckEx(ctx, path, callback, function () {
|
|
if (_this._mimeType) {
|
|
_this._mimeType(path, {
|
|
context: ctx,
|
|
targetSource: targetSource
|
|
}, callback);
|
|
}
|
|
else {
|
|
StandardMethods_1.StandardMethods.standardMimeType(ctx, _this, path, targetSource, callback);
|
|
}
|
|
});
|
|
});
|
|
};
|
|
FileSystem.prototype.sizeAsync = function (ctx, path, targetSource) {
|
|
var _this = this;
|
|
return promise_1.promisifyCall(function (cb) { return _this.size(ctx, path, targetSource, cb); });
|
|
};
|
|
FileSystem.prototype.size = function (ctx, path, _targetSource, _callback) {
|
|
var _this = this;
|
|
var targetSource = promise_1.ensureValue(_callback ? _targetSource : undefined, false);
|
|
var callback = _callback ? _callback : _targetSource;
|
|
var pPath = new Path_1.Path(path);
|
|
issuePrivilegeCheck(this, ctx, pPath, targetSource ? 'canReadContentSource' : 'canReadContentTranslated', callback, function () {
|
|
_this.fastExistCheckEx(ctx, pPath, callback, function () {
|
|
if (!_this._size)
|
|
return callback(null, undefined);
|
|
_this._size(pPath, {
|
|
context: ctx,
|
|
targetSource: targetSource
|
|
}, callback);
|
|
});
|
|
});
|
|
};
|
|
/**
|
|
* Get the list of available lock kinds.
|
|
*
|
|
* @param ctx Context of the operation.
|
|
* @param path Path of the resource.
|
|
*/
|
|
FileSystem.prototype.availableLocksAsync = function (ctx, path) {
|
|
var _this = this;
|
|
return promise_1.promisifyCall(function (cb) { return _this.availableLocks(ctx, path, cb); });
|
|
};
|
|
/**
|
|
* Get the list of available lock kinds.
|
|
*
|
|
* @param ctx Context of the operation.
|
|
* @param path Path of the resource.
|
|
* @param callback Returns the list of available lock kinds.
|
|
*/
|
|
FileSystem.prototype.availableLocks = function (ctx, path, callback) {
|
|
var _this = this;
|
|
var pPath = new Path_1.Path(path);
|
|
issuePrivilegeCheck(this, ctx, pPath, 'canReadLocks', callback, function () {
|
|
_this.fastExistCheckEx(ctx, pPath, callback, function () {
|
|
if (!_this._availableLocks) {
|
|
callback(null, [
|
|
new LockKind_1.LockKind(LockScope_1.LockScope.Exclusive, LockType_1.LockType.Write),
|
|
new LockKind_1.LockKind(LockScope_1.LockScope.Shared, LockType_1.LockType.Write)
|
|
]);
|
|
}
|
|
else {
|
|
_this._availableLocks(pPath, {
|
|
context: ctx
|
|
}, callback);
|
|
}
|
|
});
|
|
});
|
|
};
|
|
/**
|
|
* Get the lock manager of the resource.
|
|
*
|
|
* @param ctx Context of the operation.
|
|
* @param path Path of the resource.
|
|
*/
|
|
FileSystem.prototype.lockManagerAsync = function (ctx, path) {
|
|
var _this = this;
|
|
return promise_1.promisifyCall(function (cb) { return _this.lockManager(ctx, path, cb); });
|
|
};
|
|
/**
|
|
* Get the lock manager of the resource.
|
|
*
|
|
* @param ctx Context of the operation.
|
|
* @param path Path of the resource.
|
|
* @param callback Returns the lock manager of the resource.
|
|
*/
|
|
FileSystem.prototype.lockManager = function (ctx, path, callback) {
|
|
var _this = this;
|
|
var pPath = new Path_1.Path(path);
|
|
this.fastExistCheckEx(ctx, pPath, callback, function () {
|
|
_this._lockManager(pPath, {
|
|
context: ctx
|
|
}, function (e, lm) {
|
|
if (e)
|
|
return callback(e);
|
|
var buffIsLocked = new BufferedIsLocked(_this, ctx, pPath);
|
|
var fs = _this;
|
|
var manager = {
|
|
getLocksAsync: function () {
|
|
return promise_1.promisifyCall(function (cb) { return manager.getLocks(cb); });
|
|
},
|
|
getLocks: function (callback) {
|
|
issuePrivilegeCheck(fs, ctx, pPath, 'canReadLocks', callback, function () {
|
|
lm.getLocks(callback);
|
|
});
|
|
},
|
|
setLockAsync: function (lock) {
|
|
return promise_1.promisifyCall(function (cb) { return manager.setLock(lock, cb); });
|
|
},
|
|
setLock: function (lock, callback) {
|
|
fs.emit('before-lock-set', ctx, pPath, { lock: lock });
|
|
issuePrivilegeCheck(fs, ctx, pPath, 'canWriteLocks', callback, function () {
|
|
buffIsLocked.isLocked(function (e, isLocked) {
|
|
if (e || isLocked)
|
|
return callback(e ? e : Errors_1.Errors.Locked);
|
|
lm.setLock(lock, function (e) {
|
|
if (!e)
|
|
fs.emit('lock-set', ctx, pPath, { lock: lock });
|
|
callback(e);
|
|
});
|
|
});
|
|
});
|
|
},
|
|
removeLockAsync: function (uuid) {
|
|
return promise_1.promisifyCall(function (cb) { return manager.removeLock(uuid, cb); });
|
|
},
|
|
removeLock: function (uuid, callback) {
|
|
fs.emit('before-lock-remove', ctx, pPath, { uuid: uuid });
|
|
issuePrivilegeCheck(fs, ctx, pPath, 'canWriteLocks', callback, function () {
|
|
buffIsLocked.isLocked(function (e, isLocked) {
|
|
if (e || isLocked)
|
|
return callback(e ? e : Errors_1.Errors.Locked);
|
|
lm.removeLock(uuid, function (e, removed) {
|
|
if (!e)
|
|
fs.emit('lock-remove', ctx, pPath, { uuid: uuid, removed: removed });
|
|
callback(e, removed);
|
|
});
|
|
});
|
|
});
|
|
},
|
|
getLockAsync: function (uuid) {
|
|
return promise_1.promisifyCall(function (cb) { return manager.getLock(uuid, cb); });
|
|
},
|
|
getLock: function (uuid, callback) {
|
|
issuePrivilegeCheck(fs, ctx, pPath, 'canReadLocks', callback, function () {
|
|
lm.getLock(uuid, callback);
|
|
});
|
|
},
|
|
refreshAsync: function (uuid, timeoutSeconds) {
|
|
return promise_1.promisifyCall(function (cb) { return manager.refresh(uuid, timeoutSeconds, cb); });
|
|
},
|
|
refresh: function (uuid, timeoutSeconds, callback) {
|
|
fs.emit('before-lock-refresh', ctx, pPath, { uuid: uuid, timeout: timeoutSeconds });
|
|
issuePrivilegeCheck(fs, ctx, pPath, 'canWriteLocks', callback, function () {
|
|
buffIsLocked.isLocked(function (e, isLocked) {
|
|
if (e || isLocked)
|
|
return callback(e ? e : Errors_1.Errors.Locked);
|
|
lm.refresh(uuid, timeoutSeconds, function (e, lock) {
|
|
if (!e)
|
|
fs.emit('lock-refresh', ctx, pPath, { uuid: uuid, timeout: timeoutSeconds, lock: lock });
|
|
callback(e, lock);
|
|
});
|
|
});
|
|
});
|
|
}
|
|
};
|
|
callback(null, manager);
|
|
});
|
|
});
|
|
};
|
|
/**
|
|
* Get the property manager of the resource.
|
|
*
|
|
* @param ctx Context of the operation.
|
|
* @param path Path of the resource.
|
|
*/
|
|
FileSystem.prototype.propertyManagerAsync = function (ctx, path) {
|
|
var _this = this;
|
|
return promise_1.promisifyCall(function (cb) { return _this.propertyManager(ctx, path, cb); });
|
|
};
|
|
/**
|
|
* Get the property manager of the resource.
|
|
*
|
|
* @param ctx Context of the operation.
|
|
* @param path Path of the resource.
|
|
* @param callback Returns the property manager of the resource.
|
|
*/
|
|
FileSystem.prototype.propertyManager = function (ctx, path, callback) {
|
|
var _this = this;
|
|
var pPath = new Path_1.Path(path);
|
|
this.fastExistCheckEx(ctx, pPath, callback, function () {
|
|
_this._propertyManager(pPath, {
|
|
context: ctx
|
|
}, function (e, pm) {
|
|
if (e)
|
|
return callback(e);
|
|
var buffIsLocked = new BufferedIsLocked(_this, ctx, pPath);
|
|
var fs = _this;
|
|
callback(null, {
|
|
setProperty: function (name, value, attributes, callback) {
|
|
fs.emit('before-property-set', ctx, pPath, { name: name, value: value, attributes: attributes });
|
|
issuePrivilegeCheck(fs, ctx, pPath, 'canWriteProperties', callback, function () {
|
|
buffIsLocked.isLocked(function (e, isLocked) {
|
|
if (e || isLocked)
|
|
return callback(e ? e : Errors_1.Errors.Locked);
|
|
pm.setProperty(name, value, attributes, function (e) {
|
|
if (!e)
|
|
fs.emit('property-set', ctx, pPath, { name: name, value: value, attributes: attributes });
|
|
callback(e);
|
|
});
|
|
});
|
|
});
|
|
},
|
|
getProperty: function (name, callback) {
|
|
issuePrivilegeCheck(fs, ctx, pPath, 'canReadProperties', callback, function () {
|
|
pm.getProperty(name, callback);
|
|
});
|
|
},
|
|
removeProperty: function (name, callback) {
|
|
fs.emit('before-property-remove', ctx, pPath, { name: name });
|
|
issuePrivilegeCheck(fs, ctx, pPath, 'canWriteProperties', callback, function () {
|
|
buffIsLocked.isLocked(function (e, isLocked) {
|
|
if (e || isLocked)
|
|
return callback(e ? e : Errors_1.Errors.Locked);
|
|
pm.removeProperty(name, function (e) {
|
|
if (!e)
|
|
fs.emit('property-remove', ctx, pPath, { name: name });
|
|
callback(e);
|
|
});
|
|
});
|
|
});
|
|
},
|
|
getProperties: function (callback, byCopy) {
|
|
var _this = this;
|
|
issuePrivilegeCheck(fs, ctx, pPath, 'canReadProperties', callback, function () {
|
|
pm.getProperties(function (e, bag) {
|
|
if (!bag)
|
|
return callback(e, bag);
|
|
ctx.server.options.storageManager.available(ctx, _this, function (availableSize) {
|
|
if (availableSize === -1)
|
|
return callback(e, bag);
|
|
ctx.server.options.storageManager.reserved(ctx, _this, function (reservedSize) {
|
|
bag['DAV:quota-available-bytes'] = {
|
|
value: availableSize.toString()
|
|
};
|
|
bag['DAV:quota-used-bytes'] = {
|
|
value: reservedSize.toString()
|
|
};
|
|
callback(e, bag);
|
|
});
|
|
});
|
|
}, byCopy);
|
|
});
|
|
}
|
|
});
|
|
});
|
|
});
|
|
};
|
|
FileSystem.prototype.readDirAsync = function (ctx, path, retrieveExternalFiles) {
|
|
var _this = this;
|
|
return promise_1.promisifyCall(function (cb) { return _this.readDir(ctx, path, retrieveExternalFiles, cb); });
|
|
};
|
|
FileSystem.prototype.readDir = function (ctx, path, _retrieveExternalFiles, _callback) {
|
|
var _this = this;
|
|
var retrieveExternalFiles = promise_1.ensureValue(_callback ? _retrieveExternalFiles : undefined, false);
|
|
var __callback = _callback ? _callback : _retrieveExternalFiles;
|
|
var pPath = new Path_1.Path(path);
|
|
var callback = function (e, data) {
|
|
if (e)
|
|
return __callback(e);
|
|
if (!data)
|
|
data = [];
|
|
_this.getFullPath(ctx, function (e, fsFullPath) {
|
|
new Workflow_1.Workflow()
|
|
.each(data, function (path, cb) {
|
|
_this.checkPrivilege(ctx, path, 'canReadProperties', function (e, can) {
|
|
if (e)
|
|
cb(e);
|
|
else
|
|
cb(null, can ? path : null);
|
|
});
|
|
})
|
|
.error(__callback)
|
|
.done(function () { return __callback(null, data.filter(function (p) { return !!p; }).map(function (p) { return p.fileName(); })); });
|
|
});
|
|
};
|
|
issuePrivilegeCheck(this, ctx, pPath, 'canReadProperties', callback, function () {
|
|
_this.fastExistCheckEx(ctx, pPath, callback, function () {
|
|
var next = function (base) {
|
|
if (!_this._readDir)
|
|
return callback(null, base);
|
|
_this._readDir(pPath, {
|
|
context: ctx
|
|
}, function (e, paths) {
|
|
if (e)
|
|
return callback(e);
|
|
if (paths.length === 0)
|
|
return callback(null, base);
|
|
if (paths[0].constructor === String)
|
|
base = base.concat(paths.map(function (s) { return pPath.getChildPath(s); }));
|
|
else
|
|
base = base.concat(paths);
|
|
callback(null, base);
|
|
});
|
|
};
|
|
if (!retrieveExternalFiles)
|
|
return next([]);
|
|
_this.getFullPath(ctx, function (e, thisFullPath) {
|
|
if (e)
|
|
return callback(e);
|
|
ctx.server.getChildFileSystems(thisFullPath.getChildPath(pPath), function (fss) {
|
|
_this.localize(ctx, fss.map(function (f) { return f.path; }), function (e, paths) {
|
|
if (e)
|
|
return callback(e);
|
|
next(paths);
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|
|
};
|
|
FileSystem.neutralizeEmptyDate = function (date, defaultDate) {
|
|
if (!date || isNaN(date)) {
|
|
if (defaultDate === undefined || defaultDate === null)
|
|
defaultDate = 0;
|
|
return defaultDate;
|
|
}
|
|
else {
|
|
return date;
|
|
}
|
|
};
|
|
/**
|
|
* Get the creation date information of a resource.
|
|
* If neither '_creationDate' nor '_lastModifiedDate' are implemented, it returns 0.
|
|
* If '_creationDate' is not implemented, it calls the 'lastModifiedDate' method.
|
|
* Otherwise it calls the '_creationDate' method.
|
|
*
|
|
* @param ctx Context of the operation.
|
|
* @param path Path of the resource.
|
|
*/
|
|
FileSystem.prototype.creationDateAsync = function (ctx, path) {
|
|
var _this = this;
|
|
return promise_1.promisifyCall(function (cb) { return _this.creationDate(ctx, path, cb); });
|
|
};
|
|
/**
|
|
* Get the creation date information of a resource.
|
|
* If neither '_creationDate' nor '_lastModifiedDate' are implemented, it returns 0.
|
|
* If '_creationDate' is not implemented, it calls the 'lastModifiedDate' method.
|
|
* Otherwise it calls the '_creationDate' method.
|
|
*
|
|
* @param ctx Context of the operation.
|
|
* @param path Path of the resource.
|
|
* @param callback Returns the creation date of the resource.
|
|
*/
|
|
FileSystem.prototype.creationDate = function (ctx, path, callback) {
|
|
var _this = this;
|
|
var pPath = new Path_1.Path(path);
|
|
callback = FileSystem.neutralizeEmptyDateCallback(callback);
|
|
issuePrivilegeCheck(this, ctx, pPath, 'canReadProperties', callback, function () {
|
|
_this.fastExistCheckEx(ctx, pPath, callback, function () {
|
|
if (!_this._creationDate && !_this._lastModifiedDate)
|
|
return callback(null, 0);
|
|
if (!_this._creationDate)
|
|
return _this.lastModifiedDate(ctx, pPath, callback);
|
|
_this._creationDate(pPath, {
|
|
context: ctx
|
|
}, callback);
|
|
});
|
|
});
|
|
};
|
|
/**
|
|
* Get the last modified date information of a resource.
|
|
* If neither '_creationDate' nor '_lastModifiedDate' are implemented, it returns 0.
|
|
* If '_lastModifiedDate' is not implemented, it calls the 'creationDate' method.
|
|
* Otherwise it calls the '_lastModifiedDate' method.
|
|
*
|
|
* @param ctx Context of the operation.
|
|
* @param path Path of the resource.
|
|
*/
|
|
FileSystem.prototype.lastModifiedDateAsync = function (ctx, path) {
|
|
var _this = this;
|
|
return promise_1.promisifyCall(function (cb) { return _this.lastModifiedDate(ctx, path, cb); });
|
|
};
|
|
/**
|
|
* Get the last modified date information of a resource.
|
|
* If neither '_creationDate' nor '_lastModifiedDate' are implemented, it returns 0.
|
|
* If '_lastModifiedDate' is not implemented, it calls the 'creationDate' method.
|
|
* Otherwise it calls the '_lastModifiedDate' method.
|
|
*
|
|
* @param ctx Context of the operation.
|
|
* @param path Path of the resource.
|
|
* @param callback Returns the last modified date of the resource.
|
|
*/
|
|
FileSystem.prototype.lastModifiedDate = function (ctx, path, callback) {
|
|
var _this = this;
|
|
var pPath = new Path_1.Path(path);
|
|
callback = FileSystem.neutralizeEmptyDateCallback(callback);
|
|
issuePrivilegeCheck(this, ctx, pPath, 'canReadProperties', callback, function () {
|
|
_this.fastExistCheckEx(ctx, pPath, callback, function () {
|
|
if (!_this._creationDate && !_this._lastModifiedDate)
|
|
return callback(null, 0);
|
|
if (!_this._lastModifiedDate)
|
|
return _this.creationDate(ctx, pPath, callback);
|
|
_this._lastModifiedDate(pPath, {
|
|
context: ctx
|
|
}, callback);
|
|
});
|
|
});
|
|
};
|
|
/**
|
|
* Get the name of the resource.
|
|
*
|
|
* @param ctx Context of the operation.
|
|
* @param path Path of the resource.
|
|
*/
|
|
FileSystem.prototype.webNameAsync = function (ctx, path) {
|
|
var _this = this;
|
|
return promise_1.promisifyCall(function (cb) { return _this.webName(ctx, path, cb); });
|
|
};
|
|
/**
|
|
* Get the name of the resource.
|
|
*
|
|
* @param ctx Context of the operation.
|
|
* @param path Path of the resource.
|
|
* @param callback Returns the name of the resource.
|
|
*/
|
|
FileSystem.prototype.webName = function (ctx, path, callback) {
|
|
var _this = this;
|
|
var pPath = new Path_1.Path(path);
|
|
issuePrivilegeCheck(this, ctx, pPath, 'canReadProperties', callback, function () {
|
|
_this.fastExistCheckEx(ctx, pPath, callback, function () {
|
|
if (pPath.isRoot())
|
|
_this.getFullPath(ctx, function (e, pPath) { return callback(e, e ? null : pPath.fileName()); });
|
|
else
|
|
callback(null, pPath.fileName());
|
|
});
|
|
});
|
|
};
|
|
/**
|
|
* Get the 'displayName' information of the resource.
|
|
* This value is used in the 'DAV:displayName' tag in the PROPFIND response body.
|
|
* Its default behaviour is to return the result of the 'webName' method. This behaviour can be overrided by implementing the '_displayName' method.
|
|
*
|
|
* @param ctx Context of the operation.
|
|
* @param path Path of the resource.
|
|
*/
|
|
FileSystem.prototype.displayNameAsync = function (ctx, path) {
|
|
var _this = this;
|
|
return promise_1.promisifyCall(function (cb) { return _this.displayName(ctx, path, cb); });
|
|
};
|
|
/**
|
|
* Get the 'displayName' information of the resource.
|
|
* This value is used in the 'DAV:displayName' tag in the PROPFIND response body.
|
|
* Its default behaviour is to return the result of the 'webName' method. This behaviour can be overrided by implementing the '_displayName' method.
|
|
*
|
|
* @param ctx Context of the operation.
|
|
* @param path Path of the resource.
|
|
* @param callback Returns the 'displayName' information of the resource.
|
|
*/
|
|
FileSystem.prototype.displayName = function (ctx, path, callback) {
|
|
var _this = this;
|
|
var pPath = new Path_1.Path(path);
|
|
issuePrivilegeCheck(this, ctx, pPath, 'canReadProperties', callback, function () {
|
|
_this.fastExistCheckEx(ctx, pPath, callback, function () {
|
|
if (!_this._displayName)
|
|
return _this.webName(ctx, pPath, callback);
|
|
_this._displayName(pPath, {
|
|
context: ctx
|
|
}, callback);
|
|
});
|
|
});
|
|
};
|
|
/**
|
|
* Get the type of the resource.
|
|
*
|
|
* @param ctx Context of the operation.
|
|
* @param path Path of the resource.
|
|
*/
|
|
FileSystem.prototype.typeAsync = function (ctx, path) {
|
|
var _this = this;
|
|
return promise_1.promisifyCall(function (cb) { return _this.type(ctx, path, cb); });
|
|
};
|
|
/**
|
|
* Get the type of the resource.
|
|
*
|
|
* @param ctx Context of the operation.
|
|
* @param path Path of the resource.
|
|
* @param callback Returns the type of the resource.
|
|
*/
|
|
FileSystem.prototype.type = function (ctx, path, callback) {
|
|
var _this = this;
|
|
var pPath = new Path_1.Path(path);
|
|
issuePrivilegeCheck(this, ctx, pPath, 'canReadProperties', callback, function () {
|
|
_this.fastExistCheckEx(ctx, pPath, callback, function () {
|
|
_this._type(pPath, {
|
|
context: ctx
|
|
}, callback);
|
|
});
|
|
});
|
|
};
|
|
FileSystem.prototype.addSubTreeAsync = function (ctx, rootPath, tree) {
|
|
var _this = this;
|
|
return promise_1.promisifyCall(function (cb) { return _this.addSubTree(ctx, rootPath, tree, cb); });
|
|
};
|
|
FileSystem.prototype.addSubTree = function (ctx, _rootPath, _tree, _callback) {
|
|
var _this = this;
|
|
var _rootPathIsPath = Path_1.Path.isPath(_rootPath);
|
|
var tree = _rootPathIsPath ? _tree : _rootPath;
|
|
var rootPath = _rootPathIsPath ? new Path_1.Path(_rootPath) : new Path_1.Path('/');
|
|
var callback = _callback ? _callback : _tree;
|
|
callback = callback ? callback : function () { };
|
|
if (tree.constructor === CommonTypes_1.ResourceType) {
|
|
this.create(ctx, rootPath, tree, callback);
|
|
}
|
|
else if (tree.constructor === String || tree.constructor === Buffer) {
|
|
var data_1 = tree;
|
|
this.openWriteStream(ctx, rootPath, 'mustCreate', true, data_1.length, function (e, w, created) {
|
|
if (e)
|
|
return callback(e);
|
|
w.end(data_1);
|
|
w.on('error', function (e) {
|
|
callback(e);
|
|
});
|
|
w.on('finish', function () {
|
|
callback();
|
|
});
|
|
});
|
|
}
|
|
else {
|
|
new Workflow_1.Workflow()
|
|
.each(Object.keys(tree), function (name, cb) {
|
|
var value = tree[name];
|
|
var childPath = rootPath.getChildPath(name);
|
|
if (value.constructor === CommonTypes_1.ResourceType || value.constructor === String || value.constructor === Buffer) {
|
|
_this.addSubTree(ctx, childPath, value, cb);
|
|
}
|
|
else {
|
|
_this.addSubTree(ctx, childPath, CommonTypes_1.ResourceType.Directory, function (e) {
|
|
if (e)
|
|
return cb(e);
|
|
_this.addSubTree(ctx, childPath, value, cb);
|
|
});
|
|
}
|
|
})
|
|
.error(callback)
|
|
.done(function (_) { return callback(); });
|
|
}
|
|
};
|
|
FileSystem.prototype.listDeepLocksAsync = function (ctx, startPath, depth) {
|
|
var _this = this;
|
|
return promise_1.promisifyCall(function (cb) { return _this.listDeepLocks(ctx, startPath, depth, cb); });
|
|
};
|
|
FileSystem.prototype.listDeepLocks = function (ctx, startPath, _depth, _callback) {
|
|
var _this = this;
|
|
var depth = promise_1.ensureValue(_callback ? _depth : undefined, 0);
|
|
var callback = _callback ? _callback : _depth;
|
|
var pStartPath = new Path_1.Path(startPath);
|
|
this.lockManager(ctx, pStartPath, function (e, lm) {
|
|
if (e === Errors_1.Errors.ResourceNotFound) {
|
|
lm = {
|
|
getLocks: function (callback) {
|
|
callback(null, []);
|
|
}
|
|
};
|
|
}
|
|
else if (e) {
|
|
return callback(e);
|
|
}
|
|
lm.getLocks(function (e, locks) {
|
|
if (e === Errors_1.Errors.NotEnoughPrivilege) {
|
|
locks = [];
|
|
}
|
|
else if (e) {
|
|
return callback(e);
|
|
}
|
|
if (depth !== -1)
|
|
locks = locks.filter(function (f) { return f.depth === -1 || f.depth >= depth; });
|
|
var go = function (fs, parentPath) {
|
|
var destDepth = depth === -1 ? -1 : depth + 1;
|
|
fs.listDeepLocks(ctx, parentPath, destDepth, function (e, pLocks) {
|
|
if (e)
|
|
return callback(e);
|
|
if (locks && locks.length > 0)
|
|
pLocks[pStartPath.toString()] = locks;
|
|
callback(null, pLocks);
|
|
});
|
|
};
|
|
if (!pStartPath.isRoot()) {
|
|
go(_this, pStartPath.getParent());
|
|
}
|
|
else {
|
|
_this.getFullPath(ctx, function (e, fsPath) {
|
|
if (e)
|
|
return callback(e);
|
|
if (fsPath.isRoot()) {
|
|
var result = {};
|
|
if (locks && locks.length > 0)
|
|
result[pStartPath.toString()] = locks;
|
|
return callback(null, result);
|
|
}
|
|
ctx.server.getFileSystem(fsPath.getParent(), function (fs, _, subPath) {
|
|
go(fs, subPath);
|
|
});
|
|
});
|
|
}
|
|
});
|
|
});
|
|
};
|
|
FileSystem.prototype.getFullPathAsync = function (ctx, path) {
|
|
var _this = this;
|
|
return promise_1.promisifyCall(function (cb) { return _this.getFullPath(ctx, path, cb); });
|
|
};
|
|
FileSystem.prototype.getFullPath = function (ctx, _path, _callback) {
|
|
var path = !_path || typeof _path === 'function' ? undefined : new Path_1.Path(_path);
|
|
var callback = _callback ? _callback : _path;
|
|
ctx.server.getFileSystemPath(this, function (fsPath) {
|
|
callback(null, path ? fsPath.getChildPath(path) : fsPath);
|
|
});
|
|
};
|
|
FileSystem.prototype.localizeAsync = function (ctx, fullPath) {
|
|
var _this = this;
|
|
return promise_1.promisifyCall(function (cb) { return _this.localize(ctx, fullPath, cb); });
|
|
};
|
|
FileSystem.prototype.localize = function (ctx, fullPath, callback) {
|
|
this.getFullPath(ctx, function (e, fsFullPath) {
|
|
if (e)
|
|
return callback(e);
|
|
var paths = fullPath.constructor === Array ? fullPath : [fullPath];
|
|
callback(null, paths
|
|
.map(function (p) { return new Path_1.Path(p); })
|
|
.map(function (p) {
|
|
fsFullPath.paths.forEach(function () { return p.removeRoot(); });
|
|
return p;
|
|
}));
|
|
});
|
|
};
|
|
FileSystem.prototype.checkPrivilegeAsync = function (ctx, path, privileges) {
|
|
var _this = this;
|
|
return promise_1.promisifyCall(function (cb) { return _this.checkPrivilege(ctx, path, privileges, cb); });
|
|
};
|
|
FileSystem.prototype.checkPrivilege = function (ctx, path, privileges, callback) {
|
|
var _this = this;
|
|
if (privileges.constructor === String)
|
|
privileges = [privileges];
|
|
this.getFullPath(ctx, path, function (e, fullPath) {
|
|
_this.privilegeManager(ctx, path, function (e, privilegeManager) {
|
|
if (e)
|
|
return callback(e);
|
|
var resource = _this.resource(ctx, new Path_1.Path(path));
|
|
privilegeManager.can(fullPath, resource, privileges, callback);
|
|
});
|
|
});
|
|
};
|
|
/**
|
|
* Get the privilege manager to use to authorize actions for a user.
|
|
* By default, it returns the value in the server options, but it can be overrided by implementing the '_privilegeManager' method.
|
|
*
|
|
* @param ctx Context of the operation.
|
|
* @param path Path of the resource.
|
|
*/
|
|
FileSystem.prototype.privilegeManagerAsync = function (ctx, path) {
|
|
var _this = this;
|
|
return promise_1.promisifyCall(function (cb) { return _this.privilegeManager(ctx, path, cb); });
|
|
};
|
|
/**
|
|
* Get the privilege manager to use to authorize actions for a user.
|
|
* By default, it returns the value in the server options, but it can be overrided by implementing the '_privilegeManager' method.
|
|
*
|
|
* @param ctx Context of the operation.
|
|
* @param path Path of the resource.
|
|
* @param callback Returns the privilege manager representing the requested resource.
|
|
*/
|
|
FileSystem.prototype.privilegeManager = function (ctx, path, callback) {
|
|
if (!this._privilegeManager)
|
|
return callback(null, ctx.server.options.privilegeManager);
|
|
this._privilegeManager(new Path_1.Path(path), {
|
|
context: ctx
|
|
}, callback);
|
|
};
|
|
FileSystem.prototype.isLockedAsync = function (ctx, path, depth) {
|
|
var _this = this;
|
|
return promise_1.promisifyCall(function (cb) { return _this.isLockedAsync(ctx, path, depth); });
|
|
};
|
|
FileSystem.prototype.isLocked = function (ctx, path, _depth, _callback) {
|
|
var _this = this;
|
|
var callback = _callback ? _callback : _depth;
|
|
var depth = typeof _depth === 'number' ? _depth : 0;
|
|
if (ctx.user && ctx.user.isAdministrator)
|
|
return callback(null, false);
|
|
var pPath = new Path_1.Path(path);
|
|
var checkThis = function () {
|
|
_this._lockManager(pPath, { context: ctx }, function (e, lm) {
|
|
if (e === Errors_1.Errors.ResourceNotFound)
|
|
return callback(null, false);
|
|
if (e)
|
|
return callback(e);
|
|
lm.getLocks(function (e, locks) {
|
|
if (e === Errors_1.Errors.ResourceNotFound)
|
|
return callback(null, false);
|
|
if (e)
|
|
return callback(e);
|
|
locks = locks.filter(function (l) { return l.depth === -1 || l.depth >= depth; });
|
|
if (!ctx.user)
|
|
return callback(null, locks.length > 0);
|
|
if (locks.some(function (l) { return ctx.user.uid !== l.userUid && l.lockKind.scope.isSame(LockScope_1.LockScope.Exclusive); }))
|
|
return callback(null, true);
|
|
var isShared = false;
|
|
for (var _i = 0, locks_1 = locks; _i < locks_1.length; _i++) {
|
|
var lock = locks_1[_i];
|
|
if (lock.lockKind.scope.isSame(LockScope_1.LockScope.Shared)) {
|
|
isShared = true;
|
|
if (lock.userUid === ctx.user.uid)
|
|
return callback(null, false);
|
|
}
|
|
}
|
|
callback(null, isShared);
|
|
});
|
|
});
|
|
};
|
|
this.getFullPath(ctx, pPath, function (e, fullPath) {
|
|
if (fullPath.isRoot())
|
|
return checkThis();
|
|
ctx.server.getFileSystem(pPath.getParent(), function (fs, rootPath, subPath) {
|
|
fs.isLocked(ctx, subPath, depth + 1, function (e, locked) {
|
|
if (e || locked)
|
|
return callback(e, locked);
|
|
checkThis();
|
|
});
|
|
});
|
|
});
|
|
};
|
|
/**
|
|
* Serialize the file system based on the 'this.serializer()' value.
|
|
*/
|
|
FileSystem.prototype.serializeAsync = function () {
|
|
var _this = this;
|
|
return promise_1.promisifyCall(function (cb) { return _this.serialize(cb); });
|
|
};
|
|
/**
|
|
* Serialize the file system based on the 'this.serializer()' value.
|
|
*
|
|
* @param callback Returns the serialized data or an error.
|
|
*/
|
|
FileSystem.prototype.serialize = function (callback) {
|
|
var serializer = this.serializer();
|
|
if (!serializer)
|
|
return callback();
|
|
serializer.serialize(this, callback);
|
|
};
|
|
FileSystem.prototype.on = function (ctx, event, listener) {
|
|
var _this = this;
|
|
var server = ctx.events ? ctx : ctx.server;
|
|
server.on(event, function (ctx, fs, path) {
|
|
if (fs === _this)
|
|
listener(ctx, path);
|
|
});
|
|
return this;
|
|
};
|
|
/**
|
|
* Trigger an event.
|
|
*
|
|
* @param event Name of the event.
|
|
* @param ctx Context of the event.
|
|
* @param path Path of the resource on which the event happened.
|
|
*/
|
|
FileSystem.prototype.emit = function (event, ctx, path, data) {
|
|
ctx.server.emit(event, ctx, this, path, data);
|
|
};
|
|
FileSystem.neutralizeEmptyDateCallback = function (callback) {
|
|
return function (e, date) {
|
|
callback(e, FileSystem.neutralizeEmptyDate(date));
|
|
};
|
|
};
|
|
return FileSystem;
|
|
}());
|
|
exports.FileSystem = FileSystem;
|
|
function issuePrivilegeCheck(fs, ctx, path, privilege, badCallback, goodCallback) {
|
|
fs.checkPrivilege(ctx, path, privilege, function (e, can) {
|
|
if (e)
|
|
badCallback(e);
|
|
else if (!can)
|
|
badCallback(Errors_1.Errors.NotEnoughPrivilege);
|
|
else
|
|
goodCallback();
|
|
});
|
|
}
|