/* * Copyright (C) 2016 Andy Spencer * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include "util.h" #include "conf.h" #include "date.h" #include "cal.h" /* Local Types */ typedef struct ews_t { cal_t cal; struct ews_t *next; // Config char *username; char *password; char *location; char *domain; // Parsing CURL *curl; XML_Parser expat; 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 = "\n" "\n" " \n" " \n" " \n" " IdOnly\n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" "\n" ; /* Local functions */ static void on_start(void *_cal, const char *tag, const char **attrs) { ews_t *cal = _cal; /* Debug print */ if (cal->debug) { printf("%*s%s\n", cal->indent*4, "", tag); for (int i = 0; attrs[i]; i += 2) { printf("%*s %s=\"%s\"\n", cal->indent*4+6, "--", attrs[i+0], attrs[i+1]); attrs+=2; } cal->indent++; } } static void on_end(void *_cal, const char *tag) { ews_t *cal = _cal; /* Debug print */ if (cal->debug) { if (cal->buf.len) printf("%*s \"%s\"\n", cal->indent*4+2, "--", (char*)cal->buf.data); cal->indent--; } /* Parse items */ cal->buf.len = 0; } static void on_data(void *_cal, const char *data, int len) { ews_t *cal = _cal; if (cal->debug) append(&cal->buf, data, len); } static size_t on_write(void *buf, size_t size, size_t n, ews_t *cal) { int len = size * n; XML_Parse(cal->expat, buf, len, 0); 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(" desc = %s", cal->cal.desc); debug(" username = %s", cal->username); debug(" password = %s", cal->password); debug(" location = %s", cal->location); debug(" domain = %s", cal->domain); /* Setup Expat */ if (!(cal->expat = XML_ParserCreate(NULL))) error("XML Parser Create"); XML_SetUserData(cal->expat, cal); XML_SetStartElementHandler(cal->expat, on_start); XML_SetEndElementHandler(cal->expat, on_end); XML_SetCharacterDataHandler(cal->expat, on_data); /* 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"); /* Cleanup */ curl_easy_cleanup(cal->curl); XML_ParserFree(cal->expat); } /* Config parser */ void ews_config(const char *group, const char *name, const char *key, const char *value) { ews_t *cal = NULL, *last = NULL; /* Make sure it's valid */ if (!match(group, "ews") || !name) return; /* Find existing calendar */ for (cal = calendars; cal; last = cal, cal = cal->next) if (match(cal->cal.name, name)) break; /* Create new calendar */ if (!cal) { cal = new0(ews_t); cal->cal.type = "ews"; cal->cal.name = get_name(name); if (last) last->next = cal; else calendars = cal; } /* Set calendar values */ if (match(key, "location")) cal->location = get_string(value); else if (match(key, "username")) cal->username = get_string(value); else if (match(key, "password")) cal->password = get_string(value); else if (match(key, "domain")) cal->domain = get_string(value); } /* Cal functions */ cal_t *ews_cals(void) { for (ews_t *cal = calendars; cal; cal = cal->next) { sync_ews(cal); cal->cal.next = &cal->next->cal; } return &calendars->cal; } /* Event functions */ event_t *ews_events(date_t start, date_t end) { return NULL; } /* Todo functions */ todo_t *ews_todos(date_t start, date_t end) { return NULL; } /* 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"); }