From b3bce1c9030b1ed9562e624beb1f5c37dc365983 Mon Sep 17 00:00:00 2001 From: Art Cancro Date: Fri, 22 Apr 2005 04:26:35 +0000 Subject: [PATCH] * is_msg_is_mset() has been renamed to is_msg_in_sequence_set() because "sequence set" is now the official terminology as of RFC3501. * imap_set_seen_flags() no longer calls is_msg_in_sequence_set() for each message and for each flag. It's just too expensive. We now parse each flag's sequence set manually, marking the relevant messages as we go. --- citadel/ChangeLog | 9 ++++++ citadel/imap_search.c | 2 +- citadel/msgbase.c | 4 +-- citadel/room_ops.c | 4 +-- citadel/serv_imap.c | 70 ++++++++++++++++++++++++++++++++++++------- citadel/serv_pop3.c | 2 +- citadel/tools.c | 9 ++---- citadel/tools.h | 2 +- 8 files changed, 78 insertions(+), 24 deletions(-) diff --git a/citadel/ChangeLog b/citadel/ChangeLog index c4cd8b67a..a3733a906 100644 --- a/citadel/ChangeLog +++ b/citadel/ChangeLog @@ -1,4 +1,11 @@ $Log$ + Revision 645.8 2005/04/22 04:26:34 ajc + * is_msg_is_mset() has been renamed to is_msg_in_sequence_set() because + "sequence set" is now the official terminology as of RFC3501. + * imap_set_seen_flags() no longer calls is_msg_in_sequence_set() for each + message and for each flag. It's just too expensive. We now parse each + flag's sequence set manually, marking the relevant messages as we go. + Revision 645.7 2005/04/22 00:52:03 ajc * small fix to previous commit @@ -6610,3 +6617,5 @@ Sat Jul 11 00:20:48 EDT 1998 Nathan Bryant Fri Jul 10 1998 Art Cancro * Initial CVS import + + diff --git a/citadel/imap_search.c b/citadel/imap_search.c index dac0ee6d1..16cabdf98 100644 --- a/citadel/imap_search.c +++ b/citadel/imap_search.c @@ -361,7 +361,7 @@ int imap_do_search_msg(int seq, struct CtdlMessage *supplied_msg, } else if (!strcasecmp(itemlist[pos], "UID")) { - if (is_msg_in_mset(itemlist[pos+1], IMAP->msgids[seq-1])) { + if (is_msg_in_sequence_set(itemlist[pos+1], IMAP->msgids[seq-1])) { match = 1; } pos += 2; diff --git a/citadel/msgbase.c b/citadel/msgbase.c index 880875131..75a6830a1 100644 --- a/citadel/msgbase.c +++ b/citadel/msgbase.c @@ -349,7 +349,7 @@ void CtdlSetSeen(long target_msgnum, int target_setting, int which_set) { is_seen = target_setting; } else { - if (is_msg_in_mset(vset, msglist[i])) { + if (is_msg_in_sequence_set(vset, msglist[i])) { is_seen = 1; } } @@ -490,7 +490,7 @@ int CtdlForEachMessage(int mode, long ref, if (num_msgs > 0) for (a = 0; a < num_msgs; ++a) { thismsg = msglist[a]; - is_seen = is_msg_in_mset(vbuf.v_seen, thismsg); + is_seen = is_msg_in_sequence_set(vbuf.v_seen, thismsg); if (is_seen) lastold = thismsg; if ((thismsg > 0L) && ( diff --git a/citadel/room_ops.c b/citadel/room_ops.c index b335942d2..47ae34128 100644 --- a/citadel/room_ops.c +++ b/citadel/room_ops.c @@ -152,7 +152,7 @@ void CtdlRoomAccess(struct ctdlroom *roombuf, struct ctdluser *userbuf, } NEWMSG: /* By the way, we also check for the presence of new messages */ - if (is_msg_in_mset(vbuf.v_seen, roombuf->QRhighest) == 0) { + if (is_msg_in_sequence_set(vbuf.v_seen, roombuf->QRhighest) == 0) { retval = retval | UA_HASNEWMSGS; } @@ -829,7 +829,7 @@ void usergoto(char *where, int display_result, int transiently, if (num_msgs > 0) for (a = 0; a < num_msgs; ++a) { if (msglist[a] > 0L) { ++total_messages; - if (is_msg_in_mset(vbuf.v_seen, msglist[a]) == 0) { + if (is_msg_in_sequence_set(vbuf.v_seen, msglist[a]) == 0) { ++new_messages; } } diff --git a/citadel/serv_imap.c b/citadel/serv_imap.c index 2eaa0b3be..ef157b2b1 100644 --- a/citadel/serv_imap.c +++ b/citadel/serv_imap.c @@ -108,30 +108,81 @@ void imap_free_transmitted_message(void) /* - * Set the \\Seen flag for messages which aren't new + * Set the \Seen, \Recent. and \Answered flags, based on the sequence + * sets stored in the visit record for this user/room. Note that we have + * to parse each sequence set manually here, because calling the utility + * function is_msg_in_sequence_set() over and over again is too expensive. */ void imap_set_seen_flags(void) { struct visit vbuf; int i; + int num_sets; + int s; + char setstr[SIZ], lostr[SIZ], histr[SIZ]; + long lo, hi; + if (IMAP->num_msgs < 1) return; CtdlGetRelationship(&vbuf, &CC->user, &CC->room); - if (IMAP->num_msgs > 0) { + + for (i = 0; i < IMAP->num_msgs; ++i) { + IMAP->flags[i] = IMAP->flags[i] & ~IMAP_SEEN; + IMAP->flags[i] |= IMAP_RECENT; + IMAP->flags[i] = IMAP->flags[i] & ~IMAP_ANSWERED; + } + + /* Do the "\Seen" flag. (Any message not "\Seen" is considered "\Recent".) */ + num_sets = num_tokens(vbuf.v_seen, ','); + for (s=0; s= 2) { + extract_token(histr, setstr, 1, ':', sizeof histr); + if (!strcmp(histr, "*")) { + snprintf(histr, sizeof histr, "%ld", LONG_MAX); + } + } + else { + strcpy(histr, lostr); + } + lo = atol(lostr); + hi = atol(histr); + for (i = 0; i < IMAP->num_msgs; ++i) { - if (is_msg_in_mset(vbuf.v_seen, IMAP->msgids[i])) { + if ((IMAP->msgids[i] >= lo) && (IMAP->msgids[i] <= hi)) { IMAP->flags[i] |= IMAP_SEEN; + IMAP->flags[i] = IMAP->flags[i] & ~IMAP_RECENT; } - else { - IMAP->flags[i] |= IMAP_RECENT; + } + } + + /* Do the ANSWERED flag */ + num_sets = num_tokens(vbuf.v_answered, ','); + for (s=0; s= 2) { + extract_token(histr, setstr, 1, ':', sizeof histr); + if (!strcmp(histr, "*")) { + snprintf(histr, sizeof histr, "%ld", LONG_MAX); } - if (is_msg_in_mset - (vbuf.v_answered, IMAP->msgids[i])) { + } + else { + strcpy(histr, lostr); + } + lo = atol(lostr); + hi = atol(histr); + + for (i = 0; i < IMAP->num_msgs; ++i) { + if ((IMAP->msgids[i] >= lo) && (IMAP->msgids[i] <= hi)) { IMAP->flags[i] |= IMAP_ANSWERED; } } } -} +} @@ -175,8 +226,6 @@ void imap_load_msgids(void) imap_add_single_msgid, NULL); imap_set_seen_flags(); - /* lprintf(CTDL_DEBUG, "imap_load_msgids() mapped %d messages\n", - IMAP->num_msgs); */ } @@ -195,7 +244,6 @@ void imap_rescan_msgids(void) int num_msgs = 0; int num_recent = 0; - if (IMAP->selected == 0) { lprintf(CTDL_ERR, "imap_load_msgids() can't run; no room selected\n"); diff --git a/citadel/serv_pop3.c b/citadel/serv_pop3.c index f09852c2e..d83f01f3e 100644 --- a/citadel/serv_pop3.c +++ b/citadel/serv_pop3.c @@ -188,7 +188,7 @@ int pop3_grab_mailbox(void) { CtdlGetRelationship(&vbuf, &CC->user, &CC->room); POP3->lastseen = (-1); if (POP3->num_msgs) for (i=0; inum_msgs; ++i) { - if (is_msg_in_mset(vbuf.v_seen, + if (is_msg_in_sequence_set(vbuf.v_seen, (POP3->msgs[POP3->num_msgs-1].msgnum) )) { POP3->lastseen = i; } diff --git a/citadel/tools.c b/citadel/tools.c index b1e95fcc4..abdf2bc8d 100644 --- a/citadel/tools.c +++ b/citadel/tools.c @@ -409,17 +409,14 @@ void fmt_date(char *buf, size_t n, time_t thetime, int seconds) { /* * Determine whether the specified message number is contained within the - * specified set. + * specified sequence set. */ -int is_msg_in_mset(char *mset, long msgnum) { +int is_msg_in_sequence_set(char *mset, long msgnum) { int num_sets; int s; - char setstr[SIZ], lostr[SIZ], histr[SIZ]; /* was 1024 */ + char setstr[SIZ], lostr[SIZ], histr[SIZ]; long lo, hi; - /* - * Now set it for all specified messages. - */ num_sets = num_tokens(mset, ','); for (s=0; s