X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=citadel%2Fmsgbase.c;h=77bc946156b93f57f13931ad2b2ef985aff9f916;hb=068d33e5d8569b2c4a2c8582178427892b0a8dee;hp=30f9a6888b9c084a681e257656731a7b6ef4bbc0;hpb=1a0e6bea859c26612782daf164e4062ef58a0cf4;p=citadel.git diff --git a/citadel/msgbase.c b/citadel/msgbase.c index 30f9a6888..77bc94615 100644 --- a/citadel/msgbase.c +++ b/citadel/msgbase.c @@ -1,16 +1,14 @@ -/* - * Implements the message store. - * - * Copyright (c) 1987-2018 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 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. - */ +// Implements the message store. +// +// Copyright (c) 1987-2021 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 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. #include @@ -19,7 +17,6 @@ #include #include #include -#include "md5.h" #include "ctdl_module.h" #include "citserver.h" #include "control.h" @@ -35,15 +32,9 @@ 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] = { +// These are the four-character field headers we use when outputting +// messages in Citadel format (as opposed to RFC822 format). +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,38 +44,38 @@ 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) -{ +int GetFieldFromMnemonic(eMsgField *f, const char* c) { void *v = NULL; if (GetHash(msgKeyLookup, c, 4, &v)) { *f = (eMsgField) v; @@ -93,8 +84,7 @@ int GetFieldFromMnemonic(eMsgField *f, const char* c) return 0; } -void FillMsgKeyLookupTable(void) -{ +void FillMsgKeyLookupTable(void) { long i; msgKeyLookup = NewHash (1, FourHash); @@ -106,6 +96,7 @@ void FillMsgKeyLookupTable(void) } } + eMsgField FieldOrder[] = { /* Important fields */ emessageId , @@ -114,21 +105,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,31 +133,35 @@ 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')); + +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) + +void CM_SetField(struct CtdlMessage *Msg, eMsgField which, const char *buf, long length) { + if (Msg->cm_fields[which] != NULL) { free (Msg->cm_fields[which]); + } + if (length < 0) { // You can set the length to -1 to have CM_SetField measure it for you + length = strlen(buf); + } 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) -{ + +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) -{ + + +void CM_CutFieldAt(struct CtdlMessage *Msg, eMsgField WhichToCut, long maxlen) { if (Msg->cm_fields[WhichToCut] == NULL) return; @@ -182,50 +172,49 @@ void CM_CutFieldAt(struct CtdlMessage *Msg, eMsgField WhichToCut, long maxlen) } } -void CM_FlushField(struct CtdlMessage *Msg, eMsgField which) -{ + +void CM_FlushField(struct CtdlMessage *Msg, eMsgField which) { if (Msg->cm_fields[which] != NULL) free (Msg->cm_fields[which]); Msg->cm_fields[which] = NULL; Msg->cm_lengths[which] = 0; } -void CM_Flush(struct CtdlMessage *Msg) -{ + + +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) -{ + +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; } } -void CM_PrependToField(struct CtdlMessage *Msg, eMsgField which, const char *buf, long length) -{ +void CM_PrependToField(struct CtdlMessage *Msg, eMsgField which, const char *buf, long length) { if (Msg->cm_fields[which] != NULL) { long oldmsgsize; long newmsgsize; @@ -249,48 +238,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) + +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; - Msg->cm_lengths[which] = length; + if (length < 0) { // You can set the length to -1 to have CM_SetField measure it for you + Msg->cm_lengths[which] = strlen(Msg->cm_fields[which]); + } + else { + Msg->cm_lengths[which] = length; + } } -void CM_SetAsFieldSB(struct CtdlMessage *Msg, eMsgField which, StrBuf **buf) -{ - if (Msg->cm_fields[which] != NULL) + +void CM_SetAsFieldSB(struct CtdlMessage *Msg, eMsgField which, StrBuf **buf) { + 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) - { + +void CM_GetAsField(struct CtdlMessage *Msg, eMsgField which, char **ret, long *retlen) { + 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. - */ + +// 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,8 +292,8 @@ int CM_IsValidMsg(struct CtdlMessage *msg) { return 1; } -void CM_FreeContents(struct CtdlMessage *msg) -{ + +void CM_FreeContents(struct CtdlMessage *msg) { int i; for (i = 0; i < 256; ++i) @@ -308,15 +302,13 @@ void CM_FreeContents(struct CtdlMessage *msg) msg->cm_lengths[i] = 0; } - msg->cm_magic = 0; /* just in case */ + msg->cm_magic = 0; // just in case } -/* - * 'Destructor' for struct CtdlMessage - */ -void CM_Free(struct CtdlMessage *msg) -{ - if (CM_IsValidMsg(msg) == 0) - { + + +// 'Destructor' for struct CtdlMessage +void CM_Free(struct CtdlMessage *msg) { + if (CM_IsValidMsg(msg) == 0) { if (msg != NULL) free (msg); return; } @@ -324,40 +316,40 @@ void CM_Free(struct CtdlMessage *msg) free(msg); } -int CM_DupField(eMsgField i, struct CtdlMessage *OrgMsg, struct CtdlMessage *NewMsg) -{ + +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) -{ + +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,27 +360,21 @@ 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. - */ +// Determine if a given message matches the fields in a message template. +// Return 0 for a successful match. int CtdlMsgCmp(struct CtdlMessage *msg, struct CtdlMessage *template) { int i; - /* If there aren't any fields in the template, all messages will - * match. - */ + // If there aren't any fields in the template, all messages will match. if (template == NULL) return(0); - /* Null messages are bogus. */ + // Null messages are bogus. if (msg == NULL) return(1); for (i='A'; i<='Z'; ++i) { if (template->cm_fields[i] != NULL) { if (msg->cm_fields[i] == NULL) { - /* Considered equal if temmplate is empty string */ + // Considered equal if temmplate is empty string if (IsEmptyStr(template->cm_fields[i])) continue; return 1; } @@ -403,27 +389,23 @@ int CtdlMsgCmp(struct CtdlMessage *msg, struct CtdlMessage *template) { } - -/* - * Retrieve the "seen" message list for the current room. - */ +// Retrieve the "seen" message list for the current room. void CtdlGetSeen(char *buf, int which_set) { visit vbuf; - /* Learn about the user and room in question */ + // 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) - */ +// Manipulate the "seen msgs" string (or other message set strings) void CtdlSetSeen(long *target_msgnums, int num_target_msgnums, int target_setting, int which_set, struct ctdluser *which_user, struct ctdlroom *which_room) { @@ -432,7 +414,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; @@ -441,19 +423,19 @@ void CtdlSetSeen(long *target_msgnums, int num_target_msgnums, StrBuf *lostr; StrBuf *histr; const char *pvset; - char *is_set; /* actually an array of booleans */ + char *is_set; // actually an array of booleans - /* Don't bother doing *anything* if we were passed a list of zero messages */ + // Don't bother doing *anything* if we were passed a list of zero messages if (num_target_msgnums < 1) { return; } - /* If no room was specified, we go with the current room. */ + // If no room was specified, we go with the current room. if (!which_room) { which_room = &CC->room; } - /* If no user was specified, we go with the current user. */ + // If no user was specified, we go with the current user. if (!which_user) { which_user = &CC->user; } @@ -464,18 +446,19 @@ void CtdlSetSeen(long *target_msgnums, int num_target_msgnums, which_set, which_room->QRname); - /* Learn about the user and room in question */ + // Learn about the user and room in question CtdlGetRelationship(&vbuf, which_user, which_room); - /* Load the message list */ + // Load the message list cdbfr = cdb_fetch(CDB_MSGLISTS, &which_room->QRnumber, sizeof(long)); if (cdbfr != NULL) { msglist = (long *) cdbfr->ptr; - cdbfr->ptr = NULL; /* CtdlSetSeen() now owns this memory */ + cdbfr->ptr = NULL; // CtdlSetSeen() now owns this memory num_msgs = cdbfr->len / sizeof(long); cdb_free(cdbfr); - } else { - return; /* No messages at all? No further action. */ + } + else { + return; // No messages at all? No further action. } is_set = malloc(num_msgs * sizeof(char)); @@ -494,7 +477,7 @@ void CtdlSetSeen(long *target_msgnums, int num_target_msgnums, } -#if 0 /* This is a special diagnostic section. Do not allow it to run during normal operation. */ +#if 0 // This is a special diagnostic section. Do not allow it to run during normal operation. syslog(LOG_DEBUG, "There are %d messages in the room.\n", num_msgs); for (i=0; i 0) && (msglist[i] <= msglist[i-1])) abort(); @@ -505,7 +488,7 @@ void CtdlSetSeen(long *target_msgnums, int num_target_msgnums, } #endif - /* Translate the existing sequence set into an array of booleans */ + // Translate the existing sequence set into an array of booleans setstr = NewStrBuf(); lostr = NewStrBuf(); histr = NewStrBuf(); @@ -538,8 +521,7 @@ void CtdlSetSeen(long *target_msgnums, int num_target_msgnums, FreeStrBuf(&lostr); FreeStrBuf(&histr); - - /* Now translate the array of booleans back into a sequence set */ + // Now translate the array of booleans back into a sequence set FlushStrBuf(vset); was_seen = 0; lo = (-1); @@ -548,7 +530,7 @@ void CtdlSetSeen(long *target_msgnums, int num_target_msgnums, for (i=0; i SIZ) && (number_of_truncations < 100) ) { StrBufRemove_token(vset, 0, ','); ++number_of_truncations; } - /* - * If we're truncating the sequence set of messages marked with the 'seen' flag, - * we want the earliest messages (the truncated ones) to be marked, not unmarked. - * Otherwise messages at the beginning will suddenly appear to be 'unseen'. - */ + // If we're truncating the sequence set of messages marked with the 'seen' flag, + // we want the earliest messages (the truncated ones) to be marked, not unmarked. + // Otherwise messages at the beginning will suddenly appear to be 'unseen'. if ( (which_set == ctdlsetseen_seen) && (number_of_truncations > 0) ) { StrBuf *first_tok; first_tok = NewStrBuf(); @@ -626,7 +604,7 @@ void CtdlSetSeen(long *target_msgnums, int num_target_msgnums, vset = new_set; } - /* Decide which message set we're manipulating */ + // Decide which message set we're manipulating switch (which_set) { case ctdlsetseen_seen: safestrncpy(vbuf.v_seen, ChrPtr(vset), sizeof vbuf.v_seen); @@ -643,10 +621,8 @@ void CtdlSetSeen(long *target_msgnums, int num_target_msgnums, } -/* - * API function to perform an operation for each qualifying message in the - * current room. (Returns the number of messages processed.) - */ +// API function to perform an operation for each qualifying message in the +// current room. (Returns the number of messages processed.) int CtdlForEachMessage(int mode, long ref, char *search_string, char *content_type, struct CtdlMessage *compare, @@ -753,7 +729,7 @@ int CtdlForEachMessage(int mode, long ref, char *search_string, free(msglist); return -1; } - msg = CtdlFetchMessage(msglist[a], 1, 1); + msg = CtdlFetchMessage(msglist[a], 1); if (msg != NULL) { if (CtdlMsgCmp(msg, compare)) { msglist[a] = 0L; @@ -843,12 +819,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 +851,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 +873,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 +889,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 +909,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 +923,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 +933,6 @@ void memfmout( } - /* * Callback function for mime parser that simply lists the part */ @@ -986,6 +956,7 @@ void list_this_part(char *name, char *filename, char *partnum, char *disp, } } + /* * Callback function for multipart prefix */ @@ -1005,6 +976,7 @@ void list_this_pref(char *name, char *filename, char *partnum, char *disp, } } + /* * Callback function for multipart sufffix */ @@ -1045,14 +1017,14 @@ void mime_download(char *name, char *filename, char *partnum, char *disp, ) { CC->download_fp = tmpfile(); if (CC->download_fp == NULL) { - syslog(LOG_EMERG, "msgbase: mime_download() couldn't write: %m"); + syslog(LOG_ERR, "msgbase: mime_download() couldn't write: %m"); cprintf("%d cannot open temporary file: %s\n", ERROR + INTERNAL_ERROR, strerror(errno)); return; } rv = fwrite(content, length, 1, CC->download_fp); if (rv <= 0) { - syslog(LOG_EMERG, "msgbase: mime_download() Couldn't write: %m"); + syslog(LOG_ERR, "msgbase: mime_download() Couldn't write: %m"); cprintf("%d unable to write tempfile.\n", ERROR + TOO_BIG); fclose(CC->download_fp); CC->download_fp = NULL; @@ -1066,7 +1038,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 +1064,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,12 +1076,15 @@ 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. - * The second is the anonymous/public type byte. - * The third is the format type byte (vari, fixed, or MIME). - */ + // Parse the three bytes that begin EVERY message on disk. + // The first is always 0xFF, the on-disk magic number. + // The second is the anonymous/public type byte. + // The third is the format type byte (vari, fixed, or MIME). + // ch = *mptr++; if (ch != 255) { syslog(LOG_ERR, "msgbase: message %ld appears to be corrupted", msgnum); @@ -1119,21 +1094,18 @@ struct CtdlMessage *CtdlDeserializeMessage(long msgnum, int with_body, const cha memset(ret, 0, sizeof(struct CtdlMessage)); ret->cm_magic = CTDLMESSAGE_MAGIC; - ret->cm_anon_type = *mptr++; /* Anon type byte */ - ret->cm_format_type = *mptr++; /* Format type byte */ + ret->cm_anon_type = *mptr++; // Anon type byte + ret->cm_format_type = *mptr++; // Format type byte - /* - * The rest is zero or more arbitrary fields. Load them in. - * We're done when we encounter either a zero-length field or - * have just processed the 'M' (message text) field. - */ + // The rest is zero or more arbitrary fields. Load them in. + // We're done when we encounter either a zero-length field or + // have just processed the 'M' (message text) field. + // do { field_header = '\0'; long len; - /* work around possibly buggy messages: */ - while (field_header == '\0') - { + while (field_header == '\0') { // work around possibly buggy messages if (mptr >= upper_bound) { break; } @@ -1147,35 +1119,31 @@ struct CtdlMessage *CtdlDeserializeMessage(long msgnum, int with_body, const cha CM_SetField(ret, which, mptr, len); - mptr += len + 1; /* advance to next field */ + mptr += len + 1; // advance to next field } while ((mptr < upper_bound) && (field_header != 'M')); - return (ret); } -/* - * Load a message from disk into memory. - * This is used by CtdlOutputMsg() and other fetch functions. - * - * NOTE: Caller is responsible for freeing the returned CtdlMessage struct - * using the CM_Free(); function. - */ -struct CtdlMessage *CtdlFetchMessage(long msgnum, int with_body, int run_msg_hooks) -{ +// Load a message from disk into memory. +// This is used by CtdlOutputMsg() and other fetch functions. +// +// NOTE: Caller is responsible for freeing the returned CtdlMessage struct +// using the CM_Free(); function. +// +struct CtdlMessage *CtdlFetchMessage(long msgnum, int with_body) { struct cdbdata *dmsgtext; struct CtdlMessage *ret = NULL; syslog(LOG_DEBUG, "msgbase: CtdlFetchMessage(%ld, %d)", msgnum, with_body); dmsgtext = cdb_fetch(CDB_MSGMAIN, &msgnum, sizeof(long)); if (dmsgtext == NULL) { - syslog(LOG_ERR, "msgbase: CtdlFetchMessage(%ld, %d) Failed!", msgnum, with_body); + syslog(LOG_ERR, "msgbase: message #%ld was not found", msgnum); 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'; } @@ -1188,11 +1156,11 @@ struct CtdlMessage *CtdlFetchMessage(long msgnum, int with_body, int run_msg_hoo return NULL; } - /* Always make sure there's something in the msg text field. If - * it's NULL, the message text is most likely stored separately, - * so go ahead and fetch that. Failing that, just set a dummy - * body so other code doesn't barf. - */ + // Always make sure there's something in the msg text field. If + // it's NULL, the message text is most likely stored separately, + // 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) ) { dmsgtext = cdb_fetch(CDB_BIGMSGS, &msgnum, sizeof(long)); if (dmsgtext != NULL) { @@ -1204,27 +1172,18 @@ struct CtdlMessage *CtdlFetchMessage(long msgnum, int with_body, int run_msg_hoo CM_SetField(ret, eMesageText, HKEY("\r\n\r\n (no text)\r\n")); } - /* Perform "before read" hooks (aborting if any return nonzero) */ - if (run_msg_hooks && (PerformMessageHooks(ret, NULL, EVT_BEFOREREAD) > 0)) { - CM_Free(ret); - return NULL; - } - return (ret); } - -/* - * Pre callback function for multipart/alternative - * - * NOTE: this differs from the standard behavior for a reason. Normally when - * displaying multipart/alternative you want to show the _last_ usable - * format in the message. Here we show the _first_ one, because it's - * usually text/plain. Since this set of functions is designed for text - * output to non-MIME-aware clients, this is the desired behavior. - * - */ +// Pre callback function for multipart/alternative +// +// NOTE: this differs from the standard behavior for a reason. Normally when +// displaying multipart/alternative you want to show the _last_ usable +// format in the message. Here we show the _first_ one, because it's +// usually text/plain. Since this set of functions is designed for text +// output to non-MIME-aware clients, this is the desired behavior. +// void fixed_output_pre(char *name, char *filename, char *partnum, char *disp, void *content, char *cbtype, char *cbcharset, size_t length, char *encoding, char *cbid, void *cbuserdata) @@ -1242,9 +1201,10 @@ void fixed_output_pre(char *name, char *filename, char *partnum, char *disp, } } -/* - * Post callback function for multipart/alternative - */ + +// +// Post callback function for multipart/alternative +// void fixed_output_post(char *name, char *filename, char *partnum, char *disp, void *content, char *cbtype, char *cbcharset, size_t length, char *encoding, char *cbid, void *cbuserdata) @@ -1262,9 +1222,9 @@ void fixed_output_post(char *name, char *filename, char *partnum, char *disp, } } -/* - * Inline callback function for mime parser that wants to display text - */ + +// Inline callback function for mime parser that wants to display text +// void fixed_output(char *name, char *filename, char *partnum, char *disp, void *content, char *cbtype, char *cbcharset, size_t length, char *encoding, char *cbid, void *cbuserdata) @@ -1281,10 +1241,9 @@ void fixed_output(char *name, char *filename, char *partnum, char *disp, partnum, filename, cbtype, (long)length ); - /* - * If we're in the middle of a multipart/alternative scope and - * we've already printed another section, skip this one. - */ + // If we're in the middle of a multipart/alternative scope and + // we've already printed another section, skip this one. + // if ( (ma->is_ma) && (ma->did_print) ) { syslog(LOG_DEBUG, "msgbase: skipping part %s (%s)", partnum, cbtype); return; @@ -1304,7 +1263,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')) { @@ -1315,8 +1274,7 @@ void fixed_output(char *name, char *filename, char *partnum, char *disp, } if (ma->use_fo_hooks) { - if (PerformFixedOutputHooks(cbtype, content, length)) { - /* above function returns nonzero if it handled the part */ + if (PerformFixedOutputHooks(cbtype, content, length)) { // returns nonzero if it handled the part return; } } @@ -1328,17 +1286,17 @@ 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 - * we're going to send. - * - * We use a system of weights. When we find a part that matches one of the - * MIME types we've declared as preferential, we can store it in ma->chosen_part - * and then set ma->chosen_pref to that MIME type's position in our preference - * list. If we then hit another match, we only replace the first match if - * the preference value is lower. - */ + +// The client is elegant and sophisticated and wants to be choosy about +// MIME content types, so figure out which multipart/alternative part +// we're going to send. +// +// We use a system of weights. When we find a part that matches one of the +// MIME types we've declared as preferential, we can store it in ma->chosen_part +// and then set ma->chosen_pref to that MIME type's position in our preference +// list. If we then hit another match, we only replace the first match if +// the preference value is lower. +// void choose_preferred(char *name, char *filename, char *partnum, char *disp, void *content, char *cbtype, char *cbcharset, size_t length, char *encoding, char *cbid, void *cbuserdata) @@ -1349,11 +1307,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,9 +1319,9 @@ void choose_preferred(char *name, char *filename, char *partnum, char *disp, } } -/* - * Now that we've chosen our preferred part, output it. - */ + +// Now that we've chosen our preferred part, output it. +// void output_preferred(char *name, char *filename, char *partnum, @@ -1392,12 +1345,11 @@ void output_preferred(char *name, ma = (struct ma_info *)cbuserdata; - /* This is not the MIME part you're looking for... */ + // This is not the MIME part you're looking for... if (strcasecmp(partnum, ma->chosen_part)) return; - /* If the content-type of this part is in our preferred formats - * list, we can simply output it verbatim. - */ + // If the content-type of this part is in our preferred formats + // list, we can simply output it verbatim. for (i=0; ipreferred_formats, '|'); ++i) { extract_token(buf, CC->preferred_formats, i, '|', sizeof buf); if (!strcasecmp(buf, cbtype)) { @@ -1409,7 +1361,7 @@ void output_preferred(char *name, &decoded, &bytes_decoded); if (rc < 0) - break; /* Give us the chance, maybe theres another one. */ + break; // Give us the chance, maybe theres another one. if (rc == 0) text_content = (char *)content; else { @@ -1445,7 +1397,7 @@ void output_preferred(char *name, } } - /* No translations required or possible: output as text/plain */ + // No translations required or possible: output as text/plain cprintf("Content-type: text/plain\n\n"); rc = 0; if (ma->dont_decode == 0) @@ -1455,7 +1407,7 @@ void output_preferred(char *name, &decoded, &bytes_decoded); if (rc < 0) - return; /* Give us the chance, maybe theres another one. */ + return; // Give us the chance, maybe theres another one. if (rc == 0) text_content = (char *)content; else { @@ -1463,8 +1415,7 @@ void output_preferred(char *name, length = bytes_decoded; } - fixed_output(name, filename, partnum, disp, text_content, cbtype, cbcharset, - length, encoding, cbid, cbuserdata); + fixed_output(name, filename, partnum, disp, text_content, cbtype, cbcharset, length, encoding, cbid, cbuserdata); if (decoded != NULL) free(decoded); } @@ -1476,9 +1427,7 @@ struct encapmsg { }; -/* - * Callback function for - */ +// Callback function void extract_encapsulated_message(char *name, char *filename, char *partnum, char *disp, void *content, char *cbtype, char *cbcharset, size_t length, char *encoding, char *cbid, void *cbuserdata) @@ -1487,7 +1436,7 @@ void extract_encapsulated_message(char *name, char *filename, char *partnum, cha encap = (struct encapmsg *)cbuserdata; - /* Only proceed if this is the desired section... */ + // Only proceed if this is the desired section... if (!strcasecmp(encap->desired_section, partnum)) { encap->msglen = length; encap->msg = malloc(length + 2); @@ -1497,20 +1446,17 @@ void extract_encapsulated_message(char *name, char *filename, char *partnum, cha } -/* - * Determine whether the specified message exists in the cached_msglist - * (This is a security check) - */ +// Determine whether the specified message exists in the cached_msglist +// (This is a security check) int check_cached_msglist(long msgnum) { - /* cases in which we skip the check */ - if (!CC) return om_ok; /* not a session */ - if (CC->client_socket <= 0) return om_ok; /* not a client session */ - if (CC->cached_msglist == NULL) return om_access_denied; /* no msglist fetched */ - if (CC->cached_num_msgs == 0) return om_access_denied; /* nothing to check */ - + // cases in which we skip the check + if (!CC) return om_ok; // not a session + if (CC->client_socket <= 0) return om_ok; // not a client session + if (CC->cached_msglist == NULL) return om_access_denied; // no msglist fetched + if (CC->cached_num_msgs == 0) return om_access_denied; // nothing to check - /* Do a binary search within the cached_msglist for the requested msgnum */ + // Do a binary search within the cached_msglist for the requested msgnum int min = 0; int max = (CC->cached_num_msgs - 1); @@ -1531,18 +1477,14 @@ int check_cached_msglist(long msgnum) { } - -/* - * Get a message off disk. (returns om_* values found in msgbase.h) - * - */ -int CtdlOutputMsg(long msg_num, /* message number (local) to fetch */ - int mode, /* how would you like that message? */ - int headers_only, /* eschew the message body? */ - int do_proto, /* do Citadel protocol responses? */ - int crlf, /* Use CRLF newlines instead of LF? */ - char *section, /* NULL or a message/rfc822 section */ - int flags, /* various flags; see msgbase.h */ +// Get a message off disk. (returns om_* values found in msgbase.h) +int CtdlOutputMsg(long msg_num, // message number (local) to fetch + int mode, // how would you like that message? + int headers_only, // eschew the message body? + int do_proto, // do Citadel protocol responses? + int crlf, // Use CRLF newlines instead of LF? + char *section, // NULL or a message/rfc822 section + int flags, // various flags; see msgbase.h char **Author, char **Address, char **MessageID @@ -1599,10 +1541,10 @@ int CtdlOutputMsg(long msg_num, /* message number (local) to fetch */ * request that we don't even bother loading the body into memory. */ if (headers_only == HEADERS_FAST) { - TheMessage = CtdlFetchMessage(msg_num, 0, 1); + TheMessage = CtdlFetchMessage(msg_num, 0); } else { - TheMessage = CtdlFetchMessage(msg_num, 1, 1); + TheMessage = CtdlFetchMessage(msg_num, 1); } if (TheMessage == NULL) { @@ -1688,13 +1630,8 @@ int CtdlOutputMsg(long msg_num, /* message number (local) to fetch */ } - -void OutputCtdlMsgHeaders( - struct CtdlMessage *TheMessage, - int do_proto) /* do Citadel protocol responses? */ -{ +void OutputCtdlMsgHeaders(struct CtdlMessage *TheMessage, int do_proto) { int i; - int suppress_f = 0; char buf[SIZ]; char display_name[256]; @@ -1721,52 +1658,44 @@ 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; Field = FieldOrder[i]; if (Field != eMesageText) { - if ( (!CM_IsEmpty(TheMessage, Field)) - && (msgkeys[Field] != NULL) ) { - if ((Field == eenVelopeTo) || - (Field == eRecipient) || - (Field == eCarbonCopY)) { + if ( (!CM_IsEmpty(TheMessage, Field)) && (msgkeys[Field] != NULL) ) { + if ((Field == eenVelopeTo) || (Field == eRecipient) || (Field == eCarbonCopY)) { sanitize_truncated_recipient(TheMessage->cm_fields[Field]); } if (Field == eAuthor) { - if (do_proto) cprintf("%s=%s\n", - msgkeys[Field], - display_name); - } - else if ((Field == erFc822Addr) && (suppress_f)) { - /* do nothing */ + if (do_proto) { + cprintf("%s=%s\n", msgkeys[Field], display_name); + } } /* 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]); + } + } + /* Give the client a hint about whether the message originated locally */ + if (Field == erFc822Addr) { + if (IsDirectory(TheMessage->cm_fields[Field] ,0)) { + cprintf("locl=yes\n"); // message originated locally. + } + + + } } } } - } + 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 +1746,18 @@ 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 +1767,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 +1792,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 +1819,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 +1832,6 @@ void Dump_RFC822HeadersBody( mptr = TheMessage->cm_fields[eMesageText]; - prev_ch = '\0'; while (*mptr != '\0') { if (*mptr == '\r') { @@ -1942,7 +1855,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 +1866,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 +1891,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 +1933,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 +1957,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) */ @@ -2076,11 +1983,11 @@ int CtdlOutputPreLoadedMsg( * using functions that are bounds-checked, and therefore we can * make them substantially smaller than SIZ. */ - char suser[100]; - char luser[100]; - char fuser[100]; - char snode[100]; - char mid[100]; + char suser[1024]; + char luser[1024]; + char fuser[1024]; + char snode[1024]; + char mid[1024]; syslog(LOG_DEBUG, "msgbase: CtdlOutputPreLoadedMsg(TheMessage=%s, %d, %d, %d, %d", ((TheMessage == NULL) ? "NULL" : "not null"), @@ -2164,7 +2071,7 @@ int CtdlOutputPreLoadedMsg( /* Tell the client which format type we're using. */ if ( (mode == MT_CITADEL) && (do_proto) ) { - cprintf("type=%d\n", TheMessage->cm_format_type); + cprintf("type=%d\n", TheMessage->cm_format_type); // Tell the client which format type we're using. } /* nhdr=yes means that we're only displaying headers, no body */ @@ -2175,15 +2082,15 @@ int CtdlOutputPreLoadedMsg( cprintf("nhdr=yes\n"); } - if ((mode == MT_CITADEL) || (mode == MT_MIME)) + if ((mode == MT_CITADEL) || (mode == MT_MIME)) { OutputCtdlMsgHeaders(TheMessage, do_proto); - + } /* begin header processing loop for RFC822 transfer format */ strcpy(suser, ""); strcpy(luser, ""); strcpy(fuser, ""); - memcpy(snode, CtdlGetConfigStr("c_nodename"), strlen(CtdlGetConfigStr("c_nodename")) + 1); + strcpy(snode, ""); if (mode == MT_RFC822) OutputRFC822MsgHeaders( TheMessage, @@ -2203,12 +2110,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); } @@ -2441,7 +2344,7 @@ int CtdlSaveMsgPointersInRoom(char *roomname, long newmsgidlist[], int num_newms msg = supplied_msg; } else { - msg = CtdlFetchMessage(msgid, 0, 1); + msg = CtdlFetchMessage(msgid, 0); } if (msg != NULL) { @@ -2466,7 +2369,10 @@ int CtdlSaveMsgPointersInRoom(char *roomname, long newmsgidlist[], int num_newms } /* Submit this room for processing by hooks */ - PerformRoomHooks(&CC->room); + int total_roomhook_errors = PerformRoomHooks(&CC->room); + if (total_roomhook_errors) { + syslog(LOG_WARNING, "msgbase: room hooks returned %d errors", total_roomhook_errors); + } /* Go back to the room we were in before we wandered here... */ CtdlGetRoom(&CC->room, hold_rm); @@ -2497,8 +2403,6 @@ int CtdlSaveMsgPointerInRoom(char *roomname, long msgid, } - - /* * Message base operation to save a new message to the message store * (returns new message number) @@ -2518,8 +2422,7 @@ long CtdlSaveThisMessage(struct CtdlMessage *msg, long msgid, int Reply) { * 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, eMesageText) && msg->cm_lengths[eMesageText] > BIGMSG) { is_bigmsg = 1; holdM = msg->cm_fields[eMesageText]; msg->cm_fields[eMesageText] = NULL; @@ -2549,8 +2452,7 @@ long CtdlSaveThisMessage(struct CtdlMessage *msg, long msgid, int Reply) { } /* Write our little bundle of joy into the message base */ - retval = cdb_store(CDB_MSGMAIN, &msgid, (int)sizeof(long), - smr.ser, smr.len); + retval = cdb_store(CDB_MSGMAIN, &msgid, (int)sizeof(long), smr.ser, smr.len); if (retval < 0) { syslog(LOG_ERR, "msgbase: can't store message %ld: %ld", msgid, retval); } @@ -2574,6 +2476,7 @@ long CtdlSaveThisMessage(struct CtdlMessage *msg, long msgid, int Reply) { return(retval); } + long send_message(struct CtdlMessage *msg) { long newmsgid; long retval; @@ -2607,9 +2510,8 @@ long send_message(struct CtdlMessage *msg) { } - /* - * Serialize a struct CtdlMessage into the format used on disk and network. + * Serialize a struct CtdlMessage into the format used on disk. * * This function loads up a "struct ser_ret" (defined in server.h) which * contains the length of the serialized message and a pointer to the @@ -2649,9 +2551,8 @@ void CtdlSerializeMessage(struct ser_ret *ret, /* return values */ ret->ser[2] = msg->cm_format_type; wlen = 3; - for (i=0; i < NDiskFields; ++i) - if (msg->cm_fields[FieldOrder[i]] != NULL) - { + for (i=0; i < NDiskFields; ++i) { + if (msg->cm_fields[FieldOrder[i]] != NULL) { ret->ser[wlen++] = (char)FieldOrder[i]; memcpy(&ret->ser[wlen], @@ -2660,6 +2561,7 @@ void CtdlSerializeMessage(struct ser_ret *ret, /* return values */ 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); @@ -2695,16 +2597,13 @@ void ReplicationChecks(struct CtdlMessage *msg) { } - /* * Save a message to disk and submit it into the delivery system. */ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ - recptypes *recps, /* recipients (if mail) */ - const char *force, /* force a particular room? */ - int flags /* should the message be exported clean? */ - ) -{ + struct recptypes *recps, /* recipients (if mail) */ + const char *force /* force a particular room? */ +) { char hold_rm[ROOMNAMELEN]; char actual_rm[ROOMNAMELEN]; char force_room[ROOMNAMELEN]; @@ -2821,7 +2720,7 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ * If this message has no O (room) field, generate one. */ if (CM_IsEmpty(msg, eOriginalRoom) && !IsEmptyStr(CC->room.QRname)) { - CM_SetField(msg, eOriginalRoom, CC->room.QRname, strlen(CC->room.QRname)); + CM_SetField(msg, eOriginalRoom, CC->room.QRname, -1); } /* Perform "before save" hooks (aborting if any return nonzero) */ @@ -2849,8 +2748,7 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ memset(&smi, 0, sizeof(struct MetaData)); smi.meta_msgnum = newmsgid; smi.meta_refcount = 0; - safestrncpy(smi.meta_content_type, content_type, - sizeof smi.meta_content_type); + safestrncpy(smi.meta_content_type, content_type, sizeof smi.meta_content_type); /* * Measure how big this message will be when rendered as RFC822. @@ -2883,7 +2781,7 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ */ if ((!CC->internal_pgm) || (recps == NULL)) { if (CtdlSaveMsgPointerInRoom(actual_rm, newmsgid, 1, msg) != 0) { - syslog(LOG_ERR, "msgbase: ERROR saving message pointer!"); + syslog(LOG_ERR, "msgbase: ERROR saving message pointer %ld in %s", newmsgid, actual_rm); CtdlSaveMsgPointerInRoom(CtdlGetConfigStr("c_aideroom"), newmsgid, 0, msg); } } @@ -2894,13 +2792,13 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ } /* If other rooms are specified, drop them there too. */ - if ((recps != NULL) && (recps->num_room > 0)) + if ((recps != NULL) && (recps->num_room > 0)) { for (i=0; irecp_room, '|'); ++i) { - extract_token(recipient, recps->recp_room, i, - '|', sizeof recipient); + extract_token(recipient, recps->recp_room, i, '|', sizeof recipient); syslog(LOG_DEBUG, "msgbase: delivering to room <%s>", recipient); CtdlSaveMsgPointerInRoom(recipient, newmsgid, 0, msg); } + } /* Bump this user's messages posted counter. */ syslog(LOG_DEBUG, "msgbase: updating user"); @@ -2909,33 +2807,29 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ CtdlPutCurrentUserLock(); /* Decide where bounces need to be delivered */ - if ((recps != NULL) && (recps->bounce_to == NULL)) - { + 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]); + else if (!IsEmptyStr(msg->cm_fields[eAuthor])){ + strcpy(bounce_to, msg->cm_fields[eAuthor]); } recps->bounce_to = bounce_to; } CM_SetFieldLONG(msg, eVltMsgNum, newmsgid); - /* If this is private, local mail, make a copy in the * recipient's mailbox and bump the reference count. */ - if ((recps != NULL) && (recps->num_local > 0)) - { + if ((recps != NULL) && (recps->num_local > 0)) { char *pch; int ntokens; pch = recps->recp_local; recps->recp_local = recipient; ntokens = num_tokens(pch, '|'); - for (i=0; i", recipient); if (CtdlGetUser(&userbuf, recipient) == 0) { @@ -2960,8 +2854,9 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ /* Go back to the room we started from */ syslog(LOG_DEBUG, "msgbase: returning to original room %s", hold_rm); - if (strcasecmp(hold_rm, CC->room.QRname)) + if (strcasecmp(hold_rm, CC->room.QRname)) { CtdlUserGoto(hold_rm, 0, 1, NULL, NULL, NULL, NULL); + } /* * Any addresses to harvest for someone's address book? @@ -2971,10 +2866,8 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ } if (collected_addresses != NULL) { - aptr = (struct addresses_to_be_filed *) - malloc(sizeof(struct addresses_to_be_filed)); - CtdlMailboxName(actual_rm, sizeof actual_rm, - &CC->user, USERCONTACTSROOM); + aptr = (struct addresses_to_be_filed *) malloc(sizeof(struct addresses_to_be_filed)); + CtdlMailboxName(actual_rm, sizeof actual_rm, &CC->user, USERCONTACTSROOM); aptr->roomname = strdup(actual_rm); aptr->collected_addresses = collected_addresses; begin_critical_section(S_ATBF); @@ -3035,7 +2928,7 @@ long quickie_message(const char *from, const char *subject) { struct CtdlMessage *msg; - recptypes *recp = NULL; + struct recptypes *recp = NULL; msg = malloc(sizeof(struct CtdlMessage)); memset(msg, 0, sizeof(struct CtdlMessage)); @@ -3044,11 +2937,11 @@ long quickie_message(const char *from, msg->cm_format_type = format_type; if (!IsEmptyStr(from)) { - CM_SetField(msg, eAuthor, from, strlen(from)); + CM_SetField(msg, eAuthor, from, -1); } else if (!IsEmptyStr(fromaddr)) { char *pAt; - CM_SetField(msg, eAuthor, fromaddr, strlen(fromaddr)); + CM_SetField(msg, eAuthor, fromaddr, -1); pAt = strchr(msg->cm_fields[eAuthor], '@'); if (pAt != NULL) { CM_CutFieldAt(msg, eAuthor, pAt - msg->cm_fields[eAuthor]); @@ -3058,21 +2951,20 @@ long quickie_message(const char *from, msg->cm_fields[eAuthor] = strdup("Citadel"); } - 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(fromaddr)) CM_SetField(msg, erFc822Addr, fromaddr, -1); + if (!IsEmptyStr(room)) CM_SetField(msg, eOriginalRoom, room, -1); if (!IsEmptyStr(to)) { - CM_SetField(msg, eRecipient, to, strlen(to)); + CM_SetField(msg, eRecipient, to, -1); recp = validate_recipients(to, NULL, 0); } if (!IsEmptyStr(subject)) { - CM_SetField(msg, eMsgSubject, subject, strlen(subject)); + CM_SetField(msg, eMsgSubject, subject, -1); } if (!IsEmptyStr(text)) { - CM_SetField(msg, eMesageText, text, strlen(text)); + CM_SetField(msg, eMesageText, text, -1); } - long msgnum = CtdlSubmitMsg(msg, recp, room, 0); + long msgnum = CtdlSubmitMsg(msg, recp, room); CM_Free(msg); if (recp != NULL) free_recipients(recp); return msgnum; @@ -3088,8 +2980,7 @@ StrBuf *CtdlReadMessageBodyBuf(char *terminator, /* token signalling EOT */ StrBuf *exist, /* if non-null, append to it; exist is ALWAYS freed */ int crlf /* CRLF newlines instead of LF */ - ) -{ +) { StrBuf *Message; StrBuf *LineBuf; int flushing = 0; @@ -3126,13 +3017,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); } @@ -3170,6 +3057,7 @@ char *CtdlReadMessageBody(char *terminator, /* token signalling EOT */ return SmashStrBuf(&Message); } + struct CtdlMessage *CtdlMakeMessage( struct ctdluser *author, /* author's user structure */ char *recipient, /* NULL if it's not mail */ @@ -3183,8 +3071,7 @@ struct CtdlMessage *CtdlMakeMessage( char *supplied_euid, /* ...or NULL if this is irrelevant */ char *preformatted_text, /* ...or NULL to read text from client */ char *references /* Thread references */ -) -{ +) { return CtdlMakeMessageLen( author, /* author's user structure */ recipient, /* NULL if it's not mail */ @@ -3210,6 +3097,7 @@ struct CtdlMessage *CtdlMakeMessage( } + /* * Build a binary message to be saved on disk. * (NOTE: if you supply 'preformatted_text', the buffer you give it @@ -3217,7 +3105,6 @@ struct CtdlMessage *CtdlMakeMessage( * responsible for managing that memory -- it will be freed along with * the rest of the fields when CM_Free() is called.) */ - struct CtdlMessage *CtdlMakeMessageLen( struct ctdluser *author, /* author's user structure */ char *recipient, /* NULL if it's not mail */ @@ -3240,10 +3127,7 @@ struct CtdlMessage *CtdlMakeMessageLen( long textlen, char *references, /* Thread references */ long reflen - ) -{ - /* Don't confuse the poor folks if it's not routed mail. * / - char dest_node[256] = "";*/ +) { long blen; char buf[1024]; struct CtdlMessage *msg; @@ -3264,7 +3148,7 @@ struct CtdlMessage *CtdlMakeMessageLen( CM_SetField(msg, eMessagePath, my_email, myelen); } else if (!IsEmptyStr(author->fullname)) { - CM_SetField(msg, eMessagePath, author->fullname, strlen(author->fullname)); + CM_SetField(msg, eMessagePath, author->fullname, -1); } convert_spaces_to_underscores(msg->cm_fields[eMessagePath]); @@ -3283,16 +3167,13 @@ struct CtdlMessage *CtdlMakeMessageLen( if (!!IsEmptyStr(CC->room.QRname)) { if (CC->room.QRflags & QR_MAILBOX) { /* room */ - CM_SetField(msg, eOriginalRoom, &CC->room.QRname[11], strlen(&CC->room.QRname[11])); + CM_SetField(msg, eOriginalRoom, &CC->room.QRname[11], -1); } else { - CM_SetField(msg, eOriginalRoom, CC->room.QRname, strlen(CC->room.QRname)); + CM_SetField(msg, eOriginalRoom, CC->room.QRname, -1); } } - 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); } @@ -3304,7 +3185,7 @@ struct CtdlMessage *CtdlMakeMessageLen( CM_SetField(msg, erFc822Addr, my_email, myelen); } else if ( (author == &CC->user) && (!IsEmptyStr(CC->cs_inet_email)) ) { - CM_SetField(msg, erFc822Addr, CC->cs_inet_email, strlen(CC->cs_inet_email)); + CM_SetField(msg, erFc822Addr, CC->cs_inet_email, -1); } if (subject != NULL) { @@ -3353,18 +3234,15 @@ struct CtdlMessage *CtdlMakeMessageLen( } - - /* * API function to delete messages which match a set of criteria * (returns the actual number of messages deleted) */ -int CtdlDeleteMessages(const char *room_name, /* which room */ - long *dmsgnums, /* array of msg numbers to be deleted */ - int num_dmsgnums, /* number of msgs to be deleted, or 0 for "any" */ - char *content_type /* or "" for any. regular expressions expected. */ - ) -{ +int CtdlDeleteMessages(const char *room_name, // which room + long *dmsgnums, // array of msg numbers to be deleted + int num_dmsgnums, // number of msgs to be deleted, or 0 for "any" + char *content_type // or "" for any. regular expressions expected. +) { struct ctdlroom qrbuf; struct cdbdata *cdbfr; long *msglist = NULL; @@ -3500,14 +3378,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 +3395,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 +3418,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; - } - 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. - */ -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); + AdjRefCount(msgnum[i], incr); } - - 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. + * AdjRefCount - adjust the reference count for a message. We need to delete from disk any message whose reference count reaches zero. */ -void TDAP_AdjRefCount(long msgnum, int incr) +void AdjRefCount(long msgnum, int incr) { - struct MetaData smi; long delnum; @@ -3723,12 +3453,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 +3472,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,14 +3483,13 @@ 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; char roomname[ROOMNAMELEN]; struct CtdlMessage *msg; @@ -3809,19 +3535,15 @@ 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; - 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"))); + CM_SetField(msg, eAuthor, CC->user.fullname, -1); + CM_SetField(msg, eOriginalRoom, req_room, -1); 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. @@ -3832,15 +3554,14 @@ void CtdlWriteObject(char *req_room, /* Room to stuff it in */ ); } /* Now write the data */ - CtdlSubmitMsg(msg, NULL, roomname, 0); + CtdlSubmitMsg(msg, NULL, roomname); CM_Free(msg); } - -/*****************************************************************************/ -/* MODULE INITIALIZATION STUFF */ -/*****************************************************************************/ +/************************************************************************/ +/* MODULE INITIALIZATION */ +/************************************************************************/ CTDL_MODULE_INIT(msgbase) { @@ -3848,6 +3569,6 @@ CTDL_MODULE_INIT(msgbase) FillMsgKeyLookupTable(); } - /* return our Subversion id for the Log */ + /* return our module id for the log */ return "msgbase"; }