more places to fix the new linebreak behaviour of the base64 encoder.
[citadel.git] / citadel / modules / imap / serv_imap.c
index eab1e8571803cc11f754321e9a565d27781d8bd1..278cc73323392b3883c08ff8ee58b75d1b8fa163 100644 (file)
@@ -69,7 +69,7 @@
 #include "imap_misc.h"
 
 #include "ctdl_module.h"
-
+int IMAPDebugEnabled = 0;
 HashList *ImapCmds = NULL;
 void registerImapCMD(const char *First, long FLen, 
                     const char *Second, long SLen,
@@ -102,8 +102,9 @@ void imap_cleanup(void)
 
 const imap_handler_hook *imap_lookup(int num_parms, ConstStr *Params)
 {
+       struct CitContext *CCC = CC;
        void *v;
-       citimap *Imap = IMAP;
+       citimap *Imap = CCCIMAP;
 
        if (num_parms < 1)
                return NULL;
@@ -112,33 +113,33 @@ const imap_handler_hook *imap_lookup(int num_parms, ConstStr *Params)
        StrBufPlain(Imap->Reply, CKEY(Params[1]));
        StrBufUpCase(Imap->Reply);
 
-       syslog(LOG_DEBUG, "---- Looking up [%s] -----", 
+       IMAP_syslog(LOG_DEBUG, "---- Looking up [%s] -----", 
                      ChrPtr(Imap->Reply));
        if (GetHash(ImapCmds, SKEY(Imap->Reply), &v))
        {
-               syslog(LOG_DEBUG, "Found."); 
+               IMAPM_syslog(LOG_DEBUG, "Found."); 
                FlushStrBuf(Imap->Reply);
                return (imap_handler_hook *) v;
        }
 
        if (num_parms == 1)
        {
-               syslog(LOG_DEBUG, "NOT Found."); 
+               IMAPM_syslog(LOG_DEBUG, "NOT Found."); 
                FlushStrBuf(Imap->Reply);
                return NULL;
        }
        
-       syslog(LOG_DEBUG, "---- Looking up [%s] -----", 
+       IMAP_syslog(LOG_DEBUG, "---- Looking up [%s] -----", 
                      ChrPtr(Imap->Reply));
        StrBufAppendBufPlain(Imap->Reply, CKEY(Params[2]), 0);
        StrBufUpCase(Imap->Reply);
        if (GetHash(ImapCmds, SKEY(Imap->Reply), &v))
        {
-               syslog(LOG_DEBUG, "Found."); 
+               IMAPM_syslog(LOG_DEBUG, "Found."); 
                FlushStrBuf(Imap->Reply);
                return (imap_handler_hook *) v;
        }
-       syslog(LOG_DEBUG, "NOT Found."); 
+       IMAPM_syslog(LOG_DEBUG, "NOT Found."); 
        FlushStrBuf(Imap->Reply);
                return NULL;
 }
@@ -152,11 +153,13 @@ struct irl {
 };
 
 /* Data which is passed between imap_rename() and imap_rename_backend() */
-struct irlparms {
-       char *oldname;
-       char *newname;
+typedef struct __irlparms {
+       const char *oldname;
+       long oldnamelen;
+       const char *newname;
+       long newnamelen;
        struct irl **irl;
-};
+}irlparms;
 
 
 /*
@@ -290,7 +293,7 @@ void imap_add_single_msgid(long msgnum, void *userdata)
        if (Imap->num_msgs > Imap->num_alloc) {
                Imap->num_alloc += REALLOC_INCREMENT;
                Imap->msgids = realloc(Imap->msgids, (Imap->num_alloc * sizeof(long)) );
-               Imap->flags = realloc(Imap->flags, (Imap->num_alloc * sizeof(long)) );
+               Imap->flags = realloc(Imap->flags, (Imap->num_alloc * sizeof(unsigned int)) );
        }
        Imap->msgids[Imap->num_msgs - 1] = msgnum;
        Imap->flags[Imap->num_msgs - 1] = 0;
@@ -303,11 +306,12 @@ void imap_add_single_msgid(long msgnum, void *userdata)
  */
 void imap_load_msgids(void)
 {
+       struct CitContext *CCC = CC;
        struct cdbdata *cdbfr;
-       citimap *Imap = IMAP;
+       citimap *Imap = CCCIMAP;
 
        if (Imap->selected == 0) {
-               syslog(LOG_ERR, "imap_load_msgids() can't run; no room selected");
+               IMAPM_syslog(LOG_ERR, "imap_load_msgids() can't run; no room selected");
                return;
        }
 
@@ -316,16 +320,17 @@ void imap_load_msgids(void)
        /* Load the message list */
        cdbfr = cdb_fetch(CDB_MSGLISTS, &CC->room.QRnumber, sizeof(long));
        if (cdbfr != NULL) {
-               Imap->msgids = malloc(cdbfr->len);
-               memcpy(Imap->msgids, cdbfr->ptr, cdbfr->len);
+               Imap->msgids = (long*)cdbfr->ptr;
                Imap->num_msgs = cdbfr->len / sizeof(long);
                Imap->num_alloc = cdbfr->len / sizeof(long);
+               cdbfr->ptr = NULL;
+               cdbfr->len = 0;
                cdb_free(cdbfr);
        }
 
        if (Imap->num_msgs) {
-               Imap->flags = malloc(Imap->num_alloc * sizeof(long));
-               memset(Imap->flags, 0, (Imap->num_alloc * sizeof(long)) );
+               Imap->flags = malloc(Imap->num_alloc * sizeof(unsigned int));
+               memset(Imap->flags, 0, (Imap->num_alloc * sizeof(unsigned int)) );
        }
 
        imap_set_seen_flags(0);
@@ -337,7 +342,8 @@ void imap_load_msgids(void)
  */
 void imap_rescan_msgids(void)
 {
-       citimap *Imap = IMAP;
+       struct CitContext *CCC = CC;
+       citimap *Imap = CCCIMAP;
        int original_num_msgs = 0;
        long original_highest = 0L;
        int i, j, jstart;
@@ -348,7 +354,7 @@ void imap_rescan_msgids(void)
        int num_recent = 0;
 
        if (Imap->selected == 0) {
-               syslog(LOG_ERR, "imap_load_msgids() can't run; no room selected");
+               IMAPM_syslog(LOG_ERR, "imap_load_msgids() can't run; no room selected");
                return;
        }
 
@@ -366,14 +372,10 @@ void imap_rescan_msgids(void)
         */
        cdbfr = cdb_fetch(CDB_MSGLISTS, &CC->room.QRnumber, sizeof(long));
        if (cdbfr != NULL) {
-               msglist = malloc(cdbfr->len);
-               if (msglist == NULL) {
-                       syslog(LOG_CRIT, "IMAP: malloc() failed");
-                       CC->kill_me = KILLME_MALLOC_FAILED;
-                       return;
-               }
-               memcpy(msglist, cdbfr->ptr, (size_t)cdbfr->len);
+               msglist = (long*)cdbfr->ptr;
+               cdbfr->ptr = NULL;
                num_msgs = cdbfr->len / sizeof(long);
+               cdbfr->len = 0;
                cdb_free(cdbfr);
        } else {
                num_msgs = 0;
@@ -406,15 +408,14 @@ void imap_rescan_msgids(void)
                                 * array.
                                 */
                                --Imap->num_msgs;
-                               memcpy(&Imap->msgids[i],
-                                      &Imap->msgids[i + 1],
-                                      (sizeof(long) *
-                                       (Imap->num_msgs - i)));
-                               memcpy(&Imap->flags[i],
-                                      &Imap->flags[i + 1],
-                                      (sizeof(long) *
-                                       (Imap->num_msgs - i)));
-
+                               memmove(&Imap->msgids[i],
+                                       &Imap->msgids[i + 1],
+                                       (sizeof(long) *
+                                        (Imap->num_msgs - i)));
+                               memmove(&Imap->flags[i],
+                                       &Imap->flags[i + 1],
+                                       (sizeof(unsigned int) *
+                                        (Imap->num_msgs - i)));
                                --i;
                        }
 
@@ -460,7 +461,7 @@ void imap_rescan_msgids(void)
                IAPrintf("* %d RECENT\r\n", num_recent);
        }
 
-       if (num_msgs != 0) {
+       if (msglist != NULL) {
                free(msglist);
        }
        Imap->last_mtime = CC->room.QRmtime;
@@ -473,7 +474,8 @@ void imap_rescan_msgids(void)
  */
 void imap_cleanup_function(void)
 {
-       citimap *Imap = IMAP;
+       struct CitContext *CCC = CC;
+       citimap *Imap = CCCIMAP;
 
        /* Don't do this stuff if this is not a Imap session! */
        if (CC->h_command_function != imap_command_loop)
@@ -484,7 +486,7 @@ void imap_cleanup_function(void)
                imap_do_expunge();
        }
 
-       syslog(LOG_DEBUG, "Performing IMAP cleanup hook");
+       IMAPM_syslog(LOG_DEBUG, "Performing IMAP cleanup hook");
        imap_free_msgids();
        imap_free_transmitted_message();
 
@@ -504,7 +506,7 @@ void imap_cleanup_function(void)
        FreeStrBuf(&Imap->Reply);
        if (Imap->Cmd.Params != NULL) free(Imap->Cmd.Params);
        free(Imap);
-       syslog(LOG_DEBUG, "Finished IMAP cleanup hook");
+       IMAPM_syslog(LOG_DEBUG, "Finished IMAP cleanup hook");
 }
 
 
@@ -675,7 +677,11 @@ void imap_authenticate(int num_parms, ConstStr *Params)
        }
 
        if (!strcasecmp(Params[2].Key, "LOGIN")) {
-               CtdlEncodeBase64(UsrBuf, "Username:", 9, 0);
+               size_t len = CtdlEncodeBase64(UsrBuf, "Username:", 9, 0);
+               if (UsrBuf[len - 1] == '\n') {
+                       UsrBuf[len - 1] = '\0';
+               }
+
                IAPrintf("+ %s\r\n", UsrBuf);
                IMAP->authstate = imap_as_expecting_username;
                strcpy(IMAP->authseq, Params[0].Key);
@@ -683,7 +689,10 @@ void imap_authenticate(int num_parms, ConstStr *Params)
        }
 
        if (!strcasecmp(Params[2].Key, "PLAIN")) {
-               // CtdlEncodeBase64(UsrBuf, "Username:", 9, 0);
+               // size_t len = CtdlEncodeBase64(UsrBuf, "Username:", 9, 0);
+               // if (UsrBuf[len - 1] == '\n') {
+               //   UsrBuf[len - 1] = '\0';
+               // }
                // IAPuts("+ %s\r\n", UsrBuf);
                IAPuts("+ \r\n");
                IMAP->authstate = imap_as_expecting_plainauth;
@@ -702,22 +711,42 @@ void imap_auth_plain(void)
 {
        citimap *Imap = IMAP;
        const char *decoded_authstring;
-       char ident[256];
-       char user[256];
-       char pass[256];
+       char ident[256] = "";
+       char user[256] = "";
+       char pass[256] = "";
        int result;
-       long len;
+       long decoded_len;
+       long len = 0;
+       long plen = 0;
 
        memset(pass, 0, sizeof(pass));
-       StrBufDecodeBase64(Imap->Cmd.CmdBuf);
+       decoded_len = StrBufDecodeBase64(Imap->Cmd.CmdBuf);
+
+       if (decoded_len > 0)
+       {
+               decoded_authstring = ChrPtr(Imap->Cmd.CmdBuf);
+
+               len = safestrncpy(ident, decoded_authstring, sizeof ident);
+
+               decoded_len -= len - 1;
+               decoded_authstring += len + 1;
 
-       decoded_authstring = ChrPtr(Imap->Cmd.CmdBuf);
-       safestrncpy(ident, decoded_authstring, sizeof ident);
-       safestrncpy(user, &decoded_authstring[strlen(ident) + 1], sizeof user);
-       len = safestrncpy(pass, &decoded_authstring[strlen(ident) + strlen(user) + 2], sizeof pass);
-       if (len < 0)
-               len = sizeof(pass) - 1;
+               if (decoded_len > 0)
+               {
+                       len = safestrncpy(user, decoded_authstring, sizeof user);
 
+                       decoded_authstring += len + 1;
+                       decoded_len -= len - 1;
+               }
+
+               if (decoded_len > 0)
+               {
+                       plen = safestrncpy(pass, decoded_authstring, sizeof pass);
+
+                       if (plen < 0)
+                               plen = sizeof(pass) - 1;
+               }
+       }
        Imap->authstate = imap_as_normal;
 
        if (!IsEmptyStr(ident)) {
@@ -728,7 +757,7 @@ void imap_auth_plain(void)
        }
 
        if (result == login_ok) {
-               if (CtdlTryPassword(pass, len) == pass_ok) {
+               if (CtdlTryPassword(pass, plen) == pass_ok) {
                        IAPrintf("%s OK authentication succeeded\r\n", Imap->authseq);
                        return;
                }
@@ -746,7 +775,11 @@ void imap_auth_login_user(long state)
        case imap_as_expecting_username:
                StrBufDecodeBase64(Imap->Cmd.CmdBuf);
                CtdlLoginExistingUser(NULL, ChrPtr(Imap->Cmd.CmdBuf));
-               CtdlEncodeBase64(PWBuf, "Password:", 9, 0);
+               size_t len = CtdlEncodeBase64(PWBuf, "Password:", 9, 0);
+               if (PWBuf[len - 1] == '\n') {
+                       PWBuf[len - 1] = '\0';
+               }
+
                IAPrintf("+ %s\r\n", PWBuf);
                
                Imap->authstate = imap_as_expecting_password;
@@ -868,7 +901,7 @@ void imap_select(int num_parms, ConstStr *Params)
         * the number of messages and number of new messages.
         */
        memcpy(&CC->room, &QRscratch, sizeof(struct ctdlroom));
-       CtdlUserGoto(NULL, 0, 0, &msgs, &new);
+       CtdlUserGoto(NULL, 0, 0, &msgs, &new, NULL, NULL);
        Imap->selected = 1;
 
        if (!strcasecmp(Params[1].Key, "EXAMINE")) {
@@ -909,13 +942,14 @@ void imap_select(int num_parms, ConstStr *Params)
  */
 int imap_do_expunge(void)
 {
-       citimap *Imap = IMAP;
+       struct CitContext *CCC = CC;
+       citimap *Imap = CCCIMAP;
        int i;
        int num_expunged = 0;
        long *delmsgs = NULL;
        int num_delmsgs = 0;
 
-       syslog(LOG_DEBUG, "imap_do_expunge() called");
+       IMAPM_syslog(LOG_DEBUG, "imap_do_expunge() called");
        if (Imap->selected == 0) {
                return (0);
        }
@@ -938,7 +972,7 @@ int imap_do_expunge(void)
                imap_rescan_msgids();
        }
 
-       syslog(LOG_DEBUG, "Expunged %d messages from <%s>", num_expunged, CC->room.QRname);
+       IMAP_syslog(LOG_DEBUG, "Expunged %d messages from <%s>", num_expunged, CC->room.QRname);
        return (num_expunged);
 }
 
@@ -978,6 +1012,7 @@ void imap_close(int num_parms, ConstStr *Params)
  */
 void imap_namespace(int num_parms, ConstStr *Params)
 {
+       long len;
        int i;
        struct floor *fl;
        int floors = 0;
@@ -998,8 +1033,8 @@ void imap_namespace(int num_parms, ConstStr *Params)
                if (fl->f_flags & F_INUSE) {
                        /* if (floors > 0) IAPuts(" "); samjam says this confuses javamail */
                        IAPuts("(");
-                       snprintf(Namespace, sizeof(Namespace), "%s/", fl->f_name);
-                       plain_imap_strout(Namespace);
+                       len = snprintf(Namespace, sizeof(Namespace), "%s/", fl->f_name);
+                       IPutStr(Namespace, len);
                        IAPuts(" \"/\")");
                        ++floors;
                }
@@ -1018,6 +1053,7 @@ void imap_namespace(int num_parms, ConstStr *Params)
  */
 void imap_create(int num_parms, ConstStr *Params)
 {
+       struct CitContext *CCC = CC;
        int ret;
        char roomname[ROOMNAMELEN];
        int floornum;
@@ -1033,14 +1069,14 @@ void imap_create(int num_parms, ConstStr *Params)
 
        if (strchr(Params[2].Key, '\\') != NULL) {
                IReply("NO Invalid character in folder name");
-               syslog(LOG_DEBUG, "invalid character in folder name");
+               IMAPM_syslog(LOG_ERR, "invalid character in folder name");
                return;
        }
 
        ret = imap_roomname(roomname, sizeof roomname, Params[2].Key);
        if (ret < 0) {
                IReply("NO Invalid mailbox name or location");
-               syslog(LOG_DEBUG, "invalid mailbox name or location");
+               IMAPM_syslog(LOG_ERR, "invalid mailbox name or location");
                return;
        }
        floornum = (ret & 0x00ff);      /* lower 8 bits = floor number */
@@ -1049,7 +1085,7 @@ void imap_create(int num_parms, ConstStr *Params)
        if (flags & IR_MAILBOX) {
                if (strncasecmp(Params[2].Key, "INBOX/", 6)) {
                        IReply("NO Personal folders must be created under INBOX");
-                       syslog(LOG_DEBUG, "not subordinate to inbox");
+                       IMAPM_syslog(LOG_ERR, "not subordinate to inbox");
                        return;
                }
        }
@@ -1062,8 +1098,8 @@ void imap_create(int num_parms, ConstStr *Params)
                newroomview = VIEW_BBS;
        }
 
-       syslog(LOG_INFO, "IMAP: Create new room <%s> on floor <%d> with type <%d>",
-               roomname, floornum, newroomtype);
+       IMAP_syslog(LOG_INFO, "Create new room <%s> on floor <%d> with type <%d>",
+                   roomname, floornum, newroomtype);
 
        ret = CtdlCreateRoom(roomname, newroomtype, "", floornum, 1, 0, newroomview);
        if (ret == 0) {
@@ -1084,7 +1120,7 @@ void imap_create(int num_parms, ConstStr *Params)
                CtdlAideMessage(notification_message, "Room Creation Message");
                free(notification_message);
        }
-       syslog(LOG_DEBUG, "imap_create() completed");
+       IMAPM_syslog(LOG_DEBUG, "imap_create() completed");
 }
 
 
@@ -1150,6 +1186,7 @@ int imap_grabroom(char *returned_roomname, const char *foldername, int zapped_ok
  */
 void imap_status(int num_parms, ConstStr *Params)
 {
+       long len;
        int ret;
        char roomname[ROOMNAMELEN];
        char imaproomname[SIZ];
@@ -1170,7 +1207,7 @@ void imap_status(int num_parms, ConstStr *Params)
        if (IMAP->selected) {
                strcpy(savedroom, CC->room.QRname);
        }
-       CtdlUserGoto(roomname, 0, 0, &msgs, &new);
+       CtdlUserGoto(roomname, 0, 0, &msgs, &new, NULL, NULL);
 
        /*
         * Tell the client what it wants to know.  In fact, tell it *more* than
@@ -1178,9 +1215,9 @@ void imap_status(int num_parms, ConstStr *Params)
         * names and simply spew all possible data items.  It's far easier to
         * code and probably saves us some processing time too.
         */
-       imap_mailboxname(imaproomname, sizeof imaproomname, &CC->room);
+       len = imap_mailboxname(imaproomname, sizeof imaproomname, &CC->room);
        IAPuts("* STATUS ");
-              plain_imap_strout(imaproomname);
+       IPutStr(imaproomname, len);
        IAPrintf(" (MESSAGES %d ", msgs);
        IAPrintf("RECENT %d ", new);    /* Initially, new==recent */
        IAPrintf("UIDNEXT %ld ", CitControl.MMhighest + 1);
@@ -1191,7 +1228,7 @@ void imap_status(int num_parms, ConstStr *Params)
         * our happy day without violent explosions.
         */
        if (IMAP->selected) {
-               CtdlUserGoto(savedroom, 0, 0, &msgs, &new);
+               CtdlUserGoto(savedroom, 0, 0, &msgs, &new, NULL, NULL);
        }
 
        /*
@@ -1229,14 +1266,14 @@ void imap_subscribe(int num_parms, ConstStr *Params)
        if (IMAP->selected) {
                strcpy(savedroom, CC->room.QRname);
        }
-       CtdlUserGoto(roomname, 0, 0, &msgs, &new);
+       CtdlUserGoto(roomname, 0, 0, &msgs, &new, NULL, NULL);
 
        /*
         * If another folder is selected, go back to that room so we can resume
         * our happy day without violent explosions.
         */
        if (IMAP->selected) {
-               CtdlUserGoto(savedroom, 0, 0, &msgs, &new);
+               CtdlUserGoto(savedroom, 0, 0, &msgs, &new, NULL, NULL);
        }
 
        IReply("OK SUBSCRIBE completed");
@@ -1266,7 +1303,7 @@ void imap_unsubscribe(int num_parms, ConstStr *Params)
        if (IMAP->selected) {
                strcpy(savedroom, CC->room.QRname);
        }
-       CtdlUserGoto(roomname, 0, 0, &msgs, &new);
+       CtdlUserGoto(roomname, 0, 0, &msgs, &new, NULL, NULL);
 
        /* 
         * Now make the API call to zap the room
@@ -1282,7 +1319,7 @@ void imap_unsubscribe(int num_parms, ConstStr *Params)
         * our happy day without violent explosions.
         */
        if (IMAP->selected) {
-               CtdlUserGoto(savedroom, 0, 0, &msgs, &new);
+               CtdlUserGoto(savedroom, 0, 0, &msgs, &new, NULL, NULL);
        }
 }
 
@@ -1312,7 +1349,7 @@ void imap_delete(int num_parms, ConstStr *Params)
        if (IMAP->selected) {
                strcpy(savedroom, CC->room.QRname);
        }
-       CtdlUserGoto(roomname, 0, 0, &msgs, &new);
+       CtdlUserGoto(roomname, 0, 0, &msgs, &new, NULL, NULL);
 
        /*
         * Now delete the room.
@@ -1329,7 +1366,7 @@ void imap_delete(int num_parms, ConstStr *Params)
         * our happy day without violent explosions.
         */
        if (IMAP->selected) {
-               CtdlUserGoto(savedroom, 0, 0, &msgs, &new);
+               CtdlUserGoto(savedroom, 0, 0, &msgs, &new, NULL, NULL);
        }
 }
 
@@ -1344,19 +1381,19 @@ void imap_rename_backend(struct ctdlroom *qrbuf, void *data)
        char newroomname[ROOMNAMELEN];
        int newfloor = 0;
        struct irl *irlp = NULL;        /* scratch pointer */
-       struct irlparms *irlparms;
+       irlparms *myirlparms;
 
-       irlparms = (struct irlparms *) data;
+       myirlparms = (irlparms *) data;
        imap_mailboxname(foldername, sizeof foldername, qrbuf);
 
        /* Rename subfolders */
-       if ((!strncasecmp(foldername, irlparms->oldname,
-                         strlen(irlparms->oldname))
-            && (foldername[strlen(irlparms->oldname)] == '/'))) {
+       if ((!strncasecmp(foldername, myirlparms->oldname,
+                         myirlparms->oldnamelen)
+           && (foldername[myirlparms->oldnamelen] == '/'))) {
 
                sprintf(newfoldername, "%s/%s",
-                       irlparms->newname,
-                       &foldername[strlen(irlparms->oldname) + 1]
+                       myirlparms->newname,
+                       &foldername[myirlparms->oldnamelen + 1]
                    );
 
                newfloor = imap_roomname(newroomname,
@@ -1367,8 +1404,8 @@ void imap_rename_backend(struct ctdlroom *qrbuf, void *data)
                strcpy(irlp->irl_newroom, newroomname);
                strcpy(irlp->irl_oldroom, qrbuf->QRname);
                irlp->irl_newfloor = newfloor;
-               irlp->next = *(irlparms->irl);
-               *(irlparms->irl) = irlp;
+               irlp->next = *(myirlparms->irl);
+               *(myirlparms->irl) = irlp;
        }
 }
 
@@ -1386,7 +1423,7 @@ void imap_rename(int num_parms, ConstStr *Params)
        int r;
        struct irl *irl = NULL; /* the list */
        struct irl *irlp = NULL;        /* scratch pointer */
-       struct irlparms irlparms;
+       irlparms irlparms;
        char aidemsg[1024];
 
        if (strchr(Params[3].Key, '\\') != NULL) {
@@ -1436,7 +1473,9 @@ void imap_rename(int num_parms, ConstStr *Params)
        /* Otherwise, do the subfolders.  Build a list of rooms to rename... */
        else {
                irlparms.oldname = Params[2].Key;
+               irlparms.oldnamelen = Params[2].len;
                irlparms.newname = Params[3].Key;
+               irlparms.newnamelen = Params[3].len;
                irlparms.irl = &irl;
                CtdlForEachRoom(imap_rename_backend, (void *) &irlparms);
 
@@ -1446,8 +1485,9 @@ void imap_rename(int num_parms, ConstStr *Params)
                                           irl->irl_newroom,
                                           irl->irl_newfloor);
                        if (r != crr_ok) {
+                               struct CitContext *CCC = CC;
                                /* FIXME handle error returns better */
-                               syslog(LOG_ERR, "IMAP: CtdlRenameRoom() error %d", r);
+                               IMAP_syslog(LOG_ERR, "CtdlRenameRoom() error %d", r);
                        }
                        irlp = irl;
                        irl = irl->next;
@@ -1471,6 +1511,7 @@ void imap_rename(int num_parms, ConstStr *Params)
  */
 void imap_command_loop(void)
 {
+       struct CitContext *CCC = CC;
        struct timeval tv1, tv2;
        suseconds_t total_time = 0;
        citimap *Imap;
@@ -1478,8 +1519,8 @@ void imap_command_loop(void)
        const imap_handler_hook *h;
 
        gettimeofday(&tv1, NULL);
-       CC->lastcmd = time(NULL);
-       Imap = IMAP;
+       CCC->lastcmd = time(NULL);
+       Imap = CCCIMAP;
 
        flush_output();
        if (Imap->Cmd.CmdBuf == NULL)
@@ -1488,23 +1529,23 @@ void imap_command_loop(void)
                FlushStrBuf(Imap->Cmd.CmdBuf);
 
        if (CtdlClientGetLine(Imap->Cmd.CmdBuf) < 1) {
-               syslog(LOG_ERR, "IMAP: client disconnected: ending session.");
+               IMAPM_syslog(LOG_ERR, "client disconnected: ending session.");
                CC->kill_me = KILLME_CLIENT_DISCONNECTED;
                return;
        }
 
        if (Imap->authstate == imap_as_expecting_password) {
-               syslog(LOG_INFO, "IMAP: <password>");
+               IMAPM_syslog(LOG_INFO, "<password>");
        }
        else if (Imap->authstate == imap_as_expecting_plainauth) {
-               syslog(LOG_INFO, "IMAP: <plain_auth>");
+               IMAPM_syslog(LOG_INFO, "<plain_auth>");
        }
        else if ((Imap->authstate == imap_as_expecting_multilineusername) || 
                 cbmstrcasestr(ChrPtr(Imap->Cmd.CmdBuf), " LOGIN ")) {
-               syslog(LOG_INFO, "IMAP: LOGIN...");
+               IMAPM_syslog(LOG_INFO, "LOGIN...");
        }
        else {
-               syslog(LOG_INFO, "IMAP: %s", ChrPtr(Imap->Cmd.CmdBuf));
+               IMAP_syslog(LOG_DEBUG, "%s", ChrPtr(Imap->Cmd.CmdBuf));
        }
 
        pchs = ChrPtr(Imap->Cmd.CmdBuf);
@@ -1556,18 +1597,18 @@ void imap_command_loop(void)
 /* debug output the parsed vector */
        {
                int i;
-               syslog(LOG_DEBUG, "----- %ld params", Imap->Cmd.num_parms);
+               IMAP_syslog(LOG_DEBUG, "----- %ld params", Imap->Cmd.num_parms);
 
        for (i=0; i < Imap->Cmd.num_parms; i++) {
                if (Imap->Cmd.Params[i].len != strlen(Imap->Cmd.Params[i].Key))
-                       syslog(LOG_DEBUG, "*********** %ld != %ld : %s",
-                                     Imap->Cmd.Params[i].len, 
-                                     strlen(Imap->Cmd.Params[i].Key),
+                       IMAP_syslog(LOG_DEBUG, "*********** %ld != %ld : %s",
+                                   Imap->Cmd.Params[i].len, 
+                                   strlen(Imap->Cmd.Params[i].Key),
                                      Imap->Cmd.Params[i].Key);
                else
-                       syslog(LOG_DEBUG, "%ld : %s",
-                                     Imap->Cmd.Params[i].len, 
-                                     Imap->Cmd.Params[i].Key);
+                       IMAP_syslog(LOG_DEBUG, "%ld : %s",
+                                   Imap->Cmd.Params[i].len, 
+                                   Imap->Cmd.Params[i].Key);
        }}
 #endif
 
@@ -1618,10 +1659,10 @@ BAIL:
 
        gettimeofday(&tv2, NULL);
        total_time = (tv2.tv_usec + (tv2.tv_sec * 1000000)) - (tv1.tv_usec + (tv1.tv_sec * 1000000));
-       syslog(LOG_DEBUG, "IMAP command completed in %ld.%ld seconds",
-               (total_time / 1000000),
-               (total_time % 1000000)
-       );
+       IMAP_syslog(LOG_DEBUG, "IMAP command completed in %ld.%ld seconds",
+                   (total_time / 1000000),
+                   (total_time % 1000000)
+               );
 }
 
 void imap_noop (int num_parms, ConstStr *Params)
@@ -1643,7 +1684,10 @@ void imap_logout(int num_parms, ConstStr *Params)
 const char *CitadelServiceIMAP="IMAP";
 const char *CitadelServiceIMAPS="IMAPS";
 
-
+void SetIMAPDebugEnabled(const int n)
+{
+       IMAPDebugEnabled = n;
+}
 /*
  * This function is called to register the IMAP extension with Citadel.
  */
@@ -1699,13 +1743,14 @@ CTDL_MODULE_INIT(imap)
 
        if (!threading)
        {
+               CtdlRegisterDebugFlagHook(HKEY("imapsrv"), SetIMAPDebugEnabled, &IMAPDebugEnabled);
                CtdlRegisterServiceHook(config.c_imap_port,
                                        NULL, imap_greeting, imap_command_loop, NULL, CitadelServiceIMAP);
 #ifdef HAVE_OPENSSL
                CtdlRegisterServiceHook(config.c_imaps_port,
                                        NULL, imaps_greeting, imap_command_loop, NULL, CitadelServiceIMAPS);
 #endif
-               CtdlRegisterSessionHook(imap_cleanup_function, EVT_STOP);
+               CtdlRegisterSessionHook(imap_cleanup_function, EVT_STOP, PRIO_STOP + 30);
                CtdlRegisterCleanupHook(imap_cleanup);
        }