]> code.citadel.org Git - citadel.git/blobdiff - citadel/imap_store.c
* Added "instant expunge" and "allow spoofing" site config options.
[citadel.git] / citadel / imap_store.c
index dade924ba41f365b6eaa6a272bc494d44fb040ad..49784cc13dadd0092cb7f0180f917cf516b41d99 100644 (file)
 #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"
 #include "config.h"
-#include "dynloader.h"
+#include "serv_extensions.h"
 #include "room_ops.h"
 #include "user_ops.h"
 #include "policy.h"
 #include "genstamp.h"
 
 
+
+
+
+
 /*
- * imap_do_store() calls imap_do_store_msg() to output the deta of an
- * individual message, once it has been successfully loaded from disk.
+ * imap_do_store() calls imap_do_store_msg() to tweak the settings of
+ * an individual message.
+ *
+ * We also implement the ".SILENT" protocol option here.  :(
  */
-void imap_do_store_msg(int num, int num_items, char **itemlist) {
-       int i;
-       int flagbucket = 0;
-
-       /* at this point it should be down to "item (flags)" */
-       if (num_items < 2) return;
+void imap_do_store_msg(int seq, char *oper, unsigned int bits_to_twiddle) {
+       int silent = 0;
 
-       /* put together the flag bucket */
-       for (i=0; i<strlen(itemlist[1]); ++i) {
-               if (!strncasecmp(&itemlist[1][i], "\\Deleted", 8))
-                       flagbucket |= IMAP_DELETED;
+       if (!strncasecmp(oper, "FLAGS", 5)) {
+               IMAP->flags[seq] &= IMAP_MASK_SYSTEM;
+               IMAP->flags[seq] |= bits_to_twiddle;
+               silent = strncasecmp(&oper[5], ".SILENT", 7);
        }
-
-       /*
-        * Figure out what to do and do it.  Brazenly IGnore the ".SILENT"
-        * option, since it is not illegal to output the data anyway.
-        */
-       if (!strncasecmp(itemlist[0], "FLAGS", 5)) {
-               IMAP->flags[num] &= IMAP_INTERNAL_MASK;
-               IMAP->flags[num] |= flagbucket;
+       else if (!strncasecmp(oper, "+FLAGS", 6)) {
+               IMAP->flags[seq] |= bits_to_twiddle;
+               silent = strncasecmp(&oper[6], ".SILENT", 7);
        }
-
-       if (!strncasecmp(itemlist[0], "+FLAGS", 6)) {
-               IMAP->flags[num] |= flagbucket;
+       else if (!strncasecmp(oper, "-FLAGS", 6)) {
+               IMAP->flags[seq] &= (~bits_to_twiddle);
+               silent = strncasecmp(&oper[6], ".SILENT", 7);
        }
 
-       if (!strncasecmp(itemlist[0], "-FLAGS", 6)) {
-               IMAP->flags[num] &= ~flagbucket;
+       if (bits_to_twiddle & IMAP_SEEN) {
+               CtdlSetSeen(IMAP->msgids[seq],
+                       ((IMAP->flags[seq] & IMAP_SEEN) ? 1 : 0),
+                       ctdlsetseen_seen,
+                       NULL, NULL
+               );
+       }
+       if (bits_to_twiddle & IMAP_ANSWERED) {
+               CtdlSetSeen(IMAP->msgids[seq],
+                       ((IMAP->flags[seq] & IMAP_ANSWERED) ? 1 : 0),
+                       ctdlsetseen_answered,
+                       NULL, NULL
+               );
        }
 
-       /*
-        * Tell the client what happen (someone set up us the bomb!)
+       /* '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.
         */
-       cprintf("* %d FETCH ", num+1);  /* output sequence number */
-       imap_output_flags(num);
-       cprintf("\r\n");
+       if (silent) {
+               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 the flags.
  */
-void imap_do_store(int num_items, char **itemlist, int is_uid) {
-       int i;
+void imap_do_store(int num_items, char **itemlist) {
+       int i, j;
+       unsigned int bits_to_twiddle = 0;
+       char *oper;
+       char flag[32];
+       char whichflags[256];
+       char num_flags;
+
+       if (num_items < 2) return;
+       oper = itemlist[0];
+
+       for (i=1; i<num_items; ++i) {
+               strcpy(whichflags, itemlist[i]);
+               if (whichflags[0]=='(') safestrncpy(whichflags, &whichflags[1], sizeof whichflags);
+               if (whichflags[strlen(whichflags)-1]==')') {
+                       whichflags[strlen(whichflags)-1]=0;
+               }
+               striplt(whichflags);
+
+               /* A client might twiddle more than one bit at a time.
+                * Note that we check for the flag names without the leading
+                * backslash because imap_parameterize() strips them out.
+                */
+               num_flags = num_tokens(whichflags, ' ');
+               for (j=0; j<num_flags; ++j) {
+                       extract_token(flag, whichflags, j, ' ', sizeof flag);
+
+                       if ((!strcasecmp(flag, "\\Deleted"))
+                          || (!strcasecmp(flag, "Deleted"))) {
+                               if (CtdlDoIHavePermissionToDeleteMessagesFromThisRoom()) {
+                                       bits_to_twiddle |= IMAP_DELETED;
+                               }
+                       }
+                       if ((!strcasecmp(flag, "\\Seen"))
+                          || (!strcasecmp(flag, "Seen"))) {
+                               bits_to_twiddle |= IMAP_SEEN;
+                       }
+                       if ((!strcasecmp(flag, "\\Answered")) 
+                          || (!strcasecmp(flag, "\\Answered"))) {
+                               bits_to_twiddle |= IMAP_ANSWERED;
+                       }
+               }
+       }
 
        if (IMAP->num_msgs > 0) {
                for (i = 0; i < IMAP->num_msgs; ++i) {
-                       if (IMAP->flags[i] && IMAP_SELECTED) {
-                               imap_do_store_msg(i, num_items, itemlist);
+                       if (IMAP->flags[i] & IMAP_SELECTED) {
+                               imap_do_store_msg(i, oper, bits_to_twiddle);
                        }
                }
        }
+
+       /*
+        * The following two commands implement "instant expunge" if enabled.
+        */
+       if (config.c_instant_expunge) {
+               imap_do_expunge();
+               imap_rescan_msgids();
+       }
+
 }
 
 
@@ -112,7 +183,7 @@ void imap_store(int num_parms, char *parms[]) {
        int num_items;
        int i;
 
-       if (num_parms < 4) {
+       if (num_parms < 3) {
                cprintf("%s BAD invalid parameters\r\n", parms[0]);
                return;
        }
@@ -121,8 +192,7 @@ void imap_store(int num_parms, char *parms[]) {
                imap_pick_range(parms[2], 0);
        }
        else {
-               cprintf("%s BAD No message set specified to STORE\r\n",
-                       parms[0]);
+               cprintf("%s BAD invalid parameters\r\n", parms[0]);
                return;
        }
 
@@ -138,7 +208,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]);
 }
 
@@ -151,7 +221,7 @@ void imap_uidstore(int num_parms, char *parms[]) {
        int num_items;
        int i;
 
-       if (num_parms < 5) {
+       if (num_parms < 4) {
                cprintf("%s BAD invalid parameters\r\n", parms[0]);
                return;
        }
@@ -160,8 +230,7 @@ void imap_uidstore(int num_parms, char *parms[]) {
                imap_pick_range(parms[3], 1);
        }
        else {
-               cprintf("%s BAD No message set specified to STORE\r\n",
-                       parms[0]);
+               cprintf("%s BAD invalid parameters\r\n", parms[0]);
                return;
        }
 
@@ -177,7 +246,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]);
 }