* When translating the input from a REGI command into a vCard, set the telephone...
[citadel.git] / citadel / ical_dezonify.c
blob776fe8634a1ff5e73d69539ba8b47d9bd8c1498e
1 /*
2 * $Id$
4 * Function to go through an ical component set and convert all non-UTC
5 * date/time properties to UTC. It also strips out any VTIMEZONE
6 * subcomponents afterwards, because they're irrelevant.
8 */
11 #include "sysdep.h"
12 #include <stdlib.h>
13 #include <unistd.h>
14 #include <sys/types.h>
15 #include <limits.h>
16 #include <stdio.h>
17 #include <string.h>
18 #include <strings.h>
19 #include <libical/ical.h>
20 #include <libcitadel.h>
21 #include "citadel.h"
22 #include "server.h"
23 #include "citserver.h"
24 #include "sysdep_decls.h"
25 #include "support.h"
26 #include "config.h"
27 #include "ical_dezonify.h"
31 * Figure out which time zone needs to be used for timestamps that are
32 * not UTC and do not have a time zone specified.
34 icaltimezone *get_default_icaltimezone(void) {
36 icaltimezone *zone = NULL;
37 char *default_zone_name = config.c_default_cal_zone;
38 //char *default_zone_name = "America/New_York";
40 if (!zone) {
41 zone = icaltimezone_get_builtin_timezone(default_zone_name);
43 if (!zone) {
44 CtdlLogPrintf(CTDL_ALERT,
45 "Unable to load '%s' time zone. Defaulting to UTC.\n",
46 default_zone_name);
47 zone = icaltimezone_get_utc_timezone();
49 if (!zone) {
50 CtdlLogPrintf(1, "Unable to load UTC time zone!\n");
52 return zone;
57 * Back end function for ical_dezonify()
59 * We supply this with the master component, the relevant component,
60 * and the property (which will be a DTSTART, DTEND, etc.)
61 * which we want to convert to UTC.
63 void ical_dezonify_backend(icalcomponent *cal,
64 icalcomponent *rcal,
65 icalproperty *prop) {
67 icaltimezone *t = NULL;
68 icalparameter *param;
69 const char *tzid = NULL;
70 struct icaltimetype TheTime;
71 int utc_declared_as_tzid = 0; /**< Component declared 'TZID=GMT' instead of using Z syntax */
73 /* Give me nothing and I will give you nothing in return. */
74 if (cal == NULL) return;
76 /* Hunt for a TZID parameter in this property. */
77 param = icalproperty_get_first_parameter(prop, ICAL_TZID_PARAMETER);
79 /* Get the stringish name of this TZID. */
80 if (param != NULL) {
81 tzid = icalparameter_get_tzid(param);
83 /* Convert it to an icaltimezone type. */
84 if (tzid != NULL) {
85 /* CtdlLogPrintf(9, " * Stringy supplied timezone is: '%s'\n", tzid); */
86 if ( (!strcasecmp(tzid, "UTC")) || (!strcasecmp(tzid, "GMT")) ) {
87 utc_declared_as_tzid = 1;
88 /* CtdlLogPrintf(9, " * ...and we handle that internally.\n"); */
90 else {
91 /* try attached first */
92 t = icalcomponent_get_timezone(cal, tzid);
94 lprintf(9, " * ...and I %s have tzdata for that zone.\n",
95 (t ? "DO" : "DO NOT")
98 /* then try built-in timezones */
99 if (!t) {
100 t = icaltimezone_get_builtin_timezone(tzid);
102 if (t) {
103 lprintf(9, " * Using system tzdata!\n");
112 /* Now we know the timezone. Convert to UTC. */
114 if (icalproperty_isa(prop) == ICAL_DTSTART_PROPERTY) {
115 TheTime = icalproperty_get_dtstart(prop);
117 else if (icalproperty_isa(prop) == ICAL_DTEND_PROPERTY) {
118 TheTime = icalproperty_get_dtend(prop);
120 else if (icalproperty_isa(prop) == ICAL_DUE_PROPERTY) {
121 TheTime = icalproperty_get_due(prop);
123 else if (icalproperty_isa(prop) == ICAL_EXDATE_PROPERTY) {
124 TheTime = icalproperty_get_exdate(prop);
126 else {
127 return;
130 /* CtdlLogPrintf(9, " * Was: %s\n", icaltime_as_ical_string(TheTime)); */
132 if (TheTime.is_utc) {
133 /* CtdlLogPrintf(9, " * This property is ALREADY UTC.\n"); */
136 else if (utc_declared_as_tzid) {
137 /* CtdlLogPrintf(9, " * Replacing '%s' TZID with 'Z' suffix.\n", tzid); */
138 TheTime.is_utc = 1;
141 else {
142 /* Do the conversion. */
143 if (t != NULL) {
144 /* CtdlLogPrintf(9, " * Timezone prop found. Converting to UTC.\n"); */
146 else {
147 /* CtdlLogPrintf(9, " * Converting default timezone to UTC.\n"); */
150 if (t == NULL) {
151 t = get_default_icaltimezone();
154 icaltimezone_convert_time(&TheTime,
156 icaltimezone_get_utc_timezone()
158 TheTime.is_utc = 1;
161 icalproperty_remove_parameter_by_kind(prop, ICAL_TZID_PARAMETER);
162 /* CtdlLogPrintf(9, " * Now: %s\n", icaltime_as_ical_string(TheTime)); */
164 /* Now add the converted property back in. */
165 if (icalproperty_isa(prop) == ICAL_DTSTART_PROPERTY) {
166 icalproperty_set_dtstart(prop, TheTime);
168 else if (icalproperty_isa(prop) == ICAL_DTEND_PROPERTY) {
169 icalproperty_set_dtend(prop, TheTime);
171 else if (icalproperty_isa(prop) == ICAL_DUE_PROPERTY) {
172 icalproperty_set_due(prop, TheTime);
174 else if (icalproperty_isa(prop) == ICAL_EXDATE_PROPERTY) {
175 icalproperty_set_exdate(prop, TheTime);
181 * Recursive portion of ical_dezonify()
183 void ical_dezonify_recurse(icalcomponent *cal, icalcomponent *rcal) {
184 icalcomponent *c;
185 icalproperty *p;
188 * Recurse through all subcomponents *except* VTIMEZONE ones.
190 for (c=icalcomponent_get_first_component(
191 rcal, ICAL_ANY_COMPONENT);
192 c != NULL;
193 c = icalcomponent_get_next_component(
194 rcal, ICAL_ANY_COMPONENT)
196 if (icalcomponent_isa(c) != ICAL_VTIMEZONE_COMPONENT) {
197 ical_dezonify_recurse(cal, c);
202 * Now look for DTSTART and DTEND properties
204 for (p=icalcomponent_get_first_property(rcal, ICAL_ANY_PROPERTY);
205 p != NULL;
206 p = icalcomponent_get_next_property(rcal, ICAL_ANY_PROPERTY)
208 if (
209 (icalproperty_isa(p) == ICAL_DTSTART_PROPERTY)
210 || (icalproperty_isa(p) == ICAL_DTEND_PROPERTY)
211 || (icalproperty_isa(p) == ICAL_DUE_PROPERTY)
212 || (icalproperty_isa(p) == ICAL_EXDATE_PROPERTY)
214 ical_dezonify_backend(cal, rcal, p);
221 * Convert all DTSTART and DTEND properties in all subcomponents to UTC.
222 * This function will search any VTIMEZONE subcomponents to learn the
223 * relevant timezone information.
225 void ical_dezonify(icalcomponent *cal) {
226 icalcomponent *vt = NULL;
228 /* CtdlLogPrintf(9, "ical_dezonify() started\n"); */
230 /* Convert all times to UTC */
231 ical_dezonify_recurse(cal, cal);
233 /* Strip out VTIMEZONE subcomponents -- we don't need them anymore */
234 while (vt = icalcomponent_get_first_component(
235 cal, ICAL_VTIMEZONE_COMPONENT), vt != NULL) {
236 icalcomponent_remove_component(cal, vt);
237 icalcomponent_free(vt);
240 /* CtdlLogPrintf(9, "ical_dezonify() completed\n"); */