Permalink
Browse files

DAVACL now fully implemented except for a storage backend

  • Loading branch information...
1 parent fa019d5 commit cccb410adde0722858bbec817257fdc37f60d402 @mikedeboer committed Jan 25, 2013
View
@@ -714,9 +714,26 @@ jsDAV_Handler.STATUS_MAP = {
self.getPropertiesForPath(path, requestedProperties, depth, function(err, newProperties) {
if (!Util.empty(err))
return self.handleError(err);
- // This is a multi-status response
- self.httpResponse.writeHead(207, {"content-type": "application/xml; charset=utf-8"});
- self.httpResponse.end(self.generateMultiStatus(newProperties));
+
+ // Normally this header is only needed for OPTIONS responses, however..
+ // iCal seems to also depend on these being set for PROPFIND. Since
+ // this is not harmful, we'll add it.
+ var features = ["1", "3", "extended-mkcol"];
+ for (var plugin in self.plugins) {
+ if (!self.plugins[plugin].getFeatures)
+ Util.log("method getFeatures() NOT implemented for plugin " + plugin, "error");
+ else
+ features = features.concat(self.plugins[plugin].getFeatures());
+ }
+
+ // This is a multi-status response.
+ self.httpResponse.writeHead(207, {
+ "content-type": "application/xml; charset=utf-8",
+ "vary": "Brief,Prefer",
+ "DAV": features.join(",");
+ });
+ var prefer = self.getHTTPPrefer();
+ self.httpResponse.end(self.generateMultiStatus(newProperties, prefer["return-minimal"]));
});
});
});
@@ -745,7 +762,34 @@ jsDAV_Handler.STATUS_MAP = {
self.updateProperties(self.getRequestUri(), newProperties, function(err, result) {
if (!Util.empty(err))
return self.handleError(err);
- self.httpResponse.writeHead(207, {"content-type": "application/xml; charset=utf-8"});
+
+ var prefer = this.getHTTPPrefer();
+ if (prefer["return-minimal"]) {
+ // If return-minimal is specified, we only have to check if the
+ // request was succesful, and don't need to return the
+ // multi-status.
+ var prop;
+ var ok = true;
+ for (code in result) {
+ prop = result[code];
+ if (parseInt(code, 10) > 299) {
+ ok = false;
+ break;
+ }
+ }
+ if (ok) {
+ self.httpResponse.writeHead(204, {
+ "vary": "Brief, Prefer"
+ });
+ self.httpResponse.end();
+ return;
+ }
+ }
+
+ self.httpResponse.writeHead(207, {
+ "content-type": "application/xml; charset=utf-8",
+ "vary": "Brief, Prefer"
+ });
self.httpResponse.end(self.generateMultiStatus(result));
});
});
@@ -1446,7 +1490,7 @@ jsDAV_Handler.STATUS_MAP = {
* @param {Array} fileProperties The list with nodes
* @return {String}
*/
- this.generateMultiStatus = function(fileProperties) {
+ this.generateMultiStatus = function(fileProperties, strip404s) {
var namespace, prefix, entry, href, response;
var xml = '<?xml version="1.0" encoding="utf-8"?><d:multistatus';
@@ -1463,6 +1507,9 @@ jsDAV_Handler.STATUS_MAP = {
href = entry["href"];
//delete entry["href"];
+ if (strip404s && entry["404"])
+ delete entry["404"];
+
response = jsDAV_Property_Response.new(href, entry);
xml = response.serialize(this, xml);
}
@@ -1860,6 +1907,75 @@ jsDAV_Handler.STATUS_MAP = {
return parseInt(depth, 10);
};
+ /**
+ * Returns the HTTP Prefer header information.
+ *
+ * The prefer header is defined in:
+ * http://tools.ietf.org/html/draft-snell-http-prefer-14
+ *
+ * This method will return an array with options.
+ *
+ * Currently, the following options may be returned:
+ * {
+ * "return-asynch" : true,
+ * "return-minimal" : true,
+ * "return-representation" : true,
+ * "wait" : 30,
+ * "strict" : true,
+ * "lenient" : true,
+ * }
+ *
+ * This method also supports the Brief header, and will also return
+ * 'return-minimal' if the brief header was set to 't'.
+ *
+ * For the boolean options, false will be returned if the headers are not
+ * specified. For the integer options it will be 'null'.
+ *
+ * @return array
+ */
+ this.getHTTPPrefer = function() {
+ var result = {
+ "return-asynch" : false,
+ "return-minimal" : false,
+ "return-representation" : false,
+ "wait" : null,
+ "strict" : false,
+ "lenient" : false
+ };
+
+ var prefer = this.httpRequest.headers.prefer;
+ if (prefer) {
+ prefer.split(",").map(function(item) {
+ return Util.trim(item);
+ }).forEach(function(parameter) {
+ // Right now our regex only supports the tokens actually
+ // specified in the draft. We may need to expand this if new
+ // tokens get registered.
+ var matches = parameter.match(/^([a-z0-9\-]+)(?:=([0-9]+))?$/);
+ var token = matches[1];
+
+ switch(token) {
+ case "return-asynch" :
+ case "return-minimal" :
+ case "return-representation" :
+ case "strict" :
+ case "lenient" :
+ result[token] = true;
+ break;
+ case "wait" :
+ result[token] = matches[2];
+ break;
+ }
+ });
+ }
+
+ var brief = this.httpRequest.headers.brief;
+ if (brief && brief == "t")
+ result["return-minimal"] = true;
+
+ return result;
+ };
+
/**
* This method parses the PROPFIND request and returns its information
*
View
@@ -1,7 +1,7 @@
/*
* @package jsDAV
* @subpackage DAV
- * @copyright Copyright(c) 2011 Ajax.org B.V. <info AT ajax DOT org>
+ * @copyright Copyright(c) 2013 Mike de Boer. <info AT mikedeboer DOT nl>
* @author Mike de Boer <info AT mikedeboer DOT nl>
* @license http://github.com/mikedeboer/jsDAV/blob/master/LICENSE MIT License
*/
@@ -51,8 +51,8 @@ var jsDAV_Property_Href = module.exports = jsDAV_Property_iHref.extend({
* @return jsDAV_Property_Href
*/
unserialize: function(dom) {
- if (Xml.toClarkNotation(dom.firstChild) === "{DAV:}href") {
- return jsDAV_Property_Href.new(dom.firstChild.textContent, false);
- }
+ return (Xml.toClarkNotation(dom.firstChild) === "{DAV:}href")
+ ? jsDAV_Property_Href.new(dom.firstChild.textContent, false)
+ : null;
}
});
@@ -0,0 +1,89 @@
+/*
+ * @package jsDAV
+ * @subpackage DAV
+ * @copyright Copyright(c) 2013 Mike de Boer. <info AT mikedeboer DOT nl>
+ * @author Mike de Boer <info AT mikedeboer DOT nl>
+ * @license http://github.com/mikedeboer/jsDAV/blob/master/LICENSE MIT License
+ */
+"use strict";
+
+var jsDAV_Property = require("./../interfaces/property");
+
+var Xml = require("./../../shared/xml");
+
+var jsDAV_Property_HrefList = module.exports = jsDAV_Property.extend({
+
+ /**
+ * hrefs
+ *
+ * @var array
+ */
+ hrefs: null,
+
+ /**
+ * Automatically prefix the url with the server base directory
+ *
+ * @var bool
+ */
+ autoPrefix: true,
+
+ /**
+ * __construct
+ *
+ * @param array hrefs
+ * @param bool autoPrefix
+ */
+ initialize: function(hrefs, autoPrefix) {
+ this.hrefs = hrefs;
+ this.autoPrefix = typeof autoPrefix == "boolean" ? autoPrefix : true;
+ },
+
+ /**
+ * Returns the uris
+ *
+ * @return array
+ */
+ getHrefs: function() {
+ return this.hrefs;
+ },
+
+ /**
+ * Serializes this property.
+ *
+ * It will additionally prepend the href property with the server's base uri.
+ *
+ * @param Sabre_DAV_Server server
+ * @param DOMElement dom
+ * @return void
+ */
+ serialize: function(handler, dom) {
+ var propPrefix = Xml.xmlNamespaces["DAV:"];
+ var autoPrefix = this.autoPrefix;
+ var aXml = [];
+
+ this.hrefs.forEach(function(href) {
+ href = Xml.escapeXml((autoPrefix ? handler.server.getBaseUri() : "") + href);
+ aXml.push("<" + propPrefix + ":href>" + href + "</" + propPrefix + ":href>");
+ });
+ return dom + aXml.join("");
+ },
+
+ /**
+ * Unserializes this property from a DOM Element
+ *
+ * This method returns an instance of this class.
+ * It will only decode {DAV:}href values.
+ *
+ * @param {DOMElement} dom
+ * @return jsDAV_Property_HrefList
+ */
+ unserialize: function(dom) {
+ var hrefs = [];
+ for (var i = 0, l = dom.childNodes.length; i < l; ++i) {
+ if (Xml.toClarkNotation(dom.childNodes[i]) === "{DAV:}href")
+ hrefs.push(dom.childNodes[i].textContent);
+ }
+
+ return jsDAV_Property_HrefList.new(hrefs, false);
+ }
+});
@@ -0,0 +1,49 @@
+/*
+ * @package jsDAV
+ * @subpackage DAV
+ * @copyright Copyright(c) 2013 Mike de Boer. <info AT mikedeboer DOT nl>
+ * @author Mike de Boer <info AT mikedeboer DOT nl>
+ * @license http://github.com/mikedeboer/jsDAV/blob/master/LICENSE MIT License
+ */
+"use strict";
+
+var jsDAV_Property = require("./../property");
+var jsDAV_Property_Response = require("./../property/response");
+
+var jsDAV_Property_Response = module.exports = jsDAV_Property.extend({
+ /**
+ * Response objects.
+ *
+ * @var array
+ */
+ responses: [],
+
+ /**
+ * The only valid argument is a list of Sabre\DAV\Property\Response
+ * objects.
+ *
+ * @param array responses;
+ */
+ initialize: function(responses) {
+ responses.forEach(function(response) {
+ if (!response.hasFeature(jsDAV_Property_Response))
+ throw new Error("You must pass an array of jsDAV_Property_Response objects");
+ });
+ this.responses = responses;
+ },
+
+ /**
+ * serialize
+ *
+ * @param {jsDAV_Server} server
+ * @param {String} dom
+ * @return void
+ */
+ serialize: function(handler, dom) {
+ var aXml = [];
+ this.responses.forEach(function(response) {
+ aXml.push(response.serialize(handler, ""));
+ });
+ return dom + aXml.join("");
+ }
+});
Oops, something went wrong.

0 comments on commit cccb410

Please sign in to comment.