* more imap. imap sucks. die crispin die.
authorArt Cancro <ajc@citadel.org>
Sun, 4 Feb 2001 02:40:08 +0000 (02:40 +0000)
committerArt Cancro <ajc@citadel.org>
Sun, 4 Feb 2001 02:40:08 +0000 (02:40 +0000)
citadel/ChangeLog
citadel/imap_fetch.c
citadel/imap_tools.c
citadel/imap_tools.h
citadel/policy.c
citadel/room_ops.c
citadel/room_ops.h
citadel/serv_imap.c

index b281961be9eaf438b520e25eb817f68a9845d1bb..c5ca8c01b1b32f2cca347b7b11661c843eda3771 100644 (file)
@@ -1,4 +1,7 @@
  $Log$
+ Revision 573.81  2001/02/04 02:40:07  ajc
+ * more imap.  imap sucks.  die crispin die.
+
  Revision 573.80  2001/02/03 10:02:12  error
  * serv_ical.c: Verify that objects posted to My Calendar> are of type
    text/x-calendar or text/calendar; abort saving if not
@@ -2365,4 +2368,3 @@ 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 6f07f64ffcec71bf455da58f2c2236268a2c569c..360fe09be5deccf10d2f363521c0e75602f979a5 100644 (file)
@@ -827,7 +827,7 @@ void imap_pick_range(char *range, int is_uid) {
        int i;
        int num_sets;
        int s;
-       char setstr[1024], lostr[1024], histr[1024];
+       char setstr[SIZ], lostr[SIZ], histr[SIZ];       /* was 1024 */
        int lo, hi;
        char *actual_range;
 
@@ -884,7 +884,7 @@ void imap_pick_range(char *range, int is_uid) {
  * This function is called by the main command loop.
  */
 void imap_fetch(int num_parms, char *parms[]) {
-       char items[1024];
+       char items[SIZ];        /* was 1024 */
        char *itemlist[SIZ];
        int num_items;
        int i;
@@ -916,7 +916,7 @@ void imap_fetch(int num_parms, char *parms[]) {
  * This function is called by the main command loop.
  */
 void imap_uidfetch(int num_parms, char *parms[]) {
-       char items[1024];
+       char items[SIZ];        /* was 1024 */
        char *itemlist[SIZ];
        int num_items;
        int i;
index 8c93605455b2591b4b0eaa868ba8563c25cbaeba..0e7a058c3c730a3a4e65403a0c1870bee5914c94 100644 (file)
@@ -13,6 +13,7 @@
 #include "citadel.h"
 #include "sysdep_decls.h"
 #include "tools.h"
+#include "room_ops.h"
 #include "internet_addressing.h"
 #include "imap_tools.h"
 
@@ -92,15 +93,78 @@ int imap_parameterize(char **args, char *buf) {
  * Convert a struct quickroom to an IMAP-compatible mailbox name.
  */
 void imap_mailboxname(char *buf, int bufsize, struct quickroom *qrbuf) {
+       struct floor *fl;
 
-       safestrncpy(buf, qrbuf->QRname, bufsize);
+       /*
+        * For mailboxes, just do it straight...
+        */
        if (qrbuf->QRflags & QR_MAILBOX) {
+               safestrncpy(buf, qrbuf->QRname, bufsize);
                strcpy(buf, &buf[11]);
                if (!strcasecmp(buf, MAILROOM)) strcpy(buf, "INBOX");
        }
+
+       /*
+        * Otherwise, prefix the floor name as a "public folders" moniker
+        */
+       else {
+               fl = cgetfloor(qrbuf->QRfloor);
+               snprintf(buf, bufsize, "%s|%s",
+                       fl->f_name,
+                       qrbuf->QRname);
+       }
+}
+
+
+/*
+ * Convert an inputted folder name to our best guess as to what an equivalent
+ * room name should be.  It returns the floor number that the room is on (or
+ * will be on), or -1 if an error occurred.
+ */
+int imap_roomname(char *rbuf, int bufsize, char *foldername) {
+       int levels;
+       char buf[SIZ];
+       int i;
+       struct floor *fl;
+
+       if (foldername == NULL) return(0);
+       levels = num_parms(foldername);
+
+       /* When we can support hierarchial mailboxes, take this out. */
+       if (levels > 2) return(-1);
+
+       /*
+        * Convert the crispy idiot's reserved names to our reserved names.
+        */
+       if (!strcasecmp(foldername, "INBOX")) {
+               safestrncpy(rbuf, MAILROOM, bufsize);
+               return(0);
+       }
+
+       if (levels > 1) {
+               extract(buf, foldername, 0);
+               for (i=0; i<MAXFLOORS; ++i) {
+                       fl = cgetfloor(i);
+                       if (fl->f_flags & F_INUSE) {
+                               if (!strcasecmp(buf, fl->f_name)) {
+                                       extract(rbuf, foldername, 1);
+                                       return(i);
+                               }
+                       }
+               }
+
+               extract(rbuf, buf, 1);
+               return(0);
+       }
+
+       safestrncpy(rbuf, foldername, bufsize);
+       return(0);
 }
 
 
+
+
+
 /*
  * Output a struct internet_address_list in the form an IMAP client wants
  */
index 1505d2828c2db2318bcfcca49069e61c720c09b2..b47bcb95ec51473a1cb87292e1298d5e091ae6f0 100644 (file)
@@ -3,7 +3,10 @@
  *
  */
 
+
+
 void imap_strout(char *buf);
 int imap_parameterize(char **args, char *buf);
 void imap_mailboxname(char *buf, int bufsize, struct quickroom *qrbuf);
 void imap_ial_out(struct internet_address_list *ialist);
+int imap_roomname(char *buf, int bufsize, char *foldername);
index 1ae97f38b78a48edfc717269742b78e89965843f..7c51fd0b6da65b37b3a1e1a2cdb465e79e8d7a90 100644 (file)
  * Retrieve the applicable expire policy for a specific room
  */
 void GetExpirePolicy(struct ExpirePolicy *epbuf, struct quickroom *qrbuf) {
-       struct floor flbuf;
+       struct floor *fl;
 
        /* If the room has its own policy, return it */ 
        if (qrbuf->QRep.expire_mode != 0) {
                memcpy(epbuf, &qrbuf->QRep, sizeof(struct ExpirePolicy));
                return;
-               }
+       }
 
-       /* Otherwise, if the floor has its own policy, return it */     
-       getfloor(&flbuf, qrbuf->QRfloor);
-       if (flbuf.f_ep.expire_mode != 0) {
-               memcpy(epbuf, &flbuf.f_ep, sizeof(struct ExpirePolicy));
+       /* Otherwise, if the floor has its own policy, return it */
+       fl = cgetfloor(qrbuf->QRfloor);
+       if (fl->f_ep.expire_mode != 0) {
+               memcpy(epbuf, &fl->f_ep, sizeof(struct ExpirePolicy));
                return;
-               }
+       }
 
        /* Otherwise, fall back on the system default */
        memcpy(epbuf, &config.c_ep, sizeof(struct ExpirePolicy));
-       }
+}
 
 
 /*
@@ -54,27 +54,27 @@ void GetExpirePolicy(struct ExpirePolicy *epbuf, struct quickroom *qrbuf) {
  */
 void cmd_gpex(char *argbuf) {
        struct ExpirePolicy exp;
-       struct floor flbuf;
+       struct floor *fl;
        char which[SIZ];
 
        extract(which, argbuf, 0);
        if (!strcasecmp(which, "room")) {
                memcpy(&exp, &CC->quickroom.QRep, sizeof(struct ExpirePolicy));
-               }
+       }
        else if (!strcasecmp(which, "floor")) {
-               getfloor(&flbuf, CC->quickroom.QRfloor);
-               memcpy(&exp, &flbuf.f_ep, sizeof(struct ExpirePolicy));
-               }
+               fl = cgetfloor(CC->quickroom.QRfloor);
+               memcpy(&exp, &fl->f_ep, sizeof(struct ExpirePolicy));
+       }
        else if (!strcasecmp(which, "site")) {
                memcpy(&exp, &config.c_ep, sizeof(struct ExpirePolicy));
-               }
+       }
        else {
                cprintf("%d Invalid keyword.\n", ERROR);
                return;
-               }
+       }
 
        cprintf("%d %d|%d\n", OK, exp.expire_mode, exp.expire_value);
-       }
+}
 
 
 /*
@@ -93,26 +93,26 @@ void cmd_spex(char *argbuf) {
        if ((exp.expire_mode < 0) || (exp.expire_mode > 3)) {
                cprintf("%d Invalid policy.\n", ERROR);
                return;
-               }
+       }
 
        if (!strcasecmp(which, "room")) {
                if (!is_room_aide()) {
                        cprintf("%d Higher access required.\n",
                                ERROR+HIGHER_ACCESS_REQUIRED);
                        return;
-                       }
+               }
                lgetroom(&CC->quickroom, CC->quickroom.QRname);
                memcpy(&CC->quickroom.QRep, &exp, sizeof(struct ExpirePolicy));
                lputroom(&CC->quickroom);
                cprintf("%d Room expire policy set.\n", OK);
                return;
-               }
+       }
 
        if (CC->usersupp.axlevel < 6) {
                cprintf("%d Higher access required.\n",
                        ERROR+HIGHER_ACCESS_REQUIRED);
                return;
-               }
+       }
 
        if (!strcasecmp(which, "floor")) {
                lgetfloor(&flbuf, CC->quickroom.QRfloor);
@@ -120,25 +120,25 @@ void cmd_spex(char *argbuf) {
                lputfloor(&flbuf, CC->quickroom.QRfloor);
                cprintf("%d Floor expire policy set.\n", OK);
                return;
-               }
+       }
 
        else if (!strcasecmp(which, "site")) {
                if (exp.expire_mode == EXPIRE_NEXTLEVEL) {
                        cprintf("%d Invalid policy (no higher level)\n",
                                ERROR);
                        return;
-                       }
+               }
                memcpy(&config.c_ep, &exp, sizeof(struct ExpirePolicy));
                put_config();
                cprintf("%d Site expire policy set.\n", OK);
                return;
-               }
+       }
 
        else {
                cprintf("%d Invalid keyword.\n", ERROR);
                return;
-               }
-
        }
 
+}
+
 
index 48c7d00d2318577ddc787ca74e2eb925821f9105..0367122f8a543f9eab0486a1cdd5774841639aea 100644 (file)
@@ -26,6 +26,8 @@
 #include "control.h"
 #include "tools.h"
 
+struct floor *floorcache[MAXFLOORS];
+
 /*
  * Generic routine for determining user access to rooms
  */
@@ -278,6 +280,23 @@ void lgetfloor(struct floor *flbuf, int floor_num)
 }
 
 
+/*
+ * cgetfloor()  -  Get floor record from *cache* (loads from disk if needed)
+ *    
+ * This is strictly a performance hack.
+ */
+struct floor *cgetfloor(int floor_num) {
+       
+       if (floorcache[floor_num] == NULL) {
+               floorcache[floor_num] = mallok(sizeof(struct floor));
+               getfloor(floorcache[floor_num], floor_num);
+       }
+
+       return(floorcache[floor_num]);
+}
+
+
+
 /*
  * putfloor()  -  store floor data on disk
  */
@@ -285,6 +304,11 @@ void putfloor(struct floor *flbuf, int floor_num)
 {
        cdb_store(CDB_FLOORTAB, &floor_num, sizeof(int),
                  flbuf, sizeof(struct floor));
+
+       /* If we've cached this, clear it out, 'cuz it's WRONG now! */
+       if (floorcache[floor_num] != NULL) {
+               phree(floorcache[floor_num]);
+       }
 }
 
 
@@ -912,6 +936,7 @@ void cmd_getr(void)
 void cmd_setr(char *args)
 {
        char buf[SIZ];
+       struct floor *fl;
        struct floor flbuf;
        char old_name[ROOMNAMELEN];
        int old_floor;
@@ -932,8 +957,8 @@ void cmd_setr(char *args)
 
 
        if (num_parms(args) >= 6) {
-               getfloor(&flbuf, extract_int(args, 5));
-               if ((flbuf.f_flags & F_INUSE) == 0) {
+               fl = cgetfloor(extract_int(args, 5));
+               if ((fl->f_flags & F_INUSE) == 0) {
                        cprintf("%d Invalid floor number.\n",
                                ERROR + INVALID_FLOOR_OPERATION);
                        return;
@@ -1268,7 +1293,7 @@ void cmd_cre8(char *args)
        char aaa[SIZ];
        unsigned newflags;
        struct quickroom qrbuf;
-       struct floor flbuf;
+       struct floor *fl;
 
        cre8_ok = extract_int(args, 0);
        extract(new_room_name, args, 1);
@@ -1290,8 +1315,8 @@ void cmd_cre8(char *args)
        }
 
        if (num_parms(args) >= 5) {
-               getfloor(&flbuf, extract_int(args, 4));
-               if ((flbuf.f_flags & F_INUSE) == 0) {
+               fl = cgetfloor(extract_int(args, 4));
+               if ((fl->f_flags & F_INUSE) == 0) {
                        cprintf("%d Invalid floor number.\n",
                                ERROR + INVALID_FLOOR_OPERATION);
                        return;
index aee21030f174d141563de9e41ace279c3f798294..06a951b2ffcb78c8d86bcddcf1d492d668a931cc 100644 (file)
@@ -12,6 +12,7 @@ void b_deleteroom(char *);
 int lgetroom(struct quickroom *qrbuf, char *room_name);
 void lputroom(struct quickroom *qrbuf);
 void getfloor (struct floor *flbuf, int floor_num);
+struct floor *cgetfloor(int floor_num);
 void lgetfloor (struct floor *flbuf, int floor_num);
 void putfloor (struct floor *flbuf, int floor_num);
 void lputfloor (struct floor *flbuf, int floor_num);
index adce7eddd477791798c4deb6eb8ced1858e6cd04..c3a70d0a8edf082485a41cd997f5bd5807a24216 100644 (file)
@@ -2,10 +2,14 @@
  * $Id$ 
  *
  * IMAP server for the Citadel/UX system
- * Copyright (C) 2000 by Art Cancro and others.
+ * Copyright (C) 2000-2001 by Art Cancro and others.
  * This code is released under the terms of the GNU General Public License.
  *
- * *** THIS IS UNDER DEVELOPMENT.  IT DOES NOT WORK.  DO NOT USE IT. ***
+ * WARNING: this is an incomplete implementation, still in progress.  Parts of
+ * it work, but it's not really usable yet from a user perspective.
+ *
+ * WARNING: Mark Crispin is an idiot.  IMAP is the most brain-damaged protocol
+ * you will ever have the profound lack of pleasure to encounter.
  * 
  */
 
@@ -159,7 +163,7 @@ void imap_login(int num_parms, char *parms[]) {
 
 
 /*
- * Implements the AYTHENTICATE command
+ * Implements the AUTHENTICATE command
  */
 void imap_authenticate(int num_parms, char *parms[]) {
        char buf[SIZ];
@@ -233,15 +237,14 @@ void imap_select(int num_parms, char *parms[]) {
        int ra = 0;
        struct quickroom QRscratch;
        int msgs, new;
+       int floornum;
 
-       strcpy(towhere, parms[2]);
-
-       /* IMAP uses the reserved name "INBOX" for the user's default incoming
-        * mail folder.  Convert this to whatever Citadel is using for the
-        * default mail room name (usually "Mail>").
-        */
-       if (!strcasecmp(towhere, "INBOX")) {
-               strcpy(towhere, MAILROOM);
+       /* Convert the supplied folder name to a roomname */
+       floornum = imap_roomname(towhere, sizeof towhere, parms[2]);
+       if (floornum < 0) {
+               cprintf("%s NO Invalid mailbox name.\r\n", parms[0]);
+               IMAP->selected = 0;
+               return;
        }
 
         /* First try a regular match */
@@ -380,6 +383,25 @@ void imap_list(int num_parms, char *parms[]) {
 
 
 
+/*
+ * Implements the CREATE command (FIXME not finished yet)
+ *
+ */
+void imap_create(int num_parms, char *parms[]) {
+       int floornum;
+       int levels;
+
+       floornum = imap_roomname(parms[1]);
+       if (floornum < 0) {
+               cprintf("%s NO Invalid name\r\n", parms[0]);
+               return;
+       }
+
+       cprintf("%s NO CREATE unimplemented\r\n", parms[0]);
+}
+
+
+
 /* 
  * Main command loop for IMAP sessions.
  */
@@ -418,12 +440,15 @@ void imap_command_loop(void) {
 
        /* Ok, at this point we're in normal command mode */
 
-       /* grab the tag */
+       /* Grab the tag, command, and parameters.  Check syntax. */
        num_parms = imap_parameterize(parms, cmdbuf);
+       if (num_parms < 2) {
+               cprintf("BAD syntax error\r\n");
+       }
 
-       /* commands which may be executed in any state */
+       /* The commands below may be executed in any state */
 
-       if ( (!strcasecmp(parms[1], "NOOP"))
+       else if ( (!strcasecmp(parms[1], "NOOP"))
           || (!strcasecmp(parms[1], "CHECK")) ) {
                cprintf("%s OK This command successfully did nothing.\r\n",
                        parms[0]);
@@ -452,7 +477,7 @@ void imap_command_loop(void) {
                cprintf("%s BAD Not logged in.\r\n", parms[0]);
        }
 
-       /* commands requiring the client to be logged in */
+       /* The commans below require a logged-in state */
 
        else if (!strcasecmp(parms[1], "SELECT")) {
                imap_select(num_parms, parms);
@@ -470,11 +495,15 @@ void imap_command_loop(void) {
                imap_list(num_parms, parms);
        }
 
+       else if (!strcasecmp(parms[1], "CREATE")) {
+               imap_create(num_parms, parms);
+       }
+
        else if (IMAP->selected == 0) {
                cprintf("%s BAD no folder selected\r\n", parms[0]);
        }
 
-       /* commands requiring the SELECT state */
+       /* The commands below require the SELECT state on a mailbox */
 
        else if (!strcasecmp(parms[1], "FETCH")) {
                imap_fetch(num_parms, parms);
@@ -498,7 +527,9 @@ void imap_command_loop(void) {
                imap_close(num_parms, parms);
        }
 
-       /* end of commands */
+       /* End of commands.  If we get here, the command is either invalid
+        * or unimplemented.
+        */
 
        else {
                cprintf("%s BAD command unrecognized\r\n", parms[0]);
@@ -508,6 +539,10 @@ void imap_command_loop(void) {
 
 
 
+/*
+ * This function is called by dynloader.c to register the IMAP module
+ * with the Citadel server.
+ */
 char *Dynamic_Module_Init(void)
 {
        SYM_IMAP = CtdlGetDynamicSymbol();