The CtdlWriteObject() API no longer uses a temp file
[citadel.git] / citadel / modules / calendar / serv_calendar.c
index cc134e0d1a721623ca9e06b623a4ef78e66fa576..41bedf0268047948043c0daec435e99abed8e7b6 100644 (file)
@@ -105,8 +105,6 @@ icalcomponent *ical_encapsulate_subcomponent(icalcomponent *subcomp) {
  * to the currently selected room.
  */
 void ical_write_to_cal(struct ctdluser *u, icalcomponent *cal) {
-       char temp[PATH_MAX];
-       FILE *fp = NULL;
        char *ser = NULL;
        icalcomponent *encaps = NULL;
        struct CtdlMessage *msg = NULL;
@@ -131,24 +129,16 @@ void ical_write_to_cal(struct ctdluser *u, icalcomponent *cal) {
 
        /* If the caller supplied a user, write to that user's default calendar room */
        if (u) {
-               /* Make a temp file out of it */
-               CtdlMakeTempFileName(temp, sizeof temp);
-               fp = fopen(temp, "w");
-               if (fp != NULL) {
-                       fwrite(ser, strlen(ser), 1, fp);
-                       fclose(fp);
-               
-                       /* This handy API function does all the work for us. */
-                       CtdlWriteObject(USERCALENDARROOM,       /* which room */
-                               "text/calendar",        /* MIME type */
-                               temp,                   /* temp file */
-                               u,                      /* which user */
-                               0,                      /* not binary */
-                               0,                      /* don't delete others of this type */
-                               0                       /* no flags */
-                       );
-                       unlink(temp);
-               }
+               /* This handy API function does all the work for us. */
+               CtdlWriteObject(USERCALENDARROOM,       /* which room */
+                       "text/calendar",        /* MIME type */
+                       ser,                    /* data */
+                       strlen(ser)+1,          /* length */
+                       u,                      /* which user */
+                       0,                      /* not binary */
+                       0,                      /* don't delete others of this type */
+                       0                       /* no flags */
+               );
        }
 
        /* If the caller did not supply a user, write to the currently selected room */
@@ -167,7 +157,7 @@ void ical_write_to_cal(struct ctdluser *u, icalcomponent *cal) {
                strcat(msg->cm_fields['M'], ser);
        
                /* Now write the data */
-               CtdlSubmitMsg(msg, NULL, "");
+               CtdlSubmitMsg(msg, NULL, "", QP_EADDR);
                CtdlFreeMessage(msg);
        }
 
@@ -332,7 +322,7 @@ void ical_send_a_reply(icalcomponent *request, char *action) {
        reply_message_text = malloc(strlen(serialized_reply) + SIZ);
        if (reply_message_text != NULL) {
                sprintf(reply_message_text,
-                       "Content-type: text/calendar charset=\"utf-8\"\r\n\r\n%s\r\n",
+                       "Content-type: text/calendar; charset=\"utf-8\"\r\n\r\n%s\r\n",
                        serialized_reply
                );
 
@@ -349,7 +339,7 @@ void ical_send_a_reply(icalcomponent *request, char *action) {
        
                if (msg != NULL) {
                        valid = validate_recipients(organizer_string, NULL, 0);
-                       CtdlSubmitMsg(msg, valid, "");
+                       CtdlSubmitMsg(msg, valid, "", QP_EADDR);
                        CtdlFreeMessage(msg);
                        free_recipients(valid);
                }
@@ -656,7 +646,7 @@ int ical_update_my_calendar_with_reply(icalcomponent *cal) {
        /*
         * Look in the EUID index for a message with
         * the Citadel EUID set to the value we're looking for.  Since
-        * Citadel always sets the message EUID to the vCalendar UID of
+        * Citadel always sets the message EUID to the iCalendar UID of
         * the event, this will work.
         */
        msgnum_being_replaced = locate_message_by_euid(uid, &CC->room);
@@ -707,7 +697,7 @@ int ical_update_my_calendar_with_reply(icalcomponent *cal) {
        message_text = malloc(strlen(serialized_event) + SIZ);
        if (message_text != NULL) {
                sprintf(message_text,
-                       "Content-type: text/calendar charset=\"utf-8\"\r\n\r\n%s\r\n",
+                       "Content-type: text/calendar; charset=\"utf-8\"\r\n\r\n%s\r\n",
                        serialized_event
                );
 
@@ -725,7 +715,7 @@ int ical_update_my_calendar_with_reply(icalcomponent *cal) {
        
                if (msg != NULL) {
                        CIT_ICAL->avoid_sending_invitations = 1;
-                       CtdlSubmitMsg(msg, NULL, roomname);
+                       CtdlSubmitMsg(msg, NULL, roomname, QP_EADDR);
                        CtdlFreeMessage(msg);
                        CIT_ICAL->avoid_sending_invitations = 0;
                }
@@ -1425,7 +1415,7 @@ void ical_getics(void)
        if ( (CC->room.QRdefaultview != VIEW_CALENDAR)
           &&(CC->room.QRdefaultview != VIEW_TASKS) ) {
                cprintf("%d Not a calendar room\n", ERROR+NOT_HERE);
-               return;         /* Not a vCalendar-centric room */
+               return;         /* Not an iCalendar-centric room */
        }
 
        encaps = icalcomponent_new_vcalendar();
@@ -1477,7 +1467,7 @@ void ical_putics(void)
        if ( (CC->room.QRdefaultview != VIEW_CALENDAR)
           &&(CC->room.QRdefaultview != VIEW_TASKS) ) {
                cprintf("%d Not a calendar room\n", ERROR+NOT_HERE);
-               return;         /* Not a vCalendar-centric room */
+               return;         /* Not an iCalendar-centric room */
        }
 
        if (!CtdlDoIHavePermissionToDeleteMessagesFromThisRoom()) {
@@ -1799,7 +1789,7 @@ void ical_send_out_invitations(icalcomponent *cal) {
        
                if (msg != NULL) {
                        valid = validate_recipients(attendees_string, NULL, 0);
-                       CtdlSubmitMsg(msg, valid, "");
+                       CtdlSubmitMsg(msg, valid, "", QP_EADDR);
                        CtdlFreeMessage(msg);
                        free_recipients(valid);
                }
@@ -1875,16 +1865,17 @@ void ical_saving_vevent(icalcomponent *cal) {
  * the summary of the event (becomes message subject),
  * and the start time (becomes message date/time).
  */
-void ical_ctdl_set_exclusive_msgid(char *name, char *filename, char *partnum,
+void ical_obj_beforesave_backend(char *name, char *filename, char *partnum,
                char *disp, void *content, char *cbtype, char *cbcharset, size_t length,
                char *encoding, void *cbuserdata)
 {
        icalcomponent *cal, *nested_event, *nested_todo, *whole_cal;
        icalproperty *p;
-       struct icalmessagemod *imm;
-       char new_uid[SIZ];
+       char new_uid[256] = "";
+       char buf[1024] = "";
+       struct CtdlMessage *msg = (struct CtdlMessage *) cbuserdata;
 
-       imm = (struct icalmessagemod *)cbuserdata;
+       if (!msg) return;
 
        /* We're only interested in calendar data. */
        if (  (strcasecmp(cbtype, "text/calendar"))
@@ -1916,6 +1907,9 @@ void ical_ctdl_set_exclusive_msgid(char *name, char *filename, char *partnum,
                }
                
                if (cal != NULL) {
+
+                       /* Set the message EUID to the iCalendar UID */
+
                        p = ical_ctdl_get_subprop(cal, ICAL_UID_PROPERTY);
                        if (p == NULL) {
                                /* If there's no uid we must generate one */
@@ -1924,16 +1918,44 @@ void ical_ctdl_set_exclusive_msgid(char *name, char *filename, char *partnum,
                                p = ical_ctdl_get_subprop(cal, ICAL_UID_PROPERTY);
                        }
                        if (p != NULL) {
-                               strcpy(imm->uid, icalproperty_get_comment(p));
+                               safestrncpy(buf, icalproperty_get_comment(p), sizeof buf);
+                               if (!IsEmptyStr(buf)) {
+                                       if (msg->cm_fields['E'] != NULL) {
+                                               free(msg->cm_fields['E']);
+                                       }
+                                       msg->cm_fields['E'] = strdup(buf);
+                                       CtdlLogPrintf(CTDL_DEBUG, "Saving calendar UID <%s>\n", buf);
+                               }
                        }
+
+                       /* Set the message subject to the iCalendar summary */
+
                        p = ical_ctdl_get_subprop(cal, ICAL_SUMMARY_PROPERTY);
                        if (p != NULL) {
-                               strcpy(imm->subject, icalproperty_get_comment(p));
+                               safestrncpy(buf, icalproperty_get_comment(p), sizeof buf);
+                               if (!IsEmptyStr(buf)) {
+                                       if (msg->cm_fields['U'] != NULL) {
+                                               free(msg->cm_fields['U']);
+                                       }
+                                       msg->cm_fields['U'] = strdup(buf);
+                               }
                        }
+
+                       /* Set the message date/time to the iCalendar start time */
+
                        p = ical_ctdl_get_subprop(cal, ICAL_DTSTART_PROPERTY);
                        if (p != NULL) {
-                               imm->dtstart = icaltime_as_timet(icalproperty_get_dtstart(p));
+                               time_t idtstart;
+                               idtstart = icaltime_as_timet(icalproperty_get_dtstart(p));
+                               if (idtstart > 0) {
+                                       if (msg->cm_fields['T'] != NULL) {
+                                               free(msg->cm_fields['T']);
+                                       }
+                                       msg->cm_fields['T'] = strdup("000000000000000000");
+                                       sprintf(msg->cm_fields['T'], "%ld", idtstart);
+                               }
                        }
+
                }
                icalcomponent_free(cal);
                if (whole_cal != cal) {
@@ -1947,24 +1969,18 @@ void ical_ctdl_set_exclusive_msgid(char *name, char *filename, char *partnum,
 
 /*
  * See if we need to prevent the object from being saved (we don't allow
- * MIME types other than text/calendar in "calendar" or "tasks"  rooms).  Also,
- * when saving an event to the calendar, set the message's Citadel exclusive
- * message ID to the UID of the object.  This causes our replication checker to
- * automatically delete any existing instances of the same object.  (Isn't
- * that cool?)
+ * MIME types other than text/calendar in "calendar" or "tasks" rooms).
  *
- * We also set the message's Subject to the event summary, and the Date/time to
- * the event start time.
+ * If the message is being saved, we also set various message header fields
+ * using data found in the iCalendar object.
  */
 int ical_obj_beforesave(struct CtdlMessage *msg)
 {
-       struct icalmessagemod imm;
-
        /* First determine if this is a calendar or tasks room */
        if (  (CC->room.QRdefaultview != VIEW_CALENDAR)
           && (CC->room.QRdefaultview != VIEW_TASKS)
        ) {
-               return(0);              /* Not a vCalendar-centric room */
+               return(0);              /* Not an iCalendar-centric room */
        }
 
        /* It must be an RFC822 message! */
@@ -1977,38 +1993,15 @@ int ical_obj_beforesave(struct CtdlMessage *msg)
                return(1);              /* You tried to save a null message! */
        }
 
-       memset(&imm, 0, sizeof(struct icalmessagemod));
-       
        /* Do all of our lovely back-end parsing */
        mime_parser(msg->cm_fields['M'],
                NULL,
-               *ical_ctdl_set_exclusive_msgid,
+               *ical_obj_beforesave_backend,
                NULL, NULL,
-               (void *)&imm,
+               (void *)msg,
                0
        );
 
-       if (!IsEmptyStr(imm.uid)) {
-               if (msg->cm_fields['E'] != NULL) {
-                       free(msg->cm_fields['E']);
-               }
-               msg->cm_fields['E'] = strdup(imm.uid);
-               CtdlLogPrintf(CTDL_DEBUG, "Saving calendar UID <%s>\n", msg->cm_fields['E']);
-       }
-       if (!IsEmptyStr(imm.subject)) {
-               if (msg->cm_fields['U'] != NULL) {
-                       free(msg->cm_fields['U']);
-               }
-               msg->cm_fields['U'] = strdup(imm.subject);
-       }
-       if (imm.dtstart > 0) {
-               if (msg->cm_fields['T'] != NULL) {
-                       free(msg->cm_fields['T']);
-               }
-               msg->cm_fields['T'] = strdup("000000000000000000");
-               sprintf(msg->cm_fields['T'], "%ld", imm.dtstart);
-       }
-
        return(0);
 }
 
@@ -2142,7 +2135,7 @@ void ical_fixed_output_backend(icalcomponent *cal,
 
 
 /*
- * Function to output vcalendar data as plain text.  Nobody uses MSG0
+ * Function to output iCalendar data as plain text.  Nobody uses MSG0
  * anymore, so really this is just so we expose the vCard data to the full
  * text indexer.
  */