#include <stdio.h>
+#include <curl/curl.h>
+
#include "util.h"
#include "conf.h"
#include "date.h"
char *password;
char *location;
char *domain;
+
+ // Parsing
+ CURL *curl;
+ buf_t buf;
+
+ // Debugging
+ int debug;
+ int indent;
} ews_t;
/* Static data */
static ews_t *calendars;
+static CURLM *curlm;
+
+/* SOAP Requests */
+static char *req_calendar =
+ "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
+ "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
+ " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n"
+ " xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"\n"
+ " xmlns:t=\"http://schemas.microsoft.com/exchange/services/2006/types\"\n"
+ " xmlns:m=\"http://schemas.microsoft.com/exchange/services/2006/messages\">\n"
+ " <soap:Body>\n"
+ " <m:FindItem Traversal=\"Shallow\">\n"
+ " <m:ItemShape>\n"
+ " <t:BaseShape>IdOnly</t:BaseShape>\n"
+ " <t:AdditionalProperties>\n"
+ " <t:FieldURI FieldURI=\"calendar:CalendarItemType\" />\n"
+ " <t:FieldURI FieldURI=\"calendar:Start\" />\n"
+ " <t:FieldURI FieldURI=\"calendar:End\" />\n"
+ " <t:FieldURI FieldURI=\"item:ItemClass\" />\n"
+ " <t:FieldURI FieldURI=\"item:Subject\" />\n"
+ " </t:AdditionalProperties>\n"
+ " </m:ItemShape>\n"
+ " <m:CalendarView StartDate=\"2016-01-01T00:00:00-00:00\"\n"
+ " EndDate=\"2018-01-01T00:00:00-00:00\"\n"
+ " MaxEntriesReturned=\"1000\" />\n"
+ " <m:ParentFolderIds>\n"
+ " <t:DistinguishedFolderId Id=\"calendar\" />\n"
+ " </m:ParentFolderIds>\n"
+ " </m:FindItem>\n"
+ " </soap:Body>\n"
+ "</soap:Envelope>\n"
+;
/* Local functions */
+static void dump_xml(const char *buf, int len)
+{
+ int indent = 0;
+ for (int i = 0; i < len; i++) {
+ const char prev = i>0 ? buf[i-1] : '\0';
+ const char this = buf[i];
+ const char next = i<len ? buf[i+1] : '\0';
+ if (this == '<' && next == '/')
+ indent--;
+ if (this == '<' && prev == '>') {
+ putchar('\n');
+ for (int j = 0; j < indent*4; j++)
+ putchar(' ');
+ }
+ if (this == '>' && prev == '/')
+ indent--;
+ if (this == '<' && next != '/' && next != '?')
+ indent++;
+ putchar(buf[i]);
+ }
+ putchar('\n');
+}
+
+static size_t on_write(void *buf, size_t size, size_t n, ews_t *cal)
+{
+ int len = size * n;
+ append(&cal->buf, buf, len);
+ return len;
+}
+
static void sync_ews(ews_t *cal)
{
+ CURLcode err;
+ long status;
+ struct curl_slist *hdr = NULL;
+
+ /* Debug output */
debug("Loading EWS:");
debug(" type = %s", cal->cal.type);
debug(" name = %s", cal->cal.name);
debug(" password = %s", cal->password);
debug(" location = %s", cal->location);
debug(" domain = %s", cal->domain);
+
+ /* Setup HTTP request */
+ if (!(cal->curl = curl_easy_init()))
+ error("Curl easy init failed");
+ if (curl_easy_setopt(cal->curl, CURLOPT_URL, cal->location))
+ error("Curl easy setopt failed");
+ if (curl_easy_setopt(cal->curl, CURLOPT_WRITEFUNCTION, on_write))
+ error("Curl easy set write function failed");
+ if (curl_easy_setopt(cal->curl, CURLOPT_WRITEDATA, cal))
+ error("Curl easy set write data failed");
+
+ /* Skip SSL checks */
+ if (curl_easy_setopt(cal->curl, CURLOPT_SSL_VERIFYPEER, 0L))
+ error("Curl easy set no verify peer failed");
+ if (curl_easy_setopt(cal->curl, CURLOPT_SSL_VERIFYHOST, 0L))
+ error("Curl easy set no verify hosts failed");
+
+ /* Set login info */
+ if (curl_easy_setopt(cal->curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY))
+ error("Curl easy set http auth failed");
+ if (curl_easy_setopt(cal->curl, CURLOPT_USERNAME, cal->username))
+ error("Curl easy set username failed");
+ if (curl_easy_setopt(cal->curl, CURLOPT_PASSWORD, cal->password))
+ error("Curl easy set password failed");
+
+ /* Setup SOAP request */
+ hdr = curl_slist_append(hdr, "Accept: text/xml");
+ hdr = curl_slist_append(hdr, "Content-Type: text/xml");
+ if (curl_easy_setopt(cal->curl, CURLOPT_HTTPHEADER, hdr))
+ error("Curl easy set http header failed");
+ if (curl_easy_setopt(cal->curl, CURLOPT_POST, 1L))
+ error("Curl easy set post failed");
+ if (curl_easy_setopt(cal->curl, CURLOPT_POSTFIELDS, req_calendar))
+ error("Curl easy set post failed");
+
+ /* Curl Easy */
+ if ((err = curl_easy_perform(cal->curl)))
+ error("Curl easy perform failed: %s", curl_easy_strerror(err));
+ if ((err = curl_easy_getinfo(cal->curl, CURLINFO_RESPONSE_CODE, &status)))
+ error("Curl easy get info failed: %s", curl_easy_strerror(err));
+
+ /* Output response */
+ if (cal->debug)
+ printf("EWS -- HTTP Status %ld\n", status);
+ if (cal->debug && !cal->buf.data)
+ printf("EWS -- No Response Data\n");
+ if (cal->debug)
+ dump_xml(cal->buf.data, cal->buf.len);
+
+ /* Cleanup */
+ curl_easy_cleanup(cal->curl);
+ release(&cal->buf);
}
/* Config parser */
/* Test functions */
void ews_test(char *url, char *user, char *pass)
{
+ ews_t cal = {
+ .location = url,
+ .username = user && user[0] ? user : NULL,
+ .password = pass && pass[0] ? pass : NULL,
+ .debug = 1,
+ };
+
+ /* Setup CURL */
printf("EWS -- test start\n");
+ if (curl_global_init(CURL_GLOBAL_DEFAULT))
+ error("Curl global init failed");
+ if (!(curlm = curl_multi_init()))
+ error("Curl multi init failed");
+
+ /* Sync the calendar */
+ sync_ews(&cal);
+
+ /* Cleanup */
+ curl_multi_cleanup(curlm);
+ curl_global_cleanup();
printf("EWS -- test end\n");
}