diff --git a/lib/server/MethodCallArgs.d.ts b/lib/server/MethodCallArgs.d.ts index e4f4b130..f84f40ea 100644 --- a/lib/server/MethodCallArgs.d.ts +++ b/lib/server/MethodCallArgs.d.ts @@ -1,6 +1,7 @@ /// import { BasicPrivilege } from '../user/privilege/IPrivilegeManager'; import { IResource, ReturnCallback } from '../resource/IResource'; +import { EventsName, DetailsType } from './webDAVServer/Events'; import { XMLElement } from '../helper/XML'; import { WebDAVServer } from './webDAVServer/WebDAVServer'; import { FSPath } from '../manager/FSManager'; @@ -33,6 +34,8 @@ export declare class MethodCallArgs { findHeader(name: string, defaultValue?: string): string; getResource(callback: ReturnCallback): void; dateISO8601(ticks: number): string; + invokeEvent(event: EventsName, subjectResource?: IResource, details?: DetailsType): void; + wrapEvent(event: EventsName, subjectResource?: IResource, details?: DetailsType): () => void; fullUri(uri?: string): string; prefixUri(): string; getResourcePath(resource: IResource, callback: ReturnCallback): void; diff --git a/lib/server/MethodCallArgs.js b/lib/server/MethodCallArgs.js index 67770d93..d54b1912 100644 --- a/lib/server/MethodCallArgs.js +++ b/lib/server/MethodCallArgs.js @@ -139,6 +139,19 @@ var MethodCallArgs = (function () { result += h + ':' + m; return result; }; + MethodCallArgs.prototype.invokeEvent = function (event, subjectResource, details) { + this.server.invoke(event, this, subjectResource, details); + }; + MethodCallArgs.prototype.wrapEvent = function (event, subjectResource, details) { + var _this = this; + var oldExit = this.exit; + this.exit = function () { + if (Math.floor(_this.response.statusCode / 100) === 2) + _this.invokeEvent(event, subjectResource, details); + oldExit(); + }; + return this.exit; + }; MethodCallArgs.prototype.fullUri = function (uri) { if (uri === void 0) { uri = null; } if (!uri) diff --git a/lib/server/commands/Copy.js b/lib/server/commands/Copy.js index ae93d247..7dfc2543 100644 --- a/lib/server/commands/Copy.js +++ b/lib/server/commands/Copy.js @@ -45,7 +45,9 @@ function copy(arg, source, rDest, destination, callback) { var dest = rDest.fsManager.newResource(destination.toString(), destination.fileName(), type, rDest); arg.requirePrivilege(['canCreate', 'canSetProperty', 'canWrite'], dest, function () { dest.create(function (e) { return _(e, function () { + arg.invokeEvent('create', dest); rDest.addChild(dest, function (e) { return _(e, function () { + arg.invokeEvent('addChild', rDest, dest); copyAllProperties(source, dest, function (e) { return _(e, function () { if (!type.isFile) { next(); @@ -53,12 +55,19 @@ function copy(arg, source, rDest, destination, callback) { } source.read(true, function (e, rstream) { return _(e, function () { dest.write(true, function (e, wstream) { return _(e, function () { - rstream.on('end', next); + rstream.on('end', function () { + arg.invokeEvent('read', source); + next(); + }); + wstream.on('finish', function () { + arg.invokeEvent('write', dest); + }); rstream.pipe(wstream); }); }); }); }); function next() { if (!type.isDirectory) { + arg.invokeEvent('copy', source, dest); callback(null); return; } @@ -73,11 +82,14 @@ function copy(arg, source, rDest, destination, callback) { return; } --nb; - if (nb === 0) + if (nb === 0) { + arg.invokeEvent('copy', source, dest); callback(null); + } } if (nb === 0) { callback(null); + arg.invokeEvent('copy', source, dest); return; } children.forEach(function (child) { @@ -114,8 +126,11 @@ function default_1(arg, callback) { callback(); return; } - destination = destination.substring(destination.indexOf('://') + '://'.length); - destination = destination.substring(destination.indexOf('/')); + var startIndex = destination.indexOf('://'); + if (startIndex !== -1) { + destination = destination.substring(startIndex + '://'.length); + destination = destination.substring(destination.indexOf('/')); + } destination = new FSManager_1.FSPath(destination); arg.server.getResourceFromPath(destination.getParent(), function (e, rDest) { if (e) { @@ -174,6 +189,7 @@ function default_1(arg, callback) { callback(e); return; } + arg.invokeEvent('delete', destCollision); done(true); }); }); }); }); diff --git a/lib/server/commands/Delete.js b/lib/server/commands/Delete.js index 16b469d4..c1b862c9 100644 --- a/lib/server/commands/Delete.js +++ b/lib/server/commands/Delete.js @@ -14,8 +14,10 @@ function default_1(arg, callback) { r.delete(function (e) { return process.nextTick(function () { if (e) arg.setCode(WebDAVRequest_1.HTTPCodes.InternalServerError); - else + else { arg.setCode(WebDAVRequest_1.HTTPCodes.OK); + arg.invokeEvent('delete', r); + } callback(); }); }); }); diff --git a/lib/server/commands/Get.js b/lib/server/commands/Get.js index 9d56863a..4c231ef7 100644 --- a/lib/server/commands/Get.js +++ b/lib/server/commands/Get.js @@ -61,6 +61,7 @@ function default_1(arg, callback) { callback(); } else { + arg.invokeEvent('read', r); var range = arg.findHeader('Range'); if (range) { var rex = /([0-9]+)/g; diff --git a/lib/server/commands/Lock.js b/lib/server/commands/Lock.js index c5458990..85268c00 100644 --- a/lib/server/commands/Lock.js +++ b/lib/server/commands/Lock.js @@ -56,12 +56,20 @@ function createLock(arg, callback) { callback(); return; } + arg.invokeEvent('create', resource); r.addChild(resource, function (e) { - if (e) + if (e) { arg.setCode(WebDAVRequest_1.HTTPCodes.InternalServerError); - else - arg.setCode(WebDAVRequest_1.HTTPCodes.Created); - callback(); + callback(); + } + else { + arg.invokeEvent('addChild', r, resource); + writeLock(resource, function () { + arg.setCode(WebDAVRequest_1.HTTPCodes.Created); + arg.writeXML(createResponse(arg, lock_1)); + callback(); + }); + } }); }); }); }); @@ -75,7 +83,7 @@ function createLock(arg, callback) { callback(); return; } - arg.checkIfHeader(r, function () { + function writeLock(r, cb) { arg.requirePrivilege(['canSetLock'], r, function () { r.setLock(lock_1, function (e) { return process.nextTick(function () { if (e) { @@ -83,12 +91,18 @@ function createLock(arg, callback) { callback(); return; } + arg.invokeEvent('lock', r, lock_1); arg.response.setHeader('Lock-Token', lock_1.uuid); - arg.setCode(WebDAVRequest_1.HTTPCodes.OK); - arg.writeXML(createResponse(arg, lock_1)); - callback(); + cb(); }); }); }); + } + arg.checkIfHeader(r, function () { + writeLock(r, function () { + arg.setCode(WebDAVRequest_1.HTTPCodes.OK); + arg.writeXML(createResponse(arg, lock_1)); + callback(); + }); }); }); } @@ -113,6 +127,7 @@ function refreshLock(arg, lockUUID, callback) { return; } lock.refresh(); + arg.invokeEvent('refreshLock', r, lock); arg.setCode(WebDAVRequest_1.HTTPCodes.OK); arg.writeXML(createResponse(arg, lock)); callback(); diff --git a/lib/server/commands/Mkcol.js b/lib/server/commands/Mkcol.js index 398cb50b..7d1f5dac 100644 --- a/lib/server/commands/Mkcol.js +++ b/lib/server/commands/Mkcol.js @@ -33,11 +33,14 @@ function default_1(arg, callback) { callback(); return; } + arg.invokeEvent('create', resource); r.addChild(resource, function (e) { return process.nextTick(function () { if (e) arg.setCode(WebDAVRequest_1.HTTPCodes.InternalServerError); - else + else { + arg.invokeEvent('addChild', r, resource); arg.setCode(WebDAVRequest_1.HTTPCodes.Created); + } callback(); }); }); }); }); diff --git a/lib/server/commands/Move.js b/lib/server/commands/Move.js index b7fa713f..9c242301 100644 --- a/lib/server/commands/Move.js +++ b/lib/server/commands/Move.js @@ -27,8 +27,10 @@ function default_1(arg, callback) { r.moveTo(rDest, destination.fileName(), overwrite, function (e) { return process.nextTick(function () { if (e) arg.setCode(WebDAVRequest_1.HTTPCodes.InternalServerError); - else + else { + arg.invokeEvent('move', r, destination); arg.setCode(WebDAVRequest_1.HTTPCodes.Created); + } callback(); }); }); }); diff --git a/lib/server/commands/Put.js b/lib/server/commands/Put.js index a5cc62e1..266fe9fc 100644 --- a/lib/server/commands/Put.js +++ b/lib/server/commands/Put.js @@ -25,13 +25,16 @@ function createResource(arg, callback, validCallback) { callback(); return; } + arg.invokeEvent('create', resource); r.addChild(resource, function (e) { return process.nextTick(function () { if (e) { arg.setCode(WebDAVRequest_1.HTTPCodes.InternalServerError); callback(); } - else + else { + arg.invokeEvent('addChild', r, resource); validCallback(resource); + } }); }); }); }); }); @@ -55,8 +58,10 @@ function unchunkedMethod(arg, callback) { stream.end(); if (e) arg.setCode(WebDAVRequest_1.HTTPCodes.InternalServerError); - else + else { + arg.invokeEvent('write', r); arg.setCode(WebDAVRequest_1.HTTPCodes.OK); + } callback(); }); }); }); @@ -79,8 +84,10 @@ function unchunkedMethod(arg, callback) { stream.end(arg.data, function (e) { if (e) arg.setCode(WebDAVRequest_1.HTTPCodes.InternalServerError); - else + else { + arg.invokeEvent('write', r); arg.setCode(WebDAVRequest_1.HTTPCodes.Created); + } callback(); }); }); }); @@ -108,8 +115,10 @@ function unchunkedMethod(arg, callback) { stream.end(arg.data, function (e) { if (e) arg.setCode(WebDAVRequest_1.HTTPCodes.InternalServerError); - else + else { + arg.invokeEvent('write', r); arg.setCode(WebDAVRequest_1.HTTPCodes.OK); + } callback(); }); }); }); @@ -137,8 +146,10 @@ unchunkedMethod.chunked = function (arg, callback) { stream.end(); if (e) arg.setCode(WebDAVRequest_1.HTTPCodes.InternalServerError); - else + else { + arg.invokeEvent('write', r); arg.setCode(WebDAVRequest_1.HTTPCodes.OK); + } callback(); }); }); }); @@ -161,6 +172,7 @@ unchunkedMethod.chunked = function (arg, callback) { arg.request.pipe(stream); stream.on('finish', function (e) { arg.setCode(WebDAVRequest_1.HTTPCodes.Created); + arg.invokeEvent('write', r); callback(); }); stream.on('error', function (e) { @@ -192,6 +204,7 @@ unchunkedMethod.chunked = function (arg, callback) { arg.request.pipe(stream); stream.on('finish', function (e) { arg.setCode(WebDAVRequest_1.HTTPCodes.OK); + arg.invokeEvent('write', r); callback(); }); stream.on('error', function (e) { diff --git a/lib/server/commands/Unlock.js b/lib/server/commands/Unlock.js index 7d31bc22..42371416 100644 --- a/lib/server/commands/Unlock.js +++ b/lib/server/commands/Unlock.js @@ -38,8 +38,10 @@ function default_1(arg, callback) { r.removeLock(lock.uuid, function (e, done) { if (e || !done) arg.setCode(WebDAVRequest_1.HTTPCodes.Forbidden); - else + else { + arg.invokeEvent('unlock', r, lock); arg.setCode(WebDAVRequest_1.HTTPCodes.NoContent); + } callback(); }); }); diff --git a/lib/server/webDAVServer/Events.d.ts b/lib/server/webDAVServer/Events.d.ts new file mode 100644 index 00000000..cb4fdb83 --- /dev/null +++ b/lib/server/webDAVServer/Events.d.ts @@ -0,0 +1,15 @@ +import { MethodCallArgs } from '../WebDAVRequest'; +import { XMLElement } from '../../helper/XML'; +import { IResource } from '../../resource/IResource'; +import { FSPath } from '../../manager/FSPath'; +import { Lock } from '../../resource/lock/Lock'; +export declare type EventsName = 'create' | 'delete' | 'copy' | 'move' | 'lock' | 'refreshLock' | 'unlock' | 'setProperty' | 'removeProperty' | 'write' | 'read' | 'addChild'; +export declare type DetailsType = IResource | FSPath | Lock | XMLElement; +export declare type Listener = (arg: MethodCallArgs, subjectResource: IResource, details?: DetailsType) => void; +export declare function invoke(event: EventsName, arg: MethodCallArgs, subjectResource?: IResource, details?: DetailsType): void; +export declare function register(event: EventsName, listener: Listener): void; +export declare function registerWithName(event: EventsName, name: string, listener: Listener): void; +export declare function clear(event: EventsName): void; +export declare function clearAll(event: EventsName): void; +export declare function remove(event: EventsName, listener: Listener): void; +export declare function removeByName(event: EventsName, name: string): void; diff --git a/lib/server/webDAVServer/Events.js b/lib/server/webDAVServer/Events.js new file mode 100644 index 00000000..3a7586fb --- /dev/null +++ b/lib/server/webDAVServer/Events.js @@ -0,0 +1,54 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +function getEventBag(_this, event) { + if (!_this.__events) + _this.__events = {}; + if (event && !_this.__events[event]) { + _this.__events[event] = { + all: [], + named: {} + }; + return _this.__events[event]; + } + return event ? _this.__events[event] : _this.__events; +} +function invoke(event, arg, subjectResource, details) { + var events = getEventBag(this, event); + events.all.forEach(function (e) { return process.nextTick(function () { return e(arg, subjectResource, details); }); }); +} +exports.invoke = invoke; +function register(event, listener) { + var events = getEventBag(this, event); + events.all.push(listener); +} +exports.register = register; +function registerWithName(event, name, listener) { + var events = getEventBag(this, event); + events.all.push(listener); + events.named[name] = listener; +} +exports.registerWithName = registerWithName; +function clear(event) { + var events = getEventBag(this, event); + events.all = []; + events.named = {}; +} +exports.clear = clear; +function clearAll(event) { + this.__events = {}; +} +exports.clearAll = clearAll; +function remove(event, listener) { + var events = getEventBag(this, event); + events.all.indexOf(listener); +} +exports.remove = remove; +function removeByName(event, name) { + var events = getEventBag(this, event); + var listener = events.named[name]; + if (listener) { + delete events.named[name]; + events.all.splice(events.all.indexOf(listener), 1); + } +} +exports.removeByName = removeByName; diff --git a/lib/server/webDAVServer/WebDAVServer.d.ts b/lib/server/webDAVServer/WebDAVServer.d.ts index 2eb536b4..2277b249 100644 --- a/lib/server/webDAVServer/WebDAVServer.d.ts +++ b/lib/server/webDAVServer/WebDAVServer.d.ts @@ -1,7 +1,7 @@ /// import { WebDAVServerOptions } from '../WebDAVServerOptions'; import { ResourceTreeNode, WebDAVServerStartCallback } from './Types'; -import { WebDAVRequest } from '../WebDAVRequest'; +import { MethodCallArgs, WebDAVRequest } from '../WebDAVRequest'; import { IResource, ReturnCallback } from '../../resource/IResource'; import { HTTPAuthentication } from '../../user/authentication/HTTPAuthentication'; import { IPrivilegeManager } from '../../user/privilege/IPrivilegeManager'; @@ -11,6 +11,7 @@ import * as http from 'http'; import * as persistence from './Persistence'; import * as beforeAfter from './BeforeAfter'; import * as startStop from './StartStop'; +import * as events from './Events'; export { WebDAVServerOptions } from '../WebDAVServerOptions'; export declare class WebDAVServer { httpAuthentication: HTTPAuthentication; @@ -42,4 +43,11 @@ export declare class WebDAVServer { protected invokeBARequest: typeof beforeAfter.invokeBARequest; protected invokeBeforeRequest: typeof beforeAfter.invokeBeforeRequest; protected invokeAfterRequest: typeof beforeAfter.invokeAfterRequest; + invoke(event: events.EventsName, arg: MethodCallArgs, subjectResource?: IResource | FSPath, details?: events.DetailsType): void; + on(event: events.EventsName, listener: events.Listener): any; + on(event: events.EventsName, eventName: string, listener: events.Listener): any; + clearEvent(event: events.EventsName): void; + clearEvents(event: events.EventsName): void; + removeEvent(event: events.EventsName, listener: events.Listener): any; + removeEvent(event: events.EventsName, eventName: string): any; } diff --git a/lib/server/webDAVServer/WebDAVServer.js b/lib/server/webDAVServer/WebDAVServer.js index 59645d21..99ab3341 100644 --- a/lib/server/webDAVServer/WebDAVServer.js +++ b/lib/server/webDAVServer/WebDAVServer.js @@ -6,6 +6,7 @@ var persistence = require("./Persistence"); var beforeAfter = require("./BeforeAfter"); var startStop = require("./StartStop"); var resource = require("./Resource"); +var events = require("./Events"); var WebDAVServerOptions_2 = require("../WebDAVServerOptions"); exports.WebDAVServerOptions = WebDAVServerOptions_2.WebDAVServerOptions; var WebDAVServer = (function () { @@ -50,6 +51,27 @@ var WebDAVServer = (function () { WebDAVServer.prototype.normalizeMethodName = function (method) { return method.toLowerCase(); }; + WebDAVServer.prototype.invoke = function (event, arg, subjectResource, details) { + events.invoke.bind(this)(event, subjectResource, details); + }; + WebDAVServer.prototype.on = function (event, eName_listener, listener) { + if (eName_listener.constructor === Function) + events.register.bind(this)(event, eName_listener); + else + events.registerWithName.bind(this)(event, eName_listener, listener); + }; + WebDAVServer.prototype.clearEvent = function (event) { + events.clear.bind(this)(event); + }; + WebDAVServer.prototype.clearEvents = function (event) { + events.clearAll.bind(this)(); + }; + WebDAVServer.prototype.removeEvent = function (event, eName_listener) { + if (eName_listener.constructor === Function) + events.remove.bind(this)(event, eName_listener); + else + events.removeByName.bind(this)(event, eName_listener); + }; return WebDAVServer; }()); exports.WebDAVServer = WebDAVServer; diff --git a/src/server/MethodCallArgs.ts b/src/server/MethodCallArgs.ts index f27284ed..97bce761 100644 --- a/src/server/MethodCallArgs.ts +++ b/src/server/MethodCallArgs.ts @@ -1,5 +1,6 @@ import { requirePrivilege, BasicPrivilege } from '../user/privilege/IPrivilegeManager' import { IResource, ReturnCallback } from '../resource/IResource' +import { EventsName, DetailsType } from './webDAVServer/Events' import { XML, XMLElement } from '../helper/XML' import { parseIfHeader } from '../helper/IfParser' import { WebDAVServer } from './webDAVServer/WebDAVServer' @@ -206,6 +207,22 @@ export class MethodCallArgs return result; } + invokeEvent(event : EventsName, subjectResource ?: IResource, details ?: DetailsType) + { + this.server.invoke(event, this, subjectResource, details); + } + wrapEvent(event : EventsName, subjectResource ?: IResource, details ?: DetailsType) + { + const oldExit = this.exit; + this.exit = () => { + if(Math.floor(this.response.statusCode / 100) === 2) + this.invokeEvent(event, subjectResource, details); + + oldExit(); + } + return this.exit; + } + fullUri(uri : string = null) { if(!uri) diff --git a/src/server/commands/Copy.ts b/src/server/commands/Copy.ts index 7d87669b..8fb26bd1 100644 --- a/src/server/commands/Copy.ts +++ b/src/server/commands/Copy.ts @@ -63,7 +63,11 @@ function copy(arg : MethodCallArgs, source : IResource, rDest : IResource, desti arg.requirePrivilege([ 'canCreate', 'canSetProperty', 'canWrite' ], dest, () => { dest.create((e) => _(e, () => { + arg.invokeEvent('create', dest); + rDest.addChild(dest, (e) => _(e, () => { + arg.invokeEvent('addChild', rDest, dest); + copyAllProperties(source, dest, (e) => _(e, () => { if(!type.isFile) { @@ -73,7 +77,13 @@ function copy(arg : MethodCallArgs, source : IResource, rDest : IResource, desti source.read(true, (e, rstream) => _(e, () => { dest.write(true, (e, wstream) => _(e, () => { - rstream.on('end', next); + rstream.on('end', () => { + arg.invokeEvent('read', source); + next(); + }); + wstream.on('finish', () => { + arg.invokeEvent('write', dest); + }) rstream.pipe(wstream); })) })) @@ -82,6 +92,7 @@ function copy(arg : MethodCallArgs, source : IResource, rDest : IResource, desti { if(!type.isDirectory) { + arg.invokeEvent('copy', source, dest); callback(null); return; } @@ -101,12 +112,16 @@ function copy(arg : MethodCallArgs, source : IResource, rDest : IResource, desti --nb; if(nb === 0) + { + arg.invokeEvent('copy', source, dest); callback(null); + } } if(nb === 0) { callback(null); + arg.invokeEvent('copy', source, dest); return; } @@ -151,8 +166,12 @@ export default function(arg : MethodCallArgs, callback) return; } - destination = destination.substring(destination.indexOf('://') + '://'.length) - destination = destination.substring(destination.indexOf('/')) + const startIndex = destination.indexOf('://'); + if(startIndex !== -1) + { + destination = destination.substring(startIndex + '://'.length) + destination = destination.substring(destination.indexOf('/')) // Remove the hostname + port + } destination = new FSPath(destination) arg.server.getResourceFromPath(destination.getParent(), (e, rDest) => { @@ -230,6 +249,7 @@ export default function(arg : MethodCallArgs, callback) return; } + arg.invokeEvent('delete', destCollision); done(true); })) })) diff --git a/src/server/commands/Delete.ts b/src/server/commands/Delete.ts index df0a69ea..d0bbdbb7 100644 --- a/src/server/commands/Delete.ts +++ b/src/server/commands/Delete.ts @@ -18,7 +18,10 @@ export default function(arg : MethodCallArgs, callback) if(e) arg.setCode(HTTPCodes.InternalServerError); else + { arg.setCode(HTTPCodes.OK); + arg.invokeEvent('delete', r); + } callback(); })) }) diff --git a/src/server/commands/Get.ts b/src/server/commands/Get.ts index 8cf45e45..f66afd45 100644 --- a/src/server/commands/Get.ts +++ b/src/server/commands/Get.ts @@ -64,6 +64,8 @@ export default function(arg : MethodCallArgs, callback) } else { + arg.invokeEvent('read', r); + const range = arg.findHeader('Range'); if(range) { diff --git a/src/server/commands/Lock.ts b/src/server/commands/Lock.ts index 898df2ee..efdaaccb 100644 --- a/src/server/commands/Lock.ts +++ b/src/server/commands/Lock.ts @@ -72,12 +72,22 @@ function createLock(arg : MethodCallArgs, callback) return; } + arg.invokeEvent('create', resource); r.addChild(resource, (e) => { if(e) + { arg.setCode(HTTPCodes.InternalServerError); + callback(); + } else - arg.setCode(HTTPCodes.Created); - callback(); + { + arg.invokeEvent('addChild', r, resource); + writeLock(resource, () => { + arg.setCode(HTTPCodes.Created); + arg.writeXML(createResponse(arg, lock)); + callback(); + }); + } }) })) }) @@ -95,7 +105,8 @@ function createLock(arg : MethodCallArgs, callback) return; } - arg.checkIfHeader(r, () => { + function writeLock(r : IResource, cb) + { arg.requirePrivilege([ 'canSetLock' ], r, () => { r.setLock(lock, (e) => process.nextTick(() => { if(e) @@ -105,12 +116,19 @@ function createLock(arg : MethodCallArgs, callback) return; } + arg.invokeEvent('lock', r, lock); arg.response.setHeader('Lock-Token', lock.uuid); - arg.setCode(HTTPCodes.OK); - arg.writeXML(createResponse(arg, lock)); - callback(); + cb(); })) }) + } + + arg.checkIfHeader(r, () => { + writeLock(r, () => { + arg.setCode(HTTPCodes.OK); + arg.writeXML(createResponse(arg, lock)); + callback(); + }) }) }) } @@ -143,6 +161,7 @@ function refreshLock(arg : MethodCallArgs, lockUUID : string, callback) lock.refresh(); + arg.invokeEvent('refreshLock', r, lock); arg.setCode(HTTPCodes.OK); arg.writeXML(createResponse(arg, lock)); callback(); diff --git a/src/server/commands/Mkcol.ts b/src/server/commands/Mkcol.ts index 34df9c8a..4a5e773e 100644 --- a/src/server/commands/Mkcol.ts +++ b/src/server/commands/Mkcol.ts @@ -42,11 +42,15 @@ export default function(arg : MethodCallArgs, callback) return; } + arg.invokeEvent('create', resource); r.addChild(resource, (e) => process.nextTick(() => { if(e) arg.setCode(HTTPCodes.InternalServerError) else + { + arg.invokeEvent('addChild', r, resource); arg.setCode(HTTPCodes.Created) + } callback(); })) })) diff --git a/src/server/commands/Move.ts b/src/server/commands/Move.ts index d76c2b33..edb30f0c 100644 --- a/src/server/commands/Move.ts +++ b/src/server/commands/Move.ts @@ -35,7 +35,10 @@ export default function(arg : MethodCallArgs, callback) if(e) arg.setCode(HTTPCodes.InternalServerError) else + { + arg.invokeEvent('move', r, destination); arg.setCode(HTTPCodes.Created) + } callback() })) }) diff --git a/src/server/commands/Put.ts b/src/server/commands/Put.ts index 83d8b265..8b662acb 100644 --- a/src/server/commands/Put.ts +++ b/src/server/commands/Put.ts @@ -31,6 +31,7 @@ function createResource(arg : MethodCallArgs, callback, validCallback : (resourc return; } + arg.invokeEvent('create', resource); r.addChild(resource, (e) => process.nextTick(() => { if(e) { @@ -38,7 +39,10 @@ function createResource(arg : MethodCallArgs, callback, validCallback : (resourc callback(); } else + { + arg.invokeEvent('addChild', r, resource); validCallback(resource); + } })) })) }) @@ -71,7 +75,10 @@ export default function unchunkedMethod(arg : MethodCallArgs, callback) if(e) arg.setCode(HTTPCodes.InternalServerError) else + { + arg.invokeEvent('write', r); arg.setCode(HTTPCodes.OK) + } callback() })) }) @@ -100,7 +107,10 @@ export default function unchunkedMethod(arg : MethodCallArgs, callback) if(e) arg.setCode(HTTPCodes.InternalServerError) else + { + arg.invokeEvent('write', r); arg.setCode(HTTPCodes.Created) + } callback(); }); })) @@ -135,7 +145,10 @@ export default function unchunkedMethod(arg : MethodCallArgs, callback) if(e) arg.setCode(HTTPCodes.InternalServerError) else + { + arg.invokeEvent('write', r); arg.setCode(HTTPCodes.OK) + } callback(); }); })) @@ -171,7 +184,10 @@ export default function unchunkedMethod(arg : MethodCallArgs, callback) if(e) arg.setCode(HTTPCodes.InternalServerError) else + { + arg.invokeEvent('write', r); arg.setCode(HTTPCodes.OK) + } callback() })) }) @@ -199,6 +215,7 @@ export default function unchunkedMethod(arg : MethodCallArgs, callback) arg.request.pipe(stream); stream.on('finish', (e) => { arg.setCode(HTTPCodes.Created) + arg.invokeEvent('write', r); callback(); }); stream.on('error', (e) => { @@ -236,6 +253,7 @@ export default function unchunkedMethod(arg : MethodCallArgs, callback) arg.request.pipe(stream); stream.on('finish', (e) => { arg.setCode(HTTPCodes.OK) + arg.invokeEvent('write', r); callback(); }); stream.on('error', (e) => { diff --git a/src/server/commands/Unlock.ts b/src/server/commands/Unlock.ts index 6233e7e9..10278efa 100644 --- a/src/server/commands/Unlock.ts +++ b/src/server/commands/Unlock.ts @@ -56,7 +56,10 @@ export default function(arg : MethodCallArgs, callback) if(e || !done) arg.setCode(HTTPCodes.Forbidden); else + { + arg.invokeEvent('unlock', r, lock); arg.setCode(HTTPCodes.NoContent); + } callback(); }) }) diff --git a/src/server/webDAVServer/Events.ts b/src/server/webDAVServer/Events.ts new file mode 100644 index 00000000..d29a9de3 --- /dev/null +++ b/src/server/webDAVServer/Events.ts @@ -0,0 +1,80 @@ +import { MethodCallArgs } from '../WebDAVRequest' +import { XMLElement } from '../../helper/XML' +import { IResource } from '../../resource/IResource' +import { FSPath } from '../../manager/FSPath' +import { Lock } from '../../resource/lock/Lock' + +export type EventsName = 'create' | 'delete' | 'copy' | 'move' + | 'lock' | 'refreshLock' | 'unlock' + | 'setProperty' | 'removeProperty' + | 'write' | 'read' + | 'addChild'; + +export type DetailsType = IResource | FSPath | Lock | XMLElement; +export type Listener = (arg : MethodCallArgs, subjectResource : IResource, details ?: DetailsType) => void; + +function getEventBag(_this : any, event ?: string) +{ + if(!_this.__events) + _this.__events = { }; + + if(event && !_this.__events[event]) + { + _this.__events[event] = { + all: [], + named: {} + }; + return _this.__events[event]; + } + + return event ? _this.__events[event] : _this.__events; +} + +export function invoke(event : EventsName, arg : MethodCallArgs, subjectResource ?: IResource, details ?: DetailsType) +{ + const events = getEventBag(this, event); + events.all.forEach((e) => process.nextTick(() => e(arg, subjectResource, details))); +} + +export function register(event : EventsName, listener : Listener) +{ + const events = getEventBag(this, event); + events.all.push(listener) +} + +export function registerWithName(event : EventsName, name : string, listener : Listener) +{ + const events = getEventBag(this, event); + events.all.push(listener); + events.named[name] = listener; +} + +export function clear(event : EventsName) +{ + const events = getEventBag(this, event); + events.all = []; + events.named = {}; +} + +export function clearAll(event : EventsName) +{ + this.__events = { }; +} + +export function remove(event : EventsName, listener : Listener) +{ + const events = getEventBag(this, event); + events.all.indexOf(listener); +} + +export function removeByName(event : EventsName, name : string) +{ + const events = getEventBag(this, event); + const listener = events.named[name]; + if(listener) + { + delete events.named[name]; + events.all.splice(events.all.indexOf(listener), 1); + } +} + diff --git a/src/server/webDAVServer/WebDAVServer.ts b/src/server/webDAVServer/WebDAVServer.ts index 65e5e2b1..a61b1439 100644 --- a/src/server/webDAVServer/WebDAVServer.ts +++ b/src/server/webDAVServer/WebDAVServer.ts @@ -13,6 +13,7 @@ import * as persistence from './Persistence' import * as beforeAfter from './BeforeAfter' import * as startStop from './StartStop' import * as resource from './Resource' +import * as events from './Events' export { WebDAVServerOptions } from '../WebDAVServerOptions' @@ -101,4 +102,37 @@ export class WebDAVServer protected invokeBARequest = beforeAfter.invokeBARequest protected invokeBeforeRequest = beforeAfter.invokeBeforeRequest protected invokeAfterRequest = beforeAfter.invokeAfterRequest + + // Events + invoke(event : events.EventsName, arg : MethodCallArgs, subjectResource ?: IResource | FSPath, details ?: events.DetailsType) + { + events.invoke.bind(this)(event, subjectResource, details); + } + + on(event : events.EventsName, listener : events.Listener) + on(event : events.EventsName, eventName : string, listener : events.Listener) + on(event : events.EventsName, eName_listener : string | (events.Listener), listener ?: events.Listener) + { + if(eName_listener.constructor === Function) + events.register.bind(this)(event, eName_listener); + else + events.registerWithName.bind(this)(event, eName_listener, listener); + } + clearEvent(event : events.EventsName) + { + events.clear.bind(this)(event); + } + clearEvents(event : events.EventsName) + { + events.clearAll.bind(this)(); + } + removeEvent(event : events.EventsName, listener : events.Listener) + removeEvent(event : events.EventsName, eventName : string) + removeEvent(event : events.EventsName, eName_listener : string | (events.Listener)) + { + if(eName_listener.constructor === Function) + events.remove.bind(this)(event, eName_listener); + else + events.removeByName.bind(this)(event, eName_listener); + } }