* ical_dezonify.c: brought over new version from the Citadel source (again)
[citadel.git] / webcit / ical_dezonify.c
1 /* 
2  * $Id$ 
3  *
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.
7  *
8  */
9
10
11 #include <unistd.h>
12 #include <sys/types.h>
13 #include <limits.h>
14 #include <stdio.h>
15 #include <string.h>
16 #include <strings.h>
17 #include "webcit.h"
18
19 #ifdef HAVE_ICAL_H
20 #include <ical.h>
21
22
23 /*
24  * Back end function for ical_dezonify()
25  *
26  * We supply this with the master component, the relevant component,
27  * and the property (which will be a DTSTART, DTEND, etc.)
28  * which we want to convert to UTC.
29  */
30 void ical_dezonify_backend(icalcomponent *cal,
31                         icalcomponent *rcal,
32                         icalproperty *prop) {
33
34         icaltimezone *t = NULL;
35         icalparameter *param;
36         const char *tzid;
37         struct icaltimetype TheTime;
38
39         /* Give me nothing and I will give you nothing in return. */
40         if (cal == NULL) return;
41
42         /* Hunt for a TZID parameter in this property. */
43         param = icalproperty_get_first_parameter(prop, ICAL_TZID_PARAMETER);
44
45         /* Get the stringish name of this TZID. */
46         if (param != NULL) {
47                 tzid = icalparameter_get_tzid(param);
48
49                 /* Convert it to an icaltimezone type. */
50                 if (tzid != NULL) {
51                         t = icalcomponent_get_timezone(cal, tzid);
52                 }
53
54         }
55
56         /* Now we know the timezone.  Convert to UTC. */
57
58         if (icalproperty_isa(prop) == ICAL_DTSTART_PROPERTY) {
59                 TheTime = icalproperty_get_dtstart(prop);
60         }
61         else if (icalproperty_isa(prop) == ICAL_DTEND_PROPERTY) {
62                 TheTime = icalproperty_get_dtend(prop);
63         }
64         else if (icalproperty_isa(prop) == ICAL_DUE_PROPERTY) {
65                 TheTime = icalproperty_get_due(prop);
66         }
67         else if (icalproperty_isa(prop) == ICAL_EXDATE_PROPERTY) {
68                 TheTime = icalproperty_get_exdate(prop);
69         }
70         else {
71                 return;
72         }
73
74         /* Do the conversion. */
75         if (t != NULL) {
76                 icaltimezone_convert_time(&TheTime,
77                                         t,
78                                         icaltimezone_get_utc_timezone()
79                 );
80         }
81         TheTime.is_utc = 1;
82         icalproperty_remove_parameter_by_kind(prop, ICAL_TZID_PARAMETER);
83
84         /* Now add the converted property back in. */
85         if (icalproperty_isa(prop) == ICAL_DTSTART_PROPERTY) {
86                 icalproperty_set_dtstart(prop, TheTime);
87         }
88         else if (icalproperty_isa(prop) == ICAL_DTEND_PROPERTY) {
89                 icalproperty_set_dtend(prop, TheTime);
90         }
91         else if (icalproperty_isa(prop) == ICAL_DUE_PROPERTY) {
92                 icalproperty_set_due(prop, TheTime);
93         }
94         else if (icalproperty_isa(prop) == ICAL_EXDATE_PROPERTY) {
95                 icalproperty_set_exdate(prop, TheTime);
96         }
97 }
98
99
100 /*
101  * Recursive portion of ical_dezonify()
102  */
103 void ical_dezonify_recur(icalcomponent *cal, icalcomponent *rcal) {
104         icalcomponent *c;
105         icalproperty *p;
106
107         /*
108          * Recurse through all subcomponents *except* VTIMEZONE ones.
109          */
110         for (c=icalcomponent_get_first_component(
111                                         rcal, ICAL_ANY_COMPONENT);
112                 c != NULL;
113                 c = icalcomponent_get_next_component(
114                                         rcal, ICAL_ANY_COMPONENT)
115         ) {
116                 if (icalcomponent_isa(c) != ICAL_VTIMEZONE_COMPONENT) {
117                         ical_dezonify_recur(cal, c);
118                 }
119         }
120
121         /*
122          * Now look for DTSTART and DTEND properties
123          */
124         for (p=icalcomponent_get_first_property(
125                                 rcal, ICAL_ANY_PROPERTY);
126                 p != NULL;
127                 p = icalcomponent_get_next_property(
128                                 rcal, ICAL_ANY_PROPERTY)
129         ) {
130                 if (
131                         (icalproperty_isa(p) == ICAL_DTSTART_PROPERTY)
132                         || (icalproperty_isa(p) == ICAL_DTEND_PROPERTY)
133                         || (icalproperty_isa(p) == ICAL_DUE_PROPERTY)
134                         || (icalproperty_isa(p) == ICAL_EXDATE_PROPERTY)
135                    ) {
136                         ical_dezonify_backend(cal, rcal, p);
137                 }
138         }
139 }
140
141
142 /*
143  * Convert all DTSTART and DTEND properties in all subcomponents to UTC.
144  * This function will search any VTIMEZONE subcomponents to learn the
145  * relevant timezone information.
146  */
147 void ical_dezonify(icalcomponent *cal) {
148         icalcomponent *vt = NULL;
149
150         /* Convert all times to UTC */
151         ical_dezonify_recur(cal, cal);
152
153         /* Strip out VTIMEZONE subcomponents -- we don't need them anymore */
154         while (vt = icalcomponent_get_first_component(
155                         cal, ICAL_VTIMEZONE_COMPONENT), vt != NULL) {
156                 icalcomponent_remove_component(cal, vt);
157                 icalcomponent_free(vt);
158         }
159
160 }
161
162
163 #endif /* HAVE_ICAL_H */