* BIG rewrite of header handling and slimming of context_loop and session_loop; shuff...
[citadel.git] / webcit / calendar.c
index d110b8f50ef24c376110bf921ff3120ae3ae6c7c..b1e9b9a585af94f2263e32a080f42b0e95f83a57 100644 (file)
@@ -125,7 +125,7 @@ void cal_process_object(StrBuf *Target,
                        }
                        else {
                                tt = icaltime_as_timet(t);
-                               webcit_fmt_date(buf, tt, DATEFMT_FULL);
+                               webcit_fmt_date(buf, 256, tt, DATEFMT_FULL);
                                StrBufAppendPrintf(Target, "<dt>");
                                StrBufAppendPrintf(Target, _("Starting date/time:"));
                                StrBufAppendPrintf(Target, "</dt><dd>%s</dd>", buf);
@@ -136,7 +136,7 @@ void cal_process_object(StrBuf *Target,
                if (p != NULL) {
                        t = icalproperty_get_dtend(p);
                        tt = icaltime_as_timet(t);
-                       webcit_fmt_date(buf, tt, DATEFMT_FULL);
+                       webcit_fmt_date(buf, 256, tt, DATEFMT_FULL);
                        StrBufAppendPrintf(Target, "<dt>");
                        StrBufAppendPrintf(Target, _("Ending date/time:"));
                        StrBufAppendPrintf(Target, "</dt><dd>%s</dd>", buf);
@@ -275,7 +275,6 @@ void cal_process_object(StrBuf *Target,
 
 /*
  * Deserialize a calendar object in a message so it can be displayed.
- *
  */
 void cal_process_attachment(wc_mime_attachment *Mime) 
 {
@@ -298,9 +297,8 @@ void cal_process_attachment(wc_mime_attachment *Mime)
 
 
 
-/**
- * \brief accept/decline meeting
- * Respond to a meeting request
+/*
+ * Respond to a meeting request - accept/decline meeting
  */
 void respond_to_request(void) 
 {
@@ -344,8 +342,8 @@ void respond_to_request(void)
 
 
 
-/**
- * \brief Handle an incoming RSVP
+/*
+ * Handle an incoming RSVP
  */
 void handle_rsvp(void) 
 {
@@ -627,7 +625,7 @@ void display_edit_individual_task(icalcomponent *supplied_vtodo, long msgnum, ch
                created_new_vtodo = 1;
        }
        
-       /*/ TODO: Can we take all this and move it into a template?      */
+       /* TODO: Can we take all this and move it into a template?       */
        output_headers(1, 1, 1, 0, 0, 0);
        wprintf("<!-- start task edit form -->");
        p = icalcomponent_get_first_property(vtodo, ICAL_SUMMARY_PROPERTY);
@@ -778,9 +776,10 @@ void display_edit_individual_task(icalcomponent *supplied_vtodo, long msgnum, ch
 }
 
 /*
- * \brief Save an edited task
- * \param supplied_vtodo the task to save
- * \param msgnum number of the mesage in our db
+ * Save an edited task
+ *
+ * supplied_vtodo      the task to save
+ * msgnum              number of the mesage in our db
  */
 void save_individual_task(icalcomponent *supplied_vtodo, long msgnum, char* from, int unread,
                                struct calview *calv)
@@ -920,7 +919,7 @@ void save_individual_task(icalcomponent *supplied_vtodo, long msgnum, char* from
                                );
                }
 
-               /** Increment the sequence ID */
+               /* Increment the sequence ID */
                lprintf(9, "Increment the sequence ID\n");
                while (prop = icalcomponent_get_first_property(vtodo,
                                                               ICAL_SEQUENCE_PROPERTY), (prop != NULL) ) {
@@ -936,7 +935,7 @@ void save_individual_task(icalcomponent *supplied_vtodo, long msgnum, char* from
                                           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
@@ -955,7 +954,7 @@ void save_individual_task(icalcomponent *supplied_vtodo, long msgnum, char* from
                        serv_puts(icalcomponent_as_ical_string(encaps));
                        serv_puts("000");
 
-                       /**
+                       /*
                         * Probably not necessary; the server will see the UID
                         * of the object and delete the old one anyway, but
                         * just in case...
@@ -992,6 +991,45 @@ void save_individual_task(icalcomponent *supplied_vtodo, long msgnum, char* from
 
 
 
+void process_ical_object(long msgnum, int unread,
+                        char *from, 
+                        char *FlatIcal, 
+                        icalcomponent_kind which_kind,
+                        IcalCallbackFunc CallBack,
+                        struct calview *calv
+       ) 
+{
+       icalcomponent *cal, *c;
+
+       cal = icalcomponent_new_from_string(FlatIcal);
+       if (cal != NULL) {
+
+               /* A which_kind of (-1) means just load the whole thing */
+               if (which_kind == (-1)) {
+                       CallBack(cal, msgnum, from, unread, calv);
+               }
+               
+               /* Otherwise recurse and hunt */
+               else {
+                       
+                       /* Simple components of desired type */
+                       if (icalcomponent_isa(cal) == which_kind) {
+                               CallBack(cal, msgnum, from, unread, calv);
+                       }
+                       
+                       /* Subcomponents of desired type */
+                       for (c = icalcomponent_get_first_component(cal, which_kind);
+                            (c != 0);
+                            c = icalcomponent_get_next_component(cal, which_kind)) {
+                               CallBack(c, msgnum, from, unread, calv);
+                       }
+                       
+               }
+               
+               icalcomponent_free(cal);
+       }
+}
+
 /*
  * Code common to all icalendar display handlers.  Given a message number and a MIME
  * type, we load the message and hunt for that MIME type.  If found, we load
@@ -999,14 +1037,16 @@ void save_individual_task(icalcomponent *supplied_vtodo, long msgnum, char* from
  * the requested object type, and feed it to the specified handler.
  */
 void load_ical_object(long msgnum, int unread,
-                          icalcomponent_kind which_kind,
-                          void (*callback)(icalcomponent *, long, char*, int, struct calview *),
-                          struct calview *calv
+                     icalcomponent_kind which_kind,
+                     IcalCallbackFunc CallBack,
+                     struct calview *calv,
+                     int RenderAsync
        ) 
 {
        StrBuf *Buf;
-       size_t BufLen;
-       char buf[1024];
+       StrBuf *Data;
+       const char *bptr;
+       int Done = 0;
        char from[128] = "";
        char mime_partnum[256];
        char mime_filename[256];
@@ -1015,70 +1055,111 @@ void load_ical_object(long msgnum, int unread,
        int mime_length;
        char relevant_partnum[256];
        char *relevant_source = NULL;
-       icalcomponent *cal, *c;
+       int phase = 0;                          /* 0 = citadel headers, 1 = mime headers, 2 = body */
+       char msg4_content_type[256] = "";
+       char msg4_content_encoding[256] = "";
+       int msg4_content_length = 0;
 
        relevant_partnum[0] = '\0';
-       sprintf(buf, "MSG4 %ld", msgnum);       /* we need the mime headers */
-       serv_puts(buf);
-       serv_getln(buf, sizeof buf);
-       if (buf[0] != '1') return;
-
+       serv_printf("MSG4 %ld", msgnum);        /* we need the mime headers */
        Buf = NewStrBuf();
-       while (BufLen = StrBuf_ServGetlnBuffered(Buf), strcmp(ChrPtr(Buf), "000")) {
-               if (!strncasecmp(ChrPtr(Buf), "part=", 5)) {
-                       extract_token(mime_filename, &ChrPtr(Buf)[5], 1, '|', sizeof mime_filename);
-                       extract_token(mime_partnum, &ChrPtr(Buf)[5], 2, '|', sizeof mime_partnum);
-                       extract_token(mime_disposition, &ChrPtr(Buf)[5], 3, '|', sizeof mime_disposition);
-                       extract_token(mime_content_type, &ChrPtr(Buf)[5], 4, '|', sizeof mime_content_type);
-                       mime_length = extract_int(&ChrPtr(Buf)[5], 5);
-
-                       if (  (!strcasecmp(mime_content_type, "text/calendar"))
-                             || (!strcasecmp(mime_content_type, "application/ics"))
-                             || (!strcasecmp(mime_content_type, "text/vtodo"))
-                               ) {
-                               strcpy(relevant_partnum, mime_partnum);
-                       }
+       StrBuf_ServGetln(Buf);
+       if (GetServerStatus(Buf, NULL) != 1) {
+               FreeStrBuf (&Buf);
+               return;
+       }
+       while (!Done && (StrBuf_ServGetln(Buf)>=0)) {
+               if ( (StrLength(Buf)==3) && 
+                    !strcmp(ChrPtr(Buf), "000")) {
+                       Done = 1;
+                       break;
                }
-               else if (!strncasecmp(ChrPtr(Buf), "from=", 4)) {
-                       extract_token(from, ChrPtr(Buf), 1, '=', sizeof(from));
+               bptr = ChrPtr(Buf);
+               switch (phase) {
+               case 0:
+                       if (!strncasecmp(bptr, "part=", 5)) {
+                               extract_token(mime_filename, &bptr[5], 1, '|', sizeof mime_filename);
+                               extract_token(mime_partnum, &bptr[5], 2, '|', sizeof mime_partnum);
+                               extract_token(mime_disposition, &bptr[5], 3, '|', sizeof mime_disposition);
+                               extract_token(mime_content_type, &bptr[5], 4, '|', sizeof mime_content_type);
+                               mime_length = extract_int(&bptr[5], 5);
+
+                               if (  (!strcasecmp(mime_content_type, "text/calendar"))
+                                     || (!strcasecmp(mime_content_type, "application/ics"))
+                                     || (!strcasecmp(mime_content_type, "text/vtodo"))
+                                       ) {
+                                       strcpy(relevant_partnum, mime_partnum);
+                               }
+                       }
+                       else if (!strncasecmp(bptr, "from=", 4)) {
+                               extract_token(from, bptr, 1, '=', sizeof(from));
+                       }
+                       else if ((phase == 0) && (!strncasecmp(bptr, "text", 4))) {
+                               phase = 1;
+                       }
+               break;
+               case 1:
+                       if (!IsEmptyStr(bptr)) {
+                               if (!strncasecmp(bptr, "Content-type: ", 14)) {
+                                       safestrncpy(msg4_content_type, &bptr[14], sizeof msg4_content_type);
+                                       striplt(msg4_content_type);
+                               }
+                               else if (!strncasecmp(bptr, "Content-transfer-encoding: ", 27)) {
+                                       safestrncpy(msg4_content_encoding, &bptr[27], sizeof msg4_content_encoding);
+                                       striplt(msg4_content_type);
+                               }
+                               else if ((!strncasecmp(bptr, "Content-length: ", 16))) {
+                                       msg4_content_length = atoi(&bptr[16]);
+                               }
+                               break;
+                       }
+                       else {
+                               phase++;
+                               
+                               if ((msg4_content_length > 0)
+                                   && ( !strcasecmp(msg4_content_encoding, "7bit"))
+                                   && ((!strcasecmp(mime_content_type, "text/calendar"))
+                                       || (!strcasecmp(mime_content_type, "application/ics"))
+                                       || (!strcasecmp(mime_content_type, "text/vtodo"))
+                                           )
+                                       ) 
+                               {
+                               }
+                       }
+               case 2:
+                       Data = NewStrBufPlain(NULL, msg4_content_length * 2);
+                       if (msg4_content_length > 0) {
+                               StrBuf_ServGetBLOBBuffered(Data, msg4_content_length);
+                               phase ++;
+                       }
+                       else {
+                               StrBufAppendBuf(Data, Buf, 0);
+                               StrBufAppendBufPlain(Data, "\r\n", 1, 0);
+                       }
+               case 3:
+                       StrBufAppendBuf(Data, Buf, 0);
                }
        }
        FreeStrBuf(&Buf);
 
-       if (!IsEmptyStr(relevant_partnum)) {
-               relevant_source = load_mimepart(msgnum, relevant_partnum);
-               if (relevant_source != NULL) {
-
-                       cal = icalcomponent_new_from_string(relevant_source);
-                       if (cal != NULL) {
-
-                               /* A which_kind of (-1) means just load the whole thing */
-                               if (which_kind == (-1)) {
-                                       callback(cal, msgnum, from, unread, calv);
-                               }
-
-                               /* Otherwise recurse and hunt */
-                               else {
-
-                                       /* Simple components of desired type */
-                                       if (icalcomponent_isa(cal) == which_kind) {
-                                               callback(cal, msgnum, from, unread, calv);
-                                       }
-       
-                                       /* Subcomponents of desired type */
-                                       for (c = icalcomponent_get_first_component(cal, which_kind);
-                                       (c != 0);
-                                       c = icalcomponent_get_next_component(cal, which_kind)) {
-                                               callback(c, msgnum, from, unread, calv);
-                                       }
-
-                               }
+       /* If MSG4 didn't give us the part we wanted, but we know that we can find it
+        * as one of the other MIME parts, attempt to load it now.
+        */
+       if ((Data == NULL) && (!IsEmptyStr(relevant_partnum))) {
+               Data = load_mimepart(msgnum, relevant_partnum);
+       }
 
-                               icalcomponent_free(cal);
-                       }
-                       free(relevant_source);
-               }
+       if (Data != NULL) {
+               relevant_source = (char*) ChrPtr(Data);
+               process_ical_object(msgnum, unread,
+                                   from, 
+                                   relevant_source, 
+                                   which_kind,
+                                   CallBack,
+                                   calv);
+               FreeStrBuf (&Data);
        }
+
        icalmemory_free_ring();
 }
 
@@ -1086,15 +1167,14 @@ void load_ical_object(long msgnum, int unread,
  * Display a calendar item
  */
 void load_calendar_item(message_summary *Msg, int unread, struct calview *c) {
-       /*load_ical_object(Msg->msgnum, unread, ICAL_VEVENT_COMPONENT, display_individual_cal, c);*/
-       load_ical_object(Msg->msgnum, unread, (-1), display_individual_cal, c);
+       load_ical_object(Msg->msgnum, unread, (-1), display_individual_cal, c, 1);
 }
 
 /*
  * Display task view
  */
 void display_task(message_summary *Msg, int unread) {
-       load_ical_object(Msg->msgnum, unread, ICAL_VTODO_COMPONENT, display_individual_cal, NULL);
+       load_ical_object(Msg->msgnum, unread, ICAL_VTODO_COMPONENT, display_individual_cal, NULL, 0);
 }
 
 /*
@@ -1112,9 +1192,9 @@ void display_edit_task(void) {
        if (msgnum > 0L) {
                /* existing task */
                load_ical_object(msgnum, 0,
-                                     ICAL_VTODO_COMPONENT,
-                                     display_edit_individual_task,
-                                     NULL
+                                ICAL_VTODO_COMPONENT,
+                                display_edit_individual_task,
+                                NULL, 0
                );
        }
        else {
@@ -1130,7 +1210,7 @@ void save_task(void) {
        long msgnum = 0L;
        msgnum = lbstr("msgnum");
        if (msgnum > 0L) {
-               load_ical_object(msgnum, 0, ICAL_VTODO_COMPONENT, save_individual_task, NULL);
+               load_ical_object(msgnum, 0, ICAL_VTODO_COMPONENT, save_individual_task, NULL, 0);
        }
        else {
                save_individual_task(NULL, 0L, "", 0, NULL);
@@ -1146,7 +1226,7 @@ void display_edit_event(void) {
        msgnum = lbstr("msgnum");
        if (msgnum > 0L) {
                /* existing event */
-               load_ical_object(msgnum, 0, ICAL_VEVENT_COMPONENT, display_edit_individual_event, NULL);
+               load_ical_object(msgnum, 0, ICAL_VEVENT_COMPONENT, display_edit_individual_event, NULL, 0);
        }
        else {
                /* new event */
@@ -1163,8 +1243,7 @@ void save_event(void) {
        msgnum = lbstr("msgnum");
 
        if (msgnum > 0L) {
-               /* load_ical_object(msgnum, 0, ICAL_VEVENT_COMPONENT, save_individual_event, NULL); */
-               load_ical_object(msgnum, 0, (-1), save_individual_event, NULL);
+               load_ical_object(msgnum, 0, (-1), save_individual_event, NULL, 0);
        }
        else {
                save_individual_event(NULL, 0L, "", 0, NULL);
@@ -1178,7 +1257,9 @@ void save_event(void) {
 /*
  * Anonymous request of freebusy data for a user
  */
-void do_freebusy(const char *req) {
+void do_freebusy(void)
+{ /// TODO: request line const char *req) {
+       const char req[] = "";
        char who[SIZ];
        char buf[SIZ];
        int len;
@@ -1217,7 +1298,6 @@ void do_freebusy(const char *req) {
 
 
 
-
 void 
 InitModule_CALENDAR
 (void)
@@ -1226,6 +1306,7 @@ InitModule_CALENDAR
        RegisterPreference("dayend", _("Calendar day view ends at:"), PRF_INT, NULL);
        RegisterPreference("weekstart", _("Week starts on:"), PRF_INT, NULL);
 
+       WebcitAddUrlHandler(HKEY("freebusy"), do_freebusy, COOKIEUNNEEDED|ANONYMOUS|FORCE_SESSIONCLOSE);
        WebcitAddUrlHandler(HKEY("display_edit_task"), display_edit_task, 0);
        WebcitAddUrlHandler(HKEY("save_task"), save_task, 0);
        WebcitAddUrlHandler(HKEY("display_edit_event"), display_edit_event, 0);