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