From bc8879ffb1371e6dce25e4440b79c04685c6258f Mon Sep 17 00:00:00 2001 From: Art Cancro Date: Sat, 20 Sep 2008 06:08:44 +0000 Subject: [PATCH] Fixed a bug in CtdlSetSeen() where if the target room was not the currently selected room, the list of seen/unseen or answered/unanswered messages could become corrupted. --- citadel/msgbase.c | 107 ++++++++++++++++++++++------------------- libcitadel/lib/tools.c | 6 +-- 2 files changed, 60 insertions(+), 53 deletions(-) diff --git a/citadel/msgbase.c b/citadel/msgbase.c index 5a7fe2ff5..8ae8a4d3d 100644 --- a/citadel/msgbase.c +++ b/citadel/msgbase.c @@ -340,8 +340,6 @@ void CtdlSetSeen(long *target_msgnums, int num_target_msgnums, int was_seen = 0; long lo = (-1L); long hi = (-1L); - long t = (-1L); - int trimming = 0; struct visit vbuf; long *msglist; int num_msgs = 0; @@ -349,8 +347,8 @@ void CtdlSetSeen(long *target_msgnums, int num_target_msgnums, char *is_set; /* actually an array of booleans */ int num_sets; int s; + int w = 0; char setstr[SIZ], lostr[SIZ], histr[SIZ]; - size_t tmp; /* Don't bother doing *anything* if we were passed a list of zero messages */ if (num_target_msgnums < 1) { @@ -367,7 +365,7 @@ void CtdlSetSeen(long *target_msgnums, int num_target_msgnums, which_user = &CC->user; } - CtdlLogPrintf(CTDL_DEBUG, "CtdlSetSeen(%d msgs starting with %ld, %s, %d) in <%s>\n", + CtdlLogPrintf(CTDL_DEBUG, "CtdlSetSeen(%d msgs starting with %ld, %s, %d) in <%s>\n", num_target_msgnums, target_msgnums[0], (target_setting ? "SET" : "CLEAR"), which_set, @@ -377,7 +375,7 @@ void CtdlSetSeen(long *target_msgnums, int num_target_msgnums, CtdlGetRelationship(&vbuf, which_user, which_room); /* Load the message list */ - cdbfr = cdb_fetch(CDB_MSGLISTS, &CC->room.QRnumber, sizeof(long)); + cdbfr = cdb_fetch(CDB_MSGLISTS, &which_room->QRnumber, sizeof(long)); if (cdbfr != NULL) { msglist = (long *) cdbfr->ptr; cdbfr->ptr = NULL; /* CtdlSetSeen() now owns this memory */ @@ -400,7 +398,19 @@ void CtdlSetSeen(long *target_msgnums, int num_target_msgnums, break; } - CtdlLogPrintf(CTDL_DEBUG, "before optimize: %s\n", vset); + +#if 0 /* This is a special diagnostic section. Do not allow it to run during normal operation. */ + CtdlLogPrintf(CTDL_DEBUG, "There are %d messages in the room.\n", num_msgs); + for (i=0; i 0) if (msglist[i] <= msglist[i-1]) abort(); + } + CtdlLogPrintf(CTDL_DEBUG, "We are twiddling %d of them.\n", num_target_msgnums); + for (k=0; k 0) if (target_msgnums[k] <= target_msgnums[k-1]) abort(); + } +#endif + + CtdlLogPrintf(CTDL_DEBUG, "before update: %s\n", vset); /* Translate the existing sequence set into an array of booleans */ num_sets = num_tokens(vset, ','); @@ -429,73 +439,73 @@ void CtdlSetSeen(long *target_msgnums, int num_target_msgnums, } } - CtdlLogPrintf(CTDL_DEBUG, " after optimize: %s\n", vset); /* Now translate the array of booleans back into a sequence set */ strcpy(vset, ""); - lo = (-1L); - hi = (-1L); - was_seen = ((which_set == ctdlsetseen_seen) ? 1 : 0); + was_seen = 0; + lo = (-1); + hi = (-1); for (i=0; i sizeof vset) { - remove_token(vset, 0, ','); - trimming = 1; - if (j--) break; /* loop no more than 9 times */ + if (!IsEmptyStr(vset)) { + strcat(vset, ","); } - if ( (trimming) && (which_set == ctdlsetseen_seen) ) { - t = atol(vset); - if (t<2) t=2; - --t; - snprintf(lostr, sizeof lostr, - "1:%ld,%s", t, vset); - safestrncpy(vset, lostr, sizeof vset); + if (lo == hi) { + sprintf(&vset[strlen(vset)], "%ld", hi); } - if (trimming) { - CtdlLogPrintf(CTDL_DEBUG, "32m ** TRIMMING ** \n"); + else { + sprintf(&vset[strlen(vset)], "%ld:%ld", lo, hi); } - /* end trim-o-matic code */ - - tmp = strlen(vset); - if (tmp > 0) { + } + else if ((is_seen) && (i == num_msgs - 1)) { + w = 1; + if (!IsEmptyStr(vset)) { strcat(vset, ","); - ++tmp; - } - if ((lo == -1) && (hi == -1)) { - /* bogus pair, do nothing */ } - else if (lo == hi) { - snprintf(&vset[tmp], (sizeof vset) - tmp, "%ld", lo); + if ((i==0) || (was_seen == 0)) { + sprintf(&vset[strlen(vset)], "%ld", msglist[i]); } else { - snprintf(&vset[tmp], (sizeof vset) - tmp, "%ld:%ld", lo, hi); + sprintf(&vset[strlen(vset)], "%ld:%ld", lo, msglist[i]); + } + } + + /* 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 ((strlen(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); + } } - lo = (-1L); - hi = (-1L); } + was_seen = is_seen; } + CtdlLogPrintf(CTDL_DEBUG, " after update: %s\n", vset); + /* Decide which message set we're manipulating */ switch (which_set) { case ctdlsetseen_seen: @@ -505,9 +515,8 @@ void CtdlSetSeen(long *target_msgnums, int num_target_msgnums, safestrncpy(vbuf.v_answered, vset, sizeof vbuf.v_answered); break; } - free(is_set); - CtdlLogPrintf(CTDL_DEBUG, " after update: %s\n", vset); + free(is_set); free(msglist); CtdlSetRelationship(&vbuf, which_user, which_room); } diff --git a/libcitadel/lib/tools.c b/libcitadel/lib/tools.c index fac3cb5ad..66b85ad23 100644 --- a/libcitadel/lib/tools.c +++ b/libcitadel/lib/tools.c @@ -881,10 +881,8 @@ int is_msg_in_mset(char *mset, long msgnum) { /* - * \brief searches for a paternn within asearch string - * \param search the string to search - * \param patn the pattern to find in string - * \returns position in string + * searches for a pattern within a search string + * returns position in string */ int pattern2(char *search, char *patn) { -- 2.30.2