diff options
-rw-r--r-- | Makefile | 1 | ||||
-rw-r--r-- | lib/webcals/xhr.js | 10 | ||||
-rw-r--r-- | package.json | 3 | ||||
-rw-r--r-- | webcals.js | 149 |
4 files changed, 158 insertions, 5 deletions
@@ -20,6 +20,7 @@ package: test-agent-config cat $(VENDOR)/sax.js >> $(WEB_FILE) echo ';' >> $(WEB_FILE) cat $(LIB_ROOT)/webcals.js >> $(WEB_FILE) + cat $(LIB_ROOT)/ical.js >> $(WEB_FILE) cat $(LIB_ROOT)/responder.js >> $(WEB_FILE) cat $(LIB_ROOT)/sax.js >> $(WEB_FILE) cat $(LIB_ROOT)/template.js >> $(WEB_FILE) diff --git a/lib/webcals/xhr.js b/lib/webcals/xhr.js index a8d8d58..fb925f0 100644 --- a/lib/webcals/xhr.js +++ b/lib/webcals/xhr.js @@ -52,7 +52,7 @@ url: null, headers: {}, - data: {}, + data: null, _seralize: function _seralize() { return this.data; @@ -80,7 +80,12 @@ } xhr = this.xhr = new this.xhrClass(); - xhr.open(this.method, this.url, this.async, this.user, this.password); + + if (Xhr.authHack) { + xhr.open(this.method, this.url, this.async); + } else { + xhr.open(this.method, this.url, this.async, this.user, this.password); + } for (header in this.headers) { if (this.headers.hasOwnProperty(header)) { @@ -88,6 +93,7 @@ } } + xhr.onreadystatechange = function onReadyStateChange() { var data; if (xhr.readyState === 4) { diff --git a/package.json b/package.json index 947171c..16d6c31 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,8 @@ "devDependencies": { "mocha": "~1.1", "chai": "~1.0", - "test-agent": "~0.6" + "test-agent": "~0.6", + "http-proxy": "~0.8" }, "license": "MIT", "engine": { @@ -1107,6 +1107,145 @@ function write (chunk) { module )); +(function(module, ns) { + // Credit: Andreas Gal - I removed the callback / xhr logic + + // Iterate over all entries if x is an array, otherwise just call fn on x. + + /* Pattern for an individual entry: name:value */ + var ENTRY = /^([A-Za-z0-9-]+)((?:;[A-Za-z0-9-]+=(?:"[^"]+"|[^";:,]+)(?:,(?:"[^"]+"|[^";:,]+))*)*):(.*)$/; + + /* Pattern for an individual parameter: name=value[,value] */ + var PARAM = /;([A-Za-z0-9-]+)=((?:"[^"]+"|[^";:,]+)(?:,(?:"[^"]+"|[^";:,]+))*)/g; + + /* Pattern for an individual parameter value: value | "value" */ + var PARAM_VALUE = /,?("[^"]+"|[^";:,]+)/g; + + // Parse a calendar in iCal format. + function ParseICal(text) { + // Parse the text into an object graph + var lines = text.replace(/\r/g, '').split('\n'); + var tos = Object.create(null); + var stack = [tos]; + + // Parse parameters for an entry. Foramt: <param>=<pvalue>[;...] + function parseParams(params) { + var map = Object.create(null); + var param = PARAM.exec(params); + while (param) { + var values = []; + var value = PARAM_VALUE.exec(param[2]); + while (value) { + values.push(value[1].replace(/^"(.*)"$/, '$1')); + value = PARAM_VALUE.exec(param[2]); + } + map[param[1].toLowerCase()] = (values.length > 1 ? values : values[0]); + param = PARAM.exec(params); + } + return map; + } + + // Add a property to the current object. If a property with the same name + // already exists, turn it into an array. + function add(prop, value, params) { + if (params) + value = { parameters: parseParams(params), value: value }; + if (prop in tos) { + var previous = tos[prop]; + if (previous instanceof Array) { + previous.push(value); + return; + } + value = [previous, value]; + } + tos[prop] = value; + } + + for (var n = 0; n < lines.length; ++n) { + var line = lines[n]; + // check whether the line continues (next line stats with space or tab) + var nextLine; + while ((nextLine = lines[n+1]) && (nextLine[0] === ' ' || nextLine[0] === '\t')) { + line += nextLine.substr(1); + ++n; + continue; + } + // parse the entry, format is 'PROPERTY:VALUE' + var matches = ENTRY.exec(line); + + if (!matches) { + throw new Error('invalid format'); + } + + var prop = matches[1].toLowerCase(); + var params = matches[2]; + var value = matches[3]; + switch (prop) { + case 'begin': + var obj = Object.create(null); + add(value.toLowerCase(), obj); + stack.push(tos = obj); + break; + case 'end': + stack.pop(); + tos = stack[stack.length - 1]; + if (stack.length == 1) { + var cal = stack[0]; + if (typeof cal.vcalendar !== 'object' || cal.vcalendar instanceof Array) { + throw new Error('single vcalendar object expected'); + } + + return cal.vcalendar; + } + break; + default: + add(prop, value, params); + break; + } + } + throw new Error('unexpected end of file'); + } + + function Value(v) { + return (typeof v !== 'object') ? v : v.value; + } + + function Parameter(v, name) { + if (typeof v !== 'object') + return undefined; + return v.parameters[name]; + } + + // Parse a time specification. + function ParseDateTime(v) { + var dt = Value(v); + if (Parameter(v, 'VALUE') === 'DATE') { + // 20081202 + return new Date(dt.substr(0, 4), dt.substr(4, 2), dt.substr(6, 2)); + } + v = Value(v); + // 20120426T130000Z + var year = dt.substr(0, 4); + var month = dt.substr(4, 2) - 1; + var day = dt.substr(6, 2); + var hour = dt.substr(9, 2); + var min = dt.substr(11, 2); + var sec = dt.substr(13, 2); + if (dt[15] == 'Z') { + return new Date(Date.UTC(year, month, day, hour, min, sec)); + } + return new Date(year, month, day, hour, min, sec); + } + + module.exports = ParseICal; + +}.apply( + this, + (this.Webcals) ? + [Webcals('ical'), Webcals] : + [module, require('./webcals')] +)); + /** @namespace */ @@ -1710,7 +1849,7 @@ function write (chunk) { url: null, headers: {}, - data: {}, + data: null, _seralize: function _seralize() { return this.data; @@ -1738,7 +1877,12 @@ function write (chunk) { } xhr = this.xhr = new this.xhrClass(); - xhr.open(this.method, this.url, this.async, this.user, this.password); + + if (Xhr.authHack) { + xhr.open(this.method, this.url, this.async); + } else { + xhr.open(this.method, this.url, this.async, this.user, this.password); + } for (header in this.headers) { if (this.headers.hasOwnProperty(header)) { @@ -1746,6 +1890,7 @@ function write (chunk) { } } + xhr.onreadystatechange = function onReadyStateChange() { var data; if (xhr.readyState === 4) { |