aboutsummaryrefslogtreecommitdiffstats
path: root/lib/caldav/sax
diff options
context:
space:
mode:
authorJames Lal <james@lightsofapollo.com>2012-07-06 08:13:15 -0700
committerJames Lal <james@lightsofapollo.com>2012-07-06 08:13:15 -0700
commit20711f003e97a4a57d1e2838ba78a994c5faf6c0 (patch)
treeb060e5de05a9ffefc2ec836469c087fffa99dcef /lib/caldav/sax
parentc8e85fe1e0a1d2e15df580068244324ff536a23a (diff)
downloadjsCalDAV-20711f003e97a4a57d1e2838ba78a994c5faf6c0.tar.gz
webcals -> caldav rename (yes, back again)
Diffstat (limited to 'lib/caldav/sax')
-rw-r--r--lib/caldav/sax/base.js73
-rw-r--r--lib/caldav/sax/dav_response.js208
-rw-r--r--lib/caldav/sax/index.js14
3 files changed, 295 insertions, 0 deletions
diff --git a/lib/caldav/sax/base.js b/lib/caldav/sax/base.js
new file mode 100644
index 0000000..a823aad
--- /dev/null
+++ b/lib/caldav/sax/base.js
@@ -0,0 +1,73 @@
+(function(module, ns) {
+
+ var Base = {
+
+ name: 'base',
+
+ tagField: 'local',
+
+ /**
+ * Creates a new object with base as its prototype.
+ * Adds ._super to object as convenience prop to access
+ * the parents functions.
+ *
+ * @param {Object} obj function overrides.
+ * @return {Object} new object.
+ */
+ create: function(obj) {
+ var key;
+ var child = Object.create(this);
+
+ child._super = this;
+
+ for (key in obj) {
+ if (obj.hasOwnProperty(key)) {
+ child[key] = obj[key];
+ }
+ }
+
+ return child;
+ },
+
+ onopentag: function(data, handler) {
+ var current = this.current;
+ var name = data[handler.tagField];
+
+ this.stack.push(this.current);
+
+ if (name in current) {
+ var next = {};
+
+ if (!(current[name] instanceof Array)) {
+ current[name] = [current[name]];
+ }
+
+ current[name].push(next);
+
+ this.current = next;
+ } else {
+ this.current = current[name] = {};
+ }
+ },
+
+ ontext: function(data) {
+ this.current.value = data;
+ },
+
+ onclosetag: function() {
+ this.current = this.stack.pop();
+ },
+
+ onend: function() {
+ this.emit('complete', this.root);
+ }
+ };
+
+ module.exports = Base;
+
+}.apply(
+ this,
+ (this.Caldav) ?
+ [Caldav('sax/base'), Caldav] :
+ [module, require('../caldav')]
+));
diff --git a/lib/caldav/sax/dav_response.js b/lib/caldav/sax/dav_response.js
new file mode 100644
index 0000000..b2556a7
--- /dev/null
+++ b/lib/caldav/sax/dav_response.js
@@ -0,0 +1,208 @@
+(function(module, ns) {
+
+ var HTTP_STATUS = /([0-9]{3,3})/;
+
+ var Base = ns.require('sax/base');
+ var ParseICal = ns.require('ical');
+
+ 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 CalendarDataHandler = Base.create({
+ name: 'calendar data',
+
+ //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]] = ParseICal(data);
+ }
+ });
+
+
+ var HrefHandler = Base.create({
+ name: 'href',
+
+ //don't add text only elements
+ //to the stack as objects
+ onopentag: null,
+ onclosetag: null,
+
+ onopentag: function() {
+ if (this.currentTag.handler === this.handler) {
+ this.stack.push(this.current);
+ this.current = null;
+ }
+ },
+
+ onclosetag: function() {
+ var current = this.currentTag;
+ var data;
+
+ if (current.handler === this.handler) {
+ data = this.current;
+
+ this.current = this.stack.pop();
+ this.current[current.local] = data;
+ }
+ },
+
+ ontext: function(data) {
+ if (this.currentTag.local === 'href') {
+ this.current = 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,
+ 'DAV:/principal-URL': HrefHandler,
+ 'urn:ietf:params:xml:ns:caldav/calendar-data': CalendarDataHandler,
+ 'DAV:/value': TextHandler,
+ 'urn:ietf:params:xml:ns:caldav/calendar-home-set': HrefHandler,
+ 'urn:ietf:params:xml:ns:caldav/calendar-user-address-set': HrefHandler
+ },
+
+ onopentag: function(data, handler) {
+ //orphan
+ if (data.tagSpec === 'DAV:/propstat') {
+ //blank slate propstat
+ if (!('propstat' in this.current)) {
+ this.current['propstat'] = {};
+ }
+
+ this.stack.push(this.current);
+
+ //contents will be copied over later.
+ return this.current = {};
+ }
+
+ handler._super.onopentag.call(this, data, handler);
+ },
+
+ oncomplete: function() {
+ var propstat = this.stack[this.stack.length - 1];
+ propstat = propstat.propstat;
+ var key;
+ var status = this.current.status;
+ var props = this.current.prop;
+
+ delete this.current.status;
+ delete this.current.prop;
+
+ for (key in props) {
+ if (props.hasOwnProperty(key)) {
+ propstat[key] = {
+ status: status,
+ value: props[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.Caldav) ?
+ [Caldav('sax/dav_response'), Caldav] :
+ [module, require('../caldav')]
+));
diff --git a/lib/caldav/sax/index.js b/lib/caldav/sax/index.js
new file mode 100644
index 0000000..2ba2f16
--- /dev/null
+++ b/lib/caldav/sax/index.js
@@ -0,0 +1,14 @@
+(function(module, ns) {
+
+ module.exports = {
+ Abstract: ns.require('sax/abstract'),
+ CalendarQuery: ns.require('sax/dav_response')
+ };
+
+}.apply(
+ this,
+ (this.Caldav) ?
+ [Caldav('sax'), Caldav] :
+ [module, require('../caldav')]
+));
+