#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 */
};
+void CtdlMsgSetCM_Fields(struct CtdlMessage *Msg, const char 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';
+}
+
/*
* This function is self explanatory.
* (What can I say, I'm in a weird mood today...)
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;
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;
free(msg);
}
+int DupCMField(int 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
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;
*extract_encapsulated_message,
NULL, NULL, (void *)&encap, 0
);
+
+ if ((Author != NULL) && (*Author == NULL))
+ {
+ *Author = TheMessage->cm_fields['A'];
+ TheMessage->cm_fields['A'] = NULL;
+ }
+ if ((Address != NULL) && (*Address == NULL))
+ {
+ *Address = TheMessage->cm_fields['F'];
+ TheMessage->cm_fields['F'] = NULL;
+ }
CtdlFreeMessage(TheMessage);
TheMessage = NULL;
}
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['A'];
+ TheMessage->cm_fields['A'] = NULL;
+ }
+ if ((Address != NULL) && (*Address == NULL))
+ {
+ *Address = TheMessage->cm_fields['F'];
+ TheMessage->cm_fields['F'] = 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);
}
if (outlen > 0) {
client_write(outbuf, outlen);
- outlen = 0;
}
}
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);
+}
/*
msglist = realloc(msglist, (sizeof(long) * (num_msgs + num_msgs_to_be_merged)) );
if (msglist == NULL) {
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;
}
-/*
- * 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;
-
- /*
- * Check for valid message format
- */
- if (is_valid_message(msg) == 0) {
- struct CitContext *CCC = CC;
- MSGM_syslog(LOG_ERR, "dump_message() aborting due to invalid message\n");
- return;
- }
-
- 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)
- {
- struct CitContext *CCC = CC;
- MSGM_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 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;
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 */
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! */
alias(this_recp);
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] = ' ';
}
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;
}
else {
while ((i < num_msgs) && (msglist[i] < dmsgnums[j])) i++;
+
+ if (i >= num_msgs)
+ continue;
+
if (msglist[i] == dmsgnums[j]) {
delete_this |= 0x01;
}
*/
permit = 0;
- /* Aides can move/copy */
+ /* Admins can move/copy */
if (CC->user.axlevel >= AxAideU) permit = 1;
/* Room aides can move/copy */