// Implements the message store.
//
-// Copyright (c) 1987-2023 by the citadel.org team
+// Copyright (c) 1987-2024 by the citadel.org team
//
-// This program is open source software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License version 3.
+// This program is open source software. Use, duplication, or disclosure
+// is subject to the terms of the GNU General Public License version 3.
#include <stdlib.h>
#include <unistd.h>
"jrnl", // J -> eJournal
"rep2", // K -> eReplyTo
"list", // L -> eListID
- "text", // M -> eMesageText
+ "text", // M -> eMessageText
NULL, // N (formerly used as eNodename)
"room", // O -> eOriginalRoom
"path", // P -> eMessagePath
eMsgField FieldOrder[] = {
-/* Important fields */
+// Important fields
emessageId ,
eMessagePath ,
eTimestamp ,
erFc822Addr ,
eOriginalRoom,
eRecipient ,
-/* Semi-important fields */
+// Semi-important fields
eBig_message ,
eExclusiveID ,
eWeferences ,
eJournal ,
-/* G is not used yet */
+// G is not used yet
eReplyTo ,
eListID ,
-/* Q is not used yet */
+// Q is not used yet
eenVelopeTo ,
-/* X is not used yet */
-/* Z is not used yet */
+// X is not used yet
+// Z is not used yet
eCarbonCopY ,
eMsgSubject ,
-/* internal only */
+// internal only
eErrorMsg ,
eSuppressIdx ,
eExtnotify ,
-/* Message text (MUST be last) */
- eMesageText
-/* Not saved to disk:
- eVltMsgNum
-*/
+// Message text (MUST be last)
+ eMessageText
+// Not saved to disk:
+// eVltMsgNum
+//
};
static const long NDiskFields = sizeof(FieldOrder) / sizeof(eMsgField);
}
}
- /* If a search string was specified, get a message list from
- * the full text index and remove messages which aren't on both
- * lists.
- *
- * How this works:
- * Since the lists are sorted and strictly ascending, and the
- * output list is guaranteed to be shorter than or equal to the
- * input list, we overwrite the bottom of the input list. This
- * eliminates the need to memmove big chunks of the list over and
- * over again.
- */
+ // If a search string was specified, get a message list from
+ // the full text index and remove messages which aren't on both
+ // lists.
+ //
+ // How this works:
+ // Since the lists are sorted and strictly ascending, and the
+ // output list is guaranteed to be shorter than or equal to the
+ // input list, we overwrite the bottom of the input list. This
+ // eliminates the need to memmove big chunks of the list over and
+ // over again.
if ( (num_msgs > 0) && (mode == MSGS_SEARCH) && (search_string) ) {
- /* Call search module via hook mechanism.
- * NULL means use any search function available.
- * otherwise replace with a char * to name of search routine
- */
+ // Call search module via hook mechanism.
+ // NULL means use any search function available.
+ // otherwise replace with a char * to name of search routine
search = CtdlFullTextSearch(search_string);
if (array_len(search) > 0) {
}
}
else {
- num_msgs = 0; /* No messages qualify */
+ num_msgs = 0; // No messages qualify
}
if (search != NULL) array_free(search);
- /* Now that we've purged messages which don't contain the search
- * string, treat a MSGS_SEARCH just like a MSGS_ALL from this
- * point on.
- */
+ // Now that we've purged messages which don't contain the search
+ // string, treat a MSGS_SEARCH just like a MSGS_ALL from this
+ // point on.
mode = MSGS_ALL;
}
- /*
- * Now iterate through the message list, according to the
- * criteria supplied by the caller.
- */
+ // Now iterate through the message list, according to the
+ // criteria supplied by the caller.
if (num_msgs > 0)
for (a = 0; a < num_msgs; ++a) {
if (server_shutting_down) {
}
if (need_to_free_re) regfree(&re);
- /*
- * We cache the most recent msglist in order to do security checks later
- */
+ // We cache the most recent msglist in order to do security checks later
if (CC->client_socket > 0) {
if (CC->cached_msglist != NULL) {
free(CC->cached_msglist);
}
-/*
- * memfmout() - Citadel text formatter and paginator.
- * Although the original purpose of this routine was to format
- * text to the reader's screen width, all we're really using it
- * for here is to format text out to 80 columns before sending it
- * to the client. The client software may reformat it again.
- */
+// memfmout() - Citadel text formatter and paginator.
+// Although the original purpose of this routine was to format
+// text to the reader's screen width, all we're really using it
+// for here is to format text out to 80 columns before sending it
+// to the client. The client software MAY reformat it again.
void memfmout(
- char *mptr, /* where are we going to get our text from? */
- const char *nl /* string to terminate lines with */
+ char *mptr, // where are we going to get our text from?
+ const char *nl // string to terminate lines with
) {
int column = 0;
unsigned char ch = 0;
column = 0;
}
else if (ch == '\r') {
- /* Ignore carriage returns. Newlines are always LF or CRLF but never CR. */
+ // Ignore carriage returns. Newlines are always LF or CRLF but never CR.
}
else if (isspace(ch)) {
- if (column > 72) { /* Beyond 72 columns, break on the next space */
+ if (column > 72) { // Beyond 72 columns, break on the next space
if (client_write(outbuf, len) == -1) {
syslog(LOG_ERR, "msgbase: memfmout() aborting due to write failure");
return;
else {
outbuf[len++] = ch;
++column;
- if (column > 1000) { /* Beyond 1000 columns, break anywhere */
+ if (column > 1000) { // Beyond 1000 columns, break anywhere
if (client_write(outbuf, len) == -1) {
syslog(LOG_ERR, "msgbase: memfmout() aborting due to write failure");
return;
}
-/*
- * Callback function for mime parser that simply lists the part
- */
+// Callback function for mime parser that simply lists the part
void list_this_part(char *name, char *filename, char *partnum, char *disp,
void *content, char *cbtype, char *cbcharset, size_t length, char *encoding,
char *cbid, void *cbuserdata)
}
-/*
- * Callback function for multipart prefix
- */
+// Callback function for multipart prefix
void list_this_pref(char *name, char *filename, char *partnum, char *disp,
void *content, char *cbtype, char *cbcharset, size_t length, char *encoding,
char *cbid, void *cbuserdata)
}
-/*
- * Callback function for multipart sufffix
- */
+// Callback function for multipart sufffix
void list_this_suff(char *name, char *filename, char *partnum, char *disp,
void *content, char *cbtype, char *cbcharset, size_t length, char *encoding,
char *cbid, void *cbuserdata)
}
-/*
- * Callback function for mime parser that opens a section for downloading
- * we use serv_files function here:
- */
+// Callback function for mime parser that opens a section for downloading
+// we use serv_files function here:
extern void OpenCmdResult(char *filename, const char *mime_type);
void mime_download(char *name, char *filename, char *partnum, char *disp,
void *content, char *cbtype, char *cbcharset, size_t length,
{
int rv = 0;
- /* Silently go away if there's already a download open. */
+ // Silently go away if there's already a download open.
if (CC->download_fp != NULL)
return;
}
-/*
- * Callback function for mime parser that outputs a section all at once.
- * We can specify the desired section by part number *or* content-id.
- */
+// Callback function for mime parser that outputs a section all at once.
+// We can specify the desired section by part number *or* content-id.
void mime_spew_section(char *name, char *filename, char *partnum, char *disp,
void *content, char *cbtype, char *cbcharset, size_t length,
char *encoding, char *cbid, void *cbuserdata)
// so go ahead and fetch that. Failing that, just set a dummy
// body so other code doesn't barf.
//
- if ( (CM_IsEmpty(ret, eMesageText)) && (with_body) ) {
+ if ( (CM_IsEmpty(ret, eMessageText)) && (with_body) ) {
dmsgtext = cdb_fetch(CDB_BIGMSGS, &msgnum, sizeof(long));
if (dmsgtext.ptr != NULL) {
- CM_SetField(ret, eMesageText, dmsgtext.ptr);
+ CM_SetField(ret, eMessageText, dmsgtext.ptr);
}
}
- if (CM_IsEmpty(ret, eMesageText)) {
- CM_SetField(ret, eMesageText, "\r\n\r\n (no text)\r\n");
+ if (CM_IsEmpty(ret, eMessageText)) {
+ CM_SetField(ret, eMessageText, "\r\n\r\n (no text)\r\n");
}
return (ret);
for (i=0; i<num_tokens(CC->preferred_formats, '|'); ++i) {
extract_token(buf, CC->preferred_formats, i, '|', sizeof buf);
if (!strcasecmp(buf, cbtype)) {
- /* Yeah! Go! W00t!! */
+ // Yeah! Go! W00t!!
if (ma->dont_decode == 0)
rc = mime_decode_now (content,
length,
if (section) if (!IsEmptyStr(section)) if (strcmp(section, "0")) {
memset(&encap, 0, sizeof encap);
safestrncpy(encap.desired_section, section, sizeof encap.desired_section);
- mime_parser(CM_RANGE(TheMessage, eMesageText),
+ mime_parser(CM_RANGE(TheMessage, eMessageText),
*extract_encapsulated_message,
NULL, NULL, (void *)&encap, 0
);
char buf[SIZ];
char display_name[256];
- /* begin header processing loop for Citadel message format */
+ // begin header processing loop for Citadel message format
safestrncpy(display_name, "<unknown>", sizeof display_name);
if (!CM_IsEmpty(TheMessage, eAuthor)) {
strcpy(buf, TheMessage->cm_fields[eAuthor]);
}
}
- /* Now spew the header fields in the order we like them. */
+ // 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 (Field != eMessageText) {
if ( (!CM_IsEmpty(TheMessage, Field)) && (msgkeys[Field] != NULL) ) {
if ((Field == eenVelopeTo) || (Field == eRecipient) || (Field == eCarbonCopY)) {
sanitize_truncated_recipient(TheMessage->cm_fields[Field]);
cprintf("%s=%s\n", msgkeys[Field], display_name);
}
}
- /* Masquerade display name if needed */
+ // Masquerade display name if needed
else {
if (do_proto) {
cprintf("%s=%s\n", msgkeys[Field], TheMessage->cm_fields[Field]);
}
}
- /* Give the client a hint about whether the message originated locally */
+ // 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 message 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,
case eExclusiveID:
case eJournal:
- case eMesageText:
+ case eMessageText:
case eBig_message:
case eOriginalRoom:
case eErrorMsg:
case eSuppressIdx:
case eExtnotify:
case eVltMsgNum:
- /* these don't map to mime message headers. */
+ // these don't map to mime message headers.
break;
}
if (mptr != mpptr) {
void Dump_RFC822HeadersBody(
struct CtdlMessage *TheMessage,
- int headers_only, /* eschew the message body? */
- int flags, /* should the bessage be exported clean? */
+ 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;
char *mptr;
int lfSent = 0;
- mptr = TheMessage->cm_fields[eMesageText];
+ mptr = TheMessage->cm_fields[eMessageText];
prev_ch = '\0';
while (*mptr != '\0') {
if (*mptr == '\r') {
- /* do nothing */
+ // do nothing
}
else {
if ((!eoh) &&
}
-/* 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.
- */
+// 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.
void DumpFormatFixed(
struct CtdlMessage *TheMessage,
- int mode, /* how would you like that message? */
+ int mode, // how would you like that message?
const char *nl, int nllen)
{
cit_uint8_t ch;
int xlline = 0;
char *mptr;
- mptr = TheMessage->cm_fields[eMesageText];
+ mptr = TheMessage->cm_fields[eMessageText];
if (mode == MT_MIME) {
cprintf("Content-type: text/plain\n\n");
}
}
- /* if we reach the outer bounds of our buffer, abort without respect for what we purge. */
+ // 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';
}
}
else {
// Parse the message text component
- mime_parser(CM_RANGE(TheMessage, eMesageText), *mime_download, NULL, NULL, NULL, 0);
+ mime_parser(CM_RANGE(TheMessage, eMessageText), *mime_download, NULL, NULL, NULL, 0);
// If there's no file open by this time, the requested * section wasn't found, so print an error
if (CC->download_fp == NULL) {
else {
// Locate and parse the component specified by the caller
int found_it = 0;
- mime_parser(CM_RANGE(TheMessage, eMesageText), *mime_spew_section, NULL, NULL, (void *)&found_it, 0);
+ mime_parser(CM_RANGE(TheMessage, eMessageText), *mime_spew_section, NULL, NULL, (void *)&found_it, 0);
// If section wasn't found, print an error
if (!found_it) {
if (TheMessage->cm_format_type == FMT_RFC822) {
if ( (mode == MT_CITADEL) || (mode == MT_MIME) ) {
memset(&ma, 0, sizeof(struct ma_info));
- mime_parser(CM_RANGE(TheMessage, eMesageText),
+ mime_parser(CM_RANGE(TheMessage, eMessageText),
(do_proto ? *list_this_part : NULL),
(do_proto ? *list_this_pref : NULL),
(do_proto ? *list_this_suff : NULL),
if (mode == MT_MIME) {
cprintf("Content-type: text/x-citadel-variformat\n\n");
}
- memfmout(TheMessage->cm_fields[eMesageText], nl);
+ memfmout(TheMessage->cm_fields[eMessageText], nl);
}
// If the message on disk is format 4 (MIME), we've gotta hand it
strcpy(ma.chosen_part, "1");
ma.chosen_pref = 9999;
ma.dont_decode = CC->msg4_dont_decode;
- mime_parser(CM_RANGE(TheMessage, eMesageText),
+ mime_parser(CM_RANGE(TheMessage, eMessageText),
*choose_preferred, *fixed_output_pre,
*fixed_output_post, (void *)&ma, 1);
- mime_parser(CM_RANGE(TheMessage, eMesageText),
+ mime_parser(CM_RANGE(TheMessage, eMessageText),
*output_preferred, NULL, NULL, (void *)&ma, 1);
}
else {
ma.use_fo_hooks = 1;
- mime_parser(CM_RANGE(TheMessage, eMesageText),
+ mime_parser(CM_RANGE(TheMessage, eMessageText),
*fixed_output, *fixed_output_pre,
*fixed_output_post, (void *)&ma, 0);
}
long holdMLen = 0;
// If the message is big, set its body aside for storage elsewhere and we hide the message body from the serializer
- if (!CM_IsEmpty(msg, eMesageText) && msg->cm_lengths[eMesageText] > BIGMSG) {
+ if (!CM_IsEmpty(msg, eMessageText) && msg->cm_lengths[eMessageText] > BIGMSG) {
is_bigmsg = 1;
- holdM = msg->cm_fields[eMesageText];
- msg->cm_fields[eMesageText] = NULL;
- holdMLen = msg->cm_lengths[eMesageText];
- msg->cm_lengths[eMesageText] = 0;
+ holdM = msg->cm_fields[eMessageText];
+ msg->cm_fields[eMessageText] = NULL;
+ holdMLen = msg->cm_lengths[eMessageText];
+ msg->cm_lengths[eMessageText] = 0;
}
// Serialize our data structure for storage in the database
if (is_bigmsg) {
// put the message body back into the message
- msg->cm_fields[eMesageText] = holdM;
- msg->cm_lengths[eMesageText] = holdMLen;
+ msg->cm_fields[eMessageText] = holdM;
+ msg->cm_lengths[eMessageText] = holdMLen;
}
if (smr.len == 0) {
}
-/*
- * Check to see if any messages already exist in the current room which
- * carry the same Exclusive ID as this one. If any are found, delete them.
- */
+// Check to see if any messages already exist in the current room which
+// carry the same Exclusive ID as this one. If any are found, delete them.
void ReplicationChecks(struct CtdlMessage *msg) {
long old_msgnum = (-1L);
syslog(LOG_DEBUG, "msgbase: performing replication checks in <%s>", CC->room.QRname);
- /* No exclusive id? Don't do anything. */
+ // No exclusive id? Don't do anything.
if (msg == NULL) return;
if (CM_IsEmpty(msg, eExclusiveID)) return;
- /*syslog(LOG_DEBUG, "msgbase: exclusive ID: <%s> for room <%s>",
- msg->cm_fields[eExclusiveID], CC->room.QRname);*/
-
old_msgnum = CtdlLocateMessageByEuid(msg->cm_fields[eExclusiveID], &CC->room);
if (old_msgnum > 0L) {
syslog(LOG_DEBUG, "msgbase: ReplicationChecks() replacing message %ld", old_msgnum);
}
-/*
- * Save a message to disk and submit it into the delivery system.
- */
-long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */
- struct recptypes *recps, /* recipients (if mail) */
- const char *force /* force a particular room? */
+// Save a message to disk and submit it into the delivery system.
+long CtdlSubmitMsg(struct CtdlMessage *msg, // message to save
+ 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];
- char content_type[SIZ]; /* We have to learn this */
+ char content_type[SIZ]; // We have to learn this
char recipient[SIZ];
char bounce_to[1024];
const char *room;
int qualified_for_journaling = 0;
syslog(LOG_DEBUG, "msgbase: CtdlSubmitMsg() called");
- if (CM_IsValidMsg(msg) == 0) return(-1); /* self check */
+ if (CM_IsValidMsg(msg) == 0) return(-1); // self check
- /* If this message has no timestamp, we take the liberty of
- * giving it one, right now.
- */
+ // If this message has no timestamp, we take the liberty of giving it one, right now.
if (CM_IsEmpty(msg, eTimestamp)) {
CM_SetFieldLONG(msg, eTimestamp, time(NULL));
}
- /* If this message has no path, we generate one.
- */
+ // If this message has no path, we generate one.
if (CM_IsEmpty(msg, eMessagePath)) {
if (!CM_IsEmpty(msg, eAuthor)) {
CM_CopyField(msg, eMessagePath, eAuthor);
strcpy(force_room, force);
}
- /* Learn about what's inside, because it's what's inside that counts */
- if (CM_IsEmpty(msg, eMesageText)) {
+ // Learn about what's inside, because it's what's inside that counts
+ if (CM_IsEmpty(msg, eMessageText)) {
syslog(LOG_ERR, "msgbase: ERROR; attempt to save message with NULL body");
return(-2);
}
break;
case 4:
strcpy(content_type, "text/plain");
- mptr = bmstrcasestr(msg->cm_fields[eMesageText], "Content-type:");
+ mptr = bmstrcasestr(msg->cm_fields[eMessageText], "Content-type:");
if (mptr != NULL) {
char *aptr;
safestrncpy(content_type, &mptr[13], sizeof content_type);
}
}
- /* Goto the correct room */
+ // Goto the correct room
room = (recps) ? CC->room.QRname : SENTITEMS;
syslog(LOG_DEBUG, "msgbase: selected room %s", room);
strcpy(hold_rm, CC->room.QRname);
strcpy(actual_rm, SENTITEMS);
}
- /* If the user is a twit, move to the twit room for posting */
+ // If the user is a twit, move to the twit room for posting
if (TWITDETECT) {
if (CC->user.axlevel == AxProbU) {
strcpy(hold_rm, actual_rm);
}
}
- /* ...or if this message is destined for Aide> then go there. */
+ // ...or if this message is destined for Aide> then go there.
if (!IsEmptyStr(force_room)) {
strcpy(actual_rm, force_room);
}
CtdlUserGoto(actual_rm, 0, 1, NULL, NULL, NULL, NULL);
}
- /*
- * If this message has no O (room) field, generate one.
- */
+ // 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);
}
- /* Perform "before save" hooks (aborting if any return nonzero) */
+ // Perform "before save" hooks (aborting if any return nonzero)
syslog(LOG_DEBUG, "msgbase: performing before-save hooks");
if (PerformMessageHooks(msg, recps, EVT_BEFORESAVE) > 0) return(-3);
- /*
- * If this message has an Exclusive ID, and the room is replication
- * checking enabled, then do replication checks.
- */
+ // If this message has an Exclusive ID, and the room is replication
+ // checking enabled, then do replication checks.
if (DoesThisRoomNeedEuidIndexing(&CC->room)) {
ReplicationChecks(msg);
}
- /* Save it to disk */
+ // Save it to disk
syslog(LOG_DEBUG, "msgbase: saving to disk");
newmsgid = send_message(msg);
if (newmsgid <= 0L) return(-5);
- /* Write a supplemental message info record. This doesn't have to
- * be a critical section because nobody else knows about this message
- * yet.
- */
+ // Write a supplemental message info record. This doesn't have to be
+ // a critical section because nobody else knows about this message yet.
syslog(LOG_DEBUG, "msgbase: creating metadata record");
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);
- /*
- * Measure how big this message will be when rendered as RFC822.
- * We do this for two reasons:
- * 1. We need the RFC822 length for the new metadata record, so the
- * POP and IMAP services don't have to calculate message lengths
- * while the user is waiting (multiplied by potentially hundreds
- * or thousands of messages).
- * 2. If journaling is enabled, we will need an RFC822 version of the
- * message to attach to the journalized copy.
- */
+ // Measure how big this message will be when rendered as RFC822.
+ // We do this for two reasons:
+ // 1. We need the RFC822 length for the new metadata record, so the
+ // POP and IMAP services don't have to calculate message lengths
+ // while the user is waiting (multiplied by potentially hundreds
+ // or thousands of messages).
+ // 2. If journaling is enabled, we will need an RFC822 version of the
+ // message to attach to the journalized copy.
if (CC->redirect_buffer != NULL) {
syslog(LOG_ALERT, "msgbase: CC->redirect_buffer is not NULL during message submission!");
exit(CTDLEXIT_REDIRECT);
PutMetaData(&smi);
- /* Now figure out where to store the pointers */
+ // Now figure out where to store the pointers
syslog(LOG_DEBUG, "msgbase: storing pointers");
- /* If this is being done by the networker delivering a private
- * message, we want to BYPASS saving the sender's copy (because there
- * is no local sender; it would otherwise go to the Trashcan).
- */
+ // If this is being done by the networker delivering a private
+ // message, we want to BYPASS saving the sender's copy (because there
+ // is no local sender; it would otherwise go to the Trashcan).
if ((!CC->internal_pgm) || (recps == NULL)) {
if (CtdlSaveMsgPointerInRoom(actual_rm, newmsgid, 1, msg) != 0) {
syslog(LOG_ERR, "msgbase: ERROR saving message pointer %ld in %s", newmsgid, actual_rm);
}
}
- /* For internet mail, drop a copy in the outbound queue room */
+ // For internet mail, drop a copy in the outbound queue room
if ((recps != NULL) && (recps->num_internet > 0)) {
CtdlSaveMsgPointerInRoom(SMTP_SPOOLOUT_ROOM, newmsgid, 0, msg);
}
- /* If other rooms are specified, drop them there too. */
+ // If other rooms are specified, drop them there too.
if ((recps != NULL) && (recps->num_room > 0)) {
for (i=0; i<num_tokens(recps->recp_room, '|'); ++i) {
extract_token(recipient, recps->recp_room, i, '|', sizeof recipient);
}
}
- /* Decide where bounces need to be delivered */
+ // Decide where bounces need to be delivered
if ((recps != NULL) && (recps->bounce_to == NULL)) {
if (CC->logged_in) {
strcpy(bounce_to, CC->user.fullname);
recps->recp_local = pch;
}
- /* Perform "after save" hooks */
+ // Perform "after save" hooks
syslog(LOG_DEBUG, "msgbase: performing after-save hooks");
PerformMessageHooks(msg, recps, EVT_AFTERSAVE);
CM_FlushField(msg, eVltMsgNum);
- /* Go back to the room we started from */
+ // 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)) {
CtdlUserGoto(hold_rm, 0, 1, NULL, NULL, NULL, NULL);
}
- /*
- * Any addresses to harvest for someone's address book?
- */
+ // Any addresses to harvest for someone's address book?
if ( (CC->logged_in) && (recps != NULL) ) {
collected_addresses = harvest_collected_addresses(msg);
}
end_critical_section(S_ATBF);
}
- /*
- * Determine whether this message qualifies for journaling.
- */
+ // Determine whether this message qualifies for journaling.
if (!CM_IsEmpty(msg, eJournal)) {
qualified_for_journaling = 0;
}
}
}
- /*
- * Do we have to perform journaling? If so, hand off the saved
- * RFC822 version will be handed off to the journaler for background
- * submit. Otherwise, we have to free the memory ourselves.
- */
+ // Do we have to perform journaling? If so, hand off the saved
+ // RFC822 version will be handed off to the journaler for background
+ // submit. Otherwise, we have to free the memory ourselves.
if (saved_rfc822_version != NULL) {
if (qualified_for_journaling) {
JournalBackgroundSubmit(msg, saved_rfc822_version, recps);
if ((recps != NULL) && (recps->bounce_to == bounce_to))
recps->bounce_to = NULL;
- /* Done. */
+ // Done.
return(newmsgid);
}
-/*
- * Convenience function for generating small administrative messages.
- */
+// Convenience function for generating small administrative messages.
long quickie_message(char *from,
char *fromaddr,
char *to,
CM_SetField(msg, eMsgSubject, subject);
}
if (!IsEmptyStr(text)) {
- CM_SetField(msg, eMesageText, text);
+ CM_SetField(msg, eMessageText, text);
}
long msgnum = CtdlSubmitMsg(msg, recp, room);
}
-/*
- * Back end function used by CtdlMakeMessage() and similar functions
- */
+// Back end function used by CtdlMakeMessage() and similar functions
StrBuf *CtdlReadMessageBodyBuf(char *terminator, // token signalling EOT
long tlen,
size_t maxlen, // maximum message length
Message = NewStrBufDup(exist);
}
- /* Do we need to change leading ".." to "." for SMTP escaping? */
+ // Do we need to change leading ".." to "." for SMTP escaping?
if ((tlen == 1) && (*terminator == '.')) {
dotdot = 1;
}
- /* read in the lines of message text one by one */
+ // read in the lines of message text one by one
do {
if (CtdlClientGetLine(LineBuf) < 0) {
finished = 1;
StrBufAppendBufPlain(LineBuf, HKEY("\n"), 0);
}
- /* Unescape SMTP-style input of two dots at the beginning of the line */
+ // Unescape SMTP-style input of two dots at the beginning of the line
if ((dotdot) && (StrLength(LineBuf) > 1) && (ChrPtr(LineBuf)[0] == '.')) {
StrBufCutLeft(LineBuf, 1);
}
StrBufAppendBuf(Message, LineBuf, 0);
}
- /* if we've hit the max msg length, flush the rest */
+ // if we've hit the max msg length, flush the rest
if (StrLength(Message) >= maxlen) {
flushing = 1;
}
struct CtdlMessage *CtdlMakeMessage(
- struct ctdluser *author, /* author's user structure */
- char *recipient, /* NULL if it's not mail */
- char *recp_cc, /* NULL if it's not mail */
- char *room, /* room where it's going */
- int type, /* see MES_ types in header file */
- int format_type, /* variformat, plain text, MIME... */
- char *fake_name, /* who we're masquerading as */
- char *my_email, /* which of my email addresses to use (empty is ok) */
- char *subject, /* Subject (optional) */
- char *supplied_euid, /* ...or NULL if this is irrelevant */
- char *preformatted_text, /* ...or NULL to read text from client */
- char *references /* Thread references */
+ struct ctdluser *author, // author's user structure
+ char *recipient, // NULL if it's not mail
+ char *recp_cc, // NULL if it's not mail
+ char *room, // room where it's going
+ int type, // see MES_ types in header file
+ int format_type, // variformat, plain text, MIME...
+ char *fake_name, // who we're masquerading as
+ char *my_email, // which of my email addresses to use (empty is ok)
+ char *subject, // Subject (optional)
+ 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 */
+ author, // author's user structure
+ recipient, // NULL if it's not mail
(recipient)?strlen(recipient) : 0,
- recp_cc, /* NULL if it's not mail */
+ recp_cc, // NULL if it's not mail
(recp_cc)?strlen(recp_cc): 0,
- room, /* room where it's going */
+ room, // room where it's going
(room)?strlen(room): 0,
- type, /* see MES_ types in header file */
- format_type, /* variformat, plain text, MIME... */
- fake_name, /* who we're masquerading as */
+ type, // see MES_ types in header file
+ format_type, // variformat, plain text, MIME...
+ fake_name, // who we're masquerading as
(fake_name)?strlen(fake_name): 0,
- my_email, /* which of my email addresses to use (empty is ok) */
+ my_email, // which of my email addresses to use (empty is ok)
(my_email)?strlen(my_email): 0,
- subject, /* Subject (optional) */
+ subject, // Subject (optional)
(subject)?strlen(subject): 0,
- supplied_euid, /* ...or NULL if this is irrelevant */
+ supplied_euid, // ...or NULL if this is irrelevant
(supplied_euid)?strlen(supplied_euid):0,
- preformatted_text, /* ...or NULL to read text from client */
+ preformatted_text, // ...or NULL to read text from client
(preformatted_text)?strlen(preformatted_text) : 0,
- references, /* Thread references */
+ references, // Thread references
(references)?strlen(references):0);
}
-/*
- * Build a binary message to be saved on disk.
- * (NOTE: if you supply 'preformatted_text', the buffer you give it
- * will become part of the message. This means you are no longer
- * responsible for managing that memory -- it will be freed along with
- * the rest of the fields when CM_Free() is called.)
- */
+// Build a binary message to be saved on disk.
+// (NOTE: if you supply 'preformatted_text', the buffer you give it
+// will become part of the message. This means you are no longer
+// responsible for managing that memory -- it will be freed along with
+// the rest of the fields when CM_Free() is called.)
struct CtdlMessage *CtdlMakeMessageLen(
- struct ctdluser *author, /* author's user structure */
- char *recipient, /* NULL if it's not mail */
+ struct ctdluser *author, // author's user structure
+ char *recipient, // NULL if it's not mail
long rcplen,
- char *recp_cc, /* NULL if it's not mail */
+ char *recp_cc, // NULL if it's not mail
long cclen,
- char *room, /* room where it's going */
+ char *room, // room where it's going
long roomlen,
- int type, /* see MES_ types in header file */
- int format_type, /* variformat, plain text, MIME... */
- char *fake_name, /* who we're masquerading as */
+ int type, // see MES_ types in header file
+ int format_type, // variformat, plain text, MIME...
+ char *fake_name, // who we're masquerading as
long fnlen,
- char *my_email, /* which of my email addresses to use (empty is ok) */
+ char *my_email, // which of my email addresses to use (empty is ok)
long myelen,
- char *subject, /* Subject (optional) */
+ char *subject, // Subject (optional)
long subjlen,
- char *supplied_euid, /* ...or NULL if this is irrelevant */
+ char *supplied_euid, // ...or NULL if this is irrelevant
long euidlen,
- char *preformatted_text, /* ...or NULL to read text from client */
+ char *preformatted_text, // ...or NULL to read text from client
long textlen,
- char *references, /* Thread references */
+ char *references, // Thread references
long reflen
) {
long blen;
if (recipient != NULL) rcplen = string_trim(recipient);
if (recp_cc != NULL) cclen = string_trim(recp_cc);
- /* Path or Return-Path */
+ // Path or Return-Path
if (myelen > 0) {
CM_SetField(msg, eMessagePath, my_email);
}
FreeStrBuf(&FakeAuthor);
if (!!IsEmptyStr(CC->room.QRname)) {
- if (CC->room.QRflags & QR_MAILBOX) { /* room */
+ if (CC->room.QRflags & QR_MAILBOX) { // room
CM_SetField(msg, eOriginalRoom, &CC->room.QRname[11]);
}
else {
long IsAscii;
IsAscii = -1;
i = 0;
- while ((subject[i] != '\0') &&
- (IsAscii = isascii(subject[i]) != 0 ))
+ while ((subject[i] != '\0') && (IsAscii = isascii(subject[i]) != 0 ))
i++;
if (IsAscii != 0)
CM_SetField(msg, eMsgSubject, subject);
- else /* ok, we've got utf8 in the string. */
- {
+ else { // ok, we've got utf8 in the string.
char *rfc2047Subj;
rfc2047Subj = rfc2047encode(subject, length);
CM_SetAsField(msg, eMsgSubject, &rfc2047Subj, strlen(rfc2047Subj));
}
if (preformatted_text != NULL) {
- CM_SetField(msg, eMesageText, preformatted_text);
+ CM_SetField(msg, eMessageText, preformatted_text);
}
else {
StrBuf *MsgBody;
MsgBody = CtdlReadMessageBodyBuf(HKEY("000"), CtdlGetConfigLong("c_maxmsglen"), NULL, 0);
if (MsgBody != NULL) {
- CM_SetAsFieldSB(msg, eMesageText, &MsgBody);
+ CM_SetAsFieldSB(msg, eMessageText, &MsgBody);
}
}
}
-/*
- * API function to delete messages which match a set of criteria
- * (returns the actual number of messages deleted)
- */
+// 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"
}
syslog(LOG_DEBUG, "msgbase: CtdlDeleteMessages(%s, %d msgs, %s)", room_name, num_dmsgnums, content_type);
- /* get room record, obtaining a lock... */
+ // get room record, obtaining a lock...
if (CtdlGetRoomLock(&qrbuf, room_name) != 0) {
syslog(LOG_ERR, "msgbase: CtdlDeleteMessages(): Room <%s> not found", room_name);
if (need_to_free_re) regfree(&re);
- return(0); /* room not found */
+ return(0); // room not found
}
num_msgs = CtdlFetchMsgList(qrbuf.QRnumber, &msglist);
while ((i < num_msgs) && (have_more_del)) {
delete_this = 0x00;
- /* Set/clear a bit for each criterion */
+ // Set/clear a bit for each criterion
- /* 0 messages in the list or a null list means that we are
- * interested in deleting any messages which meet the other criteria.
- */
+ // 0 messages in the list or a null list means that we are
+ // interested in deleting any messages which meet the other criteria.
if (have_delmsgs) {
delete_this |= 0x01;
}
if (regexec(&re, smi.meta_content_type, 1, &pm, 0) == 0) {
delete_this |= 0x02;
}
- } else {
+ }
+ else {
delete_this |= 0x02;
}
- /* Delete message only if all bits are set */
+ // Delete message only if all bits are set
if (delete_this == 0x03) {
dellist[num_deleted++] = msglist[i];
msglist[i] = 0L;
}
CtdlPutRoomLock(&qrbuf);
- /* Go through the messages we pulled out of the index, and decrement
- * their reference counts by 1. If this is the only room the message
- * was in, the reference count will reach zero and the message will
- * automatically be deleted from the database. We do this in a
- * separate pass because there might be plug-in hooks getting called,
- * and we don't want that happening during an S_ROOMS critical
- * section.
- */
+ // Go through the messages we pulled out of the index, and decrement
+ // their reference counts by 1. If this is the only room the message
+ // was in, the reference count will reach zero and the message will
+ // automatically be deleted from the database. We do this in a
+ // separate pass because there might be plug-in hooks getting called,
+ // and we don't want that happening during an S_ROOMS critical section.
if (num_deleted) {
for (i=0; i<num_deleted; ++i) {
PerformDeleteHooks(qrbuf.QRname, dellist[i]);
}
AdjRefCountList(dellist, num_deleted, -1);
}
- /* Now free the memory we used, and go away. */
+ // Now free the memory we used, and go away.
if (msglist != NULL) free(msglist);
if (dellist != NULL) free(dellist);
syslog(LOG_DEBUG, "msgbase: %d message(s) deleted", num_deleted);
}
-/*
- * GetMetaData() - Get the supplementary record for a message
- */
+// GetMetaData() - Get the supplementary record for a message
void GetMetaData(struct MetaData *smibuf, long msgnum) {
struct cdbdata cdbsmi;
long TheIndex;
memset(smibuf, 0, sizeof(struct MetaData));
smibuf->meta_msgnum = msgnum;
- smibuf->meta_refcount = 1; /* Default reference count is 1 */
+ smibuf->meta_refcount = 1; // Default reference count is 1
- /* Use the negative of the message number for its supp record index */
+ // Use the negative of the message number for its supp record index
TheIndex = (0L - msgnum);
cdbsmi = cdb_fetch(CDB_MSGMAIN, &TheIndex, sizeof(long));
if (cdbsmi.ptr == NULL) {
- return; /* record not found; leave it alone */
+ return; // record not found; leave it alone
}
memcpy(smibuf, cdbsmi.ptr, ((cdbsmi.len > sizeof(struct MetaData)) ? sizeof(struct MetaData) : cdbsmi.len));
return;
}
-/*
- * PutMetaData() - (re)write supplementary record for a message
- */
-void PutMetaData(struct MetaData *smibuf)
-{
+// PutMetaData() - (re)write supplementary record for a message
+void PutMetaData(struct MetaData *smibuf) {
long TheIndex;
- /* Use the negative of the message number for the metadata db index */
+ // Use the negative of the message number for the metadata db index
TheIndex = (0L - smibuf->meta_msgnum);
cdb_store(CDB_MSGMAIN,
CM_SetField(msg, eOriginalRoom, req_room);
msg->cm_flags = flags;
- CM_SetAsFieldSB(msg, eMesageText, &encoded_message);
+ CM_SetAsFieldSB(msg, eMessageText, &encoded_message);
- /* Create the requested room if we have to. */
+ // 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);
}
- /* Now write the data */
+ // Now write the data
long new_msgnum = CtdlSubmitMsg(msg, NULL, roomname);
CM_Free(msg);
return new_msgnum;
}
-/************************************************************************/
-/* MODULE INITIALIZATION */
-/************************************************************************/
+// ************************************************************************/
+// * MODULE INITIALIZATION */
+// ************************************************************************/
char *ctdl_module_init_msgbase(void) {
if (!threading) {
FillMsgKeyLookupTable();
}
- /* return our module id for the log */
+ // return our module id for the log
return "msgbase";
}