Commit 154c67f4 154c67f47ba231d3e269ad59714dcf5870a658c3 by Sergey Poznyakoff

imap4d: revamp namespace translation

Instead of translating names to full mailbox URLs, translate them
to the filesystem pathname and record (mu_record_t) that should be
used when creating the mailbox.  Never use mu_mailbox_create_default.

This patch also fixes memory leaks in some functions (the return
value from namespace_get_url was never freed).

* imap4d/imap4d.h (namespace_get_url): Remove.
(namespace_get_name): New proto.
* imap4d/namespace.c (namespace_init): Always intialize the
pfx->record member.  This requires that the default record be
initialized.
(namespace_get_url): Remove.
(namespace_get_name): New function.

* imap4d/create.c: Use namespace_get_name and
mu_mailbox_create_from_record to create mailboxes.  Fix folder
creation.
* imap4d/append.c: Use namespace_get_name and
mu_mailbox_create_from_record to create mailboxes.
* imap4d/copy.c: Likewise.
* imap4d/delete.c: Likewise.
* imap4d/quota.c: Likewise.
* imap4d/rename.c: Likewise.
* imap4d/status.c: Likewise.
1 parent b39b471f
......@@ -201,6 +201,7 @@ imap4d_append (struct imap4d_session *session,
{
int i;
char *mboxname;
mu_record_t record;
int flags = 0;
mu_mailbox_t dest_mbox = NULL;
int status;
......@@ -252,12 +253,12 @@ imap4d_append (struct imap4d_session *session,
}
msg_text = imap4d_tokbuf_getarg (tok, i);
mboxname = namespace_get_url (mboxname, NULL);
mboxname = namespace_get_name (mboxname, &record, NULL);
if (!mboxname)
return io_completion_response (command, RESP_NO, "Couldn't open mailbox");
status = mu_mailbox_create_default (&dest_mbox, mboxname);
status = mu_mailbox_create_from_record (&dest_mbox, record, mboxname);
if (status == 0)
{
/* It SHOULD NOT automatically create the mailbox. */
......
......@@ -212,6 +212,7 @@ imap4d_copy0 (imap4d_tokbuf_t tok, int isuid, char **err_text)
mu_mailbox_t cmbox = NULL;
int arg = IMAP4_ARG_1 + !!isuid;
int mode = 0;
mu_record_t record;
*err_text = NULL;
if (imap4d_tokbuf_argc (tok) != arg + 2)
......@@ -240,7 +241,7 @@ imap4d_copy0 (imap4d_tokbuf_t tok, int isuid, char **err_text)
return RESP_BAD;
}
mailbox_name = namespace_get_url (name, &mode);
mailbox_name = namespace_get_name (name, &record, &mode);
if (!mailbox_name)
{
......@@ -251,7 +252,7 @@ imap4d_copy0 (imap4d_tokbuf_t tok, int isuid, char **err_text)
/* If the destination mailbox does not exist, a server should return
an error. */
status = mu_mailbox_create_default (&cmbox, mailbox_name);
status = mu_mailbox_create_from_record (&cmbox, record, mailbox_name);
if (status == 0)
{
/* It SHOULD NOT automatifcllly create the mailbox. */
......@@ -267,7 +268,8 @@ imap4d_copy0 (imap4d_tokbuf_t tok, int isuid, char **err_text)
mu_mailbox_destroy (&cmbox);
}
mu_msgset_free (msgset);
free (mailbox_name);
if (status == 0)
{
*err_text = "Completed";
......
......@@ -39,9 +39,10 @@ imap4d_create (struct imap4d_session *session,
{
char *name;
int isdir = 0;
int mode = 0;
int rc = RESP_OK;
const char *msg = "Completed";
mu_record_t record;
int mode;
if (imap4d_tokbuf_argc (tok) != 3)
return io_completion_response (command, RESP_BAD, "Invalid arguments");
......@@ -67,8 +68,8 @@ imap4d_create (struct imap4d_session *session,
isdir = 1;
/* Allocates memory. */
name = namespace_get_url (name, &mode);
name = namespace_get_name (name, &record, &mode);
if (!name)
return io_completion_response (command, RESP_NO, "Cannot create mailbox");
......@@ -76,47 +77,59 @@ imap4d_create (struct imap4d_session *session,
if (access (name, F_OK) != 0)
{
if (make_interdir (name, MU_HIERARCHY_DELIMITER, MKDIR_PERMISSIONS))
{
rc = RESP_NO;
msg = "Cannot create mailbox";
}
rc = RESP_NO;
if (rc == RESP_OK && !isdir)
if (rc == RESP_OK)
{
mu_mailbox_t mbox;
rc = mu_mailbox_create_default (&mbox, name);
if (rc)
if (isdir)
{
mu_diag_output (MU_DIAG_ERR,
_("Cannot create mailbox %s: %s"), name,
mu_strerror (rc));
rc = RESP_NO;
msg = "Cannot create mailbox";
}
else if ((rc = mu_mailbox_open (mbox,
MU_STREAM_RDWR | MU_STREAM_CREAT
| mode)))
{
mu_diag_output (MU_DIAG_ERR,
_("Cannot open mailbox %s: %s"),
name, mu_strerror (rc));
rc = RESP_NO;
msg = "Cannot create mailbox";
if (mkdir (name, MKDIR_PERMISSIONS))
{
mu_diag_output (MU_DIAG_ERR,
_("Cannot create directory %s: %s"), name,
mu_strerror (errno));
rc = RESP_NO;
}
}
else
{
mu_mailbox_close (mbox);
mu_mailbox_destroy (&mbox);
rc = RESP_OK;
mu_mailbox_t mbox;
rc = mu_mailbox_create_from_record (&mbox, record, name);
if (rc)
{
mu_diag_output (MU_DIAG_ERR,
_("Cannot create mailbox (%s) %s: %s"), name,
record->scheme,
mu_strerror (rc));
rc = RESP_NO;
}
else if ((rc = mu_mailbox_open (mbox,
MU_STREAM_RDWR | MU_STREAM_CREAT
| mode)))
{
mu_diag_output (MU_DIAG_ERR,
_("Cannot open mailbox (%s) %s: %s"),
record->scheme,
name, mu_strerror (rc));
rc = RESP_NO;
}
else
{
mu_mailbox_close (mbox);
mu_mailbox_destroy (&mbox);
rc = RESP_OK;
}
}
}
if (rc != RESP_OK)
msg = "Cannot create mailbox";
}
else
{
rc = RESP_NO;
msg = "already exists";
}
free (name);
return io_completion_response (command, rc, "%s", msg);
}
......
......@@ -36,6 +36,7 @@ imap4d_delete (struct imap4d_session *session,
const char *msg = "Completed";
char *name;
mu_mailbox_t tmpbox;
mu_record_t record;
if (imap4d_tokbuf_argc (tok) != 3)
return io_completion_response (command, RESP_BAD, "Invalid arguments");
......@@ -48,12 +49,12 @@ imap4d_delete (struct imap4d_session *session,
if (mu_c_strcasecmp (name, "INBOX") == 0)
return io_completion_response (command, RESP_NO, "Already exist");
/* Allocates memory. */
name = namespace_get_url (name, NULL);
/* Allocates memory. */
name = namespace_get_name (name, &record, NULL);
if (!name)
return io_completion_response (command, RESP_NO, "Cannot remove");
rc = mu_mailbox_create (&tmpbox, name);
rc = mu_mailbox_create_from_record (&tmpbox, record, name);
if (rc == 0)
{
imap4d_enter_critical ();
......@@ -69,7 +70,8 @@ imap4d_delete (struct imap4d_session *session,
if (rc)
mu_diag_funcall (MU_DIAG_ERROR, "remove", name, errno);
}
free (name);
if (rc)
{
rc = RESP_NO;
......
......@@ -413,7 +413,7 @@ struct namespace *namespace_lookup (char const *name);
char *namespace_translate_name (char const *name, int url,
struct namespace_prefix const **pfx);
char *namespace_get_url (char const *name, int *mode);
char *namespace_get_name (char const *name, mu_record_t *rec, int *mode);
void translate_delim (char *dst, char const *src, int dst_delim, int src_delim);
......
......@@ -91,8 +91,7 @@ namespace_init (void)
if (mu_list_get_iterator (namespace[i].prefixes, &itr))
imap4d_bye (ERR_NO_MEM);
for (mu_iterator_first (itr);
!mu_iterator_is_done (itr); mu_iterator_next (itr))
{
......@@ -106,6 +105,9 @@ namespace_init (void)
trim_delim (pfx->dir, '/');
if (!pfx->scheme)
mu_registrar_get_default_record (&pfx->record);
rc = mu_assoc_install (prefixes, pfx->prefix, pfx);
if (rc == MU_ERR_EXISTS)
{
......@@ -351,20 +353,12 @@ namespace_translate_name (char const *name, int url,
}
char *
namespace_get_url (char const *name, int *mode)
namespace_get_name (char const *name, mu_record_t *rec, int *mode)
{
struct namespace_prefix const *pfx;
char *path = namespace_translate_name (name, 1, &pfx);
if (path && pfx->scheme)
{
char *p = mu_alloc (strlen (pfx->scheme) + 3 + strlen (path) + 1);
strcpy (p, pfx->scheme);
strcat (p, "://");
strcat (p, path);
free (path);
path = p;
}
char *path = namespace_translate_name (name, 0, &pfx);
if (rec)
*rec = pfx->record;
if (mode)
*mode = namespace[pfx->ns].mode;
return path;
......
......@@ -132,19 +132,17 @@ quota_check (mu_off_t size)
mu_mailbox_t mbox;
mu_off_t total;
int rc;
mu_record_t record;
if (auth_data->quota == 0)
return RESP_OK;
total = used_size;
mailbox_name = namespace_get_url ("INBOX", NULL);
rc = mu_mailbox_create (&mbox, mailbox_name);
mailbox_name = namespace_get_name ("INBOX", &record, NULL);
rc = mu_mailbox_create_from_record (&mbox, record, mailbox_name);
if (rc)
{
mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_create", mailbox_name, rc);
free (mailbox_name);
}
mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_create", mailbox_name, rc);
else
{
do
......
......@@ -110,6 +110,7 @@ imap4d_rename (struct imap4d_session *session,
const char *msg = "Completed";
struct stat newst;
int mode = 0;
mu_record_t newrec;
if (imap4d_tokbuf_argc (tok) != 4)
return io_completion_response (command, RESP_BAD, "Invalid arguments");
......@@ -121,7 +122,7 @@ imap4d_rename (struct imap4d_session *session,
return io_completion_response (command, RESP_NO, "Name Inbox is reservered");
/* Allocates memory. */
newname = namespace_get_url (newname, &mode);
newname = namespace_get_name (newname, &newrec, &mode);
if (!newname)
return io_completion_response (command, RESP_NO, "Permission denied");
......@@ -158,7 +159,7 @@ imap4d_rename (struct imap4d_session *session,
return io_completion_response (command, RESP_NO,
"Cannot be a directory");
}
if (mu_mailbox_create (&newmbox, newname) != 0
if (mu_mailbox_create_from_record (&newmbox, newrec, newname) != 0
|| mu_mailbox_open (newmbox,
MU_STREAM_CREAT | MU_STREAM_RDWR | mode) != 0)
{
......@@ -199,7 +200,7 @@ imap4d_rename (struct imap4d_session *session,
return io_completion_response (command, RESP_OK, "Rename successful");
}
oldname = namespace_get_url (oldname, NULL);
oldname = namespace_get_name (oldname, NULL, NULL);
/* It must exist. */
/* FIXME: 1. What if odlname or newname is a remote mailbox?
......@@ -240,6 +241,7 @@ imap4d_rename (struct imap4d_session *session,
}
free (oldname);
}
free (newname);
return io_completion_response (command, rc, "%s", msg);
}
......
......@@ -75,13 +75,14 @@ imap4d_status (struct imap4d_session *session,
int count = 0;
char *err_msg = NULL;
int argc = imap4d_tokbuf_argc (tok);
mu_record_t record;
if (argc < 4)
return io_completion_response (command, RESP_BAD, "Invalid arguments");
name = imap4d_tokbuf_getarg (tok, IMAP4_ARG_1);
mailbox_name = namespace_get_url (name, NULL);
mailbox_name = namespace_get_name (name, &record, NULL);
if (!mailbox_name)
return io_completion_response (command, RESP_NO, "Error opening mailbox");
......@@ -92,7 +93,7 @@ imap4d_status (struct imap4d_session *session,
mu_mailbox_sync (mbox);
imap4d_leave_critical ();
status = mu_mailbox_create_default (&smbox, mailbox_name);
status = mu_mailbox_create_from_record (&smbox, record, mailbox_name);
if (status == 0)
{
status = mu_mailbox_open (smbox, MU_STREAM_READ);
......