* IMAP COPY
authorArt Cancro <ajc@citadel.org>
Mon, 5 Mar 2001 04:59:32 +0000 (04:59 +0000)
committerArt Cancro <ajc@citadel.org>
Mon, 5 Mar 2001 04:59:32 +0000 (04:59 +0000)
citadel/ChangeLog
citadel/Makefile.in
citadel/imap_fetch.c
citadel/imap_misc.c [new file with mode: 0644]
citadel/imap_misc.h [new file with mode: 0644]
citadel/imap_search.c
citadel/imap_store.c
citadel/msgbase.c
citadel/msgbase.h
citadel/serv_imap.c
citadel/serv_imap.h

index 9d7e866ca655360d6bca8eff2e81c91bb0b59419..c5cc5e329cec6ba7dc37ea102a3d31a519d5d57e 100644 (file)
@@ -1,4 +1,7 @@
  $Log$
+ Revision 573.106  2001/03/05 04:59:31  ajc
+ * IMAP COPY
+
  Revision 573.105  2001/03/04 23:49:41  ajc
  * IMAP EXPUNGE responses -should- be correct now
 
@@ -2427,3 +2430,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 cc0330de6334bb5d5422206c8f60e634ce236237..fbc02c0fd00e2851f4087a89cf37fd805b5a9db8 100644 (file)
@@ -89,7 +89,7 @@ SOURCES=aidepost.c citadel.c citmail.c citserver.c client_chat.c commands.c \
        auth.c chkpwd.c html.c vcard.c serv_upgrade.c serv_vandelay.c \
        serv_smtp.c serv_pop3.c internet_addressing.c parsedate.c genstamp.c \
        domain.c clientsocket.c serv_inetcfg.c serv_rwho.c serv_bio.c \
-       serv_moderate.c client_passwords.c \
+       serv_moderate.c client_passwords.c imap_misc.c \
        serv_imap.c imap_tools.c imap_fetch.c imap_search.c imap_store.c \
        serv_network.c serv_pas2.c serv_ical.c md5.c
 
@@ -153,106 +153,46 @@ citserver: $(SERV_OBJS)
 modules/serv_chat.so: serv_chat.mo
        $(LINK_SHARED) -o modules/serv_chat.so serv_chat.mo
 
-modules/serv_chat.mo: serv_chat.mo
-       ln -f serv_chat.mo modules
-
 modules/serv_test.so: serv_test.mo
        $(LINK_SHARED) -o modules/serv_test.so serv_test.mo
 
-modules/serv_test.mo: serv_test.mo
-       ln -f serv_test.mo modules
-
 modules/serv_pop3.so: serv_pop3.mo md5.mo
        $(LINK_SHARED) -o modules/serv_pop3.so serv_pop3.mo md5.mo
 
-modules/serv_pop3.mo: serv_pop3.mo
-       ln -f serv_pop3.mo modules
-
 modules/serv_inetcfg.so: serv_inetcfg.mo
        $(LINK_SHARED) -o modules/serv_inetcfg.so serv_inetcfg.mo
 
-modules/serv_inetcfg.mo: serv_inetcfg.mo
-       ln -f serv_inetcfg.mo modules
-
 modules/serv_rwho.so: serv_rwho.mo
        $(LINK_SHARED) -o modules/serv_rwho.so serv_rwho.mo
 
-modules/serv_rwho.mo: serv_rwho.mo
-       ln -f serv_rwho.mo modules
-
 modules/serv_moderate.so: serv_moderate.mo
        $(LINK_SHARED) -o modules/serv_moderate.so serv_moderate.mo
 
-modules/serv_moderate.mo: serv_moderate.mo
-       ln -f serv_moderate.mo modules
-
 modules/serv_bio.so: serv_bio.mo
        $(LINK_SHARED) -o modules/serv_bio.so serv_bio.mo
 
-modules/serv_bio.mo: serv_bio.mo
-       ln -f serv_bio.mo modules
-
 modules/serv_expire.so: serv_expire.mo
        $(LINK_SHARED) -o modules/serv_expire.so serv_expire.mo
 
-modules/serv_expire.mo: serv_expire.mo
-       ln -f serv_expire.mo modules
-
 modules/serv_vandelay.so: serv_vandelay.mo
        $(LINK_SHARED) -o modules/serv_vandelay.so serv_vandelay.mo
 
-modules/serv_vandelay.mo: serv_vandelay.mo
-       ln -f serv_vandelay.mo modules
-
 modules/serv_network.so: serv_network.mo
        $(LINK_SHARED) -o modules/serv_network.so serv_network.mo
 
-modules/serv_network.mo: serv_network.mo
-       ln -f serv_network.mo modules
-
 modules/serv_upgrade.so: serv_upgrade.mo
        $(LINK_SHARED) -o modules/serv_upgrade.so serv_upgrade.mo
 
-modules/serv_upgrade.mo: serv_upgrade.mo
-       ln -f serv_upgrade.mo modules
-
 modules/serv_vcard.so: serv_vcard.mo vcard.mo
        $(LINK_SHARED) -o modules/serv_vcard.so serv_vcard.mo vcard.mo
 
-modules/serv_vcard.mo: serv_vcard.mo
-       ln -f serv_vcard.mo modules
-
-modules/vcard.mo: vcard.mo
-       ln -f vcard.mo modules
-
 modules/serv_smtp.so: serv_smtp.mo domain.mo
        $(LINK_SHARED) -o modules/serv_smtp.so serv_smtp.mo domain.mo
 
-modules/serv_smtp.mo: serv_smtp.mo
-       ln -f serv_smtp.mo modules
-
-modules/domain.mo: domain.mo
-       ln -f domain.mo modules
-
 modules/serv_imap.so: serv_imap.mo imap_tools.mo imap_fetch.mo \
-       imap_search.mo imap_store.mo
+       imap_search.mo imap_store.mo imap_misc.mo
        $(LINK_SHARED) -o modules/serv_imap.so imap_tools.mo serv_imap.mo \
-               imap_fetch.mo imap_search.mo imap_store.mo
-
-modules/serv_imap.mo: serv_imap.mo
-       ln -f serv_imap.mo modules
-
-modules/imap_tools.mo: imap_tools.mo
-       ln -f imap_tools.mo modules
-
-modules/imap_fetch.mo: imap_fetch.mo
-       ln -f imap_fetch.mo modules
-
-modules/imap_search.mo: imap_search.mo
-       ln -f imap_search.mo modules
-
-modules/imap_store.mo: imap_store.mo
-       ln -f imap_store.mo modules
+               imap_fetch.mo imap_search.mo imap_store.mo imap_misc.mo
 
 aidepost: aidepost.o config.o $(LIBOBJS)
        $(CC) aidepost.o config.o $(LIBOBJS) $(LDFLAGS) -o aidepost
@@ -260,18 +200,9 @@ aidepost: aidepost.o config.o $(LIBOBJS)
 modules/serv_pas2.so: serv_pas2.mo md5.mo
        $(LINK_SHARED) -o modules/serv_pas2.so serv_pas2.mo md5.mo
 
-modules/serv_pas2.mo: serv_pas2.mo
-       ln -f serv_pas2.mo modules
-
-modules/md5.mo: md5.mo
-       ln -f md5.mo modules
-
 modules/serv_ical.so: serv_ical.mo
        $(LINK_SHARED) -o modules/serv_ical.so serv_ical.mo
 
-modules/serv_ical.mo: serv_ical.mo
-       ln -f serv_ical.mo modules
-
 
 
 #
index cc2cce790b981802243a84dc193ecf97130d447f..0451ccc51a20d3d0ef7c9526f430d462a2073e83 100644 (file)
@@ -672,7 +672,7 @@ void imap_do_fetch(int num_items, char **itemlist) {
 
        if (IMAP->num_msgs > 0)
         for (i = 0; i < IMAP->num_msgs; ++i)
-         if (IMAP->flags[i] & IMAP_FETCHED) {
+         if (IMAP->flags[i] & IMAP_SELECTED) {
                msg = CtdlFetchMessage(IMAP->msgids[i]);
                if (msg != NULL) {
                        imap_do_fetch_msg(i+1, msg, num_items, itemlist);
@@ -813,14 +813,14 @@ int imap_extract_data_items(char **argv, char *items) {
 /*
  * One particularly hideous aspect of IMAP is that we have to allow the client
  * to specify arbitrary ranges and/or sets of messages to fetch.  Citadel IMAP
- * handles this by setting the IMAP_FETCHED flag for each message specified in
+ * handles this by setting the IMAP_SELECTED flag for each message specified in
  * the ranges/sets, then looping through the message array, outputting messages
  * with the flag set.  We don't bother returning an error if an out-of-range
  * number is specified (we just return quietly) because any client braindead
  * enough to request a bogus message number isn't going to notice the
  * difference anyway.
  *
- * This function clears out the IMAP_FETCHED bits, then sets that bit for each
+ * This function clears out the IMAP_SELECTED bits, then sets that bit for each
  * message included in the specified range.
  *
  * Set is_uid to 1 to fetch by UID instead of sequence number.
@@ -844,10 +844,10 @@ void imap_pick_range(char *supplied_range, int is_uid) {
        }
 
        /*
-        * Clear out the IMAP_FETCHED flags for all messages.
+        * Clear out the IMAP_SELECTED flags for all messages.
         */
        for (i = 0; i < IMAP->num_msgs; ++i) {
-               IMAP->flags[i] = IMAP->flags[i] & ~IMAP_FETCHED;
+               IMAP->flags[i] = IMAP->flags[i] & ~IMAP_SELECTED;
        }
 
        /*
@@ -874,13 +874,13 @@ void imap_pick_range(char *supplied_range, int is_uid) {
                                if ( (IMAP->msgids[i-1]>=lo)
                                   && (IMAP->msgids[i-1]<=hi)) {
                                        IMAP->flags[i-1] =
-                                               IMAP->flags[i-1] | IMAP_FETCHED;
+                                               IMAP->flags[i-1] | IMAP_SELECTED;
                                }
                        }
                        else {          /* fetch by uid */
                                if ( (i>=lo) && (i<=hi)) {
                                        IMAP->flags[i-1] =
-                                               IMAP->flags[i-1] | IMAP_FETCHED;
+                                               IMAP->flags[i-1] | IMAP_SELECTED;
                                }
                        }
                }
diff --git a/citadel/imap_misc.c b/citadel/imap_misc.c
new file mode 100644 (file)
index 0000000..4fb1687
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * $Id$
+ *
+ *
+ */
+
+
+#include "sysdep.h"
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <pwd.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#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 "room_ops.h"
+#include "user_ops.h"
+#include "policy.h"
+#include "database.h"
+#include "msgbase.h"
+#include "tools.h"
+#include "internet_addressing.h"
+#include "serv_imap.h"
+#include "imap_tools.h"
+#include "imap_fetch.h"
+#include "imap_misc.h"
+#include "genstamp.h"
+
+
+
+
+
+
+/*
+ * imap_copy() calls imap_do_copy() to do its actual work, once it's
+ * validated and boiled down the request a bit.  (returns 0 on success)
+ */
+int imap_do_copy(char *destination_folder) {
+       int i;
+       char roomname[ROOMNAMELEN];
+
+       i = imap_grabroom(roomname, destination_folder);
+       if (i != 0) return(i);
+
+       if (IMAP->num_msgs > 0) {
+               for (i = 0; i < IMAP->num_msgs; ++i) {
+                       if (IMAP->flags[i] && IMAP_SELECTED) {
+                               CtdlCopyMsgToRoom(
+                                       IMAP->msgids[i], roomname);
+       }
+
+       return(1);
+}
+
+
+/*
+ * This function is called by the main command loop.
+ */
+void imap_copy(int num_parms, char *parms[]) {
+
+       if (num_parms != 4) {
+               cprintf("%s BAD invalid parameters\r\n", parms[0]);
+               return;
+       }
+
+       if (imap_is_message_set(parms[2])) {
+               imap_pick_range(parms[2], 0);
+       }
+       else {
+               cprintf("%s BAD invalid parameters\r\n", parms[0]);
+               return;
+       }
+
+       if (imap_do_copy(parms[3]) == 0) {
+               cprintf("%s OK COPY completed\r\n", parms[0]);
+       }
+       else {
+               cprintf("%s NO COPY failed\r\n", parms[0]);
+       }
+}
+
+/*
+ * This function is called by the main command loop.
+ */
+void imap_uidcopy(int num_parms, char *parms[]) {
+
+       if (num_parms != 5) {
+               cprintf("%s BAD invalid parameters\r\n", parms[0]);
+               return;
+       }
+
+       if (imap_is_message_set(parms[3])) {
+               imap_pick_range(parms[3], 1);
+       }
+       else {
+               cprintf("%s BAD invalid parameters\r\n", parms[0]);
+               return;
+       }
+
+       if (imap_do_copy(parms[4]) == 0) {
+               cprintf("%s OK UID COPY completed\r\n", parms[0]);
+       }
+       else {
+               cprintf("%s NO UID COPY failed\r\n", parms[0]);
+       }
+}
+
+
diff --git a/citadel/imap_misc.h b/citadel/imap_misc.h
new file mode 100644 (file)
index 0000000..16533f5
--- /dev/null
@@ -0,0 +1,7 @@
+/*
+ * $Id$
+ *
+ */
+
+void imap_copy(int num_parms, char *parms[]);
+void imap_uidcopy(int num_parms, char *parms[]);
index 2ca9fb9afcc5db78bab578ca995d2fc76199ab8e..fc40923abb200a753887c7bbc426a5ec28a6add2 100644 (file)
@@ -82,7 +82,7 @@ void imap_do_search(int num_items, char **itemlist, int is_uid) {
        cprintf("* SEARCH ");
        if (IMAP->num_msgs > 0)
         for (i = 0; i < IMAP->num_msgs; ++i)
-         if (IMAP->flags[i] && IMAP_FETCHED) {
+         if (IMAP->flags[i] && IMAP_SELECTED) {
                msg = CtdlFetchMessage(IMAP->msgids[i]);
                if (msg != NULL) {
                        imap_do_search_msg(i+1, msg, num_items,
index fd3c5aac52940eeb0a4dda6b16095d5ad9ebc4f2..4861532c348915e06fcacea056a25939845d71ce 100644 (file)
@@ -68,7 +68,7 @@ void imap_do_store(int num_items, char **itemlist, int is_uid) {
 
        if (IMAP->num_msgs > 0)
         for (i = 0; i < IMAP->num_msgs; ++i)
-         if (IMAP->flags[i] && IMAP_FETCHED) {
+         if (IMAP->flags[i] && IMAP_SELECTED) {
                msg = CtdlFetchMessage(IMAP->msgids[i]);
                if (msg != NULL) {
                        imap_do_store_msg(i+1, msg, num_items,
@@ -96,14 +96,16 @@ void imap_store(int num_parms, char *parms[]) {
                return;
        }
 
-       for (i=1; i<num_parms; ++i) {
-               if (imap_is_message_set(parms[i])) {
-                       imap_pick_range(parms[2], 0);
-               }
+       if (imap_is_message_set(parms[2])) {
+               imap_pick_range(parms[2], 0);
+       }
+       else {
+               cprintf("%s BAD invalid parameters\r\n", parms[0]);
+               return;
        }
 
        strcpy(items, "");
-       for (i=2; i<num_parms; ++i) {
+       for (i=3; i<num_parms; ++i) {
                strcat(items, parms[i]);
                if (i < (num_parms-1)) strcat(items, " ");
        }
@@ -132,10 +134,12 @@ void imap_uidstore(int num_parms, char *parms[]) {
                return;
        }
 
-       for (i=1; i<num_parms; ++i) {
-               if (imap_is_message_set(parms[i])) {
-                       imap_pick_range(parms[2], 1);
-               }
+       if (imap_is_message_set(parms[3])) {
+               imap_pick_range(parms[3], 1);
+       }
+       else {
+               cprintf("%s BAD invalid parameters\r\n", parms[0]);
+               return;
        }
 
        strcpy(items, "");
index b2e8ced832e3a02314ed02429665bba30e3d1db0..ee2119bc2209da43ae4df53afe2c5708842498a0 100644 (file)
@@ -2344,6 +2344,21 @@ void cmd_dele(char *delstr)
 }
 
 
+/*
+ * Back end API function for moves and deletes
+ */
+int CtdlCopyMsgToRoom(long msgnum, char *dest) {
+       int err;
+
+       err = CtdlSaveMsgPointerInRoom(targ, num,
+               (SM_VERIFY_GOODNESS | SM_DO_REPL_CHECK) );
+       if (err != 0) return(err);
+
+       return(0);
+}
+
+
+
 /*
  * move or copy a message to another room
  */
@@ -2373,8 +2388,7 @@ void cmd_move(char *args)
                return;
        }
 
-       err = CtdlSaveMsgPointerInRoom(targ, num,
-               (SM_VERIFY_GOODNESS | SM_DO_REPL_CHECK) );
+       err = CtdlCopyMsgToRoom(num, targ);
        if (err != 0) {
                cprintf("%d Cannot store message in %s: error %d\n",
                        err, targ, err);
index c713b8556a8b20ac2136191a3a157a6c6a52f771..7fd3cba41b0ad51dfe952fe987f8bf46b88723b1 100644 (file)
@@ -100,3 +100,4 @@ int CtdlOutputPreLoadedMsg(struct CtdlMessage *,
                int headers_only,       /* eschew the message body? */
                int do_proto,           /* do Citadel protocol responses? */
                int crlf);
+int CtdlCopyMsgToRoom(long msgnum, char *dest);
index dee9b595703f5fef13cb14780d3947e6ff1eb3b6..af668a48ee4bf575992d3e4c236c2e79884236f8 100644 (file)
@@ -47,6 +47,7 @@
 #include "imap_fetch.h"
 #include "imap_search.h"
 #include "imap_store.h"
+#include "imap_misc.h"
 
 
 long SYM_IMAP;
@@ -523,26 +524,20 @@ void imap_create(int num_parms, char *parms[]) {
 
 
 /*
- * Implements the STATUS command (sort of)
- *
+ * Locate a room by its IMAP folder name, and check access to it
  */
-void imap_status(int num_parms, char *parms[]) {
+int imap_grabroom(char *returned_roomname, char *foldername) {
        int ret;
        char augmented_roomname[ROOMNAMELEN];
        char roomname[ROOMNAMELEN];
-       char buf[SIZ];
        int c;
        struct quickroom QRscratch;
        int ra;
        int ok = 0;
-       char savedroom[ROOMNAMELEN];
-       int msgs, new;
 
-       ret = imap_roomname(roomname, sizeof roomname, parms[2]);
+       ret = imap_roomname(roomname, sizeof roomname, foldername);
        if (ret < 0) {
-               cprintf("%s NO Invalid mailbox name or location\r\n",
-                       parms[0]);
-               return;
+               return(1);
        }
 
         /* First try a regular match */
@@ -569,7 +564,31 @@ void imap_status(int num_parms, char *parms[]) {
 
        /* Fail here if no such room */
        if (!ok) {
-               cprintf("%s NO ... no such room, or access denied\r\n",
+               strcpy(returned_roomname, "");
+               return(1);
+       }
+       else {
+               strcpy(returned_roomname, QRscratch.QRname);
+               return(0);
+       }
+}
+
+
+/*
+ * Implements the STATUS command (sort of)
+ *
+ */
+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;
+
+       ret = imap_grabroom(roomname, parms[2]);
+       if (ret != 0) {
+               cprintf("%s NO Invalid mailbox name or location, or access denied\r\n",
                        parms[0]);
                return;
        }
@@ -582,7 +601,7 @@ void imap_status(int num_parms, char *parms[]) {
        if (IMAP->selected) {
                strcpy(savedroom, CC->quickroom.QRname);
        }
-       usergoto(QRscratch.QRname, 0, &msgs, &new);
+       usergoto(roomname, 0, &msgs, &new);
 
        /*
         * Tell the client what it wants to know.  In fact, tell it *more* than
@@ -765,6 +784,15 @@ void imap_command_loop(void) {
                imap_uidstore(num_parms, parms);
        }
 
+       else if (!strcasecmp(parms[1], "COPY")) {
+               imap_copy(num_parms, parms);
+       }
+
+       else if ( (!strcasecmp(parms[1], "UID"))
+               && (!strcasecmp(parms[2], "COPY")) ) {
+               imap_uidcopy(num_parms, parms);
+       }
+
        else if (!strcasecmp(parms[1], "CLOSE")) {
                imap_close(num_parms, parms);
        }
index c03ce5376e0c4d9c5aab23bbe7e6b65c38fb5804..e2c082b93614e7961347a8c4396c7099b399fbfb 100644 (file)
@@ -7,6 +7,8 @@ extern long SYM_IMAP;
 void imap_cleanup_function(void);
 void imap_greeting(void);
 void imap_command_loop(void);
+int imap_grabroom(char *returned_roomname, char *foldername);
+
 
 
 struct citimap {
@@ -36,7 +38,7 @@ enum {
 #define IMAP_DELETED   4
 #define IMAP_DRAFT     8
 #define IMAP_SEEN      16
-#define IMAP_FETCHED   32      /* internal */
+#define IMAP_SELECTED  32      /* internal */
 
 
 #define IMAP ((struct citimap *)CtdlGetUserData(SYM_IMAP))