* New MSGS subcommand 'EUID' to fetch msgnum of a message by EUID ... similar to...
[citadel.git] / citadel / msgbase.c
index 8e94f87b834963a79fc6943320db15e7b97afefe..9563223d63961eb05d222e557f24192ec96fd6de 100644 (file)
@@ -353,7 +353,6 @@ void CtdlSetSeen(long *target_msgnums, int num_target_msgnums,
        StrBuf *histr;
        const char *pvset;
        char *is_set;   /* actually an array of booleans */
-       int w = 0;
 
        /* Don't bother doing *anything* if we were passed a list of zero messages */
        if (num_target_msgnums < 1) {
@@ -424,7 +423,8 @@ void CtdlSetSeen(long *target_msgnums, int num_target_msgnums,
        lostr = NewStrBuf();
        histr = NewStrBuf();
        pvset = NULL;
-       while (StrBufExtract_NextToken(setstr, vset, &pvset, ',')) {
+       while (StrBufExtract_NextToken(setstr, vset, &pvset, ',') >= 0) {
+
                StrBufExtract_token(lostr, setstr, 0, ':');
                if (StrBufNum_tokens(setstr, ':') >= 2) {
                        StrBufExtract_token(histr, setstr, 1, ':');
@@ -468,14 +468,11 @@ void CtdlSetSeen(long *target_msgnums, int num_target_msgnums,
                        }
                }
 
-               w = 0;  /* set to 1 if we write something to the string */
-
                if ((was_seen == 0) && (is_seen == 1)) {
                        lo = msglist[i];
                }
                else if ((was_seen == 1) && (is_seen == 0)) {
                        hi = msglist[i-1];
-                       w = 1;
 
                        if (StrLength(vset) > 0) {
                                StrBufAppendBufPlain(vset, HKEY(","), 0);
@@ -487,8 +484,8 @@ void CtdlSetSeen(long *target_msgnums, int num_target_msgnums,
                                StrBufAppendPrintf(vset, "%ld:%ld", lo, hi);
                        }
                }
-               else if ((is_seen) && (i == num_msgs - 1)) {
-                       w = 1;
+
+               if ((is_seen) && (i == num_msgs - 1)) {
                        if (StrLength(vset) > 0) {
                                StrBufAppendBufPlain(vset, HKEY(","), 0);
                        }
@@ -500,27 +497,48 @@ void CtdlSetSeen(long *target_msgnums, int num_target_msgnums,
                        }
                }
 
-               /* If the string is getting too long, truncate it at the beginning; repeat up to 9 times * /
-               if (w) for (j=0; j<9; ++j) {
-                       if ((StrLength(vset) + 20) > sizeof vset) {
-                               remove_token(vset, 0, ',');
-                               if (which_set == ctdlsetseen_seen) {
-                                       char temp[SIZ];
-                                       sprintf(temp, "1:%ld,", atol(vset)-1L);
-                                       strcat(temp, vset);
-                                       strcpy(vset, temp);
-                               }
-                       }
-               }
-               we don't get to long anymore.
-               */
-
                was_seen = is_seen;
        }
 
-       while (StrLength(vset) > SIZ)
+       /*
+        * We will have to stuff this string back into a 4096 byte buffer, so if it's
+        * larger than that now, truncate it by removing tokens from the beginning.
+        * The limit of 100 iterations is there to prevent an infinite loop in case
+        * something unexpected happens.
+        */
+       int number_of_truncations = 0;
+       while ( (StrLength(vset) > SIZ) && (number_of_truncations < 100) ) {
+               StrBufRemove_token(vset, 0, ',');
+               ++number_of_truncations;
+       }
+
+       /*
+        * If we're truncating the sequence set of messages marked with the 'seen' flag,
+        * we want the earliest messages (the truncated ones) to be marked, not unmarked.
+        * Otherwise messages at the beginning will suddenly appear to be 'unseen'.
+        */
+       if ( (which_set == ctdlsetseen_seen) && (number_of_truncations > 0) ) {
+               StrBuf *first_tok;
+               first_tok = NewStrBuf();
+               StrBufExtract_token(first_tok, vset, 0, ',');
                StrBufRemove_token(vset, 0, ',');
 
+               if (StrBufNum_tokens(first_tok, ':') > 1) {
+                       StrBufRemove_token(first_tok, 0, ':');
+               }
+               
+               StrBuf *new_set;
+               new_set = NewStrBuf();
+               StrBufAppendBufPlain(new_set, HKEY("1:"), 0);
+               StrBufAppendBuf(new_set, first_tok, 0);
+               StrBufAppendBufPlain(new_set, HKEY(":"), 0);
+               StrBufAppendBuf(new_set, vset, 0);
+
+               FreeStrBuf(&vset);
+               FreeStrBuf(&first_tok);
+               vset = new_set;
+       }
+
        CtdlLogPrintf(CTDL_DEBUG, " after update: %s\n", ChrPtr(vset));
 
        /* Decide which message set we're manipulating */
@@ -544,7 +562,9 @@ void CtdlSetSeen(long *target_msgnums, int num_target_msgnums,
  * API function to perform an operation for each qualifying message in the
  * current room.  (Returns the number of messages processed.)
  */
-int CtdlForEachMessage(int mode, long ref, char *search_string,
+int CtdlForEachMessage(int mode,
+                       long ref,
+                       char *search_string,
                        char *content_type,
                        struct CtdlMessage *compare,
                        void (*CallBack) (long, void *),
@@ -636,6 +656,30 @@ int CtdlForEachMessage(int mode, long ref, char *search_string,
                }
        }
 
+       /* If an EUID was specified, throw away all messages except the correct one. */
+       if (mode == MSGS_EUID) {
+               long correct_msgnum;
+               int found_match = 0;
+
+               if ((num_msgs > 0) && (search_string) ) {
+                       correct_msgnum = locate_message_by_euid(search_string, &CC->room);
+                       if ( (num_msgs > 0) && (correct_msgnum >= 0L) ) {
+                               for (i=0; i<num_msgs; ++i) {
+                                       if (msglist[i] == correct_msgnum) {
+                                               found_match = 1;
+                                       }
+                               }
+                       }
+               }
+               if (found_match) {
+                       msglist[0] = correct_msgnum;
+                       num_msgs = 1;
+               } else {
+                       num_msgs = 0;   /* didn't find the right one ... dump the rest */
+               }
+               mode = MSGS_ALL;        /* treat it like 'read all' from now on */
+       }
+
        /* If a search string was specified, get a message list from
         * the full text index and remove messages which aren't on both
         * lists.
@@ -762,6 +806,8 @@ void cmd_msgs(char *cmdbuf)
                mode = MSGS_GT;
        else if (!strncasecmp(which, "SEARCH", 6))
                mode = MSGS_SEARCH;
+       else if (!strncasecmp(which, "EUID", 4))
+               mode = MSGS_EUID;
        else
                mode = MSGS_ALL;
 
@@ -804,7 +850,7 @@ void cmd_msgs(char *cmdbuf)
 
        CtdlForEachMessage(mode,
                        ( (mode == MSGS_SEARCH) ? 0 : cm_ref ),
-                       ( (mode == MSGS_SEARCH) ? search_string : NULL ),
+                       ( ((mode == MSGS_SEARCH)||(mode == MSGS_EUID)) ? search_string : NULL ),
                        NULL,
                        template,
                        (with_headers ? headers_listing : simple_listing),
@@ -999,6 +1045,7 @@ void mime_download(char *name, char *filename, char *partnum, char *disp,
                   void *content, char *cbtype, char *cbcharset, size_t length,
                   char *encoding, char *cbid, void *cbuserdata)
 {
+       int rv = 0;
 
        /* Silently go away if there's already a download open. */
        if (CC->download_fp != NULL)
@@ -1012,7 +1059,7 @@ void mime_download(char *name, char *filename, char *partnum, char *disp,
                if (CC->download_fp == NULL)
                        return;
        
-               fwrite(content, length, 1, CC->download_fp);
+               rv = fwrite(content, length, 1, CC->download_fp);
                fflush(CC->download_fp);
                rewind(CC->download_fp);
        
@@ -2653,6 +2700,7 @@ long CtdlSubmitMsg(struct CtdlMessage *msg,       /* message to save */
        struct CitContext *CCC = CC;            /* CachedCitContext - performance boost */
        char bounce_to[1024] = "";
        size_t tmp = 0;
+       int rv = 0;
 
        CtdlLogPrintf(CTDL_DEBUG, "CtdlSubmitMsg() called\n");
        if (is_valid_message(msg) == 0) return(-1);     /* self check */
@@ -2935,7 +2983,7 @@ long CtdlSubmitMsg(struct CtdlMessage *msg,       /* message to save */
                                         (long) getpid(), CCC->cs_pid, ++seqnum);
                        network_fp = fopen(submit_filename, "wb+");
                        if (network_fp != NULL) {
-                               fwrite(smr.ser, smr.len, 1, network_fp);
+                               rv = fwrite(smr.ser, smr.len, 1, network_fp);
                                fclose(network_fp);
                        }
                        free(smr.ser);
@@ -4359,6 +4407,7 @@ void PutMetaData(struct MetaData *smibuf)
 void AdjRefCount(long msgnum, int incr)
 {
        struct arcq new_arcq;
+       int rv = 0;
 
        begin_critical_section(S_SUPPMSGMAIN);
        if (arcfp == NULL) {
@@ -4388,7 +4437,7 @@ void AdjRefCount(long msgnum, int incr)
 
        new_arcq.arcq_msgnum = msgnum;
        new_arcq.arcq_delta = incr;
-       fwrite(&new_arcq, sizeof(struct arcq), 1, arcfp);
+       rv = fwrite(&new_arcq, sizeof(struct arcq), 1, arcfp);
        fflush(arcfp);
 
        return;