libical, expat, and libsieve are now *required*.
[citadel.git] / webcit / calendar_tools.c
1 /*
2  * $Id$
3  *
4  * Miscellaneous functions which handle calendar components.
5  */
6
7 #include "webcit.h"
8 #include "webserver.h"
9
10 /** Hour strings */
11 char *hourname[] = {
12         "12am", "1am", "2am", "3am", "4am", "5am", "6am",
13         "7am", "8am", "9am", "10am", "11am", "12pm",
14         "1pm", "2pm", "3pm", "4pm", "5pm", "6pm",
15         "7pm", "8pm", "9pm", "10pm", "11pm"
16 };
17
18 /*
19  * \brief display and edit date/time
20  * The display_icaltimetype_as_webform() and icaltime_from_webform() functions
21  * handle the display and editing of date/time properties in web pages.  The
22  * first one converts an icaltimetype into valid HTML markup -- a series of form
23  * fields for editing the date and time.  When the user submits the form, the
24  * results can be fed back into the second function, which turns it back into
25  * an icaltimetype.  The "prefix" string required by both functions is prepended
26  * to all field names.  This allows a form to contain more than one date/time
27  * property (for example, a start and end time) by ensuring the field names are
28  * unique within the form.
29  *
30  * \todo NOTE: These functions assume that the icaltimetype being edited is in UTC, and
31  * will convert to/from local time for editing.  "local" in this case is assumed
32  * to be the time zone in which the WebCit server is running.  A future improvement
33  * might be to allow the user to specify his/her timezone.
34  * \param t the time we want to parse
35  * \param prefix ???? \todo
36  */
37
38
39 void display_icaltimetype_as_webform(struct icaltimetype *t, char *prefix) {
40         int i;
41         time_t now;
42         struct tm tm_now;
43         int this_year;
44         time_t tt;
45         struct tm tm;
46         const int span = 10;
47         int all_day_event = 0;
48         time_t monthselect_time;
49         struct tm monthselect_tm;
50         char monthselect_str[32];
51         int time_format;
52         
53         time_format = get_time_format_cached ();
54
55         now = time(NULL);
56         localtime_r(&now, &tm_now);
57         this_year = tm_now.tm_year + 1900;
58
59         if (t == NULL) return;
60         if (t->is_date) all_day_event = 1;
61         tt = icaltime_as_timet(*t);
62         if (all_day_event) {
63                 gmtime_r(&tt, &tm);
64         }
65         else {
66                 localtime_r(&tt, &tm);
67         }
68
69         wprintf(_("Month: "));
70         wprintf("<SELECT NAME=\"%s_month\" SIZE=\"1\">\n", prefix);
71         for (i=0; i<=11; ++i) {
72                 monthselect_time = 1137997451 + (i * 2592000);
73                 localtime_r(&monthselect_time, &monthselect_tm);
74                 wc_strftime(monthselect_str, sizeof monthselect_str, "%B", &monthselect_tm);
75                 wprintf("<OPTION %s VALUE=\"%d\">%s</OPTION>\n",
76                         ((tm.tm_mon == i) ? "SELECTED" : ""),
77                         i+1,
78                         monthselect_str
79                 );
80         }
81         wprintf("</SELECT>\n");
82
83         wprintf(_("Day: "));
84         wprintf("<SELECT NAME=\"%s_day\" SIZE=\"1\">\n", prefix);
85         for (i=1; i<=31; ++i) {
86                 wprintf("<OPTION %s VALUE=\"%d\">%d</OPTION>\n",
87                         ((tm.tm_mday == i) ? "SELECTED" : ""),
88                         i, i
89                 );
90         }
91         wprintf("</SELECT>\n");
92
93         wprintf(_("Year: "));
94         wprintf("<SELECT NAME=\"%s_year\" SIZE=\"1\">\n", prefix);
95         if ((this_year - t->year) > span) {
96                 wprintf("<OPTION SELECTED VALUE=\"%d\">%d</OPTION>\n",
97                         t->year, t->year);
98         }
99         for (i=(this_year-span); i<=(this_year+span); ++i) {
100                 wprintf("<OPTION %s VALUE=\"%d\">%d</OPTION>\n",
101                         ((t->year == i) ? "SELECTED" : ""),
102                         i, i
103                 );
104         }
105         if ((t->year - this_year) > span) {
106                 wprintf("<OPTION SELECTED VALUE=\"%d\">%d</OPTION>\n",
107                         t->year, t->year);
108         }
109         wprintf("</SELECT>\n");
110
111         wprintf(_("Hour: "));
112         wprintf("<SELECT NAME=\"%s_hour\" SIZE=\"1\">\n", prefix);
113         for (i=0; i<=23; ++i) {
114
115         if (time_format == WC_TIMEFORMAT_24) {
116                         wprintf("<OPTION %s VALUE=\"%d\">%d</OPTION>\n",
117                                 ((tm.tm_hour == i) ? "SELECTED" : ""),
118                                 i, i
119                         );
120                 }
121                 else {
122                         wprintf("<OPTION %s VALUE=\"%d\">%s</OPTION>\n",
123                                 ((tm.tm_hour == i) ? "SELECTED" : ""),
124                                 i, hourname[i]
125                         );
126                 }
127
128         }
129         wprintf("</SELECT>\n");
130
131         wprintf(_("Minute: "));
132         wprintf("<SELECT NAME=\"%s_minute\" SIZE=\"1\">\n", prefix);
133         for (i=0; i<=59; ++i) {
134                 if ( (i % 5 == 0) || (tm.tm_min == i) ) {
135                         wprintf("<OPTION %s VALUE=\"%d\">:%02d</OPTION>\n",
136                                 ((tm.tm_min == i) ? "SELECTED" : ""),
137                                 i, i
138                         );
139                 }
140         }
141         wprintf("</SELECT>\n");
142 }
143
144 /**
145  *\brief Get time from form
146  * get the time back from the user and convert it into internal structs.
147  * \param t our time element
148  * \param prefix whats that\todo ????
149  */
150 void icaltime_from_webform(struct icaltimetype *t, char *prefix) {
151         char vname[32];
152         struct icaltimetype t2;
153         char timestr[32];
154         int month, mday, year, hour, minute;
155
156         sprintf(vname, "%s_month", prefix);     month = atoi(bstr(vname));
157         sprintf(vname, "%s_day", prefix);       mday = atoi(bstr(vname));
158         sprintf(vname, "%s_year", prefix);      year = atoi(bstr(vname));
159         sprintf(vname, "%s_hour", prefix);      hour = atoi(bstr(vname));
160         sprintf(vname, "%s_minute", prefix);    minute = atoi(bstr(vname));
161
162         sprintf(timestr, "%04d%02d%02dT%02d%02d00", year, month, mday, hour, minute);
163         t2 = icaltime_from_string(timestr);
164         memcpy(t, &t2, sizeof(struct icaltimetype));
165 }
166
167
168 /**
169  *\brief Get time from form
170  * get the time back from the user and convert it into internal structs.
171  * \param t our time element
172  * \param prefix whats that\todo ????
173  */
174
175 void icaltime_from_webform_dateonly(struct icaltimetype *t, char *prefix) {
176         char vname[32];
177
178         memset(t, 0, sizeof(struct icaltimetype));
179
180         sprintf(vname, "%s_month", prefix);     t->month = atoi(bstr(vname));
181         sprintf(vname, "%s_day", prefix);       t->day = atoi(bstr(vname));
182         sprintf(vname, "%s_year", prefix);      t->year = atoi(bstr(vname));
183         t->is_utc = 1;
184         t->is_date = 1;
185 }
186
187
188 /**
189  * \brief Render PAPSTAT
190  * Render a PARTSTAT parameter as a string (and put it in parentheses)
191  * \param buf the string to put it to
192  * \param attendee the attendee to textify
193  */
194 void partstat_as_string(char *buf, icalproperty *attendee) {
195         icalparameter *partstat_param;
196         icalparameter_partstat partstat;
197
198         strcpy(buf, _("(status unknown)"));
199
200         partstat_param = icalproperty_get_first_parameter(
201                                 attendee,
202                                 ICAL_PARTSTAT_PARAMETER
203         );
204         if (partstat_param == NULL) {
205                 return;
206         }
207
208         partstat = icalparameter_get_partstat(partstat_param);
209         switch(partstat) {
210                 case ICAL_PARTSTAT_X:
211                         strcpy(buf, "(x)");
212                         break;
213                 case ICAL_PARTSTAT_NEEDSACTION:
214                         strcpy(buf, _("(needs action)"));
215                         break;
216                 case ICAL_PARTSTAT_ACCEPTED:
217                         strcpy(buf, _("(accepted)"));
218                         break;
219                 case ICAL_PARTSTAT_DECLINED:
220                         strcpy(buf, _("(declined)"));
221                         break;
222                 case ICAL_PARTSTAT_TENTATIVE:
223                         strcpy(buf, _("(tenative)"));
224                         break;
225                 case ICAL_PARTSTAT_DELEGATED:
226                         strcpy(buf, _("(delegated)"));
227                         break;
228                 case ICAL_PARTSTAT_COMPLETED:
229                         strcpy(buf, _("(completed)"));
230                         break;
231                 case ICAL_PARTSTAT_INPROCESS:
232                         strcpy(buf, _("(in process)"));
233                         break;
234                 case ICAL_PARTSTAT_NONE:
235                         strcpy(buf, _("(none)"));
236                         break;
237         }
238 }
239
240
241 /**
242  * \brief embedd
243  * Utility function to encapsulate a subcomponent into a full VCALENDAR
244  * \param subcomp the component to encapsulate
245  * \returns the meta object ???
246  */
247 icalcomponent *ical_encapsulate_subcomponent(icalcomponent *subcomp) {
248         icalcomponent *encaps;
249
250         /* lprintf(9, "ical_encapsulate_subcomponent() called\n"); */
251
252         if (subcomp == NULL) {
253                 lprintf(3, "ERROR: called with NULL argument!\n");
254                 return NULL;
255         }
256
257         /**
258          * If we're already looking at a full VCALENDAR component,
259          * don't bother ... just return itself.
260          */
261         if (icalcomponent_isa(subcomp) == ICAL_VCALENDAR_COMPONENT) {
262                 return subcomp;
263         }
264
265         /** Encapsulate the VEVENT component into a complete VCALENDAR */
266         encaps = icalcomponent_new(ICAL_VCALENDAR_COMPONENT);
267         if (encaps == NULL) {
268                 lprintf(3, "%s:%d: Error - could not allocate component!\n",
269                         __FILE__, __LINE__);
270                 return NULL;
271         }
272
273         /** Set the Product ID */
274         icalcomponent_add_property(encaps, icalproperty_new_prodid(PRODID));
275
276         /** Set the Version Number */
277         icalcomponent_add_property(encaps, icalproperty_new_version("2.0"));
278
279         /** Encapsulate the subcomponent inside */
280         /* lprintf(9, "Doing the encapsulation\n"); */
281         icalcomponent_add_component(encaps, subcomp);
282
283         /** Convert all timestamps to UTC so we don't have to deal with
284          * stupid VTIMEZONE crap.
285          */
286         ical_dezonify(encaps);
287
288         /** Return the object we just created. */
289         return(encaps);
290 }
291
292