X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=citadel%2Fmsgbase.c;h=73d6bfe199af3f8bce5cc17d615ea9d48ec1a80a;hb=e6219cc9b27e56e3b41170f864da30fa7b13ee01;hp=143b6cb2a7d2bdb76eec08223e18651ebcf1a72c;hpb=ecb3845b2d525c1a6e9130b99201ace75f2ca6d0;p=citadel.git diff --git a/citadel/msgbase.c b/citadel/msgbase.c index 143b6cb2a..73d6bfe19 100644 --- a/citadel/msgbase.c +++ b/citadel/msgbase.c @@ -38,6 +38,9 @@ #include #include #include + +#include "md5.h" + #include #include "citadel.h" #include "server.h" @@ -67,9 +70,10 @@ 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); +int MessageDebugEnabled = 0; + /* * These are the four-character field headers we use when outputting * messages in Citadel format (as opposed to RFC822 format). @@ -84,32 +88,186 @@ char *msgkeys[] = { 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; + } +} + /* * This function is self explanatory. * (What can I say, I'm in a weird mood today...) @@ -138,6 +296,7 @@ void remove_any_whitespace_to_the_left_or_right_of_at_symbol(char *name) */ int alias(char *name) { /* process alias and routing info for mail */ + struct CitContext *CCC = CC; FILE *fp; int a, i; char aaa[SIZ], bbb[SIZ]; @@ -186,7 +345,7 @@ int alias(char *name) } if (strcasecmp(original_name, name)) { - syslog(LOG_INFO, "%s is being forwarded to %s\n", original_name, name); + MSG_syslog(LOG_INFO, "%s is being forwarded to %s\n", original_name, name); } /* Change "user @ xxx" to "user" if xxx is an alias for this host */ @@ -194,7 +353,7 @@ int alias(char *name) if (name[a] == '@') { if (CtdlHostAlias(&name[a+1]) == hostalias_localhost) { name[a] = 0; - syslog(LOG_INFO, "Changed to <%s>\n", name); + MSG_syslog(LOG_INFO, "Changed to <%s>\n", name); } } } @@ -273,11 +432,11 @@ void headers_listing(long msgnum, void *userdata) cprintf("%ld|%s|%s|%s|%s|%s|\n", msgnum, - (msg->cm_fields['T'] ? msg->cm_fields['T'] : "0"), - (msg->cm_fields['A'] ? msg->cm_fields['A'] : ""), - (msg->cm_fields['N'] ? msg->cm_fields['N'] : ""), - (msg->cm_fields['F'] ? msg->cm_fields['F'] : ""), - (msg->cm_fields['U'] ? msg->cm_fields['U'] : "") + (!CM_IsEmpty(msg, eTimestamp) ? msg->cm_fields[eTimestamp] : "0"), + (!CM_IsEmpty(msg, eAuthor) ? msg->cm_fields[eAuthor] : ""), + (!CM_IsEmpty(msg, eNodeName) ? msg->cm_fields[eNodeName] : ""), + (!CM_IsEmpty(msg, erFc822Addr) ? msg->cm_fields[erFc822Addr] : ""), + (!CM_IsEmpty(msg, eMsgSubject) ? msg->cm_fields[eMsgSubject] : "") ); CtdlFreeMessage(msg); } @@ -297,8 +456,8 @@ void headers_euid(long msgnum, void *userdata) cprintf("%ld|%s|%s\n", msgnum, - (msg->cm_fields['E'] ? msg->cm_fields['E'] : ""), - (msg->cm_fields['T'] ? msg->cm_fields['T'] : "0")); + (!CM_IsEmpty(msg, eExclusiveID) ? msg->cm_fields[eExclusiveID] : ""), + (!CM_IsEmpty(msg, eTimestamp) ? msg->cm_fields[eTimestamp] : "0")); CtdlFreeMessage(msg); } @@ -342,10 +501,11 @@ int CtdlMsgCmp(struct CtdlMessage *msg, struct CtdlMessage *template) { * Retrieve the "seen" message list for the current room. */ void CtdlGetSeen(char *buf, int which_set) { + struct CitContext *CCC = CC; visit vbuf; /* Learn about the user and room in question */ - CtdlGetRelationship(&vbuf, &CC->user, &CC->room); + CtdlGetRelationship(&vbuf, &CCC->user, &CCC->room); if (which_set == ctdlsetseen_seen) safestrncpy(buf, vbuf.v_seen, SIZ); @@ -361,12 +521,13 @@ void CtdlGetSeen(char *buf, int which_set) { void CtdlSetSeen(long *target_msgnums, int num_target_msgnums, int target_setting, int which_set, struct ctdluser *which_user, struct ctdlroom *which_room) { + struct CitContext *CCC = CC; struct cdbdata *cdbfr; int i, k; int is_seen = 0; int was_seen = 0; long lo = (-1L); - long hi = (-1L); + long hi = (-1L); /// TODO: we just write here. y? visit vbuf; long *msglist; int num_msgs = 0; @@ -384,19 +545,19 @@ void CtdlSetSeen(long *target_msgnums, int num_target_msgnums, /* If no room was specified, we go with the current room. */ if (!which_room) { - which_room = &CC->room; + which_room = &CCC->room; } /* If no user was specified, we go with the current user. */ if (!which_user) { - which_user = &CC->user; + which_user = &CCC->user; } - syslog(LOG_DEBUG, "CtdlSetSeen(%d msgs starting with %ld, %s, %d) in <%s>\n", - num_target_msgnums, target_msgnums[0], - (target_setting ? "SET" : "CLEAR"), - which_set, - which_room->QRname); + MSG_syslog(LOG_DEBUG, "CtdlSetSeen(%d msgs starting with %ld, %s, %d) in <%s>\n", + num_target_msgnums, target_msgnums[0], + (target_setting ? "SET" : "CLEAR"), + which_set, + which_room->QRname); /* Learn about the user and room in question */ CtdlGetRelationship(&vbuf, which_user, which_room); @@ -429,17 +590,17 @@ 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. */ - syslog(LOG_DEBUG, "There are %d messages in the room.\n", num_msgs); + MSG_syslog(LOG_DEBUG, "There are %d messages in the room.\n", num_msgs); for (i=0; i 0) && (msglist[i] <= msglist[i-1])) abort(); } - syslog(LOG_DEBUG, "We are twiddling %d of them.\n", num_target_msgnums); + MSG_syslog(LOG_DEBUG, "We are twiddling %d of them.\n", num_target_msgnums); for (k=0; k 0) && (target_msgnums[k] <= target_msgnums[k-1])) abort(); } #endif - syslog(LOG_DEBUG, "before update: %s\n", ChrPtr(vset)); + MSG_syslog(LOG_DEBUG, "before update: %s\n", ChrPtr(vset)); /* Translate the existing sequence set into an array of booleans */ setstr = NewStrBuf(); @@ -562,7 +723,7 @@ void CtdlSetSeen(long *target_msgnums, int num_target_msgnums, vset = new_set; } - syslog(LOG_DEBUG, " after update: %s\n", ChrPtr(vset)); + MSG_syslog(LOG_DEBUG, " after update: %s\n", ChrPtr(vset)); /* Decide which message set we're manipulating */ switch (which_set) { @@ -591,7 +752,7 @@ int CtdlForEachMessage(int mode, long ref, char *search_string, ForEachMsgCallback CallBack, void *userdata) { - + struct CitContext *CCC = CC; int a, i, j; visit vbuf; struct cdbdata *cdbfr; @@ -620,13 +781,13 @@ int CtdlForEachMessage(int mode, long ref, char *search_string, if (need_to_free_re) regfree(&re); return -1; } - CtdlGetUser(&CC->user, CC->curr_user); + CtdlGetUser(&CCC->user, CCC->curr_user); if (server_shutting_down) { if (need_to_free_re) regfree(&re); return -1; } - CtdlGetRelationship(&vbuf, &CC->user, &CC->room); + CtdlGetRelationship(&vbuf, &CCC->user, &CCC->room); if (server_shutting_down) { if (need_to_free_re) regfree(&re); @@ -634,7 +795,7 @@ int CtdlForEachMessage(int mode, long ref, char *search_string, } /* Load the message list */ - cdbfr = cdb_fetch(CDB_MSGLISTS, &CC->room.QRnumber, sizeof(long)); + cdbfr = cdb_fetch(CDB_MSGLISTS, &CCC->room.QRnumber, sizeof(long)); if (cdbfr == NULL) { if (need_to_free_re) regfree(&re); return 0; /* No messages at all? No further action. */ @@ -781,7 +942,7 @@ int CtdlForEachMessage(int mode, long ref, char *search_string, || ((mode == MSGS_EQ) && (thismsg == ref)) ) ) { - if ((mode == MSGS_NEW) && (CC->user.flags & US_LASTOLD) && (lastold > 0L) && (printed_lastold == 0) && (!is_seen)) { + if ((mode == MSGS_NEW) && (CCC->user.flags & US_LASTOLD) && (lastold > 0L) && (printed_lastold == 0) && (!is_seen)) { if (CallBack) CallBack(lastold, userdata); printed_lastold = 1; @@ -796,12 +957,12 @@ int CtdlForEachMessage(int mode, long ref, char *search_string, /* * 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); + if (CCC->client_socket > 0) { + if (CCC->cached_msglist != NULL) { + free(CCC->cached_msglist); } - CC->cached_msglist = msglist; - CC->cached_num_msgs = num_msgs; + CCC->cached_msglist = msglist; + CCC->cached_num_msgs = num_msgs; } else { free(msglist); @@ -885,12 +1046,12 @@ void cmd_msgs(char *cmdbuf) template->cm_anon_type = MES_NORMAL; while(client_getln(buf, sizeof buf) >= 0 && strcmp(buf,"000")) { + long tValueLen; extract_token(tfield, buf, 0, '|', sizeof tfield); - extract_token(tvalue, buf, 1, '|', sizeof tvalue); + tValueLen = extract_token(tvalue, buf, 1, '|', sizeof tvalue); for (i='A'; i<='Z'; ++i) if (msgkeys[i]!=NULL) { if (!strcasecmp(tfield, msgkeys[i])) { - template->cm_fields[i] = - strdup(tvalue); + CM_SetField(template, i, tvalue, tValueLen); } } } @@ -960,6 +1121,7 @@ void memfmout( char *mptr, /* where are we going to get our text from? */ const char *nl /* string to terminate lines with */ ) { + struct CitContext *CCC = CC; int column = 0; unsigned char ch = 0; char outbuf[1024]; @@ -973,13 +1135,13 @@ void memfmout( if (ch == '\n') { if (client_write(outbuf, len) == -1) { - syslog(LOG_ERR, "memfmout(): aborting due to write failure.\n"); + MSGM_syslog(LOG_ERR, "memfmout(): aborting due to write failure.\n"); return; } len = 0; if (client_write(nl, nllen) == -1) { - syslog(LOG_ERR, "memfmout(): aborting due to write failure.\n"); + MSGM_syslog(LOG_ERR, "memfmout(): aborting due to write failure.\n"); return; } column = 0; @@ -991,13 +1153,13 @@ void memfmout( if (column > 72) { /* Beyond 72 columns, break on the next space */ if (client_write(outbuf, len) == -1) { - syslog(LOG_ERR, "memfmout(): aborting due to write failure.\n"); + MSGM_syslog(LOG_ERR, "memfmout(): aborting due to write failure.\n"); return; } len = 0; if (client_write(nl, nllen) == -1) { - syslog(LOG_ERR, "memfmout(): aborting due to write failure.\n"); + MSGM_syslog(LOG_ERR, "memfmout(): aborting due to write failure.\n"); return; } column = 0; @@ -1013,13 +1175,13 @@ void memfmout( if (column > 1000) { /* Beyond 1000 columns, break anywhere */ if (client_write(outbuf, len) == -1) { - syslog(LOG_ERR, "memfmout(): aborting due to write failure.\n"); + MSGM_syslog(LOG_ERR, "memfmout(): aborting due to write failure.\n"); return; } len = 0; if (client_write(nl, nllen) == -1) { - syslog(LOG_ERR, "memfmout(): aborting due to write failure.\n"); + MSGM_syslog(LOG_ERR, "memfmout(): aborting due to write failure.\n"); return; } column = 0; @@ -1029,7 +1191,7 @@ void memfmout( if (len) { if (client_write(outbuf, len) == -1) { - syslog(LOG_ERR, "memfmout(): aborting due to write failure.\n"); + MSGM_syslog(LOG_ERR, "memfmout(): aborting due to write failure.\n"); return; } len = 0; @@ -1121,17 +1283,17 @@ void mime_download(char *name, char *filename, char *partnum, char *disp, ) { CCC->download_fp = tmpfile(); if (CCC->download_fp == NULL) { - syslog(LOG_EMERG, "mime_download(): Couldn't write: %s\n", - strerror(errno)); + MSG_syslog(LOG_EMERG, "mime_download(): Couldn't write: %s\n", + strerror(errno)); cprintf("%d cannot open temporary file: %s\n", ERROR + INTERNAL_ERROR, strerror(errno)); return; } - rv = fwrite(content, length, 1, CC->download_fp); + rv = fwrite(content, length, 1, CCC->download_fp); if (rv <= 0) { - syslog(LOG_EMERG, "mime_download(): Couldn't write: %s\n", - strerror(errno)); + MSG_syslog(LOG_EMERG, "mime_download(): Couldn't write: %s\n", + strerror(errno)); cprintf("%d unable to write tempfile.\n", ERROR + TOO_BIG); fclose(CCC->download_fp); @@ -1183,6 +1345,7 @@ void mime_spew_section(char *name, char *filename, char *partnum, char *disp, */ struct CtdlMessage *CtdlFetchMessage(long msgnum, int with_body) { + struct CitContext *CCC = CC; struct cdbdata *dmsgtext; struct CtdlMessage *ret = NULL; char *mptr; @@ -1190,9 +1353,10 @@ struct CtdlMessage *CtdlFetchMessage(long msgnum, int with_body) cit_uint8_t ch; cit_uint8_t field_header; - syslog(LOG_DEBUG, "CtdlFetchMessage(%ld, %d)\n", msgnum, with_body); + 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; @@ -1205,7 +1369,7 @@ struct CtdlMessage *CtdlFetchMessage(long msgnum, int with_body) */ ch = *mptr++; if (ch != 255) { - syslog(LOG_ERR, "Message %ld appears to be corrupted.\n", msgnum); + MSG_syslog(LOG_ERR, "Message %ld appears to be corrupted.\n", msgnum); cdb_free(dmsgtext); return NULL; } @@ -1222,13 +1386,15 @@ struct CtdlMessage *CtdlFetchMessage(long msgnum, int with_body) * have just processed the 'M' (message text) field. */ do { + long len; if (mptr >= upper_bound) { break; } field_header = *mptr++; - ret->cm_fields[field_header] = strdup(mptr); + len = strlen(mptr); + CM_SetField(ret, field_header, mptr, len); - while (*mptr++ != 0); /* advance to next field */ + mptr += len + 1; /* advance to next field */ } while ((mptr < upper_bound) && (field_header != 'M')); @@ -1239,16 +1405,15 @@ struct CtdlMessage *CtdlFetchMessage(long msgnum, int with_body) * so go ahead and fetch that. Failing that, just set a dummy * body so other code doesn't barf. */ - if ( (ret->cm_fields['M'] == NULL) && (with_body) ) { + if ( (CM_IsEmpty(ret, eMesageText)) && (with_body) ) { dmsgtext = cdb_fetch(CDB_BIGMSGS, &msgnum, sizeof(long)); if (dmsgtext != NULL) { - ret->cm_fields['M'] = dmsgtext->ptr; - dmsgtext->ptr = NULL; + CM_SetAsField(ret, eMesageText, &dmsgtext->ptr, dmsgtext->len); cdb_free(dmsgtext); } } - if (ret->cm_fields['M'] == NULL) { - ret->cm_fields['M'] = strdup("\r\n\r\n (no text)\r\n"); + if (CM_IsEmpty(ret, eMesageText)) { + CM_SetField(ret, eMesageText, HKEY("\r\n\r\n (no text)\r\n")); } /* Perform "before read" hooks (aborting if any return nonzero) */ @@ -1269,7 +1434,8 @@ int is_valid_message(struct CtdlMessage *msg) { if (msg == NULL) return 0; if ((msg->cm_magic) != CTDLMESSAGE_MAGIC) { - syslog(LOG_WARNING, "is_valid_message() -- self-check failed\n"); + struct CitContext *CCC = CC; + MSGM_syslog(LOG_WARNING, "is_valid_message() -- self-check failed\n"); return 0; } return 1; @@ -1300,6 +1466,49 @@ void CtdlFreeMessage(struct CtdlMessage *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; +} + + /* * Pre callback function for multipart/alternative @@ -1315,10 +1524,11 @@ 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) { + struct CitContext *CCC = CC; struct ma_info *ma; ma = (struct ma_info *)cbuserdata; - syslog(LOG_DEBUG, "fixed_output_pre() type=<%s>\n", cbtype); + MSG_syslog(LOG_DEBUG, "fixed_output_pre() type=<%s>\n", cbtype); if (!strcasecmp(cbtype, "multipart/alternative")) { ++ma->is_ma; ma->did_print = 0; @@ -1335,10 +1545,11 @@ 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) { + struct CitContext *CCC = CC; struct ma_info *ma; ma = (struct ma_info *)cbuserdata; - syslog(LOG_DEBUG, "fixed_output_post() type=<%s>\n", cbtype); + MSG_syslog(LOG_DEBUG, "fixed_output_post() type=<%s>\n", cbtype); if (!strcasecmp(cbtype, "multipart/alternative")) { --ma->is_ma; ma->did_print = 0; @@ -1355,6 +1566,7 @@ 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) { + struct CitContext *CCC = CC; char *ptr; char *wptr; size_t wlen; @@ -1362,7 +1574,7 @@ void fixed_output(char *name, char *filename, char *partnum, char *disp, ma = (struct ma_info *)cbuserdata; - syslog(LOG_DEBUG, + MSG_syslog(LOG_DEBUG, "fixed_output() part %s: %s (%s) (%ld bytes)\n", partnum, filename, cbtype, (long)length); @@ -1371,7 +1583,7 @@ void fixed_output(char *name, char *filename, char *partnum, char *disp, * we've already printed another section, skip this one. */ if ( (ma->is_ma) && (ma->did_print) ) { - syslog(LOG_DEBUG, "Skipping part %s (%s)\n", partnum, cbtype); + MSG_syslog(LOG_DEBUG, "Skipping part %s (%s)\n", partnum, cbtype); return; } ma->did_print = 1; @@ -1428,6 +1640,7 @@ 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) { + struct CitContext *CCC = CC; char buf[1024]; int i; struct ma_info *ma; @@ -1439,11 +1652,11 @@ void choose_preferred(char *name, char *filename, char *partnum, char *disp, // 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); + for (i=0; ipreferred_formats, '|'); ++i) { + extract_token(buf, CCC->preferred_formats, i, '|', sizeof buf); if ( (!strcasecmp(buf, cbtype)) && (!ma->freeze) ) { if (i < ma->chosen_pref) { - syslog(LOG_DEBUG, "Setting chosen part: <%s>\n", partnum); + MSG_syslog(LOG_DEBUG, "Setting chosen part: <%s>\n", partnum); safestrncpy(ma->chosen_part, partnum, sizeof ma->chosen_part); ma->chosen_pref = i; } @@ -1466,6 +1679,7 @@ void output_preferred(char *name, char *cbid, void *cbuserdata) { + struct CitContext *CCC = CC; int i; char buf[128]; int add_newline = 0; @@ -1483,8 +1697,8 @@ void output_preferred(char *name, /* 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); + for (i=0; ipreferred_formats, '|'); ++i) { + extract_token(buf, CCC->preferred_formats, i, '|', sizeof buf); if (!strcasecmp(buf, cbtype)) { /* Yeah! Go! W00t!! */ if (ma->dont_decode == 0) @@ -1521,7 +1735,7 @@ void output_preferred(char *name, cprintf("\n"); if (client_write(text_content, length) == -1) { - syslog(LOG_ERR, "output_preferred(): aborting due to write failure.\n"); + MSGM_syslog(LOG_ERR, "output_preferred(): aborting due to write failure.\n"); return; } if (add_newline) cprintf("\n"); @@ -1587,12 +1801,13 @@ void extract_encapsulated_message(char *name, char *filename, char *partnum, cha * (This is a security check) */ int check_cached_msglist(long msgnum) { + struct CitContext *CCC = CC; /* 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 */ + if (!CCC) return om_ok; /* not a session */ + if (CCC->client_socket <= 0) return om_ok; /* not a client session */ + if (CCC->cached_msglist == NULL) return om_access_denied; /* no msglist fetched */ + if (CCC->cached_num_msgs == 0) return om_access_denied; /* nothing to check */ /* Do a binary search within the cached_msglist for the requested msgnum */ @@ -1601,7 +1816,7 @@ int check_cached_msglist(long msgnum) { while (max >= min) { int middle = min + (max-min) / 2 ; - if (msgnum == CC->cached_msglist[middle]) { + if (msgnum == CCC->cached_msglist[middle]) { return om_ok; } if (msgnum > CC->cached_msglist[middle]) { @@ -1641,14 +1856,17 @@ int CtdlOutputMsg(long msg_num, /* message number (local) to fetch */ 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; - int retcode = om_no_such_msg; + int retcode = CIT_OK; struct encapmsg encap; int r; - syslog(LOG_DEBUG, "CtdlOutputMsg(msgnum=%ld, mode=%d, section=%s)\n", + MSG_syslog(LOG_DEBUG, "CtdlOutputMsg(msgnum=%ld, mode=%d, section=%s)\n", msg_num, mode, (section ? section : "<>") ); @@ -1676,8 +1894,8 @@ int CtdlOutputMsg(long msg_num, /* message number (local) to fetch */ r = check_cached_msglist(msg_num); } if (r != om_ok) { - syslog(LOG_DEBUG, "Security check fail: message %ld is not in %s\n", - msg_num, CC->room.QRname + MSG_syslog(LOG_DEBUG, "Security check fail: message %ld is not in %s\n", + msg_num, CCC->room.QRname ); if (do_proto) { if (r == om_access_denied) { @@ -1713,11 +1931,22 @@ int CtdlOutputMsg(long msg_num, /* message number (local) to fetch */ if (section) if (!IsEmptyStr(section)) if (strcmp(section, "0")) { memset(&encap, 0, sizeof encap); safestrncpy(encap.desired_section, section, sizeof encap.desired_section); - mime_parser(TheMessage->cm_fields['M'], + mime_parser(TheMessage->cm_fields[eMesageText], NULL, *extract_encapsulated_message, NULL, NULL, (void *)&encap, 0 ); + + 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; @@ -1731,18 +1960,33 @@ int CtdlOutputMsg(long msg_num, /* message number (local) to fetch */ * encapsulated message instead of the top-level * message. Isn't that neat? */ - } else { - if (do_proto) cprintf("%d msg %ld has no part %s\n", - ERROR + MESSAGE_NOT_FOUND, msg_num, section); + if (do_proto) { + cprintf("%d msg %ld has no part %s\n", + ERROR + MESSAGE_NOT_FOUND, + msg_num, + section); + } retcode = om_no_such_msg; } } /* Ok, output the message now */ - retcode = CtdlOutputPreLoadedMsg(TheMessage, mode, headers_only, do_proto, crlf, flags); + 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); @@ -1751,6 +1995,7 @@ int CtdlOutputMsg(long msg_num, /* message number (local) to fetch */ char *qp_encode_email_addrs(char *source) { + struct CitContext *CCC = CC; char *user, *node, *name; const char headerStr[] = "=?UTF-8?Q?"; char *Encoded; @@ -1769,8 +2014,8 @@ char *qp_encode_email_addrs(char *source) if (source == NULL) return source; if (IsEmptyStr(source)) return source; - cit_backtrace(); - syslog(LOG_DEBUG, "qp_encode_email_addrs: [%s]\n", source); + if (MessageDebugEnabled != 0) cit_backtrace(); + MSG_syslog(LOG_DEBUG, "qp_encode_email_addrs: [%s]\n", source); AddrPtr = malloc (sizeof (long) * nAddrPtrMax); AddrUtf8 = malloc (sizeof (long) * nAddrPtrMax); @@ -1903,16 +2148,15 @@ void OutputCtdlMsgHeaders( struct CtdlMessage *TheMessage, int do_proto) /* do Citadel protocol responses? */ { - char allkeys[30]; - int i, k, n; + int i; int suppress_f = 0; char buf[SIZ]; char display_name[256]; /* begin header processing loop for Citadel message format */ safestrncpy(display_name, "", sizeof display_name); - if (TheMessage->cm_fields['A']) { - strcpy(buf, TheMessage->cm_fields['A']); + if (!CM_IsEmpty(TheMessage, eAuthor)) { + strcpy(buf, TheMessage->cm_fields[eAuthor]); if (TheMessage->cm_anon_type == MES_ANONONLY) { safestrncpy(display_name, "****", sizeof display_name); } @@ -1936,35 +2180,37 @@ void OutputCtdlMsgHeaders( * local Citadel network. */ suppress_f = 0; - if (TheMessage->cm_fields['N'] != NULL) - if (!IsEmptyStr(TheMessage->cm_fields['N'])) - if (haschar(TheMessage->cm_fields['N'], '.') == 0) { - suppress_f = 1; - } + if (!CM_IsEmpty(TheMessage, eNodeName) && + (haschar(TheMessage->cm_fields[eNodeName], '.') == 0)) + { + suppress_f = 1; + } /* Now spew the header fields in the order we like them. */ - n = safestrncpy(allkeys, FORDER, sizeof allkeys); - for (i=0; icm_fields[k] != NULL) - && (msgkeys[k] != NULL) ) { - if ((k == 'V') || (k == 'R') || (k == 'Y')) { - sanitize_truncated_recipient(TheMessage->cm_fields[k]); + for (i=0; i< NDiskFields; ++i) { + eMsgField Field; + Field = FieldOrder[i]; + if (Field != eMesageText) { + if ( (!CM_IsEmpty(TheMessage, Field)) + && (msgkeys[Field] != NULL) ) { + if ((Field == eenVelopeTo) || + (Field == eRecipient) || + (Field == eCarbonCopY)) { + sanitize_truncated_recipient(TheMessage->cm_fields[Field]); } - if (k == 'A') { + if (Field == eAuthor) { if (do_proto) cprintf("%s=%s\n", - msgkeys[k], + msgkeys[Field], display_name); } - else if ((k == 'F') && (suppress_f)) { + else if ((Field == erFc822Addr) && (suppress_f)) { /* do nothing */ } /* Masquerade display name if needed */ else { if (do_proto) cprintf("%s=%s\n", - msgkeys[k], - TheMessage->cm_fields[k] + msgkeys[Field], + TheMessage->cm_fields[Field] ); } } @@ -1995,7 +2241,7 @@ void OutputRFC822MsgHeaders( if (TheMessage->cm_fields[i]) { mptr = mpptr = TheMessage->cm_fields[i]; - if (i == 'A') { + if (i == eAuthor) { safestrncpy(luser, mptr, sizeof_luser); safestrncpy(suser, mptr, sizeof_suser); } @@ -2009,7 +2255,7 @@ void OutputRFC822MsgHeaders( else if (i == 'P') { cprintf("Return-Path: %s%s", mptr, nl); } - else if (i == 'L') { + else if (i == eListID) { cprintf("List-ID: %s%s", mptr, nl); } else if (i == 'V') { @@ -2027,7 +2273,7 @@ void OutputRFC822MsgHeaders( } else if (i == 'I') safestrncpy(mid, mptr, sizeof_mid); /// TODO: detect @ here and copy @nodename in if not found. - else if (i == 'F') + else if (i == erFc822Addr) safestrncpy(fuser, mptr, sizeof_fuser); /* else if (i == 'O') cprintf("X-Citadel-Room: %s%s", @@ -2071,7 +2317,7 @@ void OutputRFC822MsgHeaders( } } } - else if (i == 'K') { + else if (i == eReplyTo) { hptr = mptr; while ((*hptr != '\0') && isspace(*hptr)) hptr ++; @@ -2103,7 +2349,7 @@ void Dump_RFC822HeadersBody( int nllen = strlen(nl); char *mptr; - mptr = TheMessage->cm_fields['M']; + mptr = TheMessage->cm_fields[eMesageText]; prev_ch = '\0'; @@ -2154,7 +2400,8 @@ void Dump_RFC822HeadersBody( if (outlen > 1000) { if (client_write(outbuf, outlen) == -1) { - syslog(LOG_ERR, "Dump_RFC822HeadersBody(): aborting due to write failure.\n"); + struct CitContext *CCC = CC; + MSGM_syslog(LOG_ERR, "Dump_RFC822HeadersBody(): aborting due to write failure.\n"); return; } outlen = 0; @@ -2162,7 +2409,6 @@ void Dump_RFC822HeadersBody( } if (outlen > 0) { client_write(outbuf, outlen); - outlen = 0; } } @@ -2184,7 +2430,7 @@ void DumpFormatFixed( int nllen = strlen (nl); char *mptr; - mptr = TheMessage->cm_fields['M']; + mptr = TheMessage->cm_fields[eMesageText]; if (mode == MT_MIME) { cprintf("Content-type: text/plain\n\n"); @@ -2225,7 +2471,8 @@ void DumpFormatFixed( if (client_write(buf, buflen) == -1) { - syslog(LOG_ERR, "DumpFormatFixed(): aborting due to write failure.\n"); + struct CitContext *CCC = CC; + MSGM_syslog(LOG_ERR, "DumpFormatFixed(): aborting due to write failure.\n"); return; } *buf = '\0'; @@ -2252,6 +2499,7 @@ int CtdlOutputPreLoadedMsg( int crlf, /* Use CRLF newlines instead of LF? */ int flags /* should the bessage be exported clean? */ ) { + struct CitContext *CCC = CC; int i; char *mptr = NULL; const char *nl; /* newline string */ @@ -2267,16 +2515,16 @@ int CtdlOutputPreLoadedMsg( char snode[100]; char mid[100]; - syslog(LOG_DEBUG, "CtdlOutputPreLoadedMsg(TheMessage=%s, %d, %d, %d, %d\n", - ((TheMessage == NULL) ? "NULL" : "not null"), - mode, headers_only, do_proto, crlf); + MSG_syslog(LOG_DEBUG, "CtdlOutputPreLoadedMsg(TheMessage=%s, %d, %d, %d, %d\n", + ((TheMessage == NULL) ? "NULL" : "not null"), + mode, headers_only, do_proto, crlf); strcpy(mid, "unknown"); nl = (crlf ? "\r\n" : "\n"); if (!is_valid_message(TheMessage)) { - syslog(LOG_ERR, - "ERROR: invalid preloaded message for output\n"); + MSGM_syslog(LOG_ERR, + "ERROR: invalid preloaded message for output\n"); cit_backtrace (); return(om_no_such_msg); } @@ -2284,8 +2532,8 @@ int CtdlOutputPreLoadedMsg( /* Suppress envelope recipients if required to avoid disclosing BCC addresses. * Pad it with spaces in order to avoid changing the RFC822 length of the message. */ - if ( (flags & SUPPRESS_ENV_TO) && (TheMessage->cm_fields['V'] != NULL) ) { - memset(TheMessage->cm_fields['V'], ' ', strlen(TheMessage->cm_fields['V'])); + if ( (flags & SUPPRESS_ENV_TO) && (!CM_IsEmpty(TheMessage, eenVelopeTo)) ) { + memset(TheMessage->cm_fields[eenVelopeTo], ' ', strlen(TheMessage->cm_fields[eenVelopeTo])); } /* Are we downloading a MIME component? */ @@ -2294,25 +2542,25 @@ int CtdlOutputPreLoadedMsg( if (do_proto) cprintf("%d This is not a MIME message.\n", ERROR + ILLEGAL_VALUE); - } else if (CC->download_fp != NULL) { + } else if (CCC->download_fp != NULL) { if (do_proto) cprintf( "%d You already have a download open.\n", 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 */ - if (CC->download_fp == NULL) { + if (CCC->download_fp == NULL) { if (do_proto) cprintf( "%d Section %s not found.\n", ERROR + FILE_NOT_FOUND, - CC->download_desired_section); + CCC->download_desired_section); } } - return((CC->download_fp != NULL) ? om_ok : om_mime_error); + return((CCC->download_fp != NULL) ? om_ok : om_mime_error); } /* MT_SPEW_SECTION is like MT_DOWNLOAD except it outputs the whole MIME part @@ -2327,7 +2575,7 @@ int CtdlOutputPreLoadedMsg( /* Parse the message text component */ int found_it = 0; - mptr = TheMessage->cm_fields['M']; + mptr = TheMessage->cm_fields[eMesageText]; mime_parser(mptr, NULL, *mime_spew_section, NULL, NULL, (void *)&found_it, 0); /* If section wasn't found, print an error */ @@ -2335,10 +2583,10 @@ int CtdlOutputPreLoadedMsg( if (do_proto) cprintf( "%d Section %s not found.\n", ERROR + FILE_NOT_FOUND, - CC->download_desired_section); + CCC->download_desired_section); } } - return((CC->download_fp != NULL) ? om_ok : om_mime_error); + return((CCC->download_fp != NULL) ? om_ok : om_mime_error); } /* now for the user-mode message reading loops */ @@ -2425,7 +2673,7 @@ START_TEXT: /* Tell the client about the MIME parts in this message */ if (TheMessage->cm_format_type == FMT_RFC822) { if ( (mode == MT_CITADEL) || (mode == MT_MIME) ) { - mptr = TheMessage->cm_fields['M']; + mptr = TheMessage->cm_fields[eMesageText]; memset(&ma, 0, sizeof(struct ma_info)); mime_parser(mptr, NULL, (do_proto ? *list_this_part : NULL), @@ -2466,7 +2714,7 @@ START_TEXT: * message to the reader's screen width. */ if (TheMessage->cm_format_type == FMT_CITADEL) { - mptr = TheMessage->cm_fields['M']; + mptr = TheMessage->cm_fields[eMesageText]; if (mode == MT_MIME) { cprintf("Content-type: text/x-citadel-variformat\n\n"); @@ -2486,7 +2734,7 @@ START_TEXT: ma.use_fo_hooks = 0; strcpy(ma.chosen_part, "1"); ma.chosen_pref = 9999; - ma.dont_decode = CC->msg4_dont_decode; + ma.dont_decode = CCC->msg4_dont_decode; mime_parser(mptr, NULL, *choose_preferred, *fixed_output_pre, *fixed_output_post, (void *)&ma, 1); @@ -2519,7 +2767,7 @@ void cmd_msg0(char *cmdbuf) 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; } @@ -2535,7 +2783,7 @@ void cmd_msg2(char *cmdbuf) 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); } @@ -2589,7 +2837,7 @@ void cmd_msg4(char *cmdbuf) 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); } @@ -2622,7 +2870,7 @@ void cmd_opna(char *cmdbuf) 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); } @@ -2638,8 +2886,8 @@ void cmd_dlat(char *cmdbuf) 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); +} /* @@ -2656,6 +2904,7 @@ void cmd_dlat(char *cmdbuf) int CtdlSaveMsgPointersInRoom(char *roomname, long newmsgidlist[], int num_newmsgs, int do_repl_check, struct CtdlMessage *supplied_msg, int suppress_refcount_adj ) { + struct CitContext *CCC = CC; int i, j, unique; char hold_rm[ROOMNAMELEN]; struct cdbdata *cdbfr; @@ -2669,12 +2918,12 @@ int CtdlSaveMsgPointersInRoom(char *roomname, long newmsgidlist[], int num_newms long *msgs_to_be_merged = NULL; int num_msgs_to_be_merged = 0; - syslog(LOG_DEBUG, - "CtdlSaveMsgPointersInRoom(room=%s, num_msgs=%d, repl=%d, suppress_rca=%d)\n", - roomname, num_newmsgs, do_repl_check, suppress_refcount_adj + MSG_syslog(LOG_DEBUG, + "CtdlSaveMsgPointersInRoom(room=%s, num_msgs=%d, repl=%d, suppress_rca=%d)\n", + roomname, num_newmsgs, do_repl_check, suppress_refcount_adj ); - strcpy(hold_rm, CC->room.QRname); + strcpy(hold_rm, CCC->room.QRname); /* Sanity checks */ if (newmsgidlist == NULL) return(ERROR + INTERNAL_ERROR); @@ -2682,10 +2931,10 @@ int CtdlSaveMsgPointersInRoom(char *roomname, long newmsgidlist[], int num_newms if (num_newmsgs > 1) supplied_msg = NULL; /* Now the regular stuff */ - if (CtdlGetRoomLock(&CC->room, - ((roomname != NULL) ? roomname : CC->room.QRname) ) + if (CtdlGetRoomLock(&CCC->room, + ((roomname != NULL) ? roomname : CCC->room.QRname) ) != 0) { - syslog(LOG_ERR, "No such room <%s>\n", roomname); + MSG_syslog(LOG_ERR, "No such room <%s>\n", roomname); return(ERROR + ROOM_NOT_FOUND); } @@ -2694,7 +2943,7 @@ int CtdlSaveMsgPointersInRoom(char *roomname, long newmsgidlist[], int num_newms num_msgs_to_be_merged = 0; - cdbfr = cdb_fetch(CDB_MSGLISTS, &CC->room.QRnumber, sizeof(long)); + cdbfr = cdb_fetch(CDB_MSGLISTS, &CCC->room.QRnumber, sizeof(long)); if (cdbfr == NULL) { msglist = NULL; num_msgs = 0; @@ -2722,14 +2971,16 @@ int CtdlSaveMsgPointersInRoom(char *roomname, long newmsgidlist[], int num_newms } } - syslog(LOG_DEBUG, "%d unique messages to be merged\n", num_msgs_to_be_merged); + MSG_syslog(LOG_DEBUG, "%d unique messages to be merged\n", num_msgs_to_be_merged); /* * Now merge the new messages */ msglist = realloc(msglist, (sizeof(long) * (num_msgs + num_msgs_to_be_merged)) ); if (msglist == NULL) { - syslog(LOG_ALERT, "ERROR: can't realloc message list!\n"); + MSGM_syslog(LOG_ALERT, "ERROR: can't realloc message list!\n"); + free(msgs_to_be_merged); + return (ERROR + INTERNAL_ERROR); } memcpy(&msglist[num_msgs], msgs_to_be_merged, (sizeof(long) * num_msgs_to_be_merged) ); num_msgs += num_msgs_to_be_merged; @@ -2741,19 +2992,19 @@ int CtdlSaveMsgPointersInRoom(char *roomname, long newmsgidlist[], int num_newms highest_msg = msglist[num_msgs - 1]; /* Write it back to disk. */ - cdb_store(CDB_MSGLISTS, &CC->room.QRnumber, (int)sizeof(long), + cdb_store(CDB_MSGLISTS, &CCC->room.QRnumber, (int)sizeof(long), msglist, (int)(num_msgs * sizeof(long))); /* Free up the memory we used. */ free(msglist); /* Update the highest-message pointer and unlock the room. */ - CC->room.QRhighest = highest_msg; - CtdlPutRoomLock(&CC->room); + CCC->room.QRhighest = highest_msg; + CtdlPutRoomLock(&CCC->room); /* Perform replication checks if necessary */ - if ( (DoesThisRoomNeedEuidIndexing(&CC->room)) && (do_repl_check) ) { - syslog(LOG_DEBUG, "CtdlSaveMsgPointerInRoom() doing repl checks\n"); + if ( (DoesThisRoomNeedEuidIndexing(&CCC->room)) && (do_repl_check) ) { + MSGM_syslog(LOG_DEBUG, "CtdlSaveMsgPointerInRoom() doing repl checks\n"); for (i=0; icm_fields['E'] != NULL) { - index_message_by_euid(msg->cm_fields['E'], &CC->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 */ @@ -2783,20 +3034,18 @@ int CtdlSaveMsgPointersInRoom(char *roomname, long newmsgidlist[], int num_newms } else { - syslog(LOG_DEBUG, "CtdlSaveMsgPointerInRoom() skips repl checks\n"); + MSGM_syslog(LOG_DEBUG, "CtdlSaveMsgPointerInRoom() skips repl checks\n"); } /* Submit this room for processing by hooks */ - PerformRoomHooks(&CC->room); + PerformRoomHooks(&CCC->room); /* Go back to the room we were in before we wandered here... */ - CtdlGetRoom(&CC->room, hold_rm); + CtdlGetRoom(&CCC->room, hold_rm); /* Bump the reference count for all messages which were merged */ if (!suppress_refcount_adj) { - for (i=0; icm_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; } } @@ -2864,7 +3115,7 @@ long send_message(struct CtdlMessage *msg) { serialize_message(&smr, msg); if (is_bigmsg) { - msg->cm_fields['M'] = holdM; + msg->cm_fields[eMesageText] = holdM; } if (smr.len == 0) { @@ -2876,7 +3127,7 @@ long send_message(struct CtdlMessage *msg) { /* Write our little bundle of joy into the message base */ if (cdb_store(CDB_MSGMAIN, &newmsgid, (int)sizeof(long), smr.ser, smr.len) < 0) { - syslog(LOG_ERR, "Can't store message\n"); + MSGM_syslog(LOG_ERR, "Can't store message\n"); retval = 0L; } else { if (is_bigmsg) { @@ -2911,29 +3162,35 @@ long send_message(struct CtdlMessage *msg) { void serialize_message(struct ser_ret *ret, /* return values */ struct CtdlMessage *msg) /* unserialized msg */ { + struct CitContext *CCC = CC; size_t wlen, fieldlen; int i; - static char *forder = FORDER; + long lengths[NDiskFields]; + + memset(lengths, 0, sizeof(lengths)); /* * Check for valid message format */ if (is_valid_message(msg) == 0) { - syslog(LOG_ERR, "serialize_message() aborting due to invalid message\n"); + MSGM_syslog(LOG_ERR, "serialize_message() aborting due to invalid message\n"); ret->len = 0; ret->ser = NULL; return; } 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) { - syslog(LOG_ERR, "serialize_message() malloc(%ld) failed: %s\n", - (long)ret->len, strerror(errno)); + MSG_syslog(LOG_ERR, "serialize_message() malloc(%ld) failed: %s\n", + (long)ret->len, strerror(errno)); ret->len = 0; ret->ser = NULL; return; @@ -2944,81 +3201,52 @@ void serialize_message(struct ser_ret *ret, /* return values */ ret->ser[2] = msg->cm_format_type; wlen = 3; - for (i=0; i<26; ++i) if (msg->cm_fields[(int)forder[i]] != NULL) { - fieldlen = strlen(msg->cm_fields[(int)forder[i]]); - ret->ser[wlen++] = (char)forder[i]; - safestrncpy((char *)&ret->ser[wlen], msg->cm_fields[(int)forder[i]], fieldlen+1); - wlen = wlen + fieldlen + 1; - } - if (ret->len != wlen) syslog(LOG_ERR, "ERROR: len=%ld wlen=%ld\n", - (long)ret->len, (long)wlen); - - return; -} + 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); -/* - * Serialize a struct CtdlMessage into the format used on disk and network. - * - * 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 - * serialized message in memory. THE LATTER MUST BE FREED BY THE CALLER. - */ -void dump_message(struct CtdlMessage *msg, /* unserialized msg */ - long Siz) /* how many chars ? */ -{ - int i; - static char *forder = FORDER; - char *buf; + wlen = wlen + fieldlen + 1; + } - /* - * Check for valid message format - */ - if (is_valid_message(msg) == 0) { - syslog(LOG_ERR, "dump_message() aborting due to invalid message\n"); - return; + if (ret->len != wlen) { + MSG_syslog(LOG_ERR, "ERROR: len=%ld wlen=%ld\n", + (long)ret->len, (long)wlen); } - buf = (char*) malloc (Siz + 1); - - for (i=0; i<26; ++i) if (msg->cm_fields[(int)forder[i]] != NULL) { - snprintf (buf, Siz, " msg[%c] = %s ...\n", (char) forder[i], - msg->cm_fields[(int)forder[i]]); - if (client_write (buf, strlen(buf)) == -1) - { - syslog(LOG_ERR, "dump_message(): aborting due to write failure.\n"); - return; - } - } - return; } - /* * 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) { + struct CitContext *CCC = CC; long old_msgnum = (-1L); - if (DoesThisRoomNeedEuidIndexing(&CC->room) == 0) return; + if (DoesThisRoomNeedEuidIndexing(&CCC->room) == 0) return; - syslog(LOG_DEBUG, "Performing replication checks in <%s>\n", - CC->room.QRname); + MSG_syslog(LOG_DEBUG, "Performing replication checks in <%s>\n", + CCC->room.QRname); /* 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; - /*syslog(LOG_DEBUG, "Exclusive ID: <%s> for room <%s>\n", - msg->cm_fields['E'], CC->room.QRname);*/ + if (CM_IsEmpty(msg, eExclusiveID)) return; + + /*MSG_syslog(LOG_DEBUG, "Exclusive ID: <%s> for room <%s>\n", + msg->cm_fields[eExclusiveID], CCC->room.QRname);*/ - old_msgnum = CtdlLocateMessageByEuid(msg->cm_fields['E'], &CC->room); + old_msgnum = CtdlLocateMessageByEuid(msg->cm_fields[eExclusiveID], &CCC->room); if (old_msgnum > 0L) { - syslog(LOG_DEBUG, "ReplicationChecks() replacing message %ld\n", old_msgnum); - CtdlDeleteMessages(CC->room.QRname, &old_msgnum, 1, ""); + MSG_syslog(LOG_DEBUG, "ReplicationChecks() replacing message %ld\n", old_msgnum); + CtdlDeleteMessages(CCC->room.QRname, &old_msgnum, 1, ""); } } @@ -3034,12 +3262,12 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ ) { char submit_filename[128]; - char generated_timestamp[32]; char hold_rm[ROOMNAMELEN]; char actual_rm[ROOMNAMELEN]; char force_room[ROOMNAMELEN]; char content_type[SIZ]; /* We have to learn this */ char recipient[SIZ]; + const char *room; long newmsgid; const char *mptr = NULL; struct ctdluser userbuf; @@ -3060,43 +3288,42 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ char bounce_to[1024] = ""; int rv = 0; - syslog(LOG_DEBUG, "CtdlSubmitMsg() called\n"); + MSGM_syslog(LOG_DEBUG, "CtdlSubmitMsg() called\n"); if (is_valid_message(msg) == 0) return(-1); /* self check */ /* If this message has no timestamp, we take the liberty of * giving it one, right now. */ - if (msg->cm_fields['T'] == NULL) { - snprintf(generated_timestamp, sizeof generated_timestamp, "%ld", (long)time(NULL)); - msg->cm_fields['T'] = strdup(generated_timestamp); + if (CM_IsEmpty(msg, eTimestamp)) { + CM_SetFieldLONG(msg, eTimestamp, time(NULL)); } /* If this message has no path, we generate one. */ - if (msg->cm_fields['P'] == NULL) { - if (msg->cm_fields['A'] != NULL) { - msg->cm_fields['P'] = strdup(msg->cm_fields['A']); - for (a=0; !IsEmptyStr(&msg->cm_fields['P'][a]); ++a) { - if (isspace(msg->cm_fields['P'][a])) { - msg->cm_fields['P'][a] = ' '; + if (CM_IsEmpty(msg, eMessagePath)) { + if (!CM_IsEmpty(msg, eAuthor)) { + CM_CopyField(msg, eMessagePath, eAuthor); + for (a=0; !IsEmptyStr(&msg->cm_fields[eMessagePath][a]); ++a) { + if (isspace(msg->cm_fields[eMessagePath][a])) { + msg->cm_fields[eMessagePath][a] = ' '; } } } else { - msg->cm_fields['P'] = strdup("unknown"); + CM_SetField(msg, eMessagePath, HKEY("unknown")); } } if (force == NULL) { - strcpy(force_room, ""); + force_room[0] = '\0'; } else { strcpy(force_room, force); } /* Learn about what's inside, because it's what's inside that counts */ - if (msg->cm_fields['M'] == NULL) { - syslog(LOG_ERR, "ERROR: attempt to save message with NULL body\n"); + if (CM_IsEmpty(msg, eMesageText)) { + MSGM_syslog(LOG_ERR, "ERROR: attempt to save message with NULL body\n"); return(-2); } @@ -3109,7 +3336,7 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ break; case 4: strcpy(content_type, "text/plain"); - mptr = bmstrcasestr(msg->cm_fields['M'], "Content-type:"); + mptr = bmstrcasestr(msg->cm_fields[eMesageText], "Content-type:"); if (mptr != NULL) { char *aptr; safestrncpy(content_type, &mptr[13], sizeof content_type); @@ -3128,7 +3355,8 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ } /* Goto the correct room */ - syslog(LOG_DEBUG, "Selected room %s\n", (recps) ? CCC->room.QRname : SENTITEMS); + room = (recps) ? CCC->room.QRname : SENTITEMS; + MSG_syslog(LOG_DEBUG, "Selected room %s\n", room); strcpy(hold_rm, CCC->room.QRname); strcpy(actual_rm, CCC->room.QRname); if (recps != NULL) { @@ -3140,7 +3368,7 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ if (CCC->user.axlevel == AxProbU) { strcpy(hold_rm, actual_rm); strcpy(actual_rm, config.c_twitroom); - syslog(LOG_DEBUG, "Diverting to twit room\n"); + MSGM_syslog(LOG_DEBUG, "Diverting to twit room\n"); } } @@ -3149,7 +3377,7 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ strcpy(actual_rm, force_room); } - syslog(LOG_DEBUG, "Final selection: %s\n", actual_rm); + MSG_syslog(LOG_INFO, "Final selection: %s (%s)\n", actual_rm, room); if (strcasecmp(actual_rm, CCC->room.QRname)) { /* CtdlGetRoom(&CCC->room, actual_rm); */ CtdlUserGoto(actual_rm, 0, 1, NULL, NULL); @@ -3158,12 +3386,12 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ /* * If this message has no O (room) field, generate one. */ - if (msg->cm_fields['O'] == NULL) { - msg->cm_fields['O'] = strdup(CCC->room.QRname); + if (CM_IsEmpty(msg, eOriginalRoom)) { + CM_SetField(msg, eOriginalRoom, CCC->room.QRname, strlen(CCC->room.QRname)); } /* Perform "before save" hooks (aborting if any return nonzero) */ - syslog(LOG_DEBUG, "Performing before-save hooks\n"); + MSGM_syslog(LOG_DEBUG, "Performing before-save hooks\n"); if (PerformMessageHooks(msg, EVT_BEFORESAVE) > 0) return(-3); /* @@ -3175,7 +3403,7 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ } /* Save it to disk */ - syslog(LOG_DEBUG, "Saving to disk\n"); + MSGM_syslog(LOG_DEBUG, "Saving to disk\n"); newmsgid = send_message(msg); if (newmsgid <= 0L) return(-5); @@ -3183,7 +3411,7 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ * be a critical section because nobody else knows about this message * yet. */ - syslog(LOG_DEBUG, "Creating MetaData record\n"); + MSGM_syslog(LOG_DEBUG, "Creating MetaData record\n"); memset(&smi, 0, sizeof(struct MetaData)); smi.meta_msgnum = newmsgid; smi.meta_refcount = 0; @@ -3201,7 +3429,7 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ * message to attach to the journalized copy. */ if (CCC->redirect_buffer != NULL) { - syslog(LOG_ALERT, "CCC->redirect_buffer is not NULL during message submission!\n"); + MSGM_syslog(LOG_ALERT, "CCC->redirect_buffer is not NULL during message submission!\n"); abort(); } CCC->redirect_buffer = NewStrBufPlain(NULL, SIZ); @@ -3213,7 +3441,7 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ PutMetaData(&smi); /* Now figure out where to store the pointers */ - syslog(LOG_DEBUG, "Storing pointers\n"); + MSGM_syslog(LOG_DEBUG, "Storing pointers\n"); /* If this is being done by the networker delivering a private * message, we want to BYPASS saving the sender's copy (because there @@ -3221,7 +3449,7 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ */ if ((!CCC->internal_pgm) || (recps == NULL)) { if (CtdlSaveMsgPointerInRoom(actual_rm, newmsgid, 1, msg) != 0) { - syslog(LOG_ERR, "ERROR saving message pointer!\n"); + MSGM_syslog(LOG_ERR, "ERROR saving message pointer!\n"); CtdlSaveMsgPointerInRoom(config.c_aideroom, newmsgid, 0, msg); } } @@ -3236,12 +3464,12 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ for (i=0; irecp_room, '|'); ++i) { extract_token(recipient, recps->recp_room, i, '|', sizeof recipient); - syslog(LOG_DEBUG, "Delivering to room <%s>\n", recipient);///// xxxx + MSG_syslog(LOG_DEBUG, "Delivering to room <%s>\n", recipient);///// xxxx CtdlSaveMsgPointerInRoom(recipient, newmsgid, 0, msg); } /* Bump this user's messages posted counter. */ - syslog(LOG_DEBUG, "Updating user\n"); + MSGM_syslog(LOG_DEBUG, "Updating user\n"); CtdlGetUserLock(&CCC->user, CCC->curr_user); CCC->user.posted = CCC->user.posted + 1; CtdlPutUserLock(&CCC->user); @@ -3254,7 +3482,7 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ snprintf(bounce_to, sizeof bounce_to, "%s@%s", CCC->user.fullname, config.c_nodename); } else { - snprintf(bounce_to, sizeof bounce_to, "%s@%s", msg->cm_fields['A'], msg->cm_fields['N']); + snprintf(bounce_to, sizeof bounce_to, "%s@%s", msg->cm_fields[eAuthor], msg->cm_fields[eNodeName]); } /* If this is private, local mail, make a copy in the @@ -3262,9 +3490,11 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ */ if ((recps != NULL) && (recps->num_local > 0)) for (i=0; irecp_local, '|'); ++i) { - extract_token(recipient, recps->recp_local, i, - '|', sizeof recipient); - syslog(LOG_DEBUG, "Delivering private local mail to <%s>\n", + 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) { CtdlMailboxName(actual_rm, sizeof actual_rm, &userbuf, MAILROOM); @@ -3274,13 +3504,17 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ /* Generate a instruction message for the Funambol notification * server, in the same style as the SMTP queue */ + long instrlen; instr_alloc = 1024; instr = malloc(instr_alloc); - snprintf(instr, instr_alloc, - "Content-type: %s\n\nmsgid|%ld\nsubmitted|%ld\n" - "bounceto|%s\n", - SPOOLMIME, newmsgid, (long)time(NULL), - bounce_to + instrlen = snprintf( + instr, instr_alloc, + "Content-type: %s\n\nmsgid|%ld\nsubmitted|%ld\n" + "bounceto|%s\n", + SPOOLMIME, + newmsgid, + (long)time(NULL), //todo: time() is expensive! + bounce_to ); imsg = malloc(sizeof(struct CtdlMessage)); @@ -3288,29 +3522,27 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ imsg->cm_magic = CTDLMESSAGE_MAGIC; imsg->cm_anon_type = MES_NORMAL; imsg->cm_format_type = FMT_RFC822; - imsg->cm_fields['U'] = strdup("QMSG"); - imsg->cm_fields['A'] = strdup("Citadel"); - imsg->cm_fields['J'] = strdup("do not journal"); - imsg->cm_fields['M'] = instr; /* imsg owns this memory now */ - imsg->cm_fields['2'] = strdup(recipient); + CM_SetField(imsg, eMsgSubject, HKEY("QMSG")); + CM_SetField(imsg, eAuthor, HKEY("Citadel")); + CM_SetField(imsg, eJournal, HKEY("do not journal")); + CM_SetAsField(imsg, eMesageText, &instr, instrlen); + CM_SetField(imsg, eExtnotify, recipient, recipientlen); CtdlSubmitMsg(imsg, NULL, FNBL_QUEUE_ROOM, 0); CtdlFreeMessage(imsg); } } else { - syslog(LOG_DEBUG, "No user <%s>\n", recipient); + MSG_syslog(LOG_DEBUG, "No user <%s>\n", recipient); CtdlSaveMsgPointerInRoom(config.c_aideroom, newmsgid, 0, msg); } } /* Perform "after save" hooks */ - 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); + MSGM_syslog(LOG_DEBUG, "Performing after-save hooks\n"); + + 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 @@ -3325,12 +3557,12 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ extract_token(recipient, recps->recp_ignet, i, '|', sizeof recipient); - hold_R = msg->cm_fields['R']; - hold_D = msg->cm_fields['D']; - msg->cm_fields['R'] = malloc(SIZ); - msg->cm_fields['D'] = malloc(128); - extract_token(msg->cm_fields['R'], recipient, 0, '@', SIZ); - extract_token(msg->cm_fields['D'], recipient, 1, '@', 128); + hold_R = msg->cm_fields[eRecipient]; + hold_D = msg->cm_fields[eDestination]; + msg->cm_fields[eRecipient] = malloc(SIZ); + msg->cm_fields[eDestination] = malloc(128); + extract_token(msg->cm_fields[eRecipient], recipient, 0, '@', SIZ); + extract_token(msg->cm_fields[eDestination], recipient, 1, '@', 128); serialize_message(&smr, msg); if (smr.len > 0) { @@ -3342,22 +3574,22 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ if (network_fp != NULL) { rv = fwrite(smr.ser, smr.len, 1, network_fp); if (rv == -1) { - syslog(LOG_EMERG, "CtdlSubmitMsg(): Couldn't write network spool file: %s\n", - strerror(errno)); + MSG_syslog(LOG_EMERG, "CtdlSubmitMsg(): Couldn't write network spool file: %s\n", + strerror(errno)); } fclose(network_fp); } 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 */ - syslog(LOG_DEBUG, "Returning to original room %s\n", hold_rm); + MSG_syslog(LOG_DEBUG, "Returning to original room %s\n", hold_rm); if (strcasecmp(hold_rm, CCC->room.QRname)) CtdlUserGoto(hold_rm, 0, 1, NULL, NULL); @@ -3370,7 +3602,7 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ StrBuf *SpoolMsg = NewStrBuf(); long nTokens; - syslog(LOG_DEBUG, "Generating delivery instructions\n"); + MSGM_syslog(LOG_DEBUG, "Generating delivery instructions\n"); StrBufPrintf(SpoolMsg, "Content-type: "SPOOLMIME"\n" @@ -3409,10 +3641,10 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ imsg->cm_magic = CTDLMESSAGE_MAGIC; imsg->cm_anon_type = MES_NORMAL; imsg->cm_format_type = FMT_RFC822; - imsg->cm_fields['U'] = strdup("QMSG"); - imsg->cm_fields['A'] = strdup("Citadel"); - imsg->cm_fields['J'] = strdup("do not journal"); - imsg->cm_fields['M'] = SmashStrBuf(&SpoolMsg); /* imsg owns this memory now */ + imsg->cm_fields[eMsgSubject] = strdup("QMSG"); + imsg->cm_fields[eAuthor] = strdup("Citadel"); + imsg->cm_fields[eJournal] = strdup("do not journal"); + imsg->cm_fields[eMesageText] = SmashStrBuf(&SpoolMsg); /* imsg owns this memory now */ CtdlSubmitMsg(imsg, NULL, SMTP_SPOOLOUT_ROOM, QP_EADDR); CtdlFreeMessage(imsg); } @@ -3440,7 +3672,7 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ /* * Determine whether this message qualifies for journaling. */ - if (msg->cm_fields['J'] != NULL) { + if (!CM_IsEmpty(msg, eJournal)) { qualified_for_journaling = 0; } else { @@ -3474,18 +3706,16 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ } - -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; @@ -3497,35 +3727,98 @@ void quickie_message(const char *from, const char *fromaddr, char *to, char *roo 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); +} /* @@ -3534,7 +3827,7 @@ void quickie_message(const char *from, const char *fromaddr, char *to, char *roo 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 */ @@ -3551,8 +3844,7 @@ StrBuf *CtdlReadMessageBodyBuf(char *terminator, /* token signalling EOT */ 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? */ @@ -3615,7 +3907,7 @@ ReadAsyncMsg *NewAsyncMsg(const char *terminator, /* token signalling EOT */ 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 */ @@ -3638,8 +3930,7 @@ ReadAsyncMsg *NewAsyncMsg(const char *terminator, /* token signalling EOT */ 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 == '.')) { @@ -3772,7 +4063,7 @@ eReadState CtdlReadMessageBodyAsync(AsyncIO *IO) 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 */ @@ -3837,16 +4128,16 @@ struct CtdlMessage *CtdlMakeMessage( if (my_email == NULL) my_email = ""; if (!IsEmptyStr(my_email)) { - msg->cm_fields['P'] = strdup(my_email); + msg->cm_fields[eMessagePath] = strdup(my_email); } else { snprintf(buf, sizeof buf, "%s", author->fullname); - msg->cm_fields['P'] = strdup(buf); + msg->cm_fields[eMessagePath] = strdup(buf); } - convert_spaces_to_underscores(msg->cm_fields['P']); + convert_spaces_to_underscores(msg->cm_fields[eMessagePath]); snprintf(buf, sizeof buf, "%ld", (long)time(NULL)); /* timestamp */ - msg->cm_fields['T'] = strdup(buf); + msg->cm_fields[eTimestamp] = strdup(buf); if ((fake_name != NULL) && (fake_name[0])) { /* author */ FakeAuthor = NewStrBufPlain (fake_name, -1); @@ -3855,34 +4146,34 @@ struct CtdlMessage *CtdlMakeMessage( FakeAuthor = NewStrBufPlain (author->fullname, -1); } StrBufRFC2047encode(&FakeEncAuthor, FakeAuthor); - msg->cm_fields['A'] = SmashStrBuf(&FakeEncAuthor); + msg->cm_fields[eAuthor] = SmashStrBuf(&FakeEncAuthor); FreeStrBuf(&FakeAuthor); if (CC->room.QRflags & QR_MAILBOX) { /* room */ - msg->cm_fields['O'] = strdup(&CC->room.QRname[11]); + msg->cm_fields[eOriginalRoom] = strdup(&CC->room.QRname[11]); } else { - msg->cm_fields['O'] = strdup(CC->room.QRname); + msg->cm_fields[eOriginalRoom] = strdup(CC->room.QRname); } - msg->cm_fields['N'] = strdup(NODENAME); /* nodename */ - msg->cm_fields['H'] = strdup(HUMANNODE); /* hnodename */ + msg->cm_fields[eNodeName] = strdup(NODENAME); /* nodename */ + msg->cm_fields[eHumanNode] = strdup(HUMANNODE); /* hnodename */ if ((recipient != NULL) && (recipient[0] != 0)) { - msg->cm_fields['R'] = strdup(recipient); + msg->cm_fields[eRecipient] = strdup(recipient); } if ((recp_cc != NULL) && (recp_cc[0] != 0)) { - msg->cm_fields['Y'] = strdup(recp_cc); + msg->cm_fields[eCarbonCopY] = strdup(recp_cc); } if (dest_node[0] != 0) { - msg->cm_fields['D'] = strdup(dest_node); + msg->cm_fields[eDestination] = strdup(dest_node); } if (!IsEmptyStr(my_email)) { - msg->cm_fields['F'] = strdup(my_email); + msg->cm_fields[erFc822Addr] = strdup(my_email); } else if ( (author == &CC->user) && (!IsEmptyStr(CC->cs_inet_email)) ) { - msg->cm_fields['F'] = strdup(CC->cs_inet_email); + msg->cm_fields[erFc822Addr] = strdup(CC->cs_inet_email); } if (subject != NULL) { @@ -3898,40 +4189,35 @@ struct CtdlMessage *CtdlMakeMessage( (IsAscii = isascii(subject[i]) != 0 )) i++; if (IsAscii != 0) - msg->cm_fields['U'] = strdup(subject); + msg->cm_fields[eMsgSubject] = strdup(subject); else /* ok, we've got utf8 in the string. */ { - msg->cm_fields['U'] = rfc2047encode(subject, length); + msg->cm_fields[eMsgSubject] = rfc2047encode(subject, length); } } } if (supplied_euid != NULL) { - msg->cm_fields['E'] = strdup(supplied_euid); + msg->cm_fields[eExclusiveID] = strdup(supplied_euid); } if ((references != NULL) && (!IsEmptyStr(references))) { - if (msg->cm_fields['W'] != NULL) - free(msg->cm_fields['W']); - msg->cm_fields['W'] = strdup(references); + if (msg->cm_fields[eWeferences] != NULL) + free(msg->cm_fields[eWeferences]); + msg->cm_fields[eWeferences] = strdup(references); } if (preformatted_text != NULL) { - msg->cm_fields['M'] = preformatted_text; + msg->cm_fields[eMesageText] = preformatted_text; } else { - msg->cm_fields['M'] = CtdlReadMessageBody(HKEY("000"), config.c_maxmsglen, NULL, 0, 0); + msg->cm_fields[eMesageText] = CtdlReadMessageBody(HKEY("000"), config.c_maxmsglen, NULL, 0, 0); } return(msg); } -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 @@ -3966,7 +4252,7 @@ int CtdlDoIHavePermissionToPostInThisRoom( } 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); @@ -4022,7 +4308,7 @@ int CtdlCheckInternetMailPermission(struct ctdluser *who) { /* 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! */ @@ -4042,6 +4328,7 @@ int CtdlCheckInternetMailPermission(struct ctdluser *who) { struct recptypes *validate_recipients(const char *supplied_recipients, const char *RemoteIdentifier, int Flags) { + struct CitContext *CCC = CC; struct recptypes *ret; char *recipients = NULL; char *org_recp; @@ -4126,15 +4413,15 @@ struct recptypes *validate_recipients(const char *supplied_recipients, striplt(this_recp); if (IsEmptyStr(this_recp)) break; - syslog(LOG_DEBUG, "Evaluating recipient #%d: %s\n", num_recps, this_recp); + MSG_syslog(LOG_DEBUG, "Evaluating recipient #%d: %s\n", num_recps, this_recp); ++num_recps; strcpy(org_recp, this_recp); + alias(this_recp); + alias(this_recp); mailtype = alias(this_recp); - mailtype = alias(this_recp); - mailtype = alias(this_recp); - j = 0; - for (j=0; !IsEmptyStr(&this_recp[j]); ++j) { + + for (j = 0; !IsEmptyStr(&this_recp[j]); ++j) { if (this_recp[j]=='_') { this_recp_cooked[j] = ' '; } @@ -4159,8 +4446,8 @@ struct recptypes *validate_recipients(const char *supplied_recipients, && (!CtdlGetRoom(&tempQR, &this_recp_cooked[5])) ) { /* Save room so we can restore it later */ - tempQR2 = CC->room; - CC->room = tempQR; + tempQR2 = CCC->room; + CCC->room = tempQR; /* Check permissions to send mail to this room */ err = CtdlDoIHavePermissionToPostInThisRoom( @@ -4190,7 +4477,7 @@ struct recptypes *validate_recipients(const char *supplied_recipients, } /* Restore room in case something needs it */ - CC->room = tempQR2; + CCC->room = tempQR2; } else if (CtdlGetUser(&tempUS, this_recp) == 0) { @@ -4279,12 +4566,12 @@ struct recptypes *validate_recipients(const char *supplied_recipients, strcpy(ret->errormsg, "No recipients specified."); } - syslog(LOG_DEBUG, "validate_recipients()\n"); - syslog(LOG_DEBUG, " local: %d <%s>\n", ret->num_local, ret->recp_local); - syslog(LOG_DEBUG, " room: %d <%s>\n", ret->num_room, ret->recp_room); - syslog(LOG_DEBUG, " inet: %d <%s>\n", ret->num_internet, ret->recp_internet); - syslog(LOG_DEBUG, " ignet: %d <%s>\n", ret->num_ignet, ret->recp_ignet); - syslog(LOG_DEBUG, " error: %d <%s>\n", ret->num_error, ret->errormsg); + MSGM_syslog(LOG_DEBUG, "validate_recipients()\n"); + MSG_syslog(LOG_DEBUG, " local: %d <%s>\n", ret->num_local, ret->recp_local); + MSG_syslog(LOG_DEBUG, " room: %d <%s>\n", ret->num_room, ret->recp_room); + MSG_syslog(LOG_DEBUG, " inet: %d <%s>\n", ret->num_internet, ret->recp_internet); + MSG_syslog(LOG_DEBUG, " ignet: %d <%s>\n", ret->num_ignet, ret->recp_ignet); + MSG_syslog(LOG_DEBUG, " error: %d <%s>\n", ret->num_error, ret->errormsg); free(recipients); return(ret); @@ -4301,7 +4588,8 @@ void free_recipients(struct recptypes *valid) { } if (valid->recptypes_magic != RECPTYPES_MAGIC) { - syslog(LOG_EMERG, "Attempt to call free_recipients() on some other data type!\n"); + struct CitContext *CCC = CC; + MSGM_syslog(LOG_EMERG, "Attempt to call free_recipients() on some other data type!\n"); abort(); } @@ -4314,6 +4602,7 @@ void free_recipients(struct recptypes *valid) { if (valid->display_recp != NULL) free(valid->display_recp); if (valid->bounce_to != NULL) free(valid->bounce_to); if (valid->envelope_from != NULL) free(valid->envelope_from); + if (valid->sending_room != NULL) free(valid->sending_room); free(valid); } @@ -4345,7 +4634,6 @@ void cmd_ent0(char *entargs) char subject[SIZ]; int subject_required = 0; int do_confirm = 0; - int verbose_reply = 0; long msgnum; int i, j; char buf[256]; @@ -4364,7 +4652,6 @@ void cmd_ent0(char *entargs) do_confirm = extract_int(entargs, 6); extract_token(cc, entargs, 7, '|', sizeof cc); extract_token(bcc, entargs, 8, '|', sizeof bcc); - verbose_reply = extract_int(entargs, 9); switch(CC->room.QRdefaultview) { case VIEW_NOTES: case VIEW_WIKI: @@ -4612,32 +4899,26 @@ void cmd_ent0(char *entargs) * to the actual mail address so others get a valid * reply-to-header. */ - msg->cm_fields['V'] = strdup(valid->recp_orgroom); + msg->cm_fields[eenVelopeTo] = strdup(valid->recp_orgroom); } if (msg != NULL) { msgnum = CtdlSubmitMsg(msg, valid, "", QP_EADDR); - if (verbose_reply) - { - if (StrLength(CCC->StatusMessage)>0) - { - StrBufAppendBufPlain(CCC->StatusMessage, HKEY("\n000\n"), 0); - cputbuf(CCC->StatusMessage); - } - else - client_write(HKEY("\n000\n")); - } - if (do_confirm) { cprintf("%ld\n", msgnum); - if (msgnum >= 0L) { + + if (StrLength(CCC->StatusMessage) > 0) { + cprintf("%s\n", ChrPtr(CCC->StatusMessage)); + } + else if (msgnum >= 0L) { client_write(HKEY("Message accepted.\n")); } else { 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"); } @@ -4664,6 +4945,7 @@ int CtdlDeleteMessages(char *room_name, /* which room */ char *content_type /* or "" for any. regular expressions expected. */ ) { + struct CitContext *CCC = CC; struct ctdlroom qrbuf; struct cdbdata *cdbfr; long *msglist = NULL; @@ -4681,13 +4963,13 @@ int CtdlDeleteMessages(char *room_name, /* which room */ regcomp(&re, content_type, 0); need_to_free_re = 1; } - syslog(LOG_DEBUG, "CtdlDeleteMessages(%s, %d msgs, %s)\n", - room_name, num_dmsgnums, content_type); + 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) { - syslog(LOG_ERR, "CtdlDeleteMessages(): Room <%s> not found\n", - room_name); + MSG_syslog(LOG_ERR, " CtdlDeleteMessages(): Room <%s> not found\n", + room_name); if (need_to_free_re) regfree(&re); return (0); /* room not found */ } @@ -4701,7 +4983,7 @@ int CtdlDeleteMessages(char *room_name, /* which room */ cdb_free(cdbfr); } if (num_msgs > 0) { - int have_contenttype = !IsEmptyStr(content_type); + int have_contenttype = (content_type != NULL) && !IsEmptyStr(content_type); int have_delmsgs = (num_dmsgnums == 0) || (dmsgnums == NULL); int have_more_del = 1; @@ -4713,7 +4995,7 @@ int CtdlDeleteMessages(char *room_name, /* which room */ StrBuf *dbg = NewStrBuf(); for (i = 0; i < num_dmsgnums; i++) StrBufAppendPrintf(dbg, ", %ld", dmsgnums[i]); - syslog(LOG_DEBUG, "Deleting before: %s", ChrPtr(dbg)); + MSG_syslog(LOG_DEBUG, " Deleting before: %s", ChrPtr(dbg)); FreeStrBuf(&dbg); } */ @@ -4721,7 +5003,6 @@ int CtdlDeleteMessages(char *room_name, /* which room */ while ((i < num_msgs) && (have_more_del)) { delete_this = 0x00; - /* Set/clear a bit for each criterion */ /* 0 messages in the list or a null list means that we are @@ -4732,6 +5013,10 @@ int CtdlDeleteMessages(char *room_name, /* which room */ } else { while ((i < num_msgs) && (msglist[i] < dmsgnums[j])) i++; + + if (i >= num_msgs) + continue; + if (msglist[i] == dmsgnums[j]) { delete_this |= 0x01; } @@ -4760,7 +5045,7 @@ int CtdlDeleteMessages(char *room_name, /* which room */ StrBuf *dbg = NewStrBuf(); for (i = 0; i < num_deleted; i++) StrBufAppendPrintf(dbg, ", %ld", dellist[i]); - syslog(LOG_DEBUG, "Deleting: %s", ChrPtr(dbg)); + MSG_syslog(LOG_DEBUG, " Deleting: %s", ChrPtr(dbg)); FreeStrBuf(&dbg); } */ @@ -4792,7 +5077,7 @@ int CtdlDeleteMessages(char *room_name, /* which room */ /* Now free the memory we used, and go away. */ if (msglist != NULL) free(msglist); if (dellist != NULL) free(dellist); - 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); } @@ -4909,7 +5194,7 @@ void cmd_move(char *args) */ permit = 0; - /* Aides can move/copy */ + /* Admins can move/copy */ if (CC->user.axlevel >= AxAideU) permit = 1; /* Room aides can move/copy */ @@ -5023,10 +5308,11 @@ void PutMetaData(struct MetaData *smibuf) */ void AdjRefCount(long msgnum, int incr) { + struct CitContext *CCC = CC; struct arcq new_arcq; int rv = 0; - syslog(LOG_DEBUG, "AdjRefCount() msg %ld ref count delta %+d\n", msgnum, incr); + MSG_syslog(LOG_DEBUG, "AdjRefCount() msg %ld ref count delta %+d\n", msgnum, incr); begin_critical_section(S_SUPPMSGMAIN); if (arcfp == NULL) { @@ -5038,7 +5324,7 @@ void AdjRefCount(long msgnum, int incr) /* msgnum < 0 means that we're trying to close the file */ if (msgnum < 0) { - syslog(LOG_DEBUG, "Closing the AdjRefCount queue file\n"); + MSGM_syslog(LOG_DEBUG, "Closing the AdjRefCount queue file\n"); begin_critical_section(S_SUPPMSGMAIN); if (arcfp != NULL) { fclose(arcfp); @@ -5060,9 +5346,9 @@ void AdjRefCount(long msgnum, int incr) new_arcq.arcq_delta = incr; rv = fwrite(&new_arcq, sizeof(struct arcq), 1, arcfp); if (rv == -1) { - syslog(LOG_EMERG, "Couldn't write Refcount Queue File %s: %s\n", - file_arcq, - strerror(errno)); + MSG_syslog(LOG_EMERG, "Couldn't write Refcount Queue File %s: %s\n", + file_arcq, + strerror(errno)); } fflush(arcfp); @@ -5071,11 +5357,12 @@ void AdjRefCount(long msgnum, int incr) void AdjRefCountList(long *msgnum, long nmsg, int incr) { + struct CitContext *CCC = CC; long i, the_size, offset; struct arcq *new_arcq; int rv = 0; - syslog(LOG_DEBUG, "AdjRefCountList() msg %ld ref count delta %+d\n", nmsg, incr); + MSG_syslog(LOG_DEBUG, "AdjRefCountList() msg %ld ref count delta %+d\n", nmsg, incr); begin_critical_section(S_SUPPMSGMAIN); if (arcfp == NULL) { @@ -5106,9 +5393,9 @@ void AdjRefCountList(long *msgnum, long nmsg, int incr) { rv = fwrite(new_arcq + offset, 1, the_size - offset, arcfp); if (rv == -1) { - syslog(LOG_EMERG, "Couldn't write Refcount Queue File %s: %s\n", - file_arcq, - strerror(errno)); + MSG_syslog(LOG_EMERG, "Couldn't write Refcount Queue File %s: %s\n", + file_arcq, + strerror(errno)); } else { offset += rv; @@ -5130,6 +5417,7 @@ void AdjRefCountList(long *msgnum, long nmsg, int incr) */ int TDAP_ProcessAdjRefCountQueue(void) { + struct CitContext *CCC = CC; char file_arcq_temp[PATH_MAX]; int r; FILE *fp; @@ -5146,7 +5434,7 @@ int TDAP_ProcessAdjRefCountQueue(void) r = link(file_arcq, file_arcq_temp); if (r != 0) { - syslog(LOG_CRIT, "%s: %s\n", file_arcq_temp, strerror(errno)); + MSG_syslog(LOG_CRIT, "%s: %s\n", file_arcq_temp, strerror(errno)); end_critical_section(S_SUPPMSGMAIN); return(num_records_processed); } @@ -5156,7 +5444,7 @@ int TDAP_ProcessAdjRefCountQueue(void) fp = fopen(file_arcq_temp, "rb"); if (fp == NULL) { - syslog(LOG_CRIT, "%s: %s\n", file_arcq_temp, strerror(errno)); + MSG_syslog(LOG_CRIT, "%s: %s\n", file_arcq_temp, strerror(errno)); return(num_records_processed); } @@ -5168,7 +5456,7 @@ int TDAP_ProcessAdjRefCountQueue(void) fclose(fp); r = unlink(file_arcq_temp); if (r != 0) { - syslog(LOG_CRIT, "%s: %s\n", file_arcq_temp, strerror(errno)); + MSG_syslog(LOG_CRIT, "%s: %s\n", file_arcq_temp, strerror(errno)); } return(num_records_processed); @@ -5186,6 +5474,7 @@ int TDAP_ProcessAdjRefCountQueue(void) */ void TDAP_AdjRefCount(long msgnum, int incr) { + struct CitContext *CCC = CC; struct MetaData smi; long delnum; @@ -5199,15 +5488,15 @@ void TDAP_AdjRefCount(long msgnum, int incr) smi.meta_refcount += incr; PutMetaData(&smi); end_critical_section(S_SUPPMSGMAIN); - syslog(LOG_DEBUG, "TDAP_AdjRefCount() msg %ld ref count delta %+d, is now %d\n", - msgnum, incr, smi.meta_refcount + MSG_syslog(LOG_DEBUG, "TDAP_AdjRefCount() msg %ld ref count delta %+d, is now %d\n", + msgnum, incr, smi.meta_refcount ); /* If the reference count is now zero, delete the message * (and its supplementary record as well). */ if (smi.meta_refcount == 0) { - syslog(LOG_DEBUG, "Deleting message <%ld>\n", msgnum); + MSG_syslog(LOG_DEBUG, "Deleting message <%ld>\n", msgnum); /* Call delete hooks with NULL room to show it has gone altogether */ PerformDeleteHooks(NULL, msgnum); @@ -5240,7 +5529,7 @@ void CtdlWriteObject(char *req_room, /* Room to stuff it in */ unsigned int flags /* Internal save flags */ ) { - + struct CitContext *CCC = CC; struct ctdlroom qrbuf; char roomname[ROOMNAMELEN]; struct CtdlMessage *msg; @@ -5253,7 +5542,7 @@ void CtdlWriteObject(char *req_room, /* Room to stuff it in */ safestrncpy(roomname, req_room, sizeof(roomname)); } - syslog(LOG_DEBUG, "Raw length is %ld\n", (long)raw_length); + MSG_syslog(LOG_DEBUG, "Raw length is %ld\n", (long)raw_length); if (is_binary) { encoded_message = malloc((size_t) (((raw_length * 134) / 100) + 4096 ) ); @@ -5291,19 +5580,19 @@ void CtdlWriteObject(char *req_room, /* Room to stuff it in */ ); } - syslog(LOG_DEBUG, "Allocating\n"); + MSGM_syslog(LOG_DEBUG, "Allocating\n"); msg = malloc(sizeof(struct CtdlMessage)); memset(msg, 0, sizeof(struct CtdlMessage)); msg->cm_magic = CTDLMESSAGE_MAGIC; msg->cm_anon_type = MES_NORMAL; msg->cm_format_type = 4; - msg->cm_fields['A'] = strdup(CC->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) { @@ -5315,8 +5604,8 @@ void CtdlWriteObject(char *req_room, /* Room to stuff it in */ * other objects of this type that are currently in the room. */ if (is_unique) { - syslog(LOG_DEBUG, "Deleted %d other msgs of this type\n", - CtdlDeleteMessages(roomname, NULL, 0, content_type) + MSG_syslog(LOG_DEBUG, "Deleted %d other msgs of this type\n", + CtdlDeleteMessages(roomname, NULL, 0, content_type) ); } /* Now write the data */ @@ -5362,7 +5651,7 @@ char *CtdlGetSysConfig(char *sysconfname) { else { msg = CtdlFetchMessage(msgnum, 1); if (msg != NULL) { - conf = strdup(msg->cm_fields['M']); + conf = strdup(msg->cm_fields[eMesageText]); CtdlFreeMessage(msg); } else { @@ -5437,10 +5726,15 @@ void cmd_isme(char *argbuf) { /*****************************************************************************/ /* MODULE INITIALIZATION STUFF */ /*****************************************************************************/ - +void SetMessageDebugEnabled(const int n) +{ + MessageDebugEnabled = n; +} CTDL_MODULE_INIT(msgbase) { if (!threading) { + CtdlRegisterDebugFlagHook(HKEY("messages"), SetMessageDebugEnabled, &MessageDebugEnabled); + CtdlRegisterProtoHook(cmd_msgs, "MSGS", "Output a list of messages in the current room"); CtdlRegisterProtoHook(cmd_msg0, "MSG0", "Output a message in plain text format"); CtdlRegisterProtoHook(cmd_msg2, "MSG2", "Output a message in RFC822 format");