Back to index

courier  0.68.2
Classes | Defines | Functions | Variables
imapd.c File Reference
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#include <signal.h>
#include <fcntl.h>
#include <pwd.h>
#include <time.h>
#include <courierauth.h>
#include "maildir/maildiraclt.h"
#include "maildir/maildirnewshared.h"
#include <sys/types.h>
#include <sys/stat.h>
#include "imaptoken.h"
#include "imapwrite.h"
#include "imapscanclient.h"
#include "mysignal.h"
#include "imapd.h"
#include "fetchinfo.h"
#include "searchinfo.h"
#include "storeinfo.h"
#include "mailboxlist.h"
#include "thread.h"
#include "outbox.h"
#include "maildir/config.h"
#include "maildir/maildircreate.h"
#include "maildir/maildirrequota.h"
#include "maildir/maildirgetquota.h"
#include "maildir/maildirquota.h"
#include "maildir/maildirmisc.h"
#include "maildir/maildirwatch.h"
#include "maildir/maildirkeywords.h"
#include "maildir/maildirinfo.h"
#include "maildir/loginexec.h"
#include "unicode/unicode.h"

Go to the source code of this file.

Classes

struct  noopKeywordUpdateInfo
struct  addremove_info
struct  addRemoveKeywordInfo
struct  imap_addRemoveKeywordInfo
struct  temp_acl_mailbox_list
struct  do_acl_info
struct  aclset_info
struct  acldelete_info

Defines

#define dirent   direct
#define NAMLEN(dirent)   (dirent)->d_namlen
#define KEYWORD_IMAPVERBOTTEN   " (){%*\"\\]"
#define KEYWORD_SMAPVERBOTTEN   ","
#define UIDN(u)   ( new_uids ? (u)->uid:(u)->old_uid )
#define DO_FLAG(flag, flagname)
#define is_smap()   0

Functions

time_t rfc822_parsedt (const char *)
void fetchflags (unsigned long)
void smap ()
void smap_fetchflags (unsigned long)
int do_fetch (unsigned long, int, void *)
void fetch_free_cached ()
int keywords ()
int fastkeywords ()
void imapscanfail (const char *)
void bye_msg (const char *)
void mainloop ()
void initcapability ()
void imapcapability ()
int magictrash ()
void rfc2045_error (const char *p)
int maildirsize_read (const char *, int *, off_t *, unsigned *, unsigned *, struct stat *)
int maildir_info_suppress (const char *maildir)
void quotainfo_out (const char *qroot)
int is_trash (const char *m)
void emptytrash ()
int is_reserved (const char *m)
int is_reserved_name (const char *name)
char * decode_valid_mailbox (const char *p, int autosubscribe)
static time_t decode_date_time (char *p)
int get_flagname (const char *p, struct imapflags *flags)
int valid_keyword (const char *kw)
int get_keyword (struct libmail_kwMessage **kwPtr, const char *kw)
int get_flagsAndKeywords (struct imapflags *flags, struct libmail_kwMessage **kwPtr)
void get_message_flags (struct imapscanmessageinfo *mi, char *buf, struct imapflags *flags)
static char * parse_mailbox_error (const char *tag, struct imaptoken *curtoken, int ok_hierarchy, int autosubscribe)
void append_flags (char *buf, struct imapflags *flags)
FILE * maildir_mkfilename (const char *mailbox, struct imapflags *flags, unsigned long s, char **tmpname, char **newname)
void set_time (const char *tmpname, time_t timestamp)
static int store_mailbox (const char *tag, const char *mailbox, struct imapflags *flags, struct libmail_kwMessage *keywords, time_t timestamp, unsigned long nbytes, unsigned long *new_uidv, unsigned long *new_uid)
int mddelete (const char *s)
int mdcreate (const char *mailbox)
static int do_msgset (const char *msgset, int(*msgfunc)(unsigned long, int, void *), void *msgfunc_arg, int isuid)
static int write_keyword_name (struct libmail_keywordEntry *, void *)
 Show currently defined flags and keywords.
static void mailboxflags (int ro)
static void mailboxmetrics ()
static int noopAddKeyword (struct libmail_keywordEntry *ke, void *vp)
void doNoop (int real_noop)
static char * alloc_filename (const char *mbox, const char *name)
int doidle (time_t, int)
int imapenhancedidle (void)
void imapidle (void)
void do_expunge (unsigned long from, unsigned long to, int force)
static int uid_expunge (unsigned long msgnum, int uidflag, void *void_arg)
void expunge ()
static FILE * newsubscribefile (char **tmpname)
static int sub_strcmp (const char *a, const char *b)
static void subscribe (const char *f)
static void unsubscribe (const char *f)
static int do_count (unsigned long n, int byuid, void *voidptr)
static void dirsync (const char *folder)
static int addRemoveKeywords1 (void *)
static int addRemoveKeywords2 (int(*callback_func)(void *, void *), void *callback_func_arg, struct storeinfo *storeinfo_s, int *tryagain)
int addRemoveKeywords (int(*callback_func)(void *, void *), void *callback_func_arg, struct storeinfo *storeinfo_s)
int doAddRemoveKeywords (unsigned long, int, void *)
static int markmessages (unsigned long n, int i, void *dummy)
static int imap_addRemoveKeywords (void *myVoidArg, void *addRemoveVoidArg)
static int uidplus_fill (const char *mailbox, struct uidplus_info *uidplus_list, unsigned long *uidv)
static void uidplus_writemsgset (struct uidplus_info *uidplus_list, int new_uids)
static void uidplus_free (struct uidplus_info *uidplus_list)
static void uidplus_abort (struct uidplus_info *uidplus_list)
static void rename_callback (const char *old_path, const char *new_path)
static int broken_uidvs ()
static void logoutmsg ()
void bye ()
char * get_myrightson (const char *mailbox)
static void list_acl (const char *mailbox, maildir_aclt_list *)
static int get_acllist (maildir_aclt_list *l, const char *mailbox, char **computed_mailbox_owner)
static void list_myrights (const char *mailbox, const char *myrights)
static void list_postaddress (const char *mailbox)
static void accessdenied (const char *cmd, const char *folder, const char *acl_required)
static int list_callback (const char *hiersep, const char *mailbox, int flags, void *void_arg)
static int acl_read_folder (maildir_aclt_list *aclt_list, const char *maildir, const char *path)
static int acl_write_folder (maildir_aclt_list *aclt_list, const char *maildir, const char *path, const char *owner, const char **err_failedrights)
static void writeacl (const char *)
static void myrights ()
static int list_acl_cb (const char *ident, const maildir_aclt *acl, void *cb_arg)
char * compute_myrights (maildir_aclt_list *l, const char *l_owner)
static void writeacl1 (char *p)
static int getacl_cb (const char *ident, const maildir_aclt *acl, void *cb_arg)
void check_rights (const char *mailbox, char *rights_buf)
static int aclmailbox_scan (const char *hiersep, const char *mailbox, int flags, void *void_arg)
static void free_temp_acl_mailbox (struct temp_acl_mailbox_list *p)
static int cmp_mb (const void *a, const void *b)
static int aclmailbox_merge (struct temp_acl_mailbox_list *l, struct temp_acl_mailbox_list **mailbox_list)
static int aclstore (const char *, struct temp_acl_mailbox_list *)
static int aclset (const char *, struct temp_acl_mailbox_list *)
static int acldelete (const char *, struct temp_acl_mailbox_list *)
static void free_mailboxlist (struct temp_acl_mailbox_list *mailboxlist)
static void free_tempmailboxlist (struct temp_acl_mailbox_list *mailboxlist)
static int aclcmd (const char *tag)
static int fix_acl_delete (int(*func)(maildir_aclt *, const char *, const maildir_aclt *), maildir_aclt *newacl, const char *aclstr)
static int fix_acl_delete2 (maildir_aclt_list *aclt_list, const char *identifier, const char *aclstr)
void aclminimum (const char *identifier)
static void aclfailed (const char *mailbox, const char *identifier)
static int acl_settable_folder (char *mailbox, struct maildir_info *mi)
int acl_lock (const char *homedir, int(*func)(void *), void *void_arg)
static int do_acl_mod_0 (void *)
static int do_acl_mod (maildir_aclt_list *aclt_list, struct maildir_info *mi, const char *identifier, const char *newrights, const char **acl_error)
static int do_aclset (void *)
static int do_acldelete (void *)
static int folder_exists_cb (const char *hiersep, const char *mailbox, int flags, void *void_arg)
static int folder_exists (const char *folder)
int do_folder_delete (char *mailbox_name)
int acl_flags_adjust (const char *access_rights, struct imapflags *flags)
static int append (const char *tag, const char *mailbox, const char *path)
static int check_parent_create (const char *tag, const char *cmd, char *folder)
static char * acl2_identifier (const char *tag, const char *identifier)
int folder_rename (struct maildir_info *mi1, struct maildir_info *mi2, const char **errmsg)
static int validate_charset (const char *tag, char **charset)
int do_imap_command (const char *tag)
static void dogethostname ()
static void chkdisabled (const char *ip, const char *port)
static int chk_clock_skew ()
int main (int argc, char **argv)

Variables

unsigned long header_count
unsigned long body_count
time_t start_time
static const char * protocol
char * dot_trash = "." TRASH
char * trash = TRASH
char * current_mailbox = 0
FILE * debugfile = 0
int current_temp_fd = -1
const char * current_temp_fn = NULL
int current_mailbox_ro
char * current_mailbox_acl
dev_t homedir_dev
ino_t homedir_ino

Class Documentation

struct noopKeywordUpdateInfo

Definition at line 1120 of file imapd.c.

Collaboration diagram for noopKeywordUpdateInfo:
Class Members
struct libmail_kwHashtable * keywordList
struct libmail_kwMessage * messagePtr
struct addRemoveKeywordInfo

Definition at line 1906 of file imapd.c.

Collaboration diagram for addRemoveKeywordInfo:
Class Members
struct storeinfo * storeinfo
struct imap_addRemoveKeywordInfo

Definition at line 2070 of file imapd.c.

Class Members
char * msgset
int uid
struct temp_acl_mailbox_list

Definition at line 2823 of file imapd.c.

Collaboration diagram for temp_acl_mailbox_list:
Class Members
int flags
char * hier
char * mailbox
struct temp_acl_mailbox_list * next
struct do_acl_info

Definition at line 3232 of file imapd.c.

Collaboration diagram for do_acl_info:
Class Members
const char ** acl_error
maildir_aclt_list * aclt_list
const char * identifier
struct maildir_info * mi
const char * newrights
struct aclset_info

Definition at line 3406 of file imapd.c.

Collaboration diagram for aclset_info:
Class Members
const char ** acl_error
struct maildir_info * mi
maildir_aclt_list * newlist
struct acldelete_info

Definition at line 3511 of file imapd.c.

Collaboration diagram for acldelete_info:
Class Members
const char * identifier
const char * mailbox
struct maildir_info * mi

Define Documentation

#define dirent   direct

Definition at line 24 of file imapd.c.

#define DO_FLAG (   flag,
  flagname 
)
Value:
if (flags & (flag)) { writes(sep); writes(flagname); \
                            sep=" "; }
#define is_smap ( )    0

Definition at line 6291 of file imapd.c.

#define KEYWORD_IMAPVERBOTTEN   " (){%*\"\\]"

Definition at line 89 of file imapd.c.

#define KEYWORD_SMAPVERBOTTEN   ","

Definition at line 90 of file imapd.c.

#define NAMLEN (   dirent)    (dirent)->d_namlen

Definition at line 25 of file imapd.c.

#define UIDN (   u)    ( new_uids ? (u)->uid:(u)->old_uid )

Function Documentation

static void accessdenied ( const char *  cmd,
const char *  folder,
const char *  acl_required 
) [static]

Definition at line 3603 of file imapd.c.

{
       writes(" NO Access denied for ");
       writes(cmd);
       writes(" on ");
       writes(folder);
       writes(" (ACL \"");
       writes(acl_required);
       writes("\" required)\r\n");
}

Here is the call graph for this function:

Here is the caller graph for this function:

static char* acl2_identifier ( const char *  tag,
const char *  identifier 
) [static]

Definition at line 3859 of file imapd.c.

{
       const char *ident_orig=identifier;

       char *p;
       int isneg=0;

       if (*identifier == '-')
       {
              isneg=1;
              ++identifier;
       }

       if (strcmp(identifier, "anyone") == 0 ||
           strcmp(identifier, "anonymous") == 0 ||
           strcmp(identifier, "authuser") == 0 ||
           strcmp(identifier, "owner") == 0 ||
           strcmp(identifier, "administrators") == 0)
              return my_strdup(ident_orig);

       if (strchr(identifier, '='))
       {
              writes(tag);
              writes(" NO Invalid ACL identifier.\r\n");
              return NULL;
       }

       p=malloc(sizeof("-user=")+strlen(identifier));

       if (!p)
              write_error_exit(0);
       return strcat(strcat(strcpy(p, isneg ? "-":""), "user="), identifier);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int acl_flags_adjust ( const char *  access_rights,
struct imapflags flags 
)

Definition at line 3683 of file imapd.c.

{
       if (strchr(access_rights, ACL_DELETEMSGS[0]) == NULL)
              flags->deleted=0;
       if (strchr(access_rights, ACL_SEEN[0]) == NULL)
              flags->seen=0;
       if (strchr(access_rights, ACL_WRITE[0]) == NULL)
       {
              flags->answered=flags->flagged=flags->drafts=0;
              return 1;
       }
       return 0;
}

Here is the caller graph for this function:

int acl_lock ( const char *  homedir,
int(*)(void *)  func,
void *  void_arg 
)

Definition at line 3217 of file imapd.c.

{
       struct imapscaninfo ii;
       int rc;

       imapscan_init(&ii);
       rc=imapmaildirlock(&ii, homedir, func, void_arg);
       imapscan_free(&ii);
       return rc;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int acl_read_folder ( maildir_aclt_list aclt_list,
const char *  maildir,
const char *  path 
) [static]

Definition at line 2403 of file imapd.c.

{
       char *p, *q;
       int rc;

       /* Handle legacy shared. namespace */

       if (strcmp(path, SHARED) == 0)
       {
              maildir_aclt_list_init(aclt_list);
              if (maildir_aclt_list_add(aclt_list, "anyone",
                                     ACL_LOOKUP, NULL) < 0)
              {
                     maildir_aclt_list_destroy(aclt_list);
                     return -1;
              }
              return 0;
       }

       if (strncmp(path, SHARED ".", sizeof(SHARED)) == 0)
       {
              maildir_aclt_list_init(aclt_list);

              if (strchr(path+sizeof(SHARED), '.') == 0)
              {
                     if (maildir_aclt_list_add(aclt_list,
                                            "anyone",
                                            ACL_LOOKUP, NULL) < 0)
                     {
                            maildir_aclt_list_destroy(aclt_list);
                            return -1;
                     }
              }

              p=maildir_shareddir(maildir, path+sizeof(SHARED));
              if (!p)
              {
                     if (maildir_aclt_list_add(aclt_list,
                                            "anyone",
                                            ACL_LOOKUP, NULL) < 0)
                     {
                            maildir_aclt_list_destroy(aclt_list);
                            return -1;
                     }
                     return 0;
              }
              q=malloc(strlen(p)+sizeof("/new"));
              if (!q)
              {
                     free(p);
                     maildir_aclt_list_destroy(aclt_list);
                     return -1;
              }
              strcat(strcpy(q, p), "/new");
              free(p);

              if (maildir_aclt_list_add(aclt_list,
                                     "anyone",
                                     access(q, W_OK) == 0 ?
                                     ACL_LOOKUP ACL_READ
                                     ACL_SEEN ACL_WRITE ACL_INSERT

                                     ACL_DELETEFOLDER /* Wrong, but needed for ACL1 compatibility */

                                     ACL_DELETEMSGS ACL_EXPUNGE:
                                     ACL_LOOKUP ACL_READ ACL_SEEN
                                     ACL_WRITE, NULL) < 0)
              {
                     free(q);
                     maildir_aclt_list_destroy(aclt_list);
                     return -1;
              }
              free(q);
              return 0;
       }

       p=maildir_name2dir(".", path);

       if (!p)
              return -1;

       rc=maildir_acl_read(aclt_list, maildir, p[0] == '.' && p[1] == '/'
                         ? p+2:p);
       free(p);
       return rc;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int acl_settable_folder ( char *  mailbox,
struct maildir_info mi 
) [static]

Definition at line 3195 of file imapd.c.

{
       if (maildir_info_imap_find(mi, mailbox, getenv("AUTHENTICATED")) < 0)
       {
              aclfailed(mailbox, NULL);
              *mailbox=0;
              return (-1);
       }

       if (mi->homedir == NULL || mi->maildir == NULL)
       {
              writes("* ACLFAILED \"");
              writeqs(mailbox);
              writes("\" ACLs may not be modified for special mailbox\r\n");
              maildir_info_destroy(mi);
              *mailbox=0;
              return -1;
       }
       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int acl_write_folder ( maildir_aclt_list aclt_list,
const char *  maildir,
const char *  path,
const char *  owner,
const char **  err_failedrights 
) [static]

Definition at line 2492 of file imapd.c.

{
       char *p;
       int rc;

       if (strcmp(path, SHARED) == 0 ||
           strncmp(path, SHARED ".", sizeof(SHARED ".")-1) == 0)
       {
              /* Legacy */

              return 1;
       }

       p=maildir_name2dir(".", path);

       if (!p)
              return -1;

       rc=maildir_acl_write(aclt_list, maildir, p[0] == '.' && p[1] == '/'
                          ? p+2:p,
                          owner, err_failedrights);
       free(p);
       return rc;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int aclcmd ( const char *  tag) [static]

Definition at line 2976 of file imapd.c.

{
       char aclcmd[11];
       struct temp_acl_mailbox_list *mailboxlist;
       struct temp_acl_mailbox_list *mblist;
       struct imaptoken *curtoken;
       size_t i;
       int rc;
       int (*aclfunc)(const char *, struct temp_acl_mailbox_list *);

       /* Expect ACL followed only by: STORE/DELETE/SET */

       if ((curtoken=nexttoken())->tokentype != IT_ATOM ||
           strlen(curtoken->tokenbuf) > sizeof(aclcmd)-1)
       {
              errno=EINVAL;
              return -1;
       }

       strcpy(aclcmd, curtoken->tokenbuf);

       mailboxlist=NULL;

       switch ((curtoken=nexttoken_nouc())->tokentype) {
       case IT_LPAREN:
              while ((curtoken=nexttoken_nouc())->tokentype != IT_RPAREN)
              {
                     if (curtoken->tokentype != IT_QUOTED_STRING &&
                            curtoken->tokentype != IT_ATOM &&
                            curtoken->tokentype != IT_NUMBER)
                     {
                            errno=EINVAL;
                            return -1;
                     }

                     mblist=NULL;

                     if (mailbox_scan("", curtoken->tokenbuf, 0,
                                    aclmailbox_scan, &mblist) ||
                         aclmailbox_merge(mblist, &mailboxlist))
                     {
                            free_tempmailboxlist(mblist);
                            free_mailboxlist(mailboxlist);
                            return -1;

                     }

                     free_tempmailboxlist(mblist);
              }
              break;
       case IT_QUOTED_STRING:
       case IT_ATOM:
       case IT_NUMBER:

              mblist=NULL;
              if (mailbox_scan("", curtoken->tokenbuf, LIST_CHECK1FOLDER,
                             aclmailbox_scan, &mblist) ||
                  aclmailbox_merge(mblist, &mailboxlist))

              {
                     free_tempmailboxlist(mblist);
                     free_mailboxlist(mailboxlist);
                     return -1;
              }
              free_tempmailboxlist(mblist);
              break;
       }

       rc=0;

       aclfunc=strcmp(aclcmd, "STORE") == 0 ? aclstore:
              strcmp(aclcmd, "DELETE") == 0 ? acldelete:
              strcmp(aclcmd, "SET") == 0 ? aclset:NULL;

       rc= aclfunc ? (*aclfunc)(tag, mailboxlist): -1;

       if (rc == 0)
       {
              for (i=0; mailboxlist && mailboxlist[i].mailbox; i++)
              {
                     if (mailboxlist[i].mailbox[0])
                            list_callback(mailboxlist[i].hier,
                                         mailboxlist[i].mailbox,
                                         LIST_ACL | mailboxlist[i].flags,
                                         "LIST");
              }
       }
       free_mailboxlist(mailboxlist);

       if (rc == 0)
       {
              writes(tag);
              writes(" OK ACL ");
              writes(aclcmd);
              writes(" completed.\r\n");
       }
       else
       {
              errno=EINVAL;
       }
       return rc;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int acldelete ( const char *  tag,
struct temp_acl_mailbox_list mailboxes 
) [static]

Definition at line 3519 of file imapd.c.

{
       struct imaptoken *curtoken;
       const char *identifier;
       size_t i;

       if ((curtoken=nexttoken_nouc())->tokentype != IT_QUOTED_STRING &&
           curtoken->tokentype != IT_ATOM &&
           curtoken->tokentype != IT_NUMBER)
              return -1;

       identifier=curtoken->tokenbuf;

       for (i=0; mailboxes && mailboxes[i].mailbox; i++)
       {
              struct maildir_info mi;
              struct acldelete_info ai;

              if (acl_settable_folder(mailboxes[i].mailbox, &mi))
                     continue;

              {
                     CHECK_RIGHTSM(mailboxes[i].mailbox,
                                  acl_rights,
                                  ACL_ADMINISTER);
                     if (acl_rights[0] == 0)
                     {
                            writes("* ACLFAILED \"");
                            writeqs(mailboxes[i].mailbox);
                            writes("\"");
                            accessdenied("ACL DELETE",
                                        mailboxes[i].mailbox,
                                        ACL_ADMINISTER);
                            maildir_info_destroy(&mi);
                            mailboxes[i].mailbox[0]=0;
                            continue;
                     }
              }

              ai.mailbox=mailboxes[i].mailbox;
              ai.mi= &mi;
              ai.identifier=identifier;
              if (acl_lock(mi.homedir, do_acldelete, &ai))
                     mailboxes[i].mailbox[0]=0;
              maildir_info_destroy(&mi);
       }
       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void aclfailed ( const char *  mailbox,
const char *  identifier 
) [static]

Definition at line 3173 of file imapd.c.

{
       if (!identifier)
       {
              writes("* ACLFAILED \"");
              writeqs(mailbox);
              writes("\" ");
              writes(strerror(errno));
              writes("\r\n");
              return;
       }

       writes("* RIGHTS-INFO \"");
       writeqs(mailbox);
       writes("\" \"");
       writeqs(identifier);
       writes("\" ");

       aclminimum(identifier);
       writes("\r\n");
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int aclmailbox_merge ( struct temp_acl_mailbox_list l,
struct temp_acl_mailbox_list **  mailbox_list 
) [static]

Definition at line 2882 of file imapd.c.

{
       size_t n, o;
       struct temp_acl_mailbox_list *p;
       struct temp_acl_mailbox_list *newa;

       /* Count # of mailboxes so far */

       for (n=0; *mailbox_list && (*mailbox_list)[n].mailbox; n++)
              ;

       /* Count # of new mailboxes */

       for (p=l, o=0; p; p=p->next)
              ++o;

       if (n + o == 0)
              return 0; /* The list is empty */

       /* Expand the array */

       if ((newa= *mailbox_list == NULL ? malloc( (n+o+1)*sizeof(*l)):
            realloc(*mailbox_list, (n+o+1)*sizeof(*l))) == NULL)
              return -1;

       *mailbox_list=newa;
       while (l)
       {
              newa[n]= *l;

              if ((newa[n].mailbox=strdup(l->mailbox)) == NULL)
                     return -1;

              if ((newa[n].hier=strdup(l->hier)) == NULL)
              {
                     free(newa[n].mailbox);
                     newa[n].mailbox=NULL;
                     return -1;
              }

              ++n;
              memset(&newa[n], 0, sizeof(newa[n]));

              l=l->next;
       }
       qsort(newa, n, sizeof(*l), cmp_mb);

       /* Remove dupes */

       for (n=o=0; newa[n].mailbox; n++)
       {
              if (newa[n+1].mailbox &&
                  strcmp(newa[n].mailbox, newa[n+1].mailbox) == 0)
              {
                     free_temp_acl_mailbox(&newa[n]);
                     continue;
              }
              newa[o]=newa[n];
              ++o;
       }
       memset(&newa[o], 0, sizeof(newa[o]));

       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int aclmailbox_scan ( const char *  hiersep,
const char *  mailbox,
int  flags,
void *  void_arg 
) [static]

Definition at line 2835 of file imapd.c.

{
       struct temp_acl_mailbox_list **p
              =(struct temp_acl_mailbox_list **)void_arg,
              *q=malloc(sizeof(struct temp_acl_mailbox_list));

       if (!q || !(q->mailbox=malloc(strlen(mailbox)+1)))
       {
              if (q) free(q);
              return -1;
       }
       if (!(q->hier=strdup(hiersep)))
       {
              free(q->mailbox);
              free(q);
              return -1;
       }
       strcpy(q->mailbox, mailbox);
       q->next= *p;
       q->flags=flags;
       *p=q;
       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void aclminimum ( const char *  identifier)

Definition at line 3145 of file imapd.c.

{
       if (strcmp(identifier, "administrators") == 0 ||
           strcmp(identifier, "group=administrators") == 0)
       {
              writes(ACL_ALL);
              return;
       }

       if (strcmp(identifier, "-administrators") == 0 ||
           strcmp(identifier, "-group=administrators") == 0)
       {
              writes("\"\"");
              return;
       }

       writes(*identifier == '-' ? "\"\"":ACL_ADMINISTER ACL_LOOKUP);
       writes(" " ACL_CREATE
              " " ACL_EXPUNGE 
              " " ACL_INSERT
              " " ACL_POST
              " " ACL_READ
              " " ACL_SEEN
              " " ACL_DELETEMSGS
              " " ACL_WRITE
              " " ACL_DELETEFOLDER);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int aclset ( const char *  tag,
struct temp_acl_mailbox_list mailboxes 
) [static]

Definition at line 3414 of file imapd.c.

{
       struct imaptoken *curtoken;
       char *identifier;
       maildir_aclt_list newlist;
       size_t i;

       maildir_aclt_list_init(&newlist);

       while ((curtoken=nexttoken_nouc())->tokentype != IT_EOL)
       {
              if (curtoken->tokentype != IT_QUOTED_STRING &&
                  curtoken->tokentype != IT_ATOM &&
                  curtoken->tokentype != IT_NUMBER)
                     return -1;
              if ((identifier=strdup(curtoken->tokenbuf)) == NULL)
                     write_error_exit(0);

              if ((curtoken=nexttoken_nouc())->tokentype
                  != IT_QUOTED_STRING &&
                  curtoken->tokentype != IT_ATOM &&
                  curtoken->tokentype != IT_NUMBER)
              {
                     free(identifier);
                     maildir_aclt_list_destroy(&newlist);
                     return -1;
              }

              if (fix_acl_delete2(&newlist, identifier,
                                curtoken->tokenbuf) < 0)
              {
                     maildir_aclt_list_destroy(&newlist);
                     writes(tag);
                     writes(" NO ACL SET <");
                     writes(identifier);
                     writes(", ");
                     writes(curtoken->tokenbuf);
                     writes("> failed.\r\n");
                     free(identifier);
                     return 0;
              }
              free(identifier);
       }

       for (i=0; mailboxes && mailboxes[i].mailbox; i++)
       {
              const char *acl_error;
              struct maildir_info mi;
              struct aclset_info ai;

              if (acl_settable_folder(mailboxes[i].mailbox, &mi))
                     continue;

              {
                     CHECK_RIGHTSM(mailboxes[i].mailbox,
                                  acl_rights,
                                  ACL_ADMINISTER);
                     if (acl_rights[0] == 0)
                     {
                            maildir_info_destroy(&mi);
                            writes("* ACLFAILED \"");
                            writeqs(mailboxes[i].mailbox);
                            writes("\"");
                            accessdenied("ACL SET", mailboxes[i].mailbox,
                                        ACL_ADMINISTER);
                            mailboxes[i].mailbox[0]=0;
                            continue;
                     }
              }

              acl_error=NULL;
              ai.mi=&mi;
              ai.acl_error= &acl_error;
              ai.newlist= &newlist;

              if (acl_lock(mi.homedir, do_aclset, &ai))
              {
                     aclfailed(mailboxes[i].mailbox, acl_error);
                     maildir_info_destroy(&mi);
                     mailboxes[i].mailbox[0]=0;
                     continue;
              }
              maildir_info_destroy(&mi);
       }
       maildir_aclt_list_destroy(&newlist);
       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int aclstore ( const char *  tag,
struct temp_acl_mailbox_list mailboxes 
) [static]

Definition at line 3333 of file imapd.c.

{
       struct imaptoken *curtoken;
       char *identifier;
       size_t i;

       if ((curtoken=nexttoken_nouc())->tokentype != IT_QUOTED_STRING &&
           curtoken->tokentype != IT_ATOM &&
           curtoken->tokentype != IT_NUMBER)
              return -1;

       if ((identifier=strdup(curtoken->tokenbuf)) == NULL)
              write_error_exit(0);

       if ((curtoken=nexttoken_nouc())->tokentype != IT_QUOTED_STRING &&
           curtoken->tokentype != IT_ATOM &&
           curtoken->tokentype != IT_NUMBER)
       {
              free(identifier);
              return -1;
       }

       for (i=0; mailboxes && mailboxes[i].mailbox; i++)
       {
              maildir_aclt_list aclt_list;
              const char *acl_error;
              struct maildir_info mi;

              if (acl_settable_folder(mailboxes[i].mailbox, &mi))
                     continue;

              {
                     CHECK_RIGHTSM(mailboxes[i].mailbox,
                                  acl_rights,
                                  ACL_ADMINISTER);
                     if (acl_rights[0] == 0)
                     {
                            writes("* ACLFAILED \"");
                            writeqs(mailboxes[i].mailbox);
                            writes("\"");
                            accessdenied("ACL STORE",
                                        mailboxes[i].mailbox,
                                        ACL_ADMINISTER);
                            maildir_info_destroy(&mi);
                            mailboxes[i].mailbox[0]=0;
                            continue;
                     }
              }

              if (acl_read_folder(&aclt_list, mi.homedir, mi.maildir))
              {
                     aclfailed(mailboxes[i].mailbox, NULL);
                     maildir_info_destroy(&mi);
                     continue;
              }

              if (do_acl_mod(&aclt_list, &mi, identifier, curtoken->tokenbuf,
                            &acl_error) < 0)
              {
                     aclfailed(mailboxes[i].mailbox, acl_error);

                     maildir_aclt_list_destroy(&aclt_list);
                     maildir_info_destroy(&mi);
                     continue;
              }
              maildir_aclt_list_destroy(&aclt_list);
              maildir_info_destroy(&mi);
       }

       free(identifier);
       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int addRemoveKeywords ( int(*)(void *, void *)  callback_func,
void *  callback_func_arg,
struct storeinfo storeinfo_s 
)

Definition at line 1864 of file imapd.c.

{
       int tryagain;
       struct addremove_info ai;

       if (!keywords())
              return 0;

       if (current_mailbox_acl &&
           strchr(current_mailbox_acl, ACL_WRITE[0]) == NULL)
              return 0; /* No permission */
       do
       {
              ai.callback_func=callback_func;
              ai.callback_func_arg=callback_func_arg;
              ai.storeinfo_s=storeinfo_s;
              ai.tryagain= &tryagain;

              if (imapmaildirlock(&current_maildir_info,
                                current_mailbox,
                                addRemoveKeywords1,
                                &ai))
                     return -1;
       } while (tryagain);

       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int addRemoveKeywords1 ( void *  void_arg) [static]

Definition at line 1894 of file imapd.c.

{
       struct addremove_info *ai=(struct addremove_info *)void_arg;

       return addRemoveKeywords2(ai->callback_func,
                              ai->callback_func_arg,
                              ai->storeinfo_s,
                              ai->tryagain);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int addRemoveKeywords2 ( int(*)(void *, void *)  callback_func,
void *  callback_func_arg,
struct storeinfo storeinfo_s,
int *  tryagain 
) [static]

Definition at line 1911 of file imapd.c.

{
       struct addRemoveKeywordInfo arki;
       int rc;

       *tryagain=0;

       libmail_kwgInit(&arki.kwg);

       arki.storeinfo=storeinfo_s;

       rc=libmail_kwgReadMaildir(&arki.kwg, current_mailbox);

       if (rc == 0)
              rc= (*callback_func)(callback_func_arg, &arki);

       if (rc < 0)
       {
              libmail_kwgDestroy(&arki.kwg);
              return -1;
       }

       if (rc > 0) /* Race */
       {
              libmail_kwgDestroy(&arki.kwg);
              *tryagain=1;
              return 0;
       }

       libmail_kwgDestroy(&arki.kwg);
       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static char* alloc_filename ( const char *  mbox,
const char *  name 
) [static]

Definition at line 1374 of file imapd.c.

{
char   *p=malloc(strlen(mbox)+strlen(name)+sizeof("/cur/"));

       if (!p)       write_error_exit(0);

       strcat(strcat(strcpy(p, mbox), "/cur/"), name);
       return (p);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int append ( const char *  tag,
const char *  mailbox,
const char *  path 
) [static]

Definition at line 3698 of file imapd.c.

{

       struct imapflags flags;
       struct libmail_kwMessage *keywords;
       time_t timestamp=0;
       unsigned long new_uidv, new_uid;
       char access_rights[8];
       struct imaptoken *curtoken;

       if (access(path, 0))
       {
              writes(tag);
              writes(" NO [TRYCREATE] Must create mailbox before append\r\n");
              return (0);
       }

       {
              CHECK_RIGHTSM(mailbox,
                           append_rights,
                           ACL_INSERT ACL_DELETEMSGS
                           ACL_SEEN ACL_WRITE);

              if (strchr(append_rights, ACL_INSERT[0]) == NULL)
              {
                     writes(tag);
                     accessdenied("APPEND",
                                 mailbox,
                                 ACL_INSERT);
                     return 0;
              }

              strcpy(access_rights, append_rights);
       }

       if (current_mailbox &&
           strcmp(path, current_mailbox) == 0 && current_mailbox_ro)
       {
              writes(tag);
              writes(" NO Current box is selected READ-ONLY.\r\n");
              return (0);
       }

       curtoken=nexttoken_noparseliteral();
       memset(&flags, 0, sizeof(flags));
       if ((keywords=libmail_kwmCreate()) == NULL)
              write_error_exit(0);

       if (curtoken->tokentype == IT_LPAREN)
       {
              if (get_flagsAndKeywords(&flags, &keywords))
              {
                     libmail_kwmDestroy(keywords);
                     return (-1);
              }
              curtoken=nexttoken_noparseliteral();
       }
       else if (curtoken->tokentype == IT_ATOM)
       {
              if (get_flagname(curtoken->tokenbuf, &flags))
              {
                     if (!valid_keyword(curtoken->tokenbuf))
                     {
                            libmail_kwmDestroy(keywords);
                            return -1;
                     }

                     libmail_kwmSetName(current_maildir_info.keywordList,
                                      keywords,
                                      curtoken->tokenbuf);
              }
              curtoken=nexttoken_noparseliteral();
       }
       else if (curtoken->tokentype == IT_NIL)
              curtoken=nexttoken_noparseliteral();

       if (curtoken->tokentype == IT_QUOTED_STRING)
       {
              timestamp=decode_date_time(curtoken->tokenbuf);
              if (timestamp == 0)
              {
                     libmail_kwmDestroy(keywords);
                     return (-1);
              }
              curtoken=nexttoken_noparseliteral();
       }
       else if (curtoken->tokentype == IT_NIL)
              curtoken=nexttoken_noparseliteral();

       if (curtoken->tokentype != IT_LITERAL_STRING_START)
       {
              libmail_kwmDestroy(keywords);
              return (-1);
       }

       acl_flags_adjust(access_rights, &flags);

       if (store_mailbox(tag, path, &flags,
                       acl_flags_adjust(access_rights, &flags)
                       ? NULL:keywords,
                       timestamp,
                       curtoken->tokennum, &new_uidv, &new_uid))
       {
              libmail_kwmDestroy(keywords);
              unread('\n');
              return (0);
       }
       libmail_kwmDestroy(keywords);

       if (nexttoken()->tokentype != IT_EOL)
       {
              return (-1);
       }

       dirsync(path);
       writes(tag);
       writes(" OK [APPENDUID ");
       writen(new_uidv);
       writes(" ");
       writen(new_uid);
       writes("] APPEND Ok.\r\n");
       return (0);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void append_flags ( char *  buf,
struct imapflags flags 
)

Definition at line 597 of file imapd.c.

{
       if (flags->drafts)   strcat(buf, "D");
       if (flags->flagged)  strcat(buf, "F");
       if (flags->answered) strcat(buf, "R");
       if (flags->seen)     strcat(buf, "S");
       if (flags->deleted)  strcat(buf, "T");
}

Here is the caller graph for this function:

static int broken_uidvs ( ) [static]

Definition at line 2228 of file imapd.c.

{
       const char *p=getenv("IMAP_BROKENUIDV");

       return (p && atoi(p) != 0);
}

Here is the caller graph for this function:

void bye ( )

Definition at line 2240 of file imapd.c.

Here is the caller graph for this function:

void bye_msg ( const char *  )

Definition at line 46 of file imaptoken.c.

{
       const char *a=getenv("AUTHENTICATED");
       char buf[NUMBUFSIZE];
       const char *tls=getenv("IMAP_TLS");

       libmail_str_time_t(time(NULL)-start_time, buf);

       if (tls && atoi(tls))
              tls=", starttls=1";
       else
              tls="";

       if (a && *a)
              fprintf(stderr, "%s, user=%s, "
                     "ip=[%s], headers=%lu, body=%lu, rcvd=%lu, sent=%lu, time=%s%s\n",
                     type,
                     a, getenv("TCPREMOTEIP"), header_count, body_count, bytes_received_count, bytes_sent_count,
                     buf, tls);
       else
              fprintf(stderr, "DEBUG: Disconnected, ip=[%s], time=%s%s\n",
                     getenv("TCPREMOTEIP"),
                     buf, tls);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int check_parent_create ( const char *  tag,
const char *  cmd,
char *  folder 
) [static]

Definition at line 3825 of file imapd.c.

{
       char *parentPtr;

       parentPtr=strrchr(folder, HIERCH);

       if (parentPtr)
       {
              *parentPtr=0;

              {
                     CHECK_RIGHTSM(folder,
                                  create_rights,
                                  ACL_CREATE);

                     if (create_rights[0])
                     {
                            if (parentPtr)
                                   *parentPtr=HIERCH;
                            return 0;
                     }
              }
       }

       writes(tag);
       accessdenied(cmd, folder, ACL_CREATE);
       if (parentPtr)
              *parentPtr=HIERCH;
       return -1;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void check_rights ( const char *  mailbox,
char *  rights_buf 
)

Definition at line 2777 of file imapd.c.

{
       char *r=get_myrightson(mailbox);
       char *p, *q;

       if (!r)
       {
              fprintf(stderr, "ERR: Error reading ACLs for %s: %s\n",
                     mailbox, strerror(errno));
              *rights_buf=0;
              return;
       }

       for (p=q=rights_buf; *p; p++)
       {
              if (strchr(r, *p) == NULL)
                     continue;

              *q++ = *p;
       }
       *q=0;
       free(r);
}

Here is the call graph for this function:

static int chk_clock_skew ( ) [static]

Definition at line 6249 of file imapd.c.

{
       static const char fn[]="tmp/courier-imap.clockskew.chk";
       struct stat stat_buf;
       int fd;
       time_t t;

       unlink(fn);
       fd=open(fn, O_RDWR|O_TRUNC|O_CREAT, 0666);
       time(&t);

       if (fd < 0)
              return 0; /* Something else is wrong */

       if (fstat(fd, &stat_buf) < 0)
       {
              close(fd);
              return -1; /* Something else is wrong */
       }
       close(fd);
       unlink(fn);

       if (stat_buf.st_mtime < t - 30 || stat_buf.st_mtime > t+30)
              return -1;
       return 0;
}

Here is the caller graph for this function:

static void chkdisabled ( const char *  ip,
const char *  port 
) [static]

Definition at line 6226 of file imapd.c.

{
       const char *p;
       if (auth_getoptionenvint("disableimap"))
       {
              writes("* BYE IMAP access disabled for this account.\r\n");
              writeflush();
              exit(0);
       }

       if (    auth_getoptionenvint("disableinsecureimap")
           && ((p=getenv("IMAP_TLS")) == NULL || !atoi(p)))
       {
              writes("* BYE IMAP access disabled via insecure connection.\r\n");
              writeflush();
              exit(0);
       }

       fprintf(stderr, "INFO: LOGIN, user=%s, ip=[%s], port=[%s], protocol=%s\n",
              getenv("AUTHENTICATED"), ip, port,
              protocol);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int cmp_mb ( const void *  a,
const void *  b 
) [static]

Definition at line 2868 of file imapd.c.

{
       return (strcmp ( ((struct temp_acl_mailbox_list *)a)->mailbox,
                      ((struct temp_acl_mailbox_list *)b)->mailbox));
}

Here is the caller graph for this function:

char * compute_myrights ( maildir_aclt_list l,
const char *  l_owner 
)

Definition at line 2763 of file imapd.c.

{
       maildir_aclt aa;
       char *a;

       if (maildir_acl_computerights(&aa, l, getenv("AUTHENTICATED"),
                                  l_owner) < 0)
              return NULL;

       a=my_strdup(maildir_aclt_ascstr(&aa));
       maildir_aclt_destroy(&aa);
       return a;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static time_t decode_date_time ( char *  p) [static]

Definition at line 403 of file imapd.c.

{
unsigned      i;

       /* Convert to format rfc822_parsedt likes */

       for (i=1; p[i] != ' '; i++)
       {
              if (!p[i])    return (0);
              if (p[i] == '-')     p[i]=' ';
       }
       return (rfc822_parsedt(p));
}

Here is the call graph for this function:

Here is the caller graph for this function:

char* decode_valid_mailbox ( const char *  p,
int  autosubscribe 
)

Definition at line 330 of file imapd.c.

{
       struct maildir_info mi;
       char *q, *r;

       if (maildir_info_imap_find(&mi, p, getenv("AUTHENTICATED")) < 0)
       {
              return NULL;
       }

       if (mi.homedir && mi.maildir)
       {
              q=maildir_name2dir(mi.homedir, mi.maildir);

              if (q)
              {
                     r=malloc(strlen(q)+sizeof("/."));
                     if (!r)       write_error_exit(0);
                     strcat(strcpy(r, q), "/.");
                     if (access(r, 0) == 0)
                     {
                            free(r);
                            maildir_info_destroy(&mi);
                            return q;
                     }
                     free(r);
                     free(q);
              }
              maildir_info_destroy(&mi);
              return NULL;
       }

       if (mi.mailbox_type == MAILBOXTYPE_OLDSHARED)
       {
              const char *q;
              char *r;

              if ((q=strchr(p, '.')) == NULL)
              {
                     maildir_info_destroy(&mi);
                     errno=EINVAL;
                     return NULL;
              }

              r=maildir_shareddir(".", q+1);
              if (!r)
              {
                     maildir_info_destroy(&mi);
                     errno=EINVAL;
                     return NULL;
              }

              if (access(r, 0) == 0)
              {
                     maildir_info_destroy(&mi);
                     return r;
              }

              maildir_shared_subscribe(".", q+1);
              if (access(r, 0) == 0)
              {
                     maildir_info_destroy(&mi);
                     return r;
              }

              free(r);
              maildir_info_destroy(&mi);
              return NULL;
       }
       maildir_info_destroy(&mi);
       return (NULL);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void dirsync ( const char *  folder) [static]

Definition at line 1811 of file imapd.c.

{
#if EXPLICITDIRSYNC

       char *p=malloc(strlen(folder)+sizeof("/new"));
       int fd;

       if (!p)
              write_error_exit(0);

       p=strcat(strcpy(p, folder), "/new");

       fd=open(p, O_RDONLY);

       if (fd >= 0)
       {
              fsync(fd);
              close(fd);
       }

       p=strcat(strcpy(p, folder), "/cur");

       fd=open(p, O_RDONLY);

       if (fd >= 0)
       {
              fsync(fd);
              close(fd);
       }

       free(p);
#endif
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int do_acl_mod ( maildir_aclt_list aclt_list,
struct maildir_info mi,
const char *  identifier,
const char *  newrights,
const char **  acl_error 
) [static]

Definition at line 3241 of file imapd.c.

{
       struct do_acl_info dai;

       *acl_error=NULL;

       dai.aclt_list=aclt_list;
       dai.mi=mi;
       dai.identifier=identifier;
       dai.newrights=newrights;
       dai.acl_error=acl_error;
       return acl_lock(mi->homedir, do_acl_mod_0, &dai);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int do_acl_mod_0 ( void *  void_arg) [static]

Definition at line 3259 of file imapd.c.

{
       struct do_acl_info *dai=
              (struct do_acl_info *)void_arg;
       maildir_aclt_list *aclt_list=dai->aclt_list;
       struct maildir_info *mi=dai->mi;
       const char *identifier=dai->identifier;
       const char *newrights=dai->newrights;
       const char **acl_error=dai->acl_error;

       if (newrights[0] == '+')
       {
              maildir_aclt newacl;
              const maildir_aclt *oldacl;

              if (fix_acl_delete(&maildir_aclt_init,
                               &newacl, newrights+1) < 0
                  || ((oldacl=maildir_aclt_list_find(aclt_list, identifier))
                     != NULL && maildir_aclt_add(&newacl, NULL, oldacl) < 0)
                  || maildir_aclt_list_add(aclt_list, identifier, NULL,
                                        &newacl) < 0 ||
                  acl_write_folder(aclt_list, mi->homedir,
                                        mi->maildir,
                                        mi->owner, acl_error) < 0)

                     {
                            maildir_aclt_destroy(&newacl);
                            return -1;
                     }
              maildir_aclt_destroy(&newacl);
       }
       else if (newrights[0] == '-')
       {
              maildir_aclt newacl;
              const maildir_aclt *oldacl;

              oldacl=maildir_aclt_list_find(aclt_list, identifier);

              if (maildir_aclt_init(&newacl, oldacl == NULL ? "":NULL,
                                  oldacl) < 0
                  || fix_acl_delete(&maildir_aclt_del,
                                  &newacl, newrights+1) < 0
                  || (strlen(maildir_aclt_ascstr(&newacl)) == 0 ?
                     maildir_aclt_list_del(aclt_list, identifier):
                     maildir_aclt_list_add(aclt_list, identifier,
                                         NULL, &newacl)) < 0 ||
                  acl_write_folder(aclt_list, mi->homedir,
                                        mi->maildir,
                                        mi->owner,
                                        acl_error) < 0)
                     {
                            maildir_aclt_destroy(&newacl);
                            return -1;
                     }
                     maildir_aclt_destroy(&newacl);
       }
       else
       {
              acl_error=NULL;

              if ((newrights[0] == 0 ?
                   maildir_aclt_list_del(aclt_list, identifier):
                   fix_acl_delete2(aclt_list, identifier, newrights)) < 0
                  || acl_write_folder(aclt_list, mi->homedir,
                                   mi->maildir, mi->owner,
                                   acl_error) < 0)
              {
                     return -1;
              }
       }

       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int do_acldelete ( void *  void_arg) [static]

Definition at line 3568 of file imapd.c.

{
       struct acldelete_info *ai=
              (struct acldelete_info *)void_arg;
       const char *mailbox=ai->mailbox;
       struct maildir_info *mi=ai->mi;

       maildir_aclt_list aclt_list;
       const char *acl_error;

       if (acl_read_folder(&aclt_list, mi->homedir, mi->maildir) < 0)
       {
              writes("* NO Error reading ACLs for ");
              writes(mailbox);
              writes(": ");
              writes(strerror(errno));
              writes("\r\n");
              return -1;
       }

       acl_error=NULL;

       if (maildir_aclt_list_del(&aclt_list, ai->identifier) < 0 ||
           acl_write_folder(&aclt_list, mi->homedir, mi->maildir,
                          mi->owner, &acl_error) < 0)
       {
              aclfailed(mailbox, acl_error);
              maildir_aclt_list_destroy(&aclt_list);
              return -1;
       }
       maildir_aclt_list_destroy(&aclt_list);
       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int do_aclset ( void *  void_arg) [static]

Definition at line 3502 of file imapd.c.

{
       struct aclset_info *ai=(struct aclset_info *)void_arg;

       return acl_write_folder(ai->newlist, ai->mi->homedir,
                            ai->mi->maildir,
                            ai->mi->owner, ai->acl_error);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int do_count ( unsigned long  n,
int  byuid,
void *  voidptr 
) [static]

Definition at line 1799 of file imapd.c.

{
       const char *p=getenv("OUTBOX_MULTIPLE_SEND");

       ++ *(int *)voidptr;

       if (p && atoi(p))
              *(int *)voidptr=1; /* Suppress the error, below */

       return 0;
}

Here is the caller graph for this function:

void do_expunge ( unsigned long  from,
unsigned long  to,
int  force 
)

Definition at line 1551 of file imapd.c.

{
unsigned long j;
struct imapflags flags;
char   *old_name;
int    move_to_trash=0;
struct stat stat_buf;
const char *cp=getenv("IMAP_LOG_DELETIONS");
int log_deletions= cp && *cp != '0';

       fetch_free_cache();

       if (magictrash() &&
           !is_trash(strncmp(current_mailbox, "./", 2) == 0?
                    current_mailbox+2:current_mailbox))
              move_to_trash=1;

       for (j=expunge_start; j < expunge_end; j++)
       {
              int file_counted=0;

              get_message_flags(current_maildir_info.msgs+j, 0, &flags);

              if (!flags.deleted && !force)
                     continue;

              old_name=alloc_filename(current_mailbox,
                     current_maildir_info.msgs[j].filename);

              if (stat(old_name, &stat_buf) < 0)
              {
                     free(old_name);
                     continue;
              }

              if (maildirquota_countfolder(current_mailbox) &&
                  maildirquota_countfile(old_name))
                     file_counted=1;

              if (is_sharedsubdir(current_mailbox))
              {
                     maildir_unlinksharedmsg(old_name);
              }
              else if (move_to_trash && current_maildir_info
                      .msgs[j].copiedflag == 0)
              {
              char   *new_name;
              char   *p;
              int will_count=0;

                     new_name=alloc_filename(dot_trash,
                            current_maildir_info.msgs[j].filename);

                     if (maildirquota_countfolder(dot_trash))
                            will_count=1;

                     if (file_counted != will_count)
                     {
                            unsigned long filesize=0;

                            if (maildir_parsequota(old_name, &filesize))
                            {
                                   if (stat(old_name, &stat_buf))
                                          stat_buf.st_size=0;
                                   filesize=(unsigned long)
                                          stat_buf.st_size;
                            }

                            maildir_quota_deleted(".",
                                                (long)filesize *
                                                (will_count
                                                 -file_counted),
                                                will_count
                                                -file_counted);
                     }

                     if ((p=strrchr(new_name, '/')) &&
                         (p=strrchr(p, MDIRSEP[0])) &&
                         strncmp(p, MDIRSEP "2,", 3) == 0)
                     {
                            char *q;

                            /* Don't mark it as deleted in the Trash */

                            if ((q=strchr(p, 'T')) != NULL)
                                   while ((*q=q[1]) != 0)
                                          ++q;

                            /* Don't mark it as a draft msg in the Trash */

                            if ((q=strchr(p, 'D')) != NULL)
                                   while ((*q=q[1]) != 0)
                                          ++q;
                     }

                     if (log_deletions)
                            fprintf(stderr, "INFO: EXPUNGED, user=%s, ip=[%s], old_name=%s, new_name=%s: only new_name will be left\n",
                                   getenv("AUTHENTICATED"),
                                   getenv("TCPREMOTEIP"),
                                   old_name, new_name);

                     if (rename(old_name, new_name))
                     {
                            mdcreate(dot_trash);
                            rename(old_name, new_name);
                     }

                     unlink(old_name);
                     /* triggers linux kernel bug if also moved to Trash by
                     sqwebmail */

                     free(new_name);
              }
              else
              {
                     unlink(old_name);

                     if (file_counted)
                     {
                            unsigned long filesize=0;

                            if (maildir_parsequota(old_name, &filesize))
                            {
                                   if (stat(old_name, &stat_buf))
                                          stat_buf.st_size=0;
                                   filesize=(unsigned long)
                                          stat_buf.st_size;
                            }

                            maildir_quota_deleted(".",-(long)filesize, -1);
                     }
              }

              if (log_deletions)
                     fprintf(stderr, "INFO: EXPUNGED, user=%s, ip=[%s], old_name=%s\n",
                            getenv("AUTHENTICATED"),
                            getenv("TCPREMOTEIP"),
                            old_name);
              free(old_name);
       }
}

Here is the call graph for this function:

Here is the caller graph for this function:

int do_fetch ( unsigned  long,
int  ,
void *   
)

Definition at line 244 of file fetch.c.

{
       struct fetchinfo *fi=(struct fetchinfo *)p;
       FILE   *fp;
       struct rfc2045 *rfc2045p;
       int    seen;
       int    open_err;

       fp=NULL;
       open_err=0;

       writes("* ");
       writen(n);
       writes(" FETCH (");

       if (byuid)
       {
       struct fetchinfo *fip;

              for (fip=fi; fip; fip=fip->next)
                     if (strcmp(fip->name, "UID") == 0)
                            break;

              if (fip == 0)
              {
                     writes("UID ");
                     writen(current_maildir_info.msgs[n-1].uid);
                     writes(" ");
              }
       }
       seen=0;
       rfc2045p=0;
       while (fi)
       {
              if (fetchitem(&fp, &open_err, fi, &current_maildir_info, n-1,
                     &rfc2045p))   seen=1;
              if ((fi=fi->next) != 0)     writes(" ");
       }
       writes(")\r\n");

       if (open_err)
       {
              writes("* NO Cannot open message ");
              writen(n);
              writes("\r\n");
              return (0);
       }


#if SMAP
       if (!smapflag)
#endif
              if (current_mailbox_acl &&
                  strchr(current_mailbox_acl, ACL_SEEN[0]) == NULL)
                     seen=0; /* No permissions */

       if (seen && !current_mailbox_ro)
       {
       struct imapflags     flags;

              get_message_flags(current_maildir_info.msgs+(n-1),
                            0, &flags);
              if (!flags.seen)
              {
                     flags.seen=1;
                     reflag_filename(&current_maildir_info.msgs[n-1],&flags,
                            fileno(fp));
                     current_maildir_info.msgs[n-1].changedflags=1;
              }
       }

       if (current_maildir_info.msgs[n-1].changedflags)
              fetchflags(n-1);
       return (0);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int do_folder_delete ( char *  mailbox_name)

Definition at line 3638 of file imapd.c.

{
       maildir_aclt_list l;
       const char *acl_error;
       struct maildir_info mi;

       if (maildir_info_imap_find(&mi, mailbox_name, getenv("AUTHENTICATED"))
           < 0)
              return -1;

       if (mi.homedir == NULL || mi.maildir == NULL)
       {
              maildir_info_destroy(&mi);
              return -1;
       }

       if (acl_read_folder(&l, mi.homedir, mi.maildir) < 0)
              return -1;

       if (strcmp(mi.maildir, INBOX))
       {
              char *p=maildir_name2dir(mi.homedir, mi.maildir);

              if (p && is_reserved(p) == 0 && mddelete(p) == 0)
              {
                     if (folder_exists(mailbox_name))
                     {
                            acl_write_folder(&l, mi.homedir,
                                           mi.maildir, NULL,
                                           &acl_error);
                     }
                     maildir_aclt_list_destroy(&l);
                     maildir_quota_recalculate(mi.homedir);
                     free(p);
                     maildir_info_destroy(&mi);
                     return 0;
              }

              if (p)
                     free(p);
       }
       maildir_aclt_list_destroy(&l);
       return -1;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int do_imap_command ( const char *  tag)

Definition at line 4025 of file imapd.c.

{
struct imaptoken *curtoken=nexttoken();
int    uid=0;

       if (curtoken->tokentype != IT_ATOM)       return (-1);

       /* Commands that work in authenticated state */

       if (strcmp(curtoken->tokenbuf, "CAPABILITY") == 0)
       {
              if (nexttoken()->tokentype != IT_EOL)     return (-1);
              writes("* CAPABILITY ");
              imapcapability();
              writes("\r\n");
              writes(tag);
              writes(" OK CAPABILITY completed\r\n");
              return (0);
       }
       if (strcmp(curtoken->tokenbuf, "NOOP") == 0)
       {
              if (nexttoken()->tokentype != IT_EOL)     return (-1);
              if (current_mailbox)
                     doNoop(1);
              writes(tag);
              writes(" OK NOOP completed\r\n");
              return (0);
       }
       if (strcmp(curtoken->tokenbuf, "IDLE") == 0)
       {
              const char *p;

               if (nexttoken()->tokentype != IT_EOL)   return (-1);

              read_eol();

              if ((p=getenv("IMAP_ENHANCEDIDLE")) == NULL
                 || !atoi(p)
                 || imapenhancedidle())
                     imapidle();
              curtoken=nexttoken();
              if (strcmp(curtoken->tokenbuf, "DONE") == 0)
              {
                     if (current_mailbox)
                            doNoop(0);
                     writes(tag);
                     writes(" OK IDLE completed\r\n");
                     return (0);
               }
               return (-1);
       }
       if (strcmp(curtoken->tokenbuf, "LOGOUT") == 0)
       {
              if (nexttoken()->tokentype != IT_EOL)     return (-1);
              fetch_free_cache();
              writes("* BYE Courier-IMAP server shutting down\r\n");
              writes(tag);
              writes(" OK LOGOUT completed\r\n");
              writeflush();
              emptytrash();
              logoutmsg();
              bye();
       }

       if (strcmp(curtoken->tokenbuf, "LIST") == 0
              || strcmp(curtoken->tokenbuf, "LSUB") == 0)
       {
              char   *reference, *name;
              int    rc;
              char   cmdbuf[5];
              int    list_flags=0;

              strcpy(cmdbuf, curtoken->tokenbuf);

              curtoken=nexttoken_nouc();
              if (curtoken->tokentype == IT_LPAREN)
              {
                     while ((curtoken=nexttoken())->tokentype != IT_RPAREN)
                     {
                            if (curtoken->tokentype != IT_QUOTED_STRING &&
                                curtoken->tokentype != IT_ATOM &&
                                curtoken->tokentype != IT_NUMBER)
                                   return (-1);

                            if (strcmp(curtoken->tokenbuf, "ACL") == 0)
                                   list_flags |= LIST_ACL;
                            if (strcmp(curtoken->tokenbuf, "MYRIGHTS")==0)
                                   list_flags |= LIST_MYRIGHTS;
                            if (strcmp(curtoken->tokenbuf,
                                      "POSTADDRESS")==0)
                                   list_flags |= LIST_POSTADDRESS;
                     }

                     curtoken=nexttoken_nouc();
              }


              if (curtoken->tokentype == IT_NIL)
                     reference=my_strdup("");
              else
              {
                     if (curtoken->tokentype != IT_QUOTED_STRING &&
                            curtoken->tokentype != IT_ATOM &&
                            curtoken->tokentype != IT_NUMBER)
                            return (-1);
                     reference=my_strdup(curtoken->tokenbuf);
              }
              curtoken=nexttoken_nouc();

              if (curtoken->tokentype == IT_NIL)
                     name=my_strdup("");
              else
              {
                     if (curtoken->tokentype != IT_QUOTED_STRING &&
                            curtoken->tokentype != IT_ATOM &&
                            curtoken->tokentype != IT_NUMBER)
                            return (-1);
                     name=my_strdup(curtoken->tokenbuf);
              }
              if (nexttoken()->tokentype != IT_EOL)     return (-1);

              if (strcmp(cmdbuf, "LIST"))
                     list_flags |= LIST_SUBSCRIBED;

              rc=mailbox_scan(reference, name,
                            list_flags,
                            list_callback, cmdbuf);
 
              free(reference);
              free(name);
              if (rc == 0)
              {
                     writes(tag);
                     writes(" OK ");
                     writes(cmdbuf);
                     writes(" completed\r\n");
              }
              else
              {
                     writes(tag);
                     writes(" NO ");
                     writes(strerror(errno));
                     writes("\r\n");
                     rc=0;
              }
              writeflush();
              return (rc);
       }

       if (strcmp(curtoken->tokenbuf, "APPEND") == 0)
       {
              struct imaptoken *tok=nexttoken_nouc();
              struct maildir_info mi;

              if (tok->tokentype != IT_NUMBER &&
                     tok->tokentype != IT_ATOM &&
                     tok->tokentype != IT_QUOTED_STRING)
                     return (-1);

              if (maildir_info_imap_find(&mi, tok->tokenbuf,
                                      getenv("AUTHENTICATED")) < 0)
              {
                     writes(tag);
                     writes(" NO Invalid mailbox name.\r\n");
                     return (0);
              }

              if (mi.homedir && mi.maildir)
              {
                     char *p=maildir_name2dir(mi.homedir, mi.maildir);
                     int rc;

                     if (!p)
                     {
                            maildir_info_destroy(&mi);
                            writes(tag);
                            accessdenied("APPEND",
                                        tok->tokenbuf,
                                        ACL_INSERT);
                            return 0;
                     }
                     
                     rc=append(tag, tok->tokenbuf, p);
                     free(p);
                     maildir_info_destroy(&mi);
                     return (rc);
              }
              else if (mi.mailbox_type == MAILBOXTYPE_OLDSHARED)
              {
                     char *p=strchr(tok->tokenbuf, '.');

                     if (p && (p=maildir_shareddir(".", p+1)) != NULL)
                     {
                            int rc;
                            char   *q=malloc(strlen(p)+sizeof("/shared"));

                            if (!q)       write_error_exit(0);

                            strcat(strcpy(q, p), "/shared");
                            free(p);
                            rc=append(tag, tok->tokenbuf, q);
                            free(q);
                            maildir_info_destroy(&mi);
                            return rc;
                     }
              }

              writes(tag);
              accessdenied("APPEND", "folder", ACL_INSERT);
              return (0);
       }

       if (strcmp(curtoken->tokenbuf, "GETQUOTAROOT") == 0)
       {
              char   qroot[20];
              struct maildir_info minfo;

              curtoken=nexttoken_nouc();

              if (curtoken->tokentype != IT_NUMBER &&
                     curtoken->tokentype != IT_ATOM &&
                     curtoken->tokentype != IT_QUOTED_STRING)
                     return (-1);

              if (maildir_info_imap_find(&minfo, curtoken->tokenbuf,
                                      getenv("AUTHENTICATED")))
              {
                     writes(tag);
                     writes(" NO Invalid mailbox name.\r\n");
                     return (0);
              }

              switch (minfo.mailbox_type) {
              case MAILBOXTYPE_INBOX:
                     strcpy(qroot, "ROOT");
                     break;
              case MAILBOXTYPE_OLDSHARED:
                     strcpy(qroot, "SHARED");
                     break;
              case MAILBOXTYPE_NEWSHARED:
                     strcpy(qroot, "PUBLIC");
                     break;
              }
              maildir_info_destroy(&minfo);

              writes("*");
              writes(" QUOTAROOT \"");
              writeqs(curtoken->tokenbuf);
              writes("\" \"");
              writes(qroot);
              writes("\"\r\n");
              quotainfo_out(qroot);
              writes(tag);
              writes(" OK GETQUOTAROOT Ok.\r\n");
              return(0);
       }


       if (strcmp(curtoken->tokenbuf, "SETQUOTA") == 0)
       {
              writes(tag);
              writes(" NO SETQUOTA No permission.\r\n");
              return(0);
       }

       if (strcmp(curtoken->tokenbuf, "GETQUOTA") == 0)
       {
              curtoken=nexttoken_nouc();

              if (curtoken->tokentype != IT_NUMBER &&
                     curtoken->tokentype != IT_ATOM &&
                     curtoken->tokentype != IT_QUOTED_STRING)
                     return (-1);

              quotainfo_out(curtoken->tokenbuf);
              writes(tag);
              writes(" OK GETQUOTA Ok.\r\n");
              return(0);
       }

       if (strcmp(curtoken->tokenbuf, "STATUS") == 0)
       {
              char   *mailbox;
              int    get_messages=0,
                     get_recent=0,
                     get_uidnext=0,
                     get_uidvalidity=0,
                     get_unseen=0;

              struct imapscaninfo other_info, *loaded_infoptr,
                     *infoptr;
              const char *p;
              char   *orig_mailbox;
              int    oneonly;

              curtoken=nexttoken_nouc();
              mailbox=parse_mailbox_error(tag, curtoken, 0, 0);
              if ( mailbox == 0)
                     return (0);

              orig_mailbox=my_strdup(curtoken->tokenbuf);
              curtoken=nexttoken();

              oneonly=0;
              if (curtoken->tokentype != IT_LPAREN)
              {
                     if (curtoken->tokentype != IT_ATOM)
                     {
                            free(mailbox);
                            free(orig_mailbox);
                            return (-1);
                     }
                     oneonly=1;
              }
              else   nexttoken();

              while ((curtoken=currenttoken())->tokentype == IT_ATOM)
              {
                     if (strcmp(curtoken->tokenbuf, "MESSAGES") == 0)
                            get_messages=1;
                     if (strcmp(curtoken->tokenbuf, "RECENT") == 0)
                            get_recent=1;
                     if (strcmp(curtoken->tokenbuf, "UIDNEXT") == 0)
                            get_uidnext=1;
                     if (strcmp(curtoken->tokenbuf, "UIDVALIDITY") == 0)
                            get_uidvalidity=1;
                     if (strcmp(curtoken->tokenbuf, "UNSEEN") == 0)
                            get_unseen=1;
                     nexttoken();
                     if (oneonly)  break;
              }

              if ((!oneonly && curtoken->tokentype != IT_RPAREN) ||
                     nexttoken()->tokentype != IT_EOL)
              {
                     free(mailbox);
                     free(orig_mailbox);
                     return (-1);
              }

              {
                     CHECK_RIGHTSM(orig_mailbox, status_rights, ACL_READ);

                     if (!status_rights[0])
                     {
                            writes(tag);
                            accessdenied("STATUS", orig_mailbox,
                                        ACL_READ);
                            free(mailbox);
                            free(orig_mailbox);
                            return 0;
                     }
              }


              if (current_mailbox && strcmp(current_mailbox, mailbox) == 0)
              {
                     loaded_infoptr=0;
                     infoptr= &current_maildir_info;
              }
              else
              {
                     loaded_infoptr= &other_info;
                     infoptr=loaded_infoptr;

                     imapscan_init(loaded_infoptr);

                     if (imapscan_maildir(infoptr, mailbox, 1, 1, NULL))
                     {
                            writes(tag);
                            writes(" NO [ALERT] STATUS failed\r\n");
                            free(mailbox);
                            free(orig_mailbox);
                            return (0);
                     }
              }

              writes("*");
              writes(" STATUS \"");
              writeqs(orig_mailbox);
              writes("\" (");
              p="";
              if (get_messages)
              {
                     writes("MESSAGES ");
                     writen(infoptr->nmessages+infoptr->left_unseen);
                     p=" ";
              }
              if (get_recent)
              {
              unsigned long n=infoptr->left_unseen;
              unsigned long i;

                     for (i=0; i<infoptr->nmessages; i++)
                            if (infoptr->msgs[i].recentflag)
                                   ++n;
                     writes(p);
                     writes("RECENT ");
                     writen(n);
                     p=" ";
              }

              if (get_uidnext)
              {
                     writes(p);
                     writes("UIDNEXT ");
                     writen(infoptr->nextuid);
                     p=" ";
              }

              if (get_uidvalidity)
              {
                     writes(p);
                     writes("UIDVALIDITY ");
                     writen(infoptr->uidv);
                     p=" ";
              }

              if (get_unseen)
              {
              unsigned long n=infoptr->left_unseen, i;

                     for (i=0; i<infoptr->nmessages; i++)
                     {
                     const char *p=infoptr->msgs[i].filename;

                            p=strrchr(p, MDIRSEP[0]);
                            if (p && strncmp(p, MDIRSEP "2,", 3) == 0 &&
                                   strchr(p, 'S'))      continue;
                            ++n;
                     }
                     writes(p);
                     writes("UNSEEN ");
                     writen(n);
              }
              writes(")\r\n");
              if (loaded_infoptr)
                     imapscan_free(loaded_infoptr);
              free(mailbox);
              free(orig_mailbox);
              writes(tag);
              writes(" OK STATUS Completed.\r\n");
              return (0);
       }

       if (strcmp(curtoken->tokenbuf, "CREATE") == 0)
       {
              char   *mailbox, *orig_mailbox, *p;
              int    isdummy;
              struct maildir_info mi;
              struct imapscaninfo minfo;

              curtoken=nexttoken_nouc();

              if (curtoken->tokentype != IT_NUMBER &&
                     curtoken->tokentype != IT_ATOM &&
                     curtoken->tokentype != IT_QUOTED_STRING)
                     return (-1);

              isdummy=0;

              p=strrchr(curtoken->tokenbuf, HIERCH);
              if (p && p[1] == '\0')
              {
                     *p=0;
                     isdummy=1;    /* Ignore hierarchy creation */
              }

              if (maildir_info_imap_find(&mi, curtoken->tokenbuf,
                                      getenv("AUTHENTICATED")))
              {
                     writes(tag);
                     writes(" NO Invalid mailbox name.\r\n");
                     return (0);
              }

              if (!mi.homedir || !mi.maildir)
              {
                     maildir_info_destroy(&mi);
                     writes(tag);
                     accessdenied("CREATE",
                                 curtoken->tokenbuf,
                                 ACL_CREATE);
                     maildir_info_destroy(&mi);
                     return (0);
              }

              mailbox=maildir_name2dir(mi.homedir, mi.maildir);
              if (!mailbox)
              {
                     writes(tag);
                     writes(" NO Invalid mailbox name\r\n");
                     maildir_info_destroy(&mi);
                     return (0);
              }

              if (strcmp(mailbox, ".") == 0)
              {
                     writes(tag);
                     writes(" NO INBOX already exists!\r\n");
                     free(mailbox);
                     maildir_info_destroy(&mi);
                     return (0);
              }

              if (check_parent_create(tag, "CREATE", curtoken->tokenbuf))
              {
                     free(mailbox);
                     maildir_info_destroy(&mi);
                     return (0);
              }

              if (isdummy)  *p=HIERCH;
              orig_mailbox=my_strdup(curtoken->tokenbuf);

              if (nexttoken()->tokentype != IT_EOL)
              {
                     free(mailbox);
                     free(orig_mailbox);
                     maildir_info_destroy(&mi);
                     return (-1);
              }

              if (!isdummy)
              {
                     int did_exist;
                     maildir_aclt_list l;

                     if ((did_exist=folder_exists(orig_mailbox)) != 0)
                     {
                            if (acl_read_folder(&l,
                                              mi.homedir,
                                              mi.maildir) < 0)
                            {
                                   free(mailbox);
                                   free(orig_mailbox);
                                   writes(tag);
                                   writes(" NO Cannot create this folder"
                                          ".\r\n");
                                   maildir_info_destroy(&mi);
                                   return (0);
                            }
                            maildir_acl_delete(mi.homedir, mi.maildir);
                            /* Clear out fluff */
                     }

                     if (mdcreate(mailbox))
                     {
                            if (did_exist)
                                   maildir_aclt_list_destroy(&l);
                            free(mailbox);
                            free(orig_mailbox);
                            writes(tag);
                            writes(" NO Cannot create this folder.\r\n");
                            maildir_info_destroy(&mi);
                            return (0);
                     }
                     if (did_exist)
                     {
                            const char *acl_error;

                            acl_write_folder(&l, mi.homedir,
                                           mi.maildir, NULL,
                                           &acl_error);
                            maildir_aclt_list_destroy(&l);
                     }
              }
              writes(tag);
              writes(" OK \"");
              writeqs(orig_mailbox);
              writes("\" created.\r\n");

              /*
              ** This is a dummy call to acl_read_folder that initialized
              ** the default ACLs for this folder to its parent.
              */

              {
                     CHECK_RIGHTSM(curtoken->tokenbuf, create_rights,
                                  ACL_CREATE);
              }

              imapscan_init(&minfo);
              imapscan_maildir(&minfo, mailbox, 0,0, NULL);
              imapscan_free(&minfo);

              free(mailbox);
              free(orig_mailbox);
              maildir_info_destroy(&mi);
              return (0);
       }

       if (strcmp(curtoken->tokenbuf, "DELETE") == 0)
       {
       char   *mailbox;
       char   *p;
       char   *mailbox_name;

              curtoken=nexttoken_nouc();

              if (curtoken->tokentype != IT_NUMBER &&
                     curtoken->tokentype != IT_ATOM &&
                     curtoken->tokentype != IT_QUOTED_STRING)
                     return (-1);

              p=strrchr(curtoken->tokenbuf, HIERCH);
              if (p && p[1] == '\0')             /* Ignore hierarchy DELETE */
              {
                     if (nexttoken()->tokentype != IT_EOL)
                            return (-1);
                     writes(tag);
                     writes(" OK Folder directory delete punted.\r\n");
                     return (0);
              }

              mailbox_name=my_strdup(curtoken->tokenbuf);
              mailbox=parse_mailbox_error(tag, curtoken, 1, 0);
              if ( mailbox == 0)
              {
                     free(mailbox_name);
                     return (0);
              }

              if (nexttoken()->tokentype != IT_EOL)
              {
                     free(mailbox_name);
                     free(mailbox);
                     return (-1);
              }

              if (current_mailbox && strcmp(mailbox, current_mailbox) == 0)
              {
                     free(mailbox_name);
                     free(mailbox);
                     writes(tag);
                     writes(" NO Cannot delete currently-open folder.\r\n");
                     return (0);
              }

              if (strncmp(curtoken->tokenbuf, SHARED HIERCHS,
                     sizeof(SHARED HIERCHS)-1) == 0)
              {
                     maildir_shared_unsubscribe(0, curtoken->tokenbuf+
                                             sizeof(SHARED HIERCHS)-1);
                     free(mailbox_name);
                     free(mailbox);
                     writes(tag);
                     writes(" OK UNSUBSCRIBEd a shared folder.\r\n");
                     return (0);
              }

              {
                     CHECK_RIGHTSM(curtoken->tokenbuf,
                                  delete_rights,
                                  ACL_DELETEFOLDER);
                     if (delete_rights[0] == 0)
                     {
                            free(mailbox_name);
                            free(mailbox);
                            writes(tag);
                            accessdenied("DELETE",
                                        curtoken->tokenbuf,
                                        ACL_DELETEFOLDER);
                            return 0;
                     }
              }

              if (!broken_uidvs())
                     sleep(2); /* Make sure we never recycle them*/

              fetch_free_cache();


              if (do_folder_delete(mailbox_name))
              {
                     writes(tag);
                     writes(" NO Cannot delete this folder.\r\n");
              }
              else
              {
                     writes(tag);
                     writes(" OK Folder deleted.\r\n");
              }

              free(mailbox_name);
              free(mailbox);
              return (0);
       }

       if (strcmp(curtoken->tokenbuf, "RENAME") == 0)
       {
              char *p;
              struct maildir_info mi1, mi2;
              const char *errmsg;

              curtoken=nexttoken_nouc();

              if (curtoken->tokentype != IT_NUMBER &&
                  curtoken->tokentype != IT_ATOM &&
                  curtoken->tokentype != IT_QUOTED_STRING)
              {
                     writes(tag);
                     writes(" NO Invalid mailbox\r\n");
                     return (0);
              }

              if ((p=strrchr(curtoken->tokenbuf, HIERCH))  && p[1] == 0)
                     *p=0;

              if (maildir_info_imap_find(&mi1, curtoken->tokenbuf,
                                      getenv("AUTHENTICATED")) < 0)
              {
                     writes(tag);
                     writes(" NO Invalid mailbox name.\r\n");
                     return (0);
              }

              if (mi1.homedir == NULL || mi1.maildir == NULL)
              {
                     maildir_info_destroy(&mi1);
                     writes(tag);
                     writes(" NO Invalid mailbox\r\n");
                     return (0);
              }

              {
                     CHECK_RIGHTSM(curtoken->tokenbuf,
                                  rename_rights, ACL_DELETEFOLDER);

                     if (rename_rights[0] == 0)
                     {
                            maildir_info_destroy(&mi1);
                            writes(tag);
                            accessdenied("RENAME", curtoken->tokenbuf,
                                        ACL_DELETEFOLDER);
                            return (0);
                     }
              }


              curtoken=nexttoken_nouc();
              if (curtoken->tokentype != IT_NUMBER &&
                     curtoken->tokentype != IT_ATOM &&
                     curtoken->tokentype != IT_QUOTED_STRING)
              {
                     maildir_info_destroy(&mi1);
                     return (-1);
              }

              if ((p=strrchr(curtoken->tokenbuf, HIERCH)) && p[1] == 0)
              {
                     *p=0;
              }


              if (maildir_info_imap_find(&mi2, curtoken->tokenbuf,
                                      getenv("AUTHENTICATED")) < 0)
              {
                     maildir_info_destroy(&mi1);
                     writes(tag);
                     writes(" NO Invalid mailbox name.\r\n");
                     return (0);
              }

              if (check_parent_create(tag, "RENAME", curtoken->tokenbuf))
              {
                     maildir_info_destroy(&mi1);
                     maildir_info_destroy(&mi2);
                     return 0;
              }

              if (nexttoken()->tokentype != IT_EOL)
              {
                     maildir_info_destroy(&mi1);
                     maildir_info_destroy(&mi2);
                     return (-1);
              }

              if (!broken_uidvs())
                     sleep(2);
              /* Make sure IMAP uidvs are not recycled */

              if (folder_rename(&mi1, &mi2, &errmsg))
              {
                     writes(tag);
                     writes(" NO ");
                     writes(*errmsg == '@' ? errmsg+1:errmsg);
                     if (*errmsg == '@')
                            writes(strerror(errno));
                     writes("\r\n");
              }
              else
              {
                     writes(tag);
                     writes(" OK Folder renamed.\r\n");
              }

              maildir_info_destroy(&mi1);
              maildir_info_destroy(&mi2);
              return (0);
       }

       if (strcmp(curtoken->tokenbuf, "SELECT") == 0 ||
              strcmp(curtoken->tokenbuf, "EXAMINE") == 0)
       {
       char   *mailbox;
       int    ro=curtoken->tokenbuf[0] == 'E';
       const char *p;


              curtoken=nexttoken_nouc();

              if (current_mailbox)
              {
                     free(current_mailbox);
                     imapscan_free(&current_maildir_info);
                     imapscan_init(&current_maildir_info);
                     current_mailbox=0;
              }

              if (current_mailbox_acl)
                     free(current_mailbox_acl);
              current_mailbox_acl=0;

              mailbox=parse_mailbox_error(tag, curtoken, 0, 1);
              if ( mailbox == 0)
                     return (0);

              current_mailbox_acl=get_myrightson(curtoken->tokenbuf);
              if (current_mailbox_acl == NULL)
              {
                     free(mailbox);
                     writes(tag);
                     writes(" NO Unable to read ACLs for ");
                     writes(curtoken->tokenbuf);
                     writes(": ");
                     writes(strerror(errno));
                     writes("\r\n");
                     return 0;
              }

              if (strchr(current_mailbox_acl, ACL_READ[0]) == NULL)
              {
                     free(mailbox);
                     free(current_mailbox_acl);
                     current_mailbox_acl=NULL;
                     writes(tag);
                     accessdenied("SELECT/EXAMINE", curtoken->tokenbuf,
                                 ACL_READ);
                     return 0;
              }

              if (nexttoken()->tokentype != IT_EOL)
              {
                     free(mailbox);
                     return (-1);
              }

              if (imapscan_maildir(&current_maildir_info, mailbox, 0, ro,
                                 NULL))
              {
                     free(mailbox);
                     writes(tag);
                     writes(" NO Unable to open this mailbox.\r\n");
                     return (0);
              }
              current_mailbox=mailbox;

              /* check if this is a shared read-only folder */

              if (is_sharedsubdir(mailbox) &&
                     maildir_sharedisro(mailbox))
                     ro=1;

              current_mailbox_ro=ro;

              mailboxflags(ro);
              mailboxmetrics();
              writes("* OK [UIDVALIDITY ");
              writen(current_maildir_info.uidv);
              writes("] Ok\r\n");
              myrights();
              writes(tag);

              for (p=current_mailbox_acl; *p; p++)
                     if (strchr(ACL_INSERT ACL_EXPUNGE
                               ACL_SEEN ACL_WRITE ACL_DELETEMSGS,
                               *p))
                            break;

              if (*p == 0)
                     ro=1;

              writes(ro ? " OK [READ-ONLY] Ok\r\n":" OK [READ-WRITE] Ok\r\n");
              return (0);
       }

       if (strcmp(curtoken->tokenbuf, "SUBSCRIBE") == 0)
       {
       char   *mailbox;
       char   *p;
       struct maildir_info mi;

              curtoken=nexttoken_nouc();
              if (curtoken->tokentype != IT_NUMBER &&
                     curtoken->tokentype != IT_ATOM &&
                     curtoken->tokentype != IT_QUOTED_STRING)
                     return (-1);

              p=strrchr(curtoken->tokenbuf, HIERCH);
              if (p && p[1] == '\0')             /* Ignore hierarchy DELETE */
              {
                     if (nexttoken()->tokentype != IT_EOL)
                            return (-1);
                     writes(tag);
                     writes(" OK Folder directory subscribe punted.\r\n");
                     return (0);
              }

              mailbox=my_strdup(curtoken->tokenbuf);
              if (nexttoken()->tokentype != IT_EOL)
                     return (-1);

              if (maildir_info_imap_find(&mi, mailbox,
                                      getenv("AUTHENTICATED")) < 0)
              {
                     free(mailbox);
                     writes(tag);
                     writes(" NO Invalid mailbox name.\r\n");
                     return (0);
              }

              if (mi.mailbox_type != MAILBOXTYPE_OLDSHARED)
              {
                     maildir_info_destroy(&mi);
                     subscribe(mailbox);
                     free(mailbox);
                     writes(tag);
                     writes(" OK Folder subscribed.\r\n");
                     return (0);
              }
              maildir_info_destroy(&mi);

              p=strchr(mailbox, '.');

              p=p ? maildir_shareddir(".", p+1):NULL;

              if (p == NULL || access(p, 0) == 0)
              {
                     if (p)
                            free(p);
                     free(mailbox);
                     writes(tag);
                     writes(" OK Already subscribed.\r\n");
                     return (0);
              }

              if (!p || maildir_shared_subscribe(0, strchr(mailbox, '.')+1))
              {
                     if (p)
                            free(p);
                     free(mailbox);
                     writes(tag);
                     writes(" NO Cannot subscribe to this folder.\r\n");
                     return (0);
              }
              if (p)
                     free(p);
              free(mailbox);
              writes(tag);
              writes(" OK SUBSCRIBE completed.\r\n");
              return (0);
       }

       if (strcmp(curtoken->tokenbuf, "UNSUBSCRIBE") == 0)
       {
       char   *mailbox;
       char   *p;
       struct maildir_info mi;

              curtoken=nexttoken_nouc();
              if (curtoken->tokentype != IT_NUMBER &&
                     curtoken->tokentype != IT_ATOM &&
                     curtoken->tokentype != IT_QUOTED_STRING)
                     return (-1);

              p=strrchr(curtoken->tokenbuf, HIERCH);
              if (p && p[1] == '\0')             /* Ignore hierarchy DELETE */
              {
                     if (nexttoken()->tokentype != IT_EOL)
                            return (-1);
                     writes(tag);
                     writes(" OK Folder directory unsubscribe punted.\r\n");
                     return (0);
              }

              mailbox=my_strdup(curtoken->tokenbuf);
              if (nexttoken()->tokentype != IT_EOL)
                     return (-1);

              if (maildir_info_imap_find(&mi, mailbox,
                                      getenv("AUTHENTICATED")) < 0)
              {
                     free(mailbox);
                     writes(tag);
                     writes(" NO Invalid mailbox name.\r\n");
                     return (0);
              }

              if (mi.mailbox_type != MAILBOXTYPE_OLDSHARED)
              {
                     maildir_info_destroy(&mi);
                     unsubscribe(mailbox);
                     free(mailbox);
                     writes(tag);
                     writes(" OK Folder unsubscribed.\r\n");
                     return (0);
              }
              maildir_info_destroy(&mi);

              p=strchr(mailbox, '.');

              p=p ? maildir_shareddir(".", p+1):NULL;


              if (p == NULL || access(p, 0))
              {
                     if (p)
                            free(p);
                     free(mailbox);
                     writes(tag);
                     writes(" OK Already unsubscribed.\r\n");
                     return (0);
              }

              fetch_free_cache();

              if (!p || maildir_shared_unsubscribe(0,
                                               strchr(mailbox, '.')+1))
              {
                     if (p)
                            free(p);
                     free(mailbox);
                     writes(tag);
                     writes(" NO Cannot subscribe to this folder.\r\n");
                     return (0);
              }
              if (p)
                     free(p);
              free(mailbox);
              writes(tag);
              writes(" OK UNSUBSCRIBE completed.\r\n");
              return (0);
       }

       if (strcmp(curtoken->tokenbuf, "NAMESPACE") == 0)
       {
              if (nexttoken()->tokentype != IT_EOL)
                     return (-1);
              writes("* NAMESPACE ((\"INBOX.\" \".\")) NIL "
                     "((\"#shared.\" \".\")(\""
                     SHARED ".\" \".\"))\r\n");
              writes(tag);
              writes(" OK NAMESPACE completed.\r\n");
              return (0);
       }

       if (strcmp(curtoken->tokenbuf, "ACL") == 0)
       {
              if (aclcmd(tag))
              {
                     writes(tag);
                     writes(" ACL FAILED: ");
                     writes(strerror(errno));
                     writes("\r\n");
              }
              return 0;
       }

       /* RFC 2086 */

       if (strcmp(curtoken->tokenbuf, "SETACL") == 0 ||
           strcmp(curtoken->tokenbuf, "DELETEACL") == 0)
       {
              char *mailbox;
              char *identifier;
              struct maildir_info mi;
              maildir_aclt_list aclt_list;
              const char *acl_error;
              int doset=curtoken->tokenbuf[0] == 'S';
              const char *origcmd=doset ? "SETACL":"DELETEACL";

              curtoken=nexttoken_nouc();

              mailbox=parse_mailbox_error(tag, curtoken, 0, 0);
              if (!mailbox)
                     return 0;
              free(mailbox);

              mailbox=my_strdup(curtoken->tokenbuf);

              if (maildir_info_imap_find(&mi, mailbox,
                                      getenv("AUTHENTICATED")) < 0)
              {
                     writes(tag);
                     writes(" NO Invalid mailbox.\r\n");
                     free(mailbox);
                     return 0;
              }

              if (mi.homedir == NULL || mi.maildir == NULL)
              {
                     maildir_info_destroy(&mi);
                     writes(tag);
                     writes(" NO Cannot set ACLs for this mailbox\r\n");
                     free(mailbox);
                     return 0;
              }

              switch ((curtoken=nexttoken_nouc())->tokentype) {
              case IT_QUOTED_STRING:
              case IT_ATOM:
              case IT_NUMBER:
                     break;
              default:
                     maildir_info_destroy(&mi);
                     free(mailbox);
                     return -1;
              }

              identifier=acl2_identifier(tag, curtoken->tokenbuf);

              if (identifier == NULL)
              {
                     maildir_info_destroy(&mi);
                     free(mailbox);
                     return 0;
              }

              if (doset)
              {
                     switch ((curtoken=nexttoken_nouc())->tokentype) {
                     case IT_QUOTED_STRING:
                     case IT_ATOM:
                     case IT_NUMBER:
                            break;
                     default:
                            free(identifier);
                            maildir_info_destroy(&mi);
                            free(mailbox);
                            return -1;
                     }
              }

              {
                     CHECK_RIGHTSM(mailbox,
                                  acl_rights,
                                  ACL_ADMINISTER);
                     if (acl_rights[0] == 0)
                     {
                            writes(tag);
                            accessdenied(origcmd, mailbox,
                                        ACL_ADMINISTER);
                            free(identifier);
                            maildir_info_destroy(&mi);
                            free(mailbox);
                            return 0;
                     }
              }

              if (acl_read_folder(&aclt_list, mi.homedir, mi.maildir))
              {
                     writes(tag);
                     writes(" NO Cannot read existing ACLs.\r\n");
                     free(identifier);
                     maildir_info_destroy(&mi);
                     free(mailbox);
                     return 0;
              }

              if (do_acl_mod(&aclt_list, &mi, identifier,
                            doset ? curtoken->tokenbuf:"",
                            &acl_error) < 0)
              {
                     writes(tag);
                     writes(acl_error ?
                            " NO Cannot modify ACLs as requested.\r\n" :
                            " NO Cannot modify ACLs on this mailbox.\r\n");
              }
              else
              {
                     char *p=get_myrightson(mailbox);

                     if (p)
                            free(p);
                     /* Side effect - change current folder's ACL */

                     writes(tag);
                     writes(" OK ACLs updated.\r\n");
              }

              maildir_aclt_list_destroy(&aclt_list);
              maildir_info_destroy(&mi);
              free(identifier);
              free(mailbox);
              return 0;
       }

       if (strcmp(curtoken->tokenbuf, "GETACL") == 0)
       {
              maildir_aclt_list l;
              char *mailbox_owner;
              char *mb;

              curtoken=nexttoken_nouc();

              mb=parse_mailbox_error(tag, curtoken, 0, 0);
              if (!mb)
                     return 0;
              free(mb);

              {
                     CHECK_RIGHTSM(curtoken->tokenbuf,
                                  acl_rights,
                                  ACL_ADMINISTER);
                     if (acl_rights[0] == 0)
                     {
                            writes(tag);
                            accessdenied("GETACL", curtoken->tokenbuf,
                                        ACL_ADMINISTER);
                            return 0;
                     }
              }

              if (get_acllist(&l, curtoken->tokenbuf,
                            &mailbox_owner) < 0)
              {
                     writes(tag);
                     writes(" NO Cannot retrieve ACLs for mailbox.\r\n");
                     return 0;
              }
              free(mailbox_owner);

              writes("* ACL \"");
              writeqs(curtoken->tokenbuf);
              writes("\"");
              maildir_aclt_list_enum(&l, getacl_cb, NULL);
              writes("\r\n");
              writes(tag);
              writes(" OK GETACL completed.\r\n");
              maildir_aclt_list_destroy(&l);
              return 0;
       }

       if (strcmp(curtoken->tokenbuf, "LISTRIGHTS") == 0)
       {
              maildir_aclt_list l;
              char *mailbox_owner;
              char *mb;

              curtoken=nexttoken_nouc();

              mb=parse_mailbox_error(tag, curtoken, 0, 0);
              if (!mb)
                     return 0;
              free(mb);

              {
                     char *myrights=get_myrightson(curtoken->tokenbuf);

                     if (!strchr(myrights, ACL_LOOKUP[0]) &&
                         !strchr(myrights, ACL_READ[0]) &&
                         !strchr(myrights, ACL_INSERT[0]) &&
                         !strchr(myrights, ACL_CREATE[0]) &&
                         !strchr(myrights, ACL_DELETEFOLDER[0]) &&
                         !strchr(myrights, ACL_EXPUNGE[0]) &&
                         !strchr(myrights, ACL_ADMINISTER[0]))
                     {
                            free(myrights);
                            writes(tag);
                            accessdenied("GETACL", curtoken->tokenbuf,
                                        ACL_ADMINISTER);
                            return 0;
                     }
                     free(myrights);
              }

              if (get_acllist(&l, curtoken->tokenbuf,
                            &mailbox_owner) < 0)
              {
                     writes(tag);
                     writes(" NO Cannot retrieve ACLs for mailbox.\r\n");
                     return 0;
              }

              mb=my_strdup(curtoken->tokenbuf);

              switch ((curtoken=nexttoken_nouc())->tokentype) {
              case IT_QUOTED_STRING:
              case IT_ATOM:
              case IT_NUMBER:
                     break;
              default:
                     free(mb);
                     free(mailbox_owner);
                     maildir_aclt_list_destroy(&l);
                     return -1;
              }

              writes("* LISTRIGHTS \"");
              writeqs(mb);
              writes("\" \"");
              writeqs(curtoken->tokenbuf);
              writes("\"");
              free(mb);


              if (curtoken->tokenbuf[0] == '-' &&
                  (MAILDIR_ACL_ANYONE(curtoken->tokenbuf+1) ||
                   (strncmp(mailbox_owner, "user=", 5) == 0 &&
                    strcmp(curtoken->tokenbuf+1, mailbox_owner+5) == 0)))
              {
                     writes(" \"\" "
                            ACL_CREATE " "
                            ACL_DELETE_SPECIAL " "
                            ACL_INSERT " "
                            ACL_POST " "
                            ACL_READ " "
                            ACL_SEEN " "
                            ACL_WRITE "\r\n");
              }
              else if (strncmp(mailbox_owner, "user=", 5) == 0 &&
                      strcmp(curtoken->tokenbuf, mailbox_owner+5) == 0)
              {
                     writes(" \""
                            ACL_ADMINISTER
                            ACL_LOOKUP "\" "
                            ACL_CREATE " "
                            ACL_DELETE_SPECIAL " "
                            ACL_INSERT " "
                            ACL_POST " "
                            ACL_READ " "
                            ACL_SEEN " "
                            ACL_WRITE "\r\n");
              }
              else
              {
                     writes(" \"\" "
                            ACL_ADMINISTER " "
                            ACL_CREATE " "
                            ACL_DELETE_SPECIAL " "
                            ACL_INSERT " "
                            ACL_LOOKUP " "
                            ACL_POST " "
                            ACL_READ " "
                            ACL_SEEN " "
                            ACL_WRITE "\r\n");
              }
              writes(tag);
              writes(" OK LISTRIGHTS completed.\r\n");
              free(mailbox_owner);
              maildir_aclt_list_destroy(&l);
              return 0;
       }

       if (strcmp(curtoken->tokenbuf, "MYRIGHTS") == 0)
       {
              char *mb;

              curtoken=nexttoken_nouc();

              mb=parse_mailbox_error(tag, curtoken, 0, 0);
              if (!mb)
                     return 0;
              free(mb);

              {
                     char *myrights=get_myrightson(curtoken->tokenbuf);

                     if (!strchr(myrights, ACL_LOOKUP[0]) &&
                         !strchr(myrights, ACL_READ[0]) &&
                         !strchr(myrights, ACL_INSERT[0]) &&
                         !strchr(myrights, ACL_CREATE[0]) &&
                         !strchr(myrights, ACL_DELETEFOLDER[0]) &&
                         !strchr(myrights, ACL_EXPUNGE[0]) &&
                         !strchr(myrights, ACL_ADMINISTER[0]))
                     {
                            free(myrights);
                            writes(tag);
                            accessdenied("GETACL", curtoken->tokenbuf,
                                        ACL_ADMINISTER);
                            return 0;
                     }
                     free(myrights);
              }

              mb=get_myrightson(curtoken->tokenbuf);

              if (!mb)
              {
                     writes(tag);
                     writes(" NO Cannot retrieve ACLs for mailbox.\r\n");
                     return 0;
              }

              writes("* MYRIGHTS \"");
              writeqs(curtoken->tokenbuf);
              writes("\" \"");

              writeacl1(mb);
              free(mb);
              writes("\"\r\n");
              writes(tag);
              writes(" OK MYRIGHTS completed.\r\n");
              return 0;
       }

       /* mailbox commands */

       if (current_mailbox == 0)   return (-1);

       if (strcmp(curtoken->tokenbuf, "UID") == 0)
       {
              uid=1;
              if ((curtoken=nexttoken())->tokentype != IT_ATOM)
                     return (-1);
              if (strcmp(curtoken->tokenbuf, "COPY") &&
                  strcmp(curtoken->tokenbuf, "FETCH") &&
                  strcmp(curtoken->tokenbuf, "SEARCH") &&
                  strcmp(curtoken->tokenbuf, "THREAD") &&
                  strcmp(curtoken->tokenbuf, "SORT") &&
                  strcmp(curtoken->tokenbuf, "STORE") &&
                  strcmp(curtoken->tokenbuf, "EXPUNGE"))
                     return (-1);
       }

       if (strcmp(curtoken->tokenbuf, "CLOSE") == 0)
       {
              if (nexttoken()->tokentype != IT_EOL)
                     return (-1);

              if (!current_mailbox_ro
                  && strchr(current_mailbox_acl, ACL_EXPUNGE[0]))
                     expunge();
              free(current_mailbox);
              imapscan_free(&current_maildir_info);
              imapscan_init(&current_maildir_info);
              current_mailbox=0;
              writes(tag);
              writes(" OK mailbox closed.\r\n");
              return (0);
       }

       if (strcmp(curtoken->tokenbuf, "FETCH") == 0)
       {
       struct fetchinfo *fi;
       char   *msgset;

              curtoken=nexttoken();
              if (!ismsgset(curtoken))    return (-1);
              msgset=my_strdup(curtoken->tokenbuf);

              if ((curtoken=nexttoken())->tokentype != IT_LPAREN)
              {
                     if (curtoken->tokentype != IT_ATOM)
                     {
                            free(msgset);
                            return (-1);
                     }
                     fi=fetchinfo_alloc(1);
              }
              else
              {
                     (void)nexttoken();
                     fi=fetchinfo_alloc(0);
                     if (fi && currenttoken()->tokentype != IT_RPAREN)
                     {
                            fetchinfo_free(fi);
                            fi=0;
                     }
                     nexttoken();
              }

              if (fi == 0 || currenttoken()->tokentype != IT_EOL)
              {
                     free(msgset);
                     if (fi)       fetchinfo_free(fi);
                     return (-1);
              }

              do_msgset(msgset, &do_fetch, fi, uid);
              fetchinfo_free(fi);
              free(msgset);
              writes(tag);
              writes(" OK FETCH completed.\r\n");
              return (0);
       }

       if (strcmp(curtoken->tokenbuf, "STORE") == 0)
       {
       char   *msgset;
       struct storeinfo storeinfo_s;

              curtoken=nexttoken();
              if (!ismsgset(curtoken))    return (-1);
              msgset=my_strdup(curtoken->tokenbuf);

              (void)nexttoken();
              current_maildir_info.keywordList->keywordAddedRemoved=0;

              if (storeinfo_init(&storeinfo_s) ||
                     currenttoken()->tokentype != IT_EOL)
              {
                     if (storeinfo_s.keywords)
                            libmail_kwmDestroy(storeinfo_s.keywords);
                     free(msgset);
                     return (-1);
              }

              /* Do not change \Deleted if this is a readonly mailbox */

              if (current_mailbox_ro && storeinfo_s.flags.deleted)
              {
                     if (storeinfo_s.keywords)
                            libmail_kwmDestroy(storeinfo_s.keywords);
                     free(msgset);
                     writes(tag);
                     writes(" NO Current box is selected READ-ONLY.\r\n");
                     return (0);
              }

              fetch_free_cache();

              if (current_maildir_info.keywordList->keywordAddedRemoved)
                     mailboxflags(current_mailbox_ro);

              current_maildir_info.keywordList->keywordAddedRemoved=0;

              if (do_msgset(msgset, &do_store, &storeinfo_s, uid))
              {
                     if (storeinfo_s.keywords)
                            libmail_kwmDestroy(storeinfo_s.keywords);
                     free(msgset);
                     if (current_maildir_info.keywordList
                         ->keywordAddedRemoved)
                            mailboxflags(current_mailbox_ro);

                     writes(tag);
                     writes(" NO [ALERT] You exceeded your mail quota.\r\n");
                     return (0);
              }
              if (storeinfo_s.keywords)
              {
                     struct imap_addRemoveKeywordInfo imapInfo;

                     switch (storeinfo_s.plusminus) {
                     case '+':
                     case '-':

                            imapInfo.msgset=msgset;
                            imapInfo.uid=uid;

                            if (!fastkeywords() &&
                                addRemoveKeywords(&imap_addRemoveKeywords,
                                                &imapInfo, &storeinfo_s))
                            {
                                   libmail_kwmDestroy(storeinfo_s.keywords);
                                   free(msgset);
                                   writes(tag);
                                   writes(" NO An error occured while"
                                          " updating keywords: ");
                                   writes(strerror(errno));
                                   writes(".\r\n");
                                   return 0;
                            }
                            break;
                     }

                     libmail_kwmDestroy(storeinfo_s.keywords);
              }
              free(msgset);
              if (current_maildir_info.keywordList->keywordAddedRemoved)
                     mailboxflags(current_mailbox_ro);
              writes(tag);
              writes(" OK STORE completed.\r\n");
              return (0);
       }

       if (strcmp(curtoken->tokenbuf, "SEARCH") == 0)
       {
              char *charset=0;
              struct searchinfo *si, *sihead;
              unsigned long i;

              curtoken=nexttoken_okbracket();
              if (curtoken->tokentype == IT_ATOM &&
                     strcmp(curtoken->tokenbuf, "CHARSET") == 0)
              {
                     curtoken=nexttoken();
                     if (curtoken->tokentype != IT_ATOM &&
                            curtoken->tokentype != IT_QUOTED_STRING)
                            return (-1);

                     charset=my_strdup(curtoken->tokenbuf);
                     curtoken=nexttoken();
              }

              if (validate_charset(tag, &charset))
              {
                     if (charset)
                            free(charset);
                     return (0);
              }

              if ((si=alloc_parsesearch(&sihead)) == 0)
              {
                     free(charset);
                     return (-1);
              }
              if (currenttoken()->tokentype != IT_EOL)
              {
                     free(charset);
                     free_search(sihead);
                     return (-1);
              }

#if 0
              writes("* OK ");
              debug_search(si);
              writes("\r\n");
#endif
              writes("* SEARCH");
              dosearch(si, sihead, charset, uid);
              writes("\r\n");
              free(charset);

              for (i=0; i<current_maildir_info.nmessages; i++)
                     if (current_maildir_info.msgs[i].changedflags)
                            fetchflags(i);
              writes(tag);
              writes(" OK SEARCH done.\r\n");
              free_search(sihead);
              return (0);
       }

       if (strcmp(curtoken->tokenbuf, "THREAD") == 0)
       {
       char *charset=0;
       struct searchinfo *si, *sihead;
       unsigned long i;

              /* The following jazz is mainly for future extensions */

       void (*thread_func)(struct searchinfo *, struct searchinfo *,
                         const char *, int);
       search_type thread_type;

              {
              const char *p=getenv("IMAP_DISABLETHREADSORT");
              int n= p ? atoi(p):0;

                     if (n > 0)
                     {
                            writes(tag);
                            writes(" NO This command is disabled by the system administrator.\r\n");
                            return (0);
                     }
              }

              curtoken=nexttoken();
              if (curtoken->tokentype != IT_ATOM &&
                     curtoken->tokentype != IT_QUOTED_STRING)
                     return (-1);

              if (strcmp(curtoken->tokenbuf, "ORDEREDSUBJECT") == 0)
              {
                     thread_func=dothreadorderedsubj;
                     thread_type=search_orderedsubj;
              }
              else if (strcmp(curtoken->tokenbuf, "REFERENCES") == 0)
              {
                     thread_func=dothreadreferences;
                     thread_type=search_references1;
              }
              else
              {
                     return (-1);
              }

              curtoken=nexttoken();
              if (curtoken->tokentype != IT_ATOM &&
                     curtoken->tokentype != IT_QUOTED_STRING)
                     return (-1);

              charset=my_strdup(curtoken->tokenbuf);
              curtoken=nexttoken();

              if ((si=alloc_parsesearch(&sihead)) == 0)
              {
                     if (charset)  free(charset);
                     return (-1);
              }

              si=alloc_searchextra(si, &sihead, thread_type);

              if (currenttoken()->tokentype != IT_EOL)
              {
                     if (charset)  free(charset);
                     free_search(sihead);
                     return (-1);
              }

              if (validate_charset(tag, &charset))
              {
                     if (charset)
                            free(charset);
                     return (0);
              }

              writes("* THREAD ");
              (*thread_func)(si, sihead, charset, uid);
              writes("\r\n");
              free(charset);

              for (i=0; i<current_maildir_info.nmessages; i++)
                     if (current_maildir_info.msgs[i].changedflags)
                            fetchflags(i);
              writes(tag);
              writes(" OK THREAD done.\r\n");
              free_search(sihead);
              return (0);
       }

       if (strcmp(curtoken->tokenbuf, "SORT") == 0)
       {
       char *charset=0;
       struct searchinfo *si, *sihead;
       unsigned long i;
       struct temp_sort_stack *ts=0;

              {
              const char *p=getenv("IMAP_DISABLETHREADSORT");
              int n= p ? atoi(p):0;

                     if (n > 0)
                     {
                            writes(tag);
                            writes(" NO This command is disabled by the system administrator.\r\n");
                            return (0);
                     }
              }

              curtoken=nexttoken();
              if (curtoken->tokentype != IT_LPAREN)     return (-1);
              while ((curtoken=nexttoken())->tokentype != IT_RPAREN)
              {
              search_type st;
              struct temp_sort_stack *newts;

                     if (curtoken->tokentype != IT_ATOM &&
                            curtoken->tokentype != IT_QUOTED_STRING)
                     {
                            free_temp_sort_stack(ts);
                            return (-1);
                     }

                     if (strcmp(curtoken->tokenbuf, "SUBJECT") == 0)
                     {
                            st=search_orderedsubj;
                     }
                     else if (strcmp(curtoken->tokenbuf, "ARRIVAL") == 0)
                     {
                            st=search_arrival;
                     }
                     else if (strcmp(curtoken->tokenbuf, "CC") == 0)
                     {
                            st=search_cc;
                     }
                     else if (strcmp(curtoken->tokenbuf, "DATE") == 0)
                     {
                            st=search_date;
                     }
                     else if (strcmp(curtoken->tokenbuf, "FROM") == 0)
                     {
                            st=search_from;
                     }
                     else if (strcmp(curtoken->tokenbuf, "REVERSE") == 0)
                     {
                            st=search_reverse;
                     }
                     else if (strcmp(curtoken->tokenbuf, "SIZE") == 0)
                     {
                            st=search_size;
                     }
                     else if (strcmp(curtoken->tokenbuf, "TO") == 0)
                     {
                            st=search_to;
                     }
                     else
                     {
                            free_temp_sort_stack(ts);
                            return (-1);
                     }

                     newts=(struct temp_sort_stack *)malloc(
                            sizeof(struct temp_sort_stack));
                     if (!newts)   write_error_exit(0);
                     newts->next=ts;
                     newts->type=st;
                     ts=newts;
              }

              if (ts == 0   /* No criteria */
                     || ts->type == search_reverse)
                            /* Can't end with the REVERSE keyword */
              {
                     free_temp_sort_stack(ts);
                     return (-1);
              }

              curtoken=nexttoken();
              if (curtoken->tokentype != IT_ATOM &&
                     curtoken->tokentype != IT_QUOTED_STRING)
              {
                     free_temp_sort_stack(ts);
                     return (-1);
              }

              charset=my_strdup(curtoken->tokenbuf);
              curtoken=nexttoken();

              if ((si=alloc_parsesearch(&sihead)) == 0)
              {
                     if (charset)  free(charset);
                     free_temp_sort_stack(ts);
                     return (-1);
              }

              while (ts)
              {
              struct temp_sort_stack *cts=ts;

                     ts=cts->next;
                     si=alloc_searchextra(si, &sihead, cts->type);
                     free(cts);
              }

              if (currenttoken()->tokentype != IT_EOL)
              {
                     if (charset)  free(charset);
                     free_search(sihead);
                     return (-1);
              }

              if (validate_charset(tag, &charset))
              {
                     if (charset) free(charset);
                     free_search(sihead);
                     return (0);
              }

              writes("* SORT");
              dosortmsgs(si, sihead, charset, uid);
              writes("\r\n");
              free(charset);

              for (i=0; i<current_maildir_info.nmessages; i++)
                     if (current_maildir_info.msgs[i].changedflags)
                            fetchflags(i);
              writes(tag);
              writes(" OK SORT done.\r\n");
              free_search(sihead);
              return (0);
       }

       if (strcmp(curtoken->tokenbuf, "CHECK") == 0)
       {
              if (nexttoken()->tokentype != IT_EOL)     return (-1);
              doNoop(0);
              writes(tag);
              writes(" OK CHECK completed\r\n");
              return (0);
       }

       if (strcmp(curtoken->tokenbuf, "EXPUNGE") == 0)
       {
              if (strchr(current_mailbox_acl, ACL_EXPUNGE[0]) == NULL)
              {
                     writes(tag);
                     accessdenied("EXPUNGE", "current mailbox",
                                 ACL_EXPUNGE);
                     return 0;
              }

              if (current_mailbox_ro)
              {
                     writes(tag);
                     writes(" NO Cannot expunge read-only mailbox.\r\n");
                     return 0;
              }

              if (uid)
              {
                     char *msgset;

                     curtoken=nexttoken();
                     if (!ismsgset(curtoken))    return (-1);
                     msgset=my_strdup(curtoken->tokenbuf);
                     if (nexttoken()->tokentype != IT_EOL)     return (-1);

                     do_msgset(msgset, &uid_expunge, NULL, 1);
                     free(msgset);
              }
              else
              {
                     if (nexttoken()->tokentype != IT_EOL)     return (-1);
                     expunge();
              }
              doNoop(0);
              writes(tag);
              writes(" OK EXPUNGE completed\r\n");
              return (0);
       }

       if (strcmp(curtoken->tokenbuf, "COPY") == 0)
       {
       struct maildirsize quotainfo;
       char   *mailbox;
       char   *msgset;
       struct copyquotainfo cqinfo;
       int    has_quota;
       int    isshared;
       struct do_copy_info copy_info;
       unsigned long copy_uidv;
       char access_rights[8];

              curtoken=nexttoken();
              if (!ismsgset(curtoken))    return (-1);
              msgset=my_strdup(curtoken->tokenbuf);

              curtoken=nexttoken_nouc();

              if (curtoken->tokentype != IT_NUMBER &&
                     curtoken->tokentype != IT_ATOM &&
                     curtoken->tokentype != IT_QUOTED_STRING)
              {
                     free(msgset);
                     return (-1);
              }

              mailbox=decode_valid_mailbox(curtoken->tokenbuf, 1);

              if (!mailbox)
              {
                     struct maildir_info mi;

                     free(msgset);

                     if (maildir_info_imap_find(&mi, curtoken->tokenbuf,
                                             getenv("AUTHENTICATED"))
                         == 0)
                     {
                            if (nexttoken()->tokentype == IT_EOL)
                            {
                                   maildir_info_destroy(&mi);
                                   writes(tag);
                                   writes(" NO [TRYCREATE] Mailbox does not exist.\r\n");
                                   return (0);
                            }
                            maildir_info_destroy(&mi);
                     }
                     return (-1);
              }

              {
                     CHECK_RIGHTSM(curtoken->tokenbuf,
                                  append_rights,
                                  ACL_INSERT ACL_DELETEMSGS
                                  ACL_SEEN ACL_WRITE);
                     
                     if (strchr(append_rights, ACL_INSERT[0]) == NULL)
                     {
                            writes(tag);
                            accessdenied("COPY",
                                        curtoken->tokenbuf,
                                        ACL_INSERT);
                            return 0;
                     }

                     strcpy(access_rights, append_rights);
              }

              if (nexttoken()->tokentype != IT_EOL)
              {
                     free(msgset);
                     return (-1);
              }

              if (access(mailbox, 0))
              {
                     writes(tag);
                     writes(" NO [TRYCREATE] Mailbox does not exist.\r\n");
                     free(msgset);
                     free(mailbox);
                     return (0);
              }

              fetch_free_cache();
              cqinfo.destmailbox=mailbox;
              cqinfo.acls=access_rights;

              /*
              ** If the destination is a shared folder, copy it into the
              ** real shared folder.
              */

              isshared=0;
              if (is_sharedsubdir(cqinfo.destmailbox))
              {
              char   *p=malloc(strlen(cqinfo.destmailbox)+sizeof("/shared"));

                     if (!p)       write_error_exit(0);
                     strcat(strcpy(p, cqinfo.destmailbox), "/shared");

                     free(mailbox);
                     mailbox=cqinfo.destmailbox=p;
                     isshared=1;
              }

              cqinfo.nbytes=0;
              cqinfo.nfiles=0;

              has_quota=0;
              if (!isshared && maildirquota_countfolder(cqinfo.destmailbox))
              {
                     if (maildir_openquotafile(&quotainfo,
                                            ".") == 0)
                     {
                            if (quotainfo.fd >= 0)
                                   has_quota=1;
                            maildir_closequotafile(&quotainfo);
                     }

                     if (has_quota > 0 &&
                         do_msgset(msgset, &do_copy_quota_calc, &cqinfo,
                                  uid))
                            has_quota= -1;
              }

              if (has_quota > 0 && cqinfo.nfiles > 0)
              {

                     if (maildir_quota_add_start(".", &quotainfo,
                                              cqinfo.nbytes,
                                              cqinfo.nfiles,
                                              getenv("MAILDIRQUOTA")))
                     {
                            writes(tag);
                            writes(
                     " NO [ALERT] You exceeded your mail quota.\r\n");
                            free(msgset);
                            free(mailbox);
                            return (0);
                     }

                     maildir_quota_add_end(&quotainfo,
                                         cqinfo.nbytes,
                                         cqinfo.nfiles);
              }

              if (is_outbox(mailbox))
              {
                     int counter=0;

                     if (do_msgset(msgset, &do_count, &counter, uid) ||
                         counter > 1)
                     {
                            writes(tag);
                            writes(" NO [ALERT] Only one message may be sent at a time.\r\n");
                            free(msgset);
                            free(mailbox);
                            return (0);
                     }
              }

              copy_info.mailbox=mailbox;
              copy_info.uidplus_list=NULL;
              copy_info.uidplus_tail= &copy_info.uidplus_list;
              copy_info.acls=access_rights;

              if (has_quota < 0 ||
                  do_msgset(msgset, &do_copy_message, &copy_info, uid) ||
                  uidplus_fill(copy_info.mailbox, copy_info.uidplus_list,
                             &copy_uidv))
              {
                     uidplus_abort(copy_info.uidplus_list);
                     writes(tag);
                     writes(" NO [ALERT] COPY failed - no write permission or out of disk space.\r\n");
                     free(msgset);
                     free(mailbox);
                     return (0);
              }

              dirsync(mailbox);

              writes(tag);
              writes(" OK");

              if (copy_info.uidplus_list != NULL)
              {
                     writes(" [COPYUID ");
                     writen(copy_uidv);
                     uidplus_writemsgset(copy_info.uidplus_list, 0);
                     uidplus_writemsgset(copy_info.uidplus_list, 1);
                     writes("]");
              }

              writes(" COPY completed.\r\n");
              uidplus_free(copy_info.uidplus_list);

              free(msgset);
              free(mailbox);
              return (0);
       }
       return (-1);
}

Here is the caller graph for this function:

static int do_msgset ( const char *  msgset,
int(*)(unsigned long, int, void *)  msgfunc,
void *  msgfunc_arg,
int  isuid 
) [static]

Definition at line 912 of file imapd.c.

{
unsigned long i, j;
int    rc;
unsigned long last=0;

       if (current_maildir_info.nmessages > 0)
       {
              last=current_maildir_info.nmessages;
              if (isuid)
              {
                     last=current_maildir_info.msgs[last-1].uid;
              }
       }

       while (isdigit((int)(unsigned char)*msgset) || *msgset == '*')
       {
              i=0;
              if (*msgset == '*')
              {
                     i=last;
                     ++msgset;
              }
              else while (isdigit((int)(unsigned char)*msgset))
              {
                     i=i*10 + (*msgset++-'0');
              }
              if (*msgset != ':')
                     j=i;
              else
              {
                     j=0;
                     ++msgset;
                     if (*msgset == '*')
                     {
                            j=last;
                            ++msgset;
                     }
                     else while (isdigit((int)(unsigned char)*msgset))
                     {
                            j=j*10 + (*msgset++-'0');
                     }
              }
              if (j < i)
              {
#if 0
       /* BUGS issue */
                     writes("* NO Invalid message set: ");
                     writen(i);
                     writes(":");
                     writen(j);
                     writes("\r\n");
#endif
              }
              else if (isuid)
              {
              unsigned long k;

                     for (k=0; k<current_maildir_info.nmessages; k++)
                            if (current_maildir_info.msgs[k].uid >= i)
                                   break;
                     if (k >= current_maildir_info.nmessages ||
                            current_maildir_info.msgs[k].uid > j)
                     {
#if 0
       /* BUGS issue */
                            writes("* NO Invalid message: UID ");
                            writen(i);
                            if (j > i)
                            {
                                   writes(":");
                                   writen(j);
                            }
                            writes("\r\n");
#endif
                     }
                     else while (k < current_maildir_info.nmessages &&
                            current_maildir_info.msgs[k].uid <= j)
                     {
                            if ((rc=(*msgfunc)(k+1, 1, msgfunc_arg)) != 0)
                                   return (rc);
                            ++k;
                     }
              }
              else
              {
                     do
                     {
                            if (i == 0 ||
                                i > current_maildir_info.nmessages)
                            {
                                   writes("* NO Invalid message sequence number: ");
                                   writen(i);
                                   writes("\r\n");
                                   break;
                            }

                            if ((rc=(*msgfunc)(i, 0, msgfunc_arg)) != 0)
                                   return (rc);
                     } while (i++ < j);
              }

              if (*msgset++ != ',')       break;
       }
       return (0);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int doAddRemoveKeywords ( unsigned long  n,
int  uid,
void *  vp 
)

Definition at line 1947 of file imapd.c.

{
       struct addRemoveKeywordInfo *arki=
              (struct addRemoveKeywordInfo *)vp;
       struct libmail_kwGenericEntry *ge=
              libmail_kwgFindByName(&arki->kwg,
                                  current_maildir_info.msgs[--n].filename);
       char *tmpname=NULL, *newname=NULL;
       struct stat stat_buf;
       int rc;

       if (!ge || ge->keywords == NULL)
       {
              if (arki->storeinfo->plusminus == '+')
              {
                     rc=maildir_kwSave(current_mailbox,
                                     current_maildir_info.msgs[n].
                                     filename,
                                     arki->storeinfo->keywords,
                                     &tmpname, &newname, 1);

                     if (rc < 0)
                            return -1;
              }
       }
       else if (arki->storeinfo->plusminus == '+')
       {
              int flag=0;
              struct libmail_kwMessageEntry *kme;

              for (kme=arki->storeinfo->keywords->firstEntry;
                   kme; kme=kme->next)
              {
                     if ((rc=libmail_kwmSet(ge->keywords,
                                          kme->libmail_keywordEntryPtr))
                         < 0)
                     {
                            write_error_exit(0);
                            return 0;
                     }

                     if (rc == 0)
                            flag=1;
              }

              if (flag)
              {
                     rc=maildir_kwSave(current_mailbox,
                                     current_maildir_info.msgs[n].
                                     filename,
                                     ge->keywords,
                                     &tmpname, &newname, 1);

                     if (rc < 0)
                            return -1;
              }
       }
       else
       {
              int flag=0;
              struct libmail_kwMessageEntry *kme;

              for (kme=arki->storeinfo->keywords->firstEntry;
                   kme; kme=kme->next)
              {
                     struct libmail_keywordEntry *kwe;

                     if ((kwe=libmail_kweFind(&arki->kwg.kwHashTable,
                                           keywordName(kme->
                                                      libmail_keywordEntryPtr),
                                           0)) != NULL &&

                         libmail_kwmClear(ge->keywords, kwe) == 0)
                            flag=1;
              }

              if (flag)
              {
                     rc=maildir_kwSave(current_mailbox,
                                     current_maildir_info.msgs[n].
                                     filename,
                                     ge->keywords,
                                     &tmpname, &newname, 1);

                     if (rc < 0)
                            return -1;
              }


       }

       if (tmpname)
       {
              current_maildir_info.msgs[n].changedflags=1;

              if (link(tmpname, newname) < 0)
              {
                     unlink(tmpname);
                     free(tmpname);
                     free(newname);

                     return (errno == EEXIST ? 1:-1);
              }

              if (stat(tmpname, &stat_buf) == 0 &&
                  stat_buf.st_nlink == 2)
              {
                     unlink(tmpname);
                     free(tmpname);
                     free(newname);
                     return 0;
              }
              unlink(tmpname);
              free(tmpname);
              free(newname);
              return 1;
       }

       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void dogethostname ( ) [static]

Definition at line 6152 of file imapd.c.

{
char   buf[2048];
char   *p;

       if (gethostname(buf, sizeof(buf)) < 0)
              strcpy(buf, "courier-imap");
       p=malloc(strlen(buf)+sizeof("HOSTNAME="));
       if (!p)
              write_error_exit(0);
       strcat(strcpy(p, "HOSTNAME="), buf);
       putenv(p);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int doidle ( time_t  ,
int   
)

Definition at line 85 of file imaptoken.c.

{
fd_set fds;
struct timeval tv;
time_t t;

       time(&t);
       if (t >= readtimeout)   disconnected_timeout();
       if (imap_readptrleft > 0) return 1;

       FD_ZERO(&fds);
       FD_SET(0, &fds);

       if (extraFd > 0)
       {
              FD_SET(extraFd, &fds);
       }
       else
       {
              extraFd=0;
       }

       tv.tv_sec=idletimeout;
       tv.tv_usec=0;

       select(extraFd + 1, &fds, 0, 0, &tv);
       return (FD_ISSET(0, &fds));
}

Here is the call graph for this function:

Here is the caller graph for this function:

void doNoop ( int  real_noop)

Definition at line 1138 of file imapd.c.

{
       struct imapscaninfo new_maildir_info;
       unsigned long i, j;
       int    needstats=0;
       unsigned long expunged;
#if SMAP
       unsigned long smap_expunge_count=0;
       unsigned long smap_expunge_bias=0;

       unsigned long smap_last=0;
       unsigned long smap_range=0;

       int takeSnapshot=1;
#endif
       struct noopKeywordUpdateInfo kui;

       imapscan_init(&new_maildir_info); 

       if (imapscan_maildir(&new_maildir_info, current_mailbox, 0,
                          current_mailbox_ro, NULL))
              return;

       j=0;
       expunged=0;
       for (i=0; i<current_maildir_info.nmessages; i++)
       {
              struct libmail_kwMessage *a, *b;

              while (j < new_maildir_info.nmessages &&
                     new_maildir_info.msgs[j].uid <
                            current_maildir_info.msgs[i].uid)
              {
                     /* How did this happen??? */

                     new_maildir_info.msgs[j].changedflags=1;
                     ++j;
                     needstats=1;
#if SMAP
                     takeSnapshot=0;
#endif
              }

              if (j >= new_maildir_info.nmessages ||
                     new_maildir_info.msgs[j].uid >
                            current_maildir_info.msgs[i].uid)
              {
#if SMAP
                     if (smapflag)
                     {
                            takeSnapshot=0;

                            if (smap_expunge_count > 100)
                            {
                                   if (smap_range > 0)
                                   {
                                          writes("-");
                                          writen(smap_last + smap_range
                                                 - smap_expunge_bias
                                                 + 1);
                                   }
                                   writes("\n");
                                   smap_expunge_count=0;
                            }

                            if (smap_expunge_count == 0)
                            {
                                   smap_expunge_bias=expunged;

                                   writes("* EXPUNGE ");
                                   writen(i+1-smap_expunge_bias);
                                   smap_last=i;
                                   smap_range=0;
                            }
                            else if (smap_last + smap_range + 1 == i)
                            {
                                   ++smap_range;
                            }
                            else
                            {
                                   if (smap_range > 0)
                                   {
                                          writes("-");
                                          writen(smap_last + smap_range
                                                 - smap_expunge_bias
                                                 + 1);
                                   }
                                   writes(" ");
                                   writen(i+1-smap_expunge_bias);
                                   smap_last=i;
                                   smap_range=0;
                            }
                            ++smap_expunge_count;
                     }
                     else
#endif
                     {
                            writes("* ");
                            writen(i+1-expunged);
                            writes(" EXPUNGE\r\n");
                            needstats=1;
                     }

                     ++expunged;
                     continue;
              }

              /* Must be the same */

              a=current_maildir_info.msgs[i].keywordMsg;
              b=new_maildir_info.msgs[j].keywordMsg;

              if (strcmp(current_maildir_info.msgs[i].filename,
                     new_maildir_info.msgs[j].filename) ||
                  (a && !b) || (!a && b) ||
                  (a && b && libmail_kwmCmp(a, b)))
              {
                     new_maildir_info.msgs[j].changedflags=1;
#if SMAP
                     takeSnapshot=0;
#endif
              }
              if (current_maildir_info.msgs[i].recentflag)
                     new_maildir_info.msgs[j].recentflag=1;
#if SMAP
              if (smapflag)
                     new_maildir_info.msgs[j].recentflag=0;
#endif
              new_maildir_info.msgs[j].copiedflag=
                     current_maildir_info.msgs[i].copiedflag;
              ++j;
       }

#if SMAP
       if (smapflag && smap_expunge_count)
       {
              if (smap_range > 0)
              {
                     writes("-");
                     writen(smap_last + smap_range - smap_expunge_bias + 1);
              }
              writes("\n");
       }

#endif

       while (j < new_maildir_info.nmessages)
       {
#if SMAP
              if (smapflag)
                     takeSnapshot=0;
#endif
              ++j;
              needstats=1;
       }

       new_maildir_info.keywordList->keywordAddedRemoved=0;


       /**********************************************************
        **
        ** current_maildir_info: existing keywords
        ** new_maildir_info: new keywords
        **
        ** Process new/deleted keywords as follows:
        */

       /*
       ** 1. Make sure that the old keyword list includes any new keywords.
       */

       kui.keywordList=current_maildir_info.keywordList;
       kui.messagePtr=libmail_kwmCreate();

       if (!kui.messagePtr)
              write_error_exit(0);

       current_maildir_info.keywordList->keywordAddedRemoved=0;
       libmail_kwEnumerate(new_maildir_info.keywordList,
                      noopAddKeyword, &kui);

       if (current_maildir_info.keywordList->keywordAddedRemoved)
              mailboxflags(current_mailbox_ro);
       libmail_kwmDestroy(kui.messagePtr);


       /*
       ** 2. Temporarily add all existing keywords to the new keyword list.
       */

       kui.keywordList=new_maildir_info.keywordList;
       kui.messagePtr=libmail_kwmCreate();

       if (!kui.messagePtr)
              write_error_exit(0);
       libmail_kwEnumerate(current_maildir_info.keywordList,
                      noopAddKeyword, &kui);

       imapscan_copy(&current_maildir_info, &new_maildir_info);
       imapscan_free(&new_maildir_info);

#if SMAP
       if (takeSnapshot)
       {
              if (real_noop && smapflag)
                     snapshot_save();
       }
       else
              snapshot_needed();
#endif

       if (needstats)
              mailboxmetrics();

       for (j=0; j < current_maildir_info.nmessages; j++)
              if (current_maildir_info.msgs[j].changedflags)
              {
#if SMAP
                     if (smapflag)
                            smap_fetchflags(j);
                     else
#endif
                            fetchflags(j);
              }

       /*
       ** After sending changed flags to the client, see if any keywords
       ** have gone away.
       */

       current_maildir_info.keywordList->keywordAddedRemoved=0;
       libmail_kwmDestroy(kui.messagePtr);
       if (current_maildir_info.keywordList->keywordAddedRemoved)
              mailboxflags(current_mailbox_ro);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void emptytrash ( )

Definition at line 235 of file imapd.c.

{
       char   *dir, *all_settings, *next_folder, *folder, *p;
       unsigned l;

       all_settings=getenv("IMAP_EMPTYTRASH");

       if (!all_settings)
              return;

       all_settings=strdup(all_settings);
       if (!all_settings)
              return;

       if (strchr(all_settings, ':') == 0 &&
           strchr(all_settings, ',') == 0)
       {
              l=atoi(all_settings);

              if (l <= 0)
                     l=1;

              maildir_getnew(".", trash, NULL, NULL);
              if ((dir=maildir_folderdir(".", trash)))
              {
                     maildir_purge(dir, l * 24 * 60 * 60);
                     free(dir);
              }
              free(all_settings);
              return;
       }

       for (folder=all_settings; folder && *folder; )
       {
              if (*folder == ',')
              {
                     ++folder;
                     continue;
              }
              next_folder=strchr(folder, ',');
              if (next_folder)
                     *next_folder++=0;

              p=strchr(folder, ':');
              if (!p)
              {
                     folder=next_folder;
                     continue;
              }

              *p++=0;

              l=atoi(p);
              if (l <= 0)   l=1;

              maildir_getnew(".", folder, NULL, NULL);
              if ((dir=maildir_folderdir(".", folder)))
              {
                     maildir_purge(dir, l * 24 * 60 * 60);
                     free(dir);
              }
              folder=next_folder;
       }
       free(all_settings);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void expunge ( )

Definition at line 1546 of file imapd.c.

{
       do_expunge(0, current_maildir_info.nmessages, 0);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int fastkeywords ( )

Definition at line 56 of file capability.c.

{
       return capa_keywords == 1;
}

Definition at line 1490 of file fetch.c.

Here is the call graph for this function:

Here is the caller graph for this function:

void fetchflags ( unsigned  long)

Definition at line 451 of file fetch.c.

{
#if SMAP
       if (smapflag)
       {
              writes("* FETCH ");
              writen(n+1);
       }
       else
#endif
       {
              writes("* ");
              writen(n+1);
              writes(" FETCH (");
       }

       doflags(0, 0, &current_maildir_info, n, 0);

#if SMAP
       if (smapflag)
       {
              writes("\n");
       }
       else
#endif
              writes(")\r\n");
}
static int fix_acl_delete ( int(*)(maildir_aclt *, const char *, const maildir_aclt *)  func,
maildir_aclt newacl,
const char *  aclstr 
) [static]

Definition at line 3079 of file imapd.c.

{
       char *p, *q;
       int rc;

       if (strchr(aclstr, ACL_DELETE_SPECIAL[0]) == NULL)
              return (*func)(newacl, aclstr, NULL);


       p=malloc(strlen(aclstr)+sizeof(ACL_DELETEFOLDER
                                   ACL_DELETEMSGS
                                   ACL_EXPUNGE));
       if (!p)
              return -1;

       q=p;
       while (*aclstr)
       {
              if (*aclstr != ACL_DELETE_SPECIAL[0])
                     *q++ = *aclstr;
              ++aclstr;
       }

       strcpy(q, ACL_DELETEFOLDER ACL_DELETEMSGS ACL_EXPUNGE);

       rc=(*func)(newacl, p, NULL);
       free(p);
       return rc;
}

Here is the caller graph for this function:

static int fix_acl_delete2 ( maildir_aclt_list aclt_list,
const char *  identifier,
const char *  aclstr 
) [static]

Definition at line 3112 of file imapd.c.

{
       char *p, *q;
       int rc;

       if (strchr(aclstr, ACL_DELETE_SPECIAL[0]) == NULL)
              return maildir_aclt_list_add(aclt_list, identifier, aclstr,
                                        NULL);


       p=malloc(strlen(aclstr)+sizeof(ACL_DELETEFOLDER
                                   ACL_DELETEMSGS
                                   ACL_EXPUNGE));
       if (!p)
              return -1;

       q=p;
       while (*aclstr)
       {
              if (*aclstr != ACL_DELETE_SPECIAL[0])
                     *q++ = *aclstr;
              ++aclstr;
       }

       strcpy(q, ACL_DELETEFOLDER ACL_DELETEMSGS ACL_EXPUNGE);

       rc=maildir_aclt_list_add(aclt_list, identifier, p, NULL);
       free(p);
       return rc;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int folder_exists ( const char *  folder) [static]

Definition at line 3628 of file imapd.c.

{
       int flag=0;

       if (mailbox_scan("", folder, LIST_CHECK1FOLDER,
                      folder_exists_cb, &flag))
              return 0;
       return flag;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int folder_exists_cb ( const char *  hiersep,
const char *  mailbox,
int  flags,
void *  void_arg 
) [static]

Definition at line 3619 of file imapd.c.

{
       *(int *)void_arg=1;
       return 0;
}

Here is the caller graph for this function:

int folder_rename ( struct maildir_info mi1,
struct maildir_info mi2,
const char **  errmsg 
)

Definition at line 3895 of file imapd.c.

{
       char *old_mailbox, *new_mailbox;

       if (mi1->homedir == NULL || mi1->maildir == NULL)
       {
              *errmsg="Invalid mailbox name";
              return -1;
       }

       if (mi2->homedir == NULL || mi2->maildir == NULL)
       {
              *errmsg="Invalid new mailbox name";
              return -1;
       }

       if (current_mailbox)
       {
              char *mailbox=maildir_name2dir(mi1->homedir,
                                          mi1->maildir);
              size_t l;

              if (!mailbox)
              {
                     *errmsg="Invalid mailbox name";
                     return -1;
              }

              l=strlen(mailbox);

              if (strncmp(mailbox, current_mailbox, l) == 0 &&
                  (current_mailbox[l] == 0 ||
                   current_mailbox[l] == HIERCH))
              {
                     free(mailbox);
                     *errmsg="Can't RENAME the currently-open folder";
                     return -1;
              }
              free(mailbox);
       }

       if (strcmp(mi1->homedir, mi2->homedir))
       {
              *errmsg="Cannot move a folder to a different account.";
              return -1;
       }

       if (strcmp(mi1->maildir, INBOX) == 0 ||
           strcmp(mi2->maildir, INBOX) == 0)
       {
              *errmsg="INBOX rename not implemented.";
              return -1;
       }

       if (is_reserved_name(mi1->maildir) ||
           is_reserved_name(mi2->maildir))
       {
              *errmsg="Reserved folder name - cannot rename.";
              return -1;
       }

       /* Depend on maildir_name2dir returning ./.folder, see
       ** maildir_rename() call. */

       if ((old_mailbox=maildir_name2dir(".", mi1->maildir)) == NULL ||
           strncmp(old_mailbox, "./", 2))
       {
              if (old_mailbox)
                     free(old_mailbox);
              *errmsg="Internal error in RENAME: maildir_name2dir failed"
                     " for the old folder rename.";
              return -1;
       }

       if ((new_mailbox=maildir_name2dir(".", mi2->maildir)) == NULL ||
           strncmp(new_mailbox, "./", 2))
       {
              free(old_mailbox);
              if (new_mailbox)
                     free(new_mailbox);
              *errmsg="Internal error in RENAME: maildir_name2dir failed"
                     " for the new folder rename.";
              return -1;
       }

       fetch_free_cache();

       if (maildir_rename(mi1->homedir,
                        old_mailbox+2, new_mailbox+2,
                        MAILDIR_RENAME_FOLDER |
                        MAILDIR_RENAME_SUBFOLDERS,
                        &rename_callback))
       {
              free(old_mailbox);
              free(new_mailbox);

              *errmsg="@RENAME failed: ";
              return -1;
       }

       maildir_quota_recalculate(mi1->homedir);
       free(old_mailbox);
       free(new_mailbox);
       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void free_mailboxlist ( struct temp_acl_mailbox_list mailboxlist) [static]

Definition at line 2952 of file imapd.c.

{
       size_t i;
       for (i=0; mailboxlist && mailboxlist[i].mailbox; i++)
       {
              free(mailboxlist[i].hier);
              free(mailboxlist[i].mailbox);
       }
       if (mailboxlist)
              free(mailboxlist);
}

Here is the caller graph for this function:

static void free_temp_acl_mailbox ( struct temp_acl_mailbox_list p) [static]

Definition at line 2862 of file imapd.c.

{
       free(p->mailbox);
       free(p->hier);
}

Here is the caller graph for this function:

static void free_tempmailboxlist ( struct temp_acl_mailbox_list mailboxlist) [static]

Definition at line 2964 of file imapd.c.

{
       struct temp_acl_mailbox_list *p;

       while ((p=mailboxlist) != NULL)
       {
              mailboxlist=p->next;
              free_temp_acl_mailbox(p);
              free(p);
       }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int get_acllist ( maildir_aclt_list l,
const char *  mailbox,
char **  computed_mailbox_owner 
) [static]

Definition at line 2538 of file imapd.c.

{
       int rc;
       char *v;

       struct maildir_info mi;
       char *dummy_mailbox_owner=NULL;

       if (!computed_mailbox_owner)
              computed_mailbox_owner= &dummy_mailbox_owner;

       if (maildir_info_imap_find(&mi, p, getenv("AUTHENTICATED")) < 0)
              return -1;

       v=NULL;

       if (mi.homedir && mi.maildir)
       {
              rc=acl_read_folder(l, mi.homedir, mi.maildir);
              v=maildir_name2dir(mi.homedir, mi.maildir);
       }
       else if (mi.mailbox_type == MAILBOXTYPE_OLDSHARED)
       {
              rc=acl_read_folder(l, ".", p); /* It handles it */
       }
       else if (mi.mailbox_type == MAILBOXTYPE_NEWSHARED)
       {
              /* Intermediate #shared node.  Punt */

              maildir_aclt_list_init(l);
              rc=0;

              if (maildir_aclt_list_add(l, "anyone",
                                     ACL_LOOKUP, NULL) < 0)
              {
                     maildir_aclt_list_destroy(l);
                     rc=-1;
              }
       }
       else
       {
              /* Unknown mailbox type, no ACLs */

              maildir_aclt_list_init(l);
              rc=0;
       }

       if (rc)
       {
              if (v)
                     free(v);
              maildir_info_destroy(&mi);
              return -1;
       }

       *computed_mailbox_owner=my_strdup(mi.owner);

       maildir_info_destroy(&mi);

       /* Detect if ACLs on the currently-open folder have changed */

       if (rc == 0 && current_mailbox &&
#if SMAP
           !smapflag &&
#endif

           v && strcmp(v, current_mailbox) == 0)
       {
              char *new_acl=compute_myrights(l, *computed_mailbox_owner);

              if (new_acl && strcmp(new_acl, current_mailbox_acl))
              {
                     free(current_mailbox_acl);
                     current_mailbox_acl=new_acl;
                     new_acl=NULL;
                     myrights();
              }

              if (new_acl)
                     free(new_acl);
       }
       if (v)
              free(v);
       if (dummy_mailbox_owner)
              free(dummy_mailbox_owner);
       return rc;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int get_flagname ( const char *  p,
struct imapflags flags 
)

Definition at line 417 of file imapd.c.

{
       if (strcasecmp(p, "\\SEEN") == 0)
              flags->seen=1;
       else if (strcasecmp(p, "\\ANSWERED") == 0)
              flags->answered=1;
       else if (strcasecmp(p, "\\DRAFT") == 0)
              flags->drafts=1;
       else if (strcasecmp(p, "\\DELETED") == 0)
              flags->deleted=1;
       else if (strcasecmp(p, "\\FLAGGED") == 0)
              flags->flagged=1;
       else return (-1);
       return (0);
}

Here is the caller graph for this function:

int get_flagsAndKeywords ( struct imapflags flags,
struct libmail_kwMessage **  kwPtr 
)

Definition at line 460 of file imapd.c.

{
struct imaptoken *t;

       while ((t=nexttoken_nouc())->tokentype == IT_ATOM)
       {
              if (get_flagname(t->tokenbuf, flags))
              {
                     if (!valid_keyword(t->tokenbuf))
                            return -1;

                     if (get_keyword(kwPtr, t->tokenbuf))
                            return -1;
              }
       }
       return (t->tokentype == IT_RPAREN ? 0:-1);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int get_keyword ( struct libmail_kwMessage **  kwPtr,
const char *  kw 
)

Definition at line 451 of file imapd.c.

{
       if (libmail_kwmSetName(current_maildir_info.keywordList, *kwPtr, kw) < 0)
              write_error_exit(0);

       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void get_message_flags ( struct imapscanmessageinfo mi,
char *  buf,
struct imapflags flags 
)

Definition at line 479 of file imapd.c.

{
       const char *filename=mi->filename;

       const char *DRAFT="\\Draft";
       const char *FLAGGED="\\Flagged";
       const char *REPLIED="\\Answered";
       const char *SEEN="\\Seen";
       const char *DELETED="\\Deleted";
       const char *RECENT="\\Recent";

       const char *SPC=" ";

       if (buf)
              *buf=0;

       if (flags)
              flags->seen=flags->answered=flags->deleted=flags->flagged
              =flags->recent=flags->drafts=0;

       if ((filename=strrchr(filename, MDIRSEP[0])) == 0
              || strncmp(filename, MDIRSEP "2,", 3))    return;

#if SMAP
       if (smapflag)
       {
              SPC=",";
              DRAFT="DRAFT";
              FLAGGED="MARKED";
              REPLIED="REPLIED";
              SEEN="SEEN";
              DELETED="DELETED";
              RECENT="RECENT";
       }
#endif

       if (strchr(filename, 'D'))
       {
              if (buf) strcat(buf, DRAFT);
              if (flags)  flags->drafts=1;
       }

       if (strchr(filename, 'F'))
       {
              if (buf) strcat(strcat(buf, *buf ? SPC:""), FLAGGED);
              if (flags)    flags->flagged=1;
       }
       if (strchr(filename, 'R'))
       {
              if (buf) strcat(strcat(buf, *buf ? SPC:""), REPLIED);
              if (flags)    flags->answered=1;
       }

       if (strchr(filename, 'S') != NULL)
       {
              if (buf) strcat(strcat(buf, *buf ? SPC:""), SEEN);
              if (flags)    flags->seen=1;
       }

       if (strchr(filename, 'T'))
       {
              if (buf) strcat(strcat(buf, *buf ? SPC:""), DELETED);
              if (flags)    flags->deleted=1;
       }

       if (mi->recentflag)
       {
              if (flags) flags->recent=1;
              if (buf) strcat(strcat(buf, *buf ? SPC:""), RECENT);
       }
}

Here is the caller graph for this function:

char * get_myrightson ( const char *  mailbox)

Definition at line 2747 of file imapd.c.

{
       maildir_aclt_list l;
       char *mailbox_owner;
       char *rights;

       if (get_acllist(&l, mailbox, &mailbox_owner) < 0)
              return NULL;

       rights=compute_myrights(&l, mailbox_owner);
       free(mailbox_owner);
       maildir_aclt_list_destroy(&l);
       return rights;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int getacl_cb ( const char *  ident,
const maildir_aclt acl,
void *  cb_arg 
) [static]

Definition at line 2711 of file imapd.c.

{
       char *p;
       int isneg=0;

       if (*ident == '-')
       {
              isneg=1;
              ++ident;
       }

       if (strchr(ident, '='))
       {
              if (strncmp(ident, "user=", 5))
                     return 0; /* Hear no evil */
              ident += 5;
       }

       writes(" \"");
       if (isneg)
              writes("-");
       writeqs(ident);
       writes("\" \"");


       p=my_strdup(maildir_aclt_ascstr(acl));

       writeacl1(p);

       free(p);
       writes("\"");
       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int imap_addRemoveKeywords ( void *  myVoidArg,
void *  addRemoveVoidArg 
) [static]

Definition at line 2082 of file imapd.c.

{
       struct imap_addRemoveKeywordInfo *i=
              (struct imap_addRemoveKeywordInfo *)myVoidArg;
       unsigned long j;

       for (j=0; j<current_maildir_info.nmessages; j++)
              current_maildir_info.msgs[j].storeflag=0;

       do_msgset(i->msgset, markmessages, NULL, i->uid);

       for (j=0; j<current_maildir_info.nmessages; j++)
       {
              int rc;

              if (!current_maildir_info.msgs[j].storeflag)
                     continue;

              rc=doAddRemoveKeywords(j+1, i->uid, addRemoveVoidArg);
              if (rc)
                     return rc;
       }
       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void imapcapability ( )

Definition at line 83 of file capability.c.

{
       const char *p;

       if ((p=getenv("IMAP_TLS")) && atoi(p) &&
           (p=getenv("IMAP_CAPABILITY_TLS")) && *p)
              writes(p);
       else if ((p=getenv("IMAP_CAPABILITY")) != 0 && *p)
              writes(p);
       else
              writes("IMAP4rev1");

#if SMAP
       p=getenv("SMAP_CAPABILITY");

       if (p && *p)
       {
              writes(" ");
              writes(p);

              if (keywords())
                     writes(" KEYWORDS");
       }
#endif

       if ((p=getenv("IMAP_ACL")) && atoi(p))
              writes(" ACL ACL2=UNION");

       if (have_starttls())
       {
              writes(" STARTTLS");
              if (tlsrequired())
                     writes(" LOGINDISABLED");
       }
       else
       {
              if (imap_externalauth())
                     writes(" AUTH=EXTERNAL");
       }
                     

       p=getenv("OUTBOX");

       if (p && *p)
       {
              writes(" XCOURIEROUTBOX=INBOX");
              writes(p);
       }

       if (magictrash())
              writes(" XMAGICTRASH");
}
int imapenhancedidle ( void  )

Definition at line 1392 of file imapd.c.

{
       struct maildirwatch *w;
       struct maildirwatch_contents c;
       int rc;
       int started=0;

       if (!current_mailbox)
              return (-1);

       if ((w=maildirwatch_alloc(current_mailbox)) == NULL)
       {
              perror(current_mailbox);
              fprintf(stderr, "This may be a problem with FAM or Gamin\n");
              return (-1);
       }

       rc=maildirwatch_start(w, &c);

       if (rc < 0)
       {
              perror("maildirwatch_start");
              maildirwatch_free(w);
              return (-1);
       }

       if (rc > 0)
       {
              maildirwatch_free(w);
              return (-1); /* Fallback */
       }

#if SMAP
       if (smapflag)
       {
              writes("+OK Entering ENHANCED idle mode\n");
       }
       else
#endif
              writes("+ entering ENHANCED idle mode\r\n");
       writeflush();

       for (;;)
       {
              if (!started)
              {
                     int fd;
                     int rc;

                     rc=maildirwatch_started(&c, &fd);

                     if (rc > 0)
                     {
                            started=1;
                            doNoop(0);
                            writeflush();
                     }
                     else
                     {
                            if (rc < 0)
                                   perror("maildirwatch_started");
                            if (doidle(60, fd))
                                   break;
                     }
                     continue;
              }

              if (started < 0) /* Error fallback mode*/
              {
                     if (doidle(60, -1))
                            break;
              }
              else
              {
                     int changed;
                     int fd;
                     int timeout;

                     if (maildirwatch_check(&c, &changed, &fd, &timeout)
                         == 0)
                     {
                            if (!changed)
                            {
                                   if (doidle(timeout, fd))
                                          break;
                                   continue;
                            }

                            maildirwatch_end(&c);
                            doNoop(0);

                            rc=maildirwatch_start(w, &c);

                            if (rc < 0)
                            {
                                   perror("maildirwatch_start");
                                   started= -1;
                            }
                            else
                                   started=0;
                     }
                     else
                     {
                            started= -1;
                     }
              }

              doNoop(0);
              writeflush();
       }

       maildirwatch_end(&c);
       maildirwatch_free(w);
       return (0);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void imapidle ( void  )

Definition at line 1508 of file imapd.c.

{
       const char * envp = getenv("IMAP_IDLE_TIMEOUT");
       const int idleTimeout = envp ? atoi(envp) : 60;

#if SMAP
       if (smapflag)
       {
              writes("+OK Entering idle mode...\n");
       }
       else
#endif
              writes("+ entering idle mode\r\n");
       if (current_mailbox)
              doNoop(0);
       writeflush();
       while (!doidle(idleTimeout, -1))
       {
              if (current_mailbox)
                     doNoop(0);
              writeflush();
       }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void imapscanfail ( const char *  p)

Definition at line 304 of file imapscanclient.c.

{
       fprintf(stderr, "ERR: Failed to create cache file: %s (%s)\n", p,
              getenv("AUTHENTICATED"));
#if    HAVE_STRERROR
       fprintf(stderr, "ERR: Error: %s\n", strerror(errno));
#endif

#if    HAVE_FAM
       if (errno == EIO)
       {
              fprintf(stderr,
                     "ERR: Check for proper operation and configuration\n"
                     "ERR: of the File Access Monitor daemon (famd).\n");
       }
#endif
}

Here is the caller graph for this function:

void initcapability ( )

Definition at line 22 of file capability.c.

{
       const char *p=getenv("IMAP_KEYWORDS");

       if (p) capa_keywords=atoi(p);
}
int is_reserved ( const char *  m)

Definition at line 315 of file imapd.c.

{
       if (strncmp(m, "./", 2) == 0) m += 2;

       if (is_trash(m))     return (1);
       return (0);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int is_reserved_name ( const char *  name)

Definition at line 323 of file imapd.c.

{
       if (strncmp(name, INBOX, strlen(INBOX)) == 0)
              return is_trash(name+strlen(INBOX));
       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int is_trash ( const char *  m)

Definition at line 217 of file imapd.c.

{
       if (strcmp(m, dot_trash))
       {
              /*
               * not trying to delete .Trash but folder inside of .Trash
               */
              return (0);
       }
       else
       {
              /*
               * trying to delete .Trash - stop them
               */
              return (1);
       }
}

Here is the caller graph for this function:

int keywords ( )

Definition at line 51 of file capability.c.

{
       return capa_keywords != 0;
}
static void list_acl ( const char *  mailbox,
maildir_aclt_list l 
) [static]

Definition at line 2628 of file imapd.c.

{
       writes("(\"ACL\" (");
       maildir_aclt_list_enum(l, list_acl_cb, NULL);
       writes("))");
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int list_acl_cb ( const char *  ident,
const maildir_aclt acl,
void *  cb_arg 
) [static]

Definition at line 2673 of file imapd.c.

{
       writes("(\"");
       writeqs(ident);
       writes("\" \"");
       writeacl(maildir_aclt_ascstr(acl));
       writes("\")");
       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int list_callback ( const char *  hiersep,
const char *  mailbox,
int  flags,
void *  void_arg 
) [static]

Definition at line 2270 of file imapd.c.

{
       const char *sep="";
       const char *cmd=(const char *)void_arg;
       maildir_aclt_list l;

       char *myrights=NULL;

       /*
       ** If we're going to list ACLs, grab the ACLs now, because
       ** get_acllist2() may end up calling myrights(), which generates
       ** its own output.
       */

       if (flags & (LIST_MYRIGHTS | LIST_ACL))
       {
              myrights=get_myrightson(mailbox);

              if (flags & LIST_MYRIGHTS)
              {
                     if (!maildir_acl_canlistrights(myrights))
                     {
                            flags &= ~LIST_MYRIGHTS;
#if 0
                            /* F.Y.I. only, should not be enabled
                               'cause make check may fail on systems
                               which return directory entries in a
                               different order */

                            writes("* ACLFAILED \"");
                            writeqs(mailbox);
                            writes("\"");
                            accessdenied("LIST(MYRIGHTS)",
                                        mailbox,
                                        ACL_LOOKUP
                                        ACL_READ
                                        ACL_INSERT
                                        ACL_CREATE
                                        ACL_DELETEFOLDER
                                        ACL_EXPUNGE
                                        ACL_ADMINISTER);
#endif
                     }
              }

              if (flags & LIST_ACL)
              {
                     if (!strchr(myrights, ACL_ADMINISTER[0]))
                     {
                            flags &= ~LIST_ACL;
#if 0
                            /* F.Y.I. only, should not be enabled
                               'cause make check may fail on systems
                               which return directory entries in a
                               different order */

                            writes("* ACLFAILED \"");
                            writeqs(mailbox);
                            writes("\"");
                            accessdenied("LIST(ACL)",
                                        mailbox,
                                        ACL_ADMINISTER);
#endif
                     }
              }
       }

       if (flags & LIST_ACL)
       {
              if (get_acllist(&l, mailbox, NULL) < 0)
              {
                     fprintf(stderr,
                            "ERR: Error reading ACLs for %s: %s\n",
                            mailbox, strerror(errno));
                     flags &= ~LIST_ACL;
              }
       }

       writes("* ");
       writes(cmd);
       writes(" (");

#define DO_FLAG(flag, flagname) \
       if (flags & (flag)) { writes(sep); writes(flagname); \
                            sep=" "; }

       DO_FLAG(MAILBOX_NOSELECT, "\\Noselect");
       DO_FLAG(MAILBOX_UNMARKED, "\\Unmarked");
       DO_FLAG(MAILBOX_MARKED, "\\Marked");
       DO_FLAG(MAILBOX_NOCHILDREN, "\\HasNoChildren");
       DO_FLAG(MAILBOX_NOINFERIORS, "\\Noinferiors");
       DO_FLAG(MAILBOX_CHILDREN, "\\HasChildren");
#undef DO_FLAG

       writes(") ");
       writes(hiersep);
       writes(" \"");
       writeqs(mailbox);
       writes("\"");

       if (flags & (LIST_ACL|LIST_MYRIGHTS|LIST_POSTADDRESS))
       {
              writes(" (");
              if (flags & LIST_ACL)
                     list_acl(mailbox, &l);
              if (flags & LIST_MYRIGHTS)
                     list_myrights(mailbox, myrights);
              if (flags & LIST_POSTADDRESS)
                     list_postaddress(mailbox);
              writes(")");
       }

       writes("\r\n");
       if (myrights)
              free(myrights);
       if (flags & LIST_ACL)
              maildir_aclt_list_destroy(&l);

       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void list_myrights ( const char *  mailbox,
const char *  myrights 
) [static]

Definition at line 2801 of file imapd.c.

{

       writes("(\"MYRIGHTS\" ");

       if (r == NULL)
       {
              fprintf(stderr, "ERR: Error reading ACLs for %s: %s\n",
                     mailbox, strerror(errno));
              writes(" NIL");
       }
       else
       {
              writes("\"");
              writeacl(r);
              writes("\"");
       }
       writes(")");
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void list_postaddress ( const char *  mailbox) [static]

Definition at line 2394 of file imapd.c.

{
       writes("(POSTADDRESS NIL)");
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void logoutmsg ( ) [static]

Definition at line 2235 of file imapd.c.

{
       bye_msg("INFO: LOGOUT");
}

Here is the call graph for this function:

Here is the caller graph for this function:

int magictrash ( )

Definition at line 61 of file capability.c.

{
       const char *p;

       p=getenv("IMAP_MOVE_EXPUNGE_TO_TRASH");

       if (p && atoi(p))
              return 1;
       return 0;
}

Here is the caller graph for this function:

static void mailboxflags ( int  ro) [static]

Definition at line 1025 of file imapd.c.

{
#if SMAP
       if (smapflag)
              return;
#endif

       writes("* FLAGS (");

       if (current_maildir_info.keywordList)
       {
              void (*writefunc)(const char *)=writes;

              libmail_kwEnumerate(current_maildir_info.keywordList,
                                &write_keyword_name, &writefunc);
       }

       writes("\\Draft \\Answered \\Flagged"
              " \\Deleted \\Seen \\Recent)\r\n");
       writes("* OK [PERMANENTFLAGS (");


       if (ro)
       {
              writes(")] No permanent flags permitted\r\n");
       }
       else
       {
              if (current_maildir_info.keywordList)
              {
                     void (*writefunc)(const char *)=writes;

                     libmail_kwEnumerate(current_maildir_info
                                       .keywordList,
                                       &write_keyword_name,
                                       &writefunc);
              }

              if (keywords())
                     writes("\\* ");

              writes("\\Draft \\Answered \\Flagged \\Deleted \\Seen)] Limited\r\n");
       }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void mailboxmetrics ( ) [static]

Definition at line 1085 of file imapd.c.

{
unsigned long i,j;

#if SMAP
       if (smapflag)
       {
              writes("* EXISTS ");
              writen(current_maildir_info.nmessages);
              writes("\n");
              return;
       }
#endif


       writes("* ");
       writen(current_maildir_info.nmessages);
       writes(" EXISTS\r\n");

       writes("* ");
       i=0;

       for (j=0; j<current_maildir_info.nmessages; j++)
              if (current_maildir_info.msgs[j].recentflag)
                     ++i;
       writen(i);
       writes(" RECENT\r\n");
}

Here is the call graph for this function:

Here is the caller graph for this function:

int maildir_info_suppress ( const char *  maildir)

Definition at line 150 of file imapd.c.

{
       struct stat stat_buf;

       if (stat(maildir, &stat_buf) < 0 ||
           /* maildir inaccessible, perhaps another server? */

           (stat_buf.st_dev == homedir_dev &&
            stat_buf.st_ino == homedir_ino)
                  /* Exclude ourselves from the shared list */

           )
       {
              return 1;
       }

       return 0;
}

Here is the caller graph for this function:

FILE* maildir_mkfilename ( const char *  mailbox,
struct imapflags flags,
unsigned long  s,
char **  tmpname,
char **  newname 
)

Definition at line 608 of file imapd.c.

{
       char   *p;
       char   uniqbuf[80];
       static unsigned uniqcnt=0;
       FILE   *fp;
       struct maildir_tmpcreate_info createInfo;

       sprintf(uniqbuf, "%u", uniqcnt++);

       maildir_tmpcreate_init(&createInfo);
       createInfo.openmode=0666;
       createInfo.maildir=mailbox;
       createInfo.uniq=uniqbuf;
       createInfo.msgsize=s;
       createInfo.hostname=getenv("HOSTNAME");
       createInfo.doordie=1;

       if ((fp=maildir_tmpcreate_fp(&createInfo)) == NULL)
              return NULL;

       *tmpname=createInfo.tmpname;
       *newname=createInfo.newname;

       createInfo.tmpname=NULL;
       createInfo.newname=NULL;
       maildir_tmpcreate_free(&createInfo);

       strcpy(uniqbuf, MDIRSEP "2,");
       append_flags(uniqbuf, flags);

       /* Ok, this message will really go to cur, not new */

       p=malloc(strlen(*newname)+strlen(uniqbuf)+1);
       if (!p)       write_error_exit(0);
       strcpy(p, *newname);
       memcpy(strrchr(p, '/')-3, "cur", 3);      /* HACK OF THE MILLENIA */
       strcat(p, uniqbuf);
       free(*newname);
       *newname=p;
       return fp;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int maildirsize_read ( const char *  ,
int *  ,
off_t *  ,
unsigned *  ,
unsigned *  ,
struct stat  
)
int main ( int  argc,
char **  argv 
)

Definition at line 6296 of file imapd.c.

{
       const char *ip;
       const char *p;
       const char *tag;
       const char *port;
       mode_t oldumask;

#ifdef HAVE_SETVBUF_IOLBF
       setvbuf(stderr, NULL, _IOLBF, BUFSIZ);
#endif
       time(&start_time);
       if (argc > 1 && strcmp(argv[1], "--version") == 0)
       {
              printf("%s\n", PROGRAMVERSION);
              exit(0);
       }

       if ((tag=getenv("IMAPLOGINTAG")) != 0)
       {
              if (getenv("AUTHENTICATED") == NULL)
              {
                     printf("* BYE AUTHENTICATED environment variable not set.\r\n");
                     fflush(stdout);
                     exit(0);
              }
       }
       else
       {
              const char *p;

              putenv("TCPREMOTEIP=127.0.0.1");
              putenv("TCPREMOTEPORT=0");

              p=getenv("AUTHENTICATED");
              if (!p || !*p)
              {
                     struct passwd *pw=getpwuid(getuid());
                     char *me;

                     if (!pw)
                     {
                            fprintf(stderr,
                                   "ERR: uid %lu not found in passwd file\n",
                                   (unsigned long)getuid());
                            exit(1);
                     }

                     me=malloc(sizeof("AUTHENTICATED=")+strlen(pw->pw_name));
                     if (!me)
                            write_error_exit(0);

                     strcat(strcpy(me, "AUTHENTICATED="), pw->pw_name);
                     putenv(me);
              }
       }

#if HAVE_SETLOCALE
       setlocale(LC_CTYPE, "C");
#endif

       ip=getenv("TCPREMOTEIP");
       if (!ip || !*ip)     exit(0);

       port=getenv("TCPREMOTEPORT");
       if (!port || !*port) exit(0);

       protocol=getenv("PROTOCOL");

       if (!protocol || !*protocol)
              protocol="IMAP";

       putenv("IMAP_STARTTLS=NO"); /* No longer grok STARTTLS */

       /* We use select() with a timeout, so use non-blocking filedescs */

       if (fcntl(0, F_SETFL, O_NONBLOCK) ||
           fcntl(1, F_SETFL, O_NONBLOCK))
       {
              perror("fcntl");
              exit(1);
       }

       {
       struct stat   buf;

              if ( stat(".", &buf) < 0 || buf.st_mode & S_ISVTX)
              {
                     fprintf(stderr, "INFO: LOCKED, user=%s, ip=[%s], port=[%s]\n",
                            getenv("AUTHENTICATED"), ip, port);

                     if (is_smap())
                            writes("-ERR ");
                     else
                            writes("* BYE ");

                     writes("Your account is temporarily unavailable (+t bit set on home directory).\r\n");
                     writeflush();
                     exit(0);
              }
       }

       if (argc > 1)
              p=argv[1];
       else
              p=getenv("MAILDIR");

       if (!p)
              p="./Maildir";
#if 0
       imapscanpath=getimapscanpath(argv[0]);
#endif
       if (chdir(p))
       {
              fprintf(stderr, "chdir %s: %s\n", p, strerror(errno));
              write_error_exit(strerror(errno));
       }
       maildir_loginexec();

       if (auth_getoptionenvint("disableshared"))
       {
              maildir_acl_disabled=1;
              maildir_newshared_disabled=1;
       }

       /* Remember my device/inode */

       {
              struct stat   buf;

              if ( stat(".", &buf) < 0)
                     write_error_exit("Cannot stat current directory");

              homedir_dev=buf.st_dev;
              homedir_ino=buf.st_ino;

              errno=0;

              p=getenv("IMAP_MAILBOX_SANITY_CHECK");

              if (!p || !*p) p="1";

              if (atoi(p))
              {
                     if ( buf.st_uid != geteuid() ||
                          buf.st_gid != getegid())
                            write_error_exit("Account's mailbox directory is not owned by the correct uid or gid");
              }
       }

       p=getenv("HOSTNAME");
       if (!p)
              dogethostname();

       if ((p=getenv("IMAP_TRASHFOLDERNAME")) != 0 && *p) 
       {
              trash = strdup(p);
              dot_trash = malloc(strlen(trash) + 2);
              dot_trash[0] = '.';
              strcpy(&dot_trash[1], trash); 
       }
       
#if 0
       mdcreate("." DRAFTS);
#endif

       if ((p=getenv("IMAPDEBUGFILE")) != 0 && *p &&
           access(p, 0) == 0)
       {
              oldumask = umask(027);
              debugfile=fopen(p, "a");
              umask(oldumask);
              if (debugfile==NULL)
                     write_error_exit(0);
       }
       initcapability();

       emptytrash();
       signal(SIGPIPE, SIG_IGN);

       libmail_kwVerbotten=KEYWORD_IMAPVERBOTTEN;
       libmail_kwCaseSensitive=0;

       if (!keywords())
              libmail_kwEnabled=0;

       maildir_info_munge_complex((p=getenv("IMAP_SHAREDMUNGENAMES")) &&
                               atoi(p));

#if SMAP
       if (is_smap())
       {
              if (chk_clock_skew())
              {
                     writes("-ERR Clock skew detected. Check the clock on the file server\r\n");
                     writeflush();
                     exit(0);
              }

              writes("+OK SMAP1 LOGIN Ok.\n");

              smapflag=1;

              libmail_kwVerbotten=KEYWORD_SMAPVERBOTTEN;
              libmail_kwCaseSensitive=1;

              chkdisabled(ip, port);
              smap();
              logoutmsg();
              emptytrash();
              return (0);
       }
#endif

       if (chk_clock_skew())
       {
              writes("* BYE Clock skew detected. Check the clock on the file server\r\n");
              writeflush();
              exit(0);
       }

       {
              struct maildirwatch *w;

              if ((w=maildirwatch_alloc(".")) == NULL)
              {
                     writes("* OK [ALERT] Filesystem notification initialization error -- contact your mail administrator (check for configuration errors with the FAM/Gamin library)\r\n");
              }
              else
              {
                     maildirwatch_free(w);
              }
       }

       if ((tag=getenv("IMAPLOGINTAG")) != 0)
       {
              writes(tag);
              writes(" OK LOGIN Ok.\r\n");
       }
       else
              writes("* PREAUTH Ready.\r\n");
       writeflush();
       chkdisabled(ip, port);
       imapscan_init(&current_maildir_info);
       mainloop();
       fetch_free_cached();
       bye();
       return (0);
}

Here is the call graph for this function:

void mainloop ( )

Definition at line 102 of file mainloop.c.

{
       int noerril = 0;

       signal(SIGTERM, sigexit);
       signal(SIGHUP, sigexit);
       signal(SIGINT, sigexit);

       for (;;)
       {
       char   tag[IT_MAX_ATOM_SIZE+1];
       struct imaptoken *curtoken;

              read_timeout(30 * 60);
              curtoken=nexttoken_nouc();
              tag[0]=0;
              if (curtoken->tokentype == IT_ATOM ||
                     curtoken->tokentype == IT_NUMBER)
              {
              int    rc;

                     if (strlen(tag)+strlen(curtoken->tokenbuf) > IT_MAX_ATOM_SIZE)
                            write_error_exit("max atom size too small");
                            
                     strncat(tag, curtoken->tokenbuf, IT_MAX_ATOM_SIZE);
                     rc=do_imap_command(tag);

                     if (rc == 0)
                     {
                            noerril = 0;
                            writeflush();
                            read_eol();
                            continue;
                     }
                     if (rc == -2)
                            continue;
              }

              noerril++;
              if (noerril > 9)
              {
                     errno = 0;
                     write_error_exit("TOO MANY CONSECUTIVE PROTOCOL VIOLATIONS");
              }
              read_eol();
              cmdfail(tag[0] ? tag:"*",
                     "Error in IMAP command received by server.\r\n");
              writeflush();
       }
}

Here is the caller graph for this function:

static int markmessages ( unsigned long  n,
int  i,
void *  dummy 
) [static]

Definition at line 2075 of file imapd.c.

{
       --n;
       current_maildir_info.msgs[n].storeflag=1;
       return 0;
}

Here is the caller graph for this function:

int mdcreate ( const char *  mailbox)

Definition at line 893 of file imapd.c.

{
       trap_signals();
       if (maildir_make(mailbox, 0700, 0700, 1) < 0)
       {
              if (release_signals())      _exit(0);
              return (-1);
       }

       if (release_signals())      _exit(0);
       return (0);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int mddelete ( const char *  s)

Definition at line 883 of file imapd.c.

{
int    rc;

       trap_signals();
       rc=maildir_del(s);
       if (release_signals())      _exit(0);
       return (rc);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void myrights ( ) [static]

Definition at line 2524 of file imapd.c.

{
       writes("* OK [MYRIGHTS \"");
       writeacl(current_mailbox_acl);
       writes("\"] ACL\r\n");
}

Here is the call graph for this function:

Here is the caller graph for this function:

static FILE* newsubscribefile ( char **  tmpname) [static]

Definition at line 1696 of file imapd.c.

{
       char    uniqbuf[80];
       static  unsigned tmpuniqcnt=0;
       FILE   *fp;
       struct maildir_tmpcreate_info createInfo;

       maildir_tmpcreate_init(&createInfo);

       sprintf(uniqbuf, "imapsubscribe%u", tmpuniqcnt++);

       createInfo.uniq=uniqbuf;
       createInfo.hostname=getenv("HOSTNAME");
       createInfo.doordie=1;

       if ((fp=maildir_tmpcreate_fp(&createInfo)) == NULL)
              write_error_exit(0);

       *tmpname=createInfo.tmpname;
       createInfo.tmpname=NULL;
       maildir_tmpcreate_free(&createInfo);

       return (fp);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int noopAddKeyword ( struct libmail_keywordEntry ke,
void *  vp 
) [static]

Definition at line 1125 of file imapd.c.

{
       struct noopKeywordUpdateInfo *kui=
              (struct noopKeywordUpdateInfo *)vp;

       libmail_kwmSetName(kui->keywordList, kui->messagePtr, keywordName(ke));
       /*
       ** ke originates from a different keyword namespace, so must use
       ** its name.
       */
       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static char* parse_mailbox_error ( const char *  tag,
struct imaptoken curtoken,
int  ok_hierarchy,
int  autosubscribe 
) [static]

Definition at line 553 of file imapd.c.

{
char   *mailbox;

       if (curtoken->tokentype != IT_NUMBER &&
              curtoken->tokentype != IT_ATOM &&
              curtoken->tokentype != IT_QUOTED_STRING)
       {
              mailbox=0;
       }
       else
       {
              if (ok_hierarchy && (mailbox=strrchr(curtoken->tokenbuf,
                     HIERCH)) && mailbox[1] == 0)
                            *mailbox=0;

              mailbox=decode_valid_mailbox(curtoken->tokenbuf,
                     autosubscribe);
       }

       if ( mailbox == 0)
       {
              writes(tag);
              writes(" NO Mailbox does not exist, or must be subscribed to.\r\n");
              return (0);
       }
       return (mailbox);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void quotainfo_out ( const char *  qroot)

Definition at line 170 of file imapd.c.

{
       char    quotabuf[QUOTABUFSIZE];
       char   qresult[200]="";
       char   qbuf[200];
       
       if ((maildir_getquota(".", quotabuf) == 0) && (strcmp(qroot,"ROOT") == 0))
       {
              struct maildirsize quotainfo;

              if (maildir_openquotafile(&quotainfo, ".") == 0)
                     maildir_closequotafile(&quotainfo);
              else
                     quotainfo.quota.nbytes=quotainfo.size.nbytes=
                            quotainfo.quota.nmessages=
                            quotainfo.size.nmessages=0;
                     
              if (quotainfo.quota.nbytes > 0)
              {
                     sprintf(qbuf,"STORAGE %ld %ld",
                            (long)((quotainfo.size.nbytes+1023)/1024),
                            (long)((quotainfo.quota.nbytes+1023)/1024));
                     strcat(qresult,qbuf);
              }
              if (quotainfo.quota.nmessages > 0)
              {
                     sprintf(qbuf,"MESSAGE %d %d",
                            quotainfo.size.nmessages,
                            quotainfo.quota.nmessages);
                     if (strcmp(qresult,"")!=0) strcat(qresult," ");
                     strcat(qresult,qbuf);
              }
       }

       writes("* ");
       writes("QUOTA \"");
       writes(qroot);
       writes("\"");
       if (strcmp(qresult,"")!=0)
       {
              writes(" (");
              writes(qresult);
              writes(")");
       };
       writes("\r\n");
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void rename_callback ( const char *  old_path,
const char *  new_path 
) [static]

Definition at line 2211 of file imapd.c.

{
struct imapscaninfo minfo;

       char *p=malloc(strlen(new_path)+sizeof("/" IMAPDB));

       if (!p)
              write_error_exit(0);

       strcat(strcpy(p, new_path), "/" IMAPDB);
       unlink(p);
       free(p);
       imapscan_init(&minfo);
       imapscan_maildir(&minfo, new_path, 0,0, NULL);
       imapscan_free(&minfo);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void rfc2045_error ( const char *  p)

Definition at line 140 of file imapd.c.

{
       if (write(2, p, strlen(p)) < 0)
              _exit(1);
       _exit(0);
}
time_t rfc822_parsedt ( const char *  )

Definition at line 125 of file rfc822_parsedt.c.

{
unsigned day=0, mon=0, year;
int secs;
int offset;
time_t t;
unsigned y;

       /* Ignore day of the week.  Tolerate "Tue, 25 Feb 1997 ... "
       ** without the comma.  Tolerate "Feb 25 1997 ...".
       */

       while (!day || !mon)
       {
              if (!*rfcdt)  return (0);
              if (my_isalpha(*rfcdt))
              {
                     if (mon)      return (0);
                     mon=parsekey(&rfcdt, mnames);
                     if (!mon)
                            while (*rfcdt && my_isalpha(*rfcdt))
                                   ++rfcdt;
                     continue;
              }

              if (my_isdigit(*rfcdt))
              {
                     if (day)      return (0);
                     day=parsedig(&rfcdt);
                     if (!day)     return (0);
                     continue;
              }
              ++rfcdt;
       }

       while (*rfcdt && my_isspace(*rfcdt))
              ++rfcdt;
       if (!my_isdigit(*rfcdt))    return (0);
       year=parsedig(&rfcdt);
       if (year < 70)       year += 2000;
       if (year < 100)      year += 1900;

       while (*rfcdt && my_isspace(*rfcdt))
              ++rfcdt;

       if (day == 0 || mon == 0 || mon > 12 || day > mdays(mon,year))
              return (0);

       secs=parsetime(&rfcdt);
       if (secs < 0) return (0);

       offset=0;

       /* RFC822 sez no parenthesis, but I've seen (EST) */

       while ( *rfcdt )
       {
              if (my_isalnum(*rfcdt) || *rfcdt == '+' || *rfcdt == '-')
                     break;
              ++rfcdt;
       }

       if (my_isalpha((int)(unsigned char)*rfcdt))
       {
       int    n=parsekey(&rfcdt, zonenames);

              if (n > 0)    offset= zoneoffset[n-1];
       }
       else
       {
       int    sign=1;
       unsigned n;

              switch (*rfcdt)      {
              case '-':
                     sign= -1;
              case '+':
                     ++rfcdt;
              }

              if (my_isdigit(*rfcdt))
              {
                     n=parsedig(&rfcdt);
                     if (n > 2359 || (n % 100) > 59)    n=0;
                     offset = sign * ( (n % 100) * 60 + n / 100 * 60 * 60);
              }
       }

       if (year < 1970)     return (0);
       if (year > 9999)     return (0);

       t=0;
       for (y=1970; y<year; y++)
       {
              if ( leap(y) )
              {
                     if (year-y >= 4)
                     {
                            y += 3;
                            t += ( 365*3+366 ) * 24 * 60 * 60;
                            continue;
                     }
                     t += 24 * 60 * 60;
              }
              t += 365 * 24 * 60 * 60;
       }

       for (y=1; y < mon; y++)
              t += mdays(y, year) * 24 * 60 * 60;

       return ( t + (day-1) * 24 * 60 * 60 + secs - offset );
}

Here is the caller graph for this function:

void set_time ( const char *  tmpname,
time_t  timestamp 
)

Definition at line 652 of file imapd.c.

{
#if    HAVE_UTIME
       if (timestamp)
       {
       struct utimbuf ub;

              ub.actime=ub.modtime=timestamp;
              utime(tmpname, &ub);
       }
#else
#if    HAVE_UTIMES
       if (timestamp)
       {
       struct timeval       tv;

              tv.tv_sec=timestamp;
              tv.tv_usec=0;
              utimes(tmpname, &tv);
       }
#endif
#endif
}

Here is the caller graph for this function:

void smap ( )

Definition at line 3201 of file smap.c.

{
       char buffer[8192];
       char *ptr;
       struct imapflags add_flags;
       int in_add=0;
       char *add_from=NULL;
       char *add_folder=NULL;
       time_t add_internaldate=0;
       char *add_notify=NULL;
       unsigned add_rcpt_count=0;
       struct libmail_kwMessage *addKeywords=NULL;

       struct add_rcptlist *add_rcpt_list=NULL;

       char rights_buf[40];

       imapscan_init(&current_maildir_info);
       memset(&add_flags, 0, sizeof(add_flags));

#define GETFOLDER(acl) ( strcpy(rights_buf, (acl)), \
                     getAccessToFolder(&ptr, rights_buf))

       for (;;)
       {
              char *p;

              writeflush();
              read_timeout(30 * 60);
              smap_readline(buffer, sizeof(buffer));

              ptr=buffer;

              p=getword(&ptr);
              up(p);

              if (strcmp(p, "ADD") == 0)
              {
                     char **argvec;
                     const char *okmsg="So far, so good...";
                     int err_sent=0;

                     in_add=1;
                     while (*(p=getword(&ptr)))
                     {
                            char *q=strchr(p, '=');

                            if (q)
                                   *q++=0;
                            up(p);

                            if (strcmp(p, "FOLDER") == 0)
                            {
                                   if (add_folder)
                                          free(add_folder);

                                   add_folder=
                                          GETFOLDER(ACL_INSERT
                                                   ACL_DELETEMSGS
                                                   ACL_SEEN
                                                   ACL_WRITE);
                                   if (!add_folder)
                                   {
                                          writes("-ERR Invalid folder: ");
                                          writes(strerror(errno));
                                          writes("\n");
                                          break;
                                   }

                                   if (strchr(rights_buf,
                                             ACL_INSERT[0])
                                       == NULL)
                                   {
                                          accessdenied(ACL_INSERT);
                                          free(add_folder);
                                          add_folder=NULL;
                                          break;
                                   }

                                   okmsg="Will add to this folder";
                            }

                            if (strcmp(p, "MAILFROM") == 0 && q)
                            {
                                   if (add_from)
                                          free(add_from);
                                   if ((add_from=strdup(q)) == NULL)
                                   {
                                          writes("-ERR ");
                                          writes(strerror(errno));
                                          writes("\n");
                                          break;
                                   }
                                   okmsg="MAIL FROM set";
                            }

                            if (strcmp(p, "NOTIFY") == 0 && q)
                            {
                                   if (add_notify)
                                          free(add_notify);
                                   if ((add_notify=strdup(q)) == NULL)
                                   {
                                          writes("-ERR ");
                                          writes(strerror(errno));
                                          writes("\n");
                                          break;
                                   }
                                   okmsg="NOTIFY set";
                            }

                            if (strcmp(p, "RCPTTO") == 0 && q)
                            {
                                   struct add_rcptlist *rcpt=
                                          malloc(sizeof(struct
                                                       add_rcptlist));

                                   if (rcpt == NULL ||
                                       (rcpt->rcptto=strdup(q)) == NULL)
                                   {
                                          if (rcpt)
                                                 free(rcpt);
                                          writes("-ERR ");
                                          writes(strerror(errno));
                                          writes("\n");
                                          break;
                                   }
                                   rcpt->next=add_rcpt_list;
                                   add_rcpt_list=rcpt;
                                   ++add_rcpt_count;
                                   okmsg="RCPT TO set";
                            }

                            if (strcmp(p, "FLAGS") == 0 && q)
                            {
                                   memset(&add_flags, 0,
                                          sizeof(add_flags));
                                   *--q='=';
                                   parseflags(q, &add_flags);

                                   if (strchr(rights_buf,
                                             ACL_SEEN[0])
                                       == NULL)
                                          add_flags.seen=0;
                                   if (strchr(rights_buf,
                                             ACL_DELETEMSGS[0])
                                       == NULL)
                                          add_flags.deleted=0;
                                   if (strchr(rights_buf,
                                             ACL_WRITE[0])
                                       == NULL)
                                          add_flags.answered=
                                                 add_flags.flagged=
                                                 add_flags.drafts=0;

                                   okmsg="FLAGS set";
                            }

                            if (strcmp(p, "KEYWORDS") == 0 && q &&
                                keywords() && strchr(rights_buf,
                                                  ACL_WRITE[0]))
                            {
                                   if (addKeywords)
                                          libmail_kwmDestroy(addKeywords);

                                   addKeywords=libmail_kwmCreate();

                                   if (addKeywords == NULL)
                                   {
                                          write_error_exit(0);
                                   }

                                   *--q='=';
                                   parsekeywords(q, &addKeywords);
                                   okmsg="KEYWORDS set";
                            }

                            if (strcmp(p, "INTERNALDATE") == 0 && q)
                            {
                                   add_internaldate=rfc822_parsedt(q);

                                   if (add_internaldate)
                                          okmsg="INTERNALDATE set";
                            }

                            if (p[0] == '{')
                            {
                                   char *tmpname, *newname;
                                   char *s;
                                   char *tmpKeywords=NULL;
                                   char *newKeywords=NULL;
                                   FILE *fp;
                                   unsigned long n;

                                   fp=maildir_mkfilename(add_folder
                                                       ?add_folder
                                                       :".",
                                                       &add_flags,
                                                       0,
                                                       &tmpname,
                                                       &newname);

                                   if (!fp)
                                   {
                                          writes("-ERR ");
                                          writes(strerror(errno));
                                          writes("\n");
                                          break;
                                   }

                                   fixnewfilename(newname);

                                   current_temp_fd=fileno(fp);
                                   current_temp_fn=tmpname;

                                   n=add_msg(fp, p+1, buffer,
                                            sizeof(buffer));

                                   if (n)
                                   {
                                          s=maildir_requota(newname, n);

                                          if (!s)
                                                 n=0;
                                          else
                                          {
                                                 free(newname);
                                                 newname=s;
                                          }
                                   }

                                   current_temp_fd= -1;
                                   current_temp_fn= NULL;

                                   if (n > 0 && add_folder &&
                                       maildirquota_countfolder(add_folder)
                                       && maildirquota_countfile(newname))
                                   {
                                          struct maildirsize quotainfo;

                                          if (maildir_quota_add_start(add_folder, &quotainfo, n, 1,
                                                                   getenv("MAILDIRQUOTA")))
                                          {
                                                 errno=ENOSPC;
                                                 n=0;
                                          }
                                          else
                                                 maildir_quota_add_end(&quotainfo, n, 1);
                                   }

                                   fclose(fp);

                                   chmod(tmpname, 0600);

                                   if (add_folder && n && addKeywords)
                                   {
                                          if (maildir_kwSave(add_folder,
                                                           strrchr(newname, '/')+1,
                                                           addKeywords,
                                                           &tmpKeywords,
                                                           &newKeywords,
                                                           0))
                                          {
                                                 tmpKeywords=NULL;
                                                 newKeywords=NULL;
                                                 n=0;
                                                 perror("maildir_kwSave");
                                          }
                                   }

                                   argvec=NULL;

                                   if (add_rcpt_count > 0 && n)
                                   {
                                          argvec=malloc(sizeof(char *)
                                                       * (add_rcpt_count
                                                         +10));

                                          if (!argvec)
                                                 n=0;
                                   }

                                   if (argvec)
                                   {
                                          int i=1;
                                          struct add_rcptlist *l;

                                          argvec[i++]="-oi";

                                          argvec[i++]="-f";
                                          argvec[i++]=add_from
                                                 ? add_from:
                                                 (char *)
                                                 defaultSendFrom();

                                          if (add_notify)
                                          {
                                                 argvec[i++]="-N";
                                                 argvec[i++]=add_notify;
                                          }

                                          for (l=add_rcpt_list; l;
                                               l=l->next)
                                          {
                                                 argvec[i++]=l->rcptto;
                                          }
                                          argvec[i]=0;

                                          i=imapd_sendmsg(tmpname, argvec,
                                                        &senderr);
                                          free(argvec);
                                          if (i)
                                          {
                                                 n=0;
                                                 err_sent=1;
                                          }
                                   }

                                   if (tmpKeywords)
                                   {
                                          rename(tmpKeywords,
                                                 newKeywords);
                                          free(tmpKeywords);
                                          free(newKeywords);
                                   }

                                   if (add_folder && n)
                                   {
                                          if (maildir_movetmpnew(tmpname,
                                                               newname)
                                              )
                                                 n=0;
                                          else
                                          {
                                                 if (add_internaldate)
                                                        set_time(newname,
                                                                add_internaldate);
                                                 adduid(newname);
                                          }
                                   }

                                   if (n == 0)
                                   {
                                          unlink(tmpname);
                                          free(tmpname);
                                          free(newname);
                                          if (!err_sent)
                                          {
                                                 writes("-ERR ");
                                                 writes(strerror(errno));
                                                 writes("\n");
                                          }
                                          break;
                                   }

                                   unlink(tmpname);

                                   free(tmpname);
                                   free(newname);
                                   okmsg="Message saved";
                                   p=NULL;
                                   break;
                            }
                     }

                     if (p && *p)
                            continue; /* Error inside the loop */

                     writes("+OK ");
                     writes(okmsg);
                     writes("\n");

                     if (p)
                            continue;
              }

              if (in_add)
              {
                     struct add_rcptlist *l;

                     while ((l=add_rcpt_list) != NULL)
                     {
                            add_rcpt_list=l->next;
                            free(l->rcptto);
                            free(l);
                     }
                     memset(&add_flags, 0, sizeof(add_flags));
                     if (add_from)
                            free(add_from);
                     if (add_folder)
                            free(add_folder);
                     if (add_notify)
                            free(add_notify);

                     if (addKeywords)
                            libmail_kwmDestroy(addKeywords);

                     in_add=0;
                     add_from=NULL;
                     add_folder=NULL;
                     add_internaldate=0;
                     add_notify=NULL;
                     addKeywords=NULL;
                     add_rcpt_count=0;
                     if (!p)
                            continue; /* Just added a message */
              }

              if (strcmp(p, "LOGOUT") == 0)
                     break;

              if (strcmp(p, "RSET") == 0)
              {
                     writes("+OK Reset\n");
                     continue;
              }

              if (strcmp(p, "GETACL") == 0 ||
                  strcmp(p, "ACL") == 0)
              {
                     char **fn=fn_fromwords(&ptr);
                     struct maildir_info minfo;
                     maildir_aclt_list aclt_list;
                     char *q;
                     int cnt;

                     if (!fn)
                     {
                            writes("-ERR Invalid folder: ");
                            writes(strerror(errno));
                            writes("\n");
                            continue;
                     }

                     if (maildir_info_smap_find(&minfo, fn,
                                             getenv("AUTHENTICATED"))
                         < 0)
                     {
                            maildir_smapfn_free(fn);
                            writes("-ERR Invalid folder: ");
                            writes(strerror(errno));
                            writes("\n");
                            continue;
                     }

                     if (read_acls(&aclt_list, &minfo) < 0)
                     {
                            maildir_info_destroy(&minfo);
                            maildir_smapfn_free(fn);
                            writes("-ERR Unable to read"
                                   " existing ACLS: ");
                            writes(strerror(errno));
                            writes("\n");
                            continue;
                     }

                     q=compute_myrights(&aclt_list,
                                      minfo.owner);

                     if (!q ||
                         strcmp(p, "ACL") ?
                         !strchr(q, ACL_ADMINISTER[0])
                         :
                         !maildir_acl_canlistrights(q)
                         )
                     {
                            if (q) free(q);
                            maildir_aclt_list_destroy(&aclt_list);
                            maildir_info_destroy(&minfo);
                            maildir_smapfn_free(fn);
                            accessdenied(ACL_ADMINISTER);
                            continue;
                     }
                     if (strcmp(p, "ACL") == 0)
                     {
                            writes("* ACL ");
                            smapword(q);
                            writes("\n");
                            free(q);
                     }
                     else
                     {
                            free(q);
                            cnt=0;
                            maildir_aclt_list_enum(&aclt_list,
                                                 getacl, &cnt);
                            if (cnt)
                                   writes("\n");
                     }
                     maildir_aclt_list_destroy(&aclt_list);
                     maildir_info_destroy(&minfo);
                     maildir_smapfn_free(fn);
                     writes("+OK ACLs retrieved\n");
                     continue;
              }

              if (strcmp(p, "SETACL") == 0 ||
                  strcmp(p, "DELETEACL") == 0)
              {
                     char **fn=fn_fromwords(&ptr);
                     struct setacl_info sainfo;

                     if (!fn)
                     {
                            writes("-ERR Invalid folder: ");
                            writes(strerror(errno));
                            writes("\n");
                            continue;
                     }

                     if (maildir_info_smap_find(&sainfo.minfo,
                                             fn, getenv("AUTHENTICATED"))
                         < 0)
                     {
                            maildir_smapfn_free(fn);
                            writes("-ERR Invalid folder: ");
                            writes(strerror(errno));
                            writes("\n");
                            continue;
                     }


                     sainfo.ptr= &ptr;

                     acl_lock(sainfo.minfo.homedir,
                             *p == 'S' ? setacl:deleteacl,
                             &sainfo);

                     maildir_smapfn_free(fn);
                     maildir_info_destroy(&sainfo.minfo);
                     continue;
              }

              if (strcmp(p, "LIST") == 0)
              {
                     struct list_hier *hier=NULL;

                     listcmd(&hier, &hier, &ptr);
                     continue;
              }

              if (strcmp(p, "STATUS") == 0)
              {
                     char *t;
                     struct imapscaninfo other_info, *loaded_infoptr,
                            *infoptr;
                     unsigned long n, i;

                     getword(&ptr);

                     t=GETFOLDER(ACL_LOOKUP);

                     if (!t)
                     {
                            writes("-ERR Cannot read folder status: ");
                            writes(strerror(errno));
                            writes("\n");
                            continue;
                     }

                     if (strchr(rights_buf, ACL_LOOKUP[0]) == NULL)
                     {
                            accessdenied(ACL_LOOKUP);
                            continue;
                     }

                     if (current_mailbox &&
                         strcmp(current_mailbox, t) == 0)
                     {
                            loaded_infoptr=0;
                            infoptr= &current_maildir_info;
                     }
                     else
                     {
                            loaded_infoptr= &other_info;
                            infoptr=loaded_infoptr;

                            imapscan_init(loaded_infoptr);

                            if (imapscan_maildir(infoptr, t, 1, 1, NULL))
                            {
                                   writes("-ERR Cannot read"
                                          " folder status: ");
                                   writes(strerror(errno));
                                   writes("\n");
                                   continue;
                            }
                     }

                     writes("* STATUS EXISTS=");
                     writen(infoptr->nmessages+infoptr->left_unseen);

                     n=infoptr->left_unseen, i;

                     for (i=0; i<infoptr->nmessages; i++)
                     {
                            const char *p=infoptr->msgs[i].filename;

                            p=strrchr(p, MDIRSEP[0]);
                            if (p && strncmp(p, MDIRSEP "2,", 3) == 0 &&
                                strchr(p, 'S'))  continue;
                            ++n;
                     }
                     writes(" UNSEEN=");
                     writen(n);
                     writes("\n+OK Folder status retrieved\n");
                     if (loaded_infoptr)
                            imapscan_free(loaded_infoptr);
                     continue;
              }

              if (strcmp(p, "CREATE") == 0)
              {
                     char *t;

                     strcpy(rights_buf, ACL_CREATE);
                     t=getCreateFolder(&ptr, rights_buf);

                     if (t)
                     {
                            if (mdcreate(t))
                            {
                                   writes("-ERR Cannot create folder: ");
                                   writes(strerror(errno));
                                   writes("\n");
                            }
                            else
                            {
                                   writes("+OK Folder created\n");
                            }
                            free(t);
                     }
                     else
                     {
                            if (rights_buf[0] == 0)
                                   accessdenied(ACL_CREATE);
                            else
                            {
                                   writes("-ERR Cannot create folder: ");
                                   writes(strerror(errno));
                                   writes("\n");
                            }
                     }
                     continue;
              }

              if (strcmp(p, "MKDIR") == 0)
              {
                     char *t;

                     strcpy(rights_buf, ACL_CREATE);
                     t=getCreateFolder(&ptr, rights_buf);

                     if (t)
                     {
                            writes("+OK Folder created\n");
                            free(t);
                     }
                     else if (rights_buf[0] == 0)
                            accessdenied(ACL_CREATE);
                     else
                     {
                            writes("-ERR Cannot create folder: ");
                            writes(strerror(errno));
                            writes("\n");
                     }
                     continue;
              }

              if (strcmp(p, "RMDIR") == 0)
              {
                     char *t;

                     strcpy(rights_buf, ACL_DELETEFOLDER);
                     t=getCreateFolder(&ptr, rights_buf);

                     if (t)
                     {
                            writes("+OK Folder deleted\n");
                            free(t);
                     }
                     else if (rights_buf[0] == 0)
                            accessdenied(ACL_DELETEFOLDER);
                     else
                     {
                            writes("-ERR Cannot create folder: ");
                            writes(strerror(errno));
                            writes("\n");
                     }
                     continue;
              }

              if (strcmp(p, "DELETE") == 0)
              {
                     char **fn;
                     char *t=NULL;

                     fn=fn_fromwords(&ptr);

                     if (fn)
                     {
                            struct maildir_info minfo;

                            if (maildir_info_smap_find(&minfo, fn,
                                                    getenv("AUTHENTICATED")) == 0)
                            {
                                   if (minfo.homedir && minfo.maildir)
                                   {
                                          maildir_aclt_list list;
                                          char *q;

                                          if (strcmp(minfo.maildir,
                                                    INBOX) == 0)
                                          {
                                                 writes("-ERR INBOX may"
                                                        " not be deleted\n");
                                                 maildir_info_destroy(&minfo);
                                                 continue;
                                          }

                                          if (read_acls(&list, &minfo)
                                              < 0)
                                          {
                                                 maildir_info_destroy(&minfo);
                                                 accessdenied(ACL_DELETEFOLDER);
                                                 continue;
                                          }

                                          q=compute_myrights(&list,
                                                           minfo.owner
                                                           );

                                          if (!q ||
                                              strchr(q,
                                                    ACL_DELETEFOLDER[0])
                                              == NULL)
                                          {
                                                 if (q)
                                                        free(q);
                                                 maildir_info_destroy(&minfo);
                                                 accessdenied(ACL_DELETEFOLDER);
                                                 continue;
                                          }
                                          free(q);
                                          maildir_aclt_list_destroy(&list);
                                          t=maildir_name2dir(minfo.homedir,
                                                           minfo.maildir);
                                   }
                                   maildir_info_destroy(&minfo);
                            }
                     }

                     if (t && current_mailbox &&
                         strcmp(t, current_mailbox) == 0)
                     {
                            writes("-ERR Cannot DELETE currently open folder.\n");
                            free(t);
                            continue;
                     }


                     if (t)
                     {
                            if (mddelete(t) == 0)
                            {
                                   maildir_quota_recalculate(".");
                                   writes("+OK Folder deleted");
                            }
                            else
                            {
                                   writes("-ERR Cannot delete folder: ");
                                   writes(strerror(errno));
                            }
                            writes("\n");
                            free(t);

                     }
                     else
                     {
                            if (t)
                            {
                                   free(t);
                                   errno=EINVAL;
                            }

                            writes("-ERR Unable to delete folder: ");
                            writes(strerror(errno));
                            writes("\n");
                     }
                     continue;
              }

              if (strcmp(p, "RENAME") == 0)
              {
                     struct maildir_info msrc, mdst;
                     char **fnsrc, **fndst;
                     size_t i;
                     char *save;
                     const char *errmsg;

                     if ((fnsrc=fn_fromwords(&ptr)) == NULL)
                     {
                            writes("-ERR ");
                            writes(strerror(errno));
                            writes("\n");
                            continue;
                     }

                     if ((fndst=fn_fromwords(&ptr)) == NULL)
                     {
                            maildir_smapfn_free(fnsrc);
                            writes("-ERR ");
                            writes(strerror(errno));
                            writes("\n");
                            continue;
                     }

                     for (i=0; fndst[i]; i++)
                            ;

                     if (i == 0)
                     {
                            maildir_smapfn_free(fnsrc);
                            maildir_smapfn_free(fndst);
                            writes("-ERR Invalid destination folder name\n");
                            continue;
                     }

                     if (checkacl(fnsrc, &msrc, ACL_DELETEFOLDER))
                     {
                            maildir_smapfn_free(fnsrc);
                            maildir_smapfn_free(fndst);
                            accessdenied(ACL_DELETEFOLDER);
                            continue;
                     }
                     save=fndst[--i];
                     fndst[i]=NULL;

                     if (checkacl(fndst, &mdst, ACL_CREATE))
                     {
                            fndst[i]=save;
                            maildir_smapfn_free(fnsrc);
                            maildir_smapfn_free(fndst);
                            maildir_info_destroy(&msrc);
                            accessdenied(ACL_CREATE);
                            continue;
                     }

                     fndst[i]=save;

                     maildir_info_destroy(&mdst);

                     if (maildir_info_smap_find(&mdst, fndst,
                                             getenv("AUTHENTICATED")) < 0)
                     {
                            maildir_smapf