Assert that eMessageText MUST be serialized last.
[citadel.git] / citadel / server / msgbase.c
index 8a709492334a0d88cb3c586efefdb81b21964c8c..259a3e5ab2994febe129e78febbdca89f6b31015 100644 (file)
@@ -52,7 +52,7 @@ char *msgkeys[] = {
        "jrnl", // J -> eJournal
        "rep2", // K -> eReplyTo
        "list", // L -> eListID
-       "text", // M -> eMesageText
+       "text", // M -> eMessageText
        NULL,   // N (formerly used as eNodename)
        "room", // O -> eOriginalRoom
        "path", // P -> eMessagePath
@@ -121,7 +121,7 @@ eMsgField FieldOrder[]  = {
        eSuppressIdx ,
        eExtnotify   ,
 // Message text (MUST be last)
-       eMesageText 
+       eMessageText 
 // Not saved to disk: 
 //     eVltMsgNum
 //
@@ -1102,14 +1102,14 @@ struct CtdlMessage *CtdlFetchMessage(long msgnum, int with_body) {
        // so go ahead and fetch that.  Failing that, just set a dummy
        // body so other code doesn't barf.
        //
-       if ( (CM_IsEmpty(ret, eMesageText)) && (with_body) ) {
+       if ( (CM_IsEmpty(ret, eMessageText)) && (with_body) ) {
                dmsgtext = cdb_fetch(CDB_BIGMSGS, &msgnum, sizeof(long));
                if (dmsgtext.ptr != NULL) {
-                       CM_SetField(ret, eMesageText, dmsgtext.ptr);
+                       CM_SetField(ret, eMessageText, dmsgtext.ptr);
                }
        }
-       if (CM_IsEmpty(ret, eMesageText)) {
-               CM_SetField(ret, eMesageText, "\r\n\r\n (no text)\r\n");
+       if (CM_IsEmpty(ret, eMessageText)) {
+               CM_SetField(ret, eMessageText, "\r\n\r\n (no text)\r\n");
        }
 
        return (ret);
@@ -1488,7 +1488,7 @@ int CtdlOutputMsg(long msg_num,           // message number (local) to fetch
        if (section) if (!IsEmptyStr(section)) if (strcmp(section, "0")) {
                memset(&encap, 0, sizeof encap);
                safestrncpy(encap.desired_section, section, sizeof encap.desired_section);
-               mime_parser(CM_RANGE(TheMessage, eMesageText),
+               mime_parser(CM_RANGE(TheMessage, eMessageText),
                            *extract_encapsulated_message,
                            NULL, NULL, (void *)&encap, 0
                        );
@@ -1580,7 +1580,7 @@ void OutputCtdlMsgHeaders(struct CtdlMessage *TheMessage, int do_proto) {
        for (i=0; i< NDiskFields; ++i) {
                eMsgField Field;
                Field = FieldOrder[i];
-               if (Field != eMesageText) {
+               if (Field != eMessageText) {
                        if ( (!CM_IsEmpty(TheMessage, Field)) && (msgkeys[Field] != NULL) ) {
                                if ((Field == eenVelopeTo) || (Field == eRecipient) || (Field == eCarbonCopY)) {
                                        sanitize_truncated_recipient(TheMessage->cm_fields[Field]);
@@ -1712,7 +1712,7 @@ void OutputRFC822MsgHeaders(
 
                        case eExclusiveID:
                        case eJournal:
-                       case eMesageText:
+                       case eMessageText:
                        case eBig_message:
                        case eOriginalRoom:
                        case eErrorMsg:
@@ -1748,7 +1748,7 @@ void Dump_RFC822HeadersBody(
        char *mptr;
        int lfSent = 0;
 
-       mptr = TheMessage->cm_fields[eMesageText];
+       mptr = TheMessage->cm_fields[eMessageText];
 
        prev_ch = '\0';
        while (*mptr != '\0') {
@@ -1823,7 +1823,7 @@ void DumpFormatFixed(
        int xlline = 0;
        char *mptr;
 
-       mptr = TheMessage->cm_fields[eMesageText];
+       mptr = TheMessage->cm_fields[eMessageText];
        
        if (mode == MT_MIME) {
                cprintf("Content-type: text/plain\n\n");
@@ -1937,7 +1937,7 @@ int CtdlOutputPreLoadedMsg(
                }
                else {
                        // Parse the message text component
-                       mime_parser(CM_RANGE(TheMessage, eMesageText), *mime_download, NULL, NULL, NULL, 0);
+                       mime_parser(CM_RANGE(TheMessage, eMessageText), *mime_download, NULL, NULL, NULL, 0);
 
                        // If there's no file open by this time, the requested * section wasn't found, so print an error
                        if (CC->download_fp == NULL) {
@@ -1960,7 +1960,7 @@ int CtdlOutputPreLoadedMsg(
                else {
                        // Locate and parse the component specified by the caller
                        int found_it = 0;
-                       mime_parser(CM_RANGE(TheMessage, eMesageText), *mime_spew_section, NULL, NULL, (void *)&found_it, 0);
+                       mime_parser(CM_RANGE(TheMessage, eMessageText), *mime_spew_section, NULL, NULL, (void *)&found_it, 0);
 
                        // If section wasn't found, print an error
                        if (!found_it) {
@@ -2053,7 +2053,7 @@ START_TEXT:
        if (TheMessage->cm_format_type == FMT_RFC822) {
                if ( (mode == MT_CITADEL) || (mode == MT_MIME) ) {
                        memset(&ma, 0, sizeof(struct ma_info));
-                       mime_parser(CM_RANGE(TheMessage, eMesageText),
+                       mime_parser(CM_RANGE(TheMessage, eMessageText),
                                (do_proto ? *list_this_part : NULL),
                                (do_proto ? *list_this_pref : NULL),
                                (do_proto ? *list_this_suff : NULL),
@@ -2095,7 +2095,7 @@ START_TEXT:
                if (mode == MT_MIME) {
                        cprintf("Content-type: text/x-citadel-variformat\n\n");
                }
-               memfmout(TheMessage->cm_fields[eMesageText], nl);
+               memfmout(TheMessage->cm_fields[eMessageText], nl);
        }
 
        // If the message on disk is format 4 (MIME), we've gotta hand it
@@ -2111,15 +2111,15 @@ START_TEXT:
                        strcpy(ma.chosen_part, "1");
                        ma.chosen_pref = 9999;
                        ma.dont_decode = CC->msg4_dont_decode;
-                       mime_parser(CM_RANGE(TheMessage, eMesageText),
+                       mime_parser(CM_RANGE(TheMessage, eMessageText),
                                    *choose_preferred, *fixed_output_pre,
                                    *fixed_output_post, (void *)&ma, 1);
-                       mime_parser(CM_RANGE(TheMessage, eMesageText),
+                       mime_parser(CM_RANGE(TheMessage, eMessageText),
                                    *output_preferred, NULL, NULL, (void *)&ma, 1);
                }
                else {
                        ma.use_fo_hooks = 1;
-                       mime_parser(CM_RANGE(TheMessage, eMesageText),
+                       mime_parser(CM_RANGE(TheMessage, eMessageText),
                                    *fixed_output, *fixed_output_pre,
                                    *fixed_output_post, (void *)&ma, 0);
                }
@@ -2295,27 +2295,26 @@ int CtdlSaveMsgPointerInRoom(char *roomname, long msgid, int do_repl_check, stru
 // called by server-side modules.
 long CtdlSaveThisMessage(struct CtdlMessage *msg, long msgid, int Reply) {
        long retval;
-       struct ser_ret smr;
        int is_bigmsg = 0;
        char *holdM = NULL;
        long holdMLen = 0;
 
        // If the message is big, set its body aside for storage elsewhere and we hide the message body from the serializer
-       if (!CM_IsEmpty(msg, eMesageText) && msg->cm_lengths[eMesageText] > BIGMSG) {
+       if (!CM_IsEmpty(msg, eMessageText) && msg->cm_lengths[eMessageText] > BIGMSG) {
                is_bigmsg = 1;
-               holdM = msg->cm_fields[eMesageText];
-               msg->cm_fields[eMesageText] = NULL;
-               holdMLen = msg->cm_lengths[eMesageText];
-               msg->cm_lengths[eMesageText] = 0;
+               holdM = msg->cm_fields[eMessageText];
+               msg->cm_fields[eMessageText] = NULL;
+               holdMLen = msg->cm_lengths[eMessageText];
+               msg->cm_lengths[eMessageText] = 0;
        }
 
        // Serialize our data structure for storage in the database
-       CtdlSerializeMessage(&smr, msg);
+       struct ser_ret smr = CtdlSerializeMessage(msg);
 
        if (is_bigmsg) {
                // put the message body back into the message
-               msg->cm_fields[eMesageText] = holdM;
-               msg->cm_lengths[eMesageText] = holdMLen;
+               msg->cm_fields[eMessageText] = holdM;
+               msg->cm_lengths[eMessageText] = holdMLen;
        }
 
        if (smr.len == 0) {
@@ -2380,58 +2379,54 @@ long send_message(struct CtdlMessage *msg) {
 
 // Serialize a struct CtdlMessage into the format used on disk.
 // 
-// This function loads up a "struct ser_ret" (defined in server.h) which
+// This function returns a "struct ser_ret" (defined in server.h) which
 // contains the length of the serialized message and a pointer to the
 // serialized message in memory.  THE LATTER MUST BE FREED BY THE CALLER.
-void CtdlSerializeMessage(struct ser_ret *ret,         // return values
-                         struct CtdlMessage *msg)      // unserialized msg
-{
+struct ser_ret CtdlSerializeMessage(struct CtdlMessage *msg) {
+       struct ser_ret ret;
        size_t wlen;
        int i;
 
        // Check for valid message format
        if (CM_IsValidMsg(msg) == 0) {
                syslog(LOG_ERR, "msgbase: CtdlSerializeMessage() aborting due to invalid message");
-               ret->len = 0;
-               ret->ser = NULL;
-               return;
+               ret.len = 0;
+               ret.ser = NULL;
+               return(ret);
        }
 
-       ret->len = 3;
-       for (i=0; i < NDiskFields; ++i)
-               if (msg->cm_fields[FieldOrder[i]] != NULL)
-                       ret->len += msg->cm_lengths[FieldOrder[i]] + 2;
+       ret.len = 3;
+       assert(FieldOrder[NDiskFields-1] == eMessageText);              // Message text MUST be last!
+       for (i=0; i < NDiskFields; ++i) {
+               if (msg->cm_fields[FieldOrder[i]] != NULL) {
+                       ret.len += msg->cm_lengths[FieldOrder[i]] + 2;
+               }
+       }
 
-       ret->ser = malloc(ret->len);
-       if (ret->ser == NULL) {
-               syslog(LOG_ERR, "msgbase: CtdlSerializeMessage() malloc(%ld) failed: %m", (long)ret->len);
-               ret->len = 0;
-               ret->ser = NULL;
-               return;
+       ret.ser = malloc(ret.len);
+       if (ret.ser == NULL) {
+               syslog(LOG_ERR, "msgbase: CtdlSerializeMessage() malloc(%ld) failed: %m", (long)ret.len);
+               ret.len = 0;
+               ret.ser = NULL;
+               return(ret);
        }
 
-       ret->ser[0] = 0xFF;
-       ret->ser[1] = msg->cm_anon_type;
-       ret->ser[2] = msg->cm_format_type;
+       ret.ser[0] = 0xFF;
+       ret.ser[1] = msg->cm_anon_type;
+       ret.ser[2] = msg->cm_format_type;
        wlen = 3;
 
        for (i=0; i < NDiskFields; ++i) {
                if (msg->cm_fields[FieldOrder[i]] != NULL) {
-                       ret->ser[wlen++] = (char)FieldOrder[i];
-
-                       memcpy(&ret->ser[wlen],
-                              msg->cm_fields[FieldOrder[i]],
-                              msg->cm_lengths[FieldOrder[i]] + 1);
-
+                                                                       // future improvement: do the bigmsg check right here
+                       ret.ser[wlen++] = (char)FieldOrder[i];
+                       memcpy(&ret.ser[wlen], msg->cm_fields[FieldOrder[i]], msg->cm_lengths[FieldOrder[i]] + 1);
                        wlen = wlen + msg->cm_lengths[FieldOrder[i]] + 1;
                }
        }
 
-       if (ret->len != wlen) {
-               syslog(LOG_ERR, "msgbase: ERROR; len=%ld wlen=%ld", (long)ret->len, (long)wlen);
-       }
-
-       return;
+       assert(ret.len == wlen);                                        // Make sure we measured it correctly
+       return(ret);
 }
 
 
@@ -2509,7 +2504,7 @@ long CtdlSubmitMsg(struct CtdlMessage *msg,       // message to save
        }
 
        // Learn about what's inside, because it's what's inside that counts
-       if (CM_IsEmpty(msg, eMesageText)) {
+       if (CM_IsEmpty(msg, eMessageText)) {
                syslog(LOG_ERR, "msgbase: ERROR; attempt to save message with NULL body");
                return(-2);
        }
@@ -2523,20 +2518,23 @@ long CtdlSubmitMsg(struct CtdlMessage *msg,     // message to save
                break;
        case 4:
                strcpy(content_type, "text/plain");
-               mptr = bmstrcasestr(msg->cm_fields[eMesageText], "Content-type:");
+               mptr = bmstrcasestr(msg->cm_fields[eMessageText], "Content-type:");
                if (mptr != NULL) {
                        char *aptr;
                        safestrncpy(content_type, &mptr[13], sizeof content_type);
                        string_trim(content_type);
                        aptr = content_type;
                        while (!IsEmptyStr(aptr)) {
-                               if ((*aptr == ';')
-                                   || (*aptr == ' ')
-                                   || (*aptr == 13)
-                                   || (*aptr == 10)) {
+                               if (    (*aptr == ';')
+                                       || (*aptr == ' ')
+                                       || (*aptr == 13)
+                                       || (*aptr == 10)
+                               ) {
                                        *aptr = 0;
                                }
-                               else aptr++;
+                               else {
+                                       aptr++;
+                               }
                        }
                }
        }
@@ -2789,7 +2787,7 @@ long quickie_message(char *from,
                CM_SetField(msg, eMsgSubject, subject);
        }
        if (!IsEmptyStr(text)) {
-               CM_SetField(msg, eMesageText, text);
+               CM_SetField(msg, eMessageText, text);
        }
 
        long msgnum = CtdlSubmitMsg(msg, recp, room);
@@ -3024,10 +3022,12 @@ struct CtdlMessage *CtdlMakeMessageLen(
                        long IsAscii;
                        IsAscii = -1;
                        i = 0;
-                       while ((subject[i] != '\0') && (IsAscii = isascii(subject[i]) != 0 ))
+                       while ((subject[i] != '\0') && (IsAscii = isascii(subject[i]) != 0 )) {
                                i++;
-                       if (IsAscii != 0)
+                       }
+                       if (IsAscii != 0) {
                                CM_SetField(msg, eMsgSubject, subject);
+                       }
                        else {  // ok, we've got utf8 in the string.
                                char *rfc2047Subj;
                                rfc2047Subj = rfc2047encode(subject, length);
@@ -3046,13 +3046,13 @@ struct CtdlMessage *CtdlMakeMessageLen(
        }
 
        if (preformatted_text != NULL) {
-               CM_SetField(msg, eMesageText, preformatted_text);
+               CM_SetField(msg, eMessageText, preformatted_text);
        }
        else {
                StrBuf *MsgBody;
                MsgBody = CtdlReadMessageBodyBuf(HKEY("000"), CtdlGetConfigLong("c_maxmsglen"), NULL, 0);
                if (MsgBody != NULL) {
-                       CM_SetAsFieldSB(msg, eMesageText, &MsgBody);
+                       CM_SetAsFieldSB(msg, eMessageText, &MsgBody);
                }
        }
 
@@ -3207,11 +3207,7 @@ void PutMetaData(struct MetaData *smibuf) {
 
        // Use the negative of the message number for the metadata db index
        TheIndex = (0L - smibuf->meta_msgnum);
-
-       cdb_store(CDB_MSGMAIN,
-                 &TheIndex, (int)sizeof(long),
-                 smibuf, (int)sizeof(struct MetaData)
-       );
+       cdb_store(CDB_MSGMAIN, &TheIndex, (int)sizeof(long), smibuf, (int)sizeof(struct MetaData));
 }
 
 
@@ -3319,7 +3315,7 @@ long CtdlWriteObject(char *req_room,                      // Room to stuff it in
        CM_SetField(msg, eOriginalRoom, req_room);
        msg->cm_flags = flags;
        
-       CM_SetAsFieldSB(msg, eMesageText, &encoded_message);
+       CM_SetAsFieldSB(msg, eMessageText, &encoded_message);
 
        // Create the requested room if we have to.
        if (CtdlGetRoom(&qrbuf, roomname) != 0) {