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