2 * Copyright (C) 2016 Andy Spencer <andy753421@gmail.com>
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include <curl/curl.h>
28 typedef struct ews_t {
48 static ews_t *calendars;
52 static char *req_calendar =
53 "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
54 "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
55 " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n"
56 " xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"\n"
57 " xmlns:t=\"http://schemas.microsoft.com/exchange/services/2006/types\"\n"
58 " xmlns:m=\"http://schemas.microsoft.com/exchange/services/2006/messages\">\n"
60 " <m:FindItem Traversal=\"Shallow\">\n"
62 " <t:BaseShape>IdOnly</t:BaseShape>\n"
63 " <t:AdditionalProperties>\n"
64 " <t:FieldURI FieldURI=\"calendar:CalendarItemType\" />\n"
65 " <t:FieldURI FieldURI=\"calendar:Start\" />\n"
66 " <t:FieldURI FieldURI=\"calendar:End\" />\n"
67 " <t:FieldURI FieldURI=\"item:ItemClass\" />\n"
68 " <t:FieldURI FieldURI=\"item:Subject\" />\n"
69 " </t:AdditionalProperties>\n"
71 " <m:CalendarView StartDate=\"2016-01-01T00:00:00-00:00\"\n"
72 " EndDate=\"2018-01-01T00:00:00-00:00\"\n"
73 " MaxEntriesReturned=\"1000\" />\n"
74 " <m:ParentFolderIds>\n"
75 " <t:DistinguishedFolderId Id=\"calendar\" />\n"
76 " </m:ParentFolderIds>\n"
83 static void dump_xml(const char *buf, int len)
86 for (int i = 0; i < len; i++) {
87 const char prev = i>0 ? buf[i-1] : '\0';
88 const char this = buf[i];
89 const char next = i<len ? buf[i+1] : '\0';
90 if (this == '<' && next == '/')
92 if (this == '<' && prev == '>') {
94 for (int j = 0; j < indent*4; j++)
97 if (this == '>' && prev == '/')
99 if (this == '<' && next != '/' && next != '?')
106 static size_t on_write(void *buf, size_t size, size_t n, ews_t *cal)
109 append(&cal->buf, buf, len);
113 static void sync_ews(ews_t *cal)
117 struct curl_slist *hdr = NULL;
120 debug("Loading EWS:");
121 debug(" type = %s", cal->cal.type);
122 debug(" name = %s", cal->cal.name);
123 debug(" desc = %s", cal->cal.desc);
124 debug(" username = %s", cal->username);
125 debug(" password = %s", cal->password);
126 debug(" location = %s", cal->location);
127 debug(" domain = %s", cal->domain);
129 /* Setup HTTP request */
130 if (!(cal->curl = curl_easy_init()))
131 error("Curl easy init failed");
132 if (curl_easy_setopt(cal->curl, CURLOPT_URL, cal->location))
133 error("Curl easy setopt failed");
134 if (curl_easy_setopt(cal->curl, CURLOPT_WRITEFUNCTION, on_write))
135 error("Curl easy set write function failed");
136 if (curl_easy_setopt(cal->curl, CURLOPT_WRITEDATA, cal))
137 error("Curl easy set write data failed");
139 /* Skip SSL checks */
140 if (curl_easy_setopt(cal->curl, CURLOPT_SSL_VERIFYPEER, 0L))
141 error("Curl easy set no verify peer failed");
142 if (curl_easy_setopt(cal->curl, CURLOPT_SSL_VERIFYHOST, 0L))
143 error("Curl easy set no verify hosts failed");
146 if (curl_easy_setopt(cal->curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY))
147 error("Curl easy set http auth failed");
148 if (curl_easy_setopt(cal->curl, CURLOPT_USERNAME, cal->username))
149 error("Curl easy set username failed");
150 if (curl_easy_setopt(cal->curl, CURLOPT_PASSWORD, cal->password))
151 error("Curl easy set password failed");
153 /* Setup SOAP request */
154 hdr = curl_slist_append(hdr, "Accept: text/xml");
155 hdr = curl_slist_append(hdr, "Content-Type: text/xml");
156 if (curl_easy_setopt(cal->curl, CURLOPT_HTTPHEADER, hdr))
157 error("Curl easy set http header failed");
158 if (curl_easy_setopt(cal->curl, CURLOPT_POST, 1L))
159 error("Curl easy set post failed");
160 if (curl_easy_setopt(cal->curl, CURLOPT_POSTFIELDS, req_calendar))
161 error("Curl easy set post failed");
164 if ((err = curl_easy_perform(cal->curl)))
165 error("Curl easy perform failed: %s", curl_easy_strerror(err));
166 if ((err = curl_easy_getinfo(cal->curl, CURLINFO_RESPONSE_CODE, &status)))
167 error("Curl easy get info failed: %s", curl_easy_strerror(err));
169 /* Output response */
171 printf("EWS -- HTTP Status %ld\n", status);
172 if (cal->debug && !cal->buf.data)
173 printf("EWS -- No Response Data\n");
175 dump_xml(cal->buf.data, cal->buf.len);
178 curl_easy_cleanup(cal->curl);
183 void ews_config(const char *group, const char *name, const char *key, const char *value)
185 ews_t *cal = NULL, *last = NULL;
187 /* Make sure it's valid */
188 if (!match(group, "ews") || !name)
191 /* Find existing calendar */
192 for (cal = calendars; cal; last = cal, cal = cal->next)
193 if (match(cal->cal.name, name))
196 /* Create new calendar */
199 cal->cal.type = "ews";
200 cal->cal.name = get_name(name);
207 /* Set calendar values */
208 if (match(key, "location"))
209 cal->location = get_string(value);
210 else if (match(key, "username"))
211 cal->username = get_string(value);
212 else if (match(key, "password"))
213 cal->password = get_string(value);
214 else if (match(key, "domain"))
215 cal->domain = get_string(value);
219 cal_t *ews_cals(void)
221 for (ews_t *cal = calendars; cal; cal = cal->next) {
223 cal->cal.next = &cal->next->cal;
226 return &calendars->cal;
229 /* Event functions */
230 event_t *ews_events(date_t start, date_t end)
236 todo_t *ews_todos(date_t start, date_t end)
242 void ews_test(char *url, char *user, char *pass)
246 .username = user && user[0] ? user : NULL,
247 .password = pass && pass[0] ? pass : NULL,
252 printf("EWS -- test start\n");
253 if (curl_global_init(CURL_GLOBAL_DEFAULT))
254 error("Curl global init failed");
255 if (!(curlm = curl_multi_init()))
256 error("Curl multi init failed");
258 /* Sync the calendar */
262 curl_multi_cleanup(curlm);
263 curl_global_cleanup();
264 printf("EWS -- test end\n");