]> code.citadel.org Git - citadel.git/commitdiff
* IMAP: implemented the STATUS command (sort of).
authorArt Cancro <ajc@citadel.org>
Tue, 20 Feb 2001 00:02:56 +0000 (00:02 +0000)
committerArt Cancro <ajc@citadel.org>
Tue, 20 Feb 2001 00:02:56 +0000 (00:02 +0000)
citadel/ChangeLog
citadel/Makefile.in
citadel/imap_store.c [new file with mode: 0644]
citadel/imap_store.h [new file with mode: 0644]
citadel/serv_imap.c

index 41a8a2dbb93588b093f93e97abbe0f97244039b5..d2e6dab7bfed6de9f83ed791e663257c22cce9e3 100644 (file)
@@ -1,4 +1,7 @@
  $Log$
+ Revision 573.94  2001/02/20 00:02:56  ajc
+ * IMAP: implemented the STATUS command (sort of).
+
  Revision 573.93  2001/02/19 22:24:41  ajc
  * IMAP server: added untagged, unsolicited server messages for newly arrived
    messages, and messages expunged by another session.
@@ -2421,3 +2424,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 0453f82f995c90cdf46b3d07cbcad6b8d7cdf8c0..cc0330de6334bb5d5422206c8f60e634ce236237 100644 (file)
@@ -90,7 +90,7 @@ SOURCES=aidepost.c citadel.c citmail.c citserver.c client_chat.c commands.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_imap.c imap_tools.c imap_fetch.c imap_search.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
 
 DEP_FILES=$(SOURCES:.c=.d)
@@ -234,9 +234,10 @@ modules/serv_smtp.mo: serv_smtp.mo
 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
+modules/serv_imap.so: serv_imap.mo imap_tools.mo imap_fetch.mo \
+       imap_search.mo imap_store.mo
        $(LINK_SHARED) -o modules/serv_imap.so imap_tools.mo serv_imap.mo \
-               imap_fetch.mo imap_search.mo
+               imap_fetch.mo imap_search.mo imap_store.mo
 
 modules/serv_imap.mo: serv_imap.mo
        ln -f serv_imap.mo modules
@@ -250,6 +251,9 @@ modules/imap_fetch.mo: imap_fetch.mo
 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
+
 aidepost: aidepost.o config.o $(LIBOBJS)
        $(CC) aidepost.o config.o $(LIBOBJS) $(LDFLAGS) -o aidepost
 
diff --git a/citadel/imap_store.c b/citadel/imap_store.c
new file mode 100644 (file)
index 0000000..fd3c5aa
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ * $Id$
+ *
+ * Implements the STORE command in IMAP.
+ *
+ */
+
+
+#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_store.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.
+ */
+void imap_do_store_msg(int seq, struct CtdlMessage *msg,
+                       int num_items, char **itemlist, int is_uid) {
+
+
+}
+
+
+
+/*
+ * imap_store() calls imap_do_store() to do its actual work, once it's
+ * validated and boiled down the request a bit.
+ */
+void imap_do_store(int num_items, char **itemlist, int is_uid) {
+       int i;
+       struct CtdlMessage *msg;
+
+       if (IMAP->num_msgs > 0)
+        for (i = 0; i < IMAP->num_msgs; ++i)
+         if (IMAP->flags[i] && IMAP_FETCHED) {
+               msg = CtdlFetchMessage(IMAP->msgids[i]);
+               if (msg != NULL) {
+                       imap_do_store_msg(i+1, msg, num_items,
+                                       itemlist, is_uid);
+                       CtdlFreeMessage(msg);
+               }
+               else {
+                       lprintf(1, "IMAP STORE internal error\n");
+               }
+       }
+}
+
+
+/*
+ * This function is called by the main command loop.
+ */
+void imap_store(int num_parms, char *parms[]) {
+       char items[1024];
+       char *itemlist[256];
+       int num_items;
+       int i;
+
+       if (num_parms < 3) {
+               cprintf("%s BAD invalid parameters\r\n", parms[0]);
+               return;
+       }
+
+       for (i=1; i<num_parms; ++i) {
+               if (imap_is_message_set(parms[i])) {
+                       imap_pick_range(parms[2], 0);
+               }
+       }
+
+       strcpy(items, "");
+       for (i=2; i<num_parms; ++i) {
+               strcat(items, parms[i]);
+               if (i < (num_parms-1)) strcat(items, " ");
+       }
+
+       num_items = imap_extract_data_items(itemlist, items);
+       if (num_items < 1) {
+               cprintf("%s BAD invalid data item list\r\n", parms[0]);
+               return;
+       }
+
+       imap_do_store(num_items, itemlist, 0);
+       cprintf("%s OK STORE completed\r\n", parms[0]);
+}
+
+/*
+ * This function is called by the main command loop.
+ */
+void imap_uidstore(int num_parms, char *parms[]) {
+       char items[1024];
+       char *itemlist[256];
+       int num_items;
+       int i;
+
+       if (num_parms < 4) {
+               cprintf("%s BAD invalid parameters\r\n", parms[0]);
+               return;
+       }
+
+       for (i=1; i<num_parms; ++i) {
+               if (imap_is_message_set(parms[i])) {
+                       imap_pick_range(parms[2], 1);
+               }
+       }
+
+       strcpy(items, "");
+       for (i=4; i<num_parms; ++i) {
+               strcat(items, parms[i]);
+               if (i < (num_parms-1)) strcat(items, " ");
+       }
+
+       num_items = imap_extract_data_items(itemlist, items);
+       if (num_items < 1) {
+               cprintf("%s BAD invalid data item list\r\n", parms[0]);
+               return;
+       }
+
+       imap_do_store(num_items, itemlist, 1);
+       cprintf("%s OK UID STORE completed\r\n", parms[0]);
+}
+
+
diff --git a/citadel/imap_store.h b/citadel/imap_store.h
new file mode 100644 (file)
index 0000000..d3aa734
--- /dev/null
@@ -0,0 +1,7 @@
+/*
+ * $Id$
+ *
+ */
+
+void imap_store(int num_parms, char *parms[]);
+void imap_uidstore(int num_parms, char *parms[]);
index 0f2e3f165aad90d1b7d9da0bc8c31f2b94972de5..341f967034586b9fc670b85c975c232bce7ebf32 100644 (file)
@@ -46,6 +46,7 @@
 #include "imap_tools.h"
 #include "imap_fetch.h"
 #include "imap_search.h"
+#include "imap_store.h"
 
 
 long SYM_IMAP;
@@ -294,7 +295,7 @@ void imap_capability(int num_parms, char *parms[]) {
  */
 void imap_select(int num_parms, char *parms[]) {
        char towhere[SIZ];
-       char augmented_roomname[SIZ];
+       char augmented_roomname[ROOMNAMELEN];
        int c = 0;
        int ok = 0;
        int ra = 0;
@@ -476,7 +477,7 @@ void imap_list(int num_parms, char *parms[]) {
  */
 void imap_create(int num_parms, char *parms[]) {
        int ret;
-       char roomname[SIZ];
+       char roomname[ROOMNAMELEN];
        int floornum;
        int flags;
        int newroomtype;
@@ -511,6 +512,102 @@ void imap_create(int num_parms, char *parms[]) {
 }
 
 
+/*
+ * Implements the STATUS command (sort of)
+ *
+ */
+void imap_status(int num_parms, char *parms[]) {
+       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]);
+       if (ret < 0) {
+               cprintf("%s NO Invalid mailbox name or location\r\n",
+                       parms[0]);
+               return;
+       }
+
+        /* First try a regular match */
+        c = getroom(&QRscratch, roomname);
+
+        /* Then try a mailbox name match */
+        if (c != 0) {
+                MailboxName(augmented_roomname, &CC->usersupp, roomname);
+                c = getroom(&QRscratch, augmented_roomname);
+                if (c == 0)
+                        strcpy(roomname, augmented_roomname);
+        }
+
+       /* If the room exists, check security/access */
+        if (c == 0) {
+                /* See if there is an existing user/room relationship */
+                ra = CtdlRoomAccess(&QRscratch, &CC->usersupp);
+
+                /* normal clients have to pass through security */
+                if (ra & UA_KNOWN) {
+                        ok = 1;
+               }
+       }
+
+       /* Fail here if no such room */
+       if (!ok) {
+               cprintf("%s NO ... no such room, or access denied\r\n",
+                       parms[0]);
+               return;
+       }
+
+       /*
+        * usergoto() formally takes us to the desired room, happily returning
+        * the number of messages and number of new messages.  (If another
+        * folder is selected, save its name so we can return there!!!!!)
+        */
+       if (IMAP->selected) {
+               strcpy(savedroom, CC->quickroom.QRname);
+       }
+       usergoto(QRscratch.QRname, 0, &msgs, &new);
+
+       /*
+        * Tell the client what it wants to know.  In fact, tell it *more* than
+        * 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, &QRscratch);
+       cprintf("* STATUS ");
+       imap_strout(buf);
+       cprintf(" (MESSAGES %d RECENT 0 UIDNEXT %ld "
+               "UIDVALIDITY 0 UNSEEN 0)\r\n",
+               msgs,
+               CitControl.MMhighest + 1
+       );
+
+       /*
+        * If another folder is selected, go back to that room so we can resume
+        * our happy day without violent explosions.
+        */
+       if (IMAP->selected) {
+               usergoto(savedroom, 0, &msgs, &new);
+       }
+
+       /*
+        * Oooh, look, we're done!
+        */
+       cprintf("%s OK STATUS completed\r\n", parms[0]);
+}
+
+
+
 
 /* 
  * Main command loop for IMAP sessions.
@@ -621,6 +718,10 @@ void imap_command_loop(void) {
                imap_create(num_parms, parms);
        }
 
+       else if (!strcasecmp(parms[1], "STATUS")) {
+               imap_status(num_parms, parms);
+       }
+
        else if (IMAP->selected == 0) {
                cprintf("%s BAD no folder selected\r\n", parms[0]);
        }
@@ -645,6 +746,15 @@ void imap_command_loop(void) {
                imap_uidsearch(num_parms, parms);
        }
 
+       else if (!strcasecmp(parms[1], "STORE")) {
+               imap_store(num_parms, parms);
+       }
+
+       else if ( (!strcasecmp(parms[1], "UID"))
+               && (!strcasecmp(parms[2], "STORE")) ) {
+               imap_uidstore(num_parms, parms);
+       }
+
        else if (!strcasecmp(parms[1], "CLOSE")) {
                imap_close(num_parms, parms);
        }