Protect precious strlens, as pointed out by John Goerzen
[citadel.git] / citadel / modules / calendar / serv_calendar.c
index 0d971d9d9677adbefc631acdd927254e6427f55b..8fc0dbad1e351f3457a1a2a0d43942bf2dcfe4e7 100644 (file)
@@ -3,22 +3,15 @@
  * room on a Citadel server.  It handles iCalendar objects using the
  * iTIP protocol.  See RFCs 2445 and 2446.
  *
+ * Copyright (c) 1987-2015 by the citadel.org team
  *
- * Copyright (c) 1987-2011 by the citadel.org team
+ * This program is open source software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3.
  *
- *  This program is open source software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 3 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
  */
 
 #define PRODID "-//Citadel//NONSGML Citadel Calendar//EN"
 #include "msgbase.h"
 #include "internet_addressing.h"
 #include "serv_calendar.h"
+#include "room_ops.h"
 #include "euidindex.h"
 #include "ical_dezonify.h"
+#include "config.h"
 
 
 
@@ -98,6 +93,7 @@ icalcomponent *ical_encapsulate_subcomponent(icalcomponent *subcomp) {
  */
 void ical_write_to_cal(struct ctdluser *u, icalcomponent *cal) {
        char *ser = NULL;
+       long serlen;
        icalcomponent *encaps = NULL;
        struct CtdlMessage *msg = NULL;
        icalcomponent *tmp=NULL;
@@ -119,13 +115,15 @@ void ical_write_to_cal(struct ctdluser *u, icalcomponent *cal) {
        ser = icalcomponent_as_ical_string_r(cal);
        if (ser == NULL) return;
 
+       serlen = strlen(ser);
+
        /* If the caller supplied a user, write to that user's default calendar room */
        if (u) {
                /* This handy API function does all the work for us. */
                CtdlWriteObject(USERCALENDARROOM,       /* which room */
                        "text/calendar",        /* MIME type */
                        ser,                    /* data */
-                       strlen(ser)+1,          /* length */
+                       serlen + 1,             /* length */
                        u,                      /* which user */
                        0,                      /* not binary */
                        0,                      /* don't delete others of this type */
@@ -135,22 +133,28 @@ void ical_write_to_cal(struct ctdluser *u, icalcomponent *cal) {
 
        /* If the caller did not supply a user, write to the currently selected room */
        if (!u) {
+               struct CitContext *CCC = CC;
+               StrBuf *MsgBody;
+
                msg = malloc(sizeof(struct CtdlMessage));
                memset(msg, 0, sizeof(struct CtdlMessage));
                msg->cm_magic = CTDLMESSAGE_MAGIC;
                msg->cm_anon_type = MES_NORMAL;
                msg->cm_format_type = 4;
-               msg->cm_fields[eAuthor] = strdup(CC->user.fullname);
-               msg->cm_fields[eOriginalRoom] = strdup(CC->room.QRname);
-               msg->cm_fields[eNodeName] = strdup(config.c_nodename);
-               msg->cm_fields[eHumanNode] = strdup(config.c_humannode);
-               msg->cm_fields[eMesageText] = malloc(strlen(ser) + 40);
-               strcpy(msg->cm_fields[eMesageText], "Content-type: text/calendar\r\n\r\n");
-               strcat(msg->cm_fields[eMesageText], ser);
+               CM_SetField(msg, eAuthor, CCC->user.fullname, strlen(CCC->user.fullname));
+               CM_SetField(msg, eOriginalRoom, CCC->room.QRname, strlen(CCC->room.QRname));
+               CM_SetField(msg, eNodeName, CtdlGetConfigStr("c_nodename"), strlen(CtdlGetConfigStr("c_nodename")));
+               CM_SetField(msg, eHumanNode, CtdlGetConfigStr("c_humannode"), strlen(CtdlGetConfigStr("c_humannode")));
+
+               MsgBody = NewStrBufPlain(NULL, serlen + 100);
+               StrBufAppendBufPlain(MsgBody, HKEY("Content-type: text/calendar\r\n\r\n"), 0);
+               StrBufAppendBufPlain(MsgBody, ser, serlen, 0);
+
+               CM_SetAsFieldSB(msg, eMesageText, &MsgBody);
        
                /* Now write the data */
                CtdlSubmitMsg(msg, NULL, "", QP_EADDR);
-               CtdlFreeMessage(msg);
+               CM_Free(msg);
        }
 
        /* In either case, now we can free the serialized calendar object */
@@ -175,15 +179,15 @@ void ical_send_a_reply(icalcomponent *request, char *action) {
        icalproperty *summary = NULL;
        char summary_string[SIZ];
        icalproperty *me_attend = NULL;
-       struct recptypes *recp = NULL;
+       recptypes *recp = NULL;
        icalparameter *partstat = NULL;
        char *serialized_reply = NULL;
        char *reply_message_text = NULL;
        const char *ch;
        struct CtdlMessage *msg = NULL;
-       struct recptypes *valid = NULL;
+       recptypes *valid = NULL;
 
-       strcpy(organizer_string, "");
+       *organizer_string = '\0';
        strcpy(summary_string, "Calendar item");
 
        if (request == NULL) {
@@ -302,7 +306,7 @@ void ical_send_a_reply(icalcomponent *request, char *action) {
                if (msg != NULL) {
                        valid = validate_recipients(organizer_string, NULL, 0);
                        CtdlSubmitMsg(msg, valid, "", QP_EADDR);
-                       CtdlFreeMessage(msg);
+                       CM_Free(msg);
                        free_recipients(valid);
                }
        }
@@ -365,7 +369,7 @@ void ical_respond(long msgnum, char *partnum, char *action) {
                return;
        }
 
-       msg = CtdlFetchMessage(msgnum, 1);
+       msg = CtdlFetchMessage(msgnum, 1, 1);
        if (msg == NULL) {
                cprintf("%d Message %ld not found.\n",
                        ERROR + ILLEGAL_VALUE,
@@ -376,18 +380,17 @@ void ical_respond(long msgnum, char *partnum, char *action) {
 
        memset(&ird, 0, sizeof ird);
        strcpy(ird.desired_partnum, partnum);
-       mime_parser(msg->cm_fields[eMesageText],
-               NULL,
-               *ical_locate_part,              /* callback function */
-               NULL, NULL,
-               (void *) &ird,                  /* user data */
-               0
+       mime_parser(CM_RANGE(msg, eMesageText),
+                   *ical_locate_part,          /* callback function */
+                   NULL, NULL,
+                   (void *) &ird,                      /* user data */
+                   0
        );
 
        /* We're done with the incoming message, because we now have a
         * calendar object in memory.
         */
-       CtdlFreeMessage(msg);
+       CM_Free(msg);
 
        /*
         * Here is the real meat of this function.  Handle the event.
@@ -627,19 +630,18 @@ int ical_update_my_calendar_with_reply(icalcomponent *cal) {
         * us the ability to load the event into memory so we can diddle the
         * attendees.
         */
-       msg = CtdlFetchMessage(msgnum_being_replaced, 1);
+       msg = CtdlFetchMessage(msgnum_being_replaced, 1, 1);
        if (msg == NULL) {
                return(2);                      /* internal error */
        }
        oec.c = NULL;
-       mime_parser(msg->cm_fields[eMesageText],
-               NULL,
-               *ical_locate_original_event,    /* callback function */
-               NULL, NULL,
-               &oec,                           /* user data */
-               0
+       mime_parser(CM_RANGE(msg, eMesageText),
+                   *ical_locate_original_event,        /* callback function */
+                   NULL, NULL,
+                   &oec,                               /* user data */
+                   0
        );
-       CtdlFreeMessage(msg);
+       CM_Free(msg);
 
        original_event = oec.c;
        if (original_event == NULL) {
@@ -679,7 +681,7 @@ int ical_update_my_calendar_with_reply(icalcomponent *cal) {
                if (msg != NULL) {
                        CIT_ICAL->avoid_sending_invitations = 1;
                        CtdlSubmitMsg(msg, NULL, roomname, QP_EADDR);
-                       CtdlFreeMessage(msg);
+                       CM_Free(msg);
                        CIT_ICAL->avoid_sending_invitations = 0;
                }
        }
@@ -708,7 +710,7 @@ void ical_handle_rsvp(long msgnum, char *partnum, char *action) {
                return;
        }
 
-       msg = CtdlFetchMessage(msgnum, 1);
+       msg = CtdlFetchMessage(msgnum, 1, 1);
        if (msg == NULL) {
                cprintf("%d Message %ld not found.\n",
                        ERROR + ILLEGAL_VALUE,
@@ -719,18 +721,17 @@ void ical_handle_rsvp(long msgnum, char *partnum, char *action) {
 
        memset(&ird, 0, sizeof ird);
        strcpy(ird.desired_partnum, partnum);
-       mime_parser(msg->cm_fields[eMesageText],
-               NULL,
-               *ical_locate_part,              /* callback function */
-               NULL, NULL,
-               (void *) &ird,                  /* user data */
-               0
-       );
+       mime_parser(CM_RANGE(msg, eMesageText),
+                   *ical_locate_part,          /* callback function */
+                   NULL, NULL,
+                   (void *) &ird,                      /* user data */
+                   0
+               );
 
        /* We're done with the incoming message, because we now have a
         * calendar object in memory.
         */
-       CtdlFreeMessage(msg);
+       CM_Free(msg);
 
        /*
         * Here is the real meat of this function.  Handle the event.
@@ -905,11 +906,11 @@ int ical_conflicts_phase6(struct icaltimetype t1start,
                        existing_msgnum,
                        conflict_event_uid,
                        conflict_event_summary,
-                       (       ((strlen(compare_uid)>0)
+                       (       (!IsEmptyStr(compare_uid)
                                &&(!strcasecmp(compare_uid,
                                conflict_event_uid))) ? 1 : 0
-                       )
-               );
+                               )
+                       );
                conflict_reported = 1;
        }
 
@@ -1147,18 +1148,17 @@ void ical_hunt_for_conflicts_backend(long msgnum, void *data) {
 
        proposed_event = (icalcomponent *)data;
 
-       msg = CtdlFetchMessage(msgnum, 1);
+       msg = CtdlFetchMessage(msgnum, 1, 1);
        if (msg == NULL) return;
        memset(&ird, 0, sizeof ird);
        strcpy(ird.desired_partnum, "_HUNT_");
-       mime_parser(msg->cm_fields[eMesageText],
-               NULL,
-               *ical_locate_part,              /* callback function */
-               NULL, NULL,
-               (void *) &ird,                  /* user data */
-               0
+       mime_parser(CM_RANGE(msg, eMesageText),
+                   *ical_locate_part,          /* callback function */
+                   NULL, NULL,
+                   (void *) &ird,                      /* user data */
+                   0
        );
-       CtdlFreeMessage(msg);
+       CM_Free(msg);
 
        if (ird.cal == NULL) return;
 
@@ -1209,7 +1209,7 @@ void ical_conflicts(long msgnum, char *partnum) {
        struct CtdlMessage *msg = NULL;
        struct ical_respond_data ird;
 
-       msg = CtdlFetchMessage(msgnum, 1);
+       msg = CtdlFetchMessage(msgnum, 1, 1);
        if (msg == NULL) {
                cprintf("%d Message %ld not found\n",
                        ERROR + ILLEGAL_VALUE,
@@ -1220,15 +1220,14 @@ void ical_conflicts(long msgnum, char *partnum) {
 
        memset(&ird, 0, sizeof ird);
        strcpy(ird.desired_partnum, partnum);
-       mime_parser(msg->cm_fields[eMesageText],
-               NULL,
-               *ical_locate_part,              /* callback function */
-               NULL, NULL,
-               (void *) &ird,                  /* user data */
-               0
-       );
+       mime_parser(CM_RANGE(msg, eMesageText),
+                   *ical_locate_part,          /* callback function */
+                   NULL, NULL,
+                   (void *) &ird,                      /* user data */
+                   0
+               );
 
-       CtdlFreeMessage(msg);
+       CM_Free(msg);
 
        if (ird.cal != NULL) {
                ical_hunt_for_conflicts(ird.cal);
@@ -1397,18 +1396,17 @@ void ical_freebusy_backend(long msgnum, void *data) {
 
        fb = (icalcomponent *)data;             /* User-supplied data will be the VFREEBUSY component */
 
-       msg = CtdlFetchMessage(msgnum, 1);
+       msg = CtdlFetchMessage(msgnum, 1, 1);
        if (msg == NULL) return;
        memset(&ird, 0, sizeof ird);
        strcpy(ird.desired_partnum, "_HUNT_");
-       mime_parser(msg->cm_fields[eMesageText],
-               NULL,
-               *ical_locate_part,              /* callback function */
-               NULL, NULL,
-               (void *) &ird,                  /* user data */
-               0
-       );
-       CtdlFreeMessage(msg);
+       mime_parser(CM_RANGE(msg, eMesageText),
+                   *ical_locate_part,          /* callback function */
+                   NULL, NULL,
+                   (void *) &ird,                      /* user data */
+                   0
+               );
+       CM_Free(msg);
 
        if (ird.cal) {
                ical_add_to_freebusy(fb, ird.cal);              /* Add VEVENT times to VFREEBUSY */
@@ -1429,7 +1427,7 @@ void ical_freebusy(char *who) {
        icalcomponent *encaps = NULL;
        icalcomponent *fb = NULL;
        int found_user = (-1);
-       struct recptypes *recp = NULL;
+       recptypes *recp = NULL;
        char buf[256];
        char host[256];
        char type[256];
@@ -1456,7 +1454,7 @@ void ical_freebusy(char *who) {
         * primary FQDN of this Citadel node.
         */
        if (found_user != 0) {
-               snprintf(buf, sizeof buf, "%s@%s", who, config.c_fqdn);
+               snprintf(buf, sizeof buf, "%s@%s", who, CtdlGetConfigStr("c_fqdn"));
                syslog(LOG_DEBUG, "Trying <%s>\n", buf);
                recp = validate_recipients(buf, NULL, 0);
                if (recp != NULL) {
@@ -1528,7 +1526,7 @@ void ical_freebusy(char *who) {
        sprintf(buf, "MAILTO:%s", who);
        if (strchr(buf, '@') == NULL) {
                strcat(buf, "@");
-               strcat(buf, config.c_fqdn);
+               strcat(buf, CtdlGetConfigStr("c_fqdn"));
        }
        for (i=0; buf[i]; ++i) {
                if (buf[i]==' ') buf[i] = '_';
@@ -1598,18 +1596,17 @@ void ical_getics_backend(long msgnum, void *data) {
 
        /* Look for the calendar event... */
 
-       msg = CtdlFetchMessage(msgnum, 1);
+       msg = CtdlFetchMessage(msgnum, 1, 1);
        if (msg == NULL) return;
        memset(&ird, 0, sizeof ird);
        strcpy(ird.desired_partnum, "_HUNT_");
-       mime_parser(msg->cm_fields[eMesageText],
-               NULL,
-               *ical_locate_part,              /* callback function */
-               NULL, NULL,
-               (void *) &ird,                  /* user data */
-               0
+       mime_parser(CM_RANGE(msg, eMesageText),
+                   *ical_locate_part,          /* callback function */
+                   NULL, NULL,
+                   (void *) &ird,                      /* user data */
+                   0
        );
-       CtdlFreeMessage(msg);
+       CM_Free(msg);
 
        if (ird.cal == NULL) return;
 
@@ -1752,7 +1749,7 @@ void ical_putics(void)
        }
 
        cprintf("%d Transmit data now\n", SEND_LISTING);
-       calstream = CtdlReadMessageBody(HKEY("000"), config.c_maxmsglen, NULL, 0, 0);
+       calstream = CtdlReadMessageBody(HKEY("000"), CtdlGetConfigLong("c_maxmsglen"), NULL, 0, 0);
        if (calstream == NULL) {
                return;
        }
@@ -1989,7 +1986,7 @@ void ical_send_out_invitations(icalcomponent *top_level_cal, icalcomponent *cal)
        icalcomponent *encaps = NULL;
        char *request_message_text = NULL;
        struct CtdlMessage *msg = NULL;
-       struct recptypes *valid = NULL;
+       recptypes *valid = NULL;
        char attendees_string[SIZ];
        int num_attendees = 0;
        char this_attendee[256];
@@ -2201,7 +2198,7 @@ void ical_send_out_invitations(icalcomponent *top_level_cal, icalcomponent *cal)
                if (msg != NULL) {
                        valid = validate_recipients(attendees_string, NULL, 0);
                        CtdlSubmitMsg(msg, valid, "", QP_EADDR);
-                       CtdlFreeMessage(msg);
+                       CM_Free(msg);
                        free_recipients(valid);
                }
        }
@@ -2285,10 +2282,10 @@ void ical_obj_beforesave_backend(char *name, char *filename, char *partnum,
                char *disp, void *content, char *cbtype, char *cbcharset, size_t length,
                char *encoding, char *cbid, void *cbuserdata)
 {
+       const char* pch;
        icalcomponent *cal, *nested_event, *nested_todo, *whole_cal;
        icalproperty *p;
        char new_uid[256] = "";
-       char buf[1024] = "";
        struct CtdlMessage *msg = (struct CtdlMessage *) cbuserdata;
 
        if (!msg) return;
@@ -2334,13 +2331,10 @@ void ical_obj_beforesave_backend(char *name, char *filename, char *partnum,
                                p = ical_ctdl_get_subprop(cal, ICAL_UID_PROPERTY);
                        }
                        if (p != NULL) {
-                               safestrncpy(buf, icalproperty_get_comment(p), sizeof buf);
-                               if (!IsEmptyStr(buf)) {
-                                       if (msg->cm_fields[eExclusiveID] != NULL) {
-                                               free(msg->cm_fields[eExclusiveID]);
-                                       }
-                                       msg->cm_fields[eExclusiveID] = strdup(buf);
-                                       syslog(LOG_DEBUG, "Saving calendar UID <%s>\n", buf);
+                               pch = icalproperty_get_comment(p);
+                               if (!IsEmptyStr(pch)) {
+                                       CM_SetField(msg, eExclusiveID, pch, strlen(pch));
+                                       syslog(LOG_DEBUG, "Saving calendar UID <%s>\n", pch);
                                }
                        }
 
@@ -2348,12 +2342,12 @@ void ical_obj_beforesave_backend(char *name, char *filename, char *partnum,
 
                        p = ical_ctdl_get_subprop(cal, ICAL_SUMMARY_PROPERTY);
                        if (p != NULL) {
-                               safestrncpy(buf, icalproperty_get_comment(p), sizeof buf);
-                               if (!IsEmptyStr(buf)) {
-                                       if (msg->cm_fields[eMsgSubject] != NULL) {
-                                               free(msg->cm_fields[eMsgSubject]);
-                                       }
-                                       msg->cm_fields[eMsgSubject] = rfc2047encode(buf, strlen(buf));
+                               pch = icalproperty_get_comment(p);
+                               if (!IsEmptyStr(pch)) {
+                                       char *subj;
+
+                                       subj = rfc2047encode(pch, strlen(pch));
+                                       CM_SetAsField(msg, eMsgSubject, &subj, strlen(subj));
                                }
                        }
 
@@ -2364,11 +2358,7 @@ void ical_obj_beforesave_backend(char *name, char *filename, char *partnum,
                                time_t idtstart;
                                idtstart = icaltime_as_timet(icalproperty_get_dtstart(p));
                                if (idtstart > 0) {
-                                       if (msg->cm_fields[eTimestamp] != NULL) {
-                                               free(msg->cm_fields[eTimestamp]);
-                                       }
-                                       msg->cm_fields[eTimestamp] = strdup("000000000000000000");
-                                       sprintf(msg->cm_fields[eTimestamp], "%ld", idtstart);
+                                       CM_SetFieldLONG(msg, eTimestamp, idtstart);
                                }
                        }
 
@@ -2390,7 +2380,7 @@ void ical_obj_beforesave_backend(char *name, char *filename, char *partnum,
  * 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)
+int ical_obj_beforesave(struct CtdlMessage *msg, recptypes *recp)
 {
        /* First determine if this is a calendar or tasks room */
        if (  (CC->room.QRdefaultview != VIEW_CALENDAR)
@@ -2405,18 +2395,17 @@ int ical_obj_beforesave(struct CtdlMessage *msg)
                return(1);              /* You tried to save a non-RFC822 message! */
        }
 
-       if (msg->cm_fields[eMesageText] == NULL) {
+       if (CM_IsEmpty(msg, eMesageText)) {
                return(1);              /* You tried to save a null message! */
        }
 
        /* Do all of our lovely back-end parsing */
-       mime_parser(msg->cm_fields[eMesageText],
-               NULL,
-               *ical_obj_beforesave_backend,
-               NULL, NULL,
-               (void *)msg,
-               0
-       );
+       mime_parser(CM_RANGE(msg, eMesageText),
+                   *ical_obj_beforesave_backend,
+                   NULL, NULL,
+                   (void *)msg,
+                   0
+               );
 
        return(0);
 }
@@ -2458,7 +2447,7 @@ void ical_obj_aftersave_backend(char *name, char *filename, char *partnum,
  * (This will start back end tasks such as automatic generation of invitations,
  * if such actions are appropriate.)
  */
-int ical_obj_aftersave(struct CtdlMessage *msg)
+int ical_obj_aftersave(struct CtdlMessage *msg, recptypes *recp)
 {
        char roomname[ROOMNAMELEN];
 
@@ -2476,16 +2465,15 @@ int ical_obj_aftersave(struct CtdlMessage *msg)
        if (msg->cm_format_type != 4) return(1);
 
        /* Reject null messages */
-       if (msg->cm_fields[eMesageText] == NULL) return(1);
+       if (CM_IsEmpty(msg, eMesageText)) return(1);
        
        /* Now recurse through it looking for our icalendar data */
-       mime_parser(msg->cm_fields[eMesageText],
-               NULL,
-               *ical_obj_aftersave_backend,
-               NULL, NULL,
-               NULL,
-               0
-       );
+       mime_parser(CM_RANGE(msg, eMesageText),
+                   *ical_obj_aftersave_backend,
+                   NULL, NULL,
+                   NULL,
+                   0
+               );
 
        return(0);
 }