#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",
- "rep2",
- "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 */
};
/*
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
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);
}
-
-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,
+ 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,
+ char *to,
+ char *room,
+ const char *text,
+ int format_type,
+ const char *subject,
+ int nCriterions,
+ const char **CritStr,
+ long *CritStrLen)
+{
+ int i;
+ struct UseTable ut;
+ u_char rawdigest[MD5_DIGEST_LEN];
+ struct MD5Context md5context;
+ StrBuf *guid;
+ struct cdbdata *cdbut;
+ char timestamp[64];
+ long tslen;
+ time_t ts = time(NULL);
+ time_t tsday = ts / (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);
+ /* Find out if we've already sent a similar message */
+ memcpy(ut.ut_msgid, SKEY(guid));
+ ut.ut_timestamp = ts;
+
+ cdbut = cdb_fetch(CDB_USETABLE, SKEY(guid));
+
+ if (cdbut != NULL) {
+ /* yes, we did. flood protection kicks in. */
+ syslog(LOG_DEBUG,
+ "not sending message again\n");
+ cdb_free(cdbut);
+ }
+
+ /* rewrite the record anyway, to update the timestamp */
+ cdb_store(CDB_USETABLE,
+ SKEY(guid),
+ &ut, sizeof(struct UseTable) );
+
+ FreeStrBuf(&guid);
+
+ if (cdbut != NULL) return;
+ /* 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! */
*/
permit = 0;
- /* Aides can move/copy */
+ /* Admins can move/copy */
if (CC->user.axlevel >= AxAideU) permit = 1;
/* Room aides can move/copy */