├── LICENSE
├── README.md
├── index.js
└── package.json
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 jachwe
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | node-caldav (Work-in-Progress)
2 | ===========
3 |
4 | A lightweight Node.JS Caldav Client
5 |
6 | Usage
7 | -----------
8 |
9 | ```sh
10 |
11 | var caldav = require("node-caldav");
12 |
13 | caldav.getList([caldav_baseurl],[username],[password],callback)
14 |
15 | caldav.getEvents([caldav_calendarurl],[username],[password],[startDate],[endDate],callback)
16 |
17 | ```
18 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | var https = require("https");
4 | var xmljs = require("libxmljs");
5 |
6 | module.exports = {
7 |
8 | /**
9 | * Get a list of Folders/Calendars from a given url
10 | *
11 | * @param {String} url
12 | * @param {String} user
13 | * @param {String} pass
14 | * @param {function} cb
15 |
16 | */
17 |
18 | getList: function (url, user, pass, cb) {
19 |
20 | var urlparts = /(https?)\:\/\/(.*?):?(\d*)?(\/.*\/?)/gi.exec(url);
21 | var protocol = urlparts[1];
22 | var host = urlparts[2];
23 | var port = urlparts[3] || (protocol === "https" ? 443 : 80);
24 | var path = urlparts[4];
25 |
26 | var xml = '\n' +
27 | ' \n' +
28 | ' \n' +
29 | ' \n' +
30 | ' \n' +
31 | ' ';
32 |
33 | var options = {
34 | rejectUnauthorized: false,
35 | hostname : host,
36 | port : port,
37 | path : path,
38 | method : 'PROPFIND',
39 | headers : {
40 | "Content-type" : "text/xml",
41 | "Content-Length": xml.length,
42 | "User-Agent" : "calDavClient",
43 | "Connection" : "close",
44 | "Depth" : "1"
45 | }
46 | };
47 |
48 | if (user && pass) {
49 | var userpass = new Buffer(user + ":" + pass).toString('base64');
50 | options.headers["Authorization"] = "Basic " + userpass;
51 | }
52 |
53 |
54 | var req = https.request(options, function (res) {
55 | var s = "";
56 | res.on('data', function (chunk) {
57 | s += chunk;
58 | });
59 |
60 | req.on('close', function () {
61 | var reslist = [];
62 | try {
63 | var xmlDoc = xmljs.parseXml(s);
64 | // console.log(xmlDoc.toString() );
65 | var resp = xmlDoc.find("a:response", { a: 'DAV:'});
66 | for (var i in resp) {
67 | var el = resp[i];
68 | var href = el.get("a:href", { a: 'DAV:'});
69 | var dspn = el.get("a:propstat/a:prop/a:displayname", { a: 'DAV:'});
70 | if (dspn) {
71 | var resobj = {};
72 | resobj.displayName = dspn.text();
73 | resobj.href = href.text();
74 | reslist.push(resobj);
75 | }
76 | }
77 | }
78 | catch (e) {
79 | console.log("Error parsing response")
80 | }
81 |
82 | cb(reslist);
83 |
84 | });
85 | });
86 |
87 | req.end(xml);
88 |
89 | req.on('error', function (e) {
90 | console.log('problem with request: ' + e.message);
91 | });
92 |
93 | },
94 |
95 | /**
96 | * Get a list of Events from a given Calendarurl
97 | *
98 | * @param {String} url
99 | * @param {String} user
100 | * @param {String} pass
101 | * @param {String} date from which to start like 20140101T120000Z
102 | * @param {String} date from which to stop like 20140102T120000Z, optional (can be undefined)
103 | * @param {function} cb
104 |
105 | */
106 | getEvents: function (url, user, pass, start, end, cb) {
107 |
108 | var urlparts = /(https?)\:\/\/(.*?):?(\d*)?(\/.*\/?)/gi.exec(url);
109 | var protocol = urlparts[1];
110 | var host = urlparts[2];
111 | var port = urlparts[3] || (protocol === "https" ? 443 : 80);
112 | var path = urlparts[4];
113 | var endTimeRange = (end) ? ' end="'+end+'"' : "";
114 |
115 | var xml = '\n' +
116 | '\n' +
117 | ' \n' +
118 | ' \n' +
119 | ' \n' +
120 | ' \n' +
121 | ' \n' +
122 | ' \n' +
123 | ' \n' +
124 | ' \n' +
125 | ' \n' +
126 | ' \n' +
127 | '';
128 |
129 | var options = {
130 | rejectUnauthorized: false,
131 | hostname : host,
132 | port : port,
133 | path : path,
134 | method : 'REPORT',
135 | headers : {
136 | "Content-type" : "text/xml",
137 | "Content-Length": xml.length,
138 | "User-Agent" : "calDavClient",
139 | "Connection" : "close",
140 | "Depth" : "1"
141 | }
142 | };
143 |
144 | if (user && pass) {
145 | var userpass = new Buffer(user + ":" + pass).toString('base64');
146 | options.headers["Authorization"] = "Basic " + userpass;
147 | }
148 |
149 | var req = https.request(options, function (res) {
150 | var s = "";
151 | res.on('data', function (chunk) {
152 | s += chunk;
153 | });
154 |
155 | req.on('close', function () {
156 | var reslist = [];
157 | try {
158 | var xmlDoc = xmljs.parseXml(s);
159 | // console.log(xmlDoc.toString() );
160 | var data = xmlDoc.find("a:response/a:propstat/a:prop/c:calendar-data", { a: 'DAV:', c: "urn:ietf:params:xml:ns:caldav" });
161 | for (var i in data) {
162 | var ics = data[i].text();
163 | var evs = ics.match(/BEGIN:VEVENT[\s\S]*END:VEVENT/gi);
164 | for (var x in evs) {
165 | var evobj = {};
166 | var evstr = evs[x];
167 | evstr = evstr.split("\n");
168 | for (var y in evstr) {
169 | var evpropstr = evstr[y];
170 | if (evpropstr.match(/BEGIN:|END:/gi)) {
171 | continue;
172 | }
173 | var sp = evpropstr.split(":");
174 | var key = sp[0];
175 | var val = sp[1];
176 | if (key && val) {
177 | evobj[key] = val;
178 | }
179 |
180 | }
181 | reslist.push(evobj)
182 | }
183 |
184 | }
185 | cb(reslist);
186 | }
187 | catch (e) {
188 | console.log("Error parsing response")
189 | }
190 |
191 | });
192 | });
193 |
194 | req.end(xml);
195 |
196 | req.on('error', function (e) {
197 | console.log('problem with request: ' + e.message);
198 | });
199 |
200 | }
201 | };
202 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "node-caldav",
3 | "version": "0.0.2",
4 | "description": "A lightweight node.js Caldav Client",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "repository": {
10 | "type": "git",
11 | "url": "https://github.com/jachwe/node-caldav.git"
12 | },
13 | "keywords": [
14 | "caldav",
15 | "calendar",
16 | "json",
17 | "ics"
18 | ],
19 | "dependencies": {
20 | "libxmljs": "0.10.0"
21 | },
22 | "author": "Jewe Pasch",
23 | "license": "MIT",
24 | "bugs": {
25 | "url": "https://github.com/jachwe/node-caldav/issues"
26 | },
27 | "homepage": "https://github.com/jachwe/node-caldav"
28 | }
29 |
--------------------------------------------------------------------------------