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 * Everything here will work on both a fully encapsulated VCALENDAR component
9 * or any type of subcomponent.
14 #include "webserver.h"
17 * Figure out which time zone needs to be used for timestamps that are
18 * not UTC and do not have a time zone specified.
21 icaltimezone
*get_default_icaltimezone(void) {
23 icaltimezone
*zone
= NULL
;
24 const char *default_zone_name
= ChrPtr(serv_info
.serv_default_cal_zone
);
27 zone
= icaltimezone_get_builtin_timezone(default_zone_name
);
30 lprintf(1, "Unable to load '%s' time zone. Defaulting to UTC.\n", default_zone_name
);
31 zone
= icaltimezone_get_utc_timezone();
34 lprintf(1, "Unable to load UTC time zone!\n");
41 * Back end function for ical_dezonify()
43 * We supply this with the master component, the relevant component,
44 * and the property (which will be a DTSTART, DTEND, etc.)
45 * which we want to convert to UTC.
47 void ical_dezonify_backend(icalcomponent
*cal
,
51 icaltimezone
*t
= NULL
;
53 const char *tzid
= NULL
;
54 struct icaltimetype TheTime
;
55 int utc_declared_as_tzid
= 0; /* Component declared 'TZID=GMT' instead of using Z syntax */
57 /* Give me nothing and I will give you nothing in return. */
58 if (cal
== NULL
) return;
60 /* Hunt for a TZID parameter in this property. */
61 param
= icalproperty_get_first_parameter(prop
, ICAL_TZID_PARAMETER
);
63 /* Get the stringish name of this TZID. */
65 tzid
= icalparameter_get_tzid(param
);
67 /* Convert it to an icaltimezone type. */
70 lprintf(9, " * Stringy supplied timezone is: '%s'\n", tzid
);
72 if ( (!strcasecmp(tzid
, "UTC")) || (!strcasecmp(tzid
, "GMT")) ) {
73 utc_declared_as_tzid
= 1;
75 lprintf(9, " * ...and we handle that internally.\n");
79 /* try attached first */
80 t
= icalcomponent_get_timezone(cal
, tzid
);
82 lprintf(9, " * ...and I %s have tzdata for that zone.\n",
86 /* then try built-in timezones */
88 t
= icaltimezone_get_builtin_timezone(tzid
);
91 lprintf(9, " * Using system tzdata!\n");
100 /* Now we know the timezone. Convert to UTC. */
102 if (icalproperty_isa(prop
) == ICAL_DTSTART_PROPERTY
) {
103 TheTime
= icalproperty_get_dtstart(prop
);
105 else if (icalproperty_isa(prop
) == ICAL_DTEND_PROPERTY
) {
106 TheTime
= icalproperty_get_dtend(prop
);
108 else if (icalproperty_isa(prop
) == ICAL_DUE_PROPERTY
) {
109 TheTime
= icalproperty_get_due(prop
);
111 else if (icalproperty_isa(prop
) == ICAL_EXDATE_PROPERTY
) {
112 TheTime
= icalproperty_get_exdate(prop
);
119 lprintf(9, " * Was: %s\n", icaltime_as_ical_string(TheTime
));
122 if (TheTime
.is_utc
) {
124 lprintf(9, " * This property is ALREADY UTC.\n");
128 else if (utc_declared_as_tzid
) {
130 lprintf(9, " * Replacing '%s' TZID with 'Z' suffix.\n", tzid
);
136 /* Do the conversion. */
139 lprintf(9, " * Timezone prop found. Converting to UTC.\n");
144 lprintf(9, " * Converting default timezone to UTC.\n");
149 t
= get_default_icaltimezone();
151 icaltimezone_convert_time(&TheTime
, t
, icaltimezone_get_utc_timezone());
155 icalproperty_remove_parameter_by_kind(prop
, ICAL_TZID_PARAMETER
);
157 lprintf(9, " * Now: %s\n", icaltime_as_ical_string(TheTime
));
160 /* Now add the converted property back in. */
161 if (icalproperty_isa(prop
) == ICAL_DTSTART_PROPERTY
) {
162 icalproperty_set_dtstart(prop
, TheTime
);
164 else if (icalproperty_isa(prop
) == ICAL_DTEND_PROPERTY
) {
165 icalproperty_set_dtend(prop
, TheTime
);
167 else if (icalproperty_isa(prop
) == ICAL_DUE_PROPERTY
) {
168 icalproperty_set_due(prop
, TheTime
);
170 else if (icalproperty_isa(prop
) == ICAL_EXDATE_PROPERTY
) {
171 icalproperty_set_exdate(prop
, TheTime
);
177 * Recursive portion of ical_dezonify()
179 void ical_dezonify_recurse(icalcomponent
*cal
, icalcomponent
*rcal
) {
184 * Recurse through all subcomponents *except* VTIMEZONE ones.
186 for (c
=icalcomponent_get_first_component(
187 rcal
, ICAL_ANY_COMPONENT
);
189 c
= icalcomponent_get_next_component(
190 rcal
, ICAL_ANY_COMPONENT
)
192 if (icalcomponent_isa(c
) != ICAL_VTIMEZONE_COMPONENT
) {
193 ical_dezonify_recurse(cal
, c
);
198 * Now look for DTSTART and DTEND properties
200 for (p
=icalcomponent_get_first_property(rcal
, ICAL_ANY_PROPERTY
);
202 p
= icalcomponent_get_next_property(rcal
, ICAL_ANY_PROPERTY
)
205 (icalproperty_isa(p
) == ICAL_DTSTART_PROPERTY
)
206 || (icalproperty_isa(p
) == ICAL_DTEND_PROPERTY
)
207 || (icalproperty_isa(p
) == ICAL_DUE_PROPERTY
)
208 || (icalproperty_isa(p
) == ICAL_EXDATE_PROPERTY
)
210 ical_dezonify_backend(cal
, rcal
, p
);
217 * Convert all DTSTART and DTEND properties in all subcomponents to UTC.
218 * This function will search any VTIMEZONE subcomponents to learn the
219 * relevant timezone information.
221 void ical_dezonify(icalcomponent
*cal
) {
222 icalcomponent
*vt
= NULL
;
225 lprintf(9, "ical_dezonify() started\n");
228 /* Convert all times to UTC */
229 ical_dezonify_recurse(cal
, cal
);
231 /* Strip out VTIMEZONE subcomponents -- we don't need them anymore */
232 while (vt
= icalcomponent_get_first_component(
233 cal
, ICAL_VTIMEZONE_COMPONENT
), vt
!= NULL
) {
234 icalcomponent_remove_component(cal
, vt
);
235 icalcomponent_free(vt
);
239 lprintf(9, "ical_dezonify() completed\n");