aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/webcals/sax.js18
-rw-r--r--lib/webcals/sax/dav_response.js140
-rw-r--r--samples/xml/prop-get.xml27
-rw-r--r--test/webcals/sax/dav_response_test.js75
-rw-r--r--test/webcals/sax_test.js14
5 files changed, 236 insertions, 38 deletions
diff --git a/lib/webcals/sax.js b/lib/webcals/sax.js
index 9cc8425..d6f7592 100644
--- a/lib/webcals/sax.js
+++ b/lib/webcals/sax.js
@@ -131,23 +131,26 @@
},
_fireHandler: function(event, data) {
- if (event in this.handler) {
+ if (typeof(this.handler[event]) === 'function') {
this.handler[event].call(this, data, this.handler);
}
},
onopentag: function(data) {
var handle;
- var stackData = {};
+ var stackData = {
+ local: data.local,
+ name: data.name
+ };
//build tagSpec for others to use.
data.tagSpec = data.uri + '/' + data.local;
//add to stackData
- stackData.tag = data.tagSpec;
+ stackData.tagSpec = data.tagSpec;
// shortcut to the current tag object
- this.currentTag = data;
+ this.currentTag = stackData;
//determine if we need to switch to another
//handler object.
@@ -163,10 +166,15 @@
this._fireHandler('onopentag', data);
},
+ //XXX: optimize later
+ get currentTag() {
+ return this.tagStack[this.tagStack.length - 1];
+ },
+
onclosetag: function(data) {
var stack, handler;
- stack = this.tagStack[this.tagStack.length - 1];
+ stack = this.currentTag;
if (stack.handler) {
//fire oncomplete handler if available
diff --git a/lib/webcals/sax/dav_response.js b/lib/webcals/sax/dav_response.js
new file mode 100644
index 0000000..5b3e0b7
--- /dev/null
+++ b/lib/webcals/sax/dav_response.js
@@ -0,0 +1,140 @@
+(function(module, ns) {
+
+ var HTTP_STATUS = /([0-9]{3,3})/;
+
+ var Base = ns.require('sax/base');
+
+ var TextHandler = Base.create({
+ name: 'text',
+
+ //don't add text only elements
+ //to the stack as objects
+ onopentag: null,
+ onclosetag: null,
+
+ //add the value to the parent
+ //value where key is local tag name
+ //and value is the text.
+ ontext: function(data) {
+ var handler = this.handler;
+ this.current[this.currentTag[handler.tagField]] = data;
+ }
+ });
+
+ var HttpStatusHandler = TextHandler.create({
+ name: 'status',
+
+ ontext: function(data, handler) {
+ var match = data.match(HTTP_STATUS);
+
+ if (match) {
+ var handler = this.handler;
+ this.current[this.currentTag[handler.tagField]] = match[1];
+ } else {
+ this._super.ontext.call(this, data, handler);
+ }
+ }
+ });
+
+ var ArrayHandler = Base.create({
+ name: 'array',
+
+ handles: {
+ 'DAV:/href': TextHandler
+ },
+
+ onopentag: function(data, handler) {
+ var last;
+ var tag = data[handler.tagField];
+ var last = this.tagStack[this.tagStack.length - 1];
+
+ if (last.handler === handler) {
+ this.stack.push(this.current);
+ this.current = this.current[tag] = [];
+ } else {
+ this.current.push(tag);
+ }
+ },
+
+ ontext: null,
+ onclosetag: null,
+
+ oncomplete: function() {
+ this.current = this.stack.pop();
+ }
+
+ });
+
+ var PropStatHandler = Base.create({
+ name: 'propstat',
+
+ handles: {
+ 'DAV:/href': TextHandler,
+ 'DAV:/status': HttpStatusHandler,
+ 'DAV:/resourcetype': ArrayHandler
+ },
+
+ onopentag: function(data, handler) {
+ //orphan
+ if (data.tagSpec === 'DAV:/propstat') {
+ this.stack.push(this.current);
+ return this.current = {};
+ }
+
+ handler._super.onopentag.call(this, data, handler);
+ },
+
+ oncomplete: function() {
+ var parent = this.stack[this.stack.length - 1];
+ var key;
+
+ //console.log(this.current);
+
+ for (key in this.current.prop) {
+ if (this.current.prop.hasOwnProperty(key)) {
+ parent[key] = {
+ status: this.current.status,
+ value: this.current.prop[key]
+ }
+ }
+ }
+ },
+
+ });
+
+ var Response = Base.create({
+ name: 'dav_response',
+ handles: {
+ 'DAV:/href': TextHandler,
+ 'DAV:/propstat': PropStatHandler
+ },
+
+ //onopentag: function(data, handler) {
+ //if (data.tagSpec === 'DAV:/response') {
+ //this.stack.push(this.current);
+ //return this.current = {};
+ //}
+
+ //handler._super.onopentag.call(this, data, handler._super);
+ //},
+
+ //oncomplete: function() {
+ //var parent;
+
+ //if (this.current.href) {
+ //parent = this.stack[this.stack.length - 1];
+ //parent[this.current.href] = this.current.propstat;
+ //}
+ //}
+
+ });
+
+ module.exports = Response;
+
+}.apply(
+ this,
+ (this.Webcals) ?
+ [Webcals('sax/dav_response'), Webcals] :
+ [module, require('../webcals')]
+));
+
diff --git a/samples/xml/prop-get.xml b/samples/xml/prop-get.xml
deleted file mode 100644
index 72ee984..0000000
--- a/samples/xml/prop-get.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<D:multistatus xmlns:D="DAV:">
-
- <D:response>
- <D:href>/calendar/dav/calmozilla1%40gmail.com/user/</D:href>
- <D:propstat>
- <D:status>HTTP/1.1 200 OK</D:status>
- <D:prop>
- <D:principal-URL>
- <D:href>/calendar/dav/calmozilla1@gmail.com/user/</D:href>
- </D:principal-URL>
- <D:resourcetype>
- <D:principal />
- <D:collection />
- </D:resourcetype>
- </D:prop>
- </D:propstat>
-
- <D:propstat>
- <D:status>HTTP/1.1 404 Not Found</D:status>
- <D:prop>
- <A:current-user-principal xmlns:A="DAV:" />
- </D:prop>
- </D:propstat>
- </D:response>
-
-</D:multistatus>
diff --git a/test/webcals/sax/dav_response_test.js b/test/webcals/sax/dav_response_test.js
new file mode 100644
index 0000000..8e84e6b
--- /dev/null
+++ b/test/webcals/sax/dav_response_test.js
@@ -0,0 +1,75 @@
+requireLib('sax');
+requireLib('sax/base');
+requireLib('sax/dav_response');
+
+suite('webcals/sax/base', function() {
+
+ var data,
+ subject,
+ parser,
+ Parse,
+ Response,
+ Base,
+ handler;
+
+
+ suiteSetup(function() {
+ Parse = Webcals.require('sax');
+ Base = Webcals.require('sax/base');
+ Response = Webcals.require('sax/dav_response');
+ });
+
+ setup(function() {
+ //we omit the option to pass base parser
+ //because we are the base parser
+ subject = new Parse();
+ subject.registerHandler('DAV:/response', Response);
+ });
+
+ suite('parsing', function() {
+ var xml;
+
+ defineSample('xml/propget.xml', function(data) {
+ xml = data;
+ });
+
+ expected = {
+ '/calendar/user': {
+
+ 'principal-URL': {
+ status: '200',
+ value: '/calendar/user/'
+ },
+
+ resourcetype: {
+ status: '200',
+ value: [
+ 'principal',
+ 'collection'
+ ]
+ }
+ },
+
+ '/calendar/other': {
+ missing: {
+ status: '200',
+ value: {}
+ }
+ }
+ };
+
+ test('output', function(done) {
+ subject.once('complete', function(data) {
+ console.log(JSON.stringify(data));
+ //assert.deepEqual(
+ //data, expected,
+ //"expected \n '" + JSON.stringify(data) + "'\n to equal \n '" +
+ //JSON.stringify(expected) + '\n"'
+ //);
+ done();
+ });
+ subject.write(xml).close();
+ });
+ });
+
+});
diff --git a/test/webcals/sax_test.js b/test/webcals/sax_test.js
index 18a18a0..f9479e6 100644
--- a/test/webcals/sax_test.js
+++ b/test/webcals/sax_test.js
@@ -169,15 +169,16 @@ suite('webcals/sax', function() {
test('basic event', function() {
var obj = {
local: 'foo',
- uri: 'bar'
+ uri: 'bar',
+ name: 'foo'
};
subject.onopentag(obj);
- assert.equal(subject.currentTag, obj);
assert.equal(obj.tagSpec, 'bar/foo');
assert.deepEqual(
- subject.tagStack,
- [{ tag: 'bar/foo' }]
+ subject.tagStack[0].tagSpec,
+ 'bar/foo',
+ 'works'
);
firesHandler('opentag', obj);
@@ -192,7 +193,8 @@ suite('webcals/sax', function() {
subject.registerHandler('a/a', newHandler);
subject.onopentag({
local: 'a',
- uri: 'a'
+ uri: 'a',
+ name: 'a'
});
});
@@ -200,7 +202,7 @@ suite('webcals/sax', function() {
assert.equal(subject.handler, newHandler);
assert.deepEqual(
subject.tagStack, [
- { tag: 'a/a', handler: newHandler }
+ { tagSpec: 'a/a', local: 'a', name: 'a', handler: newHandler }
]
);
});