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