958f25490aa5e644cee48e9e32856018b820a515
[citadel.git] / webcit / ical_dezonify.c
1 /* 
2  * $Id$ 
3  */
4 /**
5  * \defgroup IcalDezonify normalize ical dates to UTC
6  * Function to go through an ical component set and convert all non-UTC
7  * date/time properties to UTC.  It also strips out any VTIMEZONE
8  * subcomponents afterwards, because they're irrelevant.
9  *
10  * Everything here will work on both a fully encapsulated VCALENDAR component
11  * or any type of subcomponent.
12  *
13  */
14 /*@{*/
15
16 #include "webcit.h"
17 #include "webserver.h"
18
19
20 #ifdef WEBCIT_WITH_CALENDAR_SERVICE
21
22
23 /**
24  * \brief 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  * \param cal dunno ???
30  * \param rcal dunno ???
31  * \param prop dunno ???
32  */
33 void ical_dezonify_backend(icalcomponent *cal,
34                         icalcomponent *rcal,
35                         icalproperty *prop) {
36
37         icaltimezone *t = NULL;
38         icalparameter *param;
39         const char *tzid;
40         struct icaltimetype TheTime;
41
42         /** Give me nothing and I will give you nothing in return. */
43         if (cal == NULL) return;
44
45         /** Hunt for a TZID parameter in this property. */
46         param = icalproperty_get_first_parameter(prop, ICAL_TZID_PARAMETER);
47
48         /** Get the stringish name of this TZID. */
49         if (param != NULL) {
50                 tzid = icalparameter_get_tzid(param);
51
52                 /** Convert it to an icaltimezone type. */
53                 if (tzid != NULL) {
54                         t = icalcomponent_get_timezone(cal, tzid);
55                 }
56
57         }
58
59         /** Now we know the timezone.  Convert to UTC. */
60
61         if (icalproperty_isa(prop) == ICAL_DTSTART_PROPERTY) {
62                 TheTime = icalproperty_get_dtstart(prop);
63         }
64         else if (icalproperty_isa(prop) == ICAL_DTEND_PROPERTY) {
65                 TheTime = icalproperty_get_dtend(prop);
66         }
67         else if (icalproperty_isa(prop) == ICAL_DUE_PROPERTY) {
68                 TheTime = icalproperty_get_due(prop);
69         }
70         else if (icalproperty_isa(prop) == ICAL_EXDATE_PROPERTY) {
71                 TheTime = icalproperty_get_exdate(prop);
72         }
73         else {
74                 return;
75         }
76
77         /** Do the conversion. */
78         if (t != NULL) {
79                 icaltimezone_convert_time(&TheTime,
80                                         t,
81                                         icaltimezone_get_utc_timezone()
82                 );
83         }
84         TheTime.is_utc = 1;
85         icalproperty_remove_parameter_by_kind(prop, ICAL_TZID_PARAMETER);
86
87         /** Now add the converted property back in. */
88         if (icalproperty_isa(prop) == ICAL_DTSTART_PROPERTY) {
89                 icalproperty_set_dtstart(prop, TheTime);
90         }
91         else if (icalproperty_isa(prop) == ICAL_DTEND_PROPERTY) {
92                 icalproperty_set_dtend(prop, TheTime);
93         }
94         else if (icalproperty_isa(prop) == ICAL_DUE_PROPERTY) {
95                 icalproperty_set_due(prop, TheTime);
96         }
97         else if (icalproperty_isa(prop) == ICAL_EXDATE_PROPERTY) {
98                 icalproperty_set_exdate(prop, TheTime);
99         }
100 }
101
102
103 /**
104  * \brief Recursive portion of ical_dezonify()
105  * \param cal dunno ???
106  * \param rcal dunno ???
107  */
108 void ical_dezonify_recur(icalcomponent *cal, icalcomponent *rcal) {
109         icalcomponent *c;
110         icalproperty *p;
111
112         /**
113          * Recurse through all subcomponents *except* VTIMEZONE ones.
114          */
115         for (c=icalcomponent_get_first_component(
116                                         rcal, ICAL_ANY_COMPONENT);
117                 c != NULL;
118                 c = icalcomponent_get_next_component(
119                                         rcal, ICAL_ANY_COMPONENT)
120         ) {
121                 if (icalcomponent_isa(c) != ICAL_VTIMEZONE_COMPONENT) {
122                         ical_dezonify_recur(cal, c);
123                 }
124         }
125
126         /**
127          * Now look for DTSTART and DTEND properties
128          */
129         for (p=icalcomponent_get_first_property(
130                                 rcal, ICAL_ANY_PROPERTY);
131                 p != NULL;
132                 p = icalcomponent_get_next_property(
133                                 rcal, ICAL_ANY_PROPERTY)
134         ) {
135                 if (
136                         (icalproperty_isa(p) == ICAL_DTSTART_PROPERTY)
137                         || (icalproperty_isa(p) == ICAL_DTEND_PROPERTY)
138                         || (icalproperty_isa(p) == ICAL_DUE_PROPERTY)
139                         || (icalproperty_isa(p) == ICAL_EXDATE_PROPERTY)
140                    ) {
141                         ical_dezonify_backend(cal, rcal, p);
142                 }
143         }
144 }
145
146
147 /**
148  * \brief Convert all DTSTART and DTEND properties in all subcomponents to UTC.
149  * This function will search any VTIMEZONE subcomponents to learn the
150  * relevant timezone information.
151  * \param cal item to process
152  */
153 void ical_dezonify(icalcomponent *cal) {
154         icalcomponent *vt = NULL;
155
156         /** Convert all times to UTC */
157         ical_dezonify_recur(cal, cal);
158
159         /** Strip out VTIMEZONE subcomponents -- we don't need them anymore */
160         while (vt = icalcomponent_get_first_component(
161                         cal, ICAL_VTIMEZONE_COMPONENT), vt != NULL) {
162                 icalcomponent_remove_component(cal, vt);
163                 icalcomponent_free(vt);
164         }
165
166 }
167
168
169 #endif /* WEBCIT_WITH_CALENDAR_SERVICE */
170 /*@}*/