summaryrefslogtreecommitdiffstats
path: root/imap/imapd.c
diff options
context:
space:
mode:
Diffstat (limited to 'imap/imapd.c')
-rw-r--r--imap/imapd.c533
1 files changed, 426 insertions, 107 deletions
diff --git a/imap/imapd.c b/imap/imapd.c
index fca7149..78a689c 100644
--- a/imap/imapd.c
+++ b/imap/imapd.c
@@ -1,5 +1,5 @@
/*
-** Copyright 1998 - 2011 Double Precision, Inc.
+** Copyright 1998 - 2018 Double Precision, Inc.
** See COPYING for distribution information.
*/
@@ -85,6 +85,7 @@
#include "maildir/maildirinfo.h"
#include "maildir/loginexec.h"
#include "rfc822/rfc822.h"
+#include "rfc2045/rfc2045.h"
#include <courier-unicode.h>
#include "maildir/maildirkeywords.h"
@@ -140,6 +141,8 @@ char *current_mailbox_acl;
dev_t homedir_dev;
ino_t homedir_ino;
+int enabled_utf8=0;
+
void rfc2045_error(const char *p)
{
if (write(2, p, strlen(p)) < 0)
@@ -147,6 +150,19 @@ void rfc2045_error(const char *p)
_exit(0);
}
+void writemailbox(const char *mailbox)
+{
+ char *encoded=imap_filename_to_foldername(enabled_utf8, mailbox);
+
+ if (!encoded)
+ {
+ fprintf(stderr, "ERR: imap_filename_to_foldername(%s) failed\n",
+ mailbox);
+ exit(1);
+ }
+ writeqs(encoded);
+ free(encoded);
+}
extern int maildirsize_read(const char *,int *,off_t *,unsigned *,unsigned *,struct stat *);
@@ -330,10 +346,10 @@ int is_reserved_name(const char *name)
return 0;
}
-char *decode_valid_mailbox(const char *p, int autosubscribe)
+static char *decode_valid_mailbox_utf8(const char *p, int autosubscribe)
{
struct maildir_info mi;
- char *q, *r;
+ char *r;
if (maildir_info_imap_find(&mi, p, getenv("AUTHENTICATED")) < 0)
{
@@ -342,7 +358,7 @@ char *decode_valid_mailbox(const char *p, int autosubscribe)
if (mi.homedir && mi.maildir)
{
- q=maildir_name2dir(mi.homedir, mi.maildir);
+ char *q=maildir_name2dir(mi.homedir, mi.maildir);
if (q)
{
@@ -403,6 +419,22 @@ char *decode_valid_mailbox(const char *p, int autosubscribe)
return (NULL);
}
+char *decode_valid_mailbox(const char *mailbox, int autosubscribe)
+{
+ char *p=imap_foldername_to_filename(enabled_utf8, mailbox);
+ char *q;
+
+ if (!p)
+ {
+ errno=EINVAL;
+ return NULL;
+ }
+
+ q=decode_valid_mailbox_utf8(p, autosubscribe);
+ free(p);
+ return q;
+}
+
static int decode_date_time(char *p, time_t *tret)
{
unsigned i;
@@ -561,7 +593,7 @@ static char *parse_mailbox_error(const char *tag,
** a real folder (such as this one).
*/
- int autosubscribe) /* Really DUMP clients that do a LIST,
+ int autosubscribe) /* Really DUMB clients that do a LIST,
** and don't bother to check if a folder is
** subscribed to, or not (Pine)
*/
@@ -572,17 +604,17 @@ char *mailbox;
curtoken->tokentype != IT_ATOM &&
curtoken->tokentype != IT_QUOTED_STRING)
{
- mailbox=0;
+ writes(tag);
+ writes(" BAD Invalid command\r\n");
+ return (0);
}
- else
- {
- if (ok_hierarchy && (mailbox=strrchr(curtoken->tokenbuf,
- HIERCH)) && mailbox[1] == 0)
- *mailbox=0;
- mailbox=decode_valid_mailbox(curtoken->tokenbuf,
- autosubscribe);
- }
+ if (ok_hierarchy && (mailbox=strrchr(curtoken->tokenbuf,
+ HIERCH)) && mailbox[1] == 0)
+ *mailbox=0;
+
+ mailbox=decode_valid_mailbox(curtoken->tokenbuf,
+ autosubscribe);
if ( mailbox == 0)
{
@@ -680,19 +712,23 @@ static int store_mailbox(const char *tag, const char *mailbox,
struct imapflags *flags,
struct libmail_kwMessage *keywords,
time_t timestamp,
- unsigned long nbytes,
+ struct imaptoken *curtoken,
unsigned long *new_uidv,
unsigned long *new_uid)
{
-char *tmpname;
-char *newname;
-char *p;
-char *e;
-FILE *fp;
-unsigned long n;
-static const char nowrite[]=" NO [ALERT] Cannot create message - no write permission or out of disk space.\r\n";
-int lastnl;
-int rb;
+ unsigned long nbytes=curtoken->tokennum;
+ char *tmpname;
+ char *newname;
+ char *p;
+ char *e;
+ FILE *fp;
+ unsigned long n;
+ static const char nowrite[]=" NO [ALERT] Cannot create message - no write permission or out of disk space.\r\n";
+ int lastnl;
+ int rb;
+ int errflag;
+ struct rfc2045 *rfc2045_parser;
+ const char *errmsg=nowrite;
fp=maildir_mkfilename(mailbox, flags, 0, &tmpname, &newname);
@@ -710,6 +746,8 @@ int rb;
current_temp_fd=fileno(fp);
current_temp_fn=tmpname;
+ rfc2045_parser=rfc2045_alloc();
+
while (nbytes)
{
read_string(&p, &n, nbytes);
@@ -726,31 +764,53 @@ int rb;
}
else if (e)
{
+ rfc2045_parse(rfc2045_parser, p, e-p);
rb = fwrite(p, 1, e-p, fp);
}
else
{
+ rfc2045_parse(rfc2045_parser, p, n);
rb = fwrite(p, 1, n, fp);
}
n -= rb;
p += rb;
}
}
- if (!lastnl) putc('\n', fp);
+ if (!lastnl)
+ {
+ putc('\n', fp);
+ rfc2045_parse(rfc2045_parser, "\n", 1);
+ }
current_temp_fd=-1;
current_temp_fn=NULL;
+ errflag=0;
if (fflush(fp) || ferror(fp))
{
fprintf(stderr,
"ERR: error storing a message, user=%s, errno=%d\n",
getenv("AUTHENTICATED"), errno);
+ errflag=1;
+ }
+ if ((rfc2045_parser->rfcviolation & RFC2045_ERR8BITHEADER) &&
+ curtoken->tokentype != IT_LITERAL8_STRING_START)
+ {
+ errmsg=" NO [ALERT] Your IMAP client does not appear to "
+ "correctly implement Unicode messages, "
+ "see https://tools.ietf.org/html/rfc6855.html\r\n";
+ errflag=1;
+ }
+
+ rfc2045_free(rfc2045_parser);
+
+ if (errflag)
+ {
fclose(fp);
unlink(tmpname);
writes(tag);
- writes(nowrite);
+ writes(errmsg);
free(tmpname);
free(newname);
return (-1);
@@ -2413,7 +2473,7 @@ static int list_callback(const char *hiersep,
different order */
writes("* ACLFAILED \"");
- writeqs(mailbox);
+ writemailbox(mailbox);
writes("\"");
accessdenied("LIST(MYRIGHTS)",
mailbox,
@@ -2440,7 +2500,7 @@ static int list_callback(const char *hiersep,
different order */
writes("* ACLFAILED \"");
- writeqs(mailbox);
+ writemailbox(mailbox);
writes("\"");
accessdenied("LIST(ACL)",
mailbox,
@@ -2480,7 +2540,7 @@ static int list_callback(const char *hiersep,
writes(") ");
writes(hiersep);
writes(" \"");
- writeqs(mailbox);
+ writemailbox(mailbox);
writes("\"");
if (flags & (LIST_ACL|LIST_MYRIGHTS|LIST_POSTADDRESS))
@@ -2872,6 +2932,18 @@ char *get_myrightson(const char *mailbox)
return rights;
}
+char *get_myrightson_folder(const char *folder)
+{
+ char *p=imap_foldername_to_filename(enabled_utf8, folder);
+ char *r;
+
+ if (!p)
+ return NULL;
+
+ r=get_myrightson(p);
+ free(p);
+ return r;
+}
char *compute_myrights(maildir_aclt_list *l, const char *l_owner)
{
@@ -3113,26 +3185,37 @@ static int aclcmd(const char *tag)
case IT_LPAREN:
while ((curtoken=nexttoken_nouc())->tokentype != IT_RPAREN)
{
+ char *p;
+
if (curtoken->tokentype != IT_QUOTED_STRING &&
curtoken->tokentype != IT_ATOM &&
curtoken->tokentype != IT_NUMBER)
{
+ writes(tag);
+ writes(" BAD Invalid command\r\n");
+ return 0;
+ }
+
+ p=imap_foldername_to_filename(enabled_utf8,
+ curtoken->tokenbuf);
+ if (!p)
+ {
errno=EINVAL;
return -1;
}
-
mblist=NULL;
- if (mailbox_scan("", curtoken->tokenbuf, 0,
+ if (mailbox_scan("", p, 0,
aclmailbox_scan, &mblist) ||
aclmailbox_merge(mblist, &mailboxlist))
{
+ free(p);
free_tempmailboxlist(mblist);
free_mailboxlist(mailboxlist);
return -1;
}
-
+ free(p);
free_tempmailboxlist(mblist);
}
break;
@@ -3141,17 +3224,27 @@ static int aclcmd(const char *tag)
case IT_NUMBER:
mblist=NULL;
- if (mailbox_scan("", curtoken->tokenbuf, LIST_CHECK1FOLDER,
- aclmailbox_scan, &mblist) ||
- aclmailbox_merge(mblist, &mailboxlist))
-
{
+ char *p=imap_foldername_to_filename(enabled_utf8,
+ curtoken->tokenbuf);
+
+ if (mailbox_scan("", p, LIST_CHECK1FOLDER,
+ aclmailbox_scan, &mblist) ||
+ aclmailbox_merge(mblist, &mailboxlist))
+ {
+ free(p);
+ free_tempmailboxlist(mblist);
+ free_mailboxlist(mailboxlist);
+ return -1;
+ }
+ free(p);
free_tempmailboxlist(mblist);
- free_mailboxlist(mailboxlist);
- return -1;
}
- free_tempmailboxlist(mblist);
break;
+ case IT_ERROR:
+ writes(tag);
+ writes(" BAD Invalid command\r\n");
+ return 0;
}
rc=0;
@@ -3288,7 +3381,7 @@ static void aclfailed(const char *mailbox, const char *identifier)
if (!identifier)
{
writes("* ACLFAILED \"");
- writeqs(mailbox);
+ writemailbox(mailbox);
writes("\" ");
writes(strerror(errno));
writes("\r\n");
@@ -3296,7 +3389,7 @@ static void aclfailed(const char *mailbox, const char *identifier)
}
writes("* RIGHTS-INFO \"");
- writeqs(mailbox);
+ writemailbox(mailbox);
writes("\" \"");
writeqs(identifier);
writes("\" ");
@@ -3318,7 +3411,7 @@ static int acl_settable_folder(char *mailbox,
if (mi->homedir == NULL || mi->maildir == NULL)
{
writes("* ACLFAILED \"");
- writeqs(mailbox);
+ writemailbox(mailbox);
writes("\" ACLs may not be modified for special mailbox\r\n");
maildir_info_destroy(mi);
*mailbox=0;
@@ -3481,7 +3574,7 @@ static int aclstore(const char *tag, struct temp_acl_mailbox_list *mailboxes)
if (acl_rights[0] == 0)
{
writes("* ACLFAILED \"");
- writeqs(mailboxes[i].mailbox);
+ writemailbox(mailboxes[i].mailbox);
writes("\"");
accessdenied("ACL STORE",
mailboxes[i].mailbox,
@@ -3585,7 +3678,7 @@ static int aclset(const char *tag, struct temp_acl_mailbox_list *mailboxes)
{
maildir_info_destroy(&mi);
writes("* ACLFAILED \"");
- writeqs(mailboxes[i].mailbox);
+ writemailbox(mailboxes[i].mailbox);
writes("\"");
accessdenied("ACL SET", mailboxes[i].mailbox,
ACL_ADMINISTER);
@@ -3657,7 +3750,7 @@ static int acldelete(const char *tag, struct temp_acl_mailbox_list *mailboxes)
if (acl_rights[0] == 0)
{
writes("* ACLFAILED \"");
- writeqs(mailboxes[i].mailbox);
+ writemailbox(mailboxes[i].mailbox);
writes("\"");
accessdenied("ACL DELETE",
mailboxes[i].mailbox,
@@ -3817,6 +3910,7 @@ static int append(const char *tag, const char *mailbox, const char *path)
unsigned long new_uidv, new_uid;
char access_rights[8];
struct imaptoken *curtoken;
+ int need_rparen;
if (access(path, 0))
{
@@ -3896,9 +3990,35 @@ static int append(const char *tag, const char *mailbox, const char *path)
else if (curtoken->tokentype == IT_NIL)
curtoken=nexttoken_noparseliteral();
- if (curtoken->tokentype != IT_LITERAL_STRING_START)
+ need_rparen=0;
+
+ if (enabled_utf8 && curtoken->tokentype == IT_ATOM &&
+ strcmp(curtoken->tokenbuf, "UTF8") == 0)
+ {
+ curtoken=nexttoken();
+ if (curtoken->tokentype != IT_LPAREN)
+ {
+ libmail_kwmDestroy(keywords);
+ return (-1);
+ }
+
+ curtoken=nexttoken_noparseliteral();
+ if (curtoken->tokentype != IT_LITERAL8_STRING_START)
+ {
+ libmail_kwmDestroy(keywords);
+
+ /* Don't break the protocol level */
+ convert_literal_tokens(curtoken);
+ return (-1);
+ }
+ need_rparen=1;
+ }
+ else if (curtoken->tokentype != IT_LITERAL_STRING_START)
{
libmail_kwmDestroy(keywords);
+
+ /* Don't break the protocol level */
+ convert_literal_tokens(curtoken);
return (-1);
}
@@ -3908,7 +4028,7 @@ static int append(const char *tag, const char *mailbox, const char *path)
acl_flags_adjust(access_rights, &flags)
? NULL:keywords,
timestamp,
- curtoken->tokennum, &new_uidv, &new_uid))
+ curtoken, &new_uidv, &new_uid))
{
libmail_kwmDestroy(keywords);
unread('\n');
@@ -3916,6 +4036,14 @@ static int append(const char *tag, const char *mailbox, const char *path)
}
libmail_kwmDestroy(keywords);
+ if (need_rparen)
+ {
+ if (nexttoken()->tokentype != IT_RPAREN)
+ {
+ return (-1);
+ }
+ }
+
if (nexttoken()->tokentype != IT_EOL)
{
return (-1);
@@ -4121,6 +4249,13 @@ static int validate_charset(const char *tag, char **charset)
if (*charset == NULL)
*charset=my_strdup("UTF-8");
+ if (enabled_utf8 && strcmp(*charset, "UTF-8"))
+ {
+ writes(tag);
+ writes(" BAD [BADCHARSET] Only UTF-8 charset is valid after enabling RFC 6855 support\r\n");
+ return (-1);
+ }
+
conv=unicode_convert_tou_init(*charset, &ucptr, &ucsize, 1);
if (!conv)
@@ -4246,8 +4381,15 @@ int uid=0;
if (curtoken->tokentype != IT_QUOTED_STRING &&
curtoken->tokentype != IT_ATOM &&
curtoken->tokentype != IT_NUMBER)
- return (-1);
- reference=my_strdup(curtoken->tokenbuf);
+ {
+ writes(tag);
+ writes(" BAD Invalid command\r\n");
+ return (0);
+ }
+ reference=imap_foldername_to_filename
+ (enabled_utf8, curtoken->tokenbuf);
+ if (!reference)
+ return -1;
}
curtoken=nexttoken_nouc();
@@ -4258,8 +4400,20 @@ int uid=0;
if (curtoken->tokentype != IT_QUOTED_STRING &&
curtoken->tokentype != IT_ATOM &&
curtoken->tokentype != IT_NUMBER)
- return (-1);
- name=my_strdup(curtoken->tokenbuf);
+ {
+ free(reference);
+ writes(tag);
+ writes(" BAD Invalid command\r\n");
+ return(0);
+ }
+ name=imap_foldername_to_filename(enabled_utf8,
+ curtoken->tokenbuf);
+
+ if (!name)
+ {
+ free(reference);
+ return -1;
+ }
}
if (nexttoken()->tokentype != IT_EOL) return (-1);
@@ -4295,15 +4449,25 @@ int uid=0;
{
struct imaptoken *tok=nexttoken_nouc();
struct maildir_info mi;
+ char *mailbox;
if (tok->tokentype != IT_NUMBER &&
tok->tokentype != IT_ATOM &&
tok->tokentype != IT_QUOTED_STRING)
- return (-1);
+ {
+ writes(tag);
+ writes(" BAD Invalid command\r\n");
+ return (0);
+ }
- if (maildir_info_imap_find(&mi, tok->tokenbuf,
+ mailbox=imap_foldername_to_filename(enabled_utf8,
+ tok->tokenbuf);
+ if (!mailbox ||
+ maildir_info_imap_find(&mi, mailbox,
getenv("AUTHENTICATED")) < 0)
{
+ if (mailbox)
+ free(mailbox);
writes(tag);
writes(" NO Invalid mailbox name.\r\n");
return (0);
@@ -4319,19 +4483,21 @@ int uid=0;
maildir_info_destroy(&mi);
writes(tag);
accessdenied("APPEND",
- tok->tokenbuf,
+ mailbox,
ACL_INSERT);
+ free(mailbox);
return 0;
}
- rc=append(tag, tok->tokenbuf, p);
+ rc=append(tag, mailbox, p);
free(p);
maildir_info_destroy(&mi);
+ free(mailbox);
return (rc);
}
else if (mi.mailbox_type == MAILBOXTYPE_OLDSHARED)
{
- char *p=strchr(tok->tokenbuf, '.');
+ char *p=strchr(mailbox, '.');
if (p && (p=maildir_shareddir(".", p+1)) != NULL)
{
@@ -4342,13 +4508,14 @@ int uid=0;
strcat(strcpy(q, p), "/shared");
free(p);
- rc=append(tag, tok->tokenbuf, q);
+ rc=append(tag, mailbox, q);
free(q);
+ free(mailbox);
maildir_info_destroy(&mi);
return rc;
}
}
-
+ free(mailbox);
writes(tag);
accessdenied("APPEND", "folder", ACL_INSERT);
return (0);
@@ -4358,17 +4525,27 @@ int uid=0;
{
char qroot[20];
struct maildir_info minfo;
-
+ char *mailbox;
curtoken=nexttoken_nouc();
if (curtoken->tokentype != IT_NUMBER &&
curtoken->tokentype != IT_ATOM &&
curtoken->tokentype != IT_QUOTED_STRING)
- return (-1);
+ {
+ writes(tag);
+ writes(" BAD Invalid command\r\n");
+ return (0);
+ }
+
+ mailbox=imap_foldername_to_filename(enabled_utf8,
+ curtoken->tokenbuf);
- if (maildir_info_imap_find(&minfo, curtoken->tokenbuf,
+ if (!mailbox ||
+ maildir_info_imap_find(&minfo, mailbox,
getenv("AUTHENTICATED")))
{
+ if (mailbox)
+ free(mailbox);
writes(tag);
writes(" NO Invalid mailbox name.\r\n");
return (0);
@@ -4389,13 +4566,14 @@ int uid=0;
writes("*");
writes(" QUOTAROOT \"");
- writeqs(curtoken->tokenbuf);
+ writemailbox(mailbox);
writes("\" \"");
writes(qroot);
writes("\"\r\n");
quotainfo_out(qroot);
writes(tag);
writes(" OK GETQUOTAROOT Ok.\r\n");
+ free(mailbox);
return(0);
}
@@ -4407,6 +4585,34 @@ int uid=0;
return(0);
}
+ if (strcmp(curtoken->tokenbuf, "ENABLE") == 0)
+ {
+ while (nexttoken()->tokentype != IT_EOL)
+ {
+ switch (curtoken->tokentype) {
+ case IT_NUMBER:
+ case IT_ATOM:
+ case IT_QUOTED_STRING:
+ if (strcmp(curtoken->tokenbuf, "UTF8=ACCEPT")
+ == 0)
+ {
+ enabled_utf8=1;
+ }
+ continue;
+ default:
+ return -1;
+ }
+ }
+
+ writes("* ENABLED");
+ if (enabled_utf8)
+ writes(" UTF8=ACCEPT");
+ writes("\r\n");
+ writes(tag);
+ writes(" OK Options enabled\r\n");
+ return (0);
+ }
+
if (strcmp(curtoken->tokenbuf, "GETQUOTA") == 0)
{
curtoken=nexttoken_nouc();
@@ -4442,7 +4648,14 @@ int uid=0;
if ( mailbox == 0)
return (0);
- orig_mailbox=my_strdup(curtoken->tokenbuf);
+ orig_mailbox=imap_foldername_to_filename(enabled_utf8,
+ curtoken->tokenbuf);
+
+ if (!orig_mailbox)
+ {
+ free(mailbox);
+ return -1;
+ }
curtoken=nexttoken();
oneonly=0;
@@ -4521,7 +4734,7 @@ int uid=0;
writes("*");
writes(" STATUS \"");
- writeqs(orig_mailbox);
+ writemailbox(orig_mailbox);
writes("\" (");
p="";
if (get_messages)
@@ -4599,7 +4812,11 @@ int uid=0;
if (curtoken->tokentype != IT_NUMBER &&
curtoken->tokentype != IT_ATOM &&
curtoken->tokentype != IT_QUOTED_STRING)
- return (-1);
+ {
+ writes(tag);
+ writes(" BAD Invalid command\r\n");
+ return 0;
+ }
isdummy=0;
@@ -4610,13 +4827,20 @@ int uid=0;
isdummy=1; /* Ignore hierarchy creation */
}
- if (maildir_info_imap_find(&mi, curtoken->tokenbuf,
+ mailbox=imap_foldername_to_filename(enabled_utf8,
+ curtoken->tokenbuf);
+ if (!mailbox)
+ return -1;
+
+ if (maildir_info_imap_find(&mi, mailbox,
getenv("AUTHENTICATED")))
{
writes(tag);
writes(" NO Invalid mailbox name.\r\n");
+ free(mailbox);
return (0);
}
+ free(mailbox);
if (!mi.homedir || !mi.maildir)
{
@@ -4655,7 +4879,15 @@ int uid=0;
}
if (isdummy) *p=HIERCH;
- orig_mailbox=my_strdup(curtoken->tokenbuf);
+ orig_mailbox=imap_foldername_to_filename(enabled_utf8,
+ curtoken->tokenbuf);
+
+ if (!orig_mailbox)
+ {
+ free(mailbox);
+ maildir_info_destroy(&mi);
+ return (-1);
+ }
if (nexttoken()->tokentype != IT_EOL)
{
@@ -4711,7 +4943,7 @@ int uid=0;
}
writes(tag);
writes(" OK \"");
- writeqs(orig_mailbox);
+ writemailbox(orig_mailbox);
writes("\" created.\r\n");
/*
@@ -4745,7 +4977,11 @@ int uid=0;
if (curtoken->tokentype != IT_NUMBER &&
curtoken->tokentype != IT_ATOM &&
curtoken->tokentype != IT_QUOTED_STRING)
- return (-1);
+ {
+ writes(tag);
+ writes(" BAD Invalid command\r\n");
+ return (0);
+ }
p=strrchr(curtoken->tokenbuf, HIERCH);
if (p && p[1] == '\0') /* Ignore hierarchy DELETE */
@@ -4757,14 +4993,18 @@ int uid=0;
return (0);
}
- mailbox_name=my_strdup(curtoken->tokenbuf);
mailbox=parse_mailbox_error(tag, curtoken, 1, 0);
if ( mailbox == 0)
+ return 0;
+
+ mailbox_name=imap_foldername_to_filename(enabled_utf8,
+ curtoken->tokenbuf);
+
+ if (!mailbox_name)
{
- free(mailbox_name);
- return (0);
+ free(mailbox);
+ return (-1);
}
-
if (nexttoken()->tokentype != IT_EOL)
{
free(mailbox_name);
@@ -4781,10 +5021,10 @@ int uid=0;
return (0);
}
- if (strncmp(curtoken->tokenbuf, SHARED HIERCHS,
- sizeof(SHARED HIERCHS)-1) == 0)
+ if (strncmp(mailbox_name, SHARED HIERCHS,
+ sizeof(SHARED HIERCHS)-1) == 0)
{
- maildir_shared_unsubscribe(0, curtoken->tokenbuf+
+ maildir_shared_unsubscribe(0, mailbox_name+
sizeof(SHARED HIERCHS)-1);
free(mailbox_name);
free(mailbox);
@@ -4836,6 +5076,7 @@ int uid=0;
char *p;
struct maildir_info mi1, mi2;
const char *errmsg;
+ char *mailbox;
curtoken=nexttoken_nouc();
@@ -4844,16 +5085,23 @@ int uid=0;
curtoken->tokentype != IT_QUOTED_STRING)
{
writes(tag);
- writes(" NO Invalid mailbox\r\n");
+ writes(" BAD Invalid command\r\n");
return (0);
}
if ((p=strrchr(curtoken->tokenbuf, HIERCH)) && p[1] == 0)
*p=0;
- if (maildir_info_imap_find(&mi1, curtoken->tokenbuf,
+ mailbox=imap_foldername_to_filename(enabled_utf8,
+ curtoken->tokenbuf);
+
+ if (!mailbox)
+ return -1;
+
+ if (maildir_info_imap_find(&mi1, mailbox,
getenv("AUTHENTICATED")) < 0)
{
+ free(mailbox);
writes(tag);
writes(" NO Invalid mailbox name.\r\n");
return (0);
@@ -4861,6 +5109,7 @@ int uid=0;
if (mi1.homedir == NULL || mi1.maildir == NULL)
{
+ free(mailbox);
maildir_info_destroy(&mi1);
writes(tag);
writes(" NO Invalid mailbox\r\n");
@@ -4868,11 +5117,12 @@ int uid=0;
}
{
- CHECK_RIGHTSM(curtoken->tokenbuf,
+ CHECK_RIGHTSM(mailbox,
rename_rights, ACL_DELETEFOLDER);
if (rename_rights[0] == 0)
{
+ free(mailbox);
maildir_info_destroy(&mi1);
writes(tag);
accessdenied("RENAME", curtoken->tokenbuf,
@@ -4880,7 +5130,7 @@ int uid=0;
return (0);
}
}
-
+ free(mailbox);
curtoken=nexttoken_nouc();
if (curtoken->tokentype != IT_NUMBER &&
@@ -4888,7 +5138,9 @@ int uid=0;
curtoken->tokentype != IT_QUOTED_STRING)
{
maildir_info_destroy(&mi1);
- return (-1);
+ writes(tag);
+ writes(" BAD Invalid command\r\n");
+ return (0);
}
if ((p=strrchr(curtoken->tokenbuf, HIERCH)) && p[1] == 0)
@@ -4896,22 +5148,33 @@ int uid=0;
*p=0;
}
+ mailbox=imap_foldername_to_filename(enabled_utf8,
+ curtoken->tokenbuf);
+
+ if (!mailbox)
+ {
+ maildir_info_destroy(&mi1);
+ return -1;
+ }
- if (maildir_info_imap_find(&mi2, curtoken->tokenbuf,
+ if (maildir_info_imap_find(&mi2, mailbox,
getenv("AUTHENTICATED")) < 0)
{
+ free(mailbox);
maildir_info_destroy(&mi1);
writes(tag);
writes(" NO Invalid mailbox name.\r\n");
return (0);
}
- if (check_parent_create(tag, "RENAME", curtoken->tokenbuf))
+ if (check_parent_create(tag, "RENAME", mailbox))
{
+ free(mailbox);
maildir_info_destroy(&mi1);
maildir_info_destroy(&mi2);
return 0;
}
+ free(mailbox);
if (nexttoken()->tokentype != IT_EOL)
{
@@ -4970,7 +5233,7 @@ int uid=0;
if ( mailbox == 0)
return (0);
- current_mailbox_acl=get_myrightson(curtoken->tokenbuf);
+ current_mailbox_acl=get_myrightson_folder(curtoken->tokenbuf);
if (current_mailbox_acl == NULL)
{
free(mailbox);
@@ -5049,7 +5312,11 @@ int uid=0;
if (curtoken->tokentype != IT_NUMBER &&
curtoken->tokentype != IT_ATOM &&
curtoken->tokentype != IT_QUOTED_STRING)
- return (-1);
+ {
+ writes(tag);
+ writes(" BAD Invalid command\r\n");
+ return (0);
+ }
p=strrchr(curtoken->tokenbuf, HIERCH);
if (p && p[1] == '\0') /* Ignore hierarchy DELETE */
@@ -5061,7 +5328,10 @@ int uid=0;
return (0);
}
- mailbox=my_strdup(curtoken->tokenbuf);
+ mailbox=imap_foldername_to_filename(enabled_utf8,
+ curtoken->tokenbuf);
+ if (!mailbox)
+ return -1;
if (nexttoken()->tokentype != IT_EOL)
return (-1);
@@ -5126,7 +5396,11 @@ int uid=0;
if (curtoken->tokentype != IT_NUMBER &&
curtoken->tokentype != IT_ATOM &&
curtoken->tokentype != IT_QUOTED_STRING)
- return (-1);
+ {
+ writes(tag);
+ writes(" BAD Invalid command\r\n");
+ return (0);
+ }
p=strrchr(curtoken->tokenbuf, HIERCH);
if (p && p[1] == '\0') /* Ignore hierarchy DELETE */
@@ -5138,7 +5412,12 @@ int uid=0;
return (0);
}
- mailbox=my_strdup(curtoken->tokenbuf);
+ mailbox=imap_foldername_to_filename(enabled_utf8,
+ curtoken->tokenbuf);
+
+ if (!mailbox)
+ return -1;
+
if (nexttoken()->tokentype != IT_EOL)
return (-1);
@@ -5241,7 +5520,10 @@ int uid=0;
return 0;
free(mailbox);
- mailbox=my_strdup(curtoken->tokenbuf);
+ mailbox=imap_foldername_to_filename(enabled_utf8,
+ curtoken->tokenbuf);
+ if (!mailbox)
+ return -1;
if (maildir_info_imap_find(&mi, mailbox,
getenv("AUTHENTICATED")) < 0)
@@ -5355,6 +5637,7 @@ int uid=0;
maildir_aclt_list l;
char *mailbox_owner;
char *mb;
+ char *f;
curtoken=nexttoken_nouc();
@@ -5363,22 +5646,29 @@ int uid=0;
return 0;
free(mb);
+ f=imap_foldername_to_filename(enabled_utf8, curtoken->tokenbuf);
+
+ if (!f)
+ return -1;
+
{
- CHECK_RIGHTSM(curtoken->tokenbuf,
+ CHECK_RIGHTSM(f,
acl_rights,
ACL_ADMINISTER);
if (acl_rights[0] == 0)
{
writes(tag);
- accessdenied("GETACL", curtoken->tokenbuf,
+ accessdenied("GETACL", f,
ACL_ADMINISTER);
+ free(f);
return 0;
}
}
- if (get_acllist(&l, curtoken->tokenbuf,
+ if (get_acllist(&l, f,
&mailbox_owner) < 0)
{
+ free(f);
writes(tag);
writes(" NO Cannot retrieve ACLs for mailbox.\r\n");
return 0;
@@ -5386,13 +5676,14 @@ int uid=0;
free(mailbox_owner);
writes("* ACL \"");
- writeqs(curtoken->tokenbuf);
+ writemailbox(f);
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);
+ free(f);
return 0;
}
@@ -5408,9 +5699,14 @@ int uid=0;
if (!mb)
return 0;
free(mb);
+ mb=imap_foldername_to_filename(enabled_utf8,
+ curtoken->tokenbuf);
+
+ if (!mb)
+ return -1;
{
- char *myrights=get_myrightson(curtoken->tokenbuf);
+ char *myrights=get_myrightson(mb);
if (!strchr(myrights, ACL_LOOKUP[0]) &&
!strchr(myrights, ACL_READ[0]) &&
@@ -5422,23 +5718,23 @@ int uid=0;
{
free(myrights);
writes(tag);
- accessdenied("GETACL", curtoken->tokenbuf,
+ accessdenied("GETACL", mb,
ACL_ADMINISTER);
+ free(mb);
return 0;
}
free(myrights);
}
- if (get_acllist(&l, curtoken->tokenbuf,
+ if (get_acllist(&l, mb,
&mailbox_owner) < 0)
{
+ free(mb);
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:
@@ -5452,7 +5748,7 @@ int uid=0;
}
writes("* LISTRIGHTS \"");
- writeqs(mb);
+ writemailbox(mb);
writes("\" \"");
writeqs(curtoken->tokenbuf);
writes("\"");
@@ -5510,6 +5806,7 @@ int uid=0;
if (strcmp(curtoken->tokenbuf, "MYRIGHTS") == 0)
{
char *mb;
+ char *f;
curtoken=nexttoken_nouc();
@@ -5518,8 +5815,12 @@ int uid=0;
return 0;
free(mb);
+ f=imap_foldername_to_filename(enabled_utf8, curtoken->tokenbuf);
+ if (!f)
+ return -1;
+
{
- char *myrights=get_myrightson(curtoken->tokenbuf);
+ char *myrights=get_myrightson(f);
if (!strchr(myrights, ACL_LOOKUP[0]) &&
!strchr(myrights, ACL_READ[0]) &&
@@ -5531,25 +5832,28 @@ int uid=0;
{
free(myrights);
writes(tag);
- accessdenied("GETACL", curtoken->tokenbuf,
+ accessdenied("GETACL", f,
ACL_ADMINISTER);
+ free(f);
return 0;
}
free(myrights);
}
- mb=get_myrightson(curtoken->tokenbuf);
+ mb=get_myrightson(f);
if (!mb)
{
+ free(f);
writes(tag);
writes(" NO Cannot retrieve ACLs for mailbox.\r\n");
return 0;
}
writes("* MYRIGHTS \"");
- writeqs(curtoken->tokenbuf);
+ writemailbox(f);
writes("\" \"");
+ free(f);
writeacl1(mb);
free(mb);
@@ -5740,6 +6044,14 @@ int uid=0;
if (curtoken->tokentype == IT_ATOM &&
strcmp(curtoken->tokenbuf, "CHARSET") == 0)
{
+ if (enabled_utf8)
+ {
+ writes(tag);
+ writes(" NO CHARSET is not valid in UTF8 mode "
+ "as per RFC 6855\r\n");
+ return (0);
+ }
+
curtoken=nexttoken();
if (curtoken->tokentype != IT_ATOM &&
curtoken->tokentype != IT_QUOTED_STRING)
@@ -6089,7 +6401,9 @@ int uid=0;
curtoken->tokentype != IT_QUOTED_STRING)
{
free(msgset);
- return (-1);
+ writes(tag);
+ writes(" BAD Invalid command\r\n");
+ return (0);
}
mailbox=decode_valid_mailbox(curtoken->tokenbuf, 1);
@@ -6117,7 +6431,11 @@ int uid=0;
}
{
- CHECK_RIGHTSM(curtoken->tokenbuf,
+ char *f=imap_foldername_to_filename(enabled_utf8,
+ curtoken->tokenbuf);
+ if (!f)
+ return -1;
+ CHECK_RIGHTSM(f,
append_rights,
ACL_INSERT ACL_DELETEMSGS
ACL_SEEN ACL_WRITE);
@@ -6126,11 +6444,12 @@ int uid=0;
{
writes(tag);
accessdenied("COPY",
- curtoken->tokenbuf,
+ f,
ACL_INSERT);
+ free(f);
return 0;
}
-
+ free(f);
strcpy(access_rights, append_rights);
}