X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=webcit%2Fcalendar.c;h=10296ae798d82827a84877b4d80f15c81bc34113;hb=abeb8adc38f9d55fcb6cb3d076f57239b0a9a4d5;hp=423583060b122606e5a91f699fe799ae4e1b8625;hpb=10e202e9a1fefc16b7efb1d515af1e9f2c8d6ce7;p=citadel.git
diff --git a/webcit/calendar.c b/webcit/calendar.c
index 423583060..10296ae79 100644
--- a/webcit/calendar.c
+++ b/webcit/calendar.c
@@ -27,7 +27,7 @@
#include "webcit.h"
#include "webserver.h"
-#ifndef HAVE_ICAL_H
+#ifndef WEBCIT_WITH_CALENDAR_SERVICE
/*
* Handler stubs for builds with no calendar library available
@@ -38,7 +38,7 @@ void cal_process_attachment(char *part_source, long msgnum, char *cal_partnum) {
" but support for calendars is not available on this "
"particular system. Please ask your system administrator to "
"install a new version of the Citadel web service with "
- "calendaring enabled.
\n"
+ "calendaring enabled.
\n"
);
}
@@ -48,7 +48,7 @@ void display_calendar(long msgnum) {
"Cannot display calendar item. You are seeing this error "
"because your WebCit service has not been installed with "
"calendar support. Please contact your system administrator."
- "
\n");
+ "
\n");
}
void display_task(long msgnum) {
@@ -56,10 +56,10 @@ void display_task(long msgnum) {
"Cannot display to-do item. You are seeing this error "
"because your WebCit service has not been installed with "
"calendar support. Please contact your system administrator."
- "
\n");
+ "
\n");
}
-#else /* HAVE_ICAL_H */
+#else /* WEBCIT_WITH_CALENDAR_SERVICE */
/****** End of handler stubs. Everything below this line is real. ******/
@@ -70,6 +70,7 @@ void display_task(long msgnum) {
/*
* Process a calendar object
* ...at this point it's already been deserialized by cal_process_attachment()
+ *
*/
void cal_process_object(icalcomponent *cal,
int recursion_level,
@@ -103,8 +104,8 @@ void cal_process_object(icalcomponent *cal,
""
" "
- "Meeting invitation
- \n"
+ "Meeting invitation"
+ "\n"
);
break;
case ICAL_METHOD_REPLY:
@@ -112,8 +113,8 @@ void cal_process_object(icalcomponent *cal,
""
" "
- "Attendee's reply to your invitation
- \n"
+ "Attendee's reply to your invitation"
+ "\n"
);
break;
case ICAL_METHOD_PUBLISH:
@@ -121,8 +122,8 @@ void cal_process_object(icalcomponent *cal,
""
" "
- "Published event
- \n"
+ "Published event"
+ "\n"
);
break;
default:
@@ -200,11 +201,17 @@ void cal_process_object(icalcomponent *cal,
wprintf("
"
@@ -323,11 +332,11 @@ void cal_process_attachment(char *part_source, long msgnum, char *cal_partnum) {
cal = icalcomponent_new_from_string(part_source);
if (cal == NULL) {
- wprintf("Error parsing calendar object: %s \n",
- icalerror_strerror(icalerrno));
+ wprintf("Error parsing calendar object \n");
return;
}
+ ical_dezonify(cal);
cal_process_object(cal, 0, msgnum, cal_partnum);
/* Free the memory we obtained from libical's constructor */
@@ -343,13 +352,14 @@ void cal_process_attachment(char *part_source, long msgnum, char *cal_partnum) {
void respond_to_request(void) {
char buf[SIZ];
- output_headers(3);
+ output_headers(1, 1, 2, 0, 0, 0, 0);
- wprintf(""
- "Respond to meeting request"
- " |
\n"
+ wprintf("\n");
+ wprintf(" "
+ "Respond to meeting request"
+ " |
\n"
);
+ wprintf(" \n\n");
serv_printf("ICAL respond|%s|%s|%s|",
bstr("msgnum"),
@@ -386,7 +396,7 @@ void respond_to_request(void) {
wprintf(" wc_roomname);
- wprintf("\"> Return to messages\n");
+ wprintf("\"> Return to messages \n");
wDumpContent(1);
}
@@ -399,12 +409,14 @@ void respond_to_request(void) {
void handle_rsvp(void) {
char buf[SIZ];
- output_headers(3);
+ output_headers(1, 1, 2, 0, 0, 0, 0);
- wprintf(" "
- "Update your calendar with this RSVP"
- " |
\n"
+ wprintf(" \n");
+ wprintf(" "
+ ""
+ "Update your calendar with this RSVP"
+ " |
\n"
+ " \n \n"
);
serv_printf("ICAL handle_rsvp|%s|%s|%s|",
@@ -437,7 +449,7 @@ void handle_rsvp(void) {
wprintf(" wc_roomname);
- wprintf("\"> Return to messages\n");
+ wprintf("\"> Return to messages \n");
wDumpContent(1);
}
@@ -464,33 +476,17 @@ void display_individual_cal(icalcomponent *cal, long msgnum) {
WC->num_cal += 1;
WC->disp_cal = realloc(WC->disp_cal,
- (sizeof(icalcomponent *) * WC->num_cal) );
- WC->disp_cal[WC->num_cal - 1] = icalcomponent_new_clone(cal);
+ (sizeof(struct disp_cal) * WC->num_cal) );
+ WC->disp_cal[WC->num_cal - 1].cal = icalcomponent_new_clone(cal);
- WC->cal_msgnum = realloc(WC->cal_msgnum,
- (sizeof(long) * WC->num_cal) );
- WC->cal_msgnum[WC->num_cal - 1] = msgnum;
+ WC->disp_cal[WC->num_cal - 1].cal_msgnum = msgnum;
}
-/*
- * Display a task in the task list
- */
-void display_individual_task(icalcomponent *vtodo, long msgnum) {
- icalproperty *p;
-
- p = icalcomponent_get_first_property(vtodo, ICAL_SUMMARY_PROPERTY);
- wprintf(" ", msgnum);
- if (p != NULL) {
- escputs((char *)icalproperty_get_comment(p));
- }
- wprintf("\n");
-}
-
-
/*
* Display a task by itself (for editing)
+ *
*/
void display_edit_individual_task(icalcomponent *supplied_vtodo, long msgnum) {
icalcomponent *vtodo;
@@ -503,33 +499,55 @@ void display_edit_individual_task(icalcomponent *supplied_vtodo, long msgnum) {
if (supplied_vtodo != NULL) {
vtodo = supplied_vtodo;
+
+ /* If we're looking at a fully encapsulated VCALENDAR
+ * rather than a VTODO component, attempt to use the first
+ * relevant VTODO subcomponent. If there is none, the
+ * NULL returned by icalcomponent_get_first_component() will
+ * tell the next iteration of this function to create a
+ * new one.
+ */
+ if (icalcomponent_isa(vtodo) == ICAL_VCALENDAR_COMPONENT) {
+ display_edit_individual_task(
+ icalcomponent_get_first_component(
+ vtodo, ICAL_VTODO_COMPONENT
+ ), msgnum
+ );
+ return;
+ }
}
else {
vtodo = icalcomponent_new(ICAL_VTODO_COMPONENT);
created_new_vtodo = 1;
}
- output_headers(3);
- wprintf(" \n"
+ output_headers(1, 1, 2, 0, 0, 0, 0);
+ wprintf("\n\n"
);
+ wprintf(" \n");
wDumpContent(1);
if (created_new_vtodo) {
@@ -579,16 +599,34 @@ void display_edit_individual_task(icalcomponent *supplied_vtodo, long msgnum) {
/*
* Save an edited task
+ *
*/
void save_individual_task(icalcomponent *supplied_vtodo, long msgnum) {
char buf[SIZ];
int delete_existing = 0;
icalproperty *prop;
- icalcomponent *vtodo;
+ icalcomponent *vtodo, *encaps;
int created_new_vtodo = 0;
+ int i;
+ int sequence = 0;
if (supplied_vtodo != NULL) {
vtodo = supplied_vtodo;
+ /* If we're looking at a fully encapsulated VCALENDAR
+ * rather than a VTODO component, attempt to use the first
+ * relevant VTODO subcomponent. If there is none, the
+ * NULL returned by icalcomponent_get_first_component() will
+ * tell the next iteration of this function to create a
+ * new one.
+ */
+ if (icalcomponent_isa(vtodo) == ICAL_VCALENDAR_COMPONENT) {
+ save_individual_task(
+ icalcomponent_get_first_component(
+ vtodo, ICAL_VTODO_COMPONENT
+ ), msgnum
+ );
+ return;
+ }
}
else {
vtodo = icalcomponent_new(ICAL_VTODO_COMPONENT);
@@ -636,14 +674,50 @@ void save_individual_task(icalcomponent *supplied_vtodo, long msgnum) {
icaltime_from_webform("due")
)
);
-
+
+ /* Give this task a UID if it doesn't have one. */
+ lprintf(9, "Give this task a UID if it doesn't have one.\n");
+ if (icalcomponent_get_first_property(vtodo,
+ ICAL_UID_PROPERTY) == NULL) {
+ generate_uuid(buf);
+ icalcomponent_add_property(vtodo,
+ icalproperty_new_uid(buf)
+ );
+ }
+
+ /* Increment the sequence ID */
+ lprintf(9, "Increment the sequence ID\n");
+ while (prop = icalcomponent_get_first_property(vtodo,
+ ICAL_SEQUENCE_PROPERTY), (prop != NULL) ) {
+ i = icalproperty_get_sequence(prop);
+ lprintf(9, "Sequence was %d\n", i);
+ if (i > sequence) sequence = i;
+ icalcomponent_remove_property(vtodo, prop);
+ icalproperty_free(prop);
+ }
+ ++sequence;
+ lprintf(9, "New sequence is %d. Adding...\n", sequence);
+ icalcomponent_add_property(vtodo,
+ icalproperty_new_sequence(sequence)
+ );
+
+ /*
+ * Encapsulate event into full VCALENDAR component. Clone it first,
+ * for two reasons: one, it's easier to just free the whole thing
+ * when we're done instead of unbundling, but more importantly, we
+ * can't encapsulate something that may already be encapsulated
+ * somewhere else.
+ */
+ lprintf(9, "Encapsulating into full VCALENDAR component\n");
+ encaps = ical_encapsulate_subcomponent(icalcomponent_new_clone(vtodo));
+
/* Serialize it and save it to the message base */
serv_puts("ENT0 1|||4");
serv_gets(buf);
if (buf[0] == '4') {
serv_puts("Content-type: text/calendar");
serv_puts("");
- serv_puts(icalcomponent_as_ical_string(vtodo));
+ serv_puts(icalcomponent_as_ical_string(encaps));
serv_puts("000");
/* Probably not necessary; the server will see the UID
@@ -652,6 +726,7 @@ void save_individual_task(icalcomponent *supplied_vtodo, long msgnum) {
*/
delete_existing = 1;
}
+ icalcomponent_free(encaps);
}
/*
@@ -681,6 +756,7 @@ void save_individual_task(icalcomponent *supplied_vtodo, long msgnum) {
* type, we load the message and hunt for that MIME type. If found, we load
* the relevant part, deserialize it into a libical component, filter it for
* the requested object type, and feed it to the specified handler.
+ *
*/
void display_using_handler(long msgnum,
char *mimetype,
@@ -704,10 +780,10 @@ void display_using_handler(long msgnum,
while (serv_gets(buf), strcmp(buf, "000")) {
if (!strncasecmp(buf, "part=", 5)) {
- extract(mime_filename, &buf[5], 1);
- extract(mime_partnum, &buf[5], 2);
- extract(mime_disposition, &buf[5], 3);
- extract(mime_content_type, &buf[5], 4);
+ extract_token(mime_filename, &buf[5], 1, '|', sizeof mime_filename);
+ extract_token(mime_partnum, &buf[5], 2, '|', sizeof mime_partnum);
+ extract_token(mime_disposition, &buf[5], 3, '|', sizeof mime_disposition);
+ extract_token(mime_content_type, &buf[5], 4, '|', sizeof mime_content_type);
mime_length = extract_int(&buf[5], 5);
if (!strcasecmp(mime_content_type, "text/calendar")) {
@@ -724,6 +800,8 @@ void display_using_handler(long msgnum,
cal = icalcomponent_new_from_string(relevant_source);
if (cal != NULL) {
+ ical_dezonify(cal);
+
/* Simple components of desired type */
if (icalcomponent_isa(cal) == which_kind) {
callback(cal, msgnum);
@@ -754,12 +832,17 @@ void display_calendar(long msgnum) {
void display_task(long msgnum) {
display_using_handler(msgnum, "text/calendar",
ICAL_VTODO_COMPONENT,
- display_individual_task);
+ display_individual_cal);
}
void display_edit_task(void) {
long msgnum = 0L;
+ /* Force change the room if we have to */
+ if (strlen(bstr("taskrm")) > 0) {
+ gotoroom(bstr("taskrm"));
+ }
+
msgnum = atol(bstr("msgnum"));
if (msgnum > 0L) {
/* existing task */
@@ -818,4 +901,47 @@ void save_event(void) {
}
}
-#endif /* HAVE_ICAL_H */
+
+
+
+
+/*
+ * freebusy display (for client software)
+ */
+void do_freebusy(char *req) {
+ char who[SIZ];
+ char buf[SIZ];
+ char *fb;
+
+ extract_token(who, req, 1, ' ', sizeof who);
+ if (!strncasecmp(who, "/freebusy/", 10)) {
+ strcpy(who, &who[10]);
+ }
+ unescape_input(who);
+
+ if ( (!strcasecmp(&who[strlen(who)-4], ".vcf"))
+ || (!strcasecmp(&who[strlen(who)-4], ".vfb")) ) {
+ who[strlen(who)-4] = 0;
+ }
+
+ lprintf(9, "freebusy requested for <%s>\n", who);
+ serv_printf("ICAL freebusy|%s", who);
+ serv_gets(buf);
+
+ if (buf[0] != '1') {
+ wprintf("HTTP/1.0 404 %s\n", &buf[4]);
+ output_headers(0, 0, 0, 0, 0, 0, 0);
+ wprintf("Content-Type: text/plain\r\n");
+ wprintf("\r\n");
+ wprintf("%s\n", &buf[4]);
+ return;
+ }
+
+ fb = read_server_text();
+ http_transmit_thing(fb, strlen(fb), "text/calendar", 0);
+ free(fb);
+}
+
+
+
+#endif /* WEBCIT_WITH_CALENDAR_SERVICE */
|