* Finished the IMAP RENAME command. (I ended up using nested functions
authorArt Cancro <ajc@citadel.org>
Wed, 17 Apr 2002 04:35:07 +0000 (04:35 +0000)
committerArt Cancro <ajc@citadel.org>
Wed, 17 Apr 2002 04:35:07 +0000 (04:35 +0000)
  because it made the task much, much easier.  We can fix it later or convert
  it to C++ if we find this becomes a problem.)

citadel/ChangeLog
citadel/imap_tools.c
citadel/serv_imap.c

index 57f3e9c4c1779f2b3247a8b3738eca344fa0e85d..5cd559a4745148b5081aa10258a2a37757451e5d 100644 (file)
@@ -1,4 +1,9 @@
  $Log$
+ Revision 591.11  2002/04/17 04:35:06  ajc
+ * Finished the IMAP RENAME command.  (I ended up using nested functions
+   because it made the task much, much easier.  We can fix it later or convert
+   it to C++ if we find this becomes a problem.)
+
  Revision 591.10  2002/04/15 13:25:47  ajc
  * Add error responses to imap_rename() and set up subfolder framework
 
@@ -3605,4 +3610,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 02d5953b62c5d400f93a7a5080afbe19367206d2..f6c66689aead2784718422cd96d4f8173f69e364 100644 (file)
@@ -140,6 +140,7 @@ int imap_roomname(char *rbuf, int bufsize, char *foldername)
        int levels;
        char floorname[SIZ];
        char roomname[SIZ];
+       char buf[SIZ];
        int i;
        struct floor *fl;
        int ret = (-1);
@@ -184,6 +185,13 @@ int imap_roomname(char *rbuf, int bufsize, char *foldername)
                if (rbuf[i] == '|') rbuf[i] = '/';
        }
 
+       if (ret & IR_MAILBOX) {
+               if (atol(rbuf) == 0L) {
+                       strcpy(buf, rbuf);
+                       sprintf(rbuf, "%010ld.%s", CC->usersupp.usernum, buf);
+               }
+       }
+
        lprintf(9, "(That translates to \"%s\")\n", rbuf);
        return(ret);
 }
index 9cb5aafd27e9038ea780235c10e48fd6901b3f40..e34d7421c98482ef45d0316b7a62b27b6b4b1dd1 100644 (file)
@@ -7,7 +7,7 @@
  *
  * WARNING: this is an incomplete implementation.  It is now good enough to
  * be usable with much of the popular IMAP client software available, but it
- * is by no means perfect.  Some commands (particularly SEARCH and RENAME)
+ * is by no means perfect.  Some commands (particularly SEARCH)
  * are implemented either incompletely or not at all.
  *
  * WARNING: Mark Crispin is an idiot.  IMAP is the most brain-damaged protocol
@@ -894,41 +894,6 @@ void imap_delete(int num_parms, char *parms[]) {
 }
 
 
-
-
-/*
- * Back end function for imap_rename()
- */
-void imap_rename_backend(struct quickroom *qrbuf, void *data) {
-       struct irr_t { char *old_path; char *new_path; };
-       struct irr_t *irr = (struct irr_t *)data;
-       char foldername[SIZ];
-       char newfoldername[SIZ];
-       char newroomname[ROOMNAMELEN];
-       int newfloor;
-       int r;
-
-       imap_mailboxname(foldername, sizeof foldername, qrbuf);
-
-       if ( (!strncasecmp(foldername, irr->old_path, strlen(irr->old_path)) 
-          && (foldername[strlen(irr->old_path)] == '|')) ) {
-
-               sprintf(newfoldername, "%s|%s",
-                       irr->new_path,
-                       &foldername[strlen(irr->old_path)+1]
-               );
-
-               newfloor = imap_roomname(newroomname,
-                               sizeof newroomname, newfoldername);
-
-               r = CtdlRenameRoom(qrbuf->QRname, newroomname, newfloor);
-               /* FIXME handle error returns */
-       }
-}
-
-
-
-
 /*
  * Implements the RENAME command
  *
@@ -940,9 +905,49 @@ void imap_rename(int num_parms, char *parms[]) {
        int new_floor;
        int r;
 
-       struct irr_t { char *old_path; char *new_path; };
-       struct irr_t irr = { parms[2], parms[3] };
+       /* struct containing list of rooms to rename */
+       struct irl {
+               struct irl *next;
+               char irl_oldroom[ROOMNAMELEN];
+               char irl_newroom[ROOMNAMELEN];
+               int irl_newfloor;
+       };
+       struct irl *irl = NULL;         /* the list */
+       struct irl *irlp = NULL;        /* scratch pointer */
+
+       /*
+        * Back end function for imap_rename()
+        */
+       void imap_rename_backend(struct quickroom *qrbuf, void *data) {
+               char foldername[SIZ];
+               char newfoldername[SIZ];
+               char newroomname[ROOMNAMELEN];
+               int newfloor;
+               int r;
+       
+               imap_mailboxname(foldername, sizeof foldername, qrbuf);
+       
+               if ( (!strncasecmp(foldername, parms[2], strlen(parms[2]))
+                  && (foldername[strlen(parms[2])] == '|')) ) {
+       
+                       sprintf(newfoldername, "%s|%s",
+                               parms[3],
+                               &foldername[strlen(parms[2])+1]
+                       );
+       
+                       newfloor = imap_roomname(newroomname,
+                               sizeof newroomname, newfoldername) & 0xFF;
+
+                       irlp = (struct irl *) mallok(sizeof(struct irl));
+                       strcpy(irlp->irl_newroom, newroomname);
+                       strcpy(irlp->irl_oldroom, qrbuf->QRname);
+                       irlp->irl_newfloor = newfloor;
+                       irlp->next = irl;
+                       irl = irlp;
 
+               }
+       }
+       
        oldr = imap_roomname(old_room, sizeof old_room, parms[2]);
        newr = imap_roomname(new_room, sizeof new_room, parms[3]);
        new_floor = (newr & 0xFF);
@@ -976,8 +981,29 @@ void imap_rename(int num_parms, char *parms[]) {
                return;
        }
 
-       /* FIXME supply something */
-       ForEachRoom(imap_rename_backend, (void *)&irr );
+
+       /* If this is the INBOX, then RFC2060 says we have to just move the
+        * contents.  In a Citadel environment it's easier to rename the room
+        * (already did that) and create a new inbox.
+        */
+       if (!strcasecmp(parms[2], "INBOX")) {
+               create_room(MAILROOM, 4, "", 0, 1);
+       }
+
+       /* Otherwise, do the subfolders.  Build a list of rooms to rename... */
+       else {
+               ForEachRoom(imap_rename_backend, NULL);
+
+               /* ... and now rename them. */
+               while (irl != NULL) {
+                       r = CtdlRenameRoom(irl->irl_oldroom,
+                               irl->irl_newroom, irl->irl_newfloor);
+                       /* FIXME handle error returns */
+                       irlp = irl;
+                       irl = irl->next;
+                       phree(irlp);
+               }
+       }
 
        cprintf("%s OK RENAME completed\r\n", parms[0]);
 }