4 * Functions which handle calendar objects and their processing/display.
14 #include <sys/types.h>
16 #include <sys/socket.h>
18 #include <netinet/in.h>
28 #include "webserver.h"
33 * Handler stubs for builds with no calendar library available
35 void cal_process_attachment(char *part_source) {
37 wprintf("<I>This message contains calendaring/scheduling information,"
38 " but support for calendars is not available on this "
39 "particular system. Please ask your system administrator to "
40 "install a new version of the Citadel web service with "
41 "calendaring enabled.</I><BR>\n"
46 void display_calendar(long msgnum) {
48 "Cannot display calendar item. You are seeing this error "
49 "because your WebCit service has not been installed with "
50 "calendar support. Please contact your system administrator."
54 void display_task(long msgnum) {
56 "Cannot display to-do item. You are seeing this error "
57 "because your WebCit service has not been installed with "
58 "calendar support. Please contact your system administrator."
62 #else /* HAVE_ICAL_H */
65 /****** End of handler stubs. Everything below this line is real. ******/
71 * Process a single calendar component.
72 * It won't be a compound component at this point because those have
73 * already been broken down by cal_process_object().
75 void cal_process_subcomponent(icalcomponent *cal) {
76 wprintf("cal_process_subcomponent() called<BR>\n");
77 wprintf("cal_process_subcomponent() exiting<BR>\n");
85 * Process a calendar object
86 * ...at this point it's already been deserialized by cal_process_attachment()
88 void cal_process_object(icalcomponent *cal) {
90 int num_subcomponents = 0;
92 wprintf("cal_process_object() called<BR>\n");
94 /* Iterate through all subcomponents */
95 wprintf("Iterating through all sub-components<BR>\n");
96 for (c = icalcomponent_get_first_component(cal, ICAL_ANY_COMPONENT);
98 c = icalcomponent_get_next_component(cal, ICAL_ANY_COMPONENT)) {
99 cal_process_subcomponent(c);
103 /* Iterate through all subcomponents */
104 wprintf("Iterating through VEVENTs<BR>\n");
105 for (c = icalcomponent_get_first_component(cal, ICAL_VEVENT_COMPONENT);
107 c = icalcomponent_get_next_component(cal, ICAL_VEVENT_COMPONENT)) {
108 cal_process_subcomponent(c);
112 /* Iterate through all subcomponents */
113 wprintf("Iterating through VTODOs<BR>\n");
114 for (c = icalcomponent_get_first_component(cal, ICAL_VTODO_COMPONENT);
116 c = icalcomponent_get_next_component(cal, ICAL_VTODO_COMPONENT)) {
117 cal_process_subcomponent(c);
121 /* Iterate through all subcomponents */
122 wprintf("Iterating through VJOURNALs<BR>\n");
123 for (c = icalcomponent_get_first_component(cal, ICAL_VJOURNAL_COMPONENT);
125 c = icalcomponent_get_next_component(cal, ICAL_VJOURNAL_COMPONENT)) {
126 cal_process_subcomponent(c);
130 /* Iterate through all subcomponents */
131 wprintf("Iterating through VCALENDARs<BR>\n");
132 for (c = icalcomponent_get_first_component(cal, ICAL_VCALENDAR_COMPONENT);
134 c = icalcomponent_get_next_component(cal, ICAL_VCALENDAR_COMPONENT)) {
135 cal_process_subcomponent(c);
139 /* Iterate through all subcomponents */
140 wprintf("Iterating through VFREEBUSYs<BR>\n");
141 for (c = icalcomponent_get_first_component(cal, ICAL_VFREEBUSY_COMPONENT);
143 c = icalcomponent_get_next_component(cal, ICAL_VFREEBUSY_COMPONENT)) {
144 cal_process_subcomponent(c);
148 /* Iterate through all subcomponents */
149 wprintf("Iterating through VALARMs<BR>\n");
150 for (c = icalcomponent_get_first_component(cal, ICAL_VALARM_COMPONENT);
152 c = icalcomponent_get_next_component(cal, ICAL_VALARM_COMPONENT)) {
153 cal_process_subcomponent(c);
157 /* Iterate through all subcomponents */
158 wprintf("Iterating through VTIMEZONEs<BR>\n");
159 for (c = icalcomponent_get_first_component(cal, ICAL_VTIMEZONE_COMPONENT);
161 c = icalcomponent_get_next_component(cal, ICAL_VTIMEZONE_COMPONENT)) {
162 cal_process_subcomponent(c);
166 /* Iterate through all subcomponents */
167 wprintf("Iterating through VSCHEDULEs<BR>\n");
168 for (c = icalcomponent_get_first_component(cal, ICAL_VSCHEDULE_COMPONENT);
170 c = icalcomponent_get_next_component(cal, ICAL_VSCHEDULE_COMPONENT)) {
171 cal_process_subcomponent(c);
175 /* Iterate through all subcomponents */
176 wprintf("Iterating through VQUERYs<BR>\n");
177 for (c = icalcomponent_get_first_component(cal, ICAL_VQUERY_COMPONENT);
179 c = icalcomponent_get_next_component(cal, ICAL_VQUERY_COMPONENT)) {
180 cal_process_subcomponent(c);
184 /* Iterate through all subcomponents */
185 wprintf("Iterating through VCARs<BR>\n");
186 for (c = icalcomponent_get_first_component(cal, ICAL_VCAR_COMPONENT);
188 c = icalcomponent_get_next_component(cal, ICAL_VCAR_COMPONENT)) {
189 cal_process_subcomponent(c);
193 /* Iterate through all subcomponents */
194 wprintf("Iterating through VCOMMANDs<BR>\n");
195 for (c = icalcomponent_get_first_component(cal, ICAL_VCOMMAND_COMPONENT);
197 c = icalcomponent_get_next_component(cal, ICAL_VCOMMAND_COMPONENT)) {
198 cal_process_subcomponent(c);
202 if (num_subcomponents != 0) {
203 wprintf("Warning: %d subcomponents unhandled<BR>\n",
207 wprintf("cal_process_object() exiting<BR>\n");
212 * Deserialize a calendar object in a message so it can be processed.
213 * (This is the main entry point for these things)
215 void cal_process_attachment(char *part_source) {
218 wprintf("Processing calendar attachment<BR>\n");
219 cal = icalcomponent_new_from_string(part_source);
222 wprintf("Error parsing calendar object: %s<BR>\n",
223 icalerror_strerror(icalerrno));
227 cal_process_object(cal);
229 /* Free the memory we obtained from libical's constructor */
230 icalcomponent_free(cal);
233 /*****************************************************************************/
238 * Display handlers for message reading
244 * If we're reading calendar items, just store them for now. We have to
245 * sort and re-output them later when we draw the calendar.
247 void display_individual_cal(icalcomponent *cal, long msgnum) {
251 WC->disp_cal = realloc(WC->disp_cal,
252 (sizeof(icalcomponent *) * WC->num_cal) );
253 WC->disp_cal[WC->num_cal - 1] = icalcomponent_new_clone(cal);
255 WC->cal_msgnum = realloc(WC->cal_msgnum,
256 (sizeof(long) * WC->num_cal) );
257 WC->cal_msgnum[WC->num_cal - 1] = msgnum;
263 * Display a task in the task list
265 void display_individual_task(icalcomponent *vtodo, long msgnum) {
268 p = icalcomponent_get_first_property(vtodo, ICAL_SUMMARY_PROPERTY);
269 wprintf("<LI><A HREF=\"/display_edit_task?msgnum=%ld\">", msgnum);
271 escputs((char *)icalproperty_get_comment(p));
278 * Display a task by itself (for editing)
280 void display_edit_individual_task(icalcomponent *supplied_vtodo, long msgnum) {
281 icalcomponent *vtodo;
283 struct icaltimetype t;
285 int created_new_vtodo = 0;
289 if (supplied_vtodo != NULL) {
290 vtodo = supplied_vtodo;
293 vtodo = icalcomponent_new(ICAL_VTODO_COMPONENT);
294 created_new_vtodo = 1;
298 wprintf("<TABLE WIDTH=100%% BORDER=0 BGCOLOR=007700><TR><TD>"
299 "<FONT SIZE=+1 COLOR=\"FFFFFF\""
301 "</FONT></TD></TR></TABLE><BR>\n"
304 wprintf("<FORM METHOD=\"POST\" ACTION=\"/save_task\">\n");
305 wprintf("<INPUT TYPE=\"hidden\" NAME=\"msgnum\" VALUE=\"%ld\">\n",
309 "<INPUT TYPE=\"text\" NAME=\"summary\" "
310 "MAXLENGTH=\"64\" SIZE=\"64\" VALUE=\"");
311 p = icalcomponent_get_first_property(vtodo, ICAL_SUMMARY_PROPERTY);
313 escputs((char *)icalproperty_get_comment(p));
315 wprintf("\"><BR>\n");
317 wprintf("Start date: ");
318 p = icalcomponent_get_first_property(vtodo, ICAL_DTSTART_PROPERTY);
320 t = icalproperty_get_dtstart(p);
323 t = icaltime_from_timet(now, 0);
325 display_icaltimetype_as_webform(&t, "dtstart");
328 wprintf("Due date: ");
329 p = icalcomponent_get_first_property(vtodo, ICAL_DUE_PROPERTY);
331 t = icalproperty_get_due(p);
334 t = icaltime_from_timet(now, 0);
336 display_icaltimetype_as_webform(&t, "due");
339 wprintf("<CENTER><TEXTAREA NAME=\"description\" wrap=soft "
340 "ROWS=10 COLS=80 WIDTH=80>\n"
342 p = icalcomponent_get_first_property(vtodo, ICAL_DESCRIPTION_PROPERTY);
344 escputs((char *)icalproperty_get_comment(p));
346 wprintf("</TEXTAREA><BR>\n");
348 wprintf("<INPUT TYPE=\"submit\" NAME=\"sc\" VALUE=\"Save\">"
350 "<INPUT TYPE=\"submit\" NAME=\"sc\" VALUE=\"Delete\">\n"
352 "<INPUT TYPE=\"submit\" NAME=\"sc\" VALUE=\"Cancel\">\n"
356 wprintf("</FORM>\n");
360 if (created_new_vtodo) {
361 icalcomponent_free(vtodo);
366 * Save an edited task
368 void save_individual_task(icalcomponent *supplied_vtodo, long msgnum) {
370 int delete_existing = 0;
372 icalcomponent *vtodo;
373 int created_new_vtodo = 0;
375 if (supplied_vtodo != NULL) {
376 vtodo = supplied_vtodo;
379 vtodo = icalcomponent_new(ICAL_VTODO_COMPONENT);
380 created_new_vtodo = 1;
383 if (!strcasecmp(bstr("sc"), "Save")) {
385 /* Replace values in the component with ones from the form */
387 while (prop = icalcomponent_get_first_property(vtodo,
388 ICAL_SUMMARY_PROPERTY), prop != NULL) {
389 icalcomponent_remove_property(vtodo, prop);
391 icalcomponent_add_property(vtodo,
392 icalproperty_new_summary(bstr("summary")));
394 while (prop = icalcomponent_get_first_property(vtodo,
395 ICAL_DESCRIPTION_PROPERTY), prop != NULL) {
396 icalcomponent_remove_property(vtodo, prop);
398 icalcomponent_add_property(vtodo,
399 icalproperty_new_description(bstr("description")));
401 while (prop = icalcomponent_get_first_property(vtodo,
402 ICAL_DTSTART_PROPERTY), prop != NULL) {
403 icalcomponent_remove_property(vtodo, prop);
405 icalcomponent_add_property(vtodo,
406 icalproperty_new_dtstart(
407 icaltime_from_webform("dtstart")
411 while (prop = icalcomponent_get_first_property(vtodo,
412 ICAL_DUE_PROPERTY), prop != NULL) {
413 icalcomponent_remove_property(vtodo, prop);
415 icalcomponent_add_property(vtodo,
416 icalproperty_new_due(
417 icaltime_from_webform("due")
421 /* Serialize it and save it to the message base */
422 serv_puts("ENT0 1|||4");
425 serv_puts("Content-type: text/calendar");
427 serv_puts(icalcomponent_as_ical_string(vtodo));
434 * If the user clicked 'Delete' then delete it, period.
436 if (!strcasecmp(bstr("sc"), "Delete")) {
440 if ( (delete_existing) && (msgnum > 0L) ) {
441 serv_printf("DELE %ld", atol(bstr("msgnum")));
445 if (created_new_vtodo) {
446 icalcomponent_free(vtodo);
449 /* Go back to the task list */
456 * Code common to all display handlers. Given a message number and a MIME
457 * type, we load the message and hunt for that MIME type. If found, we load
458 * the relevant part, deserialize it into a libical component, filter it for
459 * the requested object type, and feed it to the specified handler.
461 void display_using_handler(long msgnum,
463 icalcomponent_kind which_kind,
464 void (*callback)(icalcomponent *, long)
467 char mime_partnum[SIZ];
468 char mime_filename[SIZ];
469 char mime_content_type[SIZ];
470 char mime_disposition[SIZ];
472 char relevant_partnum[SIZ];
473 char *relevant_source = NULL;
474 icalcomponent *cal, *c;
476 sprintf(buf, "MSG0 %ld|1", msgnum); /* ask for headers only */
479 if (buf[0] != '1') return;
481 while (serv_gets(buf), strcmp(buf, "000")) {
482 if (!strncasecmp(buf, "part=", 5)) {
483 extract(mime_filename, &buf[5], 1);
484 extract(mime_partnum, &buf[5], 2);
485 extract(mime_disposition, &buf[5], 3);
486 extract(mime_content_type, &buf[5], 4);
487 mime_length = extract_int(&buf[5], 5);
489 if (!strcasecmp(mime_content_type, "text/calendar")) {
490 strcpy(relevant_partnum, mime_partnum);
496 if (strlen(relevant_partnum) > 0) {
497 relevant_source = load_mimepart(msgnum, relevant_partnum);
498 if (relevant_source != NULL) {
500 cal = icalcomponent_new_from_string(relevant_source);
503 /* Simple components of desired type */
504 if (icalcomponent_isa(cal) == which_kind) {
505 callback(cal, msgnum);
508 /* Subcomponents of desired type */
509 for (c = icalcomponent_get_first_component(cal,
512 c = icalcomponent_get_next_component(cal,
516 icalcomponent_free(cal);
518 free(relevant_source);
524 void display_calendar(long msgnum) {
525 display_using_handler(msgnum, "text/calendar",
526 ICAL_VEVENT_COMPONENT,
527 display_individual_cal);
530 void display_task(long msgnum) {
531 display_using_handler(msgnum, "text/calendar",
532 ICAL_VTODO_COMPONENT,
533 display_individual_task);
536 void display_edit_task(void) {
539 msgnum = atol(bstr("msgnum"));
542 display_using_handler(msgnum, "text/calendar",
543 ICAL_VTODO_COMPONENT,
544 display_edit_individual_task);
548 display_edit_individual_task(NULL, 0L);
552 void save_task(void) {
555 msgnum = atol(bstr("msgnum"));
557 display_using_handler(msgnum, "text/calendar",
558 ICAL_VTODO_COMPONENT,
559 save_individual_task);
562 save_individual_task(NULL, 0L);
566 void display_edit_event(void) {
569 msgnum = atol(bstr("msgnum"));
572 display_using_handler(msgnum, "text/calendar",
573 ICAL_VEVENT_COMPONENT,
574 display_edit_individual_event);
578 display_edit_individual_event(NULL, 0L);
582 void save_event(void) {
585 msgnum = atol(bstr("msgnum"));
588 display_using_handler(msgnum, "text/calendar",
589 ICAL_VEVENT_COMPONENT,
590 save_individual_event);
593 save_individual_event(NULL, 0L);
597 #endif /* HAVE_ICAL_H */