commit-mailutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[SCM] GNU Mailutils branch, master, updated. release-3.1.1-25-g5e425f0


From: Sergey Poznyakoff
Subject: [SCM] GNU Mailutils branch, master, updated. release-3.1.1-25-g5e425f0
Date: Wed, 4 Jan 2017 14:38:45 +0000 (UTC)

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU Mailutils".

http://git.savannah.gnu.org/cgit/mailutils.git/commit/?id=5e425f04eeb5fad1f299fcf449404cef3b061c55

The branch, master has been updated
       via  5e425f04eeb5fad1f299fcf449404cef3b061c55 (commit)
       via  9a94d41a0c8cd941db019478c7a75b1036ddf580 (commit)
      from  068c059972fbc53d734ab816d7583ec2fb918b12 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 5e425f04eeb5fad1f299fcf449404cef3b061c55
Author: Sergey Poznyakoff <address@hidden>
Date:   Wed Jan 4 14:48:12 2017 +0200

    Tiny fix in c++ code.

commit 9a94d41a0c8cd941db019478c7a75b1036ddf580
Author: Sergey Poznyakoff <address@hidden>
Date:   Wed Jan 4 10:54:18 2017 +0200

    Rewrite namespace support
    
    * imap4d/imap4d.c (imap4d_homedir)
    (modify_homedir, mailbox_mode): Remove.
    (imap4d_srv_param): New configuration statement "namespace"
    Remove statements: homedir, personal-namespace,
    shared-namespace, other-mailbox-mode, shared-mailbox-mode.
    * imap4d/imap4d.h (imap4d_homedir, modify_homedir)
    (mailbox_mode): Remove.
    (namespace, namespace_init_session, util_getfullpath)
    (namespace_getfullpath, namespace_checkfullpath): Remove.
    (namespace_prefix, namespace): New structs.
    (namespace_lookup, namespace_translate_name)
    (namespace_get_url, translate_delim): New protos.
    * imap4d/list.c (refinfo): Revamp.
    (list_fun): Rewrite.
    * imap4d/namespace.c: Rewrite from scratch.
    * imap4d/append.c: Use new namespace functions.
    * imap4d/util.c (util_getfullpath): Remove.
    
    * imap4d/copy.c: Likewise.
    * imap4d/create.c: Likewise.
    * imap4d/delete.c: Likewise.
    * imap4d/quota.c: Likewise.
    * imap4d/rename.c: Likewise.
    * imap4d/select.c: Likewise.
    * imap4d/status.c: Likewise.
    
    * imap4d/tests/atlocal.in (make_config): New function.
    * imap4d/tests/testsuite.at (IMAP4D_CONFIG)
    (IMAP4D_RUN): New functions.
    * imap4d/tests/list.at: Update tests 16, 17, 18, 19
    
    * imap4d/tests/IDEF0955.at: Use IMAP4D_RUN.
    * imap4d/tests/IDEF0956.at: Likewise.
    * imap4d/tests/append00.at: Likewise.
    * imap4d/tests/append01.at: Likewise.
    * imap4d/tests/create01.at: Likewise.
    * imap4d/tests/create02.at: Likewise.

-----------------------------------------------------------------------

Summary of changes:
 imap4d/append.c           |    2 +-
 imap4d/copy.c             |    6 +-
 imap4d/create.c           |    6 +-
 imap4d/delete.c           |    2 +-
 imap4d/imap4d.c           |  239 ++++++++++++++-----
 imap4d/imap4d.h           |   40 +++-
 imap4d/list.c             |  131 +++++++----
 imap4d/namespace.c        |  576 +++++++++++++++++++++++++++++----------------
 imap4d/quota.c            |    6 +-
 imap4d/rename.c           |    9 +-
 imap4d/select.c           |    2 +-
 imap4d/status.c           |    2 +-
 imap4d/tests/IDEF0955.at  |    6 +-
 imap4d/tests/IDEF0956.at  |    8 +-
 imap4d/tests/append00.at  |    9 +-
 imap4d/tests/append01.at  |    9 +-
 imap4d/tests/atlocal.in   |   29 +++
 imap4d/tests/create01.at  |    5 +-
 imap4d/tests/create02.at  |    5 +-
 imap4d/tests/list.at      |   54 ++---
 imap4d/tests/testsuite.at |   30 +--
 imap4d/util.c             |   20 --
 include/mailutils/cfg.h   |    1 -
 libmu_cpp/pop3.cc         |    2 +-
 24 files changed, 756 insertions(+), 443 deletions(-)

diff --git a/imap4d/append.c b/imap4d/append.c
index 719a73e..6ebd4b2 100644
--- a/imap4d/append.c
+++ b/imap4d/append.c
@@ -253,7 +253,7 @@ imap4d_append (struct imap4d_session *session,
 
   msg_text = imap4d_tokbuf_getarg (tok, i);
   
-  mboxname = namespace_getfullpath (mboxname, NULL);
+  mboxname = namespace_get_url (mboxname, NULL);
   if (!mboxname)
     return io_completion_response (command, RESP_NO, "Couldn't open mailbox"); 
 
diff --git a/imap4d/copy.c b/imap4d/copy.c
index 82e2511..12caabd 100644
--- a/imap4d/copy.c
+++ b/imap4d/copy.c
@@ -211,7 +211,7 @@ imap4d_copy0 (imap4d_tokbuf_t tok, int isuid, char 
**err_text)
   char *end;
   mu_mailbox_t cmbox = NULL;
   int arg = IMAP4_ARG_1 + !!isuid;
-  int ns;
+  int mode = 0;
   
   *err_text = NULL;
   if (imap4d_tokbuf_argc (tok) != arg + 2)
@@ -240,7 +240,7 @@ imap4d_copy0 (imap4d_tokbuf_t tok, int isuid, char 
**err_text)
       return RESP_BAD;
     }
 
-  mailbox_name = namespace_getfullpath (name, &ns);
+  mailbox_name = namespace_get_url (name, &mode);
 
   if (!mailbox_name)
     {
@@ -255,7 +255,7 @@ imap4d_copy0 (imap4d_tokbuf_t tok, int isuid, char 
**err_text)
   if (status == 0)
     {
       /* It SHOULD NOT automatifcllly create the mailbox. */
-      status = mu_mailbox_open (cmbox, MU_STREAM_RDWR | mailbox_mode[ns]);
+      status = mu_mailbox_open (cmbox, MU_STREAM_RDWR | mode);
       if (status == 0)
        {
          mu_list_t msglist;
diff --git a/imap4d/create.c b/imap4d/create.c
index b115e11..6cacab7 100644
--- a/imap4d/create.c
+++ b/imap4d/create.c
@@ -39,7 +39,7 @@ imap4d_create (struct imap4d_session *session,
 {
   char *name;
   int isdir = 0;
-  int ns;
+  int mode = 0;
   int rc = RESP_OK;
   const char *msg = "Completed";
 
@@ -67,7 +67,7 @@ imap4d_create (struct imap4d_session *session,
     isdir = 1;
   
   /* Allocates memory.  */
-  name = namespace_getfullpath (name, &ns);
+  name = namespace_get_url (name, &mode);
 
   if (!name)
     return io_completion_response (command, RESP_NO, "Cannot create mailbox");
@@ -96,7 +96,7 @@ imap4d_create (struct imap4d_session *session,
            }
          else if ((rc = mu_mailbox_open (mbox,
                                          MU_STREAM_RDWR | MU_STREAM_CREAT
-                                         | mailbox_mode[ns])))
+                                         | mode)))
            {
              mu_diag_output (MU_DIAG_ERR,
                              _("Cannot open mailbox %s: %s"),
diff --git a/imap4d/delete.c b/imap4d/delete.c
index bbf5ae3..151b2fb 100644
--- a/imap4d/delete.c
+++ b/imap4d/delete.c
@@ -49,7 +49,7 @@ imap4d_delete (struct imap4d_session *session,
     return io_completion_response (command, RESP_NO, "Already exist");
 
  /* Allocates memory.  */
-  name = namespace_getfullpath (name, NULL);
+  name = namespace_get_url (name, NULL);
   if (!name)
     return io_completion_response (command, RESP_NO, "Cannot remove");
 
diff --git a/imap4d/imap4d.c b/imap4d/imap4d.c
index 0dce6ca..eca84c9 100644
--- a/imap4d/imap4d.c
+++ b/imap4d/imap4d.c
@@ -27,8 +27,6 @@ int imap4d_transcript;
 
 mu_mailbox_t mbox;              /* Current mailbox */
 char *real_homedir;             /* Homedir as returned by user database */
-char *imap4d_homedir;           /* Homedir as visible for the remote party */
-char *modify_homedir;           /* Expression to produce imap4d_homedir */
 int state = STATE_NONAUTH;      /* Current IMAP4 state */
 struct mu_auth_data *auth_data; 
 
@@ -40,8 +38,6 @@ mu_list_t user_retain_groups;
 
 int home_dir_mode = S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH;
 
-int mailbox_mode[NS_MAX];
-
 /* Saved command line. */
 int imap4d_argc;                 
 char **imap4d_argv;
@@ -359,7 +355,179 @@ imap_check_group_list (mu_list_t l)
     return MU_ERR_NOENT;
   return rc;
 }
+
+static int
+cb_prefix_delim (void *data, mu_config_value_t *val)
+{
+  if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
+    return 1;
+  if (val->v.string[0] == 0)
+    mu_error (_("delimiter cannot be empty"));
+  else if (val->v.string[1] != 0)
+    mu_error (_("delimiter must be a single character"));
+  else
+    *(int*) data = val->v.string[0];
+  return 0;
+}
+
+static int
+cb_prefix_scheme (void *data, mu_config_value_t *val)
+{
+  struct namespace_prefix *pfx = data;
+  char *scheme;
+  mu_record_t rec;
+  int rc;
+  int (*mbx) (mu_mailbox_t);
+  
+  if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
+    return 1;
+  scheme = mu_strdup (val->v.string);
+  rc = mu_registrar_lookup_scheme (scheme, &rec);
+  if (rc == MU_ERR_NOENT)
+    {
+      mu_error (_("unknown mailbox type"));
+      return 1;
+    }
+  else if (rc)
+    {
+      mu_diag_funcall (MU_DIAG_ERROR, "mu_registrar_lookup_scheme", scheme, 
rc);
+      return 1;
+    }
+
+  rc = mu_record_get_mailbox (rec, &mbx);
+  if (rc)
+    {
+      mu_diag_funcall (MU_DIAG_ERROR, "mu_record_get_mailbox", scheme, rc);
+      return 1;
+    }
+
+  if (!mbx || !mu_record_is_local (rec))
+    {
+      mu_error (_("not a local mailbox type"));
+      return 1;
+    }
+  
+  pfx->scheme = scheme;
+  pfx->record = rec;
+
+  return 0;
+}
+
+static struct mu_cfg_param prefix_param[] = {
+  { "directory", mu_c_string,
+    NULL, mu_offsetof (struct namespace_prefix, dir), NULL,
+    N_("Directory in the file system") },
+  { "delimiter", mu_cfg_callback,
+    NULL, mu_offsetof (struct namespace_prefix, delim), cb_prefix_delim,
+    N_("Hierarchy delimiter character") },
+  { "mailbox-type", mu_cfg_callback,
+    NULL, 0, cb_prefix_scheme,
+    N_("Type of mailboxes residing under this prefix") },
+  { NULL }
+};
+
+static struct mu_cfg_param namespace_param[] = {
+  { "mailbox-mode", mu_cfg_callback,
+    NULL, mu_offsetof (struct namespace, mode), cb_mailbox_mode,
+    N_("File mode for newly created mailboxes in this namespace"),
+    N_("mode: g(+|=)[wr]+,o(+|=)[wr]+") },
+  { "prefix", mu_cfg_section },
+  { NULL }
+};
 
+static int
+prefix_section_parser (enum mu_cfg_section_stage stage,
+                      const mu_cfg_node_t *node,
+                      const char *section_label, void **section_data,
+                      void *call_data,
+                      mu_cfg_tree_t *tree)
+{
+  struct namespace_prefix *pfx;
+
+  switch (stage)
+    {
+    case mu_cfg_section_start:
+      {
+       struct namespace *nspace = *section_data;
+      
+       if (node->label == NULL || node->label->type != MU_CFG_STRING)
+         return 1;
+
+       pfx = mu_zalloc (sizeof (*pfx));
+       pfx->prefix = mu_strdup (node->label->v.string);
+       mu_list_append (nspace->prefixes, pfx);
+       *section_data = pfx;
+      }
+      break;
+
+    case mu_cfg_section_end:
+      pfx = *section_data;
+      if (!pfx->delim)
+       pfx->delim = '/';
+      if (!pfx->dir)
+       {
+         if (pfx->prefix)
+           pfx->dir = mu_strdup (pfx->prefix);
+         else
+           {
+             mu_error (_("bad prefix definition"));
+             return 1;
+           }
+       }
+      else if (!pfx->prefix)
+       {
+         pfx->prefix = mu_alloc (strlen (pfx->dir) + 1);
+         translate_delim (pfx->prefix, pfx->dir, pfx->delim, '/');
+       }
+    }
+  return 0;
+}
+      
+static int
+namespace_section_parser (enum mu_cfg_section_stage stage,
+                         const mu_cfg_node_t *node,
+                         const char *section_label, void **section_data,
+                         void *call_data,
+                         mu_cfg_tree_t *tree)
+{
+  if (stage == mu_cfg_section_start)
+    {
+      struct namespace *ns;
+      
+      if (node->label == NULL || node->label->type != MU_CFG_STRING)
+       return 1;
+
+      ns = namespace_lookup (node->label->v.string);
+      if (!ns)
+       {
+         mu_error (_("unknown namespace"));
+         return 0;
+       }
+       
+      *section_data = ns;
+    }
+  return 0;
+}
+
+static void
+namespace_cfg_init (void)
+{
+  struct mu_cfg_section *section;
+
+  if (mu_create_canned_section ("prefix", &section))
+    abort ();
+  section->docstring = N_("Define a single prefix");
+  mu_cfg_section_add_params (section, prefix_param);
+  section->parser = prefix_section_parser;
+  
+  if (mu_create_canned_section ("namespace", &section))
+    abort ();
+  section->docstring = N_("Define a namespace");
+  section->label = "private | other | shared";
+  section->parser = namespace_section_parser;
+  mu_cfg_section_add_params (section, namespace_param);
+}
+
 static struct mu_cfg_param imap4d_srv_param[] = {
 #ifdef WITH_TLS
   { "tls", mu_cfg_callback,
@@ -385,8 +553,12 @@ static struct mu_cfg_param imap4d_cfg_param[] = {
     0, NULL, 
     N_("Deny access if the user group is in this list.") },
   
+  { "namespace", mu_cfg_section },
+  
+#if 0
   { "homedir", mu_c_string, &modify_homedir, 0, NULL,
     N_("Modify home directory.") },
+
   { "personal-namespace", MU_CFG_LIST_OF(mu_c_string), &namespace[NS_PRIVATE],
     0, NULL, 
     N_("Set personal namespace.") },
@@ -396,6 +568,7 @@ static struct mu_cfg_param imap4d_cfg_param[] = {
   { "shared-namespace", MU_CFG_LIST_OF(mu_c_string), &namespace[NS_SHARED],
     0, NULL,
     N_("Set shared namespace.") },
+  FIXME
   { "other-mailbox-mode", mu_cfg_callback, &mailbox_mode[NS_OTHER], 0,
     cb_mailbox_mode,
     N_("File mode for mailboxes in other namespace."),
@@ -404,6 +577,7 @@ static struct mu_cfg_param imap4d_cfg_param[] = {
     cb_mailbox_mode,
     N_("File mode for mailboxes in shared namespace."),
     N_("mode: g(+|=)[wr]+,o(+|=)[wr]+") },
+#endif
   { "login-disabled", mu_c_bool, &login_disabled, 0, NULL,
     N_("Disable LOGIN command.") },
   { "create-home-dir", mu_c_bool, &create_home_dir, 0, NULL,
@@ -530,52 +704,6 @@ imap4d_session_setup0 ()
   real_homedir = mu_normalize_path (mu_strdup (auth_data->dir));
   if (imap4d_check_home_dir (real_homedir, auth_data->uid, auth_data->gid))
     return 1;
-
-  if (modify_homedir)
-    {
-      char *expr = mu_tilde_expansion (modify_homedir, MU_HIERARCHY_DELIMITER,
-                                      real_homedir);
-      struct mu_wordsplit ws;
-      const char *env[5];
-
-      env[0] = "user";
-      env[1] = auth_data->name;
-      env[2] = "home";
-      env[3] = real_homedir;
-      env[4] = NULL;
-
-      ws.ws_env = env;
-      if (mu_wordsplit (expr, &ws,
-                       MU_WRDSF_NOSPLIT | MU_WRDSF_NOCMD |
-                       MU_WRDSF_ENV | MU_WRDSF_ENV_KV))
-       {
-         mu_error (_("cannot expand line `%s': %s"), expr,
-                   mu_wordsplit_strerror (&ws));
-         return 1;
-       }
-      else if (ws.ws_wordc == 0)
-       {
-         mu_error (_("expanding %s yields empty string"), expr);
-         return 1;
-       }
-      imap4d_homedir = mu_strdup (ws.ws_wordv[0]);
-      if (!imap4d_homedir)
-       {
-         mu_error ("%s", mu_strerror (errno));
-         return 1;
-       }
-    }
-  else
-    imap4d_homedir = mu_strdup (real_homedir);
-
-  if (strcmp (imap4d_homedir, real_homedir)
-      && imap4d_check_home_dir (imap4d_homedir,
-                               auth_data->uid, auth_data->gid))
-    {
-      free (imap4d_homedir);
-      free (real_homedir);
-      return 1;
-    }
   
   if (auth_data->change_uid)
     {
@@ -591,7 +719,6 @@ imap4d_session_setup0 ()
          if (rc)
            {
              mu_error(_("cannot create list: %s"), mu_strerror (rc));
-             free (imap4d_homedir);
              free (real_homedir);
              return 1;
            }
@@ -603,7 +730,6 @@ imap4d_session_setup0 ()
            {
              /* FIXME: When mu_get_user_groups goes to the library, add a
                 diag message here */
-             free (imap4d_homedir);
              free (real_homedir);
              return 1;
            }
@@ -614,15 +740,13 @@ imap4d_session_setup0 ()
            {
              mu_error (_("can't switch to user %s privileges: %s"),
                        auth_data->name, mu_strerror (rc));
-             free (imap4d_homedir);
              free (real_homedir);
              return 1;
            }
        }
     }
 
-  util_chdir (imap4d_homedir);
-  namespace_init_session (imap4d_homedir);
+  util_chdir (real_homedir);
   
   mu_diag_output (MU_DIAG_INFO,
                  _("user `%s' logged in (source: %s)"), auth_data->name,
@@ -936,6 +1060,7 @@ main (int argc, char **argv)
   mu_tcpwrapper_cfg_init ();
   manlock_cfg_init ();
   mu_acl_cfg_init ();
+  namespace_cfg_init ();
   
   mu_m_server_create (&server, program_version);
   mu_m_server_set_config_size (server, sizeof (struct imap4d_srv_config));
@@ -959,6 +1084,8 @@ main (int argc, char **argv)
       mu_error (_("too many arguments"));
       exit (EX_USAGE);
     }
+
+  namespace_init ();
   
   if (test_mode)
     mu_m_server_set_mode (server, MODE_INTERACTIVE);
@@ -966,8 +1093,6 @@ main (int argc, char **argv)
   if (login_disabled)
     imap4d_capability_add (IMAP_CAPA_LOGINDISABLED);
 
-  namespace_init ();
-
   if (mu_gsasl_enabled ())
     {
       auth_gssapi_init ();
diff --git a/imap4d/imap4d.h b/imap4d/imap4d.h
index 8630375..788271d 100644
--- a/imap4d/imap4d.h
+++ b/imap4d/imap4d.h
@@ -197,17 +197,13 @@ struct imap4d_session
   
 extern struct imap4d_command imap4d_command_table[];
 extern mu_mailbox_t mbox;
-extern char *imap4d_homedir;
 extern char *real_homedir;  
-extern char *modify_homedir;
 extern int state;
 extern size_t children;
 extern int is_virtual;
 extern struct mu_auth_data *auth_data; 
 extern const char *program_version;
   
-extern int mailbox_mode[NS_MAX];
-  
 extern int login_disabled;
 extern enum imap4d_preauth preauth_mode;
 extern char *preauth_program;
@@ -394,15 +390,34 @@ extern int imap4d_bye0 (int reason, struct imap4d_command 
*command);
 void imap4d_enter_critical (void);
 void imap4d_leave_critical (void);
 
-
 /* Namespace functions */
-extern mu_list_t namespace[NS_MAX];
-  
-extern int namespace_init_session (char *path);
-extern void namespace_init (void);
-extern char *namespace_getfullpath (const char *name, int *pns);
-extern char *namespace_checkfullpath (const char *name, const char *pattern,
-                                     int *pns);
+struct namespace_prefix
+{
+  char *prefix;              /* Prefix string */
+  int delim;                 /* Delimiter character */
+  char *dir;                 /* Directory in the file system */
+  char *scheme;              /* Mailbox URL scheme (type) */
+  mu_record_t record;        /* The corresponding record */
+  int ns;                    /* Namespace */
+};
+
+struct namespace
+{
+  char const *name;
+  int mode;                  /* File mode for creating new mailboxes */
+  mu_list_t prefixes;        /* List of prefixes (struct namespace_prefix */
+};
+
+void namespace_init (void);
+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);
+
+void translate_delim (char *dst, char const *src, int dst_delim, int 
src_delim);
+
+
 int imap4d_session_setup (char *username);
 int imap4d_session_setup0 (void);
 void imap4d_child_signal_setup (RETSIGTYPE (*handler) (int signo));
@@ -417,7 +432,6 @@ extern void imap4d_capability_init (void);
 extern int  util_start (char *);
 extern int  util_getstate (void);
 extern int  util_do_command (struct imap4d_session *, imap4d_tokbuf_t);
-extern char *util_getfullpath (const char *);
 extern struct imap4d_command *util_getcommand (char *, 
                                                struct imap4d_command []);
 
diff --git a/imap4d/list.c b/imap4d/list.c
index 3b55a6c..07cea67 100644
--- a/imap4d/list.c
+++ b/imap4d/list.c
@@ -23,8 +23,9 @@ struct refinfo
 {
   char *refptr;   /* Original reference */
   size_t reflen;  /* Length of the original reference */
-  size_t pfxlen;  /* Length of the current prefix */
-  size_t homelen; /* Length of homedir */
+  struct namespace_prefix const *pfx;
+  size_t pfxlen;
+  size_t dirlen;  /* Length of the current directory prefix */
   char *buf;
   size_t bufsize;
 };
@@ -35,12 +36,15 @@ list_fun (mu_folder_t folder, struct mu_list_response 
*resp, void *data)
   char *name;
   struct refinfo *refinfo = data;
   size_t size;
+  char *p;
+
+  if (refinfo->pfx->record && refinfo->pfx->record != resp->format)
+    return 0;
   
   name = resp->name;
   size = strlen (name);
-  if (size == refinfo->homelen + 6
-      && memcmp (name, imap4d_homedir, refinfo->homelen) == 0
-      && memcmp (name + refinfo->homelen + 1, "INBOX", 5) == 0)
+  if (size == refinfo->pfxlen + 6
+      && memcmp (name + refinfo->pfxlen + 1, "INBOX", 5) == 0)
     return 0;
      
   io_sendf ("* %s", "LIST (");
@@ -52,10 +56,10 @@ list_fun (mu_folder_t folder, struct mu_list_response 
*resp, void *data)
   else if (resp->type & MU_FOLDER_ATTRIBUTE_DIRECTORY)
     io_sendf ("\\NoSelect");
   
-  io_sendf (") \"%c\" ", resp->separator);
+  io_sendf (") \"%c\" ", refinfo->pfx->delim);
 
-  name = resp->name + refinfo->pfxlen;
-  size = strlen (name) + refinfo->reflen + 1;
+  name = resp->name + refinfo->dirlen + 1;
+  size = strlen (name) + refinfo->pfxlen + 2;
   if (size > refinfo->bufsize)
     {
       if (refinfo->buf == NULL)
@@ -82,10 +86,17 @@ list_fun (mu_folder_t folder, struct mu_list_response 
*resp, void *data)
        }
     }
 
-  if ((refinfo->reflen == 0 || refinfo->refptr[refinfo->reflen - 1] == '/')
-      && name[0] == '/')
-    name++;
-  strcpy (refinfo->buf + refinfo->reflen, name);
+  if (refinfo->pfxlen)
+    {
+      p = mu_stpcpy (refinfo->buf, refinfo->pfx->prefix);
+      if (*name)
+       *p++ = refinfo->pfx->delim;
+    }
+  else
+    p = refinfo->buf;
+  if (*name)
+    translate_delim (p, name, refinfo->pfx->delim, resp->separator);
+
   name = refinfo->buf;
   
   if (strpbrk (name, "\"{}"))
@@ -168,69 +179,84 @@ imap4d_list (struct imap4d_session *session,
     {
       int status;
       mu_folder_t folder;
+      mu_url_t url;
       char *cwd;
+      char const *dir;
       struct refinfo refinfo;
       size_t i;
+      struct namespace_prefix const *pfx;
+
+      if (*wcard == '~')
+       {
+         for (i = 1;
+              mu_c_is_class (wcard[i], MU_CTYPE_ALPHA|MU_CTYPE_DIGIT)
+                || wcard[i] == '_'; i++)
+           ;
+         ref = mu_alloc (i + 1);
+         memcpy (ref, wcard, i);
+         ref[i] = 0;
+         wcard += i;
+       }
+      else
+       ref = mu_strdup (ref);
+      
+      cwd = namespace_translate_name (ref, 0, &pfx);
+      if (!cwd)
+       {
+         free (ref);
+         return io_completion_response (command, RESP_NO,
+                                     "The requested item could not be found.");
+       }
+      free (cwd);
       
-      switch (*wcard)
+      if (*wcard == pfx->delim && ref[0] != '~')
        {
          /* Absolute Path in wcard, dump the old ref.  */
-       case '/':
-         ref = mu_strdup ("/");
-         wcard++;
-         break;
-
-         /* Absolute Path, but take care of things like ~guest/Mail,
-            ref becomes ref = ~guest.  */
-       case '~':
-         {
-           char *s = strchr (wcard, '/');
-           if (s)
-             {
-               ref = calloc (s - wcard + 1, 1);
-               memcpy (ref, wcard, s - wcard);
-               ref [s - wcard] = '\0';
-               wcard = s + 1;
-             }
-           else
-             {
-               ref = mu_strdup (wcard);
-               wcard += strlen (wcard);
-             }
-         }
-         break;
-
-       default:
-         ref = mu_strdup (ref);
+         ref[0] = 0;
        }
-
+      
       /* Find the longest directory prefix */
       i = strcspn (wcard, "%*");
-      while (i > 0 && wcard[i - 1] != '/')
+      while (i > 0 && wcard[i - 1] != pfx->delim)
        i--;
       /* Append it to the reference */
       if (i)
        {
          size_t reflen = strlen (ref);
-         int addslash = (reflen > 0 && ref[reflen-1] != '/'); 
+         int addslash = (reflen > 0
+                         && ref[reflen-1] != pfx->delim
+                         && *wcard != pfx->delim); 
          size_t len = i + reflen + addslash;
 
          ref = mu_realloc (ref, len);
          if (addslash)
-           ref[reflen++] = '/';
+           ref[reflen++] = pfx->delim;
          memcpy (ref + reflen, wcard, i - 1); /* omit the trailing / */
          ref[len-1] = 0;
+
+         wcard += i;
        }
 
-      /* Allocates.  */
-      cwd = namespace_checkfullpath (ref, wcard, NULL);
+      cwd = namespace_translate_name (ref, 0, &pfx);
       if (!cwd)
        {
          free (ref);
          return io_completion_response (command, RESP_NO,
-                                     "The requested item could not be found.");
+                                     "The requested item could not be found.");
        }
-
+      
+      if (pfx->ns == NS_OTHER
+         && strcmp (ref, pfx->prefix) == 0
+         && *mu_str_skip_cset_comp (wcard, "*%"))
+       {
+         /* [A] server MAY return NO to such a LIST command, requiring that a
+            user name be included with the Other Users' Namespace prefix
+            before listing any other user's mailboxes */
+         free (ref);
+         return io_completion_response (command, RESP_NO,
+                                     "The requested item could not be found.");
+       }         
+       
       status = mu_folder_create (&folder, cwd);
       if (status)
        {
@@ -246,8 +272,13 @@ imap4d_list (struct imap4d_session *session,
 
       refinfo.refptr = ref;
       refinfo.reflen = strlen (ref);
-      refinfo.pfxlen = strlen (cwd);
-      refinfo.homelen = strlen (imap4d_homedir);
+      refinfo.pfx = pfx;
+      
+      mu_folder_get_url (folder, &url);
+      mu_url_sget_path (url, &dir);
+      refinfo.dirlen = strlen (dir);
+            
+      refinfo.pfxlen = strlen (pfx->prefix);
 
       /* The special name INBOX is included in the output from LIST, if
         INBOX is supported by this server for this user and if the
diff --git a/imap4d/namespace.c b/imap4d/namespace.c
index 383bccd..cd3ae43 100644
--- a/imap4d/namespace.c
+++ b/imap4d/namespace.c
@@ -16,93 +16,407 @@
    along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>. */
 
 #include "imap4d.h"
+#include <mailutils/assoc.h>
 
-typedef int (*nsfp_t) (void *closure, int ns, char *path, int delim);
+struct namespace namespace[NS_MAX] = {
+  [NS_PRIVATE] = { "private" },
+  [NS_OTHER]   = { "other" },
+  [NS_SHARED]  = { "shared" }
+};
+  
+static mu_assoc_t prefixes;
 
-mu_list_t namespace[NS_MAX];
+struct namespace *
+namespace_lookup (char const *name)
+{
+  size_t i;
+  
+  for (i = 0; i < NS_MAX; i++)
+    if (strcmp (namespace[i].name, name) == 0)
+      {
+       if (!namespace[i].prefixes)
+         {
+           int rc = mu_list_create (&namespace[i].prefixes);
+           if (rc)
+             {
+               mu_diag_funcall (MU_DIAG_ERROR, "mu_list_create", NULL, rc);
+               abort ();
+             }
+         }
+       return &namespace[i];
+      }
+  return NULL;
+}
+
+static int
+cmplen (const char *aname, const void *adata,
+       const char *bname, const void *bdata,
+       void *closure)
+{
+  return strlen (bname) - strlen (aname);
+}
 
-static const char *
-printable_pathname (const char *str)
+void
+translate_delim (char *dst, char const *src, int dst_delim, int src_delim)
 {
-  if (strncmp (str, imap4d_homedir, strlen (imap4d_homedir)) == 0)
+  do
+    *dst++ = *src == src_delim ? dst_delim : *src;
+  while (*src++);
+}  
+
+static void
+trim_delim (char *str, int delim)
+{
+  size_t len = strlen (str);
+  while (len && str[len-1] == '/')
+    len--;
+  str[len] = 0;
+}
+
+void
+namespace_init (void)
+{
+  int i;
+  int rc;
+  struct namespace_prefix *pfx;
+  
+  if (mu_assoc_create (&prefixes, 0))
+    imap4d_bye (ERR_NO_MEM);
+  for (i = 0; i < NS_MAX; i++)
+    {
+      mu_iterator_t itr;
+      
+      if (mu_list_is_empty (namespace[i].prefixes))
+       continue;
+      
+      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))
+       {
+         rc = mu_iterator_current (itr, (void **)&pfx);
+         if (rc)
+           {
+             mu_diag_funcall (MU_DIAG_ERROR, "mu_iterator_current", NULL, rc);
+             continue;
+           }
+         pfx->ns = i;
+
+         trim_delim (pfx->prefix, pfx->delim);
+         trim_delim (pfx->dir, '/');
+         
+         rc = mu_assoc_install (prefixes, pfx->prefix, pfx);
+         if (rc == MU_ERR_EXISTS)
+           {
+             mu_error (_("%s: namespace prefix appears twice"), pfx->prefix);
+             exit (EX_CONFIG);
+           }
+         else if (rc)
+           {
+             mu_error (_("%s: can't install prefix: %s"),
+                       pfx->prefix, mu_strerror (rc));
+             exit (EX_CONFIG);
+           }
+       }
+    }
+
+  pfx = mu_assoc_get (prefixes, "");
+  if (pfx)
+    {
+      if (pfx->ns != NS_PRIVATE)
+       {
+         mu_error (_("empty prefix not allowed in the namespace %s"),
+                   namespace[pfx->ns].name);
+         exit (EX_CONFIG);
+       }
+    }
+  else
     {
-      str += strlen (imap4d_homedir);
-      if (str[0] == '/')
-       str++;
+      struct namespace *priv;
+      
+      pfx = mu_zalloc (sizeof (*pfx));
+      pfx->prefix = mu_strdup ("");
+      pfx->dir = mu_strdup ("$home");
+      pfx->delim = '/';
+      priv = namespace_lookup ("private");
+      mu_list_prepend (priv->prefixes, pfx);
+      rc = mu_assoc_install (prefixes, pfx->prefix, pfx);
+      if (rc)
+       {
+         mu_error (_("%s: can't install prefix: %s"),
+                   pfx->prefix, mu_strerror (rc));
+         exit (EX_CONFIG);
+       }
     }
-  return str;
+  
+  mu_assoc_sort_r (prefixes, cmplen, NULL);
 }
-
+      
 static int
-print_namespace_fun (void *item, void *data)
+expand_vars (char **env, char const *input, char **output)
 {
-  int *pcount = data;
-  const char *dir = printable_pathname (item);
-  char *suf = (dir[0] && dir[strlen (dir) - 1] != '/') ? "/" : "";
-  if ((*pcount)++)
-    io_sendf (" ");
-  io_sendf ("(\"%s%s\" \"/\")", dir, suf);
+  struct mu_wordsplit ws;
+  size_t wordc;
+  char **wordv;
+  
+  ws.ws_env = (const char **) env;
+  if (mu_wordsplit (input, &ws,
+                   MU_WRDSF_NOSPLIT | MU_WRDSF_NOCMD |
+                   MU_WRDSF_ENV | MU_WRDSF_ENV_KV))
+    {
+      mu_error (_("cannot expand line `%s': %s"), input,
+               mu_wordsplit_strerror (&ws));
+      return 1;
+    }
+  mu_wordsplit_get_words (&ws, &wordc, &wordv);
+  *output = wordv[0];
+  mu_wordsplit_free (&ws);
   return 0;
 }
 
-static void
-print_namespace (int nsid)
+static char *
+prefix_translate_name (struct namespace_prefix const *pfx, char const *name,
+                      size_t namelen, int url)
 {
-  mu_list_t list = namespace[nsid];
-  if (!list)
-    io_sendf ("NIL");
-  else
+  size_t pfxlen = strlen (pfx->prefix);
+
+  if (pfxlen <= namelen
+      && memcmp (pfx->prefix, name, pfxlen) == 0
+      && (pfxlen == 0 || pfxlen == namelen || name[pfxlen] == pfx->delim))
     {
-      int count;
-      count = 0;
-      io_sendf ("(");
-      mu_list_foreach (list, print_namespace_fun, &count);
-      io_sendf (")");
+      char *tmpl, *p;
+
+      if (!pfx->scheme)
+       url = 0;
+      name += pfxlen;
+
+      if (pfx->ns == NS_PRIVATE && strcmp (name, "INBOX") == 0)
+       {
+         tmpl = mu_strdup (auth_data->mailbox);
+         return tmpl;//FIXME
+       }
+      
+      tmpl = mu_alloc (namelen - pfxlen + strlen (pfx->dir)
+                      + (url ? strlen (pfx->scheme) + 3 : 0)
+                      + 2);
+      if (url)
+       {
+         p = mu_stpcpy (tmpl, pfx->scheme);
+         p = mu_stpcpy (p, "://");
+       }
+      else
+       p = tmpl;
+      
+      p = mu_stpcpy (p, pfx->dir);
+      if (*name)
+       {
+         *p++ = '/';
+         translate_delim (p, name, '/', pfx->delim);
+       }
+
+      return tmpl;
     }
+  return NULL;
 }
 
-struct ns_closure
+static char *
+i_translate_name (char const *name, int url, int ns,
+                 struct namespace_prefix const **return_pfx)
 {
-  int id;
-  nsfp_t fun;
-  void *closure;
-};
+  mu_iterator_t itr;
+  int rc;
+  char *res = NULL;
+  size_t namelen = strlen (name);
+
+#if 0
+  FIXME
+   if (namelen >= 5
+      && strcmp (name + namelen - 5, "INBOX") == 0
+      && (namelen == 5 && name[namelen - 6] == '/'))
+    {
+    } 
+#endif
+  
+  rc = mu_assoc_get_iterator (prefixes, &itr);
+  if (rc)
+    {
+      mu_diag_funcall (MU_DIAG_ERROR, "mu_assoc_get_iterator", NULL, rc);
+      return NULL;
+    }
+  for (mu_iterator_first (itr);
+       !mu_iterator_is_done (itr); mu_iterator_next (itr))
+    {
+      struct namespace_prefix *pfx;
+      
+      rc = mu_iterator_current (itr, (void **)&pfx);
+      if (rc)
+       {
+         mu_diag_funcall (MU_DIAG_ERROR, "mu_iterator_current", NULL, rc);
+         continue;
+       }
 
-static int
-_enum_fun (void *item, void *data)
-{
-  struct ns_closure *nsp = data;
-  return nsp->fun (nsp->closure, nsp->id, (char*) item, '/');
+      if (ns != NS_MAX && ns != pfx->ns)
+       continue;
+      
+      res = prefix_translate_name (pfx, name, namelen, url);
+      if (res)
+       {
+         if (return_pfx)
+           *return_pfx = pfx;
+         break;
+       }
+    }
+  mu_iterator_destroy (&itr);
+
+  return res;
 }
+
+static char *
+extract_username (char const *name, struct namespace_prefix const *pfx)
+{
+  char const *p = name + strlen (pfx->prefix);
+  char *end = strchr (p, pfx->delim);
+  char *user;
+  size_t len;
   
-static int
-namespace_enumerate (int id, nsfp_t f, void *closure)
+  if (end)
+    len = end - p;
+  else
+    len = strlen (p);
+  
+  user = mu_alloc (len + 1);
+  memcpy (user, p, len);
+  user[len] = 0;
+  return user;
+}
+
+enum
+  {
+    ENV_USER = 1,
+    ENV_HOME = 3,
+    ENV_NULL = 4
+  };
+
+#define ENV_INITIALIZER \
+  { [ENV_USER-1] = "user", [ENV_HOME-1] = "home", [ENV_NULL] = NULL }
+
+char *
+namespace_translate_name (char const *name, int url,
+                         struct namespace_prefix const **return_pfx)
 {
-  struct ns_closure nsc;
+  char *res = NULL;
+  struct namespace_prefix const *pfx;
+  char *env[] = ENV_INITIALIZER;
+  
+  if (name[0] == '~')
+    {
+      if (name[1] == 0 || name[1] == '/')
+       {
+         if (mu_c_strcasecmp (name, "INBOX") == 0 && auth_data->change_uid)
+           res = mu_strdup (auth_data->mailbox);
+         else
+           res = i_translate_name (name, url, NS_PRIVATE, &pfx);
+       }
+      else 
+       res = i_translate_name (name, url, NS_OTHER, &pfx);
+    }
+  else
+    res = i_translate_name (name, url, NS_MAX, &pfx);
 
-  nsc.id = id;
-  nsc.fun = f;
-  nsc.closure = closure;
-  if (namespace[id])
+  if (res)
     {
-      int rc = mu_list_foreach (namespace[id], _enum_fun, &nsc);
-      if (rc == MU_ERR_USER0)
-       return 1;
-      else if (rc != 0)
+      char *dir;
+      
+      switch (pfx->ns)
        {
-         mu_diag_funcall (MU_DIAG_ERROR, "mu_list_foreach", NULL, rc);
-         return 0;
+       case NS_PRIVATE:
+         env[ENV_USER] = auth_data->name;
+         env[ENV_HOME] = real_homedir;
+         break;
+
+       case NS_SHARED:
+         {
+           struct mu_auth_data *adata;
+           env[ENV_USER] = extract_username (name, pfx);
+           adata = mu_get_auth_by_name (env[ENV_USER]);
+           if (adata)
+             {
+               env[ENV_HOME] = mu_strdup (adata->dir);
+               mu_auth_data_free (adata);
+             }
+         }
+         break;
+
+       case NS_OTHER:
+         break;
        }
+      
+      if (expand_vars (env, res, &dir))
+       imap4d_bye (ERR_NO_MEM);
+      free (res);
+      res = dir;
+      trim_delim (res, '/');
+      
+      if (pfx->ns == NS_OTHER)
+       {
+         free (env[ENV_USER]);
+         free (env[ENV_HOME]);
+       }
+      
+      if (return_pfx)
+       *return_pfx = pfx;
     }
-  return 0;
+  return res;
 }
 
+char *
+namespace_get_url (char const *name, 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;
+    }
+  if (mode)
+    *mode = namespace[pfx->ns].mode;
+  return path;
+}
+
 static int
-namespace_enumerate_all (nsfp_t f, void *closure)
+prefix_printer(void *item, void *data)
 {
-  return namespace_enumerate (NS_PRIVATE, f, closure)
-    || namespace_enumerate (NS_OTHER, f, closure)
-    || namespace_enumerate (NS_SHARED, f, closure);
+  struct namespace_prefix *pfx = item;
+  int *first = data;
+
+  if (*first)
+    *first = 0;
+  else
+    io_sendf (" ");
+  io_sendf ("(\"%s\" \"%c\")", pfx->prefix, pfx->delim);
+  return 0;
+}
+
+static void
+print_namespace (int ns)
+{
+  if (mu_list_is_empty (namespace[ns].prefixes))
+    io_sendf ("NIL");
+  else
+    {
+      int first = 1;
+      io_sendf ("(");
+      mu_list_foreach (namespace[ns].prefixes, prefix_printer, &first);
+      io_sendf (")");
+    }
 }
 
 /*
@@ -139,153 +453,3 @@ imap4d_namespace (struct imap4d_session *session,
 
   return io_completion_response (command, RESP_OK, "Completed");
 }
-
-
-struct namespace_info
-{
-  char *name;
-  int namelen;
-  int ns;
-  int exact;
-};
-
-static int
-check_namespace (void *closure, int ns, char *path, int delim)
-{
-  struct namespace_info *p = (struct namespace_info *) closure;
-  int len = strlen (path);
-  if ((len == 0 && p->namelen == len)
-      || (len > 0 && strncmp (path, p->name, strlen (path)) == 0))
-    {
-      p->ns = ns;
-      p->exact = len == p->namelen;
-      return MU_ERR_USER0;
-    }
-  return 0;
-}
-
-static int
-risky_pattern (const char *pattern, int delim)
-{
-  for (; *pattern && *pattern != delim; pattern++)
-    {
-      if (*pattern == '%' || *pattern == '*')
-       return 1;
-    }
-  return 0;
-}
-
-char *
-namespace_checkfullpath (const char *name, const char *pattern, 
-                        int *nspace)
-{
-  struct namespace_info info;
-  const char *p;
-  char *path = NULL;
-  char *scheme = NULL;
-
-  p = strchr (name, ':');
-  if (p)
-    {
-      size_t size = p - name + 1;
-      scheme = malloc (size + 1);
-      if (!scheme)
-       return NULL;
-      memcpy (scheme, name, size);
-      scheme[size] = 0;
-      name = p + 1;
-    }
-
-  path = util_getfullpath (name);
-  if (!path)
-    {
-      free (scheme);
-      return path;
-    }
-  info.name = path;
-  info.namelen = strlen (path);
-  if (!namespace_enumerate_all (check_namespace, &info))
-    {
-      free (scheme);
-      free (path);
-      return NULL;
-    }
-
-  if (pattern &&
-      info.ns == NS_OTHER && info.exact && risky_pattern (pattern, '/'))
-    {
-      free (scheme);
-      free (path);
-      return NULL;
-    }
-
-  if (nspace)
-    *nspace = info.ns;
-  if (scheme)
-    {
-      char *pathstr = malloc (strlen (scheme) + strlen (path) + 2);
-      if (pathstr)
-       {
-         strcpy (pathstr, scheme);
-         strcat (pathstr, path);
-       }
-      free (scheme);
-      free (path);
-      path = pathstr;
-    }
-  return path;
-}
-
-char *
-namespace_getfullpath (const char *name, int *nspace)
-{
-  char *ret;
-  if (mu_c_strcasecmp (name, "INBOX") == 0 && auth_data->change_uid)
-    {
-      ret = mu_strdup (auth_data->mailbox);
-      if (nspace)
-       *nspace = NS_PRIVATE;
-    }
-  else
-    ret = namespace_checkfullpath (name, NULL, nspace);
-  return ret;
-}
-
-int
-namespace_init_session (char *path)
-{
-  if (!namespace[NS_PRIVATE])
-    mu_list_create (&namespace[NS_PRIVATE]);
-  mu_list_prepend (namespace[NS_PRIVATE],
-                  mu_strdup (mu_normalize_path (path)));
-  return 0;
-}
-
-static int
-normalize_fun (void *item, void *data)
-{
-  char *name = item;
-  mu_list_t list = data;
-  return mu_list_append (list,
-                        mu_strdup (mu_normalize_path (name)));
-}
-
-void
-namespace_init ()
-{
-  int i;
-
-  for (i = 0; i < NS_MAX; i++)
-    {
-      if (namespace[i])
-       {
-         mu_list_t list;
-         mu_list_create (&list);
-         mu_list_set_destroy_item (list, mu_list_free_item);
-         mu_list_foreach (namespace[i], normalize_fun, list);
-         mu_list_set_destroy_item (namespace[i], mu_list_free_item);
-         mu_list_destroy (&namespace[i]);
-         namespace[i] = list;
-       }
-    }
-}
diff --git a/imap4d/quota.c b/imap4d/quota.c
index 5ccf7d2..b6a9af2 100644
--- a/imap4d/quota.c
+++ b/imap4d/quota.c
@@ -120,9 +120,9 @@ directory_size (const char *dirname, mu_off_t *size)
 mu_off_t used_size;
 
 void
-quota_setup ()
+quota_setup (void)
 {
-  directory_size (imap4d_homedir, &used_size);
+  directory_size (real_homedir, &used_size);
 }
 
 int
@@ -138,7 +138,7 @@ quota_check (mu_off_t size)
 
   total = used_size;
 
-  mailbox_name = namespace_getfullpath ("INBOX", NULL);
+  mailbox_name = namespace_get_url ("INBOX", NULL);
   rc = mu_mailbox_create (&mbox, mailbox_name);
   if (rc)
     {
diff --git a/imap4d/rename.c b/imap4d/rename.c
index 6153644..56e5d31 100644
--- a/imap4d/rename.c
+++ b/imap4d/rename.c
@@ -109,7 +109,7 @@ imap4d_rename (struct imap4d_session *session,
   int rc = RESP_OK;
   const char *msg = "Completed";
   struct stat newst;
-  int ns;
+  int mode = 0;
   
   if (imap4d_tokbuf_argc (tok) != 4)
     return io_completion_response (command, RESP_BAD, "Invalid arguments");
@@ -121,7 +121,7 @@ imap4d_rename (struct imap4d_session *session,
     return io_completion_response (command, RESP_NO, "Name Inbox is 
reservered");
 
   /* Allocates memory.  */
-  newname = namespace_getfullpath (newname, &ns);
+  newname = namespace_get_url (newname, &mode);
   if (!newname)
     return io_completion_response (command, RESP_NO, "Permission denied");
 
@@ -160,8 +160,7 @@ imap4d_rename (struct imap4d_session *session,
        }
       if (mu_mailbox_create (&newmbox, newname) != 0
          || mu_mailbox_open (newmbox,
-                             MU_STREAM_CREAT | MU_STREAM_RDWR
-                               | mailbox_mode[ns]) != 0)
+                             MU_STREAM_CREAT | MU_STREAM_RDWR | mode) != 0)
        {
          free (newname);
          return io_completion_response (command, RESP_NO,
@@ -200,7 +199,7 @@ imap4d_rename (struct imap4d_session *session,
       return io_completion_response (command, RESP_OK, "Rename successful");
     }
 
-  oldname = namespace_getfullpath (oldname, NULL);
+  oldname = namespace_get_url (oldname, NULL);
 
   /* It must exist.  */
   /* FIXME: 1. What if odlname or newname is a remote mailbox?
diff --git a/imap4d/select.c b/imap4d/select.c
index 1f0759b..f81b8a0 100644
--- a/imap4d/select.c
+++ b/imap4d/select.c
@@ -59,7 +59,7 @@ imap4d_select0 (struct imap4d_command *command, const char 
*mboxname,
 
   if (strcmp (mboxname, "INBOX") == 0)
     flags |= MU_STREAM_CREAT;
-  mailbox_name = namespace_getfullpath (mboxname, NULL);
+  mailbox_name = namespace_translate_name (mboxname, 1, NULL);
 
   if (!mailbox_name)
     return io_completion_response (command, RESP_NO, "Couldn't open mailbox");
diff --git a/imap4d/status.c b/imap4d/status.c
index f2e85e4..c8efd48 100644
--- a/imap4d/status.c
+++ b/imap4d/status.c
@@ -81,7 +81,7 @@ imap4d_status (struct imap4d_session *session,
   
   name = imap4d_tokbuf_getarg (tok, IMAP4_ARG_1);
 
-  mailbox_name = namespace_getfullpath (name, NULL);
+  mailbox_name = namespace_get_url (name, NULL);
 
   if (!mailbox_name)
     return io_completion_response (command, RESP_NO, "Error opening mailbox");
diff --git a/imap4d/tests/IDEF0955.at b/imap4d/tests/IDEF0955.at
index f24f223..eaf510a 100644
--- a/imap4d/tests/IDEF0955.at
+++ b/imap4d/tests/IDEF0955.at
@@ -28,7 +28,11 @@ EOT
 
 MUT_MBCOPY($abs_top_srcdir/testsuite/spool/mbox1,INBOX)
 
-imap4d IMAP4D_OPTIONS < input | remove_uidvalidity | tr -d '\r'
+IMAP4D_RUN([1 select INBOX
+2 FETCH 1:$MU_ULONG_MAX_1 FLAGS
+3 UID FETCH 1:$MU_ULONG_MAX_1 FLAGS
+X LOGOUT
+],[expand]) | remove_uidvalidity 
 ],
 [0],
 [* PREAUTH IMAP4rev1 Test mode
diff --git a/imap4d/tests/IDEF0956.at b/imap4d/tests/IDEF0956.at
index a1c3638..4861096 100644
--- a/imap4d/tests/IDEF0956.at
+++ b/imap4d/tests/IDEF0956.at
@@ -20,14 +20,14 @@ AT_CHECK([
 test "$MU_ULONG_MAX_1" = 0 && AT_SKIP_TEST
 
 cat > input <<EOT
-1 select INBOX
-2 FETCH 1 BODY[[TEXT]]<0.$MU_ULONG_MAX_1>
-X LOGOUT
 EOT
 
 MUT_MBCOPY($abs_top_srcdir/testsuite/spool/search.mbox,INBOX)
 
-imap4d IMAP4D_OPTIONS < input | remove_uidvalidity | tr -d '\r'
+IMAP4D_RUN([1 select INBOX
+2 FETCH 1 BODY[[TEXT]]<0.$MU_ULONG_MAX_1>
+X LOGOUT
+],[expand]) | remove_uidvalidity
 ],
 [0],
 [* PREAUTH IMAP4rev1 Test mode
diff --git a/imap4d/tests/append00.at b/imap4d/tests/append00.at
index f62c35d..7aec481 100644
--- a/imap4d/tests/append00.at
+++ b/imap4d/tests/append00.at
@@ -17,8 +17,9 @@
 AT_SETUP([append with flags])
 AT_KEYWORDS([append00])
 
-AT_DATA([input],
-[1 APPEND mbox (\Seen) {300+}
+AT_CHECK([
+> mbox
+IMAP4D_RUN([1 APPEND mbox (\Seen) {300+}
 Date: Mon, 7 Feb 1994 21:52:25 -0800 (PST)
 From: Fred Foobar <address@hidden>
 Subject: afternoon meeting
@@ -31,10 +32,6 @@ Hello Joe, do you think we can meet at 3:30 tomorrow
 
 X LOGOUT
 ])
-
-AT_CHECK([
-> mbox
-imap4d IMAP4D_OPTIONS < input | tr -d '\r'
 echo "=="
 awk 'NR==1 {print "1:",$1,$2; next} NF==0 {print NR":"; next} {print 
NR":",$0}' mbox
 ],
diff --git a/imap4d/tests/append01.at b/imap4d/tests/append01.at
index b9b0ac3..37e82dd 100644
--- a/imap4d/tests/append01.at
+++ b/imap4d/tests/append01.at
@@ -17,8 +17,9 @@
 AT_SETUP([append with envelope date])
 AT_KEYWORDS([append01])
 
-AT_DATA([input],
-[1 APPEND mbox "25-Aug-2002 18:00:00 +0200" {274+}
+AT_CHECK([
+> mbox
+IMAP4D_RUN([1 APPEND mbox "25-Aug-2002 18:00:00 +0200" {274+}
 Date: Mon, 7 Feb 1994 21:52:25 -0800 (PST)
 From: Fred Foobar <address@hidden>
 Subject: afternoon meeting again
@@ -31,10 +32,6 @@ Better yet at 04:00?
 
 X LOGOUT
 ])
-
-AT_CHECK([
-> mbox
-imap4d IMAP4D_OPTIONS < input | tr -d '\r'
 echo "=="
 awk 'NF==0 {print NR":"; next} {print NR":",$0}' mbox
 ],
diff --git a/imap4d/tests/atlocal.in b/imap4d/tests/atlocal.in
index bb7120b..9c9d5fa 100644
--- a/imap4d/tests/atlocal.in
+++ b/imap4d/tests/atlocal.in
@@ -5,6 +5,35 @@
 address@hidden@:@abs_top_builddir@/imap4d:$top_srcdir:$srcdir:$PATH
 address@hidden@
 
+make_config() {
+    CWD=`pwd`
+    HOMEDIR=${CWD}${1:+/}$1
+    cat > imap4d.conf <<EOT
+logging {
+       syslog off;
+       severity notice;
+}
+
+gsasl {
+       enable off;
+}
+
+namespace private {
+       prefix "" {
+               directory "$HOMEDIR";
+       }
+       prefix "~" {
+               directory "$HOMEDIR";
+       }
+}
+
+mailbox {
+       folder "$CWD";
+       mailbox-pattern "$CWD/INBOX";
+}      
+EOT
+}
+
 remove_untagged() {
   sed '/^\*/d'
 }
diff --git a/imap4d/tests/create01.at b/imap4d/tests/create01.at
index 4df890c..3c145a1 100644
--- a/imap4d/tests/create01.at
+++ b/imap4d/tests/create01.at
@@ -18,12 +18,9 @@ AT_SETUP([create])
 AT_KEYWORDS([create create00])
 
 AT_CHECK([
-AT_DATA([input],[dnl
-1 create flat
+IMAP4D_RUN([1 create flat
 X LOGOUT
 ])
-
-imap4d IMAP4D_OPTIONS < input | tr -d '\r'
 find . -name flat
 ],
 [0],
diff --git a/imap4d/tests/create02.at b/imap4d/tests/create02.at
index fc61490..e9f7f21 100644
--- a/imap4d/tests/create02.at
+++ b/imap4d/tests/create02.at
@@ -18,12 +18,9 @@ AT_SETUP([create nested])
 AT_KEYWORDS([create create01])
 
 AT_CHECK([
-AT_DATA([input],[dnl
-1 create en/to/tre
+IMAP4D_RUN([1 create en/to/tre
 X LOGOUT
 ])
-
-imap4d IMAP4D_OPTIONS < input | tr -d '\r'
 find . -name tre
 ],
 [0],
diff --git a/imap4d/tests/list.at b/imap4d/tests/list.at
index 452517d..d880b90 100644
--- a/imap4d/tests/list.at
+++ b/imap4d/tests/list.at
@@ -79,55 +79,35 @@ LIST_CHECK([empty ref + asterisk],[list02],
 LIST_CHECK([root ref + asterisk],[list03],
 ["/" "*"],
 [dnl
-1 NO LIST The requested item could not be found.
+* LIST (\NoInferiors) "/" bigto.mbox
+* LIST (\NoInferiors) "/" mbox
+* LIST (\NoInferiors) "/" mbox1
+* LIST (\NoInferiors) "/" relational.mbox
+* LIST (\NoInferiors) "/" search.mbox
+* LIST (\NoInferiors) "/" sieve.mbox
+* LIST (\NoInferiors) "/" teaparty.mbox
 ])
 
 LIST_CHECK([absolute reference + asterisk],[list04],
-["$cwd/spool" "*"],
-[dnl
-* LIST (\NoInferiors) "/" ////bigto.mbox
-* LIST (\NoInferiors) "/" ////folder/one
-* LIST (\NoInferiors) "/" ////folder/two
-* LIST (\NoInferiors) "/" ////mbox
-* LIST (\NoInferiors) "/" ////mbox1
-* LIST (\NoInferiors) "/" ////relational.mbox
-* LIST (\NoInferiors) "/" ////search.mbox
-* LIST (\NoInferiors) "/" ////sieve.mbox
-* LIST (\NoInferiors) "/" ////teaparty.mbox
-* LIST (\NoSelect) "/" ////folder
-],
+["/foo/bar/baz" "*"],
+[],
 [mkdir IMAP4D_HOMEDIR/folder
  MUT_MBCOPY($abs_top_srcdir/testsuite/folder/one,IMAP4D_HOMEDIR/folder)
- MUT_MBCOPY($abs_top_srcdir/testsuite/folder/two,IMAP4D_HOMEDIR/folder)],
-[sed "s|$cwd/IMAP4D_HOMEDIR|///|"],
-[expand])
+ MUT_MBCOPY($abs_top_srcdir/testsuite/folder/two,IMAP4D_HOMEDIR/folder)])
 
 LIST_CHECK([absolute reference + percent],[list05],
-["$cwd/spool" "%"],
-[dnl
-* LIST (\NoInferiors) "/" ////bigto.mbox
-* LIST (\NoInferiors) "/" ////mbox
-* LIST (\NoInferiors) "/" ////mbox1
-* LIST (\NoInferiors) "/" ////relational.mbox
-* LIST (\NoInferiors) "/" ////search.mbox
-* LIST (\NoInferiors) "/" ////sieve.mbox
-* LIST (\NoInferiors) "/" ////teaparty.mbox
-* LIST (\NoSelect) "/" ////folder
-],
+["/foo/bar/baz" "%"],
+[],
 [mkdir IMAP4D_HOMEDIR/folder
  MUT_MBCOPY($abs_top_srcdir/testsuite/folder/one,IMAP4D_HOMEDIR/folder)
- MUT_MBCOPY($abs_top_srcdir/testsuite/folder/two,IMAP4D_HOMEDIR/folder)],
-[sed "s|$cwd/IMAP4D_HOMEDIR|///|"],
-[expand])
+ MUT_MBCOPY($abs_top_srcdir/testsuite/folder/two,IMAP4D_HOMEDIR/folder)])
 
 LIST_CHECK([absolute reference + mailbox],[list06],
-["$cwd/spool" "search.mbox"],
-[dnl
-* LIST (\NoInferiors) "/" ////search.mbox
-],
+["/foo/bar/baz" "mbox"],
 [],
-[sed "s|$cwd/IMAP4D_HOMEDIR|///|"],
-[expand])
+[mkdir IMAP4D_HOMEDIR/folder
+ MUT_MBCOPY($abs_top_srcdir/testsuite/folder/one,IMAP4D_HOMEDIR/folder)
+ MUT_MBCOPY($abs_top_srcdir/testsuite/folder/two,IMAP4D_HOMEDIR/folder)])
 
 LIST_CHECK([empty reference + INBOX],[list07],
 ["" INBOX],
diff --git a/imap4d/tests/testsuite.at b/imap4d/tests/testsuite.at
index 227e405..4bb3c15 100644
--- a/imap4d/tests/testsuite.at
+++ b/imap4d/tests/testsuite.at
@@ -19,14 +19,9 @@ m4_include([testsuite.inc])
 m4_define([IMAP4D_HOMEDIR])
 
 m4_define([IMAP4D_DEFAULT_OPTIONS],[dnl
---no-site-config dnl
+--no-config dnl
+--config-file=imap4d.conf dnl
 --test dnl
---set logging.syslog=0 dnl
---set logging.severity=notice dnl
---set .gsasl.enable=0 dnl
---set '|homedir='`pwd`m4_if([IMAP4D_HOMEDIR],,,/[IMAP4D_HOMEDIR]) dnl
---set '|mailbox|folder='`pwd` dnl
---set '|mailbox|mailbox-pattern='`pwd`/INBOX dnl
 ])
 
 m4_define([IMAP4D_PREAUTH_OPTIONS],[dnl
@@ -36,22 +31,27 @@ IMAP4D_DEFAULT_OPTIONS dnl
 
 m4_define([IMAP4D_OPTIONS],[IMAP4D_PREAUTH_OPTIONS])
 
+m4_define([IMAP4D_CONFIG],[make_config IMAP4D_HOMEDIR])
+
+m4_define([IMAP4D_RUN],[IMAP4D_CONFIG
+m4_if([$2],[expand],
+[cat > input <<EOT
+$1
+EOT
+],[dnl
+AT_DATA([input],[$1])dnl
+])
+imap4d IMAP4D_OPTIONS < input | tr -d '\r'])
+
 dnl ------------------------------------------------------------
 dnl IMAP4D_CHECK([PREP], [INPUT], [STDOUT = `'], [STDERR = `'],
 dnl              [FILTER = `'],[expand])
 dnl
 m4_pushdef([IMAP4D_CHECK],[
 cwd=`pwd`
-m4_if([$6],,[dnl
-AT_DATA([input],[$2])dnl
-],[cat > input <<EOT
-[$2]
-EOT
-])
 $1
 AT_CHECK([
-imap4d IMAP4D_OPTIONS < input | tr -d '\r' | dnl
- m4_if([$5],,[remove_uidvalidity],[$5])
+IMAP4D_RUN([$2],[$6]) | m4_if([$5],,[remove_uidvalidity],[$5])
 ],
 [0],
 [$3],
diff --git a/imap4d/util.c b/imap4d/util.c
index e935e90..2509707 100644
--- a/imap4d/util.c
+++ b/imap4d/util.c
@@ -17,26 +17,6 @@
 
 #include "imap4d.h"
 
-/* Get the absolute path.  */
-/* NOTE: Path is allocated and must be free()d by the caller.  */
-char *
-util_getfullpath (const char *name)
-{
-  char *exp = mu_tilde_expansion (name, MU_HIERARCHY_DELIMITER,
-                                 imap4d_homedir);
-  if (*exp != MU_HIERARCHY_DELIMITER)
-    {
-      char *p, *s =
-       mu_alloc (strlen (imap4d_homedir) + 1 + strlen (exp) + 1);
-      p = mu_stpcpy (s, imap4d_homedir);
-      *p++ = MU_HIERARCHY_DELIMITER;
-      strcpy (p, exp);
-      free (exp);
-      exp = s;
-    }
-  return mu_normalize_path (exp);
-}
-
 int
 util_do_command (struct imap4d_session *session, imap4d_tokbuf_t tok)
 {
diff --git a/include/mailutils/cfg.h b/include/mailutils/cfg.h
index 1b728ea..03d319f 100644
--- a/include/mailutils/cfg.h
+++ b/include/mailutils/cfg.h
@@ -31,7 +31,6 @@
 extern "C" {
 #endif  
 
-typedef enum mu_cfg_node_type mu_cfg_node_type_t;
 typedef struct mu_cfg_node mu_cfg_node_t;
 typedef struct mu_cfg_tree mu_cfg_tree_t;
 
diff --git a/libmu_cpp/pop3.cc b/libmu_cpp/pop3.cc
index 25dee7c..49fe7dc 100644
--- a/libmu_cpp/pop3.cc
+++ b/libmu_cpp/pop3.cc
@@ -205,7 +205,7 @@ Pop3 :: rset ()
 }
 
 void
-Pop3 :: stat (unsigned int* count, mu_off_t* octets)
+Pop3 :: stat (size_t* count, mu_off_t* octets)
 {
   int status = mu_pop3_stat (pop3, count, octets);
   if (status)


hooks/post-receive
-- 
GNU Mailutils



reply via email to

[Prev in Thread] Current Thread [Next in Thread]