diff --git a/lib/server/commands/Commands.js b/lib/server/commands/Commands.js index 74616201..27faf033 100644 --- a/lib/server/commands/Commands.js +++ b/lib/server/commands/Commands.js @@ -1,6 +1,7 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var NotImplemented_1 = require("./NotImplemented"); +var Proppatch_1 = require("./Proppatch"); var Propfind_1 = require("./Propfind"); var Options_1 = require("./Options"); var Delete_1 = require("./Delete"); @@ -11,6 +12,7 @@ var Put_1 = require("./Put"); var Get_1 = require("./Get"); exports.default = { NotImplemented: NotImplemented_1.default, + Proppatch: Proppatch_1.default, Propfind: Propfind_1.default, Options: Options_1.default, Delete: Delete_1.default, diff --git a/lib/server/commands/Proppatch.d.ts b/lib/server/commands/Proppatch.d.ts new file mode 100644 index 00000000..f8724433 --- /dev/null +++ b/lib/server/commands/Proppatch.d.ts @@ -0,0 +1,2 @@ +import { MethodCallArgs } from '../WebDAVRequest'; +export default function (arg: MethodCallArgs, callback: any): void; diff --git a/lib/server/commands/Proppatch.js b/lib/server/commands/Proppatch.js new file mode 100644 index 00000000..88468063 --- /dev/null +++ b/lib/server/commands/Proppatch.js @@ -0,0 +1,64 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var WebDAVRequest_1 = require("../WebDAVRequest"); +var http_1 = require("http"); +var XML_1 = require("../../helper/XML"); +function default_1(arg, callback) { + arg.getResource(function (e, r) { + if (e) { + arg.setCode(WebDAVRequest_1.HTTPCodes.NotFound); + callback(); + return; + } + var multistatus = XML_1.XML.createElement('D:multistatus', { + 'xmlns:D': 'DAV:' + }); + var response = multistatus.ele('D:response'); + response.ele('D:href').add(arg.fullUri()); + var xml = XML_1.XML.parse(arg.data); + var root = xml.find('DAV:propertyupdate'); + var finalize = function () { + finalize = function () { + arg.setCode(WebDAVRequest_1.HTTPCodes.MultiStatus); + arg.response.write(XML_1.XML.toXML(multistatus)); + callback(); + }; + }; + function notify(el, error) { + var code = error ? WebDAVRequest_1.HTTPCodes.Conflict : WebDAVRequest_1.HTTPCodes.OK; + var propstat = response.ele('D:propstat'); + propstat.ele('D:prop').ele(el.name); + propstat.ele('D:status').add('HTTP/1.1 ' + code + ' ' + http_1.STATUS_CODES[code]); + } + execute('DAV:set', function (el, callback) { + r.setProperty(el.name, el.elements, callback); + }); + execute('DAV:remove', function (el, callback) { + r.removeProperty(el.name, callback); + }); + function execute(name, fnProp) { + var list = root.findMany(name); + if (list.length === 0) { + finalize(); + return; + } + list.forEach(function (el) { + var els = el.find('DAV:prop').elements; + if (els.length === 0) { + finalize(); + return; + } + var nb = els.length; + els.forEach(function (el) { + fnProp(el, function (e) { + notify(el, e); + --nb; + if (nb === 0) + finalize(); + }); + }); + }); + } + }); +} +exports.default = default_1; diff --git a/src/server/commands/Commands.ts b/src/server/commands/Commands.ts index 73bad7d2..57096024 100644 --- a/src/server/commands/Commands.ts +++ b/src/server/commands/Commands.ts @@ -1,4 +1,5 @@ import NotImplemented from './NotImplemented' +import Proppatch from './Proppatch' import Propfind from './Propfind' import Options from './Options' import Delete from './Delete' @@ -10,6 +11,7 @@ import Get from './Get' export default { NotImplemented, + Proppatch, Propfind, Options, Delete, diff --git a/src/server/commands/Proppatch.ts b/src/server/commands/Proppatch.ts new file mode 100644 index 00000000..c2c537a2 --- /dev/null +++ b/src/server/commands/Proppatch.ts @@ -0,0 +1,79 @@ +import { HTTPCodes, MethodCallArgs, WebDAVRequest } from '../WebDAVRequest' +import { STATUS_CODES } from 'http' +import { IResource } from '../../resource/Resource' +import { XML } from '../../helper/XML' + +export default function(arg : MethodCallArgs, callback) +{ + arg.getResource((e, r) => { + if(e) + { + arg.setCode(HTTPCodes.NotFound) + callback(); + return; + } + + const multistatus = XML.createElement('D:multistatus', { + 'xmlns:D': 'DAV:' + }); + const response = multistatus.ele('D:response'); + response.ele('D:href').add(arg.fullUri()); + + const xml = XML.parse(arg.data); + const root = xml.find('DAV:propertyupdate'); + + let finalize = function() + { + finalize = function() + { + arg.setCode(HTTPCodes.MultiStatus); + arg.response.write(XML.toXML(multistatus)); + callback(); + } + } + + function notify(el : any, error : any) + { + const code = error ? HTTPCodes.Conflict : HTTPCodes.OK; + const propstat = response.ele('D:propstat'); + propstat.ele('D:prop').ele(el.name); + propstat.ele('D:status').add('HTTP/1.1 ' + code + ' ' + STATUS_CODES[code]); + } + + execute('DAV:set', (el, callback) => { + r.setProperty(el.name, el.elements, callback) + }) + execute('DAV:remove', (el, callback) => { + r.removeProperty(el.name, callback) + }) + + function execute(name, fnProp) + { + const list = root.findMany(name); + if(list.length === 0) + { + finalize(); + return; + } + + list.forEach(function(el) { + const els = el.find('DAV:prop').elements; + if(els.length === 0) + { + finalize(); + return; + } + + let nb = els.length; + els.forEach(function(el) { + fnProp(el, (e) => { + notify(el, e); + --nb; + if(nb === 0) + finalize(); + }) + }) + }) + } + }) +}