#include <sys/stat.h>
#include <sys/types.h>
#include <regex.h>
+
+#include "md5.h"
+
#include <libcitadel.h>
#include "citadel.h"
#include "server.h"
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL,
- "from",
- NULL, NULL, NULL,
- "exti",
- "rfca",
- NULL,
- "hnod",
- "msgn",
- "jrnl",
- NULL,
- "list",
- "text",
- "node",
- "room",
- "path",
- NULL,
- "rcpt",
- "spec",
- "time",
- "subj",
- NULL,
- "wefw",
- NULL,
- "cccc",
- NULL
+ "from", /* A */
+ NULL, /* B */
+ NULL, /* C */
+ NULL, /* D */
+ "exti", /* E */
+ "rfca", /* F */
+ NULL, /* G */
+ "hnod", /* H */
+ "msgn", /* I */
+ "jrnl", /* J */
+ "rep2", /* K */
+ "list", /* L */
+ "text", /* M */
+ "node", /* N */
+ "room", /* O */
+ "path", /* P */
+ NULL, /* Q */
+ "rcpt", /* R */
+ "spec", /* S */
+ "time", /* T */
+ "subj", /* U */
+ "nvto", /* V */
+ "wefw", /* W */
+ NULL, /* X */
+ "cccc", /* Y */
+ NULL /* Z */
};
+eMsgField FieldOrder[] = {
+/* Important fields */
+ emessageId ,
+ eMessagePath ,
+ eTimestamp ,
+ eAuthor ,
+ erFc822Addr ,
+ eOriginalRoom,
+ eNodeName ,
+ eHumanNode ,
+ eRecipient ,
+ eDestination ,
+/* Semi-important fields */
+ eBig_message ,
+ eRemoteRoom ,
+ eExclusiveID ,
+ eWeferences ,
+ eJournal ,
+/* G is not used yet, may become virus signature*/
+ eReplyTo ,
+ eListID ,
+/* Q is not used yet */
+ eSpecialField,
+ eenVelopeTo ,
+/* X is not used yet */
+/* Z is not used yet */
+ eCarbonCopY ,
+ eMsgSubject ,
+/* internal only */
+ eErrorMsg ,
+ eSuppressIdx ,
+ eExtnotify ,
+/* Message text (MUST be last) */
+ eMesageText
+/* Not saved to disk:
+ eVltMsgNum
+*/
+};
+
+static const long NDiskFields = sizeof(FieldOrder) / sizeof(eMsgField);
+
+int CM_IsEmpty(struct CtdlMessage *Msg, eMsgField which)
+{
+ return !((Msg->cm_fields[which] != NULL) &&
+ (Msg->cm_fields[which][0] != '\0'));
+}
+
+void CM_SetField(struct CtdlMessage *Msg, eMsgField which, const char *buf, long length)
+{
+ if (Msg->cm_fields[which] != NULL)
+ free (Msg->cm_fields[which]);
+ Msg->cm_fields[which] = malloc(length + 1);
+ memcpy(Msg->cm_fields[which], buf, length);
+ Msg->cm_fields[which][length] = '\0';
+}
+
+void CM_SetFieldLONG(struct CtdlMessage *Msg, eMsgField which, long lvalue)
+{
+ char buf[128];
+ long len;
+ len = snprintf(buf, sizeof(buf), "%ld", lvalue);
+ CM_SetField(Msg, which, buf, len);
+}
+void CM_CutFieldAt(struct CtdlMessage *Msg, eMsgField WhichToCut, long maxlen)
+{
+ if (Msg->cm_fields[WhichToCut] == NULL)
+ return;
+
+ if (strlen(Msg->cm_fields[WhichToCut]) > maxlen)
+ Msg->cm_fields[WhichToCut][maxlen] = '\0';
+}
+
+void CM_FlushField(struct CtdlMessage *Msg, eMsgField which)
+{
+ if (Msg->cm_fields[which] != NULL)
+ free (Msg->cm_fields[which]);
+ Msg->cm_fields[which] = NULL;
+}
+
+void CM_CopyField(struct CtdlMessage *Msg, eMsgField WhichToPutTo, eMsgField WhichtToCopy)
+{
+ long len;
+ if (Msg->cm_fields[WhichToPutTo] != NULL)
+ free (Msg->cm_fields[WhichToPutTo]);
+
+ if (Msg->cm_fields[WhichtToCopy] != NULL)
+ {
+ len = strlen(Msg->cm_fields[WhichtToCopy]);
+ Msg->cm_fields[WhichToPutTo] = malloc(len + 1);
+ memcpy(Msg->cm_fields[WhichToPutTo], Msg->cm_fields[WhichToPutTo], len);
+ Msg->cm_fields[WhichToPutTo][len] = '\0';
+ }
+ else
+ Msg->cm_fields[WhichToPutTo] = NULL;
+}
+
+
+void CM_PrependToField(struct CtdlMessage *Msg, eMsgField which, const char *buf, long length)
+{
+ if (Msg->cm_fields[which] != NULL) {
+ long oldmsgsize;
+ long newmsgsize;
+ char *new;
+
+ oldmsgsize = strlen(Msg->cm_fields[which]) + 1;
+ newmsgsize = length + oldmsgsize;
+
+ new = malloc(newmsgsize);
+ memcpy(new, buf, length);
+ memcpy(new + length, Msg->cm_fields[which], oldmsgsize);
+ free(Msg->cm_fields[which]);
+ Msg->cm_fields[which] = new;
+ }
+ else {
+ Msg->cm_fields[which] = malloc(length + 1);
+ memcpy(Msg->cm_fields[which], buf, length);
+ Msg->cm_fields[which][length] = '\0';
+ }
+}
+
+void CM_SetAsField(struct CtdlMessage *Msg, eMsgField which, char **buf, long length)
+{
+ if (Msg->cm_fields[which] != NULL)
+ free (Msg->cm_fields[which]);
+
+ Msg->cm_fields[which] = *buf;
+ *buf = NULL;
+}
+
+void CM_SetAsFieldSB(struct CtdlMessage *Msg, eMsgField which, StrBuf **buf)
+{
+ if (Msg->cm_fields[which] != NULL)
+ free (Msg->cm_fields[which]);
+
+ Msg->cm_fields[which] = SmashStrBuf(buf);
+}
+
+void CM_GetAsField(struct CtdlMessage *Msg, eMsgField which, char **ret, long *retlen)
+{
+ if (Msg->cm_fields[which] != NULL)
+ {
+ *retlen = strlen(Msg->cm_fields[which]);
+ *ret = Msg->cm_fields[which];
+ Msg->cm_fields[which] = NULL;
+ }
+ else
+ {
+ *ret = NULL;
+ *retlen = 0;
+ }
+}
+
+/*
+ * Returns 1 if the supplied pointer points to a valid Citadel message.
+ * If the pointer is NULL or the magic number check fails, returns 0.
+ */
+int is_valid_message(struct CtdlMessage *msg) {
+ if (msg == NULL)
+ return 0;
+ if ((msg->cm_magic) != CTDLMESSAGE_MAGIC) {
+ struct CitContext *CCC = CC;
+ MSGM_syslog(LOG_WARNING, "is_valid_message() -- self-check failed\n");
+ return 0;
+ }
+ return 1;
+}
+
+void CtdlFreeMessageContents(struct CtdlMessage *msg)
+{
+ int i;
+
+ for (i = 0; i < 256; ++i)
+ if (msg->cm_fields[i] != NULL) {
+ free(msg->cm_fields[i]);
+ }
+
+ msg->cm_magic = 0; /* just in case */
+}
+/*
+ * 'Destructor' for struct CtdlMessage
+ */
+void CtdlFreeMessage(struct CtdlMessage *msg)
+{
+ if (is_valid_message(msg) == 0)
+ {
+ if (msg != NULL) free (msg);
+ return;
+ }
+ CtdlFreeMessageContents(msg);
+ free(msg);
+}
+
+int DupCMField(eMsgField i, struct CtdlMessage *OrgMsg, struct CtdlMessage *NewMsg)
+{
+ long len;
+ len = strlen(OrgMsg->cm_fields[i]);
+ NewMsg->cm_fields[i] = malloc(len + 1);
+ if (NewMsg->cm_fields[i] == NULL)
+ return 0;
+ memcpy(NewMsg->cm_fields[i], OrgMsg->cm_fields[i], len);
+ NewMsg->cm_fields[i][len] = '\0';
+ return 1;
+}
+
+struct CtdlMessage * CtdlDuplicateMessage(struct CtdlMessage *OrgMsg)
+{
+ int i;
+ struct CtdlMessage *NewMsg;
+
+ if (is_valid_message(OrgMsg) == 0)
+ return NULL;
+ NewMsg = (struct CtdlMessage *)malloc(sizeof(struct CtdlMessage));
+ if (NewMsg == NULL)
+ return NULL;
+
+ memcpy(NewMsg, OrgMsg, sizeof(struct CtdlMessage));
+
+ memset(&NewMsg->cm_fields, 0, sizeof(char*) * 256);
+
+ for (i = 0; i < 256; ++i)
+ {
+ if (OrgMsg->cm_fields[i] != NULL)
+ {
+ if (!DupCMField(i, OrgMsg, NewMsg))
+ {
+ CtdlFreeMessage(NewMsg);
+ return NULL;
+ }
+ }
+ }
+
+ return NewMsg;
+}
+
+
+
/*
* This function is self explanatory.
* (What can I say, I'm in a weird mood today...)
cprintf("%ld|%s|%s|%s|%s|%s|\n",
msgnum,
- (msg->cm_fields['T'] ? msg->cm_fields['T'] : "0"),
- (msg->cm_fields['A'] ? msg->cm_fields['A'] : ""),
- (msg->cm_fields['N'] ? msg->cm_fields['N'] : ""),
- (msg->cm_fields['F'] ? msg->cm_fields['F'] : ""),
- (msg->cm_fields['U'] ? msg->cm_fields['U'] : "")
+ (!CM_IsEmpty(msg, eTimestamp) ? msg->cm_fields[eTimestamp] : "0"),
+ (!CM_IsEmpty(msg, eAuthor) ? msg->cm_fields[eAuthor] : ""),
+ (!CM_IsEmpty(msg, eNodeName) ? msg->cm_fields[eNodeName] : ""),
+ (!CM_IsEmpty(msg, erFc822Addr) ? msg->cm_fields[erFc822Addr] : ""),
+ (!CM_IsEmpty(msg, eMsgSubject) ? msg->cm_fields[eMsgSubject] : "")
);
CtdlFreeMessage(msg);
}
cprintf("%ld|%s|%s\n",
msgnum,
- (msg->cm_fields['E'] ? msg->cm_fields['E'] : ""),
- (msg->cm_fields['T'] ? msg->cm_fields['T'] : "0"));
+ (!CM_IsEmpty(msg, eExclusiveID) ? msg->cm_fields[eExclusiveID] : ""),
+ (!CM_IsEmpty(msg, eTimestamp) ? msg->cm_fields[eTimestamp] : "0"));
CtdlFreeMessage(msg);
}
template->cm_anon_type = MES_NORMAL;
while(client_getln(buf, sizeof buf) >= 0 && strcmp(buf,"000")) {
+ long tValueLen;
extract_token(tfield, buf, 0, '|', sizeof tfield);
- extract_token(tvalue, buf, 1, '|', sizeof tvalue);
+ tValueLen = extract_token(tvalue, buf, 1, '|', sizeof tvalue);
for (i='A'; i<='Z'; ++i) if (msgkeys[i]!=NULL) {
if (!strcasecmp(tfield, msgkeys[i])) {
- template->cm_fields[i] =
- strdup(tvalue);
+ CM_SetField(template, i, tvalue, tValueLen);
}
}
}
return;
}
- rv = fwrite(content, length, 1, CC->download_fp);
+ rv = fwrite(content, length, 1, CCC->download_fp);
if (rv <= 0) {
MSG_syslog(LOG_EMERG, "mime_download(): Couldn't write: %s\n",
strerror(errno));
MSG_syslog(LOG_DEBUG, "CtdlFetchMessage(%ld, %d)\n", msgnum, with_body);
dmsgtext = cdb_fetch(CDB_MSGMAIN, &msgnum, sizeof(long));
if (dmsgtext == NULL) {
+ MSG_syslog(LOG_ERR, "CtdlFetchMessage(%ld, %d) Failed!\n", msgnum, with_body);
return NULL;
}
mptr = dmsgtext->ptr;
* have just processed the 'M' (message text) field.
*/
do {
+ long len;
if (mptr >= upper_bound) {
break;
}
field_header = *mptr++;
- ret->cm_fields[field_header] = strdup(mptr);
+ len = strlen(mptr);
+ CM_SetField(ret, field_header, mptr, len);
- while (*mptr++ != 0); /* advance to next field */
+ mptr += len + 1; /* advance to next field */
} while ((mptr < upper_bound) && (field_header != 'M'));
* so go ahead and fetch that. Failing that, just set a dummy
* body so other code doesn't barf.
*/
- if ( (ret->cm_fields['M'] == NULL) && (with_body) ) {
+ if ( (CM_IsEmpty(ret, eMesageText)) && (with_body) ) {
dmsgtext = cdb_fetch(CDB_BIGMSGS, &msgnum, sizeof(long));
if (dmsgtext != NULL) {
- ret->cm_fields['M'] = dmsgtext->ptr;
- dmsgtext->ptr = NULL;
+ CM_SetAsField(ret, eMesageText, &dmsgtext->ptr, dmsgtext->len);
cdb_free(dmsgtext);
}
}
- if (ret->cm_fields['M'] == NULL) {
- ret->cm_fields['M'] = strdup("\r\n\r\n (no text)\r\n");
+ if (CM_IsEmpty(ret, eMesageText)) {
+ CM_SetField(ret, eMesageText, HKEY("\r\n\r\n (no text)\r\n"));
}
/* Perform "before read" hooks (aborting if any return nonzero) */
}
-/*
- * Returns 1 if the supplied pointer points to a valid Citadel message.
- * If the pointer is NULL or the magic number check fails, returns 0.
- */
-int is_valid_message(struct CtdlMessage *msg) {
- if (msg == NULL)
- return 0;
- if ((msg->cm_magic) != CTDLMESSAGE_MAGIC) {
- struct CitContext *CCC = CC;
- MSGM_syslog(LOG_WARNING, "is_valid_message() -- self-check failed\n");
- return 0;
- }
- return 1;
-}
-
-void CtdlFreeMessageContents(struct CtdlMessage *msg)
-{
- int i;
-
- for (i = 0; i < 256; ++i)
- if (msg->cm_fields[i] != NULL) {
- free(msg->cm_fields[i]);
- }
-
- msg->cm_magic = 0; /* just in case */
-}
-/*
- * 'Destructor' for struct CtdlMessage
- */
-void CtdlFreeMessage(struct CtdlMessage *msg)
-{
- if (is_valid_message(msg) == 0)
- {
- if (msg != NULL) free (msg);
- return;
- }
- CtdlFreeMessageContents(msg);
- free(msg);
-}
-
/*
* Pre callback function for multipart/alternative
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 */
+ int flags, /* various flags; see msgbase.h */
+ char **Author,
+ char **Address
) {
struct CitContext *CCC = CC;
struct CtdlMessage *TheMessage = NULL;
if (section) if (!IsEmptyStr(section)) if (strcmp(section, "0")) {
memset(&encap, 0, sizeof encap);
safestrncpy(encap.desired_section, section, sizeof encap.desired_section);
- mime_parser(TheMessage->cm_fields['M'],
+ mime_parser(TheMessage->cm_fields[eMesageText],
NULL,
*extract_encapsulated_message,
NULL, NULL, (void *)&encap, 0
);
+
+ if ((Author != NULL) && (*Author == NULL))
+ {
+ *Author = TheMessage->cm_fields[eAuthor];
+ TheMessage->cm_fields[eAuthor] = NULL;
+ }
+ if ((Address != NULL) && (*Address == NULL))
+ {
+ *Address = TheMessage->cm_fields[erFc822Addr];
+ TheMessage->cm_fields[erFc822Addr] = NULL;
+ }
CtdlFreeMessage(TheMessage);
TheMessage = NULL;
* encapsulated message instead of the top-level
* message. Isn't that neat?
*/
-
}
else {
if (do_proto) {
/* Ok, output the message now */
if (retcode == CIT_OK)
retcode = CtdlOutputPreLoadedMsg(TheMessage, mode, headers_only, do_proto, crlf, flags);
+ if ((Author != NULL) && (*Author == NULL))
+ {
+ *Author = TheMessage->cm_fields[eAuthor];
+ TheMessage->cm_fields[eAuthor] = NULL;
+ }
+ if ((Address != NULL) && (*Address == NULL))
+ {
+ *Address = TheMessage->cm_fields[erFc822Addr];
+ TheMessage->cm_fields[erFc822Addr] = NULL;
+ }
+
CtdlFreeMessage(TheMessage);
return(retcode);
if (source == NULL) return source;
if (IsEmptyStr(source)) return source;
- cit_backtrace();
+ if (MessageDebugEnabled != 0) cit_backtrace();
MSG_syslog(LOG_DEBUG, "qp_encode_email_addrs: [%s]\n", source);
AddrPtr = malloc (sizeof (long) * nAddrPtrMax);
struct CtdlMessage *TheMessage,
int do_proto) /* do Citadel protocol responses? */
{
- char allkeys[30];
- int i, k, n;
+ int i;
int suppress_f = 0;
char buf[SIZ];
char display_name[256];
/* begin header processing loop for Citadel message format */
safestrncpy(display_name, "<unknown>", sizeof display_name);
- if (TheMessage->cm_fields['A']) {
- strcpy(buf, TheMessage->cm_fields['A']);
+ if (!CM_IsEmpty(TheMessage, eAuthor)) {
+ strcpy(buf, TheMessage->cm_fields[eAuthor]);
if (TheMessage->cm_anon_type == MES_ANONONLY) {
safestrncpy(display_name, "****", sizeof display_name);
}
* local Citadel network.
*/
suppress_f = 0;
- if (TheMessage->cm_fields['N'] != NULL)
- if (!IsEmptyStr(TheMessage->cm_fields['N']))
- if (haschar(TheMessage->cm_fields['N'], '.') == 0) {
- suppress_f = 1;
- }
+ if (!CM_IsEmpty(TheMessage, eNodeName) &&
+ (haschar(TheMessage->cm_fields[eNodeName], '.') == 0))
+ {
+ suppress_f = 1;
+ }
/* Now spew the header fields in the order we like them. */
- n = safestrncpy(allkeys, FORDER, sizeof allkeys);
- for (i=0; i<n; ++i) {
- k = (int) allkeys[i];
- if (k != 'M') {
- if ( (TheMessage->cm_fields[k] != NULL)
- && (msgkeys[k] != NULL) ) {
- if ((k == 'V') || (k == 'R') || (k == 'Y')) {
- sanitize_truncated_recipient(TheMessage->cm_fields[k]);
+ for (i=0; i< NDiskFields; ++i) {
+ eMsgField Field;
+ Field = FieldOrder[i];
+ if (Field != eMesageText) {
+ if ( (!CM_IsEmpty(TheMessage, Field))
+ && (msgkeys[Field] != NULL) ) {
+ if ((Field == eenVelopeTo) ||
+ (Field == eRecipient) ||
+ (Field == eCarbonCopY)) {
+ sanitize_truncated_recipient(TheMessage->cm_fields[Field]);
}
- if (k == 'A') {
+ if (Field == eAuthor) {
if (do_proto) cprintf("%s=%s\n",
- msgkeys[k],
+ msgkeys[Field],
display_name);
}
- else if ((k == 'F') && (suppress_f)) {
+ else if ((Field == erFc822Addr) && (suppress_f)) {
/* do nothing */
}
/* Masquerade display name if needed */
else {
if (do_proto) cprintf("%s=%s\n",
- msgkeys[k],
- TheMessage->cm_fields[k]
+ msgkeys[Field],
+ TheMessage->cm_fields[Field]
);
}
}
if (TheMessage->cm_fields[i]) {
mptr = mpptr = TheMessage->cm_fields[i];
- if (i == 'A') {
+ if (i == eAuthor) {
safestrncpy(luser, mptr, sizeof_luser);
safestrncpy(suser, mptr, sizeof_suser);
}
else if (i == 'P') {
cprintf("Return-Path: %s%s", mptr, nl);
}
- else if (i == 'L') {
+ else if (i == eListID) {
cprintf("List-ID: %s%s", mptr, nl);
}
else if (i == 'V') {
}
else if (i == 'I')
safestrncpy(mid, mptr, sizeof_mid); /// TODO: detect @ here and copy @nodename in if not found.
- else if (i == 'F')
+ else if (i == erFc822Addr)
safestrncpy(fuser, mptr, sizeof_fuser);
/* else if (i == 'O')
cprintf("X-Citadel-Room: %s%s",
}
}
}
- else if (i == 'K') {
+ else if (i == eReplyTo) {
hptr = mptr;
while ((*hptr != '\0') && isspace(*hptr))
hptr ++;
int nllen = strlen(nl);
char *mptr;
- mptr = TheMessage->cm_fields['M'];
+ mptr = TheMessage->cm_fields[eMesageText];
prev_ch = '\0';
int nllen = strlen (nl);
char *mptr;
- mptr = TheMessage->cm_fields['M'];
+ mptr = TheMessage->cm_fields[eMesageText];
if (mode == MT_MIME) {
cprintf("Content-type: text/plain\n\n");
/* Suppress envelope recipients if required to avoid disclosing BCC addresses.
* Pad it with spaces in order to avoid changing the RFC822 length of the message.
*/
- if ( (flags & SUPPRESS_ENV_TO) && (TheMessage->cm_fields['V'] != NULL) ) {
- memset(TheMessage->cm_fields['V'], ' ', strlen(TheMessage->cm_fields['V']));
+ if ( (flags & SUPPRESS_ENV_TO) && (!CM_IsEmpty(TheMessage, eenVelopeTo)) ) {
+ memset(TheMessage->cm_fields[eenVelopeTo], ' ', strlen(TheMessage->cm_fields[eenVelopeTo]));
}
/* Are we downloading a MIME component? */
ERROR + RESOURCE_BUSY);
} else {
/* Parse the message text component */
- mptr = TheMessage->cm_fields['M'];
+ mptr = TheMessage->cm_fields[eMesageText];
mime_parser(mptr, NULL, *mime_download, NULL, NULL, NULL, 0);
/* If there's no file open by this time, the requested
* section wasn't found, so print an error
/* Parse the message text component */
int found_it = 0;
- mptr = TheMessage->cm_fields['M'];
+ mptr = TheMessage->cm_fields[eMesageText];
mime_parser(mptr, NULL, *mime_spew_section, NULL, NULL, (void *)&found_it, 0);
/* If section wasn't found, print an error
*/
/* Tell the client about the MIME parts in this message */
if (TheMessage->cm_format_type == FMT_RFC822) {
if ( (mode == MT_CITADEL) || (mode == MT_MIME) ) {
- mptr = TheMessage->cm_fields['M'];
+ mptr = TheMessage->cm_fields[eMesageText];
memset(&ma, 0, sizeof(struct ma_info));
mime_parser(mptr, NULL,
(do_proto ? *list_this_part : NULL),
* message to the reader's screen width.
*/
if (TheMessage->cm_format_type == FMT_CITADEL) {
- mptr = TheMessage->cm_fields['M'];
+ mptr = TheMessage->cm_fields[eMesageText];
if (mode == MT_MIME) {
cprintf("Content-type: text/x-citadel-variformat\n\n");
msgid = extract_long(cmdbuf, 0);
headers_only = extract_int(cmdbuf, 1);
- CtdlOutputMsg(msgid, MT_CITADEL, headers_only, 1, 0, NULL, 0);
+ CtdlOutputMsg(msgid, MT_CITADEL, headers_only, 1, 0, NULL, 0, NULL, NULL);
return;
}
msgid = extract_long(cmdbuf, 0);
headers_only = extract_int(cmdbuf, 1);
- CtdlOutputMsg(msgid, MT_RFC822, headers_only, 1, 1, NULL, 0);
+ CtdlOutputMsg(msgid, MT_RFC822, headers_only, 1, 1, NULL, 0, NULL, NULL);
}
msgid = extract_long(cmdbuf, 0);
extract_token(section, cmdbuf, 1, '|', sizeof section);
- CtdlOutputMsg(msgid, MT_MIME, 0, 1, 0, (section[0] ? section : NULL) , 0);
+ CtdlOutputMsg(msgid, MT_MIME, 0, 1, 0, (section[0] ? section : NULL) , 0, NULL, NULL);
}
extract_token(desired_section, cmdbuf, 1, '|', sizeof desired_section);
safestrncpy(CC->download_desired_section, desired_section,
sizeof CC->download_desired_section);
- CtdlOutputMsg(msgid, MT_DOWNLOAD, 0, 1, 1, NULL, 0);
+ CtdlOutputMsg(msgid, MT_DOWNLOAD, 0, 1, 1, NULL, 0, NULL, NULL);
}
extract_token(desired_section, cmdbuf, 1, '|', sizeof desired_section);
safestrncpy(CC->download_desired_section, desired_section,
sizeof CC->download_desired_section);
- CtdlOutputMsg(msgid, MT_SPEW_SECTION, 0, 1, 1, NULL, 0);
-}
+ CtdlOutputMsg(msgid, MT_SPEW_SECTION, 0, 1, 1, NULL, 0, NULL, NULL);
+}
/*
ReplicationChecks(msg);
/* If the message has an Exclusive ID, index that... */
- if (msg->cm_fields['E'] != NULL) {
- index_message_by_euid(msg->cm_fields['E'], &CCC->room, msgid);
+ if (!CM_IsEmpty(msg, eExclusiveID)) {
+ index_message_by_euid(msg->cm_fields[eExclusiveID], &CCC->room, msgid);
}
/* Free up the memory we may have allocated */
long newmsgid;
long retval;
char msgidbuf[256];
+ long msgidbuflen;
struct ser_ret smr;
int is_bigmsg = 0;
char *holdM = NULL;
/* Get a new message number */
newmsgid = get_new_message_number();
- snprintf(msgidbuf, sizeof msgidbuf, "%08lX-%08lX@%s",
- (long unsigned int) time(NULL),
- (long unsigned int) newmsgid,
- config.c_fqdn
+ msgidbuflen = snprintf(msgidbuf, sizeof msgidbuf, "%08lX-%08lX@%s",
+ (long unsigned int) time(NULL),
+ (long unsigned int) newmsgid,
+ config.c_fqdn
);
/* Generate an ID if we don't have one already */
- if (msg->cm_fields['I']==NULL) {
- msg->cm_fields['I'] = strdup(msgidbuf);
+ if (CM_IsEmpty(msg, emessageId)) {
+ CM_SetField(msg, emessageId, msgidbuf, msgidbuflen);
}
/* If the message is big, set its body aside for storage elsewhere */
- if (msg->cm_fields['M'] != NULL) {
- if (strlen(msg->cm_fields['M']) > BIGMSG) {
+ if (!CM_IsEmpty(msg, eMesageText)) {
+ if (strlen(msg->cm_fields[eMesageText]) > BIGMSG) {
is_bigmsg = 1;
- holdM = msg->cm_fields['M'];
- msg->cm_fields['M'] = NULL;
+ holdM = msg->cm_fields[eMesageText];
+ msg->cm_fields[eMesageText] = NULL;
}
}
serialize_message(&smr, msg);
if (is_bigmsg) {
- msg->cm_fields['M'] = holdM;
+ msg->cm_fields[eMesageText] = holdM;
}
if (smr.len == 0) {
struct CitContext *CCC = CC;
size_t wlen, fieldlen;
int i;
- static char *forder = FORDER;
+ long lengths[NDiskFields];
+
+ memset(lengths, 0, sizeof(lengths));
/*
* Check for valid message format
}
ret->len = 3;
- for (i=0; i<26; ++i) if (msg->cm_fields[(int)forder[i]] != NULL)
- ret->len = ret->len +
- strlen(msg->cm_fields[(int)forder[i]]) + 2;
+ for (i=0; i < NDiskFields; ++i)
+ if (msg->cm_fields[FieldOrder[i]] != NULL)
+ {
+ lengths[i] = strlen(msg->cm_fields[FieldOrder[i]]);
+ ret->len += lengths[i] + 2;
+ }
ret->ser = malloc(ret->len);
if (ret->ser == NULL) {
ret->ser[2] = msg->cm_format_type;
wlen = 3;
- for (i=0; i<26; ++i) if (msg->cm_fields[(int)forder[i]] != NULL) {
- fieldlen = strlen(msg->cm_fields[(int)forder[i]]);
- ret->ser[wlen++] = (char)forder[i];
- safestrncpy((char *)&ret->ser[wlen], msg->cm_fields[(int)forder[i]], fieldlen+1);
+ for (i=0; i < NDiskFields; ++i)
+ if (msg->cm_fields[FieldOrder[i]] != NULL)
+ {
+ fieldlen = lengths[i];
+ ret->ser[wlen++] = (char)FieldOrder[i];
+
+ memcpy(&ret->ser[wlen],
+ msg->cm_fields[FieldOrder[i]],
+ fieldlen+1);
+
wlen = wlen + fieldlen + 1;
}
+
if (ret->len != wlen) {
MSG_syslog(LOG_ERR, "ERROR: len=%ld wlen=%ld\n",
(long)ret->len, (long)wlen);
/* No exclusive id? Don't do anything. */
if (msg == NULL) return;
- if (msg->cm_fields['E'] == NULL) return;
- if (IsEmptyStr(msg->cm_fields['E'])) return;
+ if (CM_IsEmpty(msg, eExclusiveID)) return;
+
/*MSG_syslog(LOG_DEBUG, "Exclusive ID: <%s> for room <%s>\n",
- msg->cm_fields['E'], CCC->room.QRname);*/
+ msg->cm_fields[eExclusiveID], CCC->room.QRname);*/
- old_msgnum = CtdlLocateMessageByEuid(msg->cm_fields['E'], &CCC->room);
+ old_msgnum = CtdlLocateMessageByEuid(msg->cm_fields[eExclusiveID], &CCC->room);
if (old_msgnum > 0L) {
MSG_syslog(LOG_DEBUG, "ReplicationChecks() replacing message %ld\n", old_msgnum);
CtdlDeleteMessages(CCC->room.QRname, &old_msgnum, 1, "");
)
{
char submit_filename[128];
- char generated_timestamp[32];
char hold_rm[ROOMNAMELEN];
char actual_rm[ROOMNAMELEN];
char force_room[ROOMNAMELEN];
/* If this message has no timestamp, we take the liberty of
* giving it one, right now.
*/
- if (msg->cm_fields['T'] == NULL) {
- snprintf(generated_timestamp, sizeof generated_timestamp, "%ld", (long)time(NULL));
- msg->cm_fields['T'] = strdup(generated_timestamp);
+ if (CM_IsEmpty(msg, eTimestamp)) {
+ CM_SetFieldLONG(msg, eTimestamp, time(NULL));
}
/* If this message has no path, we generate one.
*/
- if (msg->cm_fields['P'] == NULL) {
- if (msg->cm_fields['A'] != NULL) {
- msg->cm_fields['P'] = strdup(msg->cm_fields['A']);
- for (a=0; !IsEmptyStr(&msg->cm_fields['P'][a]); ++a) {
- if (isspace(msg->cm_fields['P'][a])) {
- msg->cm_fields['P'][a] = ' ';
+ if (CM_IsEmpty(msg, eMessagePath)) {
+ if (!CM_IsEmpty(msg, eAuthor)) {
+ CM_CopyField(msg, eMessagePath, eAuthor);
+ for (a=0; !IsEmptyStr(&msg->cm_fields[eMessagePath][a]); ++a) {
+ if (isspace(msg->cm_fields[eMessagePath][a])) {
+ msg->cm_fields[eMessagePath][a] = ' ';
}
}
}
else {
- msg->cm_fields['P'] = strdup("unknown");
+ CM_SetField(msg, eMessagePath, HKEY("unknown"));
}
}
if (force == NULL) {
- strcpy(force_room, "");
+ force_room[0] = '\0';
}
else {
strcpy(force_room, force);
}
/* Learn about what's inside, because it's what's inside that counts */
- if (msg->cm_fields['M'] == NULL) {
+ if (CM_IsEmpty(msg, eMesageText)) {
MSGM_syslog(LOG_ERR, "ERROR: attempt to save message with NULL body\n");
return(-2);
}
break;
case 4:
strcpy(content_type, "text/plain");
- mptr = bmstrcasestr(msg->cm_fields['M'], "Content-type:");
+ mptr = bmstrcasestr(msg->cm_fields[eMesageText], "Content-type:");
if (mptr != NULL) {
char *aptr;
safestrncpy(content_type, &mptr[13], sizeof content_type);
/*
* If this message has no O (room) field, generate one.
*/
- if (msg->cm_fields['O'] == NULL) {
- msg->cm_fields['O'] = strdup(CCC->room.QRname);
+ if (CM_IsEmpty(msg, eOriginalRoom)) {
+ CM_SetField(msg, eOriginalRoom, CCC->room.QRname, strlen(CCC->room.QRname));
}
/* Perform "before save" hooks (aborting if any return nonzero) */
snprintf(bounce_to, sizeof bounce_to, "%s@%s", CCC->user.fullname, config.c_nodename);
}
else {
- snprintf(bounce_to, sizeof bounce_to, "%s@%s", msg->cm_fields['A'], msg->cm_fields['N']);
+ snprintf(bounce_to, sizeof bounce_to, "%s@%s", msg->cm_fields[eAuthor], msg->cm_fields[eNodeName]);
}
/* If this is private, local mail, make a copy in the
*/
if ((recps != NULL) && (recps->num_local > 0))
for (i=0; i<num_tokens(recps->recp_local, '|'); ++i) {
- extract_token(recipient, recps->recp_local, i,
- '|', sizeof recipient);
+ long recipientlen;
+ recipientlen = extract_token(recipient,
+ recps->recp_local, i,
+ '|', sizeof recipient);
MSG_syslog(LOG_DEBUG, "Delivering private local mail to <%s>\n",
recipient);
if (CtdlGetUser(&userbuf, recipient) == 0) {
/* Generate a instruction message for the Funambol notification
* server, in the same style as the SMTP queue
*/
+ long instrlen;
instr_alloc = 1024;
instr = malloc(instr_alloc);
- snprintf(instr, instr_alloc,
- "Content-type: %s\n\nmsgid|%ld\nsubmitted|%ld\n"
- "bounceto|%s\n",
- SPOOLMIME, newmsgid, (long)time(NULL),
- bounce_to
+ instrlen = snprintf(
+ instr, instr_alloc,
+ "Content-type: %s\n\nmsgid|%ld\nsubmitted|%ld\n"
+ "bounceto|%s\n",
+ SPOOLMIME,
+ newmsgid,
+ (long)time(NULL), //todo: time() is expensive!
+ bounce_to
);
imsg = malloc(sizeof(struct CtdlMessage));
imsg->cm_magic = CTDLMESSAGE_MAGIC;
imsg->cm_anon_type = MES_NORMAL;
imsg->cm_format_type = FMT_RFC822;
- imsg->cm_fields['U'] = strdup("QMSG");
- imsg->cm_fields['A'] = strdup("Citadel");
- imsg->cm_fields['J'] = strdup("do not journal");
- imsg->cm_fields['M'] = instr; /* imsg owns this memory now */
- imsg->cm_fields['2'] = strdup(recipient);
+ CM_SetField(imsg, eMsgSubject, HKEY("QMSG"));
+ CM_SetField(imsg, eAuthor, HKEY("Citadel"));
+ CM_SetField(imsg, eJournal, HKEY("do not journal"));
+ CM_SetAsField(imsg, eMesageText, &instr, instrlen);
+ CM_SetField(imsg, eExtnotify, recipient, recipientlen);
CtdlSubmitMsg(imsg, NULL, FNBL_QUEUE_ROOM, 0);
CtdlFreeMessage(imsg);
}
/* Perform "after save" hooks */
MSGM_syslog(LOG_DEBUG, "Performing after-save hooks\n");
- if (msg->cm_fields['3'] != NULL) free(msg->cm_fields['3']);
- msg->cm_fields['3'] = malloc(20);
- snprintf(msg->cm_fields['3'], 20, "%ld", newmsgid);
+
+ CM_SetFieldLONG(msg, eVltMsgNum, newmsgid);
PerformMessageHooks(msg, EVT_AFTERSAVE);
- free(msg->cm_fields['3']);
- msg->cm_fields['3'] = NULL;
+ CM_FlushField(msg, eVltMsgNum);
/* For IGnet mail, we have to save a new copy into the spooler for
* each recipient, with the R and D fields set to the recipient and
extract_token(recipient, recps->recp_ignet, i,
'|', sizeof recipient);
- hold_R = msg->cm_fields['R'];
- hold_D = msg->cm_fields['D'];
- msg->cm_fields['R'] = malloc(SIZ);
- msg->cm_fields['D'] = malloc(128);
- extract_token(msg->cm_fields['R'], recipient, 0, '@', SIZ);
- extract_token(msg->cm_fields['D'], recipient, 1, '@', 128);
+ hold_R = msg->cm_fields[eRecipient];
+ hold_D = msg->cm_fields[eDestination];
+ msg->cm_fields[eRecipient] = malloc(SIZ);
+ msg->cm_fields[eDestination] = malloc(128);
+ extract_token(msg->cm_fields[eRecipient], recipient, 0, '@', SIZ);
+ extract_token(msg->cm_fields[eDestination], recipient, 1, '@', 128);
serialize_message(&smr, msg);
if (smr.len > 0) {
free(smr.ser);
}
- free(msg->cm_fields['R']);
- free(msg->cm_fields['D']);
- msg->cm_fields['R'] = hold_R;
- msg->cm_fields['D'] = hold_D;
+ free(msg->cm_fields[eRecipient]);
+ free(msg->cm_fields[eDestination]);
+ msg->cm_fields[eRecipient] = hold_R;
+ msg->cm_fields[eDestination] = hold_D;
}
/* Go back to the room we started from */
imsg->cm_magic = CTDLMESSAGE_MAGIC;
imsg->cm_anon_type = MES_NORMAL;
imsg->cm_format_type = FMT_RFC822;
- imsg->cm_fields['U'] = strdup("QMSG");
- imsg->cm_fields['A'] = strdup("Citadel");
- imsg->cm_fields['J'] = strdup("do not journal");
- imsg->cm_fields['M'] = SmashStrBuf(&SpoolMsg); /* imsg owns this memory now */
+ imsg->cm_fields[eMsgSubject] = strdup("QMSG");
+ imsg->cm_fields[eAuthor] = strdup("Citadel");
+ imsg->cm_fields[eJournal] = strdup("do not journal");
+ imsg->cm_fields[eMesageText] = SmashStrBuf(&SpoolMsg); /* imsg owns this memory now */
CtdlSubmitMsg(imsg, NULL, SMTP_SPOOLOUT_ROOM, QP_EADDR);
CtdlFreeMessage(imsg);
}
/*
* Determine whether this message qualifies for journaling.
*/
- if (msg->cm_fields['J'] != NULL) {
+ if (!CM_IsEmpty(msg, eJournal)) {
qualified_for_journaling = 0;
}
else {
}
-
-void aide_message (char *text, char *subject)
-{
- quickie_message("Citadel",NULL,NULL,AIDEROOM,text,FMT_CITADEL,subject);
-}
-
-
/*
* Convenience function for generating small administrative messages.
*/
-void quickie_message(const char *from, const char *fromaddr, char *to, char *room, const char *text,
- int format_type, const char *subject)
+void quickie_message(const char *from,
+ const char *fromaddr,
+ const char *to,
+ char *room,
+ const char *text,
+ int format_type,
+ const char *subject)
{
struct CtdlMessage *msg;
struct recptypes *recp = NULL;
msg->cm_format_type = format_type;
if (from != NULL) {
- msg->cm_fields['A'] = strdup(from);
+ msg->cm_fields[eAuthor] = strdup(from);
}
else if (fromaddr != NULL) {
- msg->cm_fields['A'] = strdup(fromaddr);
- if (strchr(msg->cm_fields['A'], '@')) {
- *strchr(msg->cm_fields['A'], '@') = 0;
+ msg->cm_fields[eAuthor] = strdup(fromaddr);
+ if (strchr(msg->cm_fields[eAuthor], '@')) {
+ *strchr(msg->cm_fields[eAuthor], '@') = 0;
}
}
else {
- msg->cm_fields['A'] = strdup("Citadel");
+ msg->cm_fields[eAuthor] = strdup("Citadel");
}
- if (fromaddr != NULL) msg->cm_fields['F'] = strdup(fromaddr);
- if (room != NULL) msg->cm_fields['O'] = strdup(room);
- msg->cm_fields['N'] = strdup(NODENAME);
+ if (fromaddr != NULL) msg->cm_fields[erFc822Addr] = strdup(fromaddr);
+ if (room != NULL) msg->cm_fields[eOriginalRoom] = strdup(room);
+ msg->cm_fields[eNodeName] = strdup(NODENAME);
if (to != NULL) {
- msg->cm_fields['R'] = strdup(to);
+ msg->cm_fields[eRecipient] = strdup(to);
recp = validate_recipients(to, NULL, 0);
}
if (subject != NULL) {
- msg->cm_fields['U'] = strdup(subject);
+ msg->cm_fields[eMsgSubject] = strdup(subject);
}
- msg->cm_fields['M'] = strdup(text);
+ msg->cm_fields[eMesageText] = strdup(text);
CtdlSubmitMsg(msg, recp, room, 0);
CtdlFreeMessage(msg);
if (recp != NULL) free_recipients(recp);
}
+void flood_protect_quickie_message(const char *from,
+ const char *fromaddr,
+ const char *to,
+ char *room,
+ const char *text,
+ int format_type,
+ const char *subject,
+ int nCriterions,
+ const char **CritStr,
+ long *CritStrLen,
+ long ccid,
+ long ioid,
+ time_t NOW)
+{
+ int i;
+ u_char rawdigest[MD5_DIGEST_LEN];
+ struct MD5Context md5context;
+ StrBuf *guid;
+ char timestamp[64];
+ long tslen;
+ time_t tsday = NOW / (8*60*60); /* just care for a day... */
+
+ tslen = snprintf(timestamp, sizeof(timestamp), "%ld", tsday);
+ MD5Init(&md5context);
+
+ for (i = 0; i < nCriterions; i++)
+ MD5Update(&md5context,
+ (const unsigned char*)CritStr[i], CritStrLen[i]);
+ MD5Update(&md5context,
+ (const unsigned char*)timestamp, tslen);
+ MD5Final(rawdigest, &md5context);
+
+ guid = NewStrBufPlain(NULL,
+ MD5_DIGEST_LEN * 2 + 12);
+ StrBufHexEscAppend(guid, NULL, rawdigest, MD5_DIGEST_LEN);
+ StrBufAppendBufPlain(guid, HKEY("_fldpt"), 0);
+ if (StrLength(guid) > 40)
+ StrBufCutAt(guid, 40, NULL);
+
+ if (CheckIfAlreadySeen("FPAideMessage",
+ guid,
+ NOW,
+ tsday,
+ eUpdate,
+ ccid,
+ ioid)!= 0)
+ {
+ FreeStrBuf(&guid);
+ /* yes, we did. flood protection kicks in. */
+ syslog(LOG_DEBUG,
+ "not sending message again\n");
+ return;
+ }
+ FreeStrBuf(&guid);
+ /* no, this message isn't sent recently; go ahead. */
+ quickie_message(from,
+ fromaddr,
+ to,
+ room,
+ text,
+ format_type,
+ subject);
+}
/*
StrBuf *CtdlReadMessageBodyBuf(char *terminator, /* token signalling EOT */
long tlen,
size_t maxlen, /* maximum message length */
- char *exist, /* if non-null, append to it;
+ StrBuf *exist, /* if non-null, append to it;
exist is ALWAYS freed */
int crlf, /* CRLF newlines instead of LF */
int *sock /* socket handle or 0 for this session's client socket */
Message = NewStrBufPlain(NULL, 4 * SIZ);
}
else {
- Message = NewStrBufPlain(exist, -1);
- free(exist);
+ Message = NewStrBufDup(exist);
}
/* Do we need to change leading ".." to "." for SMTP escaping? */
long tlen,
size_t maxlen, /* maximum message length */
size_t expectlen, /* if we expect a message, how long should it be? */
- char *exist, /* if non-null, append to it;
+ StrBuf *exist, /* if non-null, append to it;
exist is ALWAYS freed */
long eLen, /* length of exist */
int crlf /* CRLF newlines instead of LF */
NewMsg->MsgBuf = NewStrBufPlain(NULL, len);
}
else {
- NewMsg->MsgBuf = NewStrBufPlain(exist, eLen);
- free(exist);
+ NewMsg->MsgBuf = NewStrBufDup(exist);
}
/* Do we need to change leading ".." to "." for SMTP escaping? */
if ((tlen == 1) && (*terminator == '.')) {
char *CtdlReadMessageBody(char *terminator, /* token signalling EOT */
long tlen,
size_t maxlen, /* maximum message length */
- char *exist, /* if non-null, append to it;
+ StrBuf *exist, /* if non-null, append to it;
exist is ALWAYS freed */
int crlf, /* CRLF newlines instead of LF */
int *sock /* socket handle or 0 for this session's client socket */
if (my_email == NULL) my_email = "";
if (!IsEmptyStr(my_email)) {
- msg->cm_fields['P'] = strdup(my_email);
+ msg->cm_fields[eMessagePath] = strdup(my_email);
}
else {
snprintf(buf, sizeof buf, "%s", author->fullname);
- msg->cm_fields['P'] = strdup(buf);
+ msg->cm_fields[eMessagePath] = strdup(buf);
}
- convert_spaces_to_underscores(msg->cm_fields['P']);
+ convert_spaces_to_underscores(msg->cm_fields[eMessagePath]);
snprintf(buf, sizeof buf, "%ld", (long)time(NULL)); /* timestamp */
- msg->cm_fields['T'] = strdup(buf);
+ msg->cm_fields[eTimestamp] = strdup(buf);
if ((fake_name != NULL) && (fake_name[0])) { /* author */
FakeAuthor = NewStrBufPlain (fake_name, -1);
FakeAuthor = NewStrBufPlain (author->fullname, -1);
}
StrBufRFC2047encode(&FakeEncAuthor, FakeAuthor);
- msg->cm_fields['A'] = SmashStrBuf(&FakeEncAuthor);
+ msg->cm_fields[eAuthor] = SmashStrBuf(&FakeEncAuthor);
FreeStrBuf(&FakeAuthor);
if (CC->room.QRflags & QR_MAILBOX) { /* room */
- msg->cm_fields['O'] = strdup(&CC->room.QRname[11]);
+ msg->cm_fields[eOriginalRoom] = strdup(&CC->room.QRname[11]);
}
else {
- msg->cm_fields['O'] = strdup(CC->room.QRname);
+ msg->cm_fields[eOriginalRoom] = strdup(CC->room.QRname);
}
- msg->cm_fields['N'] = strdup(NODENAME); /* nodename */
- msg->cm_fields['H'] = strdup(HUMANNODE); /* hnodename */
+ msg->cm_fields[eNodeName] = strdup(NODENAME); /* nodename */
+ msg->cm_fields[eHumanNode] = strdup(HUMANNODE); /* hnodename */
if ((recipient != NULL) && (recipient[0] != 0)) {
- msg->cm_fields['R'] = strdup(recipient);
+ msg->cm_fields[eRecipient] = strdup(recipient);
}
if ((recp_cc != NULL) && (recp_cc[0] != 0)) {
- msg->cm_fields['Y'] = strdup(recp_cc);
+ msg->cm_fields[eCarbonCopY] = strdup(recp_cc);
}
if (dest_node[0] != 0) {
- msg->cm_fields['D'] = strdup(dest_node);
+ msg->cm_fields[eDestination] = strdup(dest_node);
}
if (!IsEmptyStr(my_email)) {
- msg->cm_fields['F'] = strdup(my_email);
+ msg->cm_fields[erFc822Addr] = strdup(my_email);
}
else if ( (author == &CC->user) && (!IsEmptyStr(CC->cs_inet_email)) ) {
- msg->cm_fields['F'] = strdup(CC->cs_inet_email);
+ msg->cm_fields[erFc822Addr] = strdup(CC->cs_inet_email);
}
if (subject != NULL) {
(IsAscii = isascii(subject[i]) != 0 ))
i++;
if (IsAscii != 0)
- msg->cm_fields['U'] = strdup(subject);
+ msg->cm_fields[eMsgSubject] = strdup(subject);
else /* ok, we've got utf8 in the string. */
{
- msg->cm_fields['U'] = rfc2047encode(subject, length);
+ msg->cm_fields[eMsgSubject] = rfc2047encode(subject, length);
}
}
}
if (supplied_euid != NULL) {
- msg->cm_fields['E'] = strdup(supplied_euid);
+ msg->cm_fields[eExclusiveID] = strdup(supplied_euid);
}
if ((references != NULL) && (!IsEmptyStr(references))) {
- if (msg->cm_fields['W'] != NULL)
- free(msg->cm_fields['W']);
- msg->cm_fields['W'] = strdup(references);
+ if (msg->cm_fields[eWeferences] != NULL)
+ free(msg->cm_fields[eWeferences]);
+ msg->cm_fields[eWeferences] = strdup(references);
}
if (preformatted_text != NULL) {
- msg->cm_fields['M'] = preformatted_text;
+ msg->cm_fields[eMesageText] = preformatted_text;
}
else {
- msg->cm_fields['M'] = CtdlReadMessageBody(HKEY("000"), config.c_maxmsglen, NULL, 0, 0);
+ msg->cm_fields[eMesageText] = CtdlReadMessageBody(HKEY("000"), config.c_maxmsglen, NULL, 0, 0);
}
return(msg);
}
-extern int netconfig_check_roomaccess(
- char *errmsgbuf,
- size_t n,
- const char* RemoteIdentifier); /* TODO: find a smarter way */
-
/*
* Check to see whether we have permission to post a message in the current
* room. Returns a *CITADEL ERROR CODE* and puts a message in errmsgbuf, or
}
if ((PostPublic!=POST_LMTP) &&(CC->room.QRflags2 & QR2_SMTP_PUBLIC) == 0) {
- return netconfig_check_roomaccess(errmsgbuf, n, RemoteIdentifier);
+ return CtdlNetconfigCheckRoomaccess(errmsgbuf, n, RemoteIdentifier);
}
return (0);
/* User flagged ok? */
if (who->flags & US_INTERNET) return(2);
- /* Aide level access? */
+ /* Admin level access? */
if (who->axlevel >= AxAideU) return(3);
/* No mail for you! */
* to the actual mail address so others get a valid
* reply-to-header.
*/
- msg->cm_fields['V'] = strdup(valid->recp_orgroom);
+ msg->cm_fields[eenVelopeTo] = strdup(valid->recp_orgroom);
}
if (msg != NULL) {
client_write(HKEY("Internal error.\n"));
}
- if (msg->cm_fields['E'] != NULL) {
- cprintf("%s\n", msg->cm_fields['E']);
+ if (!CM_IsEmpty(msg, eExclusiveID)) {
+ cprintf("%s\n", msg->cm_fields[eExclusiveID]);
} else {
cprintf("\n");
}
regcomp(&re, content_type, 0);
need_to_free_re = 1;
}
- MSG_syslog(LOG_DEBUG, "CtdlDeleteMessages(%s, %d msgs, %s)\n",
+ MSG_syslog(LOG_DEBUG, " CtdlDeleteMessages(%s, %d msgs, %s)\n",
room_name, num_dmsgnums, content_type);
/* get room record, obtaining a lock... */
if (CtdlGetRoomLock(&qrbuf, room_name) != 0) {
- MSG_syslog(LOG_ERR, "CtdlDeleteMessages(): Room <%s> not found\n",
+ MSG_syslog(LOG_ERR, " CtdlDeleteMessages(): Room <%s> not found\n",
room_name);
if (need_to_free_re) regfree(&re);
return (0); /* room not found */
StrBuf *dbg = NewStrBuf();
for (i = 0; i < num_dmsgnums; i++)
StrBufAppendPrintf(dbg, ", %ld", dmsgnums[i]);
- MSG_syslog(LOG_DEBUG, "Deleting before: %s", ChrPtr(dbg));
+ MSG_syslog(LOG_DEBUG, " Deleting before: %s", ChrPtr(dbg));
FreeStrBuf(&dbg);
}
*/
while ((i < num_msgs) && (have_more_del)) {
delete_this = 0x00;
-
/* Set/clear a bit for each criterion */
/* 0 messages in the list or a null list means that we are
}
else {
while ((i < num_msgs) && (msglist[i] < dmsgnums[j])) i++;
+
+ if (i >= num_msgs)
+ continue;
+
if (msglist[i] == dmsgnums[j]) {
delete_this |= 0x01;
}
StrBuf *dbg = NewStrBuf();
for (i = 0; i < num_deleted; i++)
StrBufAppendPrintf(dbg, ", %ld", dellist[i]);
- MSG_syslog(LOG_DEBUG, "Deleting: %s", ChrPtr(dbg));
+ MSG_syslog(LOG_DEBUG, " Deleting: %s", ChrPtr(dbg));
FreeStrBuf(&dbg);
}
*/
/* Now free the memory we used, and go away. */
if (msglist != NULL) free(msglist);
if (dellist != NULL) free(dellist);
- MSG_syslog(LOG_DEBUG, "%d message(s) deleted.\n", num_deleted);
+ MSG_syslog(LOG_DEBUG, " %d message(s) deleted.\n", num_deleted);
if (need_to_free_re) regfree(&re);
return (num_deleted);
}
*/
permit = 0;
- /* Aides can move/copy */
+ /* Admins can move/copy */
if (CC->user.axlevel >= AxAideU) permit = 1;
/* Room aides can move/copy */
msg->cm_magic = CTDLMESSAGE_MAGIC;
msg->cm_anon_type = MES_NORMAL;
msg->cm_format_type = 4;
- msg->cm_fields['A'] = strdup(CCC->user.fullname);
- msg->cm_fields['O'] = strdup(req_room);
- msg->cm_fields['N'] = strdup(config.c_nodename);
- msg->cm_fields['H'] = strdup(config.c_humannode);
+ msg->cm_fields[eAuthor] = strdup(CCC->user.fullname);
+ msg->cm_fields[eOriginalRoom] = strdup(req_room);
+ msg->cm_fields[eNodeName] = strdup(config.c_nodename);
+ msg->cm_fields[eHumanNode] = strdup(config.c_humannode);
msg->cm_flags = flags;
- msg->cm_fields['M'] = encoded_message;
+ msg->cm_fields[eMesageText] = encoded_message;
/* Create the requested room if we have to. */
if (CtdlGetRoom(&qrbuf, roomname) != 0) {
else {
msg = CtdlFetchMessage(msgnum, 1);
if (msg != NULL) {
- conf = strdup(msg->cm_fields['M']);
+ conf = strdup(msg->cm_fields[eMesageText]);
CtdlFreeMessage(msg);
}
else {