From b88370a854ed8dd6c72588f92cece697380bca44 Mon Sep 17 00:00:00 2001 From: Adrien Castex Date: Tue, 30 May 2017 21:14:28 +0200 Subject: [PATCH] Implemented 'stream.Readable' and 'stream.Writable' for the 'write' and 'read' methods of resources instead of using a 'Int8Array' --- lib/resource/IResource.d.ts | 7 +- lib/resource/physical/PhysicalFile.d.ts | 7 +- lib/resource/physical/PhysicalFile.js | 31 +++--- lib/resource/physical/PhysicalFolder.d.ts | 7 +- lib/resource/physical/PhysicalFolder.js | 13 +-- lib/resource/physical/PhysicalResource.d.ts | 7 +- lib/resource/std/RootResource.d.ts | 7 +- lib/resource/std/RootResource.js | 7 +- lib/resource/std/StandardResource.d.ts | 7 +- lib/resource/virtual/VirtualFile.d.ts | 14 ++- lib/resource/virtual/VirtualFile.js | 39 +++++--- lib/resource/virtual/VirtualFolder.d.ts | 7 +- lib/resource/virtual/VirtualFolder.js | 13 +-- lib/resource/virtual/VirtualResource.d.ts | 7 +- lib/server/commands/Commands.d.ts | 18 ++++ lib/server/commands/Copy.js | 21 +--- lib/server/commands/Get.js | 28 ++---- lib/server/commands/Put.js | 101 ++++++-------------- src/resource/IResource.ts | 7 +- src/resource/physical/PhysicalFile.ts | 36 ++++--- src/resource/physical/PhysicalFolder.ts | 18 ++-- src/resource/physical/PhysicalResource.ts | 7 +- src/resource/std/RootResource.ts | 12 +-- src/resource/std/StandardResource.ts | 7 +- src/resource/virtual/VirtualFile.ts | 43 +++++---- src/resource/virtual/VirtualFolder.ts | 18 ++-- src/resource/virtual/VirtualResource.ts | 7 +- src/server/commands/Commands.ts | 1 + src/server/commands/Copy.ts | 23 +---- src/server/commands/Get.ts | 32 ++----- src/server/commands/Put.ts | 48 +++++++--- 31 files changed, 270 insertions(+), 330 deletions(-) create mode 100644 lib/server/commands/Commands.d.ts diff --git a/lib/resource/IResource.d.ts b/lib/resource/IResource.d.ts index 0dded50a..2245584f 100644 --- a/lib/resource/IResource.d.ts +++ b/lib/resource/IResource.d.ts @@ -1,5 +1,5 @@ /// -import { Readable } from 'stream'; +import { Readable, Writable } from 'stream'; import { FSManager } from '../manager/FSManager'; import { XMLElement } from '../helper/XML'; import { LockKind } from './lock/LockKind'; @@ -29,9 +29,8 @@ export interface IResource { rename(newName: string, callback: Return2Callback): any; isSame(resource: IResource, callback: ReturnCallback): any; isOnTheSameFSWith(resource: IResource, callback: ReturnCallback): any; - append(data: Int8Array, targetSource: boolean, callback: SimpleCallback): any; - write(data: Int8Array, targetSource: boolean, callback: SimpleCallback): any; - read(targetSource: boolean, callback: ReturnCallback): any; + write(targetSource: boolean, callback: ReturnCallback): any; + read(targetSource: boolean, callback: ReturnCallback): any; mimeType(targetSource: boolean, callback: ReturnCallback): any; size(targetSource: boolean, callback: ReturnCallback): any; getLocks(callback: ReturnCallback): any; diff --git a/lib/resource/physical/PhysicalFile.d.ts b/lib/resource/physical/PhysicalFile.d.ts index aa9999d3..da955a4f 100644 --- a/lib/resource/physical/PhysicalFile.d.ts +++ b/lib/resource/physical/PhysicalFile.d.ts @@ -1,6 +1,6 @@ /// import { IResource, SimpleCallback, ReturnCallback, ResourceType } from '../IResource'; -import { Readable } from 'stream'; +import { Readable, Writable } from 'stream'; import { PhysicalResource } from './PhysicalResource'; import { FSManager } from '../../manager/FSManager'; export declare class PhysicalFile extends PhysicalResource { @@ -8,9 +8,8 @@ export declare class PhysicalFile extends PhysicalResource { type(callback: ReturnCallback): void; create(callback: SimpleCallback): void; delete(callback: SimpleCallback): void; - append(data: Int8Array, targetSource: boolean, callback: SimpleCallback): void; - write(data: Int8Array, targetSource: boolean, callback: SimpleCallback): void; - read(targetSource: boolean, callback: ReturnCallback): void; + write(targetSource: boolean, callback: ReturnCallback): void; + read(targetSource: boolean, callback: ReturnCallback): void; mimeType(targetSource: boolean, callback: ReturnCallback): void; size(targetSource: boolean, callback: ReturnCallback): void; addChild(resource: IResource, callback: SimpleCallback): void; diff --git a/lib/resource/physical/PhysicalFile.js b/lib/resource/physical/PhysicalFile.js index 79f1c74c..f94e6075 100644 --- a/lib/resource/physical/PhysicalFile.js +++ b/lib/resource/physical/PhysicalFile.js @@ -47,31 +47,28 @@ var PhysicalFile = (function (_super) { _this.removeFromParent(callback); }); }; - PhysicalFile.prototype.append = function (data, targetSource, callback) { + PhysicalFile.prototype.write = function (targetSource, callback) { var _this = this; - fs.appendFile(this.realPath, data, function (e) { - if (e) - callback(e); - else { - _this.updateLastModified(); - callback(null); + fs.open(this.realPath, 'w', function (e, fd) { + if (e) { + callback(e, null); + return; } + callback(null, fs.createWriteStream(null, { fd: fd })); + _this.updateLastModified(); }); }; - PhysicalFile.prototype.write = function (data, targetSource, callback) { + PhysicalFile.prototype.read = function (targetSource, callback) { var _this = this; - fs.writeFile(this.realPath, data, function (e) { - if (e) - callback(e); - else { - _this.updateLastModified(); - callback(null); + fs.open(this.realPath, 'r', function (e, fd) { + if (e) { + callback(e, null); + return; } + callback(null, fs.createReadStream(null, { fd: fd })); + _this.updateLastModified(); }); }; - PhysicalFile.prototype.read = function (targetSource, callback) { - fs.readFile(this.realPath, callback); - }; PhysicalFile.prototype.mimeType = function (targetSource, callback) { var mt = mimeTypes.lookup(this.realPath); callback(null, mt ? mt : 'application/octet-stream'); diff --git a/lib/resource/physical/PhysicalFolder.d.ts b/lib/resource/physical/PhysicalFolder.d.ts index cbb472a0..e48b46da 100644 --- a/lib/resource/physical/PhysicalFolder.d.ts +++ b/lib/resource/physical/PhysicalFolder.d.ts @@ -1,6 +1,6 @@ /// import { IResource, SimpleCallback, ReturnCallback, ResourceType } from '../IResource'; -import { Readable } from 'stream'; +import { Readable, Writable } from 'stream'; import { ResourceChildren } from '../std/ResourceChildren'; import { PhysicalResource } from './PhysicalResource'; import { FSManager } from '../../manager/FSManager'; @@ -10,9 +10,8 @@ export declare class PhysicalFolder extends PhysicalResource { type(callback: ReturnCallback): void; create(callback: SimpleCallback): void; delete(callback: SimpleCallback): void; - append(data: Int8Array, targetSource: boolean, callback: SimpleCallback): void; - write(data: Int8Array, targetSource: boolean, callback: SimpleCallback): void; - read(targetSource: boolean, callback: ReturnCallback): void; + write(targetSource: boolean, callback: ReturnCallback): void; + read(targetSource: boolean, callback: ReturnCallback): void; mimeType(targetSource: boolean, callback: ReturnCallback): void; size(targetSource: boolean, callback: ReturnCallback): void; addChild(resource: IResource, callback: SimpleCallback): void; diff --git a/lib/resource/physical/PhysicalFolder.js b/lib/resource/physical/PhysicalFolder.js index 939e25f5..b981516d 100644 --- a/lib/resource/physical/PhysicalFolder.js +++ b/lib/resource/physical/PhysicalFolder.js @@ -69,11 +69,8 @@ var PhysicalFolder = (function (_super) { }); }); }; - PhysicalFolder.prototype.append = function (data, targetSource, callback) { - callback(Errors_1.Errors.InvalidOperation); - }; - PhysicalFolder.prototype.write = function (data, targetSource, callback) { - callback(Errors_1.Errors.InvalidOperation); + PhysicalFolder.prototype.write = function (targetSource, callback) { + callback(Errors_1.Errors.InvalidOperation, null); }; PhysicalFolder.prototype.read = function (targetSource, callback) { callback(Errors_1.Errors.InvalidOperation, null); @@ -93,7 +90,11 @@ var PhysicalFolder = (function (_super) { }); }; PhysicalFolder.prototype.removeChild = function (resource, callback) { - this.children.remove(resource, callback); + this.children.remove(resource, function (e) { + if (!e) + resource.parent = null; + callback(e); + }); }; PhysicalFolder.prototype.getChildren = function (callback) { callback(null, this.children.children); diff --git a/lib/resource/physical/PhysicalResource.d.ts b/lib/resource/physical/PhysicalResource.d.ts index e2354519..7a47b4d0 100644 --- a/lib/resource/physical/PhysicalResource.d.ts +++ b/lib/resource/physical/PhysicalResource.d.ts @@ -1,6 +1,6 @@ /// import { IResource, SimpleCallback, ReturnCallback, Return2Callback, ResourceType } from '../IResource'; -import { Readable } from 'stream'; +import { Readable, Writable } from 'stream'; import { StandardResource } from '../std/StandardResource'; import { FSManager } from '../../manager/FSManager'; export declare abstract class PhysicalResource extends StandardResource { @@ -13,9 +13,8 @@ export declare abstract class PhysicalResource extends StandardResource { rename(newName: string, callback: Return2Callback): void; webName(callback: ReturnCallback): void; abstract type(callback: ReturnCallback): any; - abstract append(data: Int8Array, targetSource: boolean, callback: SimpleCallback): any; - abstract write(data: Int8Array, targetSource: boolean, callback: SimpleCallback): any; - abstract read(targetSource: boolean, callback: ReturnCallback): any; + abstract write(targetSource: boolean, callback: ReturnCallback): any; + abstract read(targetSource: boolean, callback: ReturnCallback): any; abstract mimeType(targetSource: boolean, callback: ReturnCallback): any; abstract size(targetSource: boolean, callback: ReturnCallback): any; abstract addChild(resource: IResource, callback: SimpleCallback): any; diff --git a/lib/resource/std/RootResource.d.ts b/lib/resource/std/RootResource.d.ts index 43292e71..7eb0fbf1 100644 --- a/lib/resource/std/RootResource.d.ts +++ b/lib/resource/std/RootResource.d.ts @@ -1,6 +1,6 @@ /// import { IResource, SimpleCallback, ReturnCallback, Return2Callback, ResourceType } from '../IResource'; -import { Readable } from 'stream'; +import { Readable, Writable } from 'stream'; import { StandardResource } from './StandardResource'; import { ResourceChildren } from './ResourceChildren'; export declare class RootResource extends StandardResource { @@ -12,9 +12,8 @@ export declare class RootResource extends StandardResource { rename(newName: string, callback: Return2Callback): void; webName(callback: ReturnCallback): void; type(callback: ReturnCallback): void; - append(data: Int8Array, targetSource: boolean, callback: SimpleCallback): void; - write(data: Int8Array, targetSource: boolean, callback: SimpleCallback): void; - read(targetSource: boolean, callback: ReturnCallback): void; + write(targetSource: boolean, callback: ReturnCallback): void; + read(targetSource: boolean, callback: ReturnCallback): void; mimeType(targetSource: boolean, callback: ReturnCallback): void; size(targetSource: boolean, callback: ReturnCallback): void; addChild(resource: IResource, callback: SimpleCallback): void; diff --git a/lib/resource/std/RootResource.js b/lib/resource/std/RootResource.js index 95c8a5db..fd219527 100644 --- a/lib/resource/std/RootResource.js +++ b/lib/resource/std/RootResource.js @@ -40,11 +40,8 @@ var RootResource = (function (_super) { RootResource.prototype.type = function (callback) { callback(null, IResource_1.ResourceType.Directory); }; - RootResource.prototype.append = function (data, targetSource, callback) { - callback(Errors_1.Errors.InvalidOperation); - }; - RootResource.prototype.write = function (data, targetSource, callback) { - callback(Errors_1.Errors.InvalidOperation); + RootResource.prototype.write = function (targetSource, callback) { + callback(Errors_1.Errors.InvalidOperation, null); }; RootResource.prototype.read = function (targetSource, callback) { callback(Errors_1.Errors.InvalidOperation, null); diff --git a/lib/resource/std/StandardResource.d.ts b/lib/resource/std/StandardResource.d.ts index 2f66b761..df3de1cc 100644 --- a/lib/resource/std/StandardResource.d.ts +++ b/lib/resource/std/StandardResource.d.ts @@ -1,6 +1,6 @@ /// import { IResource, ReturnCallback, SimpleCallback, Return2Callback, ResourceType, ResourcePropertyValue } from '../IResource'; -import { Readable } from 'stream'; +import { Readable, Writable } from 'stream'; import { FSManager } from '../../manager/FSManager'; import { LockKind } from '../lock/LockKind'; import { LockBag } from '../lock/LockBag'; @@ -31,9 +31,8 @@ export declare abstract class StandardResource implements IResource { abstract delete(callback: SimpleCallback): any; abstract moveTo(parent: IResource, newName: string, overwrite: boolean, callback: SimpleCallback): any; abstract rename(newName: string, callback: Return2Callback): any; - abstract append(data: Int8Array, targetSource: boolean, callback: SimpleCallback): any; - abstract write(data: Int8Array, targetSource: boolean, callback: SimpleCallback): any; - abstract read(targetSource: boolean, callback: ReturnCallback): any; + abstract write(targetSource: boolean, callback: ReturnCallback): any; + abstract read(targetSource: boolean, callback: ReturnCallback): any; abstract mimeType(targetSource: boolean, callback: ReturnCallback): any; abstract size(targetSource: boolean, callback: ReturnCallback): any; creationDate(callback: ReturnCallback): void; diff --git a/lib/resource/virtual/VirtualFile.d.ts b/lib/resource/virtual/VirtualFile.d.ts index a79ce21a..ee95a8ac 100644 --- a/lib/resource/virtual/VirtualFile.d.ts +++ b/lib/resource/virtual/VirtualFile.d.ts @@ -1,22 +1,26 @@ /// import { IResource, SimpleCallback, ReturnCallback, ResourceType } from '../IResource'; -import { Readable, ReadableOptions } from 'stream'; +import { Readable, Writable } from 'stream'; import { VirtualResource } from './VirtualResource'; import { FSManager } from '../../manager/FSManager'; export declare class VirtualFileReadable extends Readable { contents: Int8Array[]; blockIndex: number; - constructor(contents: Int8Array[], options?: ReadableOptions); + constructor(contents: Int8Array[]); _read(size: number): void; } +export declare class VirtualFileWritable extends Writable { + contents: Int8Array[]; + constructor(contents: Int8Array[]); + _write(chunk: Buffer | string | any, encoding: string, callback: (error: Error) => void): void; +} export declare class VirtualFile extends VirtualResource { content: Int8Array[]; len: number; constructor(name: string, parent?: IResource, fsManager?: FSManager); type(callback: ReturnCallback): void; - append(data: Int8Array, targetSource: boolean, callback: SimpleCallback): void; - write(data: Int8Array, targetSource: boolean, callback: SimpleCallback): void; - read(targetSource: boolean, callback: ReturnCallback): void; + write(targetSource: boolean, callback: ReturnCallback): void; + read(targetSource: boolean, callback: ReturnCallback): void; mimeType(targetSource: boolean, callback: ReturnCallback): void; size(targetSource: boolean, callback: ReturnCallback): void; addChild(resource: IResource, callback: SimpleCallback): void; diff --git a/lib/resource/virtual/VirtualFile.js b/lib/resource/virtual/VirtualFile.js index e96f53b0..679fb7eb 100644 --- a/lib/resource/virtual/VirtualFile.js +++ b/lib/resource/virtual/VirtualFile.js @@ -17,8 +17,8 @@ var Errors_1 = require("../../Errors"); var mimeTypes = require("mime-types"); var VirtualFileReadable = (function (_super) { __extends(VirtualFileReadable, _super); - function VirtualFileReadable(contents, options) { - var _this = _super.call(this, options) || this; + function VirtualFileReadable(contents) { + var _this = _super.call(this) || this; _this.contents = contents; _this.blockIndex = -1; return _this; @@ -37,6 +37,20 @@ var VirtualFileReadable = (function (_super) { return VirtualFileReadable; }(stream_1.Readable)); exports.VirtualFileReadable = VirtualFileReadable; +var VirtualFileWritable = (function (_super) { + __extends(VirtualFileWritable, _super); + function VirtualFileWritable(contents) { + var _this = _super.call(this, null) || this; + _this.contents = contents; + return _this; + } + VirtualFileWritable.prototype._write = function (chunk, encoding, callback) { + this.contents.push(chunk); + callback(null); + }; + return VirtualFileWritable; +}(stream_1.Writable)); +exports.VirtualFileWritable = VirtualFileWritable; var VirtualFile = (function (_super) { __extends(VirtualFile, _super); function VirtualFile(name, parent, fsManager) { @@ -48,17 +62,16 @@ var VirtualFile = (function (_super) { VirtualFile.prototype.type = function (callback) { callback(null, IResource_1.ResourceType.File); }; - VirtualFile.prototype.append = function (data, targetSource, callback) { - this.content.push(data); - this.len += data.length; - this.updateLastModified(); - callback(null); - }; - VirtualFile.prototype.write = function (data, targetSource, callback) { - this.content = [data]; - this.len = data.length; - this.updateLastModified(); - callback(null); + VirtualFile.prototype.write = function (targetSource, callback) { + var _this = this; + var content = []; + var stream = new VirtualFileWritable(content); + stream.on('finish', function () { + _this.content = content; + _this.len = content.map(function (c) { return c.length; }).reduce(function (s, n) { return s + n; }, 0); + _this.updateLastModified(); + }); + callback(null, stream); }; VirtualFile.prototype.read = function (targetSource, callback) { callback(null, new VirtualFileReadable(this.content)); diff --git a/lib/resource/virtual/VirtualFolder.d.ts b/lib/resource/virtual/VirtualFolder.d.ts index eac681be..0363375e 100644 --- a/lib/resource/virtual/VirtualFolder.d.ts +++ b/lib/resource/virtual/VirtualFolder.d.ts @@ -1,6 +1,6 @@ /// import { IResource, SimpleCallback, ReturnCallback, ResourceType } from '../IResource'; -import { Readable } from 'stream'; +import { Readable, Writable } from 'stream'; import { ResourceChildren } from '../std/ResourceChildren'; import { VirtualResource } from './VirtualResource'; import { FSManager } from '../../manager/FSManager'; @@ -8,9 +8,8 @@ export declare class VirtualFolder extends VirtualResource { children: ResourceChildren; constructor(name: string, parent?: IResource, fsManager?: FSManager); type(callback: ReturnCallback): void; - append(data: Int8Array, targetSource: boolean, callback: SimpleCallback): void; - write(data: Int8Array, targetSource: boolean, callback: SimpleCallback): void; - read(targetSource: boolean, callback: ReturnCallback): void; + write(targetSource: boolean, callback: ReturnCallback): void; + read(targetSource: boolean, callback: ReturnCallback): void; mimeType(targetSource: boolean, callback: ReturnCallback): void; size(targetSource: boolean, callback: ReturnCallback): void; addChild(resource: IResource, callback: SimpleCallback): void; diff --git a/lib/resource/virtual/VirtualFolder.js b/lib/resource/virtual/VirtualFolder.js index eeef9348..ce8b7b72 100644 --- a/lib/resource/virtual/VirtualFolder.js +++ b/lib/resource/virtual/VirtualFolder.js @@ -25,11 +25,8 @@ var VirtualFolder = (function (_super) { VirtualFolder.prototype.type = function (callback) { callback(null, IResource_1.ResourceType.Directory); }; - VirtualFolder.prototype.append = function (data, targetSource, callback) { - callback(Errors_1.Errors.InvalidOperation); - }; - VirtualFolder.prototype.write = function (data, targetSource, callback) { - callback(Errors_1.Errors.InvalidOperation); + VirtualFolder.prototype.write = function (targetSource, callback) { + callback(Errors_1.Errors.InvalidOperation, null); }; VirtualFolder.prototype.read = function (targetSource, callback) { callback(Errors_1.Errors.InvalidOperation, null); @@ -49,7 +46,11 @@ var VirtualFolder = (function (_super) { }); }; VirtualFolder.prototype.removeChild = function (resource, callback) { - this.children.remove(resource, callback); + this.children.remove(resource, function (e) { + if (!e) + resource.parent = null; + callback(e); + }); }; VirtualFolder.prototype.getChildren = function (callback) { callback(null, this.children.children); diff --git a/lib/resource/virtual/VirtualResource.d.ts b/lib/resource/virtual/VirtualResource.d.ts index 413c07d2..2e8a1977 100644 --- a/lib/resource/virtual/VirtualResource.d.ts +++ b/lib/resource/virtual/VirtualResource.d.ts @@ -1,6 +1,6 @@ /// import { IResource, SimpleCallback, ReturnCallback, Return2Callback, ResourceType } from '../IResource'; -import { Readable } from 'stream'; +import { Readable, Writable } from 'stream'; import { FSManager } from '../../manager/FSManager'; import { StandardResource } from '../std/StandardResource'; export declare abstract class VirtualResource extends StandardResource { @@ -12,9 +12,8 @@ export declare abstract class VirtualResource extends StandardResource { rename(newName: string, callback: Return2Callback): void; webName(callback: ReturnCallback): void; abstract type(callback: ReturnCallback): any; - abstract append(data: Int8Array, targetSource: boolean, callback: SimpleCallback): any; - abstract write(data: Int8Array, targetSource: boolean, callback: SimpleCallback): any; - abstract read(targetSource: boolean, callback: ReturnCallback): any; + abstract write(targetSource: boolean, callback: ReturnCallback): any; + abstract read(targetSource: boolean, callback: ReturnCallback): any; abstract mimeType(targetSource: boolean, callback: ReturnCallback): any; abstract size(targetSource: boolean, callback: ReturnCallback): any; abstract addChild(resource: IResource, callback: SimpleCallback): any; diff --git a/lib/server/commands/Commands.d.ts b/lib/server/commands/Commands.d.ts new file mode 100644 index 00000000..02b01f6b --- /dev/null +++ b/lib/server/commands/Commands.d.ts @@ -0,0 +1,18 @@ +import { MethodCallArgs } from '../MethodCallArgs'; +declare const _default: { + NotImplemented: (arg: MethodCallArgs, callback: any) => void; + Proppatch: (arg: MethodCallArgs, callback: any) => void; + Propfind: (arg: MethodCallArgs, callback: any) => void; + Options: (arg: MethodCallArgs, callback: any) => void; + Delete: (arg: MethodCallArgs, callback: any) => void; + Unlock: (arg: MethodCallArgs, callback: any) => void; + Mkcol: (arg: MethodCallArgs, callback: any) => void; + Copy: (arg: MethodCallArgs, callback: any) => void; + Lock: (arg: MethodCallArgs, callback: any) => void; + Move: (arg: MethodCallArgs, callback: any) => void; + Head: (arg: MethodCallArgs, callback: any) => void; + Post: (arg: MethodCallArgs, callback: any) => void; + Put: (arg: MethodCallArgs, callback: any) => void; + Get: (arg: MethodCallArgs, callback: any) => void; +}; +export default _default; diff --git a/lib/server/commands/Copy.js b/lib/server/commands/Copy.js index 1212a0eb..d89ed4c5 100644 --- a/lib/server/commands/Copy.js +++ b/lib/server/commands/Copy.js @@ -51,22 +51,11 @@ function copy(arg, source, rDest, destination, callback) { next(); return; } - source.read(true, function (e, data) { return _(e, function () { - if (data.readable) { - var rdata = data; - var isFirst_1 = true; - rdata.on('data', function (chunk) { - if (isFirst_1) { - isFirst_1 = false; - dest.write(new Int8Array(0), true, function (e) { return _(e, function () { }); }); - } - else - dest.append(chunk, true, function (e) { return _(e, next); }); - }); - rdata.on('end', next); - } - else - dest.write(data, true, function (e) { return _(e, next); }); + source.read(true, function (e, rstream) { return _(e, function () { + dest.write(true, function (e, wstream) { return _(e, function () { + rstream.on('end', next); + rstream.pipe(wstream); + }); }); }); }); function next() { if (!type.isDirectory) { diff --git a/lib/server/commands/Get.js b/lib/server/commands/Get.js index 81040423..23c00e45 100644 --- a/lib/server/commands/Get.js +++ b/lib/server/commands/Get.js @@ -11,32 +11,16 @@ function default_1(arg, callback) { 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, c) { return process.nextTick(function () { - if (e) + 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); - if (c.readable) { - var rdata = c; - var isFirst = true; - rdata.on('end', callback); - rdata.pipe(arg.response); - return; - } - else { - var content = c; - if (c === undefined || c === null) - content = new Buffer(0); - else if (c.constructor === Boolean || c.constructor === Number) - content = c.toString(); - else if (c.constructor === Int8Array) - content = new Buffer(c); - else - content = c; - arg.response.write(content); - } + rstream.on('end', callback); + rstream.pipe(arg.response); } - callback(); }); }); }); }); diff --git a/lib/server/commands/Put.js b/lib/server/commands/Put.js index 8254b715..e1ff4660 100644 --- a/lib/server/commands/Put.js +++ b/lib/server/commands/Put.js @@ -50,7 +50,9 @@ function unchunkedMethod(arg, callback) { if (arg.contentLength === 0) { if (r) { arg.requirePrivilege(targetSource ? ['canSource', 'canWrite'] : ['canWrite'], r, function () { - r.write(new Buffer(0), targetSource, function (e) { return process.nextTick(function () { + r.write(targetSource, function (e, stream) { return process.nextTick(function () { + if (stream) + stream.end(); if (e) arg.setCode(WebDAVRequest_1.HTTPCodes.InternalServerError); else @@ -66,15 +68,21 @@ function unchunkedMethod(arg, callback) { }); } else { - var data_1 = new Buffer(arg.data); if (e) { createResource(arg, callback, function (r) { - r.write(data_1, targetSource, function (e) { return process.nextTick(function () { - if (e) + r.write(targetSource, function (e, stream) { return process.nextTick(function () { + if (e) { arg.setCode(WebDAVRequest_1.HTTPCodes.InternalServerError); - else - arg.setCode(WebDAVRequest_1.HTTPCodes.OK); - callback(); + callback(); + return; + } + stream.end(arg.data, function (e) { + if (e) + arg.setCode(WebDAVRequest_1.HTTPCodes.InternalServerError); + else + arg.setCode(WebDAVRequest_1.HTTPCodes.OK); + callback(); + }); }); }); }); return; @@ -91,12 +99,19 @@ function unchunkedMethod(arg, callback) { callback(); return; } - r.write(data_1, targetSource, function (e) { return process.nextTick(function () { - if (e) + r.write(targetSource, function (e, stream) { return process.nextTick(function () { + if (e) { arg.setCode(WebDAVRequest_1.HTTPCodes.InternalServerError); - else - arg.setCode(WebDAVRequest_1.HTTPCodes.OK); - callback(); + callback(); + return; + } + stream.end(arg.data, function (e) { + if (e) + arg.setCode(WebDAVRequest_1.HTTPCodes.InternalServerError); + else + arg.setCode(WebDAVRequest_1.HTTPCodes.OK); + callback(); + }); }); }); }); }); }); @@ -105,65 +120,3 @@ function unchunkedMethod(arg, callback) { }); } exports.default = unchunkedMethod; -function asyncWrite(arg, callback, resource, targetSource) { - function errorCallback(isLast) { - return function (error) { - if (error) - callback(new Errors_1.HTTPError(WebDAVRequest_1.HTTPCodes.InternalServerError, error), null); - else if (isLast) { - arg.setCode(WebDAVRequest_1.HTTPCodes.OK); - arg.exit(); - } - }; - } - callback(null, function (data, isFirst, isLast) { - if (isFirst) - resource.write(data, targetSource, errorCallback(isLast)); - else - resource.append(data, targetSource, errorCallback(isLast)); - }); -} -unchunkedMethod.startChunked = function (arg, callback) { - var targetSource = arg.findHeader('source', 'F').toUpperCase() === 'T'; - arg.getResource(function (e, r) { - if (e && e !== Errors_1.Errors.ResourceNotFound) { - callback(new Errors_1.HTTPError(WebDAVRequest_1.HTTPCodes.InternalServerError, e), null); - return; - } - arg.checkIfHeader(r, function () { - if (arg.contentLength === 0) { - if (r) { - arg.requirePrivilege(targetSource ? ['canSource', 'canWrite'] : ['canWrite'], r, function () { - asyncWrite(arg, callback, r, targetSource); - }); - return; - } - createResource(arg, callback, function (r) { - arg.setCode(WebDAVRequest_1.HTTPCodes.OK); - callback(null, null); - }); - } - else { - if (e) { - createResource(arg, callback, function (r) { - asyncWrite(arg, callback, r, targetSource); - }); - return; - } - arg.requirePrivilege(targetSource ? ['canSource', 'canWrite'] : ['canWrite'], r, function () { - r.type(function (e, type) { return process.nextTick(function () { - if (e) { - callback(new Errors_1.HTTPError(WebDAVRequest_1.HTTPCodes.InternalServerError, e), null); - return; - } - if (!type.isFile) { - callback(new Errors_1.HTTPError(WebDAVRequest_1.HTTPCodes.MethodNotAllowed, Errors_1.Errors.ExpectedAFileResourceType), null); - return; - } - asyncWrite(arg, callback, r, targetSource); - }); }); - }); - } - }); - }); -}; diff --git a/src/resource/IResource.ts b/src/resource/IResource.ts index 09e82a47..5436ff2c 100644 --- a/src/resource/IResource.ts +++ b/src/resource/IResource.ts @@ -1,4 +1,4 @@ -import { Readable, ReadableOptions } from 'stream' +import { Readable, Writable } from 'stream' import { FSManager, FSPath } from '../manager/FSManager' import { XMLElement } from '../helper/XML' import { LockKind } from './lock/LockKind' @@ -48,9 +48,8 @@ export interface IResource isOnTheSameFSWith(resource : IResource, callback : ReturnCallback) // ****************************** Content ****************************** // - append(data : Int8Array, targetSource : boolean, callback : SimpleCallback) - write(data : Int8Array, targetSource : boolean, callback : SimpleCallback) - read(targetSource : boolean, callback : ReturnCallback) + write(targetSource : boolean, callback : ReturnCallback) + read(targetSource : boolean, callback : ReturnCallback) mimeType(targetSource : boolean, callback : ReturnCallback) size(targetSource : boolean, callback : ReturnCallback) diff --git a/src/resource/physical/PhysicalFile.ts b/src/resource/physical/PhysicalFile.ts index 77192f01..14101a8e 100644 --- a/src/resource/physical/PhysicalFile.ts +++ b/src/resource/physical/PhysicalFile.ts @@ -1,5 +1,5 @@ import { IResource, SimpleCallback, ReturnCallback, ResourceType } from '../IResource' -import { Readable, ReadableOptions } from 'stream' +import { Readable, Writable } from 'stream' import { PhysicalResource } from './PhysicalResource' import { FSManager } from '../../manager/FSManager' import { Errors } from '../../Errors' @@ -49,33 +49,31 @@ export class PhysicalFile extends PhysicalResource } // ****************************** Content ****************************** // - append(data : Int8Array, targetSource : boolean, callback : SimpleCallback) + write(targetSource : boolean, callback : ReturnCallback) { - fs.appendFile(this.realPath, data, (e) => { + fs.open(this.realPath, 'w', (e, fd) => { if(e) - callback(e); - else { - this.updateLastModified(); - callback(null); + callback(e, null); + return; } - }); + + callback(null, fs.createWriteStream(null, { fd })); + this.updateLastModified(); + }) } - write(data : Int8Array, targetSource : boolean, callback : SimpleCallback) + read(targetSource : boolean, callback : ReturnCallback) { - fs.writeFile(this.realPath, data, (e) => { + fs.open(this.realPath, 'r', (e, fd) => { if(e) - callback(e); - else { - this.updateLastModified(); - callback(null); + callback(e, null); + return; } - }); - } - read(targetSource : boolean, callback : ReturnCallback) - { - fs.readFile(this.realPath, callback); + + callback(null, fs.createReadStream(null, { fd })); + this.updateLastModified(); + }) } mimeType(targetSource : boolean, callback : ReturnCallback) { diff --git a/src/resource/physical/PhysicalFolder.ts b/src/resource/physical/PhysicalFolder.ts index 4e2fed1c..a760252a 100644 --- a/src/resource/physical/PhysicalFolder.ts +++ b/src/resource/physical/PhysicalFolder.ts @@ -1,5 +1,5 @@ import { IResource, SimpleCallback, ReturnCallback, ResourceType } from '../IResource' -import { Readable, ReadableOptions } from 'stream' +import { Readable, Writable } from 'stream' import { ResourceChildren } from '../std/ResourceChildren' import { StandardResource } from '../std/StandardResource' import { PhysicalResource } from './PhysicalResource' @@ -82,15 +82,11 @@ export class PhysicalFolder extends PhysicalResource } // ****************************** Content ****************************** // - append(data : Int8Array, targetSource : boolean, callback : SimpleCallback) + write(targetSource : boolean, callback : ReturnCallback) { - callback(Errors.InvalidOperation); - } - write(data : Int8Array, targetSource : boolean, callback : SimpleCallback) - { - callback(Errors.InvalidOperation); + callback(Errors.InvalidOperation, null); } - read(targetSource : boolean, callback : ReturnCallback) + read(targetSource : boolean, callback : ReturnCallback) { callback(Errors.InvalidOperation, null); } @@ -114,7 +110,11 @@ export class PhysicalFolder extends PhysicalResource } removeChild(resource : IResource, callback : SimpleCallback) { - this.children.remove(resource, callback); + this.children.remove(resource, (e) => { + if(!e) + resource.parent = null; + callback(e); + }); } getChildren(callback : ReturnCallback) { diff --git a/src/resource/physical/PhysicalResource.ts b/src/resource/physical/PhysicalResource.ts index 436d9ca6..3e6c3e96 100644 --- a/src/resource/physical/PhysicalResource.ts +++ b/src/resource/physical/PhysicalResource.ts @@ -1,5 +1,5 @@ import { IResource, SimpleCallback, ReturnCallback, Return2Callback, ResourceType } from '../IResource' -import { Readable, ReadableOptions } from 'stream' +import { Readable, Writable } from 'stream' import { PhysicalFSManager } from '../../manager/PhysicalFSManager' import { StandardResource } from '../std/StandardResource' import { FSManager } from '../../manager/FSManager' @@ -77,9 +77,8 @@ export abstract class PhysicalResource extends StandardResource abstract type(callback : ReturnCallback) // ****************************** Content ****************************** // - abstract append(data : Int8Array, targetSource : boolean, callback : SimpleCallback) - abstract write(data : Int8Array, targetSource : boolean, callback : SimpleCallback) - abstract read(targetSource : boolean, callback : ReturnCallback) + abstract write(targetSource : boolean, callback : ReturnCallback) + abstract read(targetSource : boolean, callback : ReturnCallback) abstract mimeType(targetSource : boolean, callback : ReturnCallback) abstract size(targetSource : boolean, callback : ReturnCallback) diff --git a/src/resource/std/RootResource.ts b/src/resource/std/RootResource.ts index 02e240ee..4322e56c 100644 --- a/src/resource/std/RootResource.ts +++ b/src/resource/std/RootResource.ts @@ -1,5 +1,5 @@ import { IResource, SimpleCallback, ReturnCallback, Return2Callback, ResourceType } from '../IResource' -import { Readable, ReadableOptions } from 'stream' +import { Readable, Writable } from 'stream' import { StandardResource } from './StandardResource' import { ResourceChildren } from './ResourceChildren' import { RootFSManager } from '../../manager/RootFSManager' @@ -46,15 +46,11 @@ export class RootResource extends StandardResource } // ****************************** Content ****************************** // - append(data : Int8Array, targetSource : boolean, callback : SimpleCallback) + write(targetSource : boolean, callback : ReturnCallback) { - callback(Errors.InvalidOperation) - } - write(data : Int8Array, targetSource : boolean, callback : SimpleCallback) - { - callback(Errors.InvalidOperation) + callback(Errors.InvalidOperation, null) } - read(targetSource : boolean, callback : ReturnCallback) + read(targetSource : boolean, callback : ReturnCallback) { callback(Errors.InvalidOperation, null) } diff --git a/src/resource/std/StandardResource.ts b/src/resource/std/StandardResource.ts index e4cf858d..7d4273c8 100644 --- a/src/resource/std/StandardResource.ts +++ b/src/resource/std/StandardResource.ts @@ -1,5 +1,5 @@ import { IResource, ReturnCallback, SimpleCallback, Return2Callback, ResourceType, ResourcePropertyValue } from '../IResource' -import { Readable, ReadableOptions } from 'stream' +import { Readable, Writable } from 'stream' import { FSManager, FSPath } from '../../manager/FSManager' import { LockScope } from '../lock/LockScope' import { LockType } from '../lock/LockType' @@ -182,9 +182,8 @@ export abstract class StandardResource implements IResource abstract rename(newName : string, callback : Return2Callback) // ****************************** Content ****************************** // - abstract append(data : Int8Array, targetSource : boolean, callback : SimpleCallback) - abstract write(data : Int8Array, targetSource : boolean, callback : SimpleCallback) - abstract read(targetSource : boolean, callback : ReturnCallback) + abstract write(targetSource : boolean, callback : ReturnCallback) + abstract read(targetSource : boolean, callback : ReturnCallback) abstract mimeType(targetSource : boolean, callback : ReturnCallback) abstract size(targetSource : boolean, callback : ReturnCallback) diff --git a/src/resource/virtual/VirtualFile.ts b/src/resource/virtual/VirtualFile.ts index 0fc4afc6..a8780c11 100644 --- a/src/resource/virtual/VirtualFile.ts +++ b/src/resource/virtual/VirtualFile.ts @@ -1,5 +1,5 @@ import { IResource, SimpleCallback, ReturnCallback, ResourceType } from '../IResource' -import { Readable, ReadableOptions } from 'stream' +import { Readable, Writable } from 'stream' import { VirtualResource } from './VirtualResource' import { FSManager } from '../../manager/FSManager' import { Errors } from '../../Errors' @@ -9,9 +9,9 @@ export class VirtualFileReadable extends Readable { blockIndex : number - constructor(public contents : Int8Array[], options ?: ReadableOptions) + constructor(public contents : Int8Array[]) { - super(options); + super(); this.blockIndex = -1; } @@ -34,6 +34,20 @@ export class VirtualFileReadable extends Readable } } +export class VirtualFileWritable extends Writable +{ + constructor(public contents : Int8Array[]) + { + super(null); + } + + _write(chunk : Buffer | string | any, encoding : string, callback : (error : Error) => void) + { + this.contents.push(chunk); + callback(null); + } +} + export class VirtualFile extends VirtualResource { content : Int8Array[] @@ -54,21 +68,18 @@ export class VirtualFile extends VirtualResource } // ****************************** Content ****************************** // - append(data : Int8Array, targetSource : boolean, callback : SimpleCallback) - { - this.content.push(data); - this.len += data.length; - this.updateLastModified(); - callback(null); - } - write(data : Int8Array, targetSource : boolean, callback : SimpleCallback) + write(targetSource : boolean, callback : ReturnCallback) { - this.content = [ data ]; - this.len = data.length; - this.updateLastModified(); - callback(null); + let content = []; + const stream = new VirtualFileWritable(content); + stream.on('finish', () => { + this.content = content; + this.len = content.map((c) => c.length).reduce((s, n) => s + n, 0); + this.updateLastModified(); + }) + callback(null, stream); } - read(targetSource : boolean, callback : ReturnCallback) + read(targetSource : boolean, callback : ReturnCallback) { callback(null, new VirtualFileReadable(this.content)); } diff --git a/src/resource/virtual/VirtualFolder.ts b/src/resource/virtual/VirtualFolder.ts index a435dff7..7b3ae61a 100644 --- a/src/resource/virtual/VirtualFolder.ts +++ b/src/resource/virtual/VirtualFolder.ts @@ -1,5 +1,5 @@ import { IResource, SimpleCallback, ReturnCallback, ResourceType } from '../IResource' -import { Readable, ReadableOptions } from 'stream' +import { Readable, Writable } from 'stream' import { StandardResource } from '../std/StandardResource' import { ResourceChildren } from '../std/ResourceChildren' import { VirtualResource } from './VirtualResource' @@ -24,15 +24,11 @@ export class VirtualFolder extends VirtualResource } // ****************************** Content ****************************** // - append(data : Int8Array, targetSource : boolean, callback : SimpleCallback) + write(targetSource : boolean, callback : ReturnCallback) { - callback(Errors.InvalidOperation); - } - write(data : Int8Array, targetSource : boolean, callback : SimpleCallback) - { - callback(Errors.InvalidOperation); + callback(Errors.InvalidOperation, null); } - read(targetSource : boolean, callback : ReturnCallback) + read(targetSource : boolean, callback : ReturnCallback) { callback(Errors.InvalidOperation, null); } @@ -56,7 +52,11 @@ export class VirtualFolder extends VirtualResource } removeChild(resource : IResource, callback : SimpleCallback) { - this.children.remove(resource, callback); + this.children.remove(resource, (e) => { + if(!e) + resource.parent = null; + callback(e); + }); } getChildren(callback : ReturnCallback) { diff --git a/src/resource/virtual/VirtualResource.ts b/src/resource/virtual/VirtualResource.ts index 0906fe70..da6ae139 100644 --- a/src/resource/virtual/VirtualResource.ts +++ b/src/resource/virtual/VirtualResource.ts @@ -1,5 +1,5 @@ import { IResource, SimpleCallback, ReturnCallback, Return2Callback, ResourceType } from '../IResource' -import { Readable, ReadableOptions } from 'stream' +import { Readable, Writable } from 'stream' import { FSManager, FSPath } from '../../manager/FSManager' import { VirtualFSManager } from '../../manager/VirtualFSManager' import { StandardResource } from '../std/StandardResource' @@ -69,9 +69,8 @@ export abstract class VirtualResource extends StandardResource abstract type(callback : ReturnCallback) // ****************************** Content ****************************** // - abstract append(data : Int8Array, targetSource : boolean, callback : SimpleCallback) - abstract write(data : Int8Array, targetSource : boolean, callback : SimpleCallback) - abstract read(targetSource : boolean, callback : ReturnCallback) + abstract write(targetSource : boolean, callback : ReturnCallback) + abstract read(targetSource : boolean, callback : ReturnCallback) abstract mimeType(targetSource : boolean, callback : ReturnCallback) abstract size(targetSource : boolean, callback : ReturnCallback) diff --git a/src/server/commands/Commands.ts b/src/server/commands/Commands.ts index 813097f4..b48151da 100644 --- a/src/server/commands/Commands.ts +++ b/src/server/commands/Commands.ts @@ -1,3 +1,4 @@ +import { MethodCallArgs } from '../MethodCallArgs' import NotImplemented from './NotImplemented' import Proppatch from './Proppatch' import Propfind from './Propfind' diff --git a/src/server/commands/Copy.ts b/src/server/commands/Copy.ts index 0014c2e7..403ca18f 100644 --- a/src/server/commands/Copy.ts +++ b/src/server/commands/Copy.ts @@ -71,24 +71,11 @@ function copy(arg : MethodCallArgs, source : IResource, rDest : IResource, desti return; } - source.read(true, (e, data) => _(e, () => { - if((data as Readable).readable) - { - const rdata = data as Readable; - let isFirst = true; - rdata.on('data', (chunk) => { - if(isFirst) - { - isFirst = false; - dest.write(new Int8Array(0), true, (e) => _(e, () => { })); - } - else - dest.append(chunk as Buffer, true, (e) => _(e, next)); - }); - rdata.on('end', next); - } - else - dest.write(data as Int8Array, true, (e) => _(e, next)) + source.read(true, (e, rstream) => _(e, () => { + dest.write(true, (e, wstream) => _(e, () => { + rstream.on('end', next); + rstream.pipe(wstream); + })) })) function next() diff --git a/src/server/commands/Get.ts b/src/server/commands/Get.ts index 453e068a..10bc2b51 100644 --- a/src/server/commands/Get.ts +++ b/src/server/commands/Get.ts @@ -16,37 +16,19 @@ export default function(arg : MethodCallArgs, callback) const targetSource = arg.findHeader('source', 'F').toUpperCase() === 'T'; arg.requirePrivilege(targetSource ? [ 'canRead', 'canSource' ] : [ 'canRead' ], r, () => { - r.read(targetSource, (e, c) => process.nextTick(() => { + r.read(targetSource, (e, rstream) => process.nextTick(() => { if(e) + { arg.setCode(HTTPCodes.MethodNotAllowed); + callback(); + } else { arg.setCode(HTTPCodes.OK); - - if((c as Readable).readable) - { - const rdata = c as Readable; - let isFirst = true; - rdata.on('end', callback); - rdata.pipe(arg.response); - return; - } - else - { - let content : any = c; - if(c === undefined || c === null) - content = new Buffer(0); - else if(c.constructor === Boolean || c.constructor === Number) - content = c.toString() - else if(c.constructor === Int8Array) - content = new Buffer(c as Int8Array); - else - content = c; - - arg.response.write(content); - } + + rstream.on('end', callback); + rstream.pipe(arg.response); } - callback(); })) }) }) diff --git a/src/server/commands/Put.ts b/src/server/commands/Put.ts index 2d3eb22f..6ab48007 100644 --- a/src/server/commands/Put.ts +++ b/src/server/commands/Put.ts @@ -64,7 +64,10 @@ export default function unchunkedMethod(arg : MethodCallArgs, callback) if(r) { // Resource exists => empty it arg.requirePrivilege(targetSource ? [ 'canSource', 'canWrite' ] : [ 'canWrite' ], r, () => { - r.write(new Buffer(0), targetSource, (e) => process.nextTick(() => { + r.write(targetSource, (e, stream) => process.nextTick(() => { + if(stream) + stream.end(); + if(e) arg.setCode(HTTPCodes.InternalServerError) else @@ -82,17 +85,24 @@ export default function unchunkedMethod(arg : MethodCallArgs, callback) } else { // Write to a file - const data = new Buffer(arg.data); - if(e) { // Resource not found createResource(arg, callback, (r) => { - r.write(data, targetSource, (e) => process.nextTick(() => { + r.write(targetSource, (e, stream) => process.nextTick(() => { if(e) - arg.setCode(HTTPCodes.InternalServerError) - else - arg.setCode(HTTPCodes.OK) - callback(); + { + arg.setCode(HTTPCodes.InternalServerError); + callback(); + return; + } + + stream.end(arg.data, (e) => { + if(e) + arg.setCode(HTTPCodes.InternalServerError) + else + arg.setCode(HTTPCodes.OK) + callback(); + }); })) }) return; @@ -113,12 +123,21 @@ export default function unchunkedMethod(arg : MethodCallArgs, callback) return; } - r.write(data, targetSource, (e) => process.nextTick(() => { + r.write(targetSource, (e, stream) => process.nextTick(() => { if(e) - arg.setCode(HTTPCodes.InternalServerError) - else - arg.setCode(HTTPCodes.OK) - callback(); + { + arg.setCode(HTTPCodes.InternalServerError); + callback(); + return; + } + + stream.end(arg.data, (e) => { + if(e) + arg.setCode(HTTPCodes.InternalServerError) + else + arg.setCode(HTTPCodes.OK) + callback(); + }); })) })) }) @@ -126,7 +145,7 @@ export default function unchunkedMethod(arg : MethodCallArgs, callback) }) }) } - +/* function asyncWrite(arg : MethodCallArgs, callback : StartChunkedCallback, resource : IResource, targetSource : boolean) { function errorCallback(isLast : boolean) @@ -207,3 +226,4 @@ function asyncWrite(arg : MethodCallArgs, callback : StartChunkedCallback, resou }) }) } +*/ \ No newline at end of file