* Copyright (C) 2000-2001 by Art Cancro and others.
* This code is released under the terms of the GNU General Public License.
*
- * WARNING: this is an incomplete implementation, still in progress. Parts of
- * it work, but it's not really usable yet from a user perspective.
+ * WARNING: this is an incomplete implementation. It is now good enough to
+ * be usable with much of the popular IMAP client software available, but it
+ * is by no means perfect. Some commands (particularly SEARCH and RENAME)
+ * are implemented either incompletely or not at all.
*
* WARNING: Mark Crispin is an idiot. IMAP is the most brain-damaged protocol
* you will ever have the profound lack of pleasure to encounter.
#include <pwd.h>
#include <errno.h>
#include <sys/types.h>
-#include <sys/time.h>
+
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else
+# include <time.h>
+# endif
+#endif
+
#include <sys/wait.h>
#include <ctype.h>
#include <string.h>
#include <limits.h>
#include "citadel.h"
#include "server.h"
-#include <time.h>
#include "sysdep_decls.h"
#include "citserver.h"
#include "support.h"
}
+/*
+ * Set the \\Seen flag for messages which aren't new
+ */
+void imap_set_seen_flags(void) {
+ struct visit vbuf;
+ int i;
+
+ CtdlGetRelationship(&vbuf, &CC->usersupp, &CC->quickroom);
+ if (IMAP->num_msgs > 0) {
+ for (i=0; i<IMAP->num_msgs; ++i) {
+ if (is_msg_in_mset(vbuf.v_seen, IMAP->msgids[i])) {
+ IMAP->flags[i] |= IMAP_SEEN;
+ }
+ }
+ }
+}
+
+
+
+
/*
* Back end for imap_load_msgids()
*
- * FIXME: this should be optimized by figuring out a way to allocate memory
- * once rather than doing a reallok() for each message.
+ * Optimization: instead of calling realloc() to add each message, we
+ * allocate space in the list for REALLOC_INCREMENT messages at a time. This
+ * allows the mapping to proceed much faster.
*/
void imap_add_single_msgid(long msgnum, void *userdata) {
IMAP->num_msgs = IMAP->num_msgs + 1;
if (IMAP->msgids == NULL) {
- IMAP->msgids = mallok(IMAP->num_msgs * sizeof(long));
+ IMAP->msgids = mallok(IMAP->num_msgs * sizeof(long)
+ * REALLOC_INCREMENT);
}
- else {
+ else if (IMAP->num_msgs % REALLOC_INCREMENT == 0) {
IMAP->msgids = reallok(IMAP->msgids,
- IMAP->num_msgs * sizeof(long));
+ (IMAP->num_msgs + REALLOC_INCREMENT) * sizeof(long));
}
if (IMAP->flags == NULL) {
- IMAP->flags = mallok(IMAP->num_msgs * sizeof(long));
+ IMAP->flags = mallok(IMAP->num_msgs * sizeof(long)
+ * REALLOC_INCREMENT);
}
- else {
+ else if (IMAP->num_msgs % REALLOC_INCREMENT == 0) {
IMAP->flags = reallok(IMAP->flags,
- IMAP->num_msgs * sizeof(long));
+ (IMAP->num_msgs + REALLOC_INCREMENT) * sizeof(long));
}
IMAP->msgids[IMAP->num_msgs - 1] = msgnum;
IMAP->flags[IMAP->num_msgs - 1] = 0;
CtdlForEachMessage(MSGS_ALL, 0L, (-63), NULL, NULL,
imap_add_single_msgid, NULL);
+ imap_set_seen_flags();
lprintf(9, "imap_load_msgids() mapped %d messages\n", IMAP->num_msgs);
}
CtdlForEachMessage(MSGS_GT, original_highest, (-63), NULL, NULL,
imap_add_single_msgid, NULL);
+ imap_set_seen_flags();
+
/*
* If new messages have arrived, tell the client about them.
*/
/* FIXME ... much more info needs to be supplied here */
cprintf("* %d EXISTS\r\n", msgs);
cprintf("* %d RECENT\r\n", new);
- cprintf("* FLAGS (\\Deleted)\r\n");
- cprintf("* OK [PERMANENTFLAGS (\\Deleted)] permanent flags\r\n");
+ cprintf("* FLAGS (\\Deleted \\Seen)\r\n");
+ cprintf("* OK [PERMANENTFLAGS (\\Deleted \\Seen)] permanent flags\r\n");
cprintf("* OK [UIDVALIDITY 0] UIDs valid\r\n");
cprintf("%s OK [%s] %s completed\r\n",
parms[0],
/*
* Implements the LSUB command
- *
- * FIXME: Handle wildcards, please.
*/
void imap_lsub(int num_parms, char *parms[]) {
char pattern[SIZ];
/*
* Implements the LIST command
- *
- * FIXME: Handle wildcards, please.
*/
void imap_list(int num_parms, char *parms[]) {
char pattern[SIZ];
* it wants to know. We happily IGnore the supplied status data item
* names and simply spew all possible data items. It's far easier to
* code and probably saves us some processing time too.
- *
- * FIXME we need to implement RECENT and UNSEEN eventually...
*/
-
imap_mailboxname(buf, sizeof buf, &CC->quickroom);
cprintf("* STATUS ");
imap_strout(buf);
- cprintf(" (MESSAGES %d RECENT 0 UIDNEXT %ld "
- "UIDVALIDITY 0 UNSEEN 0)\r\n",
- msgs,
- CitControl.MMhighest + 1
- );
+ cprintf(" (MESSAGES %d ", msgs);
+ cprintf("RECENT 0 "); /* FIXME we need to implement this */
+ cprintf("UIDNEXT %ld ", CitControl.MMhighest + 1);
+ cprintf("UNSEEN %d)\r\n", new);
/*
* If another folder is selected, go back to that room so we can resume