Choose default sender email address by envelope recipient
[citadel.git] / citadel / msgbase.c
index ce52cc11365267a1cdd84efe402972e6f288bb65..dc407afdc369ff88aad6d06684dd39da9cb03b53 100644 (file)
@@ -38,6 +38,9 @@
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <regex.h>
+
+#include "md5.h"
+
 #include <libcitadel.h>
 #include "citadel.h"
 #include "server.h"
@@ -85,30 +88,32 @@ 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",
-       "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 */
 };
 
 /*
@@ -3539,6 +3544,75 @@ void quickie_message(const char *from,
        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);
+}
+
 
 /*
  * Back end function used by CtdlMakeMessage() and similar functions
@@ -3546,7 +3620,7 @@ void quickie_message(const char *from,
 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 */
@@ -3563,8 +3637,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? */
@@ -3627,7 +3700,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 */
@@ -3650,8 +3723,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 == '.')) {
@@ -3784,7 +3856,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 */