From: David Woodhouse Date: Sun, 18 Jul 2010 12:55:51 +0000 (+0100) Subject: Attempt to process timezones using ical X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=bc3fab8cb49fb7d419a78603282cb8132b4f4d46;p=users%2Fdwmw2%2Fews-sync.git Attempt to process timezones using ical --- diff --git a/Makefile b/Makefile index ffab257..b5f7120 100644 --- a/Makefile +++ b/Makefile @@ -17,8 +17,15 @@ ifeq ($(SOUP_LDFLAGS),) $(error "No libsoup support. Cannot continue"); endif +ICAL_CFLAGS += $(shell pkg-config libical --cflags) +ICAL_LDFLAGS += $(shell pkg-config libical --libs) +ifeq ($(ICAL_LDFLAGS),) +$(error "No libical support. Cannot continue"); +endif + CFLAGS := $(OPT_FLAGS) $(XML2_CFLAGS) CFLAGS_ews_autodiscover.o := $(SOUP_CFLAGS) +CFLAGS_ews2ical.o := $(ICAL_CFLAGS) %.o: %.c $(CC) -c -o $@ $(CFLAGS) $(CFLAGS_$@) $< -MD -MF .$@.dep @@ -26,7 +33,7 @@ CFLAGS_ews_autodiscover.o := $(SOUP_CFLAGS) all: ews_autodiscover ews2ical ews2ical: ews2ical.o - $(CC) -o $@ $< $(LDFLAGS) $(XML2_LDFLAGS) + $(CC) -o $@ $< $(LDFLAGS) $(XML2_LDFLAGS) $(ICAL_LDFLAGS) ews_autodiscover: ews_autodiscover.o $(CC) -o $@ $< $(LDFLAGS) $(XML2_LDFLAGS) $(SOUP_LDFLAGS) diff --git a/ews2ical.c b/ews2ical.c index 5688112..4241728 100644 --- a/ews2ical.c +++ b/ews2ical.c @@ -9,26 +9,27 @@ #include #include #include - +#include +#include FILE *calfile; int process_organizer(xmlNode *xml_node); int process_required_attendees(xmlNode *xml_node); -int process_start(xmlNode *xml_node, const char *zone); -int process_end(xmlNode *xml_node, const char *zone); +int process_start(xmlNode *xml_node, icaltimezone *zone); +int process_end(xmlNode *xml_node, icaltimezone *zone); int process_location(xmlNode *xml_node); int process_body(xmlNode *xml_node); int process_subject(xmlNode *xml_node); int process_recurrence(xmlNode *xml_node); int process_itemid(xmlNode *xmlnode); -const char *set_timezone(xmlNode *xmlnode); +icaltimezone *get_timezone(xmlNode *xmlnode); int main(int argc, char **argv) { xmlDocPtr xml_doc; xmlNode *xml_node; - const char *tzname; + icaltimezone *icaltz; int xmlfd = 0; /* stdin */ char buf[1]; @@ -127,9 +128,15 @@ int main(int argc, char **argv) fprintf(calfile, "BEGIN:VCALENDAR\n"); fprintf(calfile, "METHOD:PUBLISH\n"); fprintf(calfile, "VERSION:2.0\n"); - fprintf(calfile, "BEGIN:VEVENT\n"); - tzname = set_timezone(xml_node); + icaltz = get_timezone(xml_node); + if (icaltz) { + icalcomponent *comp = icaltimezone_get_component(icaltz); + char *vtz = icalcomponent_as_ical_string_r(comp); + printf("%s", vtz); + free(vtz); + } + fprintf(calfile, "BEGIN:VEVENT\n"); for (xml_node = xml_node->children; xml_node; xml_node = xml_node->next) { if (xml_node->type != XML_ELEMENT_NODE) @@ -139,9 +146,9 @@ int main(int argc, char **argv) else if (!strcmp((char *)xml_node->name, "RequiredAttendees")) process_required_attendees(xml_node); else if (!strcmp((char *)xml_node->name, "Start")) - process_start(xml_node, tzname); + process_start(xml_node, icaltz); else if (!strcmp((char *)xml_node->name, "End")) - process_end(xml_node, tzname); + process_end(xml_node, icaltz); else if (!strcmp((char *)xml_node->name, "Body")) process_body(xml_node); else if (!strcmp((char *)xml_node->name, "Location")) @@ -232,9 +239,10 @@ int process_required_attendees(xmlNode *xml_node) return 0; } -int process_time(xmlNode *xml_node, const char *name, const char *zone) +int process_time(xmlNode *xml_node, const char *name, icaltimezone *zone) { char *ews_time = (char *)xmlNodeGetContent(xml_node); + struct icaltimetype ical_time; struct tm tm_time; time_t t; @@ -250,38 +258,33 @@ int process_time(xmlNode *xml_node, const char *name, const char *zone) memset(&tm_time, 0, sizeof(tm_time)); tm_time.tm_year = strtol(ews_time, NULL, 10); - tm_time.tm_mon = strtol(ews_time + 5, NULL, 10); + tm_time.tm_mon = strtol(ews_time + 5, NULL, 10) - 1; tm_time.tm_mday = strtol(ews_time + 8, NULL, 10); tm_time.tm_hour = strtol(ews_time + 11, NULL, 10); tm_time.tm_min = strtol(ews_time + 14, NULL, 10); tm_time.tm_sec = strtol(ews_time + 17, NULL, 10); t = timegm(&tm_time); - - /* Now we have a number of seconds since epoch in UTC; convert - to the time zone we're using. Would be nice if there was a - sane way to do this which didn't involve setting $TZ for the - whole application -- we'll care about that when we're a plugin - for something else rather than running standalone. */ - - localtime_r(&t, &tm_time); + ical_time = icaltime_from_timet_with_zone(t, 0, zone?:icaltimezone_get_utc_timezone()); + ical_time.year -= 1900; fprintf(calfile, "%s", name); + if (zone) - fprintf(calfile, ";TZID=%s", zone); + fprintf(calfile, ";TZID=%s", icaltimezone_get_tzid(zone)); fprintf(calfile, ":%04d%02d%02d%02d%02d%02d%s\n", - tm_time.tm_year, tm_time.tm_mon, tm_time.tm_mday, - tm_time.tm_hour, tm_time.tm_min, tm_time.tm_sec, + ical_time.year, ical_time.month, ical_time.day, + ical_time.hour, ical_time.minute, ical_time.second, zone?"":"Z"); return 0; } -int process_start(xmlNode *xml_node, const char *zone) +int process_start(xmlNode *xml_node, icaltimezone *zone) { return process_time(xml_node, "DTSTART", zone); } -int process_end(xmlNode *xml_node, const char *zone) +int process_end(xmlNode *xml_node, icaltimezone *zone) { return process_time(xml_node, "DTEND", zone); } @@ -659,6 +662,10 @@ static const char *ews_tz_to_ical(const char *ewstz) { "(UTC-10:00) Hawaii", "Pacific/Honolulu" }, { "(UTC-11:00) Midway Island, Samoa", "Pacific/Midway" }, /* ? */ { "(UTC-12:00) International Date Line West", "Pacific/Apia" }, + + + +// { "Pacific Standard Time", "America/Los_Angeles" }, }; int i; int offset = 0; @@ -680,23 +687,37 @@ static const char *ews_tz_to_ical(const char *ewstz) } -const char *set_timezone(xmlNode *xml_node) +icaltimezone *get_timezone(xmlNode *xml_node) { + icaltimezone *zone = NULL; + const char *ews_tzname = NULL; const char *tzname = NULL; -#if 0 + for (xml_node = xml_node->children; xml_node; xml_node = xml_node->next) { if (xml_node->type != XML_ELEMENT_NODE) continue; else if (!strcmp((char *)xml_node->name, "TimeZone")) break; } - if (xml_node) - tzname = ews_tz_to_ical((char *)xmlNodeGetContent(xml_node)); -#endif - if (tzname) - setenv("TZ", tzname, 1); - else - setenv("TZ", "UTC", 1); - tzset(); - return tzname; + if (!xml_node) { + fprintf(stderr, "Failed to find TimeZone element; falling back to UTC\n"); + return NULL; + } + + ews_tzname = (char *)xmlNodeGetContent(xml_node); + + /* FIXME: Look for manual timezone definitions in the XML and compare against + those first, before using the standard Windows ones */ + + tzname = ews_tz_to_ical(ews_tzname); + if (!tzname) + return NULL; + + zone = icaltimezone_get_builtin_timezone(tzname); + if (zone) + return zone; + + fprintf(stderr, "Failed to load ical timezone for '%s' (%s)\n", tzname, + ews_tzname); + return NULL; }