Send crashmessage just once per day.
[citadel.git] / citadel / msgbase.c
index 9b60f0966ed8c5704cc367bb7d85937e197bdaea..ddc12aafdba517bfa33030a5873582455138d836 100644 (file)
@@ -1142,13 +1142,23 @@ struct CtdlMessage *CtdlFetchMessage(long msgnum, int with_body)
         * have just processed the 'M' (message text) field.
         */
        do {
+               field_header = '\0';
                long len;
+
+               /* work around possibly buggy messages: */
+               while (field_header == '\0')
+               {
+                       if (mptr >= upper_bound) {
+                               break;
+                       }
+                       field_header = *mptr++;
+               }
                if (mptr >= upper_bound) {
                        break;
                }
-               field_header = *mptr++;
                which = field_header;
                len = strlen(mptr);
+
                CM_SetField(ret, which, mptr, len);
 
                mptr += len + 1;        /* advance to next field */
@@ -1165,7 +1175,7 @@ struct CtdlMessage *CtdlFetchMessage(long msgnum, int with_body)
        if ( (CM_IsEmpty(ret, eMesageText)) && (with_body) ) {
                dmsgtext = cdb_fetch(CDB_BIGMSGS, &msgnum, sizeof(long));
                if (dmsgtext != NULL) {
-                       CM_SetAsField(ret, eMesageText, &dmsgtext->ptr, dmsgtext->len);
+                       CM_SetAsField(ret, eMesageText, &dmsgtext->ptr, dmsgtext->len - 1);
                        cdb_free(dmsgtext);
                }
        }
@@ -1511,14 +1521,15 @@ int check_cached_msglist(long msgnum) {
  * 
  */
 int CtdlOutputMsg(long msg_num,                /* message number (local) to fetch */
-                 int mode,             /* how would you like that message? */
-                 int headers_only,     /* eschew the message body? */
-                 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 */
-                 char **Author,
-                 char **Address
+               int mode,               /* how would you like that message? */
+               int headers_only,       /* eschew the message body? */
+               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 */
+               char **Author,
+               char **Address,
+               char **MessageID
 ) {
        struct CitContext *CCC = CC;
        struct CtdlMessage *TheMessage = NULL;
@@ -1606,6 +1617,11 @@ int CtdlOutputMsg(long msg_num,          /* message number (local) to fetch */
                        long len;
                        CM_GetAsField(TheMessage, erFc822Addr, Address, &len);
                }
+               if ((MessageID != NULL) && (*MessageID == NULL))
+               {       
+                       long len;
+                       CM_GetAsField(TheMessage, emessageId, MessageID, &len);
+               }
                CM_Free(TheMessage);
                TheMessage = NULL;
 
@@ -1645,6 +1661,11 @@ int CtdlOutputMsg(long msg_num,          /* message number (local) to fetch */
                long len;
                CM_GetAsField(TheMessage, erFc822Addr, Address, &len);
        }
+       if ((MessageID != NULL) && (*MessageID == NULL))
+       {       
+               long len;
+               CM_GetAsField(TheMessage, emessageId, MessageID, &len);
+       }
 
        CM_Free(TheMessage);
 
@@ -1746,28 +1767,28 @@ void OutputRFC822MsgHeaders(
        char *mpptr = NULL;
        char *hptr;
 
-       for (i = 0; i < 256; ++i) {
-               if (TheMessage->cm_fields[i]) {
-                       mptr = mpptr = TheMessage->cm_fields[i];
-                               
-                       if (i == eAuthor) {
+       for (i = 0; i < NDiskFields; ++i) {
+               if (TheMessage->cm_fields[FieldOrder[i]]) {
+                       mptr = mpptr = TheMessage->cm_fields[FieldOrder[i]];
+                       switch (FieldOrder[i]) {
+                       case eAuthor:
                                safestrncpy(luser, mptr, sizeof_luser);
                                safestrncpy(suser, mptr, sizeof_suser);
-                       }
-                       else if (i == 'Y') {
+                               break;
+                       case eCarbonCopY:
                                if ((flags & QP_EADDR) != 0) {
                                        mptr = qp_encode_email_addrs(mptr);
                                }
                                sanitize_truncated_recipient(mptr);
                                cprintf("CC: %s%s", mptr, nl);
-                       }
-                       else if (i == 'P') {
+                               break;
+                       case eMessagePath:
                                cprintf("Return-Path: %s%s", mptr, nl);
-                       }
-                       else if (i == eListID) {
+                               break;
+                       case eListID:
                                cprintf("List-ID: %s%s", mptr, nl);
-                       }
-                       else if (i == 'V') {
+                               break;
+                       case eenVelopeTo:
                                if ((flags & QP_EADDR) != 0) 
                                        mptr = qp_encode_email_addrs(mptr);
                                hptr = mptr;
@@ -1775,22 +1796,25 @@ void OutputRFC822MsgHeaders(
                                        hptr ++;
                                if (!IsEmptyStr(hptr))
                                        cprintf("Envelope-To: %s%s", hptr, nl);
-                       }
-                       else if (i == 'U') {
+                               break;
+                       case eMsgSubject:
                                cprintf("Subject: %s%s", mptr, nl);
                                subject_found = 1;
-                       }
-                       else if (i == 'I')
+                               break;
+                       case emessageId:
                                safestrncpy(mid, mptr, sizeof_mid); /// TODO: detect @ here and copy @nodename in if not found.
-                       else if (i == erFc822Addr)
+                               break;
+                       case erFc822Addr:
                                safestrncpy(fuser, mptr, sizeof_fuser);
-                       /* else if (i == 'O')
+                       /* case eOriginalRoom:
                           cprintf("X-Citadel-Room: %s%s",
-                          mptr, nl); */
-                       else if (i == 'N')
+                          mptr, nl)
+                          break;
+                          ; */
+                       case eNodeName:
                                safestrncpy(snode, mptr, sizeof_snode);
-                       else if (i == 'R')
-                       {
+                               break;
+                       case eRecipient:
                                if (haschar(mptr, '@') == 0)
                                {
                                        sanitize_truncated_recipient(mptr);
@@ -1806,13 +1830,13 @@ void OutputRFC822MsgHeaders(
                                        cprintf("To: %s", mptr);
                                        cprintf("%s", nl);
                                }
-                       }
-                       else if (i == 'T') {
+                               break;
+                       case eTimestamp:
                                datestring(datestamp, sizeof datestamp,
                                           atol(mptr), DATESTRING_RFC822);
                                cprintf("Date: %s%s", datestamp, nl);
-                       }
-                       else if (i == 'W') {
+                               break;
+                       case eWeferences:
                                cprintf("References: ");
                                k = num_tokens(mptr, '|');
                                for (j=0; j<k; ++j) {
@@ -1825,13 +1849,31 @@ void OutputRFC822MsgHeaders(
                                                cprintf(" ");
                                        }
                                }
-                       }
-                       else if (i == eReplyTo) {
+                               break;
+                       case eReplyTo:
                                hptr = mptr;
                                while ((*hptr != '\0') && isspace(*hptr))
                                        hptr ++;
                                if (!IsEmptyStr(hptr))
                                        cprintf("Reply-To: %s%s", mptr, nl);
+                               break;
+
+                       case eRemoteRoom:
+                       case eDestination:
+                       case eExclusiveID:
+                       case eHumanNode:
+                       case eJournal:
+                       case eMesageText:
+                       case eBig_message:
+                       case eOriginalRoom:
+                       case eSpecialField:
+                       case eErrorMsg:
+                       case eSuppressIdx:
+                       case eExtnotify:
+                       case eVltMsgNum:
+                               /* these don't map to mime message headers. */
+                               break;
+
                        }
                        if (mptr != mpptr)
                                free (mptr);
@@ -2738,7 +2780,7 @@ long CtdlSubmitMsg(struct CtdlMessage *msg,       /* message to save */
        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);
+               CtdlUserGoto(actual_rm, 0, 1, NULL, NULL, NULL, NULL);
        }
 
        /*
@@ -2828,9 +2870,9 @@ long CtdlSubmitMsg(struct CtdlMessage *msg,       /* message to save */
 
        /* Bump this user's messages posted counter. */
        MSGM_syslog(LOG_DEBUG, "Updating user\n");
-       CtdlGetUserLock(&CCC->user, CCC->curr_user);
+       CtdlLockGetCurrentUser();
        CCC->user.posted = CCC->user.posted + 1;
-       CtdlPutUserLock(&CCC->user);
+       CtdlPutCurrentUserLock();
 
        /* Decide where bounces need to be delivered */
        if ((recps != NULL) && (recps->bounce_to == NULL))
@@ -2885,7 +2927,7 @@ long CtdlSubmitMsg(struct CtdlMessage *msg,       /* message to save */
        /* Go back to the room we started from */
        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);
+               CtdlUserGoto(hold_rm, 0, 1, NULL, NULL, NULL, NULL);
 
        /*
         * Any addresses to harvest for someone's address book?
@@ -3008,7 +3050,7 @@ void flood_protect_quickie_message(const char *from,
                                   const char *subject,
                                   int nCriterions,
                                   const char **CritStr,
-                                  long *CritStrLen,
+                                  const long *CritStrLen,
                                   long ccid,
                                   long ioid,
                                   time_t NOW)
@@ -3019,7 +3061,8 @@ void flood_protect_quickie_message(const char *from,
        StrBuf *guid;
        char timestamp[64];
        long tslen;
-       time_t tsday = NOW / (8*60*60); /* just care for a day... */
+       static const time_t tsday = (8*60*60); /* just care for a day... */
+       time_t seenstamp;
 
        tslen = snprintf(timestamp, sizeof(timestamp), "%ld", tsday);
        MD5Init(&md5context);
@@ -3038,29 +3081,35 @@ void flood_protect_quickie_message(const char *from,
        if (StrLength(guid) > 40)
                StrBufCutAt(guid, 40, NULL);
 
-       if (CheckIfAlreadySeen("FPAideMessage",
-                              guid,
-                              NOW,
-                              tsday,
-                              eUpdate,
-                              ccid,
-                              ioid)!= 0)
+       seenstamp = CheckIfAlreadySeen("FPAideMessage",
+                                      guid,
+                                      NOW,
+                                      tsday,
+                                      eUpdate,
+                                      ccid,
+                                      ioid);
+       if ((seenstamp > 0) && (seenstamp < tsday))
        {
                FreeStrBuf(&guid);
                /* yes, we did. flood protection kicks in. */
                syslog(LOG_DEBUG,
-                      "not sending message again\n");
+                      "not sending message again - %ld < %ld \n", seenstamp, tsday);
                return;
        }
-       FreeStrBuf(&guid);
-       /* no, this message isn't sent recently; go ahead. */
-       quickie_message(from,
-                       fromaddr,
-                       to,
-                       room,
-                       text, 
-                       format_type,
-                       subject);
+       else
+       {
+               syslog(LOG_DEBUG,
+                      "sending message. %ld >= %ld", seenstamp, tsday);
+               FreeStrBuf(&guid);
+               /* no, this message isn't sent recently; go ahead. */
+               quickie_message(from,
+                               fromaddr,
+                               to,
+                               room,
+                               text, 
+                               format_type,
+                               subject);
+       }
 }
 
 
@@ -3215,6 +3264,11 @@ eReadState CtdlReadMessageBodyAsync(AsyncIO *IO)
                 IO->SendBuf.fd);
        
        fd = fopen(fn, "a+");
+       if (fd == NULL) {
+               syslog(LOG_EMERG, "failed to open file %s: %s", fn, strerror(errno));
+               cit_backtrace();
+               exit(1);
+       }
 #endif
 
        ReadMsg = IO->ReadMsg;
@@ -3296,7 +3350,7 @@ eReadState CtdlReadMessageBodyAsync(AsyncIO *IO)
        if (MsgFinished)
                return eReadSuccess;
        else 
-               return eAbort;
+               return eReadFail;
 }
 
 
@@ -3497,9 +3551,10 @@ struct CtdlMessage *CtdlMakeMessageLen(
                CM_SetField(msg, eMesageText, preformatted_text, textlen);
        }
        else {
-               preformatted_text = CtdlReadMessageBody(HKEY("000"), config.c_maxmsglen, NULL, 0, 0);
-               if (preformatted_text != NULL) {
-                       CM_SetField(msg, eMesageText, preformatted_text, strlen(preformatted_text));
+               StrBuf *MsgBody;
+               MsgBody = CtdlReadMessageBodyBuf(HKEY("000"), config.c_maxmsglen, NULL, 0, 0);
+               if (MsgBody != NULL) {
+                       CM_SetAsFieldSB(msg, eMesageText, &MsgBody);
                }
        }