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-2.2-539-gc22d07a


From: Sergey Poznyakoff
Subject: [SCM] GNU Mailutils branch, master, updated. release-2.2-539-gc22d07a
Date: Sat, 17 Dec 2011 00:11:39 +0000

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=c22d07a3d7bc380541bfb2603c6f5a2967ad63c9

The branch, master has been updated
       via  c22d07a3d7bc380541bfb2603c6f5a2967ad63c9 (commit)
       via  7f325d5c04a280e0711a09fef9eab86e128ace86 (commit)
       via  5c16cf454ffc05a340cbf8136c36e4cc1ed72904 (commit)
       via  b71b1bb14085900051070cb82ad334ce67f14d96 (commit)
       via  dd08262c4c55b984e9b38a3dc4a330960d01e26f (commit)
       via  33a5d85239028bc3e34eec59909253d12d5434f4 (commit)
      from  a837453677a2888155aa565666acc956cdd3f896 (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 c22d07a3d7bc380541bfb2603c6f5a2967ad63c9
Author: Sergey Poznyakoff <address@hidden>
Date:   Sat Dec 17 01:38:06 2011 +0200

    Move Python support from experimental to stable features.

commit 7f325d5c04a280e0711a09fef9eab86e128ace86
Author: Sergey Poznyakoff <address@hidden>
Date:   Sat Dec 17 01:25:53 2011 +0200

    Fix the use of the hierarchy delimiter.
    
    * include/mailutils/util.h (MU_HIERARCHY_DELIMITER): New define.
    (mu_tilde_expansion): Change signature.  Delimiter is an int.
    * libmailutils/base/tilde.c: Likewise. All uses update.
    
    * imap4d/namespace.c (namespace_checkfullpath)
    (namespace_getfullpath): Remove delim argument. All uses updated.
    * imap4d/util.c (util_getfullpath): Remove delim argument. All uses updated.

commit 5c16cf454ffc05a340cbf8136c36e4cc1ed72904
Author: Sergey Poznyakoff <address@hidden>
Date:   Sat Dec 17 00:44:05 2011 +0200

    Use IMAP-stile wildcards in folder matchers by default.
    
    * imap4d/imap4d.h: Include mailutils/imaputil.h
    * imap4d/list.c: Use mu_folder_imap_match/mu_imap_wildmatch.
    * imap4d/lsub.c: Likewise.
    * imap4d/util.c (util_wcard_match): Move as to libmailutils
    as mu_imap_wildmatch.
    * include/mailutils/imaputil.h: New file.
    * include/mailutils/Makefile.am (pkginclude_HEADERS): Add imaputil.h
    * include/mailutils/folder.h (mu_folder_imap_match)
    (mu_folder_glob_match): New protos.
    * include/mailutils/imapio.h (mu_imap_flag_to_attribute)
    (mu_imap_format_flags): Move to imaputil.h
    * libmailutils/imapio/wildmatch.c: New file.
    * libmailutils/imapio/sendflg.c: New file.
    * libmailutils/imapio/Makefile.am (libimapio_la_SOURCES): Add
    sendflg.c and wildmatch.c.
    * libmailutils/imapio/flags.c (mu_imapio_send_flags): Move to
    sendflg.c
    * libmailutils/mailbox/folder.c (mu_folder_match): Rename to
    mu_folder_glob_match.
    (mu_folder_imap_match): New function.
    (mu_folder_create_from_record): Use mu_folder_imap_match as the default
    matcher.
    * libmailutils/tests/fsfolder.c: Start command line options with a dash.
    New option "-glob".  All uses changed.
    * libproto/imap/select.c: Include imaputil.h
    * mu/imap.c: Likewise.

commit b71b1bb14085900051070cb82ad334ce67f14d96
Author: Sergey Poznyakoff <address@hidden>
Date:   Thu Dec 15 02:49:48 2011 +0200

    Provisions for loading python modules from the source tree.
    
    * python/Makefile.am (EXTRA_DIST): Add usercustomize.py
    * python/usercustomize.py: New file.
    * python/libmu_py/Makefile.am (pythonexec_LTLIBRARIES): Remove.
    * python/mailutils/Makefile.am (pythonexec_LTLIBRARIES): New
    variable (moved from ../libmu_py/Makefile.am)
    * python/libmu_py/c_api.c: Move ...
    * python/mailutils/c_api.c: ... there

commit dd08262c4c55b984e9b38a3dc4a330960d01e26f
Author: Sergey Poznyakoff <address@hidden>
Date:   Fri Dec 16 22:21:44 2011 +0200

    Add a test suite for folder delete method.
    
    * testsuite/Makefile.am: Add new test cases.
    * testsuite/testsuite.at: Inclide fldel.at, add banners.
    * testsuite/atlocal.in: Define MH_SUPPORT and MAILDIR_SUPPORT
    variables depending on whether the corresponding mailbox format
    is enabled.
    * testsuite/fldel.at: New test case.
    * testsuite/mbdel.at: Skip tests which rely on disabled mailbox
    formats.

commit 33a5d85239028bc3e34eec59909253d12d5434f4
Author: Sergey Poznyakoff <address@hidden>
Date:   Fri Dec 16 16:36:29 2011 +0200

    Share folder implementation between mbox, mh and maildir.  Fix 
mu_folder_delete.
    
    * include/mailutils/folder.h (_mu_fsfolder_init): New proto.
    * include/mailutils/mailbox.h (mu_mailbox_create_at): New proto.
    * libmailutils/mailbox/mailbox.c (mu_mailbox_create_at): New function.
    * libmailutils/mailbox/Makefile.am (libmailbox_la_SOURCES): Add fsfolder.c
    * libmailutils/mailbox/folder.c (mu_folder_delete): If folder does
    not provide its own method for deletion, use mu_mailbox_remove.
    (mu_folder_open, mu_folder_close, mu_folder_enumerate)
    (mu_folder_lsub, mu_folder_subscribe, mu_folder_unsubscribe)
    (mu_folder_rename): Return EINVAL if folder is NULL.
    (mu_folder_match): Bugfix: don't pass folder flags to fnmatch.
    * libmailutils/mailbox/fsfolder.c: New file. Implementation of
    file-system based folders.
    * libmailutils/mailbox/mailbox (_create_mailbox0): Propagate error
    return from mu_registrar_lookup_url.
    * libmailutils/tests/fsfolder00.at: New test case.
    * libmailutils/tests/fsfolder01.at: New test case.
    * libmailutils/tests/fsfolder02.at: New test case.
    * libmailutils/tests/Makefile.am (noinst_PROGRAMS): Add fsfolder.
    (TESTSUITE_AT): Add fsfolder tests.
    * libmailutils/tests/testsuite.at: Include fsfolder tests.
    
    * libproto/mbox/folder.c: Use fsfolder.
    (_mh_is_scheme): Check file even if scheme matches.
    * libproto/maildir/folder.c: Likewise.
    (_maildir_is_scheme): Check file even if scheme matches.
    * libproto/mh/folder.c: Likewise.
    
    * testsuite/fldel.c: New file.
    * testsuite/Makefile.am (noinst_PROGRAMS): Buld fldel.

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

Summary of changes:
 NEWS                                               |    5 +-
 configure.ac                                       |    2 +-
 imap4d/append.c                                    |    2 +-
 imap4d/copy.c                                      |    3 +-
 imap4d/create.c                                    |    7 +-
 imap4d/delete.c                                    |    3 +-
 imap4d/imap4d.c                                    |    3 +-
 imap4d/imap4d.h                                    |   12 +-
 imap4d/list.c                                      |   29 +-
 imap4d/lsub.c                                      |    7 +-
 imap4d/namespace.c                                 |    8 +-
 imap4d/quota.c                                     |    2 +-
 imap4d/rename.c                                    |    7 +-
 imap4d/select.c                                    |    2 +-
 imap4d/status.c                                    |    3 +-
 imap4d/util.c                                      |   76 +---
 include/mailutils/Makefile.am                      |    1 +
 include/mailutils/folder.h                         |    8 +
 include/mailutils/imapio.h                         |    3 -
 .../tzlocal.c => include/mailutils/imaputil.h      |   24 +-
 include/mailutils/mailbox.h                        |    2 +
 include/mailutils/util.h                           |    5 +-
 libmailutils/base/tilde.c                          |   10 +-
 libmailutils/cfg/driver.c                          |    2 +-
 libmailutils/cfg/lexer.l                           |    2 +-
 libmailutils/imapio/Makefile.am                    |    2 +
 libmailutils/imapio/flags.c                        |   15 +-
 libmailutils/imapio/{printf.c => sendflg.c}        |   21 +-
 libmailutils/imapio/wildmatch.c                    |   78 +++
 libmailutils/mailbox/Makefile.am                   |    1 +
 libmailutils/mailbox/folder.c                      |   77 +++-
 .../folder.c => libmailutils/mailbox/fsfolder.c    |  454 +++++++----------
 libmailutils/mailbox/mailbox.c                     |  116 ++++-
 libmailutils/mailbox/mbx_default.c                 |    5 +-
 libmailutils/tests/.gitignore                      |    1 +
 libmailutils/tests/Makefile.am                     |    4 +
 .../imapfolder.c => libmailutils/tests/fsfolder.c  |  135 ++++--
 .../tests/fsfolder00.at                            |   43 ++-
 libmailutils/tests/fsfolder01.at                   |   74 +++
 libmailutils/tests/{strerr.at => fsfolder02.at}    |   28 +-
 libmailutils/tests/testsuite.at                    |    5 +
 libmu_sieve/extensions/vacation.c                  |    2 +-
 libproto/imap/select.c                             |    1 +
 libproto/imap/tests/imapfolder.c                   |    1 -
 libproto/maildir/folder.c                          |   45 +-
 libproto/mailer/smtp_auth.c                        |    3 +-
 libproto/mbox/folder.c                             |  517 +-------------------
 libproto/mh/folder.c                               |   37 +-
 mail/util.c                                        |    2 +-
 mh/install-mh.c                                    |    2 +-
 mh/mh_global.c                                     |    2 +-
 mh/mh_init.c                                       |    8 +-
 mh/mhn.c                                           |    3 +-
 mh/send.c                                          |    2 +-
 mu/imap.c                                          |    1 +
 mu/shell.c                                         |    2 +-
 mu/wicket.c                                        |    2 +-
 pop3d/bulletin.c                                   |    6 +-
 python/Makefile.am                                 |    1 +
 python/libmu_py/Makefile.am                        |    5 -
 python/mailutils/Makefile.am                       |    8 +
 python/{libmu_py => mailutils}/c_api.c             |    0
 python/usercustomize.py                            |   63 +++
 sieve/sieve.c                                      |    2 +-
 testsuite/.gitignore                               |    1 +
 testsuite/Makefile.am                              |    2 +
 testsuite/atlocal.in                               |    2 +
 testsuite/fldel.at                                 |   81 +++
 testsuite/{mbdel.c => fldel.c}                     |   12 +-
 testsuite/mbdel.at                                 |   16 +-
 testsuite/testsuite.at                             |   10 +
 71 files changed, 1021 insertions(+), 1105 deletions(-)
 copy libmailutils/datetime/tzlocal.c => include/mailutils/imaputil.h (66%)
 copy libmailutils/imapio/{printf.c => sendflg.c} (73%)
 create mode 100644 libmailutils/imapio/wildmatch.c
 copy libproto/mbox/folder.c => libmailutils/mailbox/fsfolder.c (55%)
 copy libproto/imap/tests/imapfolder.c => libmailutils/tests/fsfolder.c (59%)
 copy imap4d/tests/create02.at => libmailutils/tests/fsfolder00.at (55%)
 create mode 100644 libmailutils/tests/fsfolder01.at
 copy libmailutils/tests/{strerr.at => fsfolder02.at} (69%)
 rename python/{libmu_py => mailutils}/c_api.c (100%)
 create mode 100644 python/usercustomize.py
 create mode 100644 testsuite/fldel.at
 copy testsuite/{mbdel.c => fldel.c} (85%)

diff --git a/NEWS b/NEWS
index a50433b..25cf5d1 100644
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,4 @@
-GNU mailutils NEWS -- history of user-visible changes. 2011-11-23
+GNU mailutils NEWS -- history of user-visible changes. 2011-12-17
 Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
 Free Software Foundation, Inc.
 See the end of file for copying conditions.
@@ -29,7 +29,6 @@ experimental.  Not currently implemented are:
 Experimental features are:
 
  - C++ bindings
- - Python bindings
 
 The discussion below lists the changes in this release.  It is divided
 in three major sections, each addressing a particular audience.  The
@@ -158,7 +157,7 @@ This can be disabled using the --without-gsasl option.
 
 ** Experimental features
 
-The C++ and Python bindings are considered experimental and unstable.
+The C++ bindings are considered experimental and unstable.
 
 * Changes to the library
 
diff --git a/configure.ac b/configure.ac
index 4edf484..9472fb7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1167,7 +1167,7 @@ case "${enableval}" in
   yes) status_python=yes ;;
   no)  status_python=no ;;
   *)   AC_MSG_ERROR(bad value ${enableval} for --enable-python) ;;
-esac],[status_python=$mu_build_experimental])
+esac],[status_python=yes])
 
 AC_SUBST(PYTHON_LIBS)
 AC_SUBST(PYTHON_INCLUDES)
diff --git a/imap4d/append.c b/imap4d/append.c
index 74aebef..df5abab 100644
--- a/imap4d/append.c
+++ b/imap4d/append.c
@@ -252,7 +252,7 @@ imap4d_append (struct imap4d_command *command, 
imap4d_tokbuf_t tok)
 
   msg_text = imap4d_tokbuf_getarg (tok, i);
   
-  mboxname = namespace_getfullpath (mboxname, "/", NULL);
+  mboxname = namespace_getfullpath (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 607c278..5e60487 100644
--- a/imap4d/copy.c
+++ b/imap4d/copy.c
@@ -232,7 +232,6 @@ imap4d_copy0 (imap4d_tokbuf_t tok, int isuid, char 
**err_text)
   mu_list_t msglist;
   char *name;
   char *mailbox_name;
-  const char *delim = "/";
   char *end;
   mu_mailbox_t cmbox = NULL;
   int arg = IMAP4_ARG_1 + !!isuid;
@@ -256,7 +255,7 @@ imap4d_copy0 (imap4d_tokbuf_t tok, int isuid, char 
**err_text)
       return RESP_BAD;
     }
 
-  mailbox_name = namespace_getfullpath (name, delim, &ns);
+  mailbox_name = namespace_getfullpath (name, &ns);
 
   if (!mailbox_name)
     {
diff --git a/imap4d/create.c b/imap4d/create.c
index b65f419..ff70619 100644
--- a/imap4d/create.c
+++ b/imap4d/create.c
@@ -37,7 +37,6 @@ int
 imap4d_create (struct imap4d_command *command, imap4d_tokbuf_t tok)
 {
   char *name;
-  const char *delim = "/";
   int isdir = 0;
   int ns;
   int rc = RESP_OK;
@@ -63,11 +62,11 @@ imap4d_create (struct imap4d_command *command, 
imap4d_tokbuf_t tok)
      The trailing delimiter will be removed by namespace normalizer, so
      test for it now.
   */
-  if (name[strlen (name) - 1] == delim[0])
+  if (name[strlen (name) - 1] == MU_HIERARCHY_DELIMITER)
     isdir = 1;
   
   /* Allocates memory.  */
-  name = namespace_getfullpath (name, delim, &ns);
+  name = namespace_getfullpath (name, &ns);
 
   if (!name)
     return io_completion_response (command, RESP_NO, "Cannot create mailbox");
@@ -75,7 +74,7 @@ imap4d_create (struct imap4d_command *command, 
imap4d_tokbuf_t tok)
   /* It will fail if the mailbox already exists.  */
   if (access (name, F_OK) != 0)
     {
-      if (make_interdir (name, delim[0], MKDIR_PERMISSIONS))
+      if (make_interdir (name, MU_HIERARCHY_DELIMITER, MKDIR_PERMISSIONS))
        {
          rc = RESP_NO;
          msg = "Cannot create mailbox";
diff --git a/imap4d/delete.c b/imap4d/delete.c
index aed74ee..9fe8b3d 100644
--- a/imap4d/delete.c
+++ b/imap4d/delete.c
@@ -33,7 +33,6 @@ imap4d_delete (struct imap4d_command *command, 
imap4d_tokbuf_t tok)
 {
   int rc = RESP_OK;
   const char *msg = "Completed";
-  const char *delim = "/";
   char *name;
   mu_mailbox_t tmpbox;
   
@@ -49,7 +48,7 @@ imap4d_delete (struct imap4d_command *command, 
imap4d_tokbuf_t tok)
     return io_completion_response (command, RESP_NO, "Already exist");
 
  /* Allocates memory.  */
-  name = namespace_getfullpath (name, delim, NULL);
+  name = namespace_getfullpath (name, NULL);
   if (!name)
     return io_completion_response (command, RESP_NO, "Cannot remove");
 
diff --git a/imap4d/imap4d.c b/imap4d/imap4d.c
index 3fbbf8f..0d93abb 100644
--- a/imap4d/imap4d.c
+++ b/imap4d/imap4d.c
@@ -325,7 +325,8 @@ imap4d_session_setup0 ()
 
   if (modify_homedir)
     {
-      char *expr = mu_tilde_expansion (modify_homedir, "/", real_homedir);
+      char *expr = mu_tilde_expansion (modify_homedir, MU_HIERARCHY_DELIMITER,
+                                      real_homedir);
       struct mu_wordsplit ws;
       const char *env[5];
 
diff --git a/imap4d/imap4d.h b/imap4d/imap4d.h
index 09e7f64..f652c1a 100644
--- a/imap4d/imap4d.h
+++ b/imap4d/imap4d.h
@@ -106,6 +106,7 @@
 #include <mailutils/io.h>
 #include <mailutils/prog.h>
 #include <mailutils/imapio.h>
+#include <mailutils/imaputil.h>
 
 #include <mu_umaxtostr.h>
 #include <muaux.h>
@@ -349,10 +350,9 @@ 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, const char *delim,
-                                   int *pns);
+extern char *namespace_getfullpath (const char *name, int *pns);
 extern char *namespace_checkfullpath (const char *name, const char *pattern,
-                                      const char *delim, int *pns);
+                                     int *pns);
 int imap4d_session_setup (char *username);
 int imap4d_session_setup0 (void);
 void imap4d_child_signal_setup (RETSIGTYPE (*handler) (int signo));
@@ -367,8 +367,7 @@ extern void imap4d_capability_init (void);
 extern int  util_start (char *);
 extern int  util_getstate (void);
 extern int  util_do_command (imap4d_tokbuf_t);
-extern char *util_tilde_expansion (const char *, const char *);
-extern char *util_getfullpath (const char *, const char *);
+extern char *util_getfullpath (const char *);
 extern struct imap4d_command *util_getcommand (char *, 
                                                struct imap4d_command []);
 
@@ -396,9 +395,6 @@ extern int util_parse_ctime_date (const char *date, time_t 
*timep,
 extern char *util_strcasestr (const char *haystack, const char *needle);
 extern char *util_localname (void);
 
-extern int util_wcard_match (const char *string, const char *pattern,
-                            const char *delim);
-
 void util_print_flags (mu_attribute_t attr);
 int util_attribute_matches_flag (mu_attribute_t attr, const char *item);
 int util_uidvalidity (mu_mailbox_t smbox, unsigned long *uidvp);
diff --git a/imap4d/list.c b/imap4d/list.c
index 82299d6..89b0f1f 100644
--- a/imap4d/list.c
+++ b/imap4d/list.c
@@ -19,12 +19,6 @@
 #include <dirent.h>
 #include <pwd.h>
 
-static int
-imap4d_match (const char *name, void *pat, int flags)
-{
-  return util_wcard_match (name, pat, "/");
-}
-
 struct refinfo
 {
   char *refptr;   /* Original reference */
@@ -141,7 +135,6 @@ imap4d_list (struct imap4d_command *command, 
imap4d_tokbuf_t tok)
 {
   char *ref;
   char *wcard;
-  const char *delim = "/";
 
   if (imap4d_tokbuf_argc (tok) != 4)
     return io_completion_response (command, RESP_BAD, "Invalid arguments");
@@ -153,9 +146,15 @@ imap4d_list (struct imap4d_command *command, 
imap4d_tokbuf_t tok)
      return the hierarchy.  */
   if (*wcard == '\0')
     {
-      io_untagged_response (RESP_NONE,
-                               "LIST (\\NoSelect) \"%s\" \"%s\"", delim,
-                              (*ref) ? delim : "");
+      if (*ref)
+       io_untagged_response (RESP_NONE,
+                             "LIST (\\NoSelect) \"%c\" \"%c\"",
+                             MU_HIERARCHY_DELIMITER,
+                             MU_HIERARCHY_DELIMITER);
+      else
+       io_untagged_response (RESP_NONE,
+                             "LIST (\\NoSelect) \"%c\" \"\"",
+                             MU_HIERARCHY_DELIMITER);
     }
   /* There is only one mailbox in the "INBOX" hierarchy ... INBOX.  */
   else if (mu_c_strcasecmp (ref, "INBOX") == 0
@@ -228,7 +227,7 @@ imap4d_list (struct imap4d_command *command, 
imap4d_tokbuf_t tok)
        }
 
       /* Allocates.  */
-      cwd = namespace_checkfullpath (ref, wcard, delim, NULL);
+      cwd = namespace_checkfullpath (ref, wcard, NULL);
       if (!cwd)
        {
          free (ref);
@@ -243,7 +242,8 @@ imap4d_list (struct imap4d_command *command, 
imap4d_tokbuf_t tok)
          return io_completion_response (command, RESP_NO,
                                      "The requested item could not be found.");
        }
-      mu_folder_set_match (folder, imap4d_match);
+      /* Force the right matcher */
+      mu_folder_set_match (folder, mu_folder_imap_match);
 
       memset (&refinfo, 0, sizeof refinfo);
 
@@ -260,8 +260,9 @@ imap4d_list (struct imap4d_command *command, 
imap4d_tokbuf_t tok)
         failure; it is not relevant whether the user's real INBOX resides
         on this or some other server. */
 
-      if (!*ref && (imap4d_match ("INBOX", wcard, 0) == 0
-                   || imap4d_match ("inbox", wcard, 0) == 0))
+      if (!*ref &&
+         (mu_imap_wildmatch (wcard, "INBOX", MU_HIERARCHY_DELIMITER) == 0
+          || mu_imap_wildmatch (wcard, "inbox", MU_HIERARCHY_DELIMITER) == 0))
        io_untagged_response (RESP_NONE, "LIST (\\NoInferiors) NIL INBOX");
 
       mu_folder_enumerate (folder, NULL, wcard, 0, 0, NULL,
diff --git a/imap4d/lsub.c b/imap4d/lsub.c
index 1ee5114..1b7f90d 100644
--- a/imap4d/lsub.c
+++ b/imap4d/lsub.c
@@ -37,7 +37,6 @@ imap4d_lsub (struct imap4d_command *command, imap4d_tokbuf_t 
tok)
   char *ref;
   char *wcard;
   char *pattern;
-  const char *delim = "/";
   mu_property_t prop;
   mu_iterator_t itr;
   
@@ -64,9 +63,9 @@ imap4d_lsub (struct imap4d_command *command, imap4d_tokbuf_t 
tok)
          
          mu_iterator_current_kv (itr, (const void **)&name, (void**)&val);
 
-         if (util_wcard_match (name, pattern, delim) == 0)
-           io_untagged_response (RESP_NONE, "LSUB () \"%s\" \"%s\"",
-                                 delim, name);
+         if (mu_imap_wildmatch (pattern, name, MU_HIERARCHY_DELIMITER) == 0)
+           io_untagged_response (RESP_NONE, "LSUB () \"%c\" \"%s\"",
+                                 MU_HIERARCHY_DELIMITER, name);
        }
     }
   else
diff --git a/imap4d/namespace.c b/imap4d/namespace.c
index bee550a..9ffbd3b 100644
--- a/imap4d/namespace.c
+++ b/imap4d/namespace.c
@@ -166,7 +166,7 @@ risky_pattern (const char *pattern, int delim)
 
 char *
 namespace_checkfullpath (const char *name, const char *pattern, 
-                        const char *delim, int *nspace)
+                        int *nspace)
 {
   struct namespace_info info;
   const char *p;
@@ -185,7 +185,7 @@ namespace_checkfullpath (const char *name, const char 
*pattern,
       name = p + 1;
     }
 
-  path = util_getfullpath (name, delim);
+  path = util_getfullpath (name);
   if (!path)
     {
       free (scheme);
@@ -226,7 +226,7 @@ namespace_checkfullpath (const char *name, const char 
*pattern,
 }
 
 char *
-namespace_getfullpath (const char *name, const char *delim, int *nspace)
+namespace_getfullpath (const char *name, int *nspace)
 {
   char *ret;
   if (mu_c_strcasecmp (name, "INBOX") == 0 && auth_data->change_uid)
@@ -236,7 +236,7 @@ namespace_getfullpath (const char *name, const char *delim, 
int *nspace)
        *nspace = NS_PRIVATE;
     }
   else
-    ret = namespace_checkfullpath (name, NULL, delim, nspace);
+    ret = namespace_checkfullpath (name, NULL, nspace);
   return ret;
 }
 
diff --git a/imap4d/quota.c b/imap4d/quota.c
index 2b1e9ae..878dec7 100644
--- a/imap4d/quota.c
+++ b/imap4d/quota.c
@@ -138,7 +138,7 @@ quota_check (mu_off_t size)
 
   total = used_size;
 
-  mailbox_name = namespace_getfullpath ("INBOX", "/", NULL);
+  mailbox_name = namespace_getfullpath ("INBOX", NULL);
   rc = mu_mailbox_create (&mbox, mailbox_name);
   if (rc)
     {
diff --git a/imap4d/rename.c b/imap4d/rename.c
index 24fa65e..440a498 100644
--- a/imap4d/rename.c
+++ b/imap4d/rename.c
@@ -110,7 +110,6 @@ imap4d_rename (struct imap4d_command *command, 
imap4d_tokbuf_t tok)
   int rc = RESP_OK;
   const char *msg = "Completed";
   struct stat newst;
-  const char *delim = "/";
   int ns;
   
   if (imap4d_tokbuf_argc (tok) != 4)
@@ -123,7 +122,7 @@ imap4d_rename (struct imap4d_command *command, 
imap4d_tokbuf_t tok)
     return io_completion_response (command, RESP_NO, "Name Inbox is 
reservered");
 
   /* Allocates memory.  */
-  newname = namespace_getfullpath (newname, delim, &ns);
+  newname = namespace_getfullpath (newname, &ns);
   if (!newname)
     return io_completion_response (command, RESP_NO, "Permission denied");
 
@@ -140,7 +139,7 @@ imap4d_rename (struct imap4d_command *command, 
imap4d_tokbuf_t tok)
        }
     }
 
-  if (make_interdir (newname, delim[0], MKDIR_PERMISSIONS))
+  if (make_interdir (newname, MU_HIERARCHY_DELIMITER, MKDIR_PERMISSIONS))
     {
       free (newname);
       return io_completion_response (command, RESP_NO, "Cannot rename");
@@ -202,7 +201,7 @@ imap4d_rename (struct imap4d_command *command, 
imap4d_tokbuf_t tok)
       return io_completion_response (command, RESP_OK, "Rename successful");
     }
 
-  oldname = namespace_getfullpath (oldname, delim, NULL);
+  oldname = namespace_getfullpath (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 8a61ad5..42cdc8c 100644
--- a/imap4d/select.c
+++ b/imap4d/select.c
@@ -58,7 +58,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_getfullpath (mboxname, 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 d0bd445..549a2fc 100644
--- a/imap4d/status.c
+++ b/imap4d/status.c
@@ -69,7 +69,6 @@ imap4d_status (struct imap4d_command *command, 
imap4d_tokbuf_t tok)
 {
   char *name;
   char *mailbox_name;
-  const char *delim = "/";
   mu_mailbox_t smbox = NULL;
   int status;
   int count = 0;
@@ -81,7 +80,7 @@ imap4d_status (struct imap4d_command *command, 
imap4d_tokbuf_t tok)
   
   name = imap4d_tokbuf_getarg (tok, IMAP4_ARG_1);
 
-  mailbox_name = namespace_getfullpath (name, delim, NULL);
+  mailbox_name = namespace_getfullpath (name, NULL);
 
   if (!mailbox_name)
     return io_completion_response (command, RESP_NO, "Error opening mailbox");
diff --git a/imap4d/util.c b/imap4d/util.c
index e520735..5ade76b 100644
--- a/imap4d/util.c
+++ b/imap4d/util.c
@@ -17,28 +17,21 @@
 
 #include "imap4d.h"
 
-/* NOTE: Allocates Memory.  */
-/* Expand: ~ --> /home/user, and ~guest --> /home/guest.  */
-char *
-util_tilde_expansion (const char *ref, const char *delim)
-{
-  return mu_tilde_expansion (ref, delim, imap4d_homedir);
-}
-
 /* Get the absolute path.  */
 /* NOTE: Path is allocated and must be free()d by the caller.  */
 char *
-util_getfullpath (const char *name, const char *delim)
+util_getfullpath (const char *name)
 {
-  char *exp = util_tilde_expansion (name, delim);
-  if (*exp != delim[0])
+  char *exp = mu_tilde_expansion (name, MU_HIERARCHY_DELIMITER,
+                                 imap4d_homedir);
+  if (*exp != MU_HIERARCHY_DELIMITER)
     {
       char *p, *s =
-       malloc (strlen (imap4d_homedir) + strlen (delim) + strlen (exp) + 1);
+       malloc (strlen (imap4d_homedir) + 1 + strlen (exp) + 1);
       if (!s)
        imap4d_bye (ERR_NO_MEM);
       p = mu_stpcpy (s, imap4d_homedir);
-      p = mu_stpcpy (p, (char*) delim);
+      *p++ = MU_HIERARCHY_DELIMITER;
       strcpy (p, exp);
       free (exp);
       exp = s;
@@ -566,63 +559,6 @@ util_localname ()
   return localname;
 }
 
-/* Match STRING against the IMAP4 wildcard pattern PATTERN. */
-
-#define WILD_FALSE 0
-#define WILD_TRUE  1
-#define WILD_ABORT 2
-
-int
-_wild_match (const char *expr, const char *name, char delim)
-{
-  while (expr && *expr)
-    {
-      if (*name == 0 && *expr != '*')
-       return WILD_ABORT;
-      switch (*expr)
-       {
-       case '*':
-         while (*++expr == '*')
-           ;
-         if (*expr == 0)
-           return WILD_TRUE;
-         while (*name)
-           {
-             int res = _wild_match (expr, name++, delim);
-             if (res != WILD_FALSE)
-               return res;
-           }
-         return WILD_ABORT;
-
-       case '%':
-         while (*++expr == '%')
-           ;
-         if (*expr == 0)
-           return strchr (name, delim) ? WILD_FALSE : WILD_TRUE;
-         while (*name && *name != delim)
-           {
-             int res = _wild_match (expr, name++, delim);
-             if (res != WILD_FALSE)
-               return res;
-           }
-         return _wild_match (expr, name, delim);
-         
-       default:
-         if (*expr != *name)
-           return WILD_FALSE;
-         expr++;
-         name++;
-       }
-    }
-  return *name == 0;
-}
-
-int
-util_wcard_match (const char *name, const char *expr, const char *delim)
-{
-  return _wild_match (expr, name, delim[0]) != WILD_TRUE;
-}
-
 /* Return the uindvalidity of a mailbox.
    When a mailbox is selected, whose first message does not keep X-UIDVALIDITY
    value, the uidvalidity is computed basing on the return of time(). Now,
diff --git a/include/mailutils/Makefile.am b/include/mailutils/Makefile.am
index a7b116d..53ea5e4 100644
--- a/include/mailutils/Makefile.am
+++ b/include/mailutils/Makefile.am
@@ -54,6 +54,7 @@ pkginclude_HEADERS = \
  header.h\
  imap.h\
  imapio.h\
+ imaputil.h\
  io.h\
  iterator.h\
  kwd.h\
diff --git a/include/mailutils/folder.h b/include/mailutils/folder.h
index e8f6cb9..c3da0a3 100644
--- a/include/mailutils/folder.h
+++ b/include/mailutils/folder.h
@@ -72,6 +72,12 @@ extern int  mu_folder_set_stream     (mu_folder_t, 
mu_stream_t);
 extern int mu_folder_set_match (mu_folder_t folder, mu_folder_match_fp pmatch);
 extern int mu_folder_get_match (mu_folder_t folder,
                                mu_folder_match_fp *pmatch);
+
+  /* Two often used matchers: */
+  /* 1. The default: IMAP-style wildcards: */
+extern int mu_folder_imap_match (const char *name, void *pattern, int flags);
+  /* 2. UNIX-style glob(7) wildcards: */
+extern int mu_folder_glob_match (const char *name, void *pattern, int flags);
   
   /* Notifications.  */
 extern int  mu_folder_get_observable (mu_folder_t, mu_observable_t *);
@@ -92,6 +98,8 @@ extern int  mu_folder_get_property   (mu_folder_t, 
mu_property_t *);
 extern int  mu_folder_decrement      (mu_folder_t);
 
 extern void mu_list_response_free    (void *data);
+
+int _mu_fsfolder_init (mu_folder_t folder);
   
 #ifdef __cplusplus
 }
diff --git a/include/mailutils/imapio.h b/include/mailutils/imapio.h
index 87f55ce..d038744 100644
--- a/include/mailutils/imapio.h
+++ b/include/mailutils/imapio.h
@@ -72,9 +72,6 @@ int mu_imapio_reply_string (mu_imapio_t io, size_t start, 
char **pbuf);
 int mu_imapio_last_error (mu_imapio_t io);
 void mu_imapio_clearerr (mu_imapio_t io);
   
-int mu_imap_flag_to_attribute (const char *item, int *attr);
-int mu_imap_format_flags (mu_stream_t str, int flags);
-
 #ifdef __cplusplus
 }
 #endif
diff --git a/libmailutils/datetime/tzlocal.c b/include/mailutils/imaputil.h
similarity index 66%
copy from libmailutils/datetime/tzlocal.c
copy to include/mailutils/imaputil.h
index cc561f5..09ddce4 100644
--- a/libmailutils/datetime/tzlocal.c
+++ b/include/mailutils/imaputil.h
@@ -14,14 +14,22 @@
    You should have received a copy of the GNU General Public License
    along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>. */
 
-#ifdef HAVE_CONFIG_H
-# include <config.h>
+#ifndef _MAILUTILS_IMAPUTIL_H
+# define _MAILUTILS_IMAPUTIL_H
+
+#ifdef __cplusplus
+extern "C" {
 #endif
-#include <mailutils/datetime.h>
 
-void
-mu_datetime_tz_local (struct mu_timezone *tz)
-{
-  tz->utc_offset = mu_utc_offset ();
-  tz->tz_name = NULL;
+# include <mailutils/types.h>
+
+int mu_imap_wildmatch (const char *pattern, const char *name, int delim);
+
+int mu_imap_flag_to_attribute (const char *item, int *attr);
+int mu_imap_format_flags (mu_stream_t str, int flags);
+
+#ifdef __cplusplus
 }
+#endif
+
+#endif /* _MAILUTILS_IMAPUTIL_H */
diff --git a/include/mailutils/mailbox.h b/include/mailutils/mailbox.h
index 8969859..f21dc89 100644
--- a/include/mailutils/mailbox.h
+++ b/include/mailutils/mailbox.h
@@ -43,6 +43,8 @@ extern int  mu_mailbox_create_from_record (mu_mailbox_t 
*pmbox,
                                           mu_record_t record,
                                           const char *name);
 extern int  mu_mailbox_create_default  (mu_mailbox_t *, const char *);
+extern int mu_mailbox_create_at (mu_mailbox_t *pmbox, mu_folder_t folder,
+                                const char *name);
 
 extern void mu_mailbox_destroy         (mu_mailbox_t *);
 
diff --git a/include/mailutils/util.h b/include/mailutils/util.h
index 237ff3f..b28d8ea 100644
--- a/include/mailutils/util.h
+++ b/include/mailutils/util.h
@@ -47,11 +47,14 @@ int mu_str_url_decode (char **ptr, const char *s);
   /* ----------------------- */
   /* File & path names.      */
   /* ----------------------- */
+  
+#define MU_HIERARCHY_DELIMITER '/'
+  
 char *mu_get_homedir (void);
 char *mu_get_full_path (const char *file);
 char *mu_normalize_path (char *path);
 char *mu_expand_path_pattern (const char *pattern, const char *username);
-char *mu_tilde_expansion (const char *ref, const char *delim,
+char *mu_tilde_expansion (const char *ref, int delim,
                          const char *homedir);
 int mu_readlink (const char *name, char **pbuf, size_t *psize, size_t *plen);
 int mu_unroll_symlink (const char *name, char **pout);
diff --git a/libmailutils/base/tilde.c b/libmailutils/base/tilde.c
index 900ffc2..6a4a7cc 100644
--- a/libmailutils/base/tilde.c
+++ b/libmailutils/base/tilde.c
@@ -31,7 +31,7 @@
 /* NOTE: Allocates Memory.  */
 /* Expand: ~ --> /home/user and to ~guest --> /home/guest.  */
 char *
-mu_tilde_expansion (const char *ref, const char *delim, const char *homedir)
+mu_tilde_expansion (const char *ref, int delim, const char *homedir)
 {
   char *base = strdup (ref);
   char *home = NULL;
@@ -52,9 +52,9 @@ mu_tilde_expansion (const char *ref, const char *delim, const 
char *homedir)
       memcpy (proto, base, proto_len);
       proto[proto_len] = 0;
       /* Allow for extra pair of slashes after the protocol specifier */
-      if (*p == delim[0])
+      if (*p == delim)
        p++;
-      if (*p == delim[0])
+      if (*p == delim)
        p++;
     }
   else
@@ -63,7 +63,7 @@ mu_tilde_expansion (const char *ref, const char *delim, const 
char *homedir)
   if (*p == '~')
     {
       p++;
-      if (*p == delim[0] || *p == '\0')
+      if (*p == delim || *p == '\0')
         {
          char *s;
          if (!homedir)
@@ -88,7 +88,7 @@ mu_tilde_expansion (const char *ref, const char *delim, const 
char *homedir)
           struct mu_auth_data *auth;
           char *s = p;
           char *name;
-          while (*s && *s != delim[0])
+          while (*s && *s != delim)
             s++;
           name = calloc (s - p + 1, 1);
           memcpy (name, p, s - p);
diff --git a/libmailutils/cfg/driver.c b/libmailutils/cfg/driver.c
index 47ca794..25ed2ab 100644
--- a/libmailutils/cfg/driver.c
+++ b/libmailutils/cfg/driver.c
@@ -503,7 +503,7 @@ mu_parse_config (const char *file, const char *progname,
                 void *target_ptr)
 {
   int rc;
-  char *full_name = mu_tilde_expansion (file, "/", NULL);
+  char *full_name = mu_tilde_expansion (file, MU_HIERARCHY_DELIMITER, NULL);
   if (full_name)
     {
       if (access (full_name, R_OK) == 0)
diff --git a/libmailutils/cfg/lexer.l b/libmailutils/cfg/lexer.l
index fcf6fdd..ded4d70 100644
--- a/libmailutils/cfg/lexer.l
+++ b/libmailutils/cfg/lexer.l
@@ -326,7 +326,7 @@ mu_cfg_parse_file (mu_cfg_tree_t **return_tree, const char 
*file, int flags)
   struct stat st;
   FILE *fp;
   int rc;
-  char *full_name = mu_tilde_expansion (file, "/", NULL);
+  char *full_name = mu_tilde_expansion (file, MU_HIERARCHY_DELIMITER, NULL);
 
   if (stat (full_name, &st))
     {
diff --git a/libmailutils/imapio/Makefile.am b/libmailutils/imapio/Makefile.am
index d196b50..beb590b 100644
--- a/libmailutils/imapio/Makefile.am
+++ b/libmailutils/imapio/Makefile.am
@@ -31,9 +31,11 @@ libimapio_la_SOURCES = \
  sendcmd.c\
  sendcmdv.c\
  sendcmde.c\
+ sendflg.c\
  time.c\
  trace.c\
  transport.c\
+ wildmatch.c\
  words.c\
  xscript.c
 
diff --git a/libmailutils/imapio/flags.c b/libmailutils/imapio/flags.c
index ed20726..8bee66d 100644
--- a/libmailutils/imapio/flags.c
+++ b/libmailutils/imapio/flags.c
@@ -21,7 +21,7 @@
 #include <mailutils/stream.h>
 #include <mailutils/errno.h>
 #include <mailutils/cstr.h>
-#include <mailutils/sys/imapio.h>
+#include <mailutils/imaputil.h>
 
 static struct
 {
@@ -84,16 +84,3 @@ mu_imap_format_flags (mu_stream_t str, int flags)
   return 0;
 }
 
-int
-mu_imapio_send_flags (struct _mu_imapio *io, int flags)
-{
-  int rc;
-
-  rc = mu_stream_write (io->_imap_stream, "(", 1, NULL);
-  if (rc)
-    return rc;
-  rc = mu_imap_format_flags (io->_imap_stream, flags);
-  if (rc == 0)
-    rc = mu_stream_write (io->_imap_stream, ")", 1, NULL);
-  return rc;
-}
diff --git a/libmailutils/imapio/printf.c b/libmailutils/imapio/sendflg.c
similarity index 73%
copy from libmailutils/imapio/printf.c
copy to libmailutils/imapio/sendflg.c
index 801e82a..b4e0d3b 100644
--- a/libmailutils/imapio/printf.c
+++ b/libmailutils/imapio/sendflg.c
@@ -15,21 +15,22 @@
    along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>. */
 
 #include <config.h>
-#include <stdarg.h>
 #include <mailutils/types.h>
 #include <mailutils/imapio.h>
 #include <mailutils/stream.h>
+#include <mailutils/imaputil.h>
 #include <mailutils/sys/imapio.h>
 
 int
-mu_imapio_printf (mu_imapio_t io, const char *fmt, ...)
+mu_imapio_send_flags (struct _mu_imapio *io, int flags)
 {
-  va_list ap;
-  int status;
-  
-  va_start (ap, fmt);
-  status = mu_stream_vprintf (io->_imap_stream, fmt, ap);
-  va_end (ap);
-  return status;
+  int rc;
+
+  rc = mu_stream_write (io->_imap_stream, "(", 1, NULL);
+  if (rc)
+    return rc;
+  rc = mu_imap_format_flags (io->_imap_stream, flags);
+  if (rc == 0)
+    rc = mu_stream_write (io->_imap_stream, ")", 1, NULL);
+  return rc;
 }
-    
diff --git a/libmailutils/imapio/wildmatch.c b/libmailutils/imapio/wildmatch.c
new file mode 100644
index 0000000..ee4e720
--- /dev/null
+++ b/libmailutils/imapio/wildmatch.c
@@ -0,0 +1,78 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+   Copyright (C) 2011 Free Software Foundation, Inc.
+
+   GNU Mailutils is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GNU Mailutils is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+#include <string.h>
+#include <mailutils/types.h>
+#include <mailutils/imaputil.h>
+
+/* Match STRING against the IMAP4 wildcard pattern PATTERN. */
+
+#define WILD_FALSE 0
+#define WILD_TRUE  1
+#define WILD_ABORT 2
+
+int
+_wild_match (const char *pat, const char *name, char delim)
+{
+  while (pat && *pat)
+    {
+      if (*name == 0 && *pat != '*')
+       return WILD_ABORT;
+      switch (*pat)
+       {
+       case '*':
+         while (*++pat == '*')
+           ;
+         if (*pat == 0)
+           return WILD_TRUE;
+         while (*name)
+           {
+             int res = _wild_match (pat, name++, delim);
+             if (res != WILD_FALSE)
+               return res;
+           }
+         return WILD_ABORT;
+
+       case '%':
+         while (*++pat == '%')
+           ;
+         if (*pat == 0)
+           return strchr (name, delim) ? WILD_FALSE : WILD_TRUE;
+         while (*name && *name != delim)
+           {
+             int res = _wild_match (pat, name++, delim);
+             if (res != WILD_FALSE)
+               return res;
+           }
+         return _wild_match (pat, name, delim);
+         
+       default:
+         if (*pat != *name)
+           return WILD_FALSE;
+         pat++;
+         name++;
+       }
+    }
+  return *name == 0;
+}
+
+int
+mu_imap_wildmatch (const char *pattern, const char *name, int delim)
+{
+  return _wild_match (pattern, name, delim) != WILD_TRUE;
+}
+
diff --git a/libmailutils/mailbox/Makefile.am b/libmailutils/mailbox/Makefile.am
index 27e6c04..cb9e775 100644
--- a/libmailutils/mailbox/Makefile.am
+++ b/libmailutils/mailbox/Makefile.am
@@ -25,6 +25,7 @@ libmailbox_la_SOURCES =  \
  body.c\
  envelope.c\
  folder.c\
+ fsfolder.c\
  hdrfirst.c\
  hdritr.c\
  header.c\
diff --git a/libmailutils/mailbox/folder.c b/libmailutils/mailbox/folder.c
index 3314fcd..c602b19 100644
--- a/libmailutils/mailbox/folder.c
+++ b/libmailutils/mailbox/folder.c
@@ -36,6 +36,8 @@
 #include <mailutils/url.h>
 #include <mailutils/errno.h>
 #include <mailutils/property.h>
+#include <mailutils/mailbox.h>
+#include <mailutils/imaputil.h>
 
 #include <mailutils/sys/folder.h>
 
@@ -47,9 +49,15 @@ static int is_known_folder (mu_url_t, mu_folder_t *);
 static struct mu_monitor folder_lock = MU_MONITOR_INITIALIZER;
 
 int
-mu_folder_match (const char *name, void *pattern, int flags)
+mu_folder_glob_match (const char *name, void *pattern, int flags)
 {
-  return fnmatch (pattern, name[0] == '/' ? name + 1 : name, flags);
+  return fnmatch (pattern, name[0] == '/' ? name + 1 : name, 0);
+}
+
+int
+mu_folder_imap_match (const char *name, void *pattern, int flags)
+{
+  return mu_imap_wildmatch (pattern, name, '/');
 }
 
 /* A folder could be remote (IMAP), or local(a spool directory) like $HOME/Mail
@@ -125,7 +133,7 @@ mu_folder_create_from_record (mu_folder_t *pfolder, 
mu_url_t url,
                  if (status == 0)
                    {
                      if (!folder->_match)
-                       folder->_match = mu_folder_match;
+                       folder->_match = mu_folder_imap_match;
                      *pfolder = folder;
                      folder->ref++;
                      /* Put on the internal list of known folders.  */
@@ -146,7 +154,7 @@ mu_folder_create_from_record (mu_folder_t *pfolder, 
mu_url_t url,
        }
     }
 
-    return MU_ERR_NOENT;
+  return MU_ERR_NOENT;
 }
 
 int
@@ -249,7 +257,9 @@ mu_folder_get_property (mu_folder_t folder, mu_property_t 
*prop)
 int
 mu_folder_open (mu_folder_t folder, int flags)
 {
-  if (folder == NULL || folder->_open == NULL)
+  if (folder == NULL)
+    return EINVAL;
+  if (folder->_open == NULL)
     return ENOSYS;
   return folder->_open (folder, flags);
 }
@@ -257,7 +267,9 @@ mu_folder_open (mu_folder_t folder, int flags)
 int
 mu_folder_close (mu_folder_t folder)
 {
-  if (folder == NULL || folder->_close == NULL)
+  if (folder == NULL)
+    return EINVAL;
+  if (folder->_close == NULL)
     return ENOSYS;
   return folder->_close (folder);
 }
@@ -381,8 +393,10 @@ mu_folder_enumerate (mu_folder_t folder, const char *name,
                     mu_folder_enumerate_fp enumfun, void *enumdata)
 {
   int status;
-  if (folder == NULL || folder->_list == NULL)
+  if (folder == NULL)
     return EINVAL;
+  else if (folder->_list == NULL)
+    return ENOSYS;
   else
     {
       mu_list_t list = NULL;
@@ -412,7 +426,9 @@ mu_folder_lsub (mu_folder_t folder, const char *dirname, 
const char *basename,
 {
   int status;
   
-  if (folder == NULL || folder->_lsub == NULL)
+  if (folder == NULL)
+    return EINVAL;
+  else if (folder->_lsub == NULL)
     return ENOSYS;
   else
     {
@@ -428,31 +444,64 @@ mu_folder_lsub (mu_folder_t folder, const char *dirname, 
const char *basename,
 int
 mu_folder_subscribe (mu_folder_t folder, const char *name)
 {
-  if (folder == NULL || folder->_subscribe == NULL)
+  if (folder == NULL)
     return EINVAL;
+  if (folder->_subscribe == NULL)
+    return ENOSYS;
   return folder->_subscribe (folder, name);
 }
 
 int
 mu_folder_unsubscribe (mu_folder_t folder, const char *name)
 {
-  if (folder == NULL || folder->_unsubscribe == NULL)
+  if (folder == NULL)
     return EINVAL;
+  if (folder->_unsubscribe == NULL)
+    return ENOSYS;
   return folder->_unsubscribe (folder, name);
 }
 
 int
 mu_folder_delete (mu_folder_t folder, const char *name)
 {
-  if (folder == NULL || folder->_delete == NULL)
-    return ENOSYS;
-  return folder->_delete (folder, name);
+  int rc;
+  
+  if (folder == NULL)
+    return EINVAL;
+  if (folder->_delete)
+    rc = folder->_delete (folder, name);
+  else
+    {
+      /* If there is no folder-specific _delete method, then try to create the
+        mailbox and call mailbox delete (remove) method.  This is necessary
+        because certain types of mailboxes share a common folder (e.g. mbox,
+        maildir and mh all use filesystem folder), but have a different
+        internal structure.  Supplying mu_folder_t with a knowledge of mailbox
+        internals will harm separation of concerns.  On the other hand,
+        removing something without looking into it may well yield undesired
+        results.  For example, a MH mailbox can hold another mailboxes, i.e.
+        be a folder itself.  Removing it blindly would result in removing
+        these mailboxes as well, which is clearly not indended.
+
+        To solve this folder and mailbox delete methods are tightly paired,
+        but without looking into each-others internal mechanisms. */
+      mu_mailbox_t mbox;
+      rc = mu_mailbox_create_at (&mbox, folder, name);
+      if (rc == 0)
+       {
+         rc = mu_mailbox_remove (mbox);
+         mu_mailbox_destroy (&mbox);
+       }
+    }
+  return rc;
 }
 
 int
 mu_folder_rename (mu_folder_t folder, const char *oldname, const char *newname)
 {
-  if (folder == NULL || folder->_rename == NULL)
+  if (folder == NULL)
+    return EINVAL;
+  if (folder->_rename == NULL)
     return ENOSYS;
   return folder->_rename (folder, oldname, newname);
 }
diff --git a/libproto/mbox/folder.c b/libmailutils/mailbox/fsfolder.c
similarity index 55%
copy from libproto/mbox/folder.c
copy to libmailutils/mailbox/fsfolder.c
index 2cc23bb..fb43e33 100644
--- a/libproto/mbox/folder.c
+++ b/libmailutils/mailbox/fsfolder.c
@@ -1,4 +1,4 @@
-/* GNU Mailutils -- a suite of utilities for electronic mail
+/* Implementation of file-system folder for GNU Mailutils
    Copyright (C) 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007, 2008,
    2010, 2011 Free Software Foundation, Inc.
 
@@ -41,169 +41,81 @@
 #include <mailutils/util.h>
 #include <mailutils/errno.h>
 #include <mailutils/debug.h>
+#include <mailutils/property.h>
+#include <mailutils/iterator.h>
 
-/* We export url parsing and the initialisation of
-   the mailbox, via the register entry/record.  */
+/* File-system folder is shared between UNIX mbox, maildir and MH
+   mailboxes.  It implements all usual folder methods, excepting
+   for _delete, which is implemented on the mailbox level.  See
+   comment to mu_folder_delete in folder.c */
+
+struct _mu_fsfolder
+{
+  char *dirname;
+  mu_property_t subscription;
+};
 
 static int
-_mbox_is_scheme (mu_record_t record, mu_url_t url, int flags)
+open_subscription (struct _mu_fsfolder *folder)
 {
-  int rc = 0;
-  
-  if (mu_url_is_scheme (url, record->scheme))
-    return MU_FOLDER_ATTRIBUTE_FILE & flags;
+  int rc;
+  mu_property_t prop;
+  mu_stream_t str;
+  char *filename = mu_make_file_name (folder->dirname, ".mu-subscr");
   
-  if (mu_scheme_autodetect_p (url))
-    {
-      struct stat st;
-      const char *path;
-
-      mu_url_sget_path (url, &path);
-      if (stat (path, &st) < 0)
-       return 0;
-
-      if (S_ISREG (st.st_mode) || S_ISCHR (st.st_mode))
-       {
-         if (st.st_size == 0)
-           {
-             rc |= MU_FOLDER_ATTRIBUTE_FILE;
-           }
-         else if (flags & MU_FOLDER_ATTRIBUTE_FILE)
-           {
-#if 0
-             /* This effectively sieves out all non-mailbox files,
-                but it makes mu_folder_enumerate crawl, which is
-                intolerable for imap4d LIST command. */
-             int fd = open (path, O_RDONLY);
-             if (fd != -1)
-               {
-                 char buf[5];
-                 if (read (fd, buf, 5) == 5)
-                   if (memcmp (buf, "From ", 5) == 0)
-                     rc |= MU_FOLDER_ATTRIBUTE_FILE;
-                 close (fd);
-               }
-#else
-             rc |= MU_FOLDER_ATTRIBUTE_FILE;
-#endif
-           }
-       }
-         
-      if ((flags & MU_FOLDER_ATTRIBUTE_DIRECTORY)
-         && S_ISDIR (st.st_mode))
-       rc |= MU_FOLDER_ATTRIBUTE_DIRECTORY;
-    }
+  rc = mu_file_stream_create (&str, filename, MU_STREAM_RDWR|MU_STREAM_CREAT);
+  if (rc)
+    return rc;
+  rc = mu_property_create_init (&prop, mu_assoc_property_init, str);
+  free (filename);
+  if (rc == 0)
+    folder->subscription = prop;
   return rc;
 }
 
-static struct _mu_record _mbox_record =
-{
-  MU_MBOX_PRIO,
-  MU_MBOX_SCHEME,
-  MU_RECORD_LOCAL,
-  MU_URL_SCHEME | MU_URL_PATH | MU_URL_PARAM,
-  MU_URL_PATH,
-  mu_url_expand_path, /* URL init.  */
-  _mailbox_mbox_init, /* Mailbox init.  */
-  NULL, /* Mailer init.  */
-  _folder_mbox_init, /* Folder init.  */
-  NULL, /* No need for an back pointer.  */
-  _mbox_is_scheme, /* _is_scheme method.  */
-  NULL, /* _get_url method.  */
-  NULL, /* _get_mailbox method.  */
-  NULL, /* _get_mailer method.  */
-  NULL  /* _get_folder method.  */
-};
-mu_record_t mu_mbox_record = &_mbox_record;
-
-/* lsub/subscribe/unsubscribe are not needed.  */
-static void folder_mbox_destroy    (mu_folder_t);
-static int folder_mbox_open        (mu_folder_t, int);
-static int folder_mbox_close       (mu_folder_t);
-static int folder_mbox_delete      (mu_folder_t, const char *);
-static int folder_mbox_rename      (mu_folder_t , const char *, const char *);
-static int folder_mbox_list        (mu_folder_t, const char *, void *, int,
-                                   size_t, mu_list_t, mu_folder_enumerate_fp,
-                                   void *);
-static int folder_mbox_subscribe   (mu_folder_t, const char *);
-static int folder_mbox_unsubscribe (mu_folder_t, const char *);
-static int folder_mbox_lsub        (mu_folder_t, const char *, const char *,
-                                   mu_list_t);
-
 
-static char *get_pathname       (const char *, const char *);
-
-static int folder_mbox_get_authority (mu_folder_t folder, mu_authority_t * 
pauth);
-
-struct _fmbox
-{
-  char *dirname;
-  char **subscribe;
-  size_t sublen;
-};
-typedef struct _fmbox *fmbox_t;
-
-
-int
-_folder_mbox_init (mu_folder_t folder)
+static char *
+get_pathname (const char *dirname, const char *basename)
 {
-  fmbox_t dfolder;
-  int status = 0;
-
-  /* We create an authority so the API is uniform across the mailbox
-     types. */
-  status = folder_mbox_get_authority (folder, NULL);
-  if (status != 0)
-    return status;
-
-  dfolder = folder->data = calloc (1, sizeof (*dfolder));
-  if (dfolder == NULL)
-    return ENOMEM;
+  char *pathname = NULL, *p;
 
-  status = mu_url_aget_path (folder->url, &dfolder->dirname);
-  if (status == MU_ERR_NOENT)
+  /* Skip eventual protocol designator. */
+  p = strchr (dirname, ':');
+  if (p && p[1] == '/' && p[2] == '/')
+    dirname = p + 3;
+  
+  /* null basename gives dirname.  */
+  if (basename == NULL)
+    pathname = (dirname) ? strdup (dirname) : strdup (".");
+  /* Absolute.  */
+  else if (basename[0] == '/')
+    pathname = strdup (basename);
+  /* Relative.  */
+  else
     {
-      dfolder->dirname = malloc (2);
-      if (dfolder->dirname == NULL)
-       status = ENOMEM;
-      else
+      size_t baselen = strlen (basename);
+      size_t dirlen = strlen (dirname);
+      while (dirlen > 0 && dirname[dirlen-1] == '/')
+       dirlen--;
+      pathname = calloc (dirlen + baselen + 2, sizeof (char));
+      if (pathname)
        {
-         strcpy (dfolder->dirname, ".");
-         status = 0;
+         memcpy (pathname, dirname, dirlen);
+         pathname[dirlen] = '/';
+         strcpy (pathname + dirlen + 1, basename);
        }
     }
-  
-  if (status)  
-    {
-      free (dfolder);
-      folder->data = NULL;
-      return status;
-    }
-
-  folder->_destroy = folder_mbox_destroy;
-
-  folder->_open = folder_mbox_open;
-  folder->_close = folder_mbox_close;
-
-  folder->_list = folder_mbox_list;
-  folder->_lsub = folder_mbox_lsub;
-  folder->_subscribe = folder_mbox_subscribe;
-  folder->_unsubscribe = folder_mbox_unsubscribe;
-  folder->_delete = folder_mbox_delete;
-  folder->_rename = folder_mbox_rename;
-  return 0;
+  return pathname;
 }
 
-void
-folder_mbox_destroy (mu_folder_t folder)
+static void
+_fsfolder_destroy (mu_folder_t folder)
 {
   if (folder->data)
     {
-      fmbox_t fmbox = folder->data;
-      if (fmbox->dirname)
-       free (fmbox->dirname);
-      if (fmbox->subscribe)
-       free (fmbox->subscribe);
+      struct _mu_fsfolder *fsfolder = folder->data;
+      free (fsfolder->dirname);
+      mu_property_destroy (&fsfolder->subscription);
       free (folder->data);
       folder->data = NULL;
     }
@@ -211,59 +123,45 @@ folder_mbox_destroy (mu_folder_t folder)
 
 /* Noop. */
 static int
-folder_mbox_open (mu_folder_t folder, int flags MU_ARG_UNUSED)
+_fsfolder_open (mu_folder_t folder, int flags MU_ARG_UNUSED)
 {
-  fmbox_t fmbox = folder->data;
+  struct _mu_fsfolder *fsfolder = folder->data;
   if (flags & MU_STREAM_CREAT)
     {
-      return (mkdir (fmbox->dirname, S_IRWXU) == 0) ? 0 : errno;
+      return (mkdir (fsfolder->dirname, S_IRWXU) == 0) ? 0 : errno;
     }
   return 0;
 }
 
 /*  Noop.  */
 static int
-folder_mbox_close (mu_folder_t folder MU_ARG_UNUSED)
-{
-  return 0;
-}
-
-static int
-folder_mbox_delete (mu_folder_t folder, const char *filename)
+_fsfolder_close (mu_folder_t folder MU_ARG_UNUSED)
 {
-  fmbox_t fmbox = folder->data;
-  if (filename)
-    {
-      int status = 0;
-      char *pathname = get_pathname (fmbox->dirname, filename);
-      if (pathname)
-       {
-         if (remove (pathname) != 0)
-           status = errno;
-         free (pathname);
-       }
-      else
-       status = ENOMEM;
-      return status;
-    }
-  return EINVAL;
+  int rc = 0;
+  struct _mu_fsfolder *fsfolder = folder->data;
+  
+  if (fsfolder->subscription)
+    rc = mu_property_save (fsfolder->subscription);
+  return rc;
 }
 
 static int
-folder_mbox_rename (mu_folder_t folder, const char *oldpath,
+_fsfolder_rename (mu_folder_t folder, const char *oldpath,
                    const char *newpath)
 {
-  fmbox_t fmbox = folder->data;
+  struct _mu_fsfolder *fsfolder = folder->data;
   if (oldpath && newpath)
     {
       int status = 0;
-      char *pathold = get_pathname (fmbox->dirname, oldpath);
+      char *pathold = get_pathname (fsfolder->dirname, oldpath);
       if (pathold)
        {
-         char *pathnew = get_pathname (fmbox->dirname, newpath);
+         char *pathnew = get_pathname (fsfolder->dirname, newpath);
          if (pathnew)
            {
-             if (rename (pathold, pathnew) != 0)
+             if (access (pathnew, F_OK) == 0)
+               status = EEXIST;
+             else if (rename (pathold, pathnew) != 0)
                status = errno;
              free (pathnew);
            }
@@ -346,6 +244,8 @@ list_helper (struct search_data *data, mu_record_t record,
       
       if (ename[ename[0] != '.' ? 0 : ename[1] != '.' ? 1 : 2] == 0)
        continue;
+      if (strncmp (ename, ".mu-", 4) == 0)
+       continue;
       fname = get_pathname (dirname, ename);
       if (lstat (fname, &st) == 0)
        {
@@ -454,19 +354,19 @@ list_helper (struct search_data *data, mu_record_t record,
 }
 
 static int
-folder_mbox_list (mu_folder_t folder, const char *ref,
-                 void *pattern,
-                 int flags,
-                 size_t max_level,
-                 mu_list_t flist,
-                 mu_folder_enumerate_fp enumfun, void *enumdata)
+_fsfolder_list (mu_folder_t folder, const char *ref,
+               void *pattern,
+               int flags,
+               size_t max_level,
+               mu_list_t flist,
+               mu_folder_enumerate_fp enumfun, void *enumdata)
 {
-  fmbox_t fmbox = folder->data;
+  struct _mu_fsfolder *fsfolder = folder->data;
   struct inode_list iroot;
   struct search_data sdata;
   
   memset (&iroot, 0, sizeof iroot);
-  sdata.dirname = get_pathname (fmbox->dirname, ref);
+  sdata.dirname = get_pathname (fsfolder->dirname, ref);
   sdata.dirlen = strlen (sdata.dirname);
   sdata.result = flist;
   sdata.enumfun = enumfun;
@@ -483,132 +383,146 @@ folder_mbox_list (mu_folder_t folder, const char *ref,
 }
 
 static int
-folder_mbox_lsub (mu_folder_t folder, const char *ref MU_ARG_UNUSED,
-                 const char *name,
-                 mu_list_t flist)
+_fsfolder_lsub (mu_folder_t folder, const char *ref, const char *name,
+               mu_list_t flist)
 {
-  fmbox_t fmbox = folder->data;
-  int status;
+  struct _mu_fsfolder *fsfolder = folder->data;
+  int rc;
+  char *pattern;
+  mu_iterator_t itr;
   
   if (name == NULL || *name == '\0')
     name = "*";
 
-  if (fmbox->sublen > 0)
-    {      
-      size_t i;
-
-      for (i = 0; i < fmbox->sublen; i++)
+  if (!fsfolder->subscription && (rc = open_subscription (fsfolder)))
+    return rc;
+    
+  pattern = mu_make_file_name (ref, name);
+  
+  rc = mu_property_get_iterator (fsfolder->subscription, &itr);
+  if (rc == 0)
+    {
+      for (mu_iterator_first (itr); !mu_iterator_is_done (itr);
+          mu_iterator_next (itr))
        {
-         if (fmbox->subscribe[i]
-             && fnmatch (name, fmbox->subscribe[i], 0) == 0)
+         const char *key, *val;
+         
+         mu_iterator_current_kv (itr, (const void **)&key, (void**)&val);
+
+         if (fnmatch (pattern, key, 0) == 0)
            {
              struct mu_list_response *resp;
              resp = malloc (sizeof (*resp));
              if (resp == NULL)
                {
-                 status = ENOMEM;
+                 rc = ENOMEM;
                  break;
                }
-             else if ((resp->name = strdup (fmbox->subscribe[i])) == NULL)
+             else if ((resp->name = strdup (key)) == NULL)
                {
                  free (resp);
-                 status = ENOMEM;
+                 rc = ENOMEM;
                  break;
                }
              resp->type = MU_FOLDER_ATTRIBUTE_FILE;
              resp->level = 0;
              resp->separator = '/';
+             rc = mu_list_append (flist, resp);
+             if (rc)
+               {
+                 free (resp);
+                 break;
+               }
            }
        }
+      mu_iterator_destroy (&itr);
     }
-  return status;
+  free (pattern);
+  return rc;
 }
 
 static int
-folder_mbox_subscribe (mu_folder_t folder, const char *name)
+_fsfolder_subscribe (mu_folder_t folder, const char *name)
 {
-  fmbox_t fmbox = folder->data;
-  char **tmp;
-  size_t i;
-  for (i = 0; i < fmbox->sublen; i++)
-    {
-      if (fmbox->subscribe[i] && strcmp (fmbox->subscribe[i], name) == 0)
-       return 0;
-    }
-  tmp = realloc (fmbox->subscribe, (fmbox->sublen + 1) * sizeof (*tmp));
-  if (tmp == NULL)
-    return ENOMEM;
-  fmbox->subscribe = tmp;
-  fmbox->subscribe[fmbox->sublen] = strdup (name);
-  if (fmbox->subscribe[fmbox->sublen] == NULL)
-    return ENOMEM;
-  fmbox->sublen++;
-  return 0;
-}
+  struct _mu_fsfolder *fsfolder = folder->data;
+  int rc;
+  
+  if (!fsfolder->subscription && (rc = open_subscription (fsfolder)))
+    return rc;
+
+  return mu_property_set_value (fsfolder->subscription, name, "", 1);
+}  
 
 static int
-folder_mbox_unsubscribe (mu_folder_t folder, const char *name)
+_fsfolder_unsubscribe (mu_folder_t folder, const char *name)
 {
-  fmbox_t fmbox = folder->data;
-  size_t i;
-  for (i = 0; i < fmbox->sublen; i++)
-    {
-      if (fmbox->subscribe[i] && strcmp (fmbox->subscribe[i], name) == 0)
-       {
-         free (fmbox->subscribe[i]);
-         fmbox->subscribe[i] = NULL;
-         return 0;
-       }
-    }
-  return MU_ERR_NOENT;
-}
+  struct _mu_fsfolder *fsfolder = folder->data;
+  int rc;
 
-static char *
-get_pathname (const char *dirname, const char *basename)
-{
-  char *pathname = NULL;
-
-  /* Skip eventual protocol designator.
-     FIXME: Actually, any valid URL spec should be allowed as dirname ... */
-  if (strncmp (dirname, MU_MBOX_SCHEME, MU_MBOX_SCHEME_LEN) == 0)
-    dirname += MU_MBOX_SCHEME_LEN;
-  else if (strncmp (dirname, MU_FILE_SCHEME, MU_FILE_SCHEME_LEN) == 0)
-    dirname += MU_FILE_SCHEME_LEN;
-  
-  /* null basename gives dirname.  */
-  if (basename == NULL)
-    pathname = (dirname) ? strdup (dirname) : strdup (".");
-  /* Absolute.  */
-  else if (basename[0] == '/')
-    pathname = strdup (basename);
-  /* Relative.  */
-  else
-    {
-      size_t baselen = strlen (basename);
-      size_t dirlen = strlen (dirname);
-      while (dirlen > 0 && dirname[dirlen-1] == '/')
-       dirlen--;
-      pathname = calloc (dirlen + baselen + 2, sizeof (char));
-      if (pathname)
-       {
-         memcpy (pathname, dirname, dirlen);
-         pathname[dirlen] = '/';
-         strcpy (pathname + dirlen + 1, basename);
-       }
-    }
-  return pathname;
+  if (!fsfolder->subscription && (rc = open_subscription (fsfolder)))
+    return rc;
+
+  return mu_property_unset (fsfolder->subscription, name);
 }
 
 static int
-folder_mbox_get_authority (mu_folder_t folder, mu_authority_t *pauth)
+_fsfolder_get_authority (mu_folder_t folder, mu_authority_t *pauth)
 {
   int status = 0;
   if (folder->authority == NULL)
-    {
-       status = mu_authority_create_null (&folder->authority, folder);
-    }
+    status = mu_authority_create_null (&folder->authority, folder);
   if (!status && pauth)
     *pauth = folder->authority;
   return status;
 }
 
+int
+_mu_fsfolder_init (mu_folder_t folder)
+{
+  struct _mu_fsfolder *dfolder;
+  int status = 0;
+
+  /* We create an authority so the API is uniform across the mailbox
+     types. */
+  status = _fsfolder_get_authority (folder, NULL);
+  if (status != 0)
+    return status;
+
+  dfolder = folder->data = calloc (1, sizeof (*dfolder));
+  if (dfolder == NULL)
+    return ENOMEM;
+
+  status = mu_url_aget_path (folder->url, &dfolder->dirname);
+  if (status == MU_ERR_NOENT)
+    {
+      dfolder->dirname = malloc (2);
+      if (dfolder->dirname == NULL)
+       status = ENOMEM;
+      else
+       {
+         strcpy (dfolder->dirname, ".");
+         status = 0;
+       }
+    }
+  
+  if (status)  
+    {
+      free (dfolder);
+      folder->data = NULL;
+      return status;
+    }
+
+  folder->_destroy = _fsfolder_destroy;
+
+  folder->_open = _fsfolder_open;
+  folder->_close = _fsfolder_close;
+
+  folder->_list = _fsfolder_list;
+  folder->_lsub = _fsfolder_lsub;
+  folder->_subscribe = _fsfolder_subscribe;
+  folder->_unsubscribe = _fsfolder_unsubscribe;
+  folder->_delete = NULL;
+  folder->_rename = _fsfolder_rename;
+  return 0;
+}
+
diff --git a/libmailutils/mailbox/mailbox.c b/libmailutils/mailbox/mailbox.c
index a31682a..990ae6a 100644
--- a/libmailutils/mailbox/mailbox.c
+++ b/libmailutils/mailbox/mailbox.c
@@ -41,6 +41,7 @@
 #include <mailutils/util.h>
 
 #include <mailutils/sys/mailbox.h>
+#include <mailutils/sys/folder.h>
 #include <mailutils/sys/url.h>
 
 /* Mailbox-specific flags */
@@ -76,7 +77,8 @@ mailbox_folder_create (mu_mailbox_t mbox, const char *name,
 int
 _mailbox_create_from_record (mu_mailbox_t *pmbox,
                             mu_record_t record,
-                            mu_url_t url, 
+                            mu_url_t url,
+                            mu_folder_t folder,
                             const char *name)
 {
   int (*m_init) (mu_mailbox_t) = NULL;
@@ -127,10 +129,16 @@ _mailbox_create_from_record (mu_mailbox_t *pmbox,
        }
       
       mbox->url = url;
-      
-      /* Create the folder before initializing the concrete mailbox.
-        The mailbox needs it's back pointer. */
-      status = mailbox_folder_create (mbox, name, record);
+
+      if (folder)
+       {
+         folder->ref++; /* FIXME: No ref/unref function for folders */
+         mbox->folder = folder;
+       }
+      else
+       /* Create the folder before initializing the concrete mailbox.
+          The mailbox needs it's back pointer. */
+       status = mailbox_folder_create (mbox, name, record);
       
       if (status == 0)
        status = m_init (mbox);   /* Create the concrete mailbox type.  */
@@ -152,11 +160,12 @@ static int
 _create_mailbox0 (mu_mailbox_t *pmbox, mu_url_t url, const char *name)
 {
   mu_record_t record = NULL;
-
-  if (mu_registrar_lookup_url (url, MU_FOLDER_ATTRIBUTE_FILE, &record, NULL)
-      == 0)
-    return _mailbox_create_from_record (pmbox, record, url, name);
-  return ENOSYS;
+  int rc;
+  
+  rc = mu_registrar_lookup_url (url, MU_FOLDER_ATTRIBUTE_FILE, &record, NULL);
+  if (rc == 0)
+    rc = _mailbox_create_from_record (pmbox, record, url, NULL, name);
+  return rc;
 }
 
 static int
@@ -203,7 +212,71 @@ mu_mailbox_create_from_record (mu_mailbox_t *pmbox, 
mu_record_t record,
   rc = mu_url_create (&url, name);
   if (rc)
     return rc;
-  rc = _mailbox_create_from_record (pmbox, record, url, name);
+  rc = _mailbox_create_from_record (pmbox, record, url, NULL, name);
+  if (rc)
+    mu_url_destroy (&url);
+  return rc;
+}
+
+int
+mu_mailbox_create_at (mu_mailbox_t *pmbox, mu_folder_t folder,
+                     const char *name)
+{
+  int rc;
+  mu_url_t url;
+  const char *oldpath;
+  
+  rc = mu_url_dup (folder->url, &url);
+  if (rc)
+    return rc;
+  do
+    {
+      char *path;
+      size_t oldlen, len;
+      mu_record_t record;
+      
+      rc = mu_url_sget_path (url, &oldpath);
+      if (rc)
+       break;
+
+      oldlen = strlen (oldpath);
+      if (oldlen == 0)
+       {
+         path = strdup (name);
+         if (!path)
+           {
+             rc = ENOMEM;
+             break;
+           }
+       }
+      else
+       {
+         if (oldpath[oldlen-1] == '/')
+           oldlen--;
+         len = oldlen + 1 + strlen (name) + 1;
+         path = malloc (len);
+         if (!path)
+           {
+             rc = ENOMEM;
+             break;
+           }
+         memcpy (path, oldpath, oldlen);
+         path[oldlen++] = '/';
+         strcpy (path + oldlen, name);
+       }
+      rc = mu_url_set_path (url, path);
+      free (path);
+      if (rc)
+       break;
+
+      rc = mu_registrar_lookup_url (url, MU_FOLDER_ATTRIBUTE_FILE,
+                                   &record, NULL);
+      if (rc)
+       break;
+      rc = _mailbox_create_from_record (pmbox, record, url, folder, name);
+    }
+  while (0);
+
   if (rc)
     mu_url_destroy (&url);
   return rc;
@@ -314,7 +387,24 @@ mu_mailbox_remove (mu_mailbox_t mbox)
   if (mbox->flags & _MU_MAILBOX_REMOVED)
     return MU_ERR_MBX_REMOVED;
   if (!mbox->_remove)
-    return MU_ERR_EMPTY_VFN;
+    {
+      /* Try the owning folder delete method.  See comment to mu_folder_delete
+        in folder.c.  This may result in a recursive call to mu_mailbox_remove
+        which is blocked by setting the _MU_MAILBOX_REMOVED flag. */
+
+      int rc;
+      const char *path;
+      
+      rc = mu_url_sget_path (mbox->url, &path);
+      if (rc == 0)
+       {
+         mbox->flags |= _MU_MAILBOX_REMOVED;
+         rc = mu_folder_delete (mbox->folder, path);
+         if (rc)
+           mbox->flags &= ~_MU_MAILBOX_REMOVED;
+       }
+      return rc;
+    }
   return mbox->_remove (mbox);
 }
 
@@ -689,7 +779,7 @@ mu_mailbox_set_folder (mu_mailbox_t mbox, mu_folder_t 
folder)
 {
   if (mbox == NULL)
     return EINVAL;
-   mbox->folder = folder;
+  mbox->folder = folder;
   return 0;
 }
 
diff --git a/libmailutils/mailbox/mbx_default.c 
b/libmailutils/mailbox/mbx_default.c
index 0556304..ff0a19b 100644
--- a/libmailutils/mailbox/mbx_default.c
+++ b/libmailutils/mailbox/mbx_default.c
@@ -345,7 +345,8 @@ attach_auth_ticket (mu_mailbox_t mbox)
       && mu_folder_get_authority (folder, &auth) == 0
       && auth)
     {
-      char *filename = mu_tilde_expansion (mu_ticket_file, "/", NULL);
+      char *filename = mu_tilde_expansion (mu_ticket_file,
+                                          MU_HIERARCHY_DELIMITER, NULL);
       mu_wicket_t wicket;
       int rc;
   
@@ -420,7 +421,7 @@ mu_mailbox_create_default (mu_mailbox_t *pmbox, const char 
*mail)
        }
     }
 
-  p = mu_tilde_expansion (mail, "/", NULL);
+  p = mu_tilde_expansion (mail, MU_HIERARCHY_DELIMITER, NULL);
   if (tmp_mbox)
     free (tmp_mbox);
   tmp_mbox = p;
diff --git a/libmailutils/tests/.gitignore b/libmailutils/tests/.gitignore
index d67519f..6a1188d 100644
--- a/libmailutils/tests/.gitignore
+++ b/libmailutils/tests/.gitignore
@@ -12,6 +12,7 @@ decode2047
 encode2047
 fltst
 fsaf
+fsfolder
 imapio
 listop
 mailcap
diff --git a/libmailutils/tests/Makefile.am b/libmailutils/tests/Makefile.am
index 1cb2968..aca151a 100644
--- a/libmailutils/tests/Makefile.am
+++ b/libmailutils/tests/Makefile.am
@@ -47,6 +47,7 @@ noinst_PROGRAMS = \
  encode2047\
  fltst\
  fsaf\
+ fsfolder\
  imapio\
  listop\
  mailcap\
@@ -78,6 +79,9 @@ TESTSUITE_AT = \
  encode2047.at\
  fromflt.at\
  fsaf.at\
+ fsfolder00.at\
+ fsfolder01.at\
+ fsfolder02.at\
  hdrflt.at\
  imapio.at\
  inline-comment.at\
diff --git a/libproto/imap/tests/imapfolder.c b/libmailutils/tests/fsfolder.c
similarity index 59%
copy from libproto/imap/tests/imapfolder.c
copy to libmailutils/tests/fsfolder.c
index cb3a08b..c2ae555 100644
--- a/libproto/imap/tests/imapfolder.c
+++ b/libmailutils/tests/fsfolder.c
@@ -1,25 +1,38 @@
 /* GNU Mailutils -- a suite of utilities for electronic mail
    Copyright (C) 2011 Free Software Foundation, Inc.
 
-   This library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 3 of the License, or (at your option) any later version.
+   GNU Mailutils is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
 
-   This library is distributed in the hope that it will be useful,
+   GNU Mailutils is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
 
-   You should have received a copy of the GNU Lesser General
-   Public License along with this library.  If not, see
-   <http://www.gnu.org/licenses/>. */
+   You should have received a copy of the GNU General Public License
+   along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>. */
 
 #ifdef HAVE_CONFIG_H
 # include <config.h>
 #endif
+#include <stdlib.h>
+#include <string.h>
+#include <mailutils/error.h>
+#include <mailutils/errno.h>
+#include <mailutils/folder.h>
+#include <mailutils/stream.h>
+#include <mailutils/stdstream.h>
+#include <mailutils/list.h>
+#include <mailutils/url.h>
+#include <mailutils/util.h>
+#include <mailutils/registrar.h>
+#include <mailutils/sys/folder.h>
+#include <mailutils/sys/registrar.h>
 
-#include <mailutils/mailutils.h>
+int sort_option;
+int prefix_len;
 
 struct command
 {
@@ -30,15 +43,29 @@ struct command
 };
 
 static int
+compare_response (void const *a, void const *b)
+{
+  struct mu_list_response const *ra = a;
+  struct mu_list_response const *rb = b;
+
+  if (ra->level < rb->level)
+    return -1;
+  if (ra->level > rb->level)
+    return 1;
+  return strcmp (ra->name, rb->name);
+}
+
+static int
 _print_list_entry (void *item, void *data)
 {
   struct mu_list_response *resp = item;
+  int len = data ? *(int*) data : 0;
   mu_printf ("%c%c %c %4d %s\n",
             (resp->type & MU_FOLDER_ATTRIBUTE_DIRECTORY) ? 'd' : '-',
             (resp->type & MU_FOLDER_ATTRIBUTE_FILE) ? 'f' : '-',
             resp->separator ? resp->separator : ' ',
             resp->level,
-            resp->name);
+            resp->name + len);
   return 0;
 }
 
@@ -48,13 +75,15 @@ com_list (mu_folder_t folder, char **argv)
   int rc;
   mu_list_t list;
   
-  mu_printf ("listing %s %s\n", argv[0], argv[1]);
+  mu_printf ("listing '%s' '%s'\n", argv[0], argv[1]);
   rc = mu_folder_list (folder, argv[0], argv[1], 0, &list);
   if (rc)
     mu_diag_funcall (MU_DIAG_ERROR, "mu_folder_list", argv[0], rc);
   else
     {
-      mu_list_foreach (list, _print_list_entry, NULL);
+      if (sort_option)
+       mu_list_sort (list, compare_response);
+      mu_list_foreach (list, _print_list_entry, &prefix_len);
       mu_list_destroy (&list);
     }
 }
@@ -71,25 +100,14 @@ com_lsub (mu_folder_t folder, char **argv)
     mu_diag_funcall (MU_DIAG_ERROR, "mu_folder_lsub", argv[0], rc);
   else
     {
+      if (sort_option)
+       mu_list_sort (list, compare_response);
       mu_list_foreach (list, _print_list_entry, NULL);
       mu_list_destroy (&list);
     }
 }
 
 static void
-com_delete (mu_folder_t folder, char **argv)
-{
-  int rc;
-  
-  mu_printf ("deleting %s\n", argv[0]);
-  rc = mu_folder_delete (folder, argv[0]);
-  if (rc)
-    mu_diag_funcall (MU_DIAG_ERROR, "mu_folder_lsub", argv[0], rc);
-  else
-    mu_printf ("delete successful\n");
-}
-
-static void
 com_rename (mu_folder_t folder, char **argv)
 {
   int rc;
@@ -131,9 +149,7 @@ com_unsubscribe (mu_folder_t folder, char **argv)
 static struct command comtab[] = {
   { "list", 2, "REF MBX", com_list },
   { "lsub", 2, "REF MBX", com_lsub },
-  { "delete", 1, "MBX", com_delete },
   { "rename", 2, "OLD NEW", com_rename },
-  { "delete", 1, "MBOX", com_delete },
   { "subscribe", 1, "MBX", com_subscribe },
   { "unsubscribe", 1, "MBX", com_unsubscribe },
   { NULL }
@@ -156,13 +172,38 @@ usage ()
   struct command *cp;
   
   mu_printf (
-    "usage: %s [debug=SPEC] url=URL OP ARG [ARG...] [OP ARG [ARG...]...]\n",
+    "usage: %s [-debug=SPEC] -name=URL [-sort] [-glob] OP ARG [ARG...] [OP ARG 
[ARG...]...]\n",
     mu_program_name);
   mu_printf ("OPerations and corresponding ARGuments are:\n");
   for (cp = comtab; cp->verb; cp++)
     mu_printf (" %s %s\n", cp->verb, cp->args);
 }
 
+static int
+_always_is_scheme (mu_record_t record, mu_url_t url, int flags)
+{
+  return 1;
+}
+
+static struct _mu_record test_record =
+{
+  0,
+  "file",
+  MU_RECORD_LOCAL,
+  MU_URL_SCHEME | MU_URL_PATH,
+  MU_URL_PATH,
+  mu_url_expand_path, /* URL init.  */
+  NULL, /* Mailbox init.  */
+  NULL, /* Mailer init.  */
+  _mu_fsfolder_init, /* Folder init.  */
+  NULL, /* No need for an back pointer.  */
+  _always_is_scheme, /* _is_scheme method.  */
+  NULL, /* _get_url method.  */
+  NULL, /* _get_mailbox method.  */
+  NULL, /* _get_mailer method.  */
+  NULL  /* _get_folder method.  */
+};
+
 int
 main (int argc, char **argv)
 {
@@ -170,10 +211,10 @@ main (int argc, char **argv)
   int rc;
   mu_folder_t folder;
   char *fname = NULL;
+  int glob_option = 0;
   
   mu_set_program_name (argv[0]);
-  mu_registrar_record (mu_imap_record);
-  mu_registrar_record (mu_imaps_record);
+  mu_registrar_record (&test_record);
 
   if (argc == 1)
     {
@@ -183,33 +224,49 @@ main (int argc, char **argv)
 
   for (i = 1; i < argc; i++)
     {
-      if (strncmp (argv[i], "debug=", 6) == 0)
-       mu_debug_parse_spec (argv[i] + 6);
-      else if (strncmp (argv[i], "url=", 4) == 0)
-       fname = argv[i] + 4;
+      if (strncmp (argv[i], "-debug=", 7) == 0)
+       mu_debug_parse_spec (argv[i] + 7);
+      else if (strncmp (argv[i], "-name=", 6) == 0)
+       fname = argv[i] + 6;
+      else if (strcmp (argv[i], "-sort") == 0)
+       sort_option = 1;
+      else if (strcmp (argv[i], "-glob") == 0)
+       glob_option = 1;
       else
        break;
     }
 
   if (!fname)
     {
-      mu_error ("URL not specified");
+      mu_error ("name not specified");
       exit (1);
     }
-      
+  
+  if (fname[0] != '/')
+    {
+      char *cwd = mu_getcwd ();
+      prefix_len = strlen (cwd);
+      if (cwd[prefix_len-1] != '/')
+       prefix_len++;
+      fname = mu_make_file_name (cwd, fname);
+      free (cwd);
+    }
+  
   rc = mu_folder_create (&folder, fname);
   if (rc)
     {
       mu_diag_funcall (MU_DIAG_ERROR, "mu_folder_create", fname, rc);
       return 1;
     }
-  
   rc = mu_folder_open (folder, MU_STREAM_READ);
   if (rc)
     {
       mu_diag_funcall (MU_DIAG_ERROR, "mu_folder_open", fname, rc);
       return 1;
     }
+
+  if (glob_option)
+    mu_folder_set_match (folder, mu_folder_glob_match);
   
   while (i < argc)
     {
diff --git a/imap4d/tests/create02.at b/libmailutils/tests/fsfolder00.at
similarity index 55%
copy from imap4d/tests/create02.at
copy to libmailutils/tests/fsfolder00.at
index 552e8d3..a2b75db 100644
--- a/imap4d/tests/create02.at
+++ b/libmailutils/tests/fsfolder00.at
@@ -14,25 +14,40 @@
 # You should have received a copy of the GNU General Public License
 # along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>.
 
-AT_SETUP([create nested])
-AT_KEYWORDS([create create01])
+AT_SETUP([List])
+AT_KEYWORDS([fsfolder folder-list])
 
 AT_CHECK([
-AT_DATA([input],[dnl
-1 create en/to/tre
-X LOGOUT
-])
+mkdir dir
+> dir/foo
+> dir/bar
+> dir/foo.mbox
+mkdir dir/subdir
+> dir/subdir/file
+> dir/subdir/baz.mbox
 
-imap4d IMAP4D_OPTIONS < input | tr -d '\r'
-find . -name tre
+fsfolder -name=dir -sort dnl
+ list "" "*" dnl
+ list subdir "*" dnl
+ list "" "*.mbox" dnl
+ list "subdir" "*.mbox"
 ],
 [0],
-[* PREAUTH IMAP4rev1 Test mode
-1 OK CREATE Completed
-* BYE Session terminating.
-X OK LOGOUT Completed
-./en/to/tre
+[listing '' '*'
+d- /    0 dir/bar
+d- /    0 dir/foo
+d- /    0 dir/foo.mbox
+d- /    0 dir/subdir
+d- /    1 dir/subdir/baz.mbox
+d- /    1 dir/subdir/file
+listing 'subdir' '*'
+d- /    0 dir/subdir/baz.mbox
+d- /    0 dir/subdir/file
+listing '' '*.mbox'
+d- /    0 dir/foo.mbox
+d- /    1 dir/subdir/baz.mbox
+listing 'subdir' '*.mbox'
+d- /    0 dir/subdir/baz.mbox
 ])
 
 AT_CLEANUP
-
diff --git a/libmailutils/tests/fsfolder01.at b/libmailutils/tests/fsfolder01.at
new file mode 100644
index 0000000..b6c2f18
--- /dev/null
+++ b/libmailutils/tests/fsfolder01.at
@@ -0,0 +1,74 @@
+# This file is part of GNU Mailutils. -*- Autotest -*-
+# Copyright (C) 2011 Free Software Foundation, Inc.
+#
+# GNU Mailutils is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 3, or (at
+# your option) any later version.
+#
+# GNU Mailutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>.
+
+AT_SETUP([Subscriptions])
+AT_KEYWORDS([fsfolder folder-subscribe])
+
+AT_CHECK([
+mkdir dir
+fsfolder -name=dir -sort lsub "" "*"
+fsfolder -name=dir subscribe foo
+fsfolder -name=dir -sort lsub "" "*"
+fsfolder -name=dir subscribe baz subscribe foo/baz subscribe foo/bar
+fsfolder -name=dir -sort lsub "" "*"
+fsfolder -name=dir -sort lsub foo "*"
+fsfolder -name=dir -sort lsub "" 'foo*'
+fsfolder -name=dir unsubscribe baz
+fsfolder -name=dir -sort lsub "" "*"
+fsfolder -name=dir unsubscribe foo
+fsfolder -name=dir -sort lsub "" "*"
+],
+[0],
+[listing subscriptions for '' '*'
+subscribing foo
+subscribe successful
+listing subscriptions for '' '*'
+-f /    0 foo
+subscribing baz
+subscribe successful
+subscribing foo/baz
+subscribe successful
+subscribing foo/bar
+subscribe successful
+listing subscriptions for '' '*'
+-f /    0 baz
+-f /    0 foo
+-f /    0 foo/bar
+-f /    0 foo/baz
+listing subscriptions for 'foo' '*'
+-f /    0 foo/bar
+-f /    0 foo/baz
+listing subscriptions for '' 'foo*'
+-f /    0 foo
+-f /    0 foo/bar
+-f /    0 foo/baz
+unsubscribing baz
+unsubscribe successful
+listing subscriptions for '' '*'
+-f /    0 foo
+-f /    0 foo/bar
+-f /    0 foo/baz
+unsubscribing foo
+unsubscribe successful
+listing subscriptions for '' '*'
+-f /    0 foo/bar
+-f /    0 foo/baz
+])
+
+AT_CLEANUP
+
+
+
diff --git a/libmailutils/tests/strerr.at b/libmailutils/tests/fsfolder02.at
similarity index 69%
copy from libmailutils/tests/strerr.at
copy to libmailutils/tests/fsfolder02.at
index 1bdbe6f..09711f8 100644
--- a/libmailutils/tests/strerr.at
+++ b/libmailutils/tests/fsfolder02.at
@@ -14,24 +14,26 @@
 # You should have received a copy of the GNU General Public License
 # along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>.
 
-AT_SETUP([strerr])
-AT_KEYWORDS([stdstream])
+AT_SETUP([Rename])
+AT_KEYWORDS([fsfolder folder-rename])
 
 AT_CHECK([
-strout -err now is the time for all good men
+mkdir dir
+> dir/foo
+fsfolder -name=dir rename foo bar
+fsfolder -name=dir list "" "*"
+> dir/baz
+fsfolder -name=dir rename bar baz
 ],
 [0],
-[],
-[strout: now
-strout: is
-strout: the
-strout: time
-strout: for
-strout: all
-strout: good
-strout: men
+[renaming foo to bar
+rename successful
+listing '' '*'
+d- /    0 dir/bar
+renaming bar to baz
+],
+[fsfolder: mu_folder_rename(bar) failed: File exists
 ])
 
 AT_CLEANUP
 
-
diff --git a/libmailutils/tests/testsuite.at b/libmailutils/tests/testsuite.at
index 888c25a..4c1b427 100644
--- a/libmailutils/tests/testsuite.at
+++ b/libmailutils/tests/testsuite.at
@@ -68,6 +68,11 @@ m4_include([mailcap.at])
 m4_include([wicket.at])
 m4_include([prop.at])
 
+AT_BANNER(File-system folder)
+m4_include([fsfolder00.at])
+m4_include([fsfolder01.at])
+m4_include([fsfolder02.at])
+
 AT_BANNER(Base64)
 m4_include([base64e.at])
 m4_include([base64d.at])
diff --git a/libmu_sieve/extensions/vacation.c 
b/libmu_sieve/extensions/vacation.c
index 160930f..299309f 100644
--- a/libmu_sieve/extensions/vacation.c
+++ b/libmu_sieve/extensions/vacation.c
@@ -348,7 +348,7 @@ check_db (mu_sieve_machine_t mach, mu_list_t tags, char 
*from)
   else
     days = DAYS_DEFAULT;
 
-  file = mu_tilde_expansion ("~/.vacation", "/", NULL);
+  file = mu_tilde_expansion ("~/.vacation", MU_HIERARCHY_DELIMITER, NULL);
   if (!file)
     {
       mu_sieve_error (mach, _("%lu: cannot build db file name"),
diff --git a/libproto/imap/select.c b/libproto/imap/select.c
index 05dd550..31c2b72 100644
--- a/libproto/imap/select.c
+++ b/libproto/imap/select.c
@@ -25,6 +25,7 @@
 #include <mailutils/assoc.h>
 #include <mailutils/stream.h>
 #include <mailutils/imap.h>
+#include <mailutils/imaputil.h>
 #include <mailutils/sys/imap.h>
 
 static int
diff --git a/libproto/imap/tests/imapfolder.c b/libproto/imap/tests/imapfolder.c
index cb3a08b..d19b052 100644
--- a/libproto/imap/tests/imapfolder.c
+++ b/libproto/imap/tests/imapfolder.c
@@ -133,7 +133,6 @@ static struct command comtab[] = {
   { "lsub", 2, "REF MBX", com_lsub },
   { "delete", 1, "MBX", com_delete },
   { "rename", 2, "OLD NEW", com_rename },
-  { "delete", 1, "MBOX", com_delete },
   { "subscribe", 1, "MBX", com_subscribe },
   { "unsubscribe", 1, "MBX", com_unsubscribe },
   { NULL }
diff --git a/libproto/maildir/folder.c b/libproto/maildir/folder.c
index bba6848..df25e53 100644
--- a/libproto/maildir/folder.c
+++ b/libproto/maildir/folder.c
@@ -37,12 +37,6 @@
 #include <mailutils/sys/amd.h>
 
 static int
-_maildir_folder_init (mu_folder_t folder MU_ARG_UNUSED)
-{
-  return 0;
-}
-
-static int
 dir_exists (const char *name, const char *suf)
 {
   struct stat st;
@@ -59,31 +53,42 @@ dir_exists (const char *name, const char *suf)
 static int
 _maildir_is_scheme (mu_record_t record, mu_url_t url, int flags)
 {
-  if (mu_url_is_scheme (url, record->scheme))
-    return MU_FOLDER_ATTRIBUTE_FILE & flags; 
-
-  if (mu_scheme_autodetect_p (url))
+  int scheme_matched = mu_url_is_scheme (url, record->scheme);
+  int rc = 0;
+  
+  if (scheme_matched || mu_scheme_autodetect_p (url))
     {
       /* Attemp auto-detection */
       const char *path;
       struct stat st;
-      
+
       if (mu_url_sget_path (url, &path))
         return 0;
 
       if (stat (path, &st) < 0)
-       return 0; 
-
+       {
+         if (errno == ENOENT && scheme_matched)
+           return MU_FOLDER_ATTRIBUTE_ALL & flags; 
+         return 0; 
+       }
+      
       if (!S_ISDIR (st.st_mode))
        return 0;
 
-      if ((flags & MU_FOLDER_ATTRIBUTE_FILE)
-         && dir_exists (path, TMPSUF)
-            && dir_exists (path, CURSUF)
-            && dir_exists (path, NEWSUF))
-        return MU_FOLDER_ATTRIBUTE_FILE|MU_FOLDER_ATTRIBUTE_DIRECTORY;
+      if (scheme_matched)
+       rc = MU_FOLDER_ATTRIBUTE_ALL;
+      else
+       {
+         rc |= MU_FOLDER_ATTRIBUTE_DIRECTORY;
+      
+         if ((flags & MU_FOLDER_ATTRIBUTE_FILE)
+             && dir_exists (path, TMPSUF)
+             && dir_exists (path, CURSUF)
+             && dir_exists (path, NEWSUF))
+           rc |= MU_FOLDER_ATTRIBUTE_FILE;
+       }
     }
-  return 0;
+  return rc & flags;
 }
 
 static int
@@ -106,7 +111,7 @@ static struct _mu_record _maildir_record =
   mu_url_expand_path, /* Url init.  */
   _mailbox_maildir_init, /* Mailbox init.  */
   NULL, /* Mailer init.  */
-  _maildir_folder_init, /* Folder init.  */
+  _mu_fsfolder_init, /* Folder init.  */
   NULL, /* back pointer.  */
   _maildir_is_scheme, /* _is_scheme method.  */
   NULL, /* _get_url method.  */
diff --git a/libproto/mailer/smtp_auth.c b/libproto/mailer/smtp_auth.c
index 6929e18..e789fb8 100644
--- a/libproto/mailer/smtp_auth.c
+++ b/libproto/mailer/smtp_auth.c
@@ -32,7 +32,8 @@
 static int
 get_ticket (mu_ticket_t *pticket)
 {
-  char *filename = mu_tilde_expansion (mu_ticket_file, "/", NULL);
+  char *filename = mu_tilde_expansion (mu_ticket_file,
+                                      MU_HIERARCHY_DELIMITER, NULL);
   mu_wicket_t wicket;
   int rc;
 
diff --git a/libproto/mbox/folder.c b/libproto/mbox/folder.c
index 2cc23bb..9e2c3f1 100644
--- a/libproto/mbox/folder.c
+++ b/libproto/mbox/folder.c
@@ -49,19 +49,23 @@ static int
 _mbox_is_scheme (mu_record_t record, mu_url_t url, int flags)
 {
   int rc = 0;
-  
-  if (mu_url_is_scheme (url, record->scheme))
-    return MU_FOLDER_ATTRIBUTE_FILE & flags;
-  
-  if (mu_scheme_autodetect_p (url))
+  int scheme_matched = mu_url_is_scheme (url, record->scheme);
+  if (scheme_matched || mu_scheme_autodetect_p (url))
     {
       struct stat st;
       const char *path;
 
       mu_url_sget_path (url, &path);
       if (stat (path, &st) < 0)
-       return 0;
-
+       {
+         if (errno == ENOENT)
+           {
+             if (scheme_matched)
+               return MU_FOLDER_ATTRIBUTE_FILE & flags;
+           }
+         return 0;
+       }
+      
       if (S_ISREG (st.st_mode) || S_ISCHR (st.st_mode))
        {
          if (st.st_size == 0)
@@ -71,7 +75,7 @@ _mbox_is_scheme (mu_record_t record, mu_url_t url, int flags)
          else if (flags & MU_FOLDER_ATTRIBUTE_FILE)
            {
 #if 0
-             /* This effectively sieves out all non-mailbox files,
+             /* FIXME: This effectively sieves out all non-mailbox files,
                 but it makes mu_folder_enumerate crawl, which is
                 intolerable for imap4d LIST command. */
              int fd = open (path, O_RDONLY);
@@ -106,7 +110,7 @@ static struct _mu_record _mbox_record =
   mu_url_expand_path, /* URL init.  */
   _mailbox_mbox_init, /* Mailbox init.  */
   NULL, /* Mailer init.  */
-  _folder_mbox_init, /* Folder init.  */
+  _mu_fsfolder_init, /* Folder init.  */
   NULL, /* No need for an back pointer.  */
   _mbox_is_scheme, /* _is_scheme method.  */
   NULL, /* _get_url method.  */
@@ -116,499 +120,4 @@ static struct _mu_record _mbox_record =
 };
 mu_record_t mu_mbox_record = &_mbox_record;
 
-/* lsub/subscribe/unsubscribe are not needed.  */
-static void folder_mbox_destroy    (mu_folder_t);
-static int folder_mbox_open        (mu_folder_t, int);
-static int folder_mbox_close       (mu_folder_t);
-static int folder_mbox_delete      (mu_folder_t, const char *);
-static int folder_mbox_rename      (mu_folder_t , const char *, const char *);
-static int folder_mbox_list        (mu_folder_t, const char *, void *, int,
-                                   size_t, mu_list_t, mu_folder_enumerate_fp,
-                                   void *);
-static int folder_mbox_subscribe   (mu_folder_t, const char *);
-static int folder_mbox_unsubscribe (mu_folder_t, const char *);
-static int folder_mbox_lsub        (mu_folder_t, const char *, const char *,
-                                   mu_list_t);
-
-
-static char *get_pathname       (const char *, const char *);
-
-static int folder_mbox_get_authority (mu_folder_t folder, mu_authority_t * 
pauth);
-
-struct _fmbox
-{
-  char *dirname;
-  char **subscribe;
-  size_t sublen;
-};
-typedef struct _fmbox *fmbox_t;
-
-
-int
-_folder_mbox_init (mu_folder_t folder)
-{
-  fmbox_t dfolder;
-  int status = 0;
-
-  /* We create an authority so the API is uniform across the mailbox
-     types. */
-  status = folder_mbox_get_authority (folder, NULL);
-  if (status != 0)
-    return status;
-
-  dfolder = folder->data = calloc (1, sizeof (*dfolder));
-  if (dfolder == NULL)
-    return ENOMEM;
-
-  status = mu_url_aget_path (folder->url, &dfolder->dirname);
-  if (status == MU_ERR_NOENT)
-    {
-      dfolder->dirname = malloc (2);
-      if (dfolder->dirname == NULL)
-       status = ENOMEM;
-      else
-       {
-         strcpy (dfolder->dirname, ".");
-         status = 0;
-       }
-    }
-  
-  if (status)  
-    {
-      free (dfolder);
-      folder->data = NULL;
-      return status;
-    }
-
-  folder->_destroy = folder_mbox_destroy;
-
-  folder->_open = folder_mbox_open;
-  folder->_close = folder_mbox_close;
-
-  folder->_list = folder_mbox_list;
-  folder->_lsub = folder_mbox_lsub;
-  folder->_subscribe = folder_mbox_subscribe;
-  folder->_unsubscribe = folder_mbox_unsubscribe;
-  folder->_delete = folder_mbox_delete;
-  folder->_rename = folder_mbox_rename;
-  return 0;
-}
-
-void
-folder_mbox_destroy (mu_folder_t folder)
-{
-  if (folder->data)
-    {
-      fmbox_t fmbox = folder->data;
-      if (fmbox->dirname)
-       free (fmbox->dirname);
-      if (fmbox->subscribe)
-       free (fmbox->subscribe);
-      free (folder->data);
-      folder->data = NULL;
-    }
-}
-
-/* Noop. */
-static int
-folder_mbox_open (mu_folder_t folder, int flags MU_ARG_UNUSED)
-{
-  fmbox_t fmbox = folder->data;
-  if (flags & MU_STREAM_CREAT)
-    {
-      return (mkdir (fmbox->dirname, S_IRWXU) == 0) ? 0 : errno;
-    }
-  return 0;
-}
-
-/*  Noop.  */
-static int
-folder_mbox_close (mu_folder_t folder MU_ARG_UNUSED)
-{
-  return 0;
-}
-
-static int
-folder_mbox_delete (mu_folder_t folder, const char *filename)
-{
-  fmbox_t fmbox = folder->data;
-  if (filename)
-    {
-      int status = 0;
-      char *pathname = get_pathname (fmbox->dirname, filename);
-      if (pathname)
-       {
-         if (remove (pathname) != 0)
-           status = errno;
-         free (pathname);
-       }
-      else
-       status = ENOMEM;
-      return status;
-    }
-  return EINVAL;
-}
-
-static int
-folder_mbox_rename (mu_folder_t folder, const char *oldpath,
-                   const char *newpath)
-{
-  fmbox_t fmbox = folder->data;
-  if (oldpath && newpath)
-    {
-      int status = 0;
-      char *pathold = get_pathname (fmbox->dirname, oldpath);
-      if (pathold)
-       {
-         char *pathnew = get_pathname (fmbox->dirname, newpath);
-         if (pathnew)
-           {
-             if (rename (pathold, pathnew) != 0)
-               status = errno;
-             free (pathnew);
-           }
-         else
-           status = ENOMEM;
-         free (pathold);
-       }
-      else
-       status = ENOMEM;
-      return status;
-    }
-  return EINVAL;
-}
-
-struct inode_list           /* Inode/dev number list used to cut off
-                              recursion */
-{
-  struct inode_list *next;
-  ino_t inode;
-  dev_t dev;
-};
-
-struct search_data
-{
-  mu_list_t result;
-  mu_folder_enumerate_fp enumfun;
-  void *enumdata;
-  char *dirname;
-  size_t dirlen;
-  void *pattern;
-  int flags;
-  size_t max_level;
-  size_t errcnt;
-  mu_folder_t folder;
-};
-
-static int
-inode_list_lookup (struct inode_list *list, struct stat *st)
-{
-  for (; list; list = list->next)
-    if (list->inode == st->st_ino && list->dev == st->st_dev)
-      return 1;
-  return 0;
-}
-
-static int
-list_helper (struct search_data *data, mu_record_t record,
-            const char *dirname, size_t level,
-            struct inode_list *ilist)
-{
-  DIR *dirp;
-  struct dirent *dp;
-  int stop = 0;
-    
-  if (data->max_level && level > data->max_level)
-    return 0;
-
-  dirp = opendir (dirname);
-  if (dirp == NULL)
-    {
-      mu_debug (MU_DEBCAT_MAILER, MU_DEBUG_ERROR,
-               ("list_helper cannot open directory %s: %s",
-                dirname, mu_strerror (errno)));
-      data->errcnt++;
-      return 1;
-    }
-
-  if (!record)
-    {
-      int type;
-      mu_registrar_lookup (dirname, MU_FOLDER_ATTRIBUTE_ALL,
-                          &record, &type);
-    }
-  
-  while ((dp = readdir (dirp)))
-    {
-      char const *ename = dp->d_name;
-      char *fname;
-      struct stat st;
-      
-      if (ename[ename[0] != '.' ? 0 : ename[1] != '.' ? 1 : 2] == 0)
-       continue;
-      fname = get_pathname (dirname, ename);
-      if (lstat (fname, &st) == 0)
-       {
-         int f;
-         if (S_ISDIR (st.st_mode))
-           f = MU_FOLDER_ATTRIBUTE_DIRECTORY;
-         else if (S_ISREG (st.st_mode))
-           f = MU_FOLDER_ATTRIBUTE_FILE;
-         else if (S_ISLNK (st.st_mode))
-           f = MU_FOLDER_ATTRIBUTE_LINK;
-         else
-           f = 0;
-         if (mu_record_list_p (record, ename, f))
-           {
-             if (data->folder->_match == NULL
-                 || data->folder->_match (fname + data->dirlen +
-                                          ((data->dirlen > 1
-                                            && data->dirname[data->dirlen-1] 
!= '/') ?
-                                           1 : 0),
-                                          data->pattern,
-                                          data->flags) == 0)
-               {
-                 char *refname = fname;
-                 int type = 0;
-                 struct mu_list_response *resp;
-                 mu_record_t rec = NULL;
-                 
-                 resp = malloc (sizeof (*resp));
-                 if (resp == NULL)
-                   {
-                     mu_debug (MU_DEBCAT_MAILER, MU_DEBUG_ERROR,
-                               ("list_helper: %s", mu_strerror (ENOMEM)));
-                     data->errcnt++;
-                     free (fname);
-                     continue;
-                   }
-                 
-                 mu_registrar_lookup (refname, MU_FOLDER_ATTRIBUTE_ALL,
-                                      &rec, &type);
-                 
-                 resp->name = fname;
-                 resp->level = level;
-                 resp->separator = '/';
-                 resp->type = type;
-                 resp->format = rec;
-                 
-                 if (resp->type == 0)
-                   {
-                     free (resp->name);
-                     free (resp);
-                     continue;
-                   }
-                 
-                 if (data->enumfun)
-                   {
-                     if (data->enumfun (data->folder, resp, data->enumdata))
-                       {
-                         free (resp->name);
-                         free (resp);
-                         stop = 1;
-                         break;
-                       }
-                   }
-                 
-                 if (data->result)
-                   {
-                     fname = NULL;
-                     mu_list_append (data->result, resp);
-                   }
-                 else
-                   free (resp);
-                 
-                 if ((type & MU_FOLDER_ATTRIBUTE_DIRECTORY)
-                     && !inode_list_lookup (ilist, &st))
-                   {
-                     struct inode_list idata;
-                     
-                     idata.inode = st.st_ino;
-                     idata.dev   = st.st_dev;
-                     idata.next  = ilist;
-                     stop = list_helper (data, rec, refname, level + 1,
-                                         &idata);
-                   }
-               }
-             else if (S_ISDIR (st.st_mode))
-               {
-                 struct inode_list idata;
-                 
-                 idata.inode = st.st_ino;
-                 idata.dev   = st.st_dev;
-                 idata.next  = ilist;
-                 stop = list_helper (data, NULL, fname, level + 1, &idata);
-               }
-           }
-       }
-      else
-       {
-         mu_debug (MU_DEBCAT_MAILER, MU_DEBUG_ERROR,
-                   ("list_helper cannot stat %s: %s",
-                    fname, mu_strerror (errno)));
-       }
-      free (fname);
-    }
-  closedir (dirp);
-  return stop;
-}
-
-static int
-folder_mbox_list (mu_folder_t folder, const char *ref,
-                 void *pattern,
-                 int flags,
-                 size_t max_level,
-                 mu_list_t flist,
-                 mu_folder_enumerate_fp enumfun, void *enumdata)
-{
-  fmbox_t fmbox = folder->data;
-  struct inode_list iroot;
-  struct search_data sdata;
-  
-  memset (&iroot, 0, sizeof iroot);
-  sdata.dirname = get_pathname (fmbox->dirname, ref);
-  sdata.dirlen = strlen (sdata.dirname);
-  sdata.result = flist;
-  sdata.enumfun = enumfun;
-  sdata.enumdata = enumdata;
-  sdata.pattern = pattern;
-  sdata.flags = flags;
-  sdata.max_level = max_level;
-  sdata.folder = folder;
-  sdata.errcnt = 0;
-  list_helper (&sdata, NULL, sdata.dirname, 0, &iroot);
-  free (sdata.dirname);
-  /* FIXME: error code */
-  return 0;
-}
-
-static int
-folder_mbox_lsub (mu_folder_t folder, const char *ref MU_ARG_UNUSED,
-                 const char *name,
-                 mu_list_t flist)
-{
-  fmbox_t fmbox = folder->data;
-  int status;
-  
-  if (name == NULL || *name == '\0')
-    name = "*";
-
-  if (fmbox->sublen > 0)
-    {      
-      size_t i;
-
-      for (i = 0; i < fmbox->sublen; i++)
-       {
-         if (fmbox->subscribe[i]
-             && fnmatch (name, fmbox->subscribe[i], 0) == 0)
-           {
-             struct mu_list_response *resp;
-             resp = malloc (sizeof (*resp));
-             if (resp == NULL)
-               {
-                 status = ENOMEM;
-                 break;
-               }
-             else if ((resp->name = strdup (fmbox->subscribe[i])) == NULL)
-               {
-                 free (resp);
-                 status = ENOMEM;
-                 break;
-               }
-             resp->type = MU_FOLDER_ATTRIBUTE_FILE;
-             resp->level = 0;
-             resp->separator = '/';
-           }
-       }
-    }
-  return status;
-}
-
-static int
-folder_mbox_subscribe (mu_folder_t folder, const char *name)
-{
-  fmbox_t fmbox = folder->data;
-  char **tmp;
-  size_t i;
-  for (i = 0; i < fmbox->sublen; i++)
-    {
-      if (fmbox->subscribe[i] && strcmp (fmbox->subscribe[i], name) == 0)
-       return 0;
-    }
-  tmp = realloc (fmbox->subscribe, (fmbox->sublen + 1) * sizeof (*tmp));
-  if (tmp == NULL)
-    return ENOMEM;
-  fmbox->subscribe = tmp;
-  fmbox->subscribe[fmbox->sublen] = strdup (name);
-  if (fmbox->subscribe[fmbox->sublen] == NULL)
-    return ENOMEM;
-  fmbox->sublen++;
-  return 0;
-}
-
-static int
-folder_mbox_unsubscribe (mu_folder_t folder, const char *name)
-{
-  fmbox_t fmbox = folder->data;
-  size_t i;
-  for (i = 0; i < fmbox->sublen; i++)
-    {
-      if (fmbox->subscribe[i] && strcmp (fmbox->subscribe[i], name) == 0)
-       {
-         free (fmbox->subscribe[i]);
-         fmbox->subscribe[i] = NULL;
-         return 0;
-       }
-    }
-  return MU_ERR_NOENT;
-}
-
-static char *
-get_pathname (const char *dirname, const char *basename)
-{
-  char *pathname = NULL;
-
-  /* Skip eventual protocol designator.
-     FIXME: Actually, any valid URL spec should be allowed as dirname ... */
-  if (strncmp (dirname, MU_MBOX_SCHEME, MU_MBOX_SCHEME_LEN) == 0)
-    dirname += MU_MBOX_SCHEME_LEN;
-  else if (strncmp (dirname, MU_FILE_SCHEME, MU_FILE_SCHEME_LEN) == 0)
-    dirname += MU_FILE_SCHEME_LEN;
-  
-  /* null basename gives dirname.  */
-  if (basename == NULL)
-    pathname = (dirname) ? strdup (dirname) : strdup (".");
-  /* Absolute.  */
-  else if (basename[0] == '/')
-    pathname = strdup (basename);
-  /* Relative.  */
-  else
-    {
-      size_t baselen = strlen (basename);
-      size_t dirlen = strlen (dirname);
-      while (dirlen > 0 && dirname[dirlen-1] == '/')
-       dirlen--;
-      pathname = calloc (dirlen + baselen + 2, sizeof (char));
-      if (pathname)
-       {
-         memcpy (pathname, dirname, dirlen);
-         pathname[dirlen] = '/';
-         strcpy (pathname + dirlen + 1, basename);
-       }
-    }
-  return pathname;
-}
-
-static int
-folder_mbox_get_authority (mu_folder_t folder, mu_authority_t *pauth)
-{
-  int status = 0;
-  if (folder->authority == NULL)
-    {
-       status = mu_authority_create_null (&folder->authority, folder);
-    }
-  if (!status && pauth)
-    *pauth = folder->authority;
-  return status;
-}
 
diff --git a/libproto/mh/folder.c b/libproto/mh/folder.c
index 66e02cf..4d9b43f 100644
--- a/libproto/mh/folder.c
+++ b/libproto/mh/folder.c
@@ -37,12 +37,6 @@
 #include <mailutils/util.h>
 #include <mailutils/cctype.h>
 
-static int
-_mh_folder_init (mu_folder_t folder MU_ARG_UNUSED)
-{
-  return 0;
-}
-
 /* Check if NAME is a valid MH message name */
 static int
 mh_message_name_p (const char *name)
@@ -90,13 +84,11 @@ static int
 _mh_is_scheme (mu_record_t record, mu_url_t url, int flags)
 {
   int rc = 0;
+  int scheme_matched = mu_url_is_scheme (url, record->scheme);
   
-  if (mu_url_is_scheme (url, record->scheme))
-    return MU_FOLDER_ATTRIBUTE_ALL & flags;
-
-  if (mu_scheme_autodetect_p (url))
+  if (scheme_matched || mu_scheme_autodetect_p (url))
     {
-      /* Attemp auto-detection */
+      /* Attempt auto-detection */
       const char *path;
       struct stat st;
       
@@ -104,18 +96,27 @@ _mh_is_scheme (mu_record_t record, mu_url_t url, int flags)
         return 0;
 
       if (stat (path, &st) < 0)
-       return 0; /* mu_mailbox_open will complain*/
-
+       {
+         if (errno == ENOENT && scheme_matched)
+           return MU_FOLDER_ATTRIBUTE_ALL & flags; 
+         return 0; /* mu_mailbox_open will complain*/
+       }
+      
       if (!S_ISDIR (st.st_mode))
        return 0;
 
-      rc |= (MU_FOLDER_ATTRIBUTE_DIRECTORY & flags);
+      if (scheme_matched)
+       rc = MU_FOLDER_ATTRIBUTE_ALL;
+      else
+       {
+         rc |= MU_FOLDER_ATTRIBUTE_DIRECTORY;
       
-      if ((flags & MU_FOLDER_ATTRIBUTE_FILE) && mh_dir_p (path))
-        return rc | MU_FOLDER_ATTRIBUTE_FILE;
+         if ((flags & MU_FOLDER_ATTRIBUTE_FILE) && mh_dir_p (path))
+           rc |= MU_FOLDER_ATTRIBUTE_FILE;
+       }
     }
 
-  return 0;
+  return rc & flags;
 }
 
 static int
@@ -142,7 +143,7 @@ static struct _mu_record _mh_record =
   mu_url_expand_path, /* Url init.  */
   _mailbox_mh_init, /* Mailbox init.  */
   NULL, /* Mailer init.  */
-  _mh_folder_init, /* Folder init.  */
+  _mu_fsfolder_init, /* Folder init.  */
   NULL, /* back pointer.  */
   _mh_is_scheme, /* _is_scheme method.  */
   NULL, /* _get_url method.  */
diff --git a/mail/util.c b/mail/util.c
index b008048..747723c 100644
--- a/mail/util.c
+++ b/mail/util.c
@@ -475,7 +475,7 @@ util_get_homedir ()
 char *
 util_fullpath (const char *inpath)
 {
-  return mu_tilde_expansion (inpath, "/", NULL);
+  return mu_tilde_expansion (inpath, MU_HIERARCHY_DELIMITER, NULL);
 }
 
 char *
diff --git a/mh/install-mh.c b/mh/install-mh.c
index 8ccc5b8..da810c3 100644
--- a/mh/install-mh.c
+++ b/mh/install-mh.c
@@ -69,7 +69,7 @@ main (int argc, char **argv)
 
   name = getenv ("MH");
   if (name)
-    name = mu_tilde_expansion (name, "/", NULL);
+    name = mu_tilde_expansion (name, MU_HIERARCHY_DELIMITER, NULL);
   else
     {
       char *home = mu_get_homedir ();
diff --git a/mh/mh_global.c b/mh/mh_global.c
index f4ee5d1..2dbce1d 100644
--- a/mh/mh_global.c
+++ b/mh/mh_global.c
@@ -94,7 +94,7 @@ mh_read_profile ()
   
   p = getenv ("MH");
   if (p)
-    p = mu_tilde_expansion (p, "/", NULL);
+    p = mu_tilde_expansion (p, MU_HIERARCHY_DELIMITER, NULL);
   else
     {
       char *home = mu_get_homedir ();
diff --git a/mh/mh_init.c b/mh/mh_init.c
index d89a05d..75976f2 100644
--- a/mh/mh_init.c
+++ b/mh/mh_init.c
@@ -390,8 +390,8 @@ mh_audit_open (char *name, mu_mailbox_t mbox)
   mu_url_t url;
   char *namep;
   
-  namep = mu_tilde_expansion (name, "/", NULL);
-  if (strchr (namep, '/') == NULL)
+  namep = mu_tilde_expansion (name, MU_HIERARCHY_DELIMITER, NULL);
+  if (strchr (namep, MU_HIERARCHY_DELIMITER) == NULL)
     {
       char *p = mh_safe_make_file_name (mu_folder_directory (), namep);
       free (namep);
@@ -487,7 +487,7 @@ mh_expand_name (const char *base, const char *name, int 
is_folder)
   char *p = NULL;
   char *namep = NULL;
   
-  namep = mu_tilde_expansion (name, "/", NULL);
+  namep = mu_tilde_expansion (name, MU_HIERARCHY_DELIMITER, NULL);
   if (namep[0] == '+')
     memmove (namep, namep + 1, strlen (namep)); /* copy null byte as well */
   else if (strncmp (namep, "../", 3) == 0 || strncmp (namep, "./", 2) == 0)
@@ -536,7 +536,7 @@ mh_find_file (const char *name, char **resolved_name)
 
   if (name[0] == '~')
     {
-      s = mu_tilde_expansion (name, "/", NULL);
+      s = mu_tilde_expansion (name, MU_HIERARCHY_DELIMITER, NULL);
       *resolved_name = s;
       if (access (s, R_OK) == 0)
        return 0;
diff --git a/mh/mhn.c b/mh/mhn.c
index ead6c83..57d7418 100644
--- a/mh/mhn.c
+++ b/mh/mhn.c
@@ -2961,7 +2961,8 @@ main (int argc, char **argv)
        }
       message = mh_file_to_message (NULL,
                                    mu_tilde_expansion (input_file,
-                                                       "/", NULL));
+                                                       MU_HIERARCHY_DELIMITER,
+                                                       NULL));
       if (!message)
        return 1;
     }
diff --git a/mh/send.c b/mh/send.c
index b654f10..1f433b9 100644
--- a/mh/send.c
+++ b/mh/send.c
@@ -327,7 +327,7 @@ read_mts_profile ()
       name = mh_expand_name (MHLIBDIR, "mtstailor", 0);
       mts_profile = mh_read_property_file (name, 1);
 
-      name = mu_tilde_expansion ("~/.mtstailor", "/", NULL);
+      name = mu_tilde_expansion ("~/.mtstailor", MU_HIERARCHY_DELIMITER, NULL);
       local_profile = mh_read_property_file (name, 1);
 
       mh_property_merge (mts_profile, local_profile);
diff --git a/mu/imap.c b/mu/imap.c
index 92e9c42..85b0f60 100644
--- a/mu/imap.c
+++ b/mu/imap.c
@@ -26,6 +26,7 @@
 #include <mailutils/mailutils.h>
 #include <mailutils/imap.h>
 #include <mailutils/imapio.h>
+#include <mailutils/imaputil.h>
 #include "mu.h"
 #include "argp.h"
 #include "xalloc.h"
diff --git a/mu/shell.c b/mu/shell.c
index 891b08b..78ac94c 100644
--- a/mu/shell.c
+++ b/mu/shell.c
@@ -296,7 +296,7 @@ get_history_file_name ()
       strcpy (hname, "~/.mu_");
       strcat (hname, rl_readline_name);
       strcat (hname, HISTFILE_SUFFIX);
-      filename = mu_tilde_expansion (hname, "/", NULL);
+      filename = mu_tilde_expansion (hname, MU_HIERARCHY_DELIMITER, NULL);
       free(hname);
     }
   return filename;
diff --git a/mu/wicket.c b/mu/wicket.c
index f01b148..81a3f3e 100644
--- a/mu/wicket.c
+++ b/mu/wicket.c
@@ -141,7 +141,7 @@ mutool_wicket (int argc, char **argv)
       return 1;
     }
 
-  wicket_file = mu_tilde_expansion (wicket_file, "/", NULL);
+  wicket_file = mu_tilde_expansion (wicket_file, MU_HIERARCHY_DELIMITER, NULL);
   if (!wicket_file)
     {
       mu_diag_funcall (MU_DIAG_ERROR, "mu_tilde_expansion", wicket_file,
diff --git a/pop3d/bulletin.c b/pop3d/bulletin.c
index 9f4105d..c42229c 100644
--- a/pop3d/bulletin.c
+++ b/pop3d/bulletin.c
@@ -75,7 +75,8 @@ read_popbull_file (size_t *pnum)
 {
   int rc = 1;
   FILE *fp;
-  char *filename = mu_tilde_expansion ("~/.popbull", "/", auth_data->dir);
+  char *filename = mu_tilde_expansion ("~/.popbull", MU_HIERARCHY_DELIMITER,
+                                      auth_data->dir);
   
   if (!filename)
     return 1;
@@ -99,7 +100,8 @@ write_popbull_file (size_t num)
 {
   int rc = 1;
   FILE *fp;
-  char *filename = mu_tilde_expansion ("~/.popbull", "/", auth_data->dir);
+  char *filename = mu_tilde_expansion ("~/.popbull", MU_HIERARCHY_DELIMITER,
+                                      auth_data->dir);
   
   if (!filename)
     return 1;
diff --git a/python/Makefile.am b/python/Makefile.am
index bdf55e6..08be9af 100644
--- a/python/Makefile.am
+++ b/python/Makefile.am
@@ -15,4 +15,5 @@
 ## along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>. 
 
 SUBDIRS = libmu_py mailutils
+EXTRA_DIST=usercustomize.py
 
diff --git a/python/libmu_py/Makefile.am b/python/libmu_py/Makefile.am
index d3d198d..84350c7 100644
--- a/python/libmu_py/Makefile.am
+++ b/python/libmu_py/Makefile.am
@@ -60,8 +60,3 @@ libmu_py_la_LIBADD = $(PYTHON_LIBS) @MU_COMMON_LIBRARIES@ \
  @address@hidden
  ${MU_LIB_MAILUTILS}
 
address@hidden@
-pythonexec_LTLIBRARIES = c_api.la
-c_api_la_LDFLAGS = -avoid-version -module -rpath $(pythonexecdir)
-c_api_la_LIBADD = $(PYTHON_LIBS) ${MU_LIB_PY}
-c_api_la_SOURCES = c_api.c
diff --git a/python/mailutils/Makefile.am b/python/mailutils/Makefile.am
index 1208361..e3bb74a 100644
--- a/python/mailutils/Makefile.am
+++ b/python/mailutils/Makefile.am
@@ -39,3 +39,11 @@ pythonsite_PYTHON=\
  url.py \
  util.py
 
address@hidden@
+pythonexec_LTLIBRARIES = c_api.la
+c_api_la_LDFLAGS = -avoid-version -module -rpath $(pythonexecdir)
+c_api_la_LIBADD = $(PYTHON_LIBS) ${MU_LIB_PY}
+c_api_la_SOURCES = c_api.c
+
+INCLUDES = @MU_LIB_COMMON_INCLUDES@ @address@hidden
+ -I$(top_srcdir)/python/libmu_py
diff --git a/python/libmu_py/c_api.c b/python/mailutils/c_api.c
similarity index 100%
rename from python/libmu_py/c_api.c
rename to python/mailutils/c_api.c
diff --git a/python/usercustomize.py b/python/usercustomize.py
new file mode 100644
index 0000000..585377c
--- /dev/null
+++ b/python/usercustomize.py
@@ -0,0 +1,63 @@
+# Libtool library loader for Python.
+# This file is part of GNU Mailutils.
+# Copyright (C) 2011 Free Software Foundation, Inc.
+#
+# GNU Mailutils is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 3, or (at
+# your option) any later version.
+#
+# GNU Mailutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>. 
+
+# This file modifies the normal import routine by looking additionally
+# into module.la file and trying to load corresponding so library (as
+# determined by the dlname variable in it) from the .libs subdirectory.
+#
+# It is used to load Mailutils Python modules from the source tree.
+#
+# Example usage:
+#
+#  PYTHONPATH=/path/to/mailutils-3.0/python python test.py
+
+import sys,os,imp
+
+class laloader(object):
+    def __init__(self, filename, libdir):
+        self.filename = filename
+        self.libdir = libdir
+
+    def load_module(self, name):
+        with open(self.filename) as f:
+            for line in f:
+                s = line.strip()
+                if s.startswith('dlname='):
+                    s = s[7:].strip("'\"")
+                    libname = self.libdir + '/' + s
+                    if os.path.exists(libname):
+                        return imp.load_dynamic(name, libname)
+        return None
+    
+class lafinder(object):
+    def __init__(self):
+        pass
+    def find_module(self, fullname, path=None):
+        ml = fullname.split(".")
+        s = '/'.join(ml)+'.la'
+        libs = '/'.join(ml[:-1]) + '/.libs'
+        for dir in sys.path:
+            name = dir + '/' + s
+            libdir = dir + '/' + libs
+            if os.path.exists(name) and os.path.exists(libdir):
+                return laloader(name, libdir)
+        return None
+
+sys.meta_path.append(lafinder())
+
+# End of file
+
diff --git a/sieve/sieve.c b/sieve/sieve.c
index 07c41f5..a1107ca 100644
--- a/sieve/sieve.c
+++ b/sieve/sieve.c
@@ -231,7 +231,7 @@ parser (int key, char *arg, struct argp_state *state)
     case ARGP_KEY_ARG:
       if (script)
        argp_error (state, _("Only one SCRIPT can be specified"));
-      script = mu_tilde_expansion (arg, "/", NULL);
+      script = mu_tilde_expansion (arg, MU_HIERARCHY_DELIMITER, NULL);
       break;
 
     case ARGP_KEY_INIT:
diff --git a/testsuite/.gitignore b/testsuite/.gitignore
index 9db984b..29a9221 100644
--- a/testsuite/.gitignore
+++ b/testsuite/.gitignore
@@ -1,5 +1,6 @@
 atconfig
 atlocal
+fldel
 package.m4
 testsuite
 testsuite.dir
diff --git a/testsuite/Makefile.am b/testsuite/Makefile.am
index 1707985..219731d 100644
--- a/testsuite/Makefile.am
+++ b/testsuite/Makefile.am
@@ -50,6 +50,7 @@ $(srcdir)/package.m4: $(top_srcdir)/configure.ac
 
 INCLUDES = @MU_LIB_COMMON_INCLUDES@ 
 noinst_PROGRAMS = \
+ fldel\
  lstuid\
  mbdel\
  mimetest\
@@ -78,6 +79,7 @@ smtpsend_LDADD = \
 ## ------------ ##
 
 TESTSUITE_AT = \
+ fldel.at\
  lstuid00.at\
  lstuid01.at\
  lstuid02.at\
diff --git a/testsuite/atlocal.in b/testsuite/atlocal.in
index 9cd80d1..2a16c4d 100644
--- a/testsuite/atlocal.in
+++ b/testsuite/atlocal.in
@@ -3,3 +3,5 @@
 # Copyright (C) 2004, 2010, 2011 Free Software Foundation, Inc.
 
 address@hidden@:@abs_top_builddir@/libtests:$top_srcdir:$srcdir:$PATH
address@hidden@MH_SUPPORT=yes
address@hidden@MAILDIR_SUPPORT=yes
diff --git a/testsuite/fldel.at b/testsuite/fldel.at
new file mode 100644
index 0000000..06ca9d8
--- /dev/null
+++ b/testsuite/fldel.at
@@ -0,0 +1,81 @@
+# This file is part of GNU Mailutils. -*- Autotest -*-
+# Copyright (C) 2010, 2011 Free Software Foundation, Inc.
+#
+# GNU Mailutils is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 3, or (at
+# your option) any later version.
+#
+# GNU Mailutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>.
+
+dnl ------------------------------------------------------------
+dnl FLDEL_TEST([FORMAT], [PROG],
+dnl             [CODE], [STDOUT = `'], [STDERR = `'],
+dnl             [RUN-IF-FAIL], [RUN-IF-PASS])
+m4_pushdef([FLDEL_TEST],[
+AT_SETUP([Folder deletion: $1])
+AT_KEYWORDS([folder fldel fldel-$1])
+AT_CHECK([$2],[$3],[$4],[$5],[$6],[$7],[$8])
+AT_CLEANUP
+])
+
+dnl ------------------------------------------------------------
+FLDEL_TEST([mbox],
+[mkdir dir
+MUT_MBCOPY($abs_top_srcdir/testsuite/spool/mbox1, dir/mbox1)
+fldel mbox:dir mbox1 || exit 2
+test -f dir/mbox1
+],
+[1])
+
+FLDEL_TEST([mh],
+[test "$MH_SUPPORT" = yes || AT_SKIP_TEST
+mkdir dir
+MUT_MBCOPY($abs_top_srcdir/testsuite/mh/mbox1, dir/mbox1)
+fldel mh:dir mbox1 || exit 2
+test -d dir/mbox1
+],
+[1])
+
+FLDEL_TEST([maildir],
+[test "$MAILDIR_SUPPORT" = yes || AT_SKIP_TEST
+mkdir dir
+MUT_MBCOPY($abs_top_srcdir/testsuite/maildir/mbox1, dir/mbox1)
+fldel maildir:dir mbox1 || exit 2
+test -d dir/mbox1
+],
+[1])
+
+FLDEL_TEST([mh with subdirs],
+[test "$MH_SUPPORT" = yes || AT_SKIP_TEST
+mkdir dir
+MUT_MBCOPY($abs_top_srcdir/testsuite/mh/mbox1, dir/mbox1)
+mkdir dir/mbox1/subfolder
+fldel mh:dir mbox1 || exit 2
+test -d dir/mbox1 && find dir/mbox1
+],
+[0],
+[mailbox removed, but has subfolders
+dir/mbox1
+dir/mbox1/subfolder
+])
+
+FLDEL_TEST([maildir with subdirs],
+[test "$MAILDIR_SUPPORT" = yes || AT_SKIP_TEST
+mkdir dir
+MUT_MBCOPY($abs_top_srcdir/testsuite/maildir/mbox1, dir/mbox1)
+mkdir dir/mbox1/subfolder
+fldel maildir:dir mbox1 || exit 2
+test -d dir/mbox1 && find dir/mbox1
+],
+[0],
+[mailbox removed, but has subfolders
+dir/mbox1
+dir/mbox1/subfolder
+])
diff --git a/testsuite/mbdel.c b/testsuite/fldel.c
similarity index 85%
copy from testsuite/mbdel.c
copy to testsuite/fldel.c
index 8451df5..206f6b6 100644
--- a/testsuite/mbdel.c
+++ b/testsuite/fldel.c
@@ -26,18 +26,18 @@ int
 main (int argc, char **argv)
 {
   int rc;
-  mu_mailbox_t mbox;
+  mu_folder_t f;
   
-  if (argc != 2)
+  if (argc != 3)
     {
-      fprintf (stderr, "usage: %s URL\n", argv[0]);
+      fprintf (stderr, "usage: %s URL NAME\n", argv[0]);
       return 1;
     }
 
   mu_register_all_mbox_formats ();
   
-  MU_ASSERT (mu_mailbox_create (&mbox, argv[1]));
-  rc = mu_mailbox_remove (mbox);
+  MU_ASSERT (mu_folder_create (&f, argv[1]));
+  rc = mu_folder_delete (f, argv[2]);
   if (rc)
     {
       if (rc == ENOTEMPTY)
@@ -48,7 +48,7 @@ main (int argc, char **argv)
       else
        fprintf (stderr, "%s\n", mu_strerror (rc));
     }
-  mu_mailbox_destroy (&mbox);
+  mu_folder_destroy (&f);
   
   return rc != 0;
 }
diff --git a/testsuite/mbdel.at b/testsuite/mbdel.at
index 4e84332..c3693eb 100644
--- a/testsuite/mbdel.at
+++ b/testsuite/mbdel.at
@@ -18,7 +18,7 @@ dnl 
------------------------------------------------------------
 dnl MBDEL_TEST([FORMAT], [PROG],
 dnl             [CODE], [STDOUT = `'], [STDERR = `'],
 dnl             [RUN-IF-FAIL], [RUN-IF-PASS])
-m4_define([MBDEL_TEST],[
+m4_pushdef([MBDEL_TEST],[
 AT_SETUP([Mailbox deletion: $1])
 AT_KEYWORDS([mailbox mbdel mbdel-$1])
 AT_CHECK([$2],[$3],[$4],[$5],[$6],[$7],[$8])
@@ -34,21 +34,24 @@ test -f mbox1
 [1])
 
 MBDEL_TEST([mh],
-[MUT_MBCOPY($abs_top_srcdir/testsuite/mh/mbox1)
+[test "$MH_SUPPORT" = yes || AT_SKIP_TEST
+MUT_MBCOPY($abs_top_srcdir/testsuite/mh/mbox1)
 mbdel mh:mbox1 || exit 2
 test -d mbox1
 ],
 [1])
 
 MBDEL_TEST([maildir],
-[MUT_MBCOPY($abs_top_srcdir/testsuite/maildir/mbox1)
+[test "$MAILDIR_SUPPORT" = yes || AT_SKIP_TEST
+MUT_MBCOPY($abs_top_srcdir/testsuite/maildir/mbox1)
 mbdel maildir:mbox1 || exit 2
 test -d mbox1
 ],
 [1])
 
 MBDEL_TEST([mh with subdirs],
-[MUT_MBCOPY($abs_top_srcdir/testsuite/mh/mbox1)
+[test "$MH_SUPPORT" = yes || AT_SKIP_TEST
+MUT_MBCOPY($abs_top_srcdir/testsuite/mh/mbox1)
 mkdir mbox1/subfolder
 mbdel mh:mbox1 || exit 2
 test -d mbox1 && find mbox1
@@ -60,7 +63,8 @@ mbox1/subfolder
 ])
 
 MBDEL_TEST([maildir with subdirs],
-[MUT_MBCOPY($abs_top_srcdir/testsuite/maildir/mbox1)
+[test "$MAILDIR_SUPPORT" = yes || AT_SKIP_TEST
+MUT_MBCOPY($abs_top_srcdir/testsuite/maildir/mbox1)
 mkdir mbox1/subfolder
 mbdel maildir:mbox1 || exit 2
 test -d mbox1 && find mbox1
@@ -70,3 +74,5 @@ test -d mbox1 && find mbox1
 mbox1
 mbox1/subfolder
 ])
+
+m4_popdef([MBDEL_TEST])
diff --git a/testsuite/testsuite.at b/testsuite/testsuite.at
index 48bbe1a..87f80dc 100644
--- a/testsuite/testsuite.at
+++ b/testsuite/testsuite.at
@@ -18,9 +18,19 @@ m4_include([testsuite.inc])
 
 AT_INIT
 
+AT_BANNER(UIDs)
 m4_include([lstuid00.at])
 m4_include([lstuid01.at])
 m4_include([lstuid02.at])
+
+AT_BANNER(mimetest)
 m4_include([mime.at])
+
+AT_BANNER(Mailbox removal)
 m4_include([mbdel.at])
+
+AT_BANNER(Folder mailbox removal)
+m4_include([fldel.at])
+
+AT_BANNER(Various)
 m4_include([ufms.at])


hooks/post-receive
-- 
GNU Mailutils



reply via email to

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