X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=citadel%2Fmsgbase.c;h=d120ca41093bdf812d15535f95abfe2e9bbba1af;hb=5ac2920028e92a453c686c799327d7a66b3e7b49;hp=30f9a6888b9c084a681e257656731a7b6ef4bbc0;hpb=1a0e6bea859c26612782daf164e4062ef58a0cf4;p=citadel.git diff --git a/citadel/msgbase.c b/citadel/msgbase.c index 30f9a6888..d120ca410 100644 --- a/citadel/msgbase.c +++ b/citadel/msgbase.c @@ -1,7 +1,7 @@ /* * Implements the message store. * - * Copyright (c) 1987-2018 by the citadel.org team + * Copyright (c) 1987-2020 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. @@ -19,7 +19,6 @@ #include #include #include -#include "md5.h" #include "ctdl_module.h" #include "citserver.h" #include "control.h" @@ -35,15 +34,11 @@ struct addresses_to_be_filed *atbf = NULL; -/* This temp file holds the queue of operations for AdjRefCount() */ -static FILE *arcfp = NULL; -void AdjRefCountList(long *msgnum, long nmsg, int incr); - /* * These are the four-character field headers we use when outputting * messages in Citadel format (as opposed to RFC822 format). */ -char *msgkeys[91] = { +char *msgkeys[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -53,34 +48,34 @@ char *msgkeys[91] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - "from", /* A -> eAuthor */ - NULL, /* B -> eBig_message */ - NULL, /* C -> eRemoteRoom */ - NULL, /* D -> eDestination */ - "exti", /* E -> eXclusivID */ - "rfca", /* F -> erFc822Addr */ - NULL, /* G */ - "hnod", /* H -> eHumanNode */ - "msgn", /* I -> emessageId */ - "jrnl", /* J -> eJournal */ - "rep2", /* K -> eReplyTo */ - "list", /* L -> eListID */ - "text", /* M -> eMesageText */ - "node", /* N -> eNodeName */ - "room", /* O -> eOriginalRoom */ - "path", /* P -> eMessagePath */ - NULL, /* Q */ - "rcpt", /* R -> eRecipient */ - "spec", /* S -> eSpecialField */ - "time", /* T -> eTimestamp */ - "subj", /* U -> eMsgSubject */ - "nvto", /* V -> eenVelopeTo */ - "wefw", /* W -> eWeferences */ - NULL, /* X */ - "cccc", /* Y -> eCarbonCopY */ - NULL /* Z */ - + "from", // A -> eAuthor + NULL, // B -> eBig_message + NULL, // C (formerly used as eRemoteRoom) + NULL, // D (formerly used as eDestination) + "exti", // E -> eXclusivID + "rfca", // F -> erFc822Addr + NULL, // G + "hnod", // H (formerly used as eHumanNode) + "msgn", // I -> emessageId + "jrnl", // J -> eJournal + "rep2", // K -> eReplyTo + "list", // L -> eListID + "text", // M -> eMesageText + NULL, // N (formerly used as eNodeName) + "room", // O -> eOriginalRoom + "path", // P -> eMessagePath + NULL, // Q + "rcpt", // R -> eRecipient + NULL, // S (formerly used as eSpecialField) + "time", // T -> eTimestamp + "subj", // U -> eMsgSubject + "nvto", // V -> eenVelopeTo + "wefw", // W -> eWeferences + NULL, // X + "cccc", // Y -> eCarbonCopY + NULL // Z }; + HashList *msgKeyLookup = NULL; int GetFieldFromMnemonic(eMsgField *f, const char* c) @@ -114,21 +109,16 @@ eMsgField FieldOrder[] = { 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*/ +/* G is not used yet */ eReplyTo , eListID , /* Q is not used yet */ - eSpecialField, eenVelopeTo , /* X is not used yet */ /* Z is not used yet */ @@ -147,22 +137,25 @@ eMsgField FieldOrder[] = { 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')); + 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) + if (Msg->cm_fields[which] != NULL) { free (Msg->cm_fields[which]); + } Msg->cm_fields[which] = malloc(length + 1); memcpy(Msg->cm_fields[which], buf, length); Msg->cm_fields[which][length] = '\0'; Msg->cm_lengths[which] = length; } + void CM_SetFieldLONG(struct CtdlMessage *Msg, eMsgField which, long lvalue) { char buf[128]; @@ -170,6 +163,8 @@ void CM_SetFieldLONG(struct CtdlMessage *Msg, eMsgField which, long lvalue) 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) @@ -182,6 +177,7 @@ void CM_CutFieldAt(struct CtdlMessage *Msg, eMsgField WhichToCut, long maxlen) } } + void CM_FlushField(struct CtdlMessage *Msg, eMsgField which) { if (Msg->cm_fields[which] != NULL) @@ -189,35 +185,37 @@ void CM_FlushField(struct CtdlMessage *Msg, eMsgField which) Msg->cm_fields[which] = NULL; Msg->cm_lengths[which] = 0; } + + void CM_Flush(struct CtdlMessage *Msg) { int i; - if (CM_IsValidMsg(Msg) == 0) + if (CM_IsValidMsg(Msg) == 0) { return; + } - for (i = 0; i < 256; ++i) - { + for (i = 0; i < 256; ++i) { CM_FlushField(Msg, i); } } + void CM_CopyField(struct CtdlMessage *Msg, eMsgField WhichToPutTo, eMsgField WhichtToCopy) { long len; - if (Msg->cm_fields[WhichToPutTo] != NULL) + if (Msg->cm_fields[WhichToPutTo] != NULL) { free (Msg->cm_fields[WhichToPutTo]); + } - if (Msg->cm_fields[WhichtToCopy] != NULL) - { + if (Msg->cm_fields[WhichtToCopy] != NULL) { len = Msg->cm_lengths[WhichtToCopy]; Msg->cm_fields[WhichToPutTo] = malloc(len + 1); memcpy(Msg->cm_fields[WhichToPutTo], Msg->cm_fields[WhichtToCopy], len); Msg->cm_fields[WhichToPutTo][len] = '\0'; Msg->cm_lengths[WhichToPutTo] = len; } - else - { + else { Msg->cm_fields[WhichToPutTo] = NULL; Msg->cm_lengths[WhichToPutTo] = 0; } @@ -249,48 +247,53 @@ void CM_PrependToField(struct CtdlMessage *Msg, eMsgField which, const char *buf } } + void CM_SetAsField(struct CtdlMessage *Msg, eMsgField which, char **buf, long length) { - if (Msg->cm_fields[which] != NULL) + if (Msg->cm_fields[which] != NULL) { free (Msg->cm_fields[which]); + } Msg->cm_fields[which] = *buf; *buf = NULL; Msg->cm_lengths[which] = length; } + void CM_SetAsFieldSB(struct CtdlMessage *Msg, eMsgField which, StrBuf **buf) { - if (Msg->cm_fields[which] != NULL) + if (Msg->cm_fields[which] != NULL) { free (Msg->cm_fields[which]); + } Msg->cm_lengths[which] = StrLength(*buf); Msg->cm_fields[which] = SmashStrBuf(buf); } + void CM_GetAsField(struct CtdlMessage *Msg, eMsgField which, char **ret, long *retlen) { - if (Msg->cm_fields[which] != NULL) - { + if (Msg->cm_fields[which] != NULL) { *retlen = Msg->cm_lengths[which]; *ret = Msg->cm_fields[which]; Msg->cm_fields[which] = NULL; Msg->cm_lengths[which] = 0; } - else - { + 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) + if (msg == NULL) { return 0; + } if ((msg->cm_magic) != CTDLMESSAGE_MAGIC) { syslog(LOG_WARNING, "msgbase: CM_IsValidMsg() self-check failed"); return 0; @@ -298,6 +301,7 @@ int CM_IsValidMsg(struct CtdlMessage *msg) { return 1; } + void CM_FreeContents(struct CtdlMessage *msg) { int i; @@ -310,13 +314,14 @@ void CM_FreeContents(struct CtdlMessage *msg) msg->cm_magic = 0; /* just in case */ } + + /* * 'Destructor' for struct CtdlMessage */ void CM_Free(struct CtdlMessage *msg) { - if (CM_IsValidMsg(msg) == 0) - { + if (CM_IsValidMsg(msg) == 0) { if (msg != NULL) free (msg); return; } @@ -324,40 +329,42 @@ void CM_Free(struct CtdlMessage *msg) free(msg); } + int CM_DupField(eMsgField i, struct CtdlMessage *OrgMsg, struct CtdlMessage *NewMsg) { long len; len = OrgMsg->cm_lengths[i]; NewMsg->cm_fields[i] = malloc(len + 1); - if (NewMsg->cm_fields[i] == NULL) + if (NewMsg->cm_fields[i] == NULL) { return 0; + } memcpy(NewMsg->cm_fields[i], OrgMsg->cm_fields[i], len); NewMsg->cm_fields[i][len] = '\0'; NewMsg->cm_lengths[i] = len; return 1; } + struct CtdlMessage * CM_Duplicate(struct CtdlMessage *OrgMsg) { int i; struct CtdlMessage *NewMsg; - if (CM_IsValidMsg(OrgMsg) == 0) + if (CM_IsValidMsg(OrgMsg) == 0) { return NULL; + } NewMsg = (struct CtdlMessage *)malloc(sizeof(struct CtdlMessage)); - if (NewMsg == NULL) + 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)) - { + for (i = 0; i < 256; ++i) { + if (OrgMsg->cm_fields[i] != NULL) { + if (!CM_DupField(i, OrgMsg, NewMsg)) { CM_Free(NewMsg); return NULL; } @@ -368,9 +375,6 @@ struct CtdlMessage * CM_Duplicate(struct CtdlMessage *OrgMsg) } - - - /* Determine if a given message matches the fields in a message template. * Return 0 for a successful match. */ @@ -403,7 +407,6 @@ int CtdlMsgCmp(struct CtdlMessage *msg, struct CtdlMessage *template) { } - /* * Retrieve the "seen" message list for the current room. */ @@ -413,14 +416,15 @@ void CtdlGetSeen(char *buf, int which_set) { /* Learn about the user and room in question */ CtdlGetRelationship(&vbuf, &CC->user, &CC->room); - if (which_set == ctdlsetseen_seen) + if (which_set == ctdlsetseen_seen) { safestrncpy(buf, vbuf.v_seen, SIZ); - if (which_set == ctdlsetseen_answered) + } + if (which_set == ctdlsetseen_answered) { safestrncpy(buf, vbuf.v_answered, SIZ); + } } - /* * Manipulate the "seen msgs" string (or other message set strings) */ @@ -432,7 +436,7 @@ void CtdlSetSeen(long *target_msgnums, int num_target_msgnums, int is_seen = 0; int was_seen = 0; long lo = (-1L); - long hi = (-1L); /// TODO: we just write here. y? + long hi = (-1L); visit vbuf; long *msglist; int num_msgs = 0; @@ -538,7 +542,6 @@ void CtdlSetSeen(long *target_msgnums, int num_target_msgnums, FreeStrBuf(&lostr); FreeStrBuf(&histr); - /* Now translate the array of booleans back into a sequence set */ FlushStrBuf(vset); was_seen = 0; @@ -843,12 +846,15 @@ int CtdlForEachMessage(int mode, long ref, char *search_string, ) ) { if ((mode == MSGS_NEW) && (CC->user.flags & US_LASTOLD) && (lastold > 0L) && (printed_lastold == 0) && (!is_seen)) { - if (CallBack) + if (CallBack) { CallBack(lastold, userdata); + } printed_lastold = 1; ++num_processed; } - if (CallBack) CallBack(thismsg, userdata); + if (CallBack) { + CallBack(thismsg, userdata); + } ++num_processed; } } @@ -872,7 +878,6 @@ int CtdlForEachMessage(int mode, long ref, char *search_string, } - /* * memfmout() - Citadel text formatter and paginator. * Although the original purpose of this routine was to format @@ -895,14 +900,12 @@ void memfmout( while (ch=*(mptr++), ch != 0) { if (ch == '\n') { - if (client_write(outbuf, len) == -1) - { + if (client_write(outbuf, len) == -1) { syslog(LOG_ERR, "msgbase: memfmout() aborting due to write failure"); return; } len = 0; - if (client_write(nl, nllen) == -1) - { + if (client_write(nl, nllen) == -1) { syslog(LOG_ERR, "msgbase: memfmout() aborting due to write failure"); return; } @@ -913,14 +916,12 @@ void memfmout( } else if (isspace(ch)) { if (column > 72) { /* Beyond 72 columns, break on the next space */ - if (client_write(outbuf, len) == -1) - { + if (client_write(outbuf, len) == -1) { syslog(LOG_ERR, "msgbase: memfmout() aborting due to write failure"); return; } len = 0; - if (client_write(nl, nllen) == -1) - { + if (client_write(nl, nllen) == -1) { syslog(LOG_ERR, "msgbase: memfmout() aborting due to write failure"); return; } @@ -935,14 +936,12 @@ void memfmout( outbuf[len++] = ch; ++column; if (column > 1000) { /* Beyond 1000 columns, break anywhere */ - if (client_write(outbuf, len) == -1) - { + if (client_write(outbuf, len) == -1) { syslog(LOG_ERR, "msgbase: memfmout() aborting due to write failure"); return; } len = 0; - if (client_write(nl, nllen) == -1) - { + if (client_write(nl, nllen) == -1) { syslog(LOG_ERR, "msgbase: memfmout(): aborting due to write failure"); return; } @@ -951,8 +950,7 @@ void memfmout( } } if (len) { - if (client_write(outbuf, len) == -1) - { + if (client_write(outbuf, len) == -1) { syslog(LOG_ERR, "msgbase: memfmout() aborting due to write failure"); return; } @@ -962,7 +960,6 @@ void memfmout( } - /* * Callback function for mime parser that simply lists the part */ @@ -986,6 +983,7 @@ void list_this_part(char *name, char *filename, char *partnum, char *disp, } } + /* * Callback function for multipart prefix */ @@ -1005,6 +1003,7 @@ void list_this_pref(char *name, char *filename, char *partnum, char *disp, } } + /* * Callback function for multipart sufffix */ @@ -1066,7 +1065,6 @@ void mime_download(char *name, char *filename, char *partnum, char *disp, } - /* * Callback function for mime parser that outputs a section all at once. * We can specify the desired section by part number *or* content-id. @@ -1093,6 +1091,7 @@ void mime_spew_section(char *name, char *filename, char *partnum, char *disp, } } + struct CtdlMessage *CtdlDeserializeMessage(long msgnum, int with_body, const char *Buffer, long Length) { struct CtdlMessage *ret = NULL; @@ -1104,6 +1103,9 @@ struct CtdlMessage *CtdlDeserializeMessage(long msgnum, int with_body, const cha mptr = Buffer; upper_bound = Buffer + Length; + if (msgnum <= 0) { + return NULL; + } /* Parse the three bytes that begin EVERY message on disk. * The first is always 0xFF, the on-disk magic number. @@ -1132,8 +1134,7 @@ struct CtdlMessage *CtdlDeserializeMessage(long msgnum, int with_body, const cha long len; /* work around possibly buggy messages: */ - while (field_header == '\0') - { + while (field_header == '\0') { if (mptr >= upper_bound) { break; } @@ -1174,8 +1175,7 @@ struct CtdlMessage *CtdlFetchMessage(long msgnum, int with_body, int run_msg_hoo return NULL; } - if (dmsgtext->ptr[dmsgtext->len - 1] != '\0') - { + if (dmsgtext->ptr[dmsgtext->len - 1] != '\0') { syslog(LOG_ERR, "msgbase: CtdlFetchMessage(%ld, %d) Forcefully terminating message!!", msgnum, with_body); dmsgtext->ptr[dmsgtext->len - 1] = '\0'; } @@ -1214,7 +1214,6 @@ struct CtdlMessage *CtdlFetchMessage(long msgnum, int with_body, int run_msg_hoo } - /* * Pre callback function for multipart/alternative * @@ -1242,6 +1241,7 @@ void fixed_output_pre(char *name, char *filename, char *partnum, char *disp, } } + /* * Post callback function for multipart/alternative */ @@ -1262,6 +1262,7 @@ void fixed_output_post(char *name, char *filename, char *partnum, char *disp, } } + /* * Inline callback function for mime parser that wants to display text */ @@ -1304,7 +1305,7 @@ void fixed_output(char *name, char *filename, char *partnum, char *disp, } if (!strcasecmp(cbtype, "text/html")) { - ptr = html_to_ascii(content, length, 80, 0); + ptr = html_to_ascii(content, length, 80); wlen = strlen(ptr); client_write(ptr, wlen); if ((wlen > 0) && (ptr[wlen-1] != '\n')) { @@ -1328,6 +1329,7 @@ void fixed_output(char *name, char *filename, char *partnum, char *disp, } } + /* * The client is elegant and sophisticated and wants to be choosy about * MIME content types, so figure out which multipart/alternative part @@ -1349,11 +1351,6 @@ void choose_preferred(char *name, char *filename, char *partnum, char *disp, ma = (struct ma_info *)cbuserdata; - // NOTE: REMOVING THIS CONDITIONAL FIXES BUG 220 - // http://bugzilla.citadel.org/show_bug.cgi?id=220 - // I don't know if there are any side effects! Please TEST TEST TEST - //if (ma->is_ma > 0) { - for (i=0; ipreferred_formats, '|'); ++i) { extract_token(buf, CC->preferred_formats, i, '|', sizeof buf); if ( (!strcasecmp(buf, cbtype)) && (!ma->freeze) ) { @@ -1366,6 +1363,7 @@ void choose_preferred(char *name, char *filename, char *partnum, char *disp, } } + /* * Now that we've chosen our preferred part, output it. */ @@ -1531,7 +1529,6 @@ int check_cached_msglist(long msgnum) { } - /* * Get a message off disk. (returns om_* values found in msgbase.h) * @@ -1688,13 +1685,11 @@ int CtdlOutputMsg(long msg_num, /* message number (local) to fetch */ } - void OutputCtdlMsgHeaders( struct CtdlMessage *TheMessage, int do_proto) /* do Citadel protocol responses? */ { int i; - int suppress_f = 0; char buf[SIZ]; char display_name[256]; @@ -1721,16 +1716,6 @@ void OutputCtdlMsgHeaders( } } - /* Don't show Internet address for users on the - * local Citadel network. - */ - suppress_f = 0; - 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. */ for (i=0; i< NDiskFields; ++i) { eMsgField Field; @@ -1748,25 +1733,21 @@ void OutputCtdlMsgHeaders( msgkeys[Field], display_name); } - else if ((Field == erFc822Addr) && (suppress_f)) { - /* do nothing */ - } /* Masquerade display name if needed */ else { - if (do_proto) cprintf("%s=%s\n", - msgkeys[Field], - TheMessage->cm_fields[Field] - ); + if (do_proto) { + cprintf("%s=%s\n", msgkeys[Field], TheMessage->cm_fields[Field]); + } } } } } - } + void OutputRFC822MsgHeaders( struct CtdlMessage *TheMessage, - int flags, /* should the bessage be exported clean */ + int flags, /* should the message be exported clean */ const char *nl, int nlen, char *mid, long sizeof_mid, char *suser, long sizeof_suser, @@ -1817,27 +1798,17 @@ void OutputRFC822MsgHeaders( subject_found = 1; break; case emessageId: - safestrncpy(mid, mptr, sizeof_mid); /// TODO: detect @ here and copy @nodename in if not found. + safestrncpy(mid, mptr, sizeof_mid); break; case erFc822Addr: safestrncpy(fuser, mptr, sizeof_fuser); - /* case eOriginalRoom: - cprintf("X-Citadel-Room: %s%s", - mptr, nl) - break; - ; */ - case eNodeName: - safestrncpy(snode, mptr, sizeof_snode); - break; case eRecipient: - if (haschar(mptr, '@') == 0) - { + if (haschar(mptr, '@') == 0) { sanitize_truncated_recipient(mptr); cprintf("To: %s@%s", mptr, CtdlGetConfigStr("c_fqdn")); cprintf("%s", nl); } - else - { + else { if ((flags & QP_EADDR) != 0) { mptr = qp_encode_email_addrs(mptr); } @@ -1847,8 +1818,7 @@ void OutputRFC822MsgHeaders( } break; case eTimestamp: - datestring(datestamp, sizeof datestamp, - atol(mptr), DATESTRING_RFC822); + datestring(datestamp, sizeof datestamp, atol(mptr), DATESTRING_RFC822); cprintf("Date: %s%s", datestamp, nl); break; case eWeferences: @@ -1873,25 +1843,21 @@ void OutputRFC822MsgHeaders( cprintf("Reply-To: %s%s", mptr, nl); break; - case eRemoteRoom: - case eDestination: case eExclusiveID: - case eHumanNode: case eJournal: case eMesageText: case eBig_message: case eOriginalRoom: - case eSpecialField: case eErrorMsg: case eSuppressIdx: case eExtnotify: case eVltMsgNum: /* these don't map to mime message headers. */ break; - } - if (mptr != mpptr) + if (mptr != mpptr) { free (mptr); + } } } if (subject_found == 0) { @@ -1904,7 +1870,6 @@ void Dump_RFC822HeadersBody( struct CtdlMessage *TheMessage, int headers_only, /* eschew the message body? */ int flags, /* should the bessage be exported clean? */ - const char *nl, int nlen) { cit_uint8_t prev_ch; @@ -1918,7 +1883,6 @@ void Dump_RFC822HeadersBody( mptr = TheMessage->cm_fields[eMesageText]; - prev_ch = '\0'; while (*mptr != '\0') { if (*mptr == '\r') { @@ -1942,7 +1906,7 @@ void Dump_RFC822HeadersBody( ((headers_only == HEADERS_ONLY) && (mptr < StartOfText)) || ((headers_only != HEADERS_NONE) && (headers_only != HEADERS_ONLY)) - ) { + ) { if (*mptr == '\n') { memcpy(&outbuf[outlen], nl, nllen); outlen += nllen; @@ -1953,20 +1917,15 @@ void Dump_RFC822HeadersBody( } } } - if (flags & ESC_DOT) - { - if ((prev_ch == '\n') && - (*mptr == '.') && - ((*(mptr+1) == '\r') || (*(mptr+1) == '\n'))) - { + if (flags & ESC_DOT) { + if ((prev_ch == '\n') && (*mptr == '.') && ((*(mptr+1) == '\r') || (*(mptr+1) == '\n'))) { outbuf[outlen++] = '.'; } prev_ch = *mptr; } ++mptr; if (outlen > 1000) { - if (client_write(outbuf, outlen) == -1) - { + if (client_write(outbuf, outlen) == -1) { syslog(LOG_ERR, "msgbase: Dump_RFC822HeadersBody() aborting due to write failure"); return; } @@ -1983,7 +1942,6 @@ void Dump_RFC822HeadersBody( } - /* If the format type on disk is 1 (fixed-format), then we want * everything to be output completely literally ... regardless of * what message transfer format is in use. @@ -2026,20 +1984,18 @@ void DumpFormatFixed( ch = '\r'; } } - /* if we reach the outer bounds of our buffer, - abort without respect what whe purge. */ - if (xlline && - ((isspace(ch)) || - (buflen > SIZ - nllen - 2))) + + /* if we reach the outer bounds of our buffer, abort without respect for what we purge. */ + if (xlline && ((isspace(ch)) || (buflen > SIZ - nllen - 2))) { ch = '\r'; + } if (ch == '\r') { memcpy (&buf[buflen], nl, nllen); buflen += nllen; buf[buflen] = '\0'; - if (client_write(buf, buflen) == -1) - { + if (client_write(buf, buflen) == -1) { syslog(LOG_ERR, "msgbase: DumpFormatFixed() aborting due to write failure"); return; } @@ -2052,10 +2008,12 @@ void DumpFormatFixed( } } buf[buflen] = '\0'; - if (!IsEmptyStr(buf)) + if (!IsEmptyStr(buf)) { cprintf("%s%s", buf, nl); + } } + /* * Get a message off disk. (returns om_* values found in msgbase.h) */ @@ -2183,7 +2141,6 @@ int CtdlOutputPreLoadedMsg( strcpy(suser, ""); strcpy(luser, ""); strcpy(fuser, ""); - memcpy(snode, CtdlGetConfigStr("c_nodename"), strlen(CtdlGetConfigStr("c_nodename")) + 1); if (mode == MT_RFC822) OutputRFC822MsgHeaders( TheMessage, @@ -2203,12 +2160,8 @@ int CtdlOutputPreLoadedMsg( } if (mode == MT_RFC822) { - if (!strcasecmp(snode, NODENAME)) { - safestrncpy(snode, FQDN, sizeof snode); - } - /* Construct a fun message id */ - cprintf("Message-ID: <%s", mid);/// todo: this possibly breaks threadding mails. + cprintf("Message-ID: <%s", mid); if (strchr(mid, '@')==NULL) { cprintf("@%s", snode); } @@ -2912,10 +2865,10 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ if ((recps != NULL) && (recps->bounce_to == NULL)) { if (CC->logged_in) { - snprintf(bounce_to, sizeof bounce_to, "%s@%s", CC->user.fullname, CtdlGetConfigStr("c_nodename")); + strcpy(bounce_to, CC->user.fullname); } else { - snprintf(bounce_to, sizeof bounce_to, "%s@%s", msg->cm_fields[eAuthor], msg->cm_fields[eNodeName]); + strcpy(bounce_to, msg->cm_fields[eAuthor]); } recps->bounce_to = bounce_to; } @@ -3060,7 +3013,6 @@ long quickie_message(const char *from, if (!IsEmptyStr(fromaddr)) CM_SetField(msg, erFc822Addr, fromaddr, strlen(fromaddr)); if (!IsEmptyStr(room)) CM_SetField(msg, eOriginalRoom, room, strlen(room)); - CM_SetField(msg, eNodeName, CtdlGetConfigStr("c_nodename"), strlen(CtdlGetConfigStr("c_nodename"))); if (!IsEmptyStr(to)) { CM_SetField(msg, eRecipient, to, strlen(to)); recp = validate_recipients(to, NULL, 0); @@ -3126,13 +3078,9 @@ StrBuf *CtdlReadMessageBodyBuf(char *terminator, /* token signalling EOT */ } /* Unescape SMTP-style input of two dots at the beginning of the line */ - if ((dotdot) && - (StrLength(LineBuf) == 2) && - (!strcmp(ChrPtr(LineBuf), ".."))) - { + if ((dotdot) && (StrLength(LineBuf) > 1) && (ChrPtr(LineBuf)[0] == '.')) { StrBufCutLeft(LineBuf, 1); } - StrBufAppendBuf(Message, LineBuf, 0); } @@ -3290,9 +3238,6 @@ struct CtdlMessage *CtdlMakeMessageLen( } } - CM_SetField(msg, eNodeName, CtdlGetConfigStr("c_nodename"), strlen(CtdlGetConfigStr("c_nodename"))); - CM_SetField(msg, eHumanNode, CtdlGetConfigStr("c_humannode"), strlen(CtdlGetConfigStr("c_humannode"))); - if (rcplen > 0) { CM_SetField(msg, eRecipient, recipient, rcplen); } @@ -3500,14 +3445,11 @@ int CtdlDeleteMessages(const char *room_name, /* which room */ } - - /* * GetMetaData() - Get the supplementary record for a message */ void GetMetaData(struct MetaData *smibuf, long msgnum) { - struct cdbdata *cdbsmi; long TheIndex; @@ -3520,11 +3462,12 @@ void GetMetaData(struct MetaData *smibuf, long msgnum) cdbsmi = cdb_fetch(CDB_MSGMAIN, &TheIndex, sizeof(long)); if (cdbsmi == NULL) { - return; /* record not found; go with defaults */ + return; /* record not found; leave it alone */ } memcpy(smibuf, cdbsmi->ptr, ((cdbsmi->len > sizeof(struct MetaData)) ? - sizeof(struct MetaData) : cdbsmi->len)); + sizeof(struct MetaData) : cdbsmi->len) + ); cdb_free(cdbsmi); return; } @@ -3542,175 +3485,29 @@ void PutMetaData(struct MetaData *smibuf) cdb_store(CDB_MSGMAIN, &TheIndex, (int)sizeof(long), - smibuf, (int)sizeof(struct MetaData)); - + smibuf, (int)sizeof(struct MetaData) + ); } + /* - * AdjRefCount - submit an adjustment to the reference count for a message. - * (These are just queued -- we actually process them later.) + * Convenience function to process a big block of AdjRefCount() operations */ -void AdjRefCount(long msgnum, int incr) -{ - struct arcq new_arcq; - int rv = 0; - - syslog(LOG_DEBUG, "msgbase: AdjRefCount() msg %ld ref count delta %+d", msgnum, incr); - - begin_critical_section(S_SUPPMSGMAIN); - if (arcfp == NULL) { - arcfp = fopen(file_arcq, "ab+"); - chown(file_arcq, CTDLUID, (-1)); - chmod(file_arcq, 0600); - } - end_critical_section(S_SUPPMSGMAIN); - - /* msgnum < 0 means that we're trying to close the file */ - if (msgnum < 0) { - syslog(LOG_DEBUG, "msgbase: closing the AdjRefCount queue file"); - begin_critical_section(S_SUPPMSGMAIN); - if (arcfp != NULL) { - fclose(arcfp); - arcfp = NULL; - } - end_critical_section(S_SUPPMSGMAIN); - return; - } - - /* - * If we can't open the queue, perform the operation synchronously. - */ - if (arcfp == NULL) { - TDAP_AdjRefCount(msgnum, incr); - return; - } - - new_arcq.arcq_msgnum = msgnum; - new_arcq.arcq_delta = incr; - rv = fwrite(&new_arcq, sizeof(struct arcq), 1, arcfp); - if (rv == -1) { - syslog(LOG_EMERG, "%s: %m", file_arcq); - } - fflush(arcfp); - - return; -} - void AdjRefCountList(long *msgnum, long nmsg, int incr) { - long i, the_size, offset; - struct arcq *new_arcq; - int rv = 0; - - begin_critical_section(S_SUPPMSGMAIN); - if (arcfp == NULL) { - arcfp = fopen(file_arcq, "ab+"); - chown(file_arcq, CTDLUID, (-1)); - chmod(file_arcq, 0600); - } - end_critical_section(S_SUPPMSGMAIN); - - /* - * If we can't open the queue, perform the operation synchronously. - */ - if (arcfp == NULL) { - for (i = 0; i < nmsg; i++) - TDAP_AdjRefCount(msgnum[i], incr); - return; - } + long i; - the_size = sizeof(struct arcq) * nmsg; - new_arcq = malloc(the_size); for (i = 0; i < nmsg; i++) { - syslog(LOG_DEBUG, "msgbase: AdjRefCountList() msg %ld ref count delta %+d", msgnum[i], incr); - new_arcq[i].arcq_msgnum = msgnum[i]; - new_arcq[i].arcq_delta = incr; + AdjRefCount(msgnum[i], incr); } - rv = 0; - offset = 0; - while ((rv >= 0) && (offset < the_size)) - { - rv = fwrite(new_arcq + offset, 1, the_size - offset, arcfp); - if (rv == -1) { - syslog(LOG_ERR, "%s: %m", file_arcq); - } - else { - offset += rv; - } - } - free(new_arcq); - fflush(arcfp); - - return; } /* - * TDAP_ProcessAdjRefCountQueue() - * - * Process the queue of message count adjustments that was created by calls - * to AdjRefCount() ... by reading the queue and calling TDAP_AdjRefCount() - * for each one. This should be an "off hours" operation. + * AdjRefCount - adjust the reference count for a message. We need to delete from disk any message whose reference count reaches zero. */ -int TDAP_ProcessAdjRefCountQueue(void) -{ - char file_arcq_temp[PATH_MAX]; - int r; - FILE *fp; - struct arcq arcq_rec; - int num_records_processed = 0; - - snprintf(file_arcq_temp, sizeof file_arcq_temp, "%s.%04x", file_arcq, rand()); - - begin_critical_section(S_SUPPMSGMAIN); - if (arcfp != NULL) { - fclose(arcfp); - arcfp = NULL; - } - - r = link(file_arcq, file_arcq_temp); - if (r != 0) { - syslog(LOG_ERR, "%s: %m", file_arcq_temp); - end_critical_section(S_SUPPMSGMAIN); - return(num_records_processed); - } - - unlink(file_arcq); - end_critical_section(S_SUPPMSGMAIN); - - fp = fopen(file_arcq_temp, "rb"); - if (fp == NULL) { - syslog(LOG_ERR, "%s: %m", file_arcq_temp); - return(num_records_processed); - } - - while (fread(&arcq_rec, sizeof(struct arcq), 1, fp) == 1) { - TDAP_AdjRefCount(arcq_rec.arcq_msgnum, arcq_rec.arcq_delta); - ++num_records_processed; - } - - fclose(fp); - r = unlink(file_arcq_temp); - if (r != 0) { - syslog(LOG_ERR, "%s: %m", file_arcq_temp); - } - - return(num_records_processed); -} - - - -/* - * TDAP_AdjRefCount - adjust the reference count for a message. - * This one does it "for real" because it's called by - * the autopurger function that processes the queue - * created by AdjRefCount(). If a message's reference - * count becomes zero, we also delete the message from - * disk and de-index it. - */ -void TDAP_AdjRefCount(long msgnum, int incr) +void AdjRefCount(long msgnum, int incr) { - struct MetaData smi; long delnum; @@ -3723,12 +3520,9 @@ void TDAP_AdjRefCount(long msgnum, int incr) smi.meta_refcount += incr; PutMetaData(&smi); end_critical_section(S_SUPPMSGMAIN); - syslog(LOG_DEBUG, "msgbase: TDAP_AdjRefCount() msg %ld ref count delta %+d, is now %d", - msgnum, incr, smi.meta_refcount - ); + syslog(LOG_DEBUG, "msgbase: AdjRefCount() msg %ld ref count delta %+d, is now %d", msgnum, incr, smi.meta_refcount); - /* If the reference count is now zero, delete the message - * (and its supplementary record as well). + /* If the reference count is now zero, delete both the message and its metadata record. */ if (smi.meta_refcount == 0) { syslog(LOG_DEBUG, "msgbase: deleting message <%ld>", msgnum); @@ -3745,9 +3539,9 @@ void TDAP_AdjRefCount(long msgnum, int incr) delnum = (0L - msgnum); cdb_delete(CDB_MSGMAIN, &delnum, (int)sizeof(long)); } - } + /* * Write a generic object to this room * @@ -3756,12 +3550,12 @@ void TDAP_AdjRefCount(long msgnum, int incr) */ void CtdlWriteObject(char *req_room, /* Room to stuff it in */ char *content_type, /* MIME type of this object */ - char *raw_message, /* Data to be written */ - off_t raw_length, /* Size of raw_message */ + char *raw_message, /* Data to be written */ + off_t raw_length, /* Size of raw_message */ struct ctdluser *is_mailbox, /* Mailbox room? */ int is_binary, /* Is encoding necessary? */ int is_unique, /* Del others of this type? */ - unsigned int flags /* Internal save flags */ + unsigned int flags /* Internal save flags */ ) { struct ctdlroom qrbuf; @@ -3811,17 +3605,13 @@ void CtdlWriteObject(char *req_room, /* Room to stuff it in */ msg->cm_format_type = 4; CM_SetField(msg, eAuthor, CC->user.fullname, strlen(CC->user.fullname)); CM_SetField(msg, eOriginalRoom, req_room, strlen(req_room)); - CM_SetField(msg, eNodeName, CtdlGetConfigStr("c_nodename"), strlen(CtdlGetConfigStr("c_nodename"))); - CM_SetField(msg, eHumanNode, CtdlGetConfigStr("c_humannode"), strlen(CtdlGetConfigStr("c_humannode"))); msg->cm_flags = flags; CM_SetAsFieldSB(msg, eMesageText, &encoded_message); /* Create the requested room if we have to. */ if (CtdlGetRoom(&qrbuf, roomname) != 0) { - CtdlCreateRoom(roomname, - ( (is_mailbox != NULL) ? 5 : 3 ), - "", 0, 1, 0, VIEW_BBS); + CtdlCreateRoom(roomname, ( (is_mailbox != NULL) ? 5 : 3 ), "", 0, 1, 0, VIEW_BBS); } /* If the caller specified this object as unique, delete all * other objects of this type that are currently in the room. @@ -3837,10 +3627,9 @@ void CtdlWriteObject(char *req_room, /* Room to stuff it in */ } - -/*****************************************************************************/ -/* MODULE INITIALIZATION STUFF */ -/*****************************************************************************/ +/************************************************************************/ +/* MODULE INITIALIZATION */ +/************************************************************************/ CTDL_MODULE_INIT(msgbase) { @@ -3848,6 +3637,6 @@ CTDL_MODULE_INIT(msgbase) FillMsgKeyLookupTable(); } - /* return our Subversion id for the Log */ + /* return our module id for the log */ return "msgbase"; }