LOG: add separating blanks in debug messages.
[citadel.git] / citadel / msgbase.c
index abb47ca161e0c8767c62bd323faff5690eefb1e0..b00b8870bb716ac9aea7666027739f200e5bdad1 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,32 +88,43 @@ 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 */
 };
 
+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...)
@@ -1133,7 +1147,7 @@ void mime_download(char *name, char *filename, char *partnum, char *disp,
                        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));
@@ -1199,6 +1213,7 @@ struct CtdlMessage *CtdlFetchMessage(long msgnum, int 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;
@@ -1307,6 +1322,49 @@ void CtdlFreeMessage(struct CtdlMessage *msg)
        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
@@ -1813,7 +1871,7 @@ char *qp_encode_email_addrs(char *source)
 
        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);
@@ -3489,18 +3547,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;
@@ -3541,6 +3597,69 @@ void quickie_message(const char *from, const char *fromaddr, char *to, char *roo
        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);
+}
 
 
 /*
@@ -3549,7 +3668,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 */
@@ -3566,8 +3685,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? */
@@ -3630,7 +3748,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 */
@@ -3653,8 +3771,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 == '.')) {
@@ -3787,7 +3904,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 */
@@ -3942,11 +4059,6 @@ struct CtdlMessage *CtdlMakeMessage(
        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
@@ -3981,7 +4093,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);
 
@@ -4037,7 +4149,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! */
@@ -4692,12 +4804,12 @@ int CtdlDeleteMessages(char *room_name,         /* which room */
                        regcomp(&re, content_type, 0);
                        need_to_free_re = 1;
                }
-       MSG_syslog(LOG_DEBUG, "CtdlDeleteMessages(%s, %d msgs, %s)\n",
+       MSG_syslog(LOG_DEBUG, " CtdlDeleteMessages(%s, %d msgs, %s)\n",
                   room_name, num_dmsgnums, content_type);
 
        /* get room record, obtaining a lock... */
        if (CtdlGetRoomLock(&qrbuf, room_name) != 0) {
-               MSG_syslog(LOG_ERR, "CtdlDeleteMessages(): Room <%s> not found\n",
+               MSG_syslog(LOG_ERR, " CtdlDeleteMessages(): Room <%s> not found\n",
                           room_name);
                if (need_to_free_re) regfree(&re);
                return (0);     /* room not found */
@@ -4724,7 +4836,7 @@ int CtdlDeleteMessages(char *room_name,           /* which room */
                        StrBuf *dbg = NewStrBuf();
                        for (i = 0; i < num_dmsgnums; i++)
                                StrBufAppendPrintf(dbg, ", %ld", dmsgnums[i]);
-                       MSG_syslog(LOG_DEBUG, "Deleting before: %s", ChrPtr(dbg));
+                       MSG_syslog(LOG_DEBUG, " Deleting before: %s", ChrPtr(dbg));
                        FreeStrBuf(&dbg);
                }
 */
@@ -4732,7 +4844,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
@@ -4743,6 +4854,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;
                                }
@@ -4771,7 +4886,7 @@ int CtdlDeleteMessages(char *room_name,           /* which room */
                        StrBuf *dbg = NewStrBuf();
                        for (i = 0; i < num_deleted; i++)
                                StrBufAppendPrintf(dbg, ", %ld", dellist[i]);
-                       MSG_syslog(LOG_DEBUG, "Deleting: %s", ChrPtr(dbg));
+                       MSG_syslog(LOG_DEBUG, " Deleting: %s", ChrPtr(dbg));
                        FreeStrBuf(&dbg);
                }
 */
@@ -4803,7 +4918,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);
-       MSG_syslog(LOG_DEBUG, "%d message(s) deleted.\n", num_deleted);
+       MSG_syslog(LOG_DEBUG, " %d message(s) deleted.\n", num_deleted);
        if (need_to_free_re) regfree(&re);
        return (num_deleted);
 }
@@ -4920,7 +5035,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 */