X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=citadel%2Fmsgbase.c;h=405790cb43ded6e5b56871264ae5f2931eec99be;hb=d2ad0f3fb9966e14acc36f9e89f48f581fb4add7;hp=825e8970a9ca9f37d4f88b885377c52be2110701;hpb=80ef4405057e7f4bc76607dcbbb520c62ae76f8d;p=citadel.git diff --git a/citadel/msgbase.c b/citadel/msgbase.c index 825e8970a..405790cb4 100644 --- a/citadel/msgbase.c +++ b/citadel/msgbase.c @@ -116,7 +116,54 @@ char *msgkeys[] = { NULL /* Z */ }; -void CtdlMsgSetCM_Fields(struct CtdlMessage *Msg, const char which, const char *buf, long length) +eMsgField FieldOrder[] = { +/* Important fields */ + emessageId , + eMessagePath , + eTimestamp , + eAuthor , + erFc822Addr , + eOriginalRoom, + eNodeName , + eHumanNode , + eRecipient , + eDestination , +/* Semi-important fields */ + eBig_message , + eRemoteRoom , + eExclusiveID , + eWeferences , + eJournal , +/* G is not used yet, may become virus signature*/ + eReplyTo , + eListID , +/* Q is not used yet */ + eSpecialField, + eenVelopeTo , +/* X is not used yet */ +/* Z is not used yet */ + eCarbonCopY , + eMsgSubject , +/* internal only */ + eErrorMsg , + eSuppressIdx , + eExtnotify , +/* Message text (MUST be last) */ + eMesageText +/* Not saved to disk: + eVltMsgNum +*/ +}; + +static const long NDiskFields = sizeof(FieldOrder) / sizeof(eMsgField); + +int CM_IsEmpty(struct CtdlMessage *Msg, eMsgField which) +{ + return !((Msg->cm_fields[which] != NULL) && + (Msg->cm_fields[which][0] != '\0')); +} + +void CM_SetField(struct CtdlMessage *Msg, eMsgField which, const char *buf, long length) { if (Msg->cm_fields[which] != NULL) free (Msg->cm_fields[which]); @@ -125,6 +172,186 @@ void CtdlMsgSetCM_Fields(struct CtdlMessage *Msg, const char which, const char * Msg->cm_fields[which][length] = '\0'; } +void CM_SetFieldLONG(struct CtdlMessage *Msg, eMsgField which, long lvalue) +{ + char buf[128]; + long len; + len = snprintf(buf, sizeof(buf), "%ld", lvalue); + CM_SetField(Msg, which, buf, len); +} +void CM_CutFieldAt(struct CtdlMessage *Msg, eMsgField WhichToCut, long maxlen) +{ + if (Msg->cm_fields[WhichToCut] == NULL) + return; + + if (strlen(Msg->cm_fields[WhichToCut]) > maxlen) + Msg->cm_fields[WhichToCut][maxlen] = '\0'; +} + +void CM_FlushField(struct CtdlMessage *Msg, eMsgField which) +{ + if (Msg->cm_fields[which] != NULL) + free (Msg->cm_fields[which]); + Msg->cm_fields[which] = NULL; +} + +void CM_CopyField(struct CtdlMessage *Msg, eMsgField WhichToPutTo, eMsgField WhichtToCopy) +{ + long len; + if (Msg->cm_fields[WhichToPutTo] != NULL) + free (Msg->cm_fields[WhichToPutTo]); + + if (Msg->cm_fields[WhichtToCopy] != NULL) + { + len = strlen(Msg->cm_fields[WhichtToCopy]); + Msg->cm_fields[WhichToPutTo] = malloc(len + 1); + memcpy(Msg->cm_fields[WhichToPutTo], Msg->cm_fields[WhichToPutTo], len); + Msg->cm_fields[WhichToPutTo][len] = '\0'; + } + else + Msg->cm_fields[WhichToPutTo] = NULL; +} + + +void CM_PrependToField(struct CtdlMessage *Msg, eMsgField which, const char *buf, long length) +{ + if (Msg->cm_fields[which] != NULL) { + long oldmsgsize; + long newmsgsize; + char *new; + + oldmsgsize = strlen(Msg->cm_fields[which]) + 1; + newmsgsize = length + oldmsgsize; + + new = malloc(newmsgsize); + memcpy(new, buf, length); + memcpy(new + length, Msg->cm_fields[which], oldmsgsize); + free(Msg->cm_fields[which]); + Msg->cm_fields[which] = new; + } + else { + Msg->cm_fields[which] = malloc(length + 1); + memcpy(Msg->cm_fields[which], buf, length); + Msg->cm_fields[which][length] = '\0'; + } +} + +void CM_SetAsField(struct CtdlMessage *Msg, eMsgField which, char **buf, long length) +{ + if (Msg->cm_fields[which] != NULL) + free (Msg->cm_fields[which]); + + Msg->cm_fields[which] = *buf; + *buf = NULL; +} + +void CM_SetAsFieldSB(struct CtdlMessage *Msg, eMsgField which, StrBuf **buf) +{ + if (Msg->cm_fields[which] != NULL) + free (Msg->cm_fields[which]); + + Msg->cm_fields[which] = SmashStrBuf(buf); +} + +void CM_GetAsField(struct CtdlMessage *Msg, eMsgField which, char **ret, long *retlen) +{ + if (Msg->cm_fields[which] != NULL) + { + *retlen = strlen(Msg->cm_fields[which]); + *ret = Msg->cm_fields[which]; + Msg->cm_fields[which] = NULL; + } + else + { + *ret = NULL; + *retlen = 0; + } +} + +/* + * Returns 1 if the supplied pointer points to a valid Citadel message. + * If the pointer is NULL or the magic number check fails, returns 0. + */ +int CM_IsValidMsg(struct CtdlMessage *msg) { + if (msg == NULL) + return 0; + if ((msg->cm_magic) != CTDLMESSAGE_MAGIC) { + struct CitContext *CCC = CC; + MSGM_syslog(LOG_WARNING, "CM_IsValidMsg() -- self-check failed\n"); + return 0; + } + return 1; +} + +void CM_FreeContents(struct CtdlMessage *msg) +{ + int i; + + for (i = 0; i < 256; ++i) + if (msg->cm_fields[i] != NULL) { + free(msg->cm_fields[i]); + } + + msg->cm_magic = 0; /* just in case */ +} +/* + * 'Destructor' for struct CtdlMessage + */ +void CM_Free(struct CtdlMessage *msg) +{ + if (CM_IsValidMsg(msg) == 0) + { + if (msg != NULL) free (msg); + return; + } + CM_FreeContents(msg); + free(msg); +} + +int CM_DupField(eMsgField i, struct CtdlMessage *OrgMsg, struct CtdlMessage *NewMsg) +{ + long len; + len = strlen(OrgMsg->cm_fields[i]); + NewMsg->cm_fields[i] = malloc(len + 1); + if (NewMsg->cm_fields[i] == NULL) + return 0; + memcpy(NewMsg->cm_fields[i], OrgMsg->cm_fields[i], len); + NewMsg->cm_fields[i][len] = '\0'; + return 1; +} + +struct CtdlMessage * CM_Duplicate(struct CtdlMessage *OrgMsg) +{ + int i; + struct CtdlMessage *NewMsg; + + if (CM_IsValidMsg(OrgMsg) == 0) + return NULL; + NewMsg = (struct CtdlMessage *)malloc(sizeof(struct CtdlMessage)); + if (NewMsg == NULL) + return NULL; + + memcpy(NewMsg, OrgMsg, sizeof(struct CtdlMessage)); + + memset(&NewMsg->cm_fields, 0, sizeof(char*) * 256); + + for (i = 0; i < 256; ++i) + { + if (OrgMsg->cm_fields[i] != NULL) + { + if (!CM_DupField(i, OrgMsg, NewMsg)) + { + CM_Free(NewMsg); + return NULL; + } + } + } + + return NewMsg; +} + + + /* * This function is self explanatory. * (What can I say, I'm in a weird mood today...) @@ -289,13 +516,13 @@ void headers_listing(long msgnum, void *userdata) cprintf("%ld|%s|%s|%s|%s|%s|\n", msgnum, - (msg->cm_fields['T'] ? msg->cm_fields['T'] : "0"), - (msg->cm_fields['A'] ? msg->cm_fields['A'] : ""), - (msg->cm_fields['N'] ? msg->cm_fields['N'] : ""), - (msg->cm_fields['F'] ? msg->cm_fields['F'] : ""), - (msg->cm_fields['U'] ? msg->cm_fields['U'] : "") + (!CM_IsEmpty(msg, eTimestamp) ? msg->cm_fields[eTimestamp] : "0"), + (!CM_IsEmpty(msg, eAuthor) ? msg->cm_fields[eAuthor] : ""), + (!CM_IsEmpty(msg, eNodeName) ? msg->cm_fields[eNodeName] : ""), + (!CM_IsEmpty(msg, erFc822Addr) ? msg->cm_fields[erFc822Addr] : ""), + (!CM_IsEmpty(msg, eMsgSubject) ? msg->cm_fields[eMsgSubject] : "") ); - CtdlFreeMessage(msg); + CM_Free(msg); } /* @@ -313,9 +540,9 @@ void headers_euid(long msgnum, void *userdata) cprintf("%ld|%s|%s\n", msgnum, - (msg->cm_fields['E'] ? msg->cm_fields['E'] : ""), - (msg->cm_fields['T'] ? msg->cm_fields['T'] : "0")); - CtdlFreeMessage(msg); + (!CM_IsEmpty(msg, eExclusiveID) ? msg->cm_fields[eExclusiveID] : ""), + (!CM_IsEmpty(msg, eTimestamp) ? msg->cm_fields[eTimestamp] : "0")); + CM_Free(msg); } @@ -715,7 +942,7 @@ int CtdlForEachMessage(int mode, long ref, char *search_string, if (CtdlMsgCmp(msg, compare)) { msglist[a] = 0L; } - CtdlFreeMessage(msg); + CM_Free(msg); } } } @@ -903,12 +1130,12 @@ void cmd_msgs(char *cmdbuf) template->cm_anon_type = MES_NORMAL; while(client_getln(buf, sizeof buf) >= 0 && strcmp(buf,"000")) { + long tValueLen; extract_token(tfield, buf, 0, '|', sizeof tfield); - extract_token(tvalue, buf, 1, '|', sizeof tvalue); + tValueLen = extract_token(tvalue, buf, 1, '|', sizeof tvalue); for (i='A'; i<='Z'; ++i) if (msgkeys[i]!=NULL) { if (!strcasecmp(tfield, msgkeys[i])) { - template->cm_fields[i] = - strdup(tvalue); + CM_SetField(template, i, tvalue, tValueLen); } } } @@ -925,48 +1152,11 @@ void cmd_msgs(char *cmdbuf) template, CallBack, NULL); - if (template != NULL) CtdlFreeMessage(template); + if (template != NULL) CM_Free(template); cprintf("000\n"); } - - -/* - * help_subst() - support routine for help file viewer - */ -void help_subst(char *strbuf, char *source, char *dest) -{ - char workbuf[SIZ]; - int p; - - while (p = pattern2(strbuf, source), (p >= 0)) { - strcpy(workbuf, &strbuf[p + strlen(source)]); - strcpy(&strbuf[p], dest); - strcat(strbuf, workbuf); - } -} - - -void do_help_subst(char *buffer) -{ - char buf2[16]; - - help_subst(buffer, "^nodename", config.c_nodename); - help_subst(buffer, "^humannode", config.c_humannode); - help_subst(buffer, "^fqdn", config.c_fqdn); - help_subst(buffer, "^username", CC->user.fullname); - snprintf(buf2, sizeof buf2, "%ld", CC->user.usernum); - help_subst(buffer, "^usernum", buf2); - help_subst(buffer, "^sysadm", config.c_sysadm); - help_subst(buffer, "^variantname", CITADEL); - snprintf(buf2, sizeof buf2, "%d", config.c_maxsessions); - help_subst(buffer, "^maxsessions", buf2); - help_subst(buffer, "^bbsdir", ctdl_message_dir); -} - - - /* * memfmout() - Citadel text formatter and paginator. * Although the original purpose of this routine was to format @@ -1243,13 +1433,15 @@ struct CtdlMessage *CtdlFetchMessage(long msgnum, int with_body) * have just processed the 'M' (message text) field. */ do { + long len; if (mptr >= upper_bound) { break; } field_header = *mptr++; - ret->cm_fields[field_header] = strdup(mptr); + len = strlen(mptr); + CM_SetField(ret, field_header, mptr, len); - while (*mptr++ != 0); /* advance to next field */ + mptr += len + 1; /* advance to next field */ } while ((mptr < upper_bound) && (field_header != 'M')); @@ -1260,21 +1452,20 @@ 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 ( (ret->cm_fields['M'] == NULL) && (with_body) ) { + if ( (CM_IsEmpty(ret, eMesageText)) && (with_body) ) { dmsgtext = cdb_fetch(CDB_BIGMSGS, &msgnum, sizeof(long)); if (dmsgtext != NULL) { - ret->cm_fields['M'] = dmsgtext->ptr; - dmsgtext->ptr = NULL; + CM_SetAsField(ret, eMesageText, &dmsgtext->ptr, dmsgtext->len); cdb_free(dmsgtext); } } - if (ret->cm_fields['M'] == NULL) { - ret->cm_fields['M'] = strdup("\r\n\r\n (no text)\r\n"); + if (CM_IsEmpty(ret, eMesageText)) { + CM_SetField(ret, eMesageText, HKEY("\r\n\r\n (no text)\r\n")); } /* Perform "before read" hooks (aborting if any return nonzero) */ if (PerformMessageHooks(ret, EVT_BEFOREREAD) > 0) { - CtdlFreeMessage(ret); + CM_Free(ret); return NULL; } @@ -1282,89 +1473,6 @@ struct CtdlMessage *CtdlFetchMessage(long msgnum, int with_body) } -/* - * Returns 1 if the supplied pointer points to a valid Citadel message. - * If the pointer is NULL or the magic number check fails, returns 0. - */ -int is_valid_message(struct CtdlMessage *msg) { - if (msg == NULL) - return 0; - if ((msg->cm_magic) != CTDLMESSAGE_MAGIC) { - struct CitContext *CCC = CC; - MSGM_syslog(LOG_WARNING, "is_valid_message() -- self-check failed\n"); - return 0; - } - return 1; -} - -void CtdlFreeMessageContents(struct CtdlMessage *msg) -{ - int i; - - for (i = 0; i < 256; ++i) - if (msg->cm_fields[i] != NULL) { - free(msg->cm_fields[i]); - } - - msg->cm_magic = 0; /* just in case */ -} -/* - * 'Destructor' for struct CtdlMessage - */ -void CtdlFreeMessage(struct CtdlMessage *msg) -{ - if (is_valid_message(msg) == 0) - { - if (msg != NULL) free (msg); - return; - } - CtdlFreeMessageContents(msg); - free(msg); -} - -int DupCMField(int i, struct CtdlMessage *OrgMsg, struct CtdlMessage *NewMsg) -{ - long len; - len = strlen(OrgMsg->cm_fields[i]); - NewMsg->cm_fields[i] = malloc(len + 1); - if (NewMsg->cm_fields[i] == NULL) - return 0; - memcpy(NewMsg->cm_fields[i], OrgMsg->cm_fields[i], len); - NewMsg->cm_fields[i][len] = '\0'; - return 1; -} - -struct CtdlMessage * CtdlDuplicateMessage(struct CtdlMessage *OrgMsg) -{ - int i; - struct CtdlMessage *NewMsg; - - if (is_valid_message(OrgMsg) == 0) - return NULL; - NewMsg = (struct CtdlMessage *)malloc(sizeof(struct CtdlMessage)); - if (NewMsg == NULL) - return NULL; - - memcpy(NewMsg, OrgMsg, sizeof(struct CtdlMessage)); - - memset(&NewMsg->cm_fields, 0, sizeof(char*) * 256); - - for (i = 0; i < 256; ++i) - { - if (OrgMsg->cm_fields[i] != NULL) - { - if (!DupCMField(i, OrgMsg, NewMsg)) - { - CtdlFreeMessage(NewMsg); - return NULL; - } - } - } - - return NewMsg; -} - - /* * Pre callback function for multipart/alternative @@ -1787,7 +1895,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(TheMessage->cm_fields['M'], + mime_parser(TheMessage->cm_fields[eMesageText], NULL, *extract_encapsulated_message, NULL, NULL, (void *)&encap, 0 @@ -1795,15 +1903,15 @@ int CtdlOutputMsg(long msg_num, /* message number (local) to fetch */ if ((Author != NULL) && (*Author == NULL)) { - *Author = TheMessage->cm_fields['A']; - TheMessage->cm_fields['A'] = NULL; + *Author = TheMessage->cm_fields[eAuthor]; + TheMessage->cm_fields[eAuthor] = NULL; } if ((Address != NULL) && (*Address == NULL)) { - *Address = TheMessage->cm_fields['F']; - TheMessage->cm_fields['F'] = NULL; + *Address = TheMessage->cm_fields[erFc822Addr]; + TheMessage->cm_fields[erFc822Addr] = NULL; } - CtdlFreeMessage(TheMessage); + CM_Free(TheMessage); TheMessage = NULL; if (encap.msg) { @@ -1816,7 +1924,6 @@ int CtdlOutputMsg(long msg_num, /* message number (local) to fetch */ * encapsulated message instead of the top-level * message. Isn't that neat? */ - } else { if (do_proto) { @@ -1835,16 +1942,16 @@ int CtdlOutputMsg(long msg_num, /* message number (local) to fetch */ retcode = CtdlOutputPreLoadedMsg(TheMessage, mode, headers_only, do_proto, crlf, flags); if ((Author != NULL) && (*Author == NULL)) { - *Author = TheMessage->cm_fields['A']; - TheMessage->cm_fields['A'] = NULL; + *Author = TheMessage->cm_fields[eAuthor]; + TheMessage->cm_fields[eAuthor] = NULL; } if ((Address != NULL) && (*Address == NULL)) { - *Address = TheMessage->cm_fields['F']; - TheMessage->cm_fields['F'] = NULL; + *Address = TheMessage->cm_fields[erFc822Addr]; + TheMessage->cm_fields[erFc822Addr] = NULL; } - CtdlFreeMessage(TheMessage); + CM_Free(TheMessage); return(retcode); } @@ -2005,16 +2112,15 @@ void OutputCtdlMsgHeaders( struct CtdlMessage *TheMessage, int do_proto) /* do Citadel protocol responses? */ { - char allkeys[30]; - int i, k, n; + int i; int suppress_f = 0; char buf[SIZ]; char display_name[256]; /* begin header processing loop for Citadel message format */ safestrncpy(display_name, "", sizeof display_name); - if (TheMessage->cm_fields['A']) { - strcpy(buf, TheMessage->cm_fields['A']); + if (!CM_IsEmpty(TheMessage, eAuthor)) { + strcpy(buf, TheMessage->cm_fields[eAuthor]); if (TheMessage->cm_anon_type == MES_ANONONLY) { safestrncpy(display_name, "****", sizeof display_name); } @@ -2038,35 +2144,37 @@ void OutputCtdlMsgHeaders( * local Citadel network. */ suppress_f = 0; - if (TheMessage->cm_fields['N'] != NULL) - if (!IsEmptyStr(TheMessage->cm_fields['N'])) - if (haschar(TheMessage->cm_fields['N'], '.') == 0) { - suppress_f = 1; - } + if (!CM_IsEmpty(TheMessage, eNodeName) && + (haschar(TheMessage->cm_fields[eNodeName], '.') == 0)) + { + suppress_f = 1; + } /* Now spew the header fields in the order we like them. */ - n = safestrncpy(allkeys, FORDER, sizeof allkeys); - for (i=0; icm_fields[k] != NULL) - && (msgkeys[k] != NULL) ) { - if ((k == 'V') || (k == 'R') || (k == 'Y')) { - sanitize_truncated_recipient(TheMessage->cm_fields[k]); + for (i=0; i< NDiskFields; ++i) { + eMsgField Field; + Field = FieldOrder[i]; + if (Field != eMesageText) { + if ( (!CM_IsEmpty(TheMessage, Field)) + && (msgkeys[Field] != NULL) ) { + if ((Field == eenVelopeTo) || + (Field == eRecipient) || + (Field == eCarbonCopY)) { + sanitize_truncated_recipient(TheMessage->cm_fields[Field]); } - if (k == 'A') { + if (Field == eAuthor) { if (do_proto) cprintf("%s=%s\n", - msgkeys[k], + msgkeys[Field], display_name); } - else if ((k == 'F') && (suppress_f)) { + else if ((Field == erFc822Addr) && (suppress_f)) { /* do nothing */ } /* Masquerade display name if needed */ else { if (do_proto) cprintf("%s=%s\n", - msgkeys[k], - TheMessage->cm_fields[k] + msgkeys[Field], + TheMessage->cm_fields[Field] ); } } @@ -2097,7 +2205,7 @@ void OutputRFC822MsgHeaders( if (TheMessage->cm_fields[i]) { mptr = mpptr = TheMessage->cm_fields[i]; - if (i == 'A') { + if (i == eAuthor) { safestrncpy(luser, mptr, sizeof_luser); safestrncpy(suser, mptr, sizeof_suser); } @@ -2111,7 +2219,7 @@ void OutputRFC822MsgHeaders( else if (i == 'P') { cprintf("Return-Path: %s%s", mptr, nl); } - else if (i == 'L') { + else if (i == eListID) { cprintf("List-ID: %s%s", mptr, nl); } else if (i == 'V') { @@ -2129,7 +2237,7 @@ void OutputRFC822MsgHeaders( } else if (i == 'I') safestrncpy(mid, mptr, sizeof_mid); /// TODO: detect @ here and copy @nodename in if not found. - else if (i == 'F') + else if (i == erFc822Addr) safestrncpy(fuser, mptr, sizeof_fuser); /* else if (i == 'O') cprintf("X-Citadel-Room: %s%s", @@ -2173,7 +2281,7 @@ void OutputRFC822MsgHeaders( } } } - else if (i == 'K') { + else if (i == eReplyTo) { hptr = mptr; while ((*hptr != '\0') && isspace(*hptr)) hptr ++; @@ -2205,7 +2313,7 @@ void Dump_RFC822HeadersBody( int nllen = strlen(nl); char *mptr; - mptr = TheMessage->cm_fields['M']; + mptr = TheMessage->cm_fields[eMesageText]; prev_ch = '\0'; @@ -2286,7 +2394,7 @@ void DumpFormatFixed( int nllen = strlen (nl); char *mptr; - mptr = TheMessage->cm_fields['M']; + mptr = TheMessage->cm_fields[eMesageText]; if (mode == MT_MIME) { cprintf("Content-type: text/plain\n\n"); @@ -2378,7 +2486,7 @@ int CtdlOutputPreLoadedMsg( strcpy(mid, "unknown"); nl = (crlf ? "\r\n" : "\n"); - if (!is_valid_message(TheMessage)) { + if (!CM_IsValidMsg(TheMessage)) { MSGM_syslog(LOG_ERR, "ERROR: invalid preloaded message for output\n"); cit_backtrace (); @@ -2388,8 +2496,8 @@ int CtdlOutputPreLoadedMsg( /* Suppress envelope recipients if required to avoid disclosing BCC addresses. * Pad it with spaces in order to avoid changing the RFC822 length of the message. */ - if ( (flags & SUPPRESS_ENV_TO) && (TheMessage->cm_fields['V'] != NULL) ) { - memset(TheMessage->cm_fields['V'], ' ', strlen(TheMessage->cm_fields['V'])); + if ( (flags & SUPPRESS_ENV_TO) && (!CM_IsEmpty(TheMessage, eenVelopeTo)) ) { + memset(TheMessage->cm_fields[eenVelopeTo], ' ', strlen(TheMessage->cm_fields[eenVelopeTo])); } /* Are we downloading a MIME component? */ @@ -2404,7 +2512,7 @@ int CtdlOutputPreLoadedMsg( ERROR + RESOURCE_BUSY); } else { /* Parse the message text component */ - mptr = TheMessage->cm_fields['M']; + mptr = TheMessage->cm_fields[eMesageText]; mime_parser(mptr, NULL, *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 @@ -2431,7 +2539,7 @@ int CtdlOutputPreLoadedMsg( /* Parse the message text component */ int found_it = 0; - mptr = TheMessage->cm_fields['M']; + mptr = TheMessage->cm_fields[eMesageText]; mime_parser(mptr, NULL, *mime_spew_section, NULL, NULL, (void *)&found_it, 0); /* If section wasn't found, print an error */ @@ -2529,7 +2637,7 @@ START_TEXT: /* Tell the client about the MIME parts in this message */ if (TheMessage->cm_format_type == FMT_RFC822) { if ( (mode == MT_CITADEL) || (mode == MT_MIME) ) { - mptr = TheMessage->cm_fields['M']; + mptr = TheMessage->cm_fields[eMesageText]; memset(&ma, 0, sizeof(struct ma_info)); mime_parser(mptr, NULL, (do_proto ? *list_this_part : NULL), @@ -2570,7 +2678,7 @@ START_TEXT: * message to the reader's screen width. */ if (TheMessage->cm_format_type == FMT_CITADEL) { - mptr = TheMessage->cm_fields['M']; + mptr = TheMessage->cm_fields[eMesageText]; if (mode == MT_MIME) { cprintf("Content-type: text/x-citadel-variformat\n\n"); @@ -2668,7 +2776,7 @@ void cmd_msg3(char *cmdbuf) } serialize_message(&smr, msg); - CtdlFreeMessage(msg); + CM_Free(msg); if (smr.len == 0) { cprintf("%d Unable to serialize message\n", @@ -2876,13 +2984,13 @@ int CtdlSaveMsgPointersInRoom(char *roomname, long newmsgidlist[], int num_newms ReplicationChecks(msg); /* If the message has an Exclusive ID, index that... */ - if (msg->cm_fields['E'] != NULL) { - index_message_by_euid(msg->cm_fields['E'], &CCC->room, msgid); + if (!CM_IsEmpty(msg, eExclusiveID)) { + index_message_by_euid(msg->cm_fields[eExclusiveID], &CCC->room, msgid); } /* Free up the memory we may have allocated */ if (msg != supplied_msg) { - CtdlFreeMessage(msg); + CM_Free(msg); } } @@ -2940,29 +3048,30 @@ long send_message(struct CtdlMessage *msg) { long newmsgid; long retval; char msgidbuf[256]; + long msgidbuflen; struct ser_ret smr; int is_bigmsg = 0; char *holdM = NULL; /* Get a new message number */ newmsgid = get_new_message_number(); - snprintf(msgidbuf, sizeof msgidbuf, "%08lX-%08lX@%s", - (long unsigned int) time(NULL), - (long unsigned int) newmsgid, - config.c_fqdn + msgidbuflen = snprintf(msgidbuf, sizeof msgidbuf, "%08lX-%08lX@%s", + (long unsigned int) time(NULL), + (long unsigned int) newmsgid, + config.c_fqdn ); /* Generate an ID if we don't have one already */ - if (msg->cm_fields['I']==NULL) { - msg->cm_fields['I'] = strdup(msgidbuf); + if (CM_IsEmpty(msg, emessageId)) { + CM_SetField(msg, emessageId, msgidbuf, msgidbuflen); } /* If the message is big, set its body aside for storage elsewhere */ - if (msg->cm_fields['M'] != NULL) { - if (strlen(msg->cm_fields['M']) > BIGMSG) { + if (!CM_IsEmpty(msg, eMesageText)) { + if (strlen(msg->cm_fields[eMesageText]) > BIGMSG) { is_bigmsg = 1; - holdM = msg->cm_fields['M']; - msg->cm_fields['M'] = NULL; + holdM = msg->cm_fields[eMesageText]; + msg->cm_fields[eMesageText] = NULL; } } @@ -2970,7 +3079,7 @@ long send_message(struct CtdlMessage *msg) { serialize_message(&smr, msg); if (is_bigmsg) { - msg->cm_fields['M'] = holdM; + msg->cm_fields[eMesageText] = holdM; } if (smr.len == 0) { @@ -3020,12 +3129,14 @@ void serialize_message(struct ser_ret *ret, /* return values */ struct CitContext *CCC = CC; size_t wlen, fieldlen; int i; - static char *forder = FORDER; + long lengths[NDiskFields]; + + memset(lengths, 0, sizeof(lengths)); /* * Check for valid message format */ - if (is_valid_message(msg) == 0) { + if (CM_IsValidMsg(msg) == 0) { MSGM_syslog(LOG_ERR, "serialize_message() aborting due to invalid message\n"); ret->len = 0; ret->ser = NULL; @@ -3033,9 +3144,12 @@ void serialize_message(struct ser_ret *ret, /* return values */ } ret->len = 3; - for (i=0; i<26; ++i) if (msg->cm_fields[(int)forder[i]] != NULL) - ret->len = ret->len + - strlen(msg->cm_fields[(int)forder[i]]) + 2; + for (i=0; i < NDiskFields; ++i) + if (msg->cm_fields[FieldOrder[i]] != NULL) + { + lengths[i] = strlen(msg->cm_fields[FieldOrder[i]]); + ret->len += lengths[i] + 2; + } ret->ser = malloc(ret->len); if (ret->ser == NULL) { @@ -3051,12 +3165,19 @@ void serialize_message(struct ser_ret *ret, /* return values */ ret->ser[2] = msg->cm_format_type; wlen = 3; - for (i=0; i<26; ++i) if (msg->cm_fields[(int)forder[i]] != NULL) { - fieldlen = strlen(msg->cm_fields[(int)forder[i]]); - ret->ser[wlen++] = (char)forder[i]; - safestrncpy((char *)&ret->ser[wlen], msg->cm_fields[(int)forder[i]], fieldlen+1); + for (i=0; i < NDiskFields; ++i) + if (msg->cm_fields[FieldOrder[i]] != NULL) + { + fieldlen = lengths[i]; + ret->ser[wlen++] = (char)FieldOrder[i]; + + memcpy(&ret->ser[wlen], + msg->cm_fields[FieldOrder[i]], + fieldlen+1); + wlen = wlen + fieldlen + 1; } + if (ret->len != wlen) { MSG_syslog(LOG_ERR, "ERROR: len=%ld wlen=%ld\n", (long)ret->len, (long)wlen); @@ -3081,12 +3202,12 @@ void ReplicationChecks(struct CtdlMessage *msg) { /* No exclusive id? Don't do anything. */ if (msg == NULL) return; - if (msg->cm_fields['E'] == NULL) return; - if (IsEmptyStr(msg->cm_fields['E'])) return; + if (CM_IsEmpty(msg, eExclusiveID)) return; + /*MSG_syslog(LOG_DEBUG, "Exclusive ID: <%s> for room <%s>\n", - msg->cm_fields['E'], CCC->room.QRname);*/ + msg->cm_fields[eExclusiveID], CCC->room.QRname);*/ - old_msgnum = CtdlLocateMessageByEuid(msg->cm_fields['E'], &CCC->room); + old_msgnum = CtdlLocateMessageByEuid(msg->cm_fields[eExclusiveID], &CCC->room); if (old_msgnum > 0L) { MSG_syslog(LOG_DEBUG, "ReplicationChecks() replacing message %ld\n", old_msgnum); CtdlDeleteMessages(CCC->room.QRname, &old_msgnum, 1, ""); @@ -3105,7 +3226,6 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ ) { char submit_filename[128]; - char generated_timestamp[32]; char hold_rm[ROOMNAMELEN]; char actual_rm[ROOMNAMELEN]; char force_room[ROOMNAMELEN]; @@ -3133,41 +3253,40 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ int rv = 0; MSGM_syslog(LOG_DEBUG, "CtdlSubmitMsg() called\n"); - if (is_valid_message(msg) == 0) return(-1); /* self check */ + if (CM_IsValidMsg(msg) == 0) return(-1); /* self check */ /* If this message has no timestamp, we take the liberty of * giving it one, right now. */ - if (msg->cm_fields['T'] == NULL) { - snprintf(generated_timestamp, sizeof generated_timestamp, "%ld", (long)time(NULL)); - msg->cm_fields['T'] = strdup(generated_timestamp); + if (CM_IsEmpty(msg, eTimestamp)) { + CM_SetFieldLONG(msg, eTimestamp, time(NULL)); } /* If this message has no path, we generate one. */ - if (msg->cm_fields['P'] == NULL) { - if (msg->cm_fields['A'] != NULL) { - msg->cm_fields['P'] = strdup(msg->cm_fields['A']); - for (a=0; !IsEmptyStr(&msg->cm_fields['P'][a]); ++a) { - if (isspace(msg->cm_fields['P'][a])) { - msg->cm_fields['P'][a] = ' '; + if (CM_IsEmpty(msg, eMessagePath)) { + if (!CM_IsEmpty(msg, eAuthor)) { + CM_CopyField(msg, eMessagePath, eAuthor); + for (a=0; !IsEmptyStr(&msg->cm_fields[eMessagePath][a]); ++a) { + if (isspace(msg->cm_fields[eMessagePath][a])) { + msg->cm_fields[eMessagePath][a] = ' '; } } } else { - msg->cm_fields['P'] = strdup("unknown"); + CM_SetField(msg, eMessagePath, HKEY("unknown")); } } if (force == NULL) { - strcpy(force_room, ""); + force_room[0] = '\0'; } else { strcpy(force_room, force); } /* Learn about what's inside, because it's what's inside that counts */ - if (msg->cm_fields['M'] == NULL) { + if (CM_IsEmpty(msg, eMesageText)) { MSGM_syslog(LOG_ERR, "ERROR: attempt to save message with NULL body\n"); return(-2); } @@ -3181,7 +3300,7 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ break; case 4: strcpy(content_type, "text/plain"); - mptr = bmstrcasestr(msg->cm_fields['M'], "Content-type:"); + mptr = bmstrcasestr(msg->cm_fields[eMesageText], "Content-type:"); if (mptr != NULL) { char *aptr; safestrncpy(content_type, &mptr[13], sizeof content_type); @@ -3231,8 +3350,8 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ /* * If this message has no O (room) field, generate one. */ - if (msg->cm_fields['O'] == NULL) { - msg->cm_fields['O'] = strdup(CCC->room.QRname); + if (CM_IsEmpty(msg, eOriginalRoom)) { + CM_SetField(msg, eOriginalRoom, CCC->room.QRname, strlen(CCC->room.QRname)); } /* Perform "before save" hooks (aborting if any return nonzero) */ @@ -3327,7 +3446,7 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ snprintf(bounce_to, sizeof bounce_to, "%s@%s", CCC->user.fullname, config.c_nodename); } else { - snprintf(bounce_to, sizeof bounce_to, "%s@%s", msg->cm_fields['A'], msg->cm_fields['N']); + snprintf(bounce_to, sizeof bounce_to, "%s@%s", msg->cm_fields[eAuthor], msg->cm_fields[eNodeName]); } /* If this is private, local mail, make a copy in the @@ -3335,8 +3454,10 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ */ if ((recps != NULL) && (recps->num_local > 0)) for (i=0; irecp_local, '|'); ++i) { - extract_token(recipient, recps->recp_local, i, - '|', sizeof recipient); + long recipientlen; + recipientlen = extract_token(recipient, + recps->recp_local, i, + '|', sizeof recipient); MSG_syslog(LOG_DEBUG, "Delivering private local mail to <%s>\n", recipient); if (CtdlGetUser(&userbuf, recipient) == 0) { @@ -3347,13 +3468,17 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ /* Generate a instruction message for the Funambol notification * server, in the same style as the SMTP queue */ + long instrlen; instr_alloc = 1024; instr = malloc(instr_alloc); - snprintf(instr, instr_alloc, - "Content-type: %s\n\nmsgid|%ld\nsubmitted|%ld\n" - "bounceto|%s\n", - SPOOLMIME, newmsgid, (long)time(NULL), - bounce_to + instrlen = snprintf( + instr, instr_alloc, + "Content-type: %s\n\nmsgid|%ld\nsubmitted|%ld\n" + "bounceto|%s\n", + SPOOLMIME, + newmsgid, + (long)time(NULL), //todo: time() is expensive! + bounce_to ); imsg = malloc(sizeof(struct CtdlMessage)); @@ -3361,13 +3486,13 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ imsg->cm_magic = CTDLMESSAGE_MAGIC; imsg->cm_anon_type = MES_NORMAL; imsg->cm_format_type = FMT_RFC822; - imsg->cm_fields['U'] = strdup("QMSG"); - imsg->cm_fields['A'] = strdup("Citadel"); - imsg->cm_fields['J'] = strdup("do not journal"); - imsg->cm_fields['M'] = instr; /* imsg owns this memory now */ - imsg->cm_fields['2'] = strdup(recipient); + CM_SetField(imsg, eMsgSubject, HKEY("QMSG")); + CM_SetField(imsg, eAuthor, HKEY("Citadel")); + CM_SetField(imsg, eJournal, HKEY("do not journal")); + CM_SetAsField(imsg, eMesageText, &instr, instrlen); + CM_SetField(imsg, eExtnotify, recipient, recipientlen); CtdlSubmitMsg(imsg, NULL, FNBL_QUEUE_ROOM, 0); - CtdlFreeMessage(imsg); + CM_Free(imsg); } } else { @@ -3378,12 +3503,10 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ /* Perform "after save" hooks */ MSGM_syslog(LOG_DEBUG, "Performing after-save hooks\n"); - if (msg->cm_fields['3'] != NULL) free(msg->cm_fields['3']); - msg->cm_fields['3'] = malloc(20); - snprintf(msg->cm_fields['3'], 20, "%ld", newmsgid); + + CM_SetFieldLONG(msg, eVltMsgNum, newmsgid); PerformMessageHooks(msg, EVT_AFTERSAVE); - free(msg->cm_fields['3']); - msg->cm_fields['3'] = NULL; + CM_FlushField(msg, eVltMsgNum); /* For IGnet mail, we have to save a new copy into the spooler for * each recipient, with the R and D fields set to the recipient and @@ -3398,12 +3521,12 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ extract_token(recipient, recps->recp_ignet, i, '|', sizeof recipient); - hold_R = msg->cm_fields['R']; - hold_D = msg->cm_fields['D']; - msg->cm_fields['R'] = malloc(SIZ); - msg->cm_fields['D'] = malloc(128); - extract_token(msg->cm_fields['R'], recipient, 0, '@', SIZ); - extract_token(msg->cm_fields['D'], recipient, 1, '@', 128); + hold_R = msg->cm_fields[eRecipient]; + hold_D = msg->cm_fields[eDestination]; + msg->cm_fields[eRecipient] = malloc(SIZ); + msg->cm_fields[eDestination] = malloc(128); + extract_token(msg->cm_fields[eRecipient], recipient, 0, '@', SIZ); + extract_token(msg->cm_fields[eDestination], recipient, 1, '@', 128); serialize_message(&smr, msg); if (smr.len > 0) { @@ -3423,10 +3546,10 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ free(smr.ser); } - free(msg->cm_fields['R']); - free(msg->cm_fields['D']); - msg->cm_fields['R'] = hold_R; - msg->cm_fields['D'] = hold_D; + free(msg->cm_fields[eRecipient]); + free(msg->cm_fields[eDestination]); + msg->cm_fields[eRecipient] = hold_R; + msg->cm_fields[eDestination] = hold_D; } /* Go back to the room we started from */ @@ -3482,12 +3605,12 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ imsg->cm_magic = CTDLMESSAGE_MAGIC; imsg->cm_anon_type = MES_NORMAL; imsg->cm_format_type = FMT_RFC822; - imsg->cm_fields['U'] = strdup("QMSG"); - imsg->cm_fields['A'] = strdup("Citadel"); - imsg->cm_fields['J'] = strdup("do not journal"); - imsg->cm_fields['M'] = SmashStrBuf(&SpoolMsg); /* imsg owns this memory now */ + imsg->cm_fields[eMsgSubject] = strdup("QMSG"); + imsg->cm_fields[eAuthor] = strdup("Citadel"); + imsg->cm_fields[eJournal] = strdup("do not journal"); + imsg->cm_fields[eMesageText] = SmashStrBuf(&SpoolMsg); /* imsg owns this memory now */ CtdlSubmitMsg(imsg, NULL, SMTP_SPOOLOUT_ROOM, QP_EADDR); - CtdlFreeMessage(imsg); + CM_Free(imsg); } /* @@ -3513,7 +3636,7 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ /* * Determine whether this message qualifies for journaling. */ - if (msg->cm_fields['J'] != NULL) { + if (!CM_IsEmpty(msg, eJournal)) { qualified_for_journaling = 0; } else { @@ -3568,32 +3691,32 @@ void quickie_message(const char *from, msg->cm_format_type = format_type; if (from != NULL) { - msg->cm_fields['A'] = strdup(from); + msg->cm_fields[eAuthor] = strdup(from); } else if (fromaddr != NULL) { - msg->cm_fields['A'] = strdup(fromaddr); - if (strchr(msg->cm_fields['A'], '@')) { - *strchr(msg->cm_fields['A'], '@') = 0; + msg->cm_fields[eAuthor] = strdup(fromaddr); + if (strchr(msg->cm_fields[eAuthor], '@')) { + *strchr(msg->cm_fields[eAuthor], '@') = 0; } } else { - msg->cm_fields['A'] = strdup("Citadel"); + msg->cm_fields[eAuthor] = strdup("Citadel"); } - if (fromaddr != NULL) msg->cm_fields['F'] = strdup(fromaddr); - if (room != NULL) msg->cm_fields['O'] = strdup(room); - msg->cm_fields['N'] = strdup(NODENAME); + if (fromaddr != NULL) msg->cm_fields[erFc822Addr] = strdup(fromaddr); + if (room != NULL) msg->cm_fields[eOriginalRoom] = strdup(room); + msg->cm_fields[eNodeName] = strdup(NODENAME); if (to != NULL) { - msg->cm_fields['R'] = strdup(to); + msg->cm_fields[eRecipient] = strdup(to); recp = validate_recipients(to, NULL, 0); } if (subject != NULL) { - msg->cm_fields['U'] = strdup(subject); + msg->cm_fields[eMsgSubject] = strdup(subject); } - msg->cm_fields['M'] = strdup(text); + msg->cm_fields[eMesageText] = strdup(text); CtdlSubmitMsg(msg, recp, room, 0); - CtdlFreeMessage(msg); + CM_Free(msg); if (recp != NULL) free_recipients(recp); } @@ -3606,18 +3729,18 @@ void flood_protect_quickie_message(const char *from, const char *subject, int nCriterions, const char **CritStr, - long *CritStrLen) + long *CritStrLen, + long ccid, + long ioid, + time_t NOW) { int i; - struct UseTable ut; u_char rawdigest[MD5_DIGEST_LEN]; struct MD5Context md5context; StrBuf *guid; - struct cdbdata *cdbut; char timestamp[64]; long tslen; - time_t ts = time(NULL); - time_t tsday = ts / (8*60*60); /* just care for a day... */ + time_t tsday = NOW / (8*60*60); /* just care for a day... */ tslen = snprintf(timestamp, sizeof(timestamp), "%ld", tsday); MD5Init(&md5context); @@ -3635,27 +3758,22 @@ void flood_protect_quickie_message(const char *from, StrBufAppendBufPlain(guid, HKEY("_fldpt"), 0); if (StrLength(guid) > 40) StrBufCutAt(guid, 40, NULL); - /* Find out if we've already sent a similar message */ - memcpy(ut.ut_msgid, SKEY(guid)); - ut.ut_timestamp = ts; - cdbut = cdb_fetch(CDB_USETABLE, SKEY(guid)); - - if (cdbut != NULL) { + if (CheckIfAlreadySeen("FPAideMessage", + guid, + NOW, + tsday, + eUpdate, + ccid, + ioid)!= 0) + { + FreeStrBuf(&guid); /* yes, we did. flood protection kicks in. */ syslog(LOG_DEBUG, "not sending message again\n"); - cdb_free(cdbut); + return; } - - /* rewrite the record anyway, to update the timestamp */ - cdb_store(CDB_USETABLE, - SKEY(guid), - &ut, sizeof(struct UseTable) ); - FreeStrBuf(&guid); - - if (cdbut != NULL) return; /* no, this message isn't sent recently; go ahead. */ quickie_message(from, fromaddr, @@ -3935,7 +4053,7 @@ char *CtdlReadMessageBody(char *terminator, /* token signalling EOT */ * (NOTE: if you supply 'preformatted_text', the buffer you give it * will become part of the message. This means you are no longer * responsible for managing that memory -- it will be freed along with - * the rest of the fields when CtdlFreeMessage() is called.) + * the rest of the fields when CM_Free() is called.) */ struct CtdlMessage *CtdlMakeMessage( @@ -3974,16 +4092,16 @@ struct CtdlMessage *CtdlMakeMessage( if (my_email == NULL) my_email = ""; if (!IsEmptyStr(my_email)) { - msg->cm_fields['P'] = strdup(my_email); + msg->cm_fields[eMessagePath] = strdup(my_email); } else { snprintf(buf, sizeof buf, "%s", author->fullname); - msg->cm_fields['P'] = strdup(buf); + msg->cm_fields[eMessagePath] = strdup(buf); } - convert_spaces_to_underscores(msg->cm_fields['P']); + convert_spaces_to_underscores(msg->cm_fields[eMessagePath]); snprintf(buf, sizeof buf, "%ld", (long)time(NULL)); /* timestamp */ - msg->cm_fields['T'] = strdup(buf); + msg->cm_fields[eTimestamp] = strdup(buf); if ((fake_name != NULL) && (fake_name[0])) { /* author */ FakeAuthor = NewStrBufPlain (fake_name, -1); @@ -3992,34 +4110,34 @@ struct CtdlMessage *CtdlMakeMessage( FakeAuthor = NewStrBufPlain (author->fullname, -1); } StrBufRFC2047encode(&FakeEncAuthor, FakeAuthor); - msg->cm_fields['A'] = SmashStrBuf(&FakeEncAuthor); + msg->cm_fields[eAuthor] = SmashStrBuf(&FakeEncAuthor); FreeStrBuf(&FakeAuthor); if (CC->room.QRflags & QR_MAILBOX) { /* room */ - msg->cm_fields['O'] = strdup(&CC->room.QRname[11]); + msg->cm_fields[eOriginalRoom] = strdup(&CC->room.QRname[11]); } else { - msg->cm_fields['O'] = strdup(CC->room.QRname); + msg->cm_fields[eOriginalRoom] = strdup(CC->room.QRname); } - msg->cm_fields['N'] = strdup(NODENAME); /* nodename */ - msg->cm_fields['H'] = strdup(HUMANNODE); /* hnodename */ + msg->cm_fields[eNodeName] = strdup(NODENAME); /* nodename */ + msg->cm_fields[eHumanNode] = strdup(HUMANNODE); /* hnodename */ if ((recipient != NULL) && (recipient[0] != 0)) { - msg->cm_fields['R'] = strdup(recipient); + msg->cm_fields[eRecipient] = strdup(recipient); } if ((recp_cc != NULL) && (recp_cc[0] != 0)) { - msg->cm_fields['Y'] = strdup(recp_cc); + msg->cm_fields[eCarbonCopY] = strdup(recp_cc); } if (dest_node[0] != 0) { - msg->cm_fields['D'] = strdup(dest_node); + msg->cm_fields[eDestination] = strdup(dest_node); } if (!IsEmptyStr(my_email)) { - msg->cm_fields['F'] = strdup(my_email); + msg->cm_fields[erFc822Addr] = strdup(my_email); } else if ( (author == &CC->user) && (!IsEmptyStr(CC->cs_inet_email)) ) { - msg->cm_fields['F'] = strdup(CC->cs_inet_email); + msg->cm_fields[erFc822Addr] = strdup(CC->cs_inet_email); } if (subject != NULL) { @@ -4035,30 +4153,30 @@ struct CtdlMessage *CtdlMakeMessage( (IsAscii = isascii(subject[i]) != 0 )) i++; if (IsAscii != 0) - msg->cm_fields['U'] = strdup(subject); + msg->cm_fields[eMsgSubject] = strdup(subject); else /* ok, we've got utf8 in the string. */ { - msg->cm_fields['U'] = rfc2047encode(subject, length); + msg->cm_fields[eMsgSubject] = rfc2047encode(subject, length); } } } if (supplied_euid != NULL) { - msg->cm_fields['E'] = strdup(supplied_euid); + msg->cm_fields[eExclusiveID] = strdup(supplied_euid); } if ((references != NULL) && (!IsEmptyStr(references))) { - if (msg->cm_fields['W'] != NULL) - free(msg->cm_fields['W']); - msg->cm_fields['W'] = strdup(references); + if (msg->cm_fields[eWeferences] != NULL) + free(msg->cm_fields[eWeferences]); + msg->cm_fields[eWeferences] = strdup(references); } if (preformatted_text != NULL) { - msg->cm_fields['M'] = preformatted_text; + msg->cm_fields[eMesageText] = preformatted_text; } else { - msg->cm_fields['M'] = CtdlReadMessageBody(HKEY("000"), config.c_maxmsglen, NULL, 0, 0); + msg->cm_fields[eMesageText] = CtdlReadMessageBody(HKEY("000"), config.c_maxmsglen, NULL, 0, 0); } return(msg); @@ -4745,7 +4863,7 @@ void cmd_ent0(char *entargs) * to the actual mail address so others get a valid * reply-to-header. */ - msg->cm_fields['V'] = strdup(valid->recp_orgroom); + msg->cm_fields[eenVelopeTo] = strdup(valid->recp_orgroom); } if (msg != NULL) { @@ -4763,15 +4881,15 @@ void cmd_ent0(char *entargs) client_write(HKEY("Internal error.\n")); } - if (msg->cm_fields['E'] != NULL) { - cprintf("%s\n", msg->cm_fields['E']); + if (!CM_IsEmpty(msg, eExclusiveID)) { + cprintf("%s\n", msg->cm_fields[eExclusiveID]); } else { cprintf("\n"); } cprintf("000\n"); } - CtdlFreeMessage(msg); + CM_Free(msg); } if (valid != NULL) { free_recipients(valid); @@ -4809,12 +4927,12 @@ int CtdlDeleteMessages(char *room_name, /* which room */ regcomp(&re, content_type, 0); need_to_free_re = 1; } - MSG_syslog(LOG_DEBUG, "CtdlDeleteMessages(%s, %d msgs, %s)\n", + MSG_syslog(LOG_DEBUG, " CtdlDeleteMessages(%s, %d msgs, %s)\n", room_name, num_dmsgnums, content_type); /* get room record, obtaining a lock... */ if (CtdlGetRoomLock(&qrbuf, room_name) != 0) { - MSG_syslog(LOG_ERR, "CtdlDeleteMessages(): Room <%s> not found\n", + MSG_syslog(LOG_ERR, " CtdlDeleteMessages(): Room <%s> not found\n", room_name); if (need_to_free_re) regfree(&re); return (0); /* room not found */ @@ -4841,7 +4959,7 @@ int CtdlDeleteMessages(char *room_name, /* which room */ StrBuf *dbg = NewStrBuf(); for (i = 0; i < num_dmsgnums; i++) StrBufAppendPrintf(dbg, ", %ld", dmsgnums[i]); - MSG_syslog(LOG_DEBUG, "Deleting before: %s", ChrPtr(dbg)); + MSG_syslog(LOG_DEBUG, " Deleting before: %s", ChrPtr(dbg)); FreeStrBuf(&dbg); } */ @@ -4849,7 +4967,6 @@ int CtdlDeleteMessages(char *room_name, /* which room */ while ((i < num_msgs) && (have_more_del)) { delete_this = 0x00; - /* Set/clear a bit for each criterion */ /* 0 messages in the list or a null list means that we are @@ -4860,6 +4977,10 @@ int CtdlDeleteMessages(char *room_name, /* which room */ } else { while ((i < num_msgs) && (msglist[i] < dmsgnums[j])) i++; + + if (i >= num_msgs) + continue; + if (msglist[i] == dmsgnums[j]) { delete_this |= 0x01; } @@ -4888,7 +5009,7 @@ int CtdlDeleteMessages(char *room_name, /* which room */ StrBuf *dbg = NewStrBuf(); for (i = 0; i < num_deleted; i++) StrBufAppendPrintf(dbg, ", %ld", dellist[i]); - MSG_syslog(LOG_DEBUG, "Deleting: %s", ChrPtr(dbg)); + MSG_syslog(LOG_DEBUG, " Deleting: %s", ChrPtr(dbg)); FreeStrBuf(&dbg); } */ @@ -4920,7 +5041,7 @@ int CtdlDeleteMessages(char *room_name, /* which room */ /* Now free the memory we used, and go away. */ if (msglist != NULL) free(msglist); if (dellist != NULL) free(dellist); - MSG_syslog(LOG_DEBUG, "%d message(s) deleted.\n", num_deleted); + MSG_syslog(LOG_DEBUG, " %d message(s) deleted.\n", num_deleted); if (need_to_free_re) regfree(&re); return (num_deleted); } @@ -5429,13 +5550,13 @@ void CtdlWriteObject(char *req_room, /* Room to stuff it in */ msg->cm_magic = CTDLMESSAGE_MAGIC; msg->cm_anon_type = MES_NORMAL; msg->cm_format_type = 4; - msg->cm_fields['A'] = strdup(CCC->user.fullname); - msg->cm_fields['O'] = strdup(req_room); - msg->cm_fields['N'] = strdup(config.c_nodename); - msg->cm_fields['H'] = strdup(config.c_humannode); + msg->cm_fields[eAuthor] = strdup(CCC->user.fullname); + msg->cm_fields[eOriginalRoom] = strdup(req_room); + msg->cm_fields[eNodeName] = strdup(config.c_nodename); + msg->cm_fields[eHumanNode] = strdup(config.c_humannode); msg->cm_flags = flags; - msg->cm_fields['M'] = encoded_message; + msg->cm_fields[eMesageText] = encoded_message; /* Create the requested room if we have to. */ if (CtdlGetRoom(&qrbuf, roomname) != 0) { @@ -5453,7 +5574,7 @@ void CtdlWriteObject(char *req_room, /* Room to stuff it in */ } /* Now write the data */ CtdlSubmitMsg(msg, NULL, roomname, 0); - CtdlFreeMessage(msg); + CM_Free(msg); } @@ -5494,8 +5615,8 @@ char *CtdlGetSysConfig(char *sysconfname) { else { msg = CtdlFetchMessage(msgnum, 1); if (msg != NULL) { - conf = strdup(msg->cm_fields['M']); - CtdlFreeMessage(msg); + conf = strdup(msg->cm_fields[eMesageText]); + CM_Free(msg); } else { conf = NULL;