]> code.citadel.org Git - citadel.git/commitdiff
* Probable completion of STATUS, COPY, STORE, and EXPUNGE commands in IMAP
authorArt Cancro <ajc@citadel.org>
Tue, 6 Mar 2001 04:44:01 +0000 (04:44 +0000)
committerArt Cancro <ajc@citadel.org>
Tue, 6 Mar 2001 04:44:01 +0000 (04:44 +0000)
citadel/ChangeLog
citadel/imap_fetch.c
citadel/imap_fetch.h
citadel/imap_misc.c
citadel/imap_store.c
citadel/serv_imap.c
citadel/serv_imap.h

index ece984e9c9c62347c384768709899647e937509b..7bb68008d3867e8209c268bf74e882efd3d3c529 100644 (file)
@@ -1,4 +1,7 @@
  $Log$
+ Revision 573.108  2001/03/06 04:44:00  ajc
+ * Probable completion of STATUS, COPY, STORE, and EXPUNGE commands in IMAP
+
  Revision 573.107  2001/03/06 03:31:58  nbryant
  database-related cleanups and paranoia tests;
  fixed a transaction-leak/deadlock problem in cdb_delete;
@@ -2435,3 +2438,4 @@ Sat Jul 11 00:20:48 EDT 1998 Nathan Bryant <bryant@cs.usm.maine.edu>
 
 Fri Jul 10 1998 Art Cancro <ajc@uncensored.citadel.org>
        * Initial CVS import 
+
index 0451ccc51a20d3d0ef7c9526f430d462a2073e83..8cc32216e03d0be9ccfef11ab6417e8790593a0d 100644 (file)
@@ -59,8 +59,10 @@ void imap_fetch_uid(int seq) {
        cprintf("UID %ld", IMAP->msgids[seq-1]);
 }
 
-void imap_fetch_flags(struct CtdlMessage *msg) {
-       cprintf("FLAGS ()");    /* FIXME do something here */
+void imap_fetch_flags(int seq) {
+       cprintf("FLAGS (");
+       if (IMAP->flags[seq] & IMAP_DELETED) cprintf("\\Deleted ");
+       cprintf(")");
 }
 
 void imap_fetch_internaldate(struct CtdlMessage *msg) {
@@ -633,7 +635,7 @@ void imap_do_fetch_msg(int seq, struct CtdlMessage *msg,
                        imap_fetch_envelope(IMAP->msgids[seq-1], msg);
                }
                else if (!strcasecmp(itemlist[i], "FLAGS")) {
-                       imap_fetch_flags(msg);
+                       imap_fetch_flags(seq-1);
                }
                else if (!strcasecmp(itemlist[i], "INTERNALDATE")) {
                        imap_fetch_internaldate(msg);
index b3f80dfc91d7c3eef12993df4177b170229875f7..f8ed5f1a48a7d0d221a4b36fc12956515c051c4e 100644 (file)
@@ -6,4 +6,5 @@
 void imap_pick_range(char *range, int is_uid);
 void imap_fetch(int num_parms, char *parms[]);
 void imap_uidfetch(int num_parms, char *parms[]);
+void imap_fetch_flags(int seq);
 int imap_extract_data_items(char **argv, char *items);
index 2f3072a13bf97d7162e52f6b98c9a466bd994d82..bb0cf672bf7f3740f8f153935bb123742df2ba08 100644 (file)
@@ -65,7 +65,7 @@ int imap_do_copy(char *destination_folder) {
                }
        }
 
-       return(1);
+       return(0);
 }
 
 
@@ -73,6 +73,7 @@ int imap_do_copy(char *destination_folder) {
  * This function is called by the main command loop.
  */
 void imap_copy(int num_parms, char *parms[]) {
+       int ret;
 
        if (num_parms != 4) {
                cprintf("%s BAD invalid parameters\r\n", parms[0]);
@@ -87,11 +88,12 @@ void imap_copy(int num_parms, char *parms[]) {
                return;
        }
 
-       if (imap_do_copy(parms[3]) == 0) {
+       ret = imap_do_copy(parms[3]);
+       if (!ret) {
                cprintf("%s OK COPY completed\r\n", parms[0]);
        }
        else {
-               cprintf("%s NO COPY failed\r\n", parms[0]);
+               cprintf("%s NO COPY failed (error %d)\r\n", parms[0], ret);
        }
 }
 
index 4861532c348915e06fcacea056a25939845d71ce..921648acccff5c93744d58b7e2846dfd09e68f2f 100644 (file)
  * imap_do_store() calls imap_do_store_msg() to output the deta of an
  * individual message, once it has been successfully loaded from disk.
  */
-void imap_do_store_msg(int seq, struct CtdlMessage *msg,
-                       int num_items, char **itemlist, int is_uid) {
-
+void imap_do_store_msg(int seq, char *oper, unsigned int bits_to_twiddle) {
+       
+       if (!strncasecmp(oper, "FLAGS", 5)) {
+               IMAP->flags[seq] &= IMAP_MASK_SYSTEM;
+               IMAP->flags[seq] |= bits_to_twiddle;
+       }
+       else if (!strncasecmp(oper, "+FLAGS", 6)) {
+               IMAP->flags[seq] |= bits_to_twiddle;
+       }
+       else if (!strncasecmp(oper, "-FLAGS", 6)) {
+               IMAP->flags[seq] &= (~bits_to_twiddle);
+       }
 
+       cprintf("* %d FETCH (", seq+1);
+       imap_fetch_flags(seq);
+       cprintf(")\r\n");
 }
 
 
 
 /*
- * imap_store() calls imap_do_store() to do its actual work, once it's
- * validated and boiled down the request a bit.
+ * imap_store() calls imap_do_store() to perform the actual bit twiddling
+ * on flags.  We brazenly ignore the ".silent" protocol option because it's not
+ * harmful to send the data anyway.  Fix it yourself if you don't like that.
  */
-void imap_do_store(int num_items, char **itemlist, int is_uid) {
+void imap_do_store(int num_items, char **itemlist) {
        int i;
-       struct CtdlMessage *msg;
-
-       if (IMAP->num_msgs > 0)
-        for (i = 0; i < IMAP->num_msgs; ++i)
-         if (IMAP->flags[i] && IMAP_SELECTED) {
-               msg = CtdlFetchMessage(IMAP->msgids[i]);
-               if (msg != NULL) {
-                       imap_do_store_msg(i+1, msg, num_items,
-                                       itemlist, is_uid);
-                       CtdlFreeMessage(msg);
+       unsigned int bits_to_twiddle = 0;
+       char *oper;
+       char flag[SIZ];
+
+       if (num_items < 2) return;
+       oper = itemlist[0];
+
+       for (i=1; i<num_items; ++i) {
+               strcpy(flag, itemlist[i]);
+               if (flag[0]=='(') strcpy(flag, &flag[1]);
+               if (flag[strlen(flag)-1]==')') flag[strlen(flag)-1]=0;
+               striplt(flag);
+
+               if (!strcasecmp(flag, "\\Deleted")) {
+                       bits_to_twiddle |= IMAP_DELETED;
                }
-               else {
-                       lprintf(1, "IMAP STORE internal error\n");
+       }
+       
+       if (IMAP->num_msgs > 0) {
+               for (i = 0; i < IMAP->num_msgs; ++i) {
+                       if (IMAP->flags[i] && IMAP_SELECTED) {
+                               imap_do_store_msg(i, oper, bits_to_twiddle);
+                       }
                }
        }
 }
@@ -116,7 +139,7 @@ void imap_store(int num_parms, char *parms[]) {
                return;
        }
 
-       imap_do_store(num_items, itemlist, 0);
+       imap_do_store(num_items, itemlist);
        cprintf("%s OK STORE completed\r\n", parms[0]);
 }
 
@@ -154,7 +177,7 @@ void imap_uidstore(int num_parms, char *parms[]) {
                return;
        }
 
-       imap_do_store(num_items, itemlist, 1);
+       imap_do_store(num_items, itemlist);
        cprintf("%s OK UID STORE completed\r\n", parms[0]);
 }
 
index af668a48ee4bf575992d3e4c236c2e79884236f8..35825e1728e41ca73a854b1106c14e95fe544707 100644 (file)
@@ -384,10 +384,47 @@ void imap_select(int num_parms, char *parms[]) {
 
 
 
+/*
+ * does the real work for expunge
+ */
+int imap_do_expunge(void) {
+       int i;
+       int num_expunged = 0;
+
+       if (IMAP->num_msgs > 0) for (i=0; i<IMAP->num_msgs; ++i) {
+               if (IMAP->flags[i] & IMAP_DELETED) {
+                       CtdlDeleteMessages(CC->quickroom.QRname,
+                                       IMAP->msgids[i], "");
+                       ++num_expunged;
+               }
+       }
+
+       if (num_expunged > 0) {
+               imap_rescan_msgids();
+       }
+
+       return(num_expunged);
+}
+
+
+/*
+ * implements the EXPUNGE command syntax
+ */
+void imap_expunge(int num_parms, char *parms[]) {
+       int num_expunged = 0;
+       imap_do_expunge();
+       cprintf("%s OK expunged %d messages.\r\n", parms[0], num_expunged);
+}
+
+
 /*
  * implements the CLOSE command
  */
 void imap_close(int num_parms, char *parms[]) {
+
+       /* Yes, we always expunge on close. */
+       imap_do_expunge();
+
        IMAP->selected = 0;
        IMAP->readonly = 0;
        imap_free_msgids();
@@ -565,7 +602,7 @@ int imap_grabroom(char *returned_roomname, char *foldername) {
        /* Fail here if no such room */
        if (!ok) {
                strcpy(returned_roomname, "");
-               return(1);
+               return(2);
        }
        else {
                strcpy(returned_roomname, QRscratch.QRname);
@@ -582,7 +619,6 @@ void imap_status(int num_parms, char *parms[]) {
        int ret;
        char roomname[ROOMNAMELEN];
        char buf[SIZ];
-       struct quickroom QRscratch;
        char savedroom[ROOMNAMELEN];
        int msgs, new;
 
@@ -612,7 +648,7 @@ void imap_status(int num_parms, char *parms[]) {
         * FIXME we need to implement RECENT and UNSEEN eventually...
         */
 
-       imap_mailboxname(buf, sizeof buf, &QRscratch);
+       imap_mailboxname(buf, sizeof buf, &CC->quickroom);
        cprintf("* STATUS ");
        imap_strout(buf);
        cprintf(" (MESSAGES %d RECENT 0 UIDNEXT %ld "
@@ -793,6 +829,10 @@ void imap_command_loop(void) {
                imap_uidcopy(num_parms, parms);
        }
 
+       else if (!strcasecmp(parms[1], "EXPUNGE")) {
+               imap_expunge(num_parms, parms);
+       }
+
        else if (!strcasecmp(parms[1], "CLOSE")) {
                imap_close(num_parms, parms);
        }
index e2c082b93614e7961347a8c4396c7099b399fbfb..0308f41cf7f428315e24ac863e96b0d0ae751fd5 100644 (file)
@@ -33,12 +33,16 @@ enum {
 /* Flags for the above struct.  Note that some of these are for internal use,
  * and are not to be reported to IMAP clients.
  */
-#define IMAP_ANSWERED  1
-#define IMAP_FLAGGED   2
-#define IMAP_DELETED   4
-#define IMAP_DRAFT     8
-#define IMAP_SEEN      16
-#define IMAP_SELECTED  32      /* internal */
+#define IMAP_ANSWERED          1
+#define IMAP_FLAGGED           2
+#define IMAP_DELETED           4
+#define IMAP_DRAFT             8
+#define IMAP_SEEN              16
+
+#define IMAP_MASK_SETABLE      0x1f
+#define IMAP_MASK_SYSTEM       0xe0
+
+#define IMAP_SELECTED          32      /* internal */
 
 
 #define IMAP ((struct citimap *)CtdlGetUserData(SYM_IMAP))