$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.
Fri Jul 10 1998 Art Cancro <ajc@uncensored.citadel.org>
* Initial CVS import
+
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)
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
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
--- /dev/null
+/*
+ * $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]);
+}
+
+
--- /dev/null
+/*
+ * $Id$
+ *
+ */
+
+void imap_store(int num_parms, char *parms[]);
+void imap_uidstore(int num_parms, char *parms[]);
#include "imap_tools.h"
#include "imap_fetch.h"
#include "imap_search.h"
+#include "imap_store.h"
long SYM_IMAP;
*/
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;
*/
void imap_create(int num_parms, char *parms[]) {
int ret;
- char roomname[SIZ];
+ char roomname[ROOMNAMELEN];
int floornum;
int flags;
int newroomtype;
}
+/*
+ * 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.
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]);
}
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);
}