]> code.citadel.org Git - citadel.git/blob - webcit/event.c
* When adding new events to the calendar, default to the month [and day]
[citadel.git] / webcit / event.c
1 /*
2  * $Id$
3  *
4  * Editing calendar events.
5  *
6  */
7
8 #include <ctype.h>
9 #include <stdlib.h>
10 #include <unistd.h>
11 #include <stdio.h>
12 #include <fcntl.h>
13 #include <signal.h>
14 #include <sys/types.h>
15 #include <sys/wait.h>
16 #include <sys/socket.h>
17 #include <limits.h>
18 #include <netinet/in.h>
19 #include <netdb.h>
20 #include <string.h>
21 #include <pwd.h>
22 #include <errno.h>
23 #include <stdarg.h>
24 #include <pthread.h>
25 #include <signal.h>
26 #include <time.h>
27 #include "webcit.h"
28 #include "webserver.h"
29
30
31 #ifdef HAVE_ICAL_H
32
33
34 /*
35  * Display an event by itself (for editing)
36  */
37 void display_edit_individual_event(icalcomponent *supplied_vevent, long msgnum) {
38         icalcomponent *vevent;
39         icalproperty *p;
40         struct icaltimetype t_start, t_end;
41         time_t now;
42         int created_new_vevent = 0;
43
44         now = time(NULL);
45
46         if (supplied_vevent != NULL) {
47                 vevent = supplied_vevent;
48         }
49         else {
50                 vevent = icalcomponent_new(ICAL_VEVENT_COMPONENT);
51                 created_new_vevent = 1;
52         }
53
54         output_headers(3);
55         wprintf("<TABLE WIDTH=100%% BORDER=0 BGCOLOR=007700><TR><TD>"
56                 "<IMG ALIGN=CENTER SRC=\"/static/vcalendar.gif\">"
57                 "<FONT SIZE=+1 COLOR=\"FFFFFF\""
58                 "<B>Edit event</B>"
59                 "</FONT></TD></TR></TABLE><BR>\n"
60         );
61
62         /************************************************************
63          * Uncomment this to see the UID in calendar events for debugging
64         wprintf("UID == ");
65         p = icalcomponent_get_first_property(vevent, ICAL_UID_PROPERTY);
66         if (p != NULL) {
67                 escputs((char *)icalproperty_get_comment(p));
68         }
69         *************************************************************/
70
71         wprintf("<FORM NAME=\"EventForm\" METHOD=\"POST\" ACTION=\"/save_event\">\n");
72
73         wprintf("<INPUT TYPE=\"hidden\" NAME=\"msgnum\" VALUE=\"%ld\">\n",
74                 msgnum);
75         wprintf("<INPUT TYPE=\"hidden\" NAME=\"calview\" VALUE=\"%s\">\n",
76                 bstr("calview"));
77         wprintf("<INPUT TYPE=\"hidden\" NAME=\"year\" VALUE=\"%s\">\n",
78                 bstr("year"));
79         wprintf("<INPUT TYPE=\"hidden\" NAME=\"month\" VALUE=\"%s\">\n",
80                 bstr("month"));
81         wprintf("<INPUT TYPE=\"hidden\" NAME=\"day\" VALUE=\"%s\">\n",
82                 bstr("day"));
83
84         /* Put it in a borderless table so it lines up nicely */
85         wprintf("<TABLE border=0 width=100%%>\n");
86
87         wprintf("<TR><TD><B>Summary</B></TD><TD>\n"
88                 "<INPUT TYPE=\"text\" NAME=\"summary\" "
89                 "MAXLENGTH=\"64\" SIZE=\"64\" VALUE=\"");
90         p = icalcomponent_get_first_property(vevent, ICAL_SUMMARY_PROPERTY);
91         if (p != NULL) {
92                 escputs((char *)icalproperty_get_comment(p));
93         }
94         wprintf("\"></TD></TR>\n");
95
96         wprintf("<TR><TD><B>Location</B></TD><TD>\n"
97                 "<INPUT TYPE=\"text\" NAME=\"location\" "
98                 "MAXLENGTH=\"64\" SIZE=\"64\" VALUE=\"");
99         p = icalcomponent_get_first_property(vevent, ICAL_LOCATION_PROPERTY);
100         if (p != NULL) {
101                 escputs((char *)icalproperty_get_comment(p));
102         }
103         wprintf("\"></TD></TR>\n");
104
105         wprintf("<TR><TD><B>Start</B></TD><TD>\n");
106         p = icalcomponent_get_first_property(vevent, ICAL_DTSTART_PROPERTY);
107         if (p != NULL) {
108                 t_start = icalproperty_get_dtstart(p);
109                 if (t_start.is_date) {
110                         t_start.hour = 0;
111                         t_start.minute = 0;
112                         t_start.second = 0;
113                 }
114         }
115         else {
116                 memset(&t_start, 0, sizeof t_start);
117                 t_start.year = atoi(bstr("year"));
118                 t_start.month = atoi(bstr("month"));
119                 t_start.day = atoi(bstr("day"));
120                 if (strlen(bstr("hour")) > 0) {
121                         t_start.hour = atoi(bstr("hour"));
122                         t_start.minute = atoi(bstr("minute"));
123                 }
124                 else {
125                         t_start.hour = 9;
126                         t_start.minute = 0;
127                 }
128                 /* t_start = icaltime_from_timet(now, 0); */
129         }
130         display_icaltimetype_as_webform(&t_start, "dtstart");
131
132         wprintf("<INPUT TYPE=\"checkbox\" NAME=\"alldayevent\" "
133                 "VALUE=\"yes\" onClick=\"
134
135                         if (this.checked) {
136                                 this.form.dtstart_hour.value='0';
137                                 this.form.dtstart_hour.disabled = true;
138                                 this.form.dtstart_minute.value='0';
139                                 this.form.dtstart_minute.disabled = true;
140                                 this.form.dtend_hour.value='0';
141                                 this.form.dtend_hour.disabled = true;
142                                 this.form.dtend_minute.value='0';
143                                 this.form.dtend_minute.disabled = true;
144                                 this.form.dtend_month.disabled = true;
145                                 this.form.dtend_day.disabled = true;
146                                 this.form.dtend_year.disabled = true;
147                         }
148                         else {
149                                 this.form.dtstart_hour.disabled = false;
150                                 this.form.dtstart_minute.disabled = false;
151                                 this.form.dtend_hour.disabled = false;
152                                 this.form.dtend_minute.disabled = false;
153                                 this.form.dtend_month.disabled = false;
154                                 this.form.dtend_day.disabled = false;
155                                 this.form.dtend_year.disabled = false;
156                         }
157
158
159                 \" %s >All day event",
160                 (t_start.is_date ? "CHECKED" : "" )
161         );
162
163         wprintf("</TD></TR>\n");
164
165         /* If this is an all-day-event, set the end time to be identical to
166          * the start time (the hour/minute/second will be set to midnight).
167          * Otherwise extract or create it.
168          */
169         wprintf("<TR><TD><B>End</B></TD><TD>\n");
170         if (t_start.is_date) {
171                 t_end = t_start;
172         }
173         else {
174                 p = icalcomponent_get_first_property(vevent,
175                                                         ICAL_DTEND_PROPERTY);
176                 if (p != NULL) {
177                         t_end = icalproperty_get_dtend(p);
178                 }
179                 else {
180                         /* If this is not an all-day event and there is no
181                          * end time specified, make the default one hour
182                          * from the start time.
183                          */
184                         t_end = t_start;
185                         t_end.hour += 1;
186                         t_end = icaltime_normalize(t_end);
187                         /* t_end = icaltime_from_timet(now, 0); */
188                 }
189         }
190         display_icaltimetype_as_webform(&t_end, "dtend");
191         wprintf("</TD></TR>\n");
192
193         wprintf("<TR><TD><B>Notes</B></TD><TD>\n"
194                 "<TEXTAREA NAME=\"description\" wrap=soft "
195                 "ROWS=10 COLS=80 WIDTH=80>\n"
196         );
197         p = icalcomponent_get_first_property(vevent, ICAL_DESCRIPTION_PROPERTY);
198         if (p != NULL) {
199                 escputs((char *)icalproperty_get_comment(p));
200         }
201         wprintf("</TEXTAREA></TD></TR></TABLE>\n");
202
203         wprintf("<CENTER>"
204                 "<INPUT TYPE=\"submit\" NAME=\"sc\" VALUE=\"Save\">"
205                 "&nbsp;&nbsp;"
206                 "<INPUT TYPE=\"submit\" NAME=\"sc\" VALUE=\"Delete\">\n"
207                 "&nbsp;&nbsp;"
208                 "<INPUT TYPE=\"submit\" NAME=\"sc\" VALUE=\"Cancel\">\n"
209                 "</CENTER>\n"
210         );
211
212         wprintf("</FORM>\n");
213         
214         wprintf("<SCRIPT language=\"javascript\">
215                 <!--
216
217                         if (document.EventForm.alldayevent.checked) {
218                                 document.EventForm.dtstart_hour.value='0';
219                                 document.EventForm.dtstart_hour.disabled = true;
220                                 document.EventForm.dtstart_minute.value='0';
221                                 document.EventForm.dtstart_minute.disabled = true;
222                                 document.EventForm.dtend_hour.value='0';
223                                 document.EventForm.dtend_hour.disabled = true;
224                                 document.EventForm.dtend_minute.value='0';
225                                 document.EventForm.dtend_minute.disabled = true;
226                                 document.EventForm.dtend_month.disabled = true;
227                                 document.EventForm.dtend_day.disabled = true;
228                                 document.EventForm.dtend_year.disabled = true;
229                         }
230                         else {
231                                 document.EventForm.dtstart_hour.disabled = false;
232                                 document.EventForm.dtstart_minute.disabled = false;
233                                 document.EventForm.dtend_hour.disabled = false;
234                                 document.EventForm.dtend_minute.disabled = false;
235                                 document.EventForm.dtend_month.disabled = false;
236                                 document.EventForm.dtend_day.disabled = false;
237                                 document.EventForm.dtend_year.disabled = false;
238                         }
239                 //-->
240                 </SCRIPT>
241         ");
242
243         wDumpContent(1);
244
245         if (created_new_vevent) {
246                 icalcomponent_free(vevent);
247         }
248 }
249
250 /*
251  * Save an edited event
252  */
253 void save_individual_event(icalcomponent *supplied_vevent, long msgnum) {
254         char buf[SIZ];
255         int delete_existing = 0;
256         icalproperty *prop;
257         icalcomponent *vevent;
258         int created_new_vevent = 0;
259         int all_day_event = 0;
260         struct icaltimetype event_start;
261
262         if (supplied_vevent != NULL) {
263                 vevent = supplied_vevent;
264         }
265         else {
266                 vevent = icalcomponent_new(ICAL_VEVENT_COMPONENT);
267                 created_new_vevent = 1;
268         }
269
270         if (!strcasecmp(bstr("sc"), "Save")) {
271
272                 /* Replace values in the component with ones from the form */
273
274                 while (prop = icalcomponent_get_first_property(vevent,
275                       ICAL_SUMMARY_PROPERTY), prop != NULL) {
276                         icalcomponent_remove_property(vevent, prop);
277                 }
278                 icalcomponent_add_property(vevent,
279                         icalproperty_new_summary(bstr("summary")));
280                 
281                 while (prop = icalcomponent_get_first_property(vevent,
282                       ICAL_LOCATION_PROPERTY), prop != NULL) {
283                         icalcomponent_remove_property(vevent, prop);
284                 }
285                 icalcomponent_add_property(vevent,
286                         icalproperty_new_location(bstr("location")));
287                 
288                 while (prop = icalcomponent_get_first_property(vevent,
289                       ICAL_DESCRIPTION_PROPERTY), prop != NULL) {
290                         icalcomponent_remove_property(vevent, prop);
291                 }
292                 icalcomponent_add_property(vevent,
293                         icalproperty_new_description(bstr("description")));
294         
295                 while (prop = icalcomponent_get_first_property(vevent,
296                       ICAL_DTSTART_PROPERTY), prop != NULL) {
297                         icalcomponent_remove_property(vevent, prop);
298                 }
299
300                 if (!strcmp(bstr("alldayevent"), "yes")) {
301                         all_day_event = 1;
302                         lprintf(9, "*** all day event ***\n");
303                 }
304                 else {
305                         all_day_event = 0;
306                 }
307
308                 event_start = icaltime_from_webform("dtstart");
309                 if (all_day_event) {
310                         event_start.is_date = 1;
311                         event_start.hour = 0;
312                         event_start.minute = 0;
313                         event_start.second = 0;
314                 }
315
316
317                 /* The following odd-looking snippet of code looks like it
318                  * takes some unnecessary steps.  It is done this way because
319                  * libical incorrectly turns an "all day event" into a normal
320                  * event starting at midnight (i.e. it serializes as date/time
321                  * instead of just date) unless icalvalue_new_date() is used.
322                  * So we force it, if this is an all day event.
323                  */
324                 prop = icalproperty_new_dtstart(event_start);
325                 if (all_day_event) {
326                         icalproperty_set_value(prop,
327                                 icalvalue_new_date(event_start)
328                         );
329                 }
330
331                 if (prop) icalcomponent_add_property(vevent, prop);
332                 else icalproperty_free(prop);
333
334
335
336                 while (prop = icalcomponent_get_first_property(vevent,
337                       ICAL_DTEND_PROPERTY), prop != NULL) {
338                         icalcomponent_remove_property(vevent, prop);
339                 }
340                 while (prop = icalcomponent_get_first_property(vevent,
341                       ICAL_DURATION_PROPERTY), prop != NULL) {
342                         icalcomponent_remove_property(vevent, prop);
343                 }
344
345                 if (all_day_event == 0) {
346                         icalcomponent_add_property(vevent,
347                                 icalproperty_new_dtend(icaltime_normalize(
348                                         icaltime_from_webform("dtend"))
349                                 )
350                         );
351                 }
352
353                 /* Give this event a UID if it doesn't have one. */
354                 if (icalcomponent_get_first_property(vevent,
355                    ICAL_UID_PROPERTY) == NULL) {
356                         generate_new_uid(buf);
357                         icalcomponent_add_property(vevent,
358                                 icalproperty_new_uid(buf)
359                         );
360                 }
361
362                 /* Serialize it and save it to the message base */
363                 serv_puts("ENT0 1|||4");
364                 serv_gets(buf);
365                 if (buf[0] == '4') {
366                         serv_puts("Content-type: text/calendar");
367                         serv_puts("");
368                         serv_puts(icalcomponent_as_ical_string(vevent));
369                         serv_puts("000");
370                         delete_existing = 1;
371                 }
372         }
373
374         /*
375          * If the user clicked 'Delete' then delete it, period.
376          */
377         if (!strcasecmp(bstr("sc"), "Delete")) {
378                 delete_existing = 1;
379         }
380
381         if ( (delete_existing) && (msgnum > 0L) ) {
382                 serv_printf("DELE %ld", atol(bstr("msgnum")));
383                 serv_gets(buf);
384         }
385
386         if (created_new_vevent) {
387                 icalcomponent_free(vevent);
388         }
389
390         /* Go back to the event list */
391         readloop("readfwd");
392 }
393
394
395 #endif /* HAVE_ICAL_H */