X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=citadel%2Fimap_store.c;h=7e163787b227a2880ff548426e23721fdaf61edc;hb=6811477765e483adae130a5d2b39f12968e3500a;hp=8ba5ba5e713d348128f65eb167b702ca27be2626;hpb=8e5a6caa1b7c687ef2fad2c76c06d12d0ed3ae67;p=citadel.git diff --git a/citadel/imap_store.c b/citadel/imap_store.c index 8ba5ba5e7..7e163787b 100644 --- a/citadel/imap_store.c +++ b/citadel/imap_store.c @@ -37,7 +37,6 @@ #include "citserver.h" #include "support.h" #include "config.h" -#include "serv_extensions.h" #include "room_ops.h" #include "user_ops.h" #include "policy.h" @@ -60,39 +59,20 @@ * imap_do_store() calls imap_do_store_msg() to tweak the settings of * an individual message. * - * We also implement the ".SILENT" protocol option here. Leave it to an - * idiot like Mark Crispin to make things unnecessarily complicated. + * We also implement the ".SILENT" protocol option here. :( */ void imap_do_store_msg(int seq, char *oper, unsigned int bits_to_twiddle) { - int silent = 0; + if (!strncasecmp(oper, "FLAGS", 5)) { IMAP->flags[seq] &= IMAP_MASK_SYSTEM; IMAP->flags[seq] |= bits_to_twiddle; - silent = strncasecmp(&oper[5], ".SILENT", 7); } else if (!strncasecmp(oper, "+FLAGS", 6)) { IMAP->flags[seq] |= bits_to_twiddle; - silent = strncasecmp(&oper[6], ".SILENT", 7); } else if (!strncasecmp(oper, "-FLAGS", 6)) { IMAP->flags[seq] &= (~bits_to_twiddle); - silent = strncasecmp(&oper[6], ".SILENT", 7); - } - - if (bits_to_twiddle & IMAP_SEEN) { - CtdlSetSeen(IMAP->msgids[seq], - ((IMAP->flags[seq] & IMAP_SEEN) ? 1 : 0) ); - } - - /* 'silent' is actually the value returned from a strncasecmp() so - * we want that option only if its value is zero. Seems backwards - * but that's the way it's supposed to be. - */ - if (silent) { - cprintf("* %d FETCH (", seq+1); - imap_fetch_flags(seq); - cprintf(")\r\n"); } } @@ -106,44 +86,117 @@ void imap_do_store(int num_items, char **itemlist) { int i, j; unsigned int bits_to_twiddle = 0; char *oper; - char flag[SIZ]; - char whichflags[SIZ]; + char flag[32]; + char whichflags[256]; char num_flags; + int silent = 0; + long *ss_msglist; + int num_ss = 0; + int last_item_twiddled = (-1); if (num_items < 2) return; oper = itemlist[0]; + if (bmstrcasestr(oper, ".SILENT")) { + silent = 1; + } + + /* + * ss_msglist is an array of message numbers to manipulate. We + * are going to supply this array to CtdlSetSeen() later. + */ + ss_msglist = malloc(IMAP->num_msgs * sizeof(long)); + if (ss_msglist == NULL) return; + /* + * Ok, go ahead and parse the flags. + */ for (i=1; inum_msgs > 0) { for (i = 0; i < IMAP->num_msgs; ++i) { if (IMAP->flags[i] & IMAP_SELECTED) { + last_item_twiddled = i; + + ss_msglist[num_ss++] = IMAP->msgids[i]; imap_do_store_msg(i, oper, bits_to_twiddle); + + if (!silent) { + cprintf("* %d FETCH (", i+1); + imap_fetch_flags(i); + cprintf(")\r\n"); + } + } } } + + /* + * Now manipulate the database -- all in one shot. + */ + if ( (last_item_twiddled >= 0) && (num_ss > 0) ) { + + if (bits_to_twiddle & IMAP_SEEN) { + CtdlSetSeen(ss_msglist, num_ss, + ((IMAP->flags[last_item_twiddled] & IMAP_SEEN) ? 1 : 0), + ctdlsetseen_seen, + NULL, NULL + ); + } + + if (bits_to_twiddle & IMAP_ANSWERED) { + CtdlSetSeen(ss_msglist, num_ss, + ((IMAP->flags[last_item_twiddled] & IMAP_ANSWERED) ? 1 : 0), + ctdlsetseen_answered, + NULL, NULL + ); + } + + } + + free(ss_msglist); + + /* + * The following two commands implement "instant expunge" if enabled. + */ + if (config.c_instant_expunge) { + imap_do_expunge(); + imap_rescan_msgids(); + } + }