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-160-g3327a23


From: Sergey Poznyakoff
Subject: [SCM] GNU Mailutils branch, master, updated. release-2.2-160-g3327a23
Date: Tue, 26 Oct 2010 10:39:11 +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=3327a23a49e532c068972a0b2d64021361540f7b

The branch, master has been updated
       via  3327a23a49e532c068972a0b2d64021361540f7b (commit)
      from  6203ae65f53758a4b893e6e176be7c153a31bef0 (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 3327a23a49e532c068972a0b2d64021361540f7b
Author: Sergey Poznyakoff <address@hidden>
Date:   Tue Oct 26 13:00:52 2010 +0300

    Rewrite URL support.
    
    The purpose is to make it modular and flexible.  URLs are
    parsed out as they are created.  Missing URL parts can be
    supplied via a "URL hint" at creation time (similar to
    the approach used in creating mu_address_t).  Ports
    can be specified either as numbers or as service names.
    Original port string representation can be retrieved from
    the URL, as well as its numeric value.
    
    * libmailutils/url/accessor.h: New file.
    * libmailutils/url/copy.c: New file.
    * libmailutils/url/create.c: New file.
    * libmailutils/url/decode.c: New file.
    * libmailutils/url/destroy.c: New file.
    * libmailutils/url/dup.c: New file.
    * libmailutils/url/expand.c: New file.
    * libmailutils/url/flag.c: New file.
    * libmailutils/url/get-auth.c: New file.
    * libmailutils/url/get-host.c: New file.
    * libmailutils/url/get-param.c: New file.
    * libmailutils/url/get-path.c: New file.
    * libmailutils/url/get-portstr.c: New file.
    * libmailutils/url/get-query.c: New file.
    * libmailutils/url/get-scheme.c: New file.
    * libmailutils/url/get-secret.c: New file.
    * libmailutils/url/get-user.c: New file.
    * libmailutils/url/match.c: New file.
    * libmailutils/url/port.c: New file.
    * libmailutils/url/scheme.c: New file.
    * libmailutils/url/uplevel.c: New file.
    * libmailutils/url/urlstr.c: New file.
    
    * configure.ac (AC_CONFIG_FILES): Add libmailutils/url/Makefile
    * libmailutils/Makefile.am (SUBDIRS): Add url.
    (libmailutils_la_LIBADD): Link with liburl.
    * libmailutils/base/Makefile.am (libbase_la_SOURCES): Remove url.c
    * libmailutils/base/url.c: Remove.
    
    * libmailutils/string/Makefile.am (libstring_la_SOURCES): Add xdecode.c
    * libmailutils/string/xdecode.c: New file.
    
    * include/mailutils/sys/url.h (_mu_url): Change type to short.
    <_get_port>: Change second argument to unsigned.
    <_get_portstr>: New method.
    * include/mailutils/url.h (MU_URL_SCHEME): New flag.
    (MU_URL_PARSE_HEXCODE, MU_URL_PARSE_HIDEPASS)
    (MU_URL_PARSE_PORTSRV, MU_URL_PARSE_PORTWC)
    (MU_URL_PARSE_PIPE, MU_URL_PARSE_SLASH): New flags.
    (mu_url_create_hint, mu_url_copy_hints): New prototypes.
    (mu_url_parse): Remove.
    (mu_url_get_port): Change second argument to unsigned.
    (mu_url_decode_len,mu_url_decode): Remove.
    (mu_url_decode): New proto.
    (mu_url_sget_portstr, mu_url_aget_portstr)
    (mu_url_get_portstr): New protos.
    
    * include/mailutils/util.h (mu_str_url_decode)
    (mu_str_url_decode_inline): New protos.
    * libproto/pop/mbox.c (pop_open): Port is unsigned.
    
    * libproto/imap/folder.c: Use MU_URL_SCHEME in url_may_have.
    * libproto/maildir/folder.c: Likewise.
    * libproto/mailer/prog.c: Likewise.
    * libproto/mailer/remote.c: Likewise.
    * libproto/mailer/sendmail.c: Likewise.
    * libproto/mailer/smtp.c: Likewise.
    * libproto/mbox/folder.c: Likewise.
    * libproto/mh/folder.c: Likewise.
    * libproto/nntp/folder.c: Likewise.
    * libproto/pop/folder.c: Likewise.
    
    * imap4d/imap4d.c: Remove calls to mu_url_parse.
    * libmailutils/base/registrar.c: Likewise.
    * libmailutils/base/wicket.c: Likewise.
    * libmailutils/mailbox/folder.c: Likewise.
    * libmailutils/mailbox/mailbox.c: Likewise.
    * libmailutils/mailer/mailer.c: Likewise.
    * libmailutils/tests/url-parse.c: Likewise.
    * libmailutils/tests/wicket.c: Likewise.
    * libproto/mailer/smtp_auth.c: Likewise.
    * maidag/deliver.c: Likewise.
    * mu/wicket.c: Likewise.
    
    * libmailutils/mime/mimehdr.c (mu_mimehdr_decode_param): Use
    mu_str_url_decode, instead of mu_url_decode.
    * libmailutils/stream/tcp.c (_tcp_instance)<port>: Change type
    to unsigned short. All uses updated.
    (mu_tcp_stream_create_with_source_ip)
    (mu_tcp_stream_create_with_source_host)
    (mu_tcp_stream_create): Port is unsigned.
    * include/mailutils/stream.h (mu_tcp_stream_create_with_source_ip)
    (mu_tcp_stream_create_with_source_host)
    (mu_tcp_stream_create): Port is unsigned.
    * include/mailutils/cpp/url.h (get_port): Return unsigned.
    * libmu_cpp/url.cc (get_port): Return unsigned.
    (parse): Empty function. Schedule for removal.
    * python/libmu_py/url.c (api_url_parse): Empty function.
    Schedule for removal.
    (api_url_get_port): Port is unsigned.
    
    * libmailutils/base/wicket.c (mu_wicket_file_match_url)
    (mu_wicket_file_match_url): New parameter: parse_flags.
    * mu/wicket.c (wicket_match): Use parse_flags to control
    whether or not to show the plaintext password.
    
    * doc/texinfo/url.texi: Update.

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

Summary of changes:
 configure.ac                                       |    1 +
 doc/texinfo/url.texi                               |    2 +-
 imap4d/imap4d.c                                    |    9 +-
 include/mailutils/auth.h                           |    4 +-
 include/mailutils/cpp/url.h                        |    2 +-
 include/mailutils/stream.h                         |    6 +-
 include/mailutils/sys/url.h                        |    6 +-
 include/mailutils/url.h                            |   52 +-
 include/mailutils/util.h                           |    3 +-
 libmailutils/Makefile.am                           |    5 +-
 libmailutils/base/Makefile.am                      |    1 -
 libmailutils/base/registrar.c                      |    4 +-
 libmailutils/base/url.c                            | 1254 --------------------
 libmailutils/base/wicket.c                         |   20 +-
 libmailutils/mailbox/folder.c                      |    4 +-
 libmailutils/mailbox/mailbox.c                     |    8 +-
 libmailutils/mailer/mailer.c                       |    4 +-
 libmailutils/mime/mimehdr.c                        |    8 +-
 libmailutils/stream/tcp.c                          |   11 +-
 libmailutils/string/Makefile.am                    |    3 +-
 libmailutils/string/{cpystr.c => xdecode.c}        |   57 +-
 libmailutils/tests/url-parse.c                     |    9 +-
 libmailutils/tests/wicket.c                        |    7 +-
 libmailutils/{diag => url}/Makefile.am             |   47 +-
 libmailutils/url/accessor.h                        |  143 +++
 libmailutils/url/copy.c                            |  145 +++
 libmailutils/url/create.c                          |  525 ++++++++
 libmailutils/url/decode.c                          |  118 ++
 libproto/nntp/url.c => libmailutils/url/destroy.c  |   62 +-
 libproto/nntp/url.c => libmailutils/url/dup.c      |   44 +-
 libmailutils/url/expand.c                          |  216 ++++
 libmailutils/{base/freeitem.c => url/flag.c}       |   22 +-
 libmailutils/url/get-auth.c                        |    3 +
 libmailutils/url/get-host.c                        |    2 +
 libmailutils/url/get-param.c                       |  131 ++
 libmailutils/url/get-path.c                        |    2 +
 libmailutils/url/get-portstr.c                     |    2 +
 libproto/pop/url.c => libmailutils/url/get-query.c |   60 +-
 libmailutils/url/get-scheme.c                      |    2 +
 .../nntp/url.c => libmailutils/url/get-secret.c    |   32 +-
 libmailutils/url/get-user.c                        |    2 +
 libmailutils/url/match.c                           |  102 ++
 libproto/nntp/url.c => libmailutils/url/port.c     |   35 +-
 libproto/nntp/url.c => libmailutils/url/scheme.c   |   37 +-
 libmailutils/{mailbox/hdrfirst.c => url/uplevel.c} |   57 +-
 libmailutils/{base/freeitem.c => url/urlstr.c}     |   11 +-
 libmu_cpp/url.cc                                   |   10 +-
 libproto/imap/folder.c                             |    6 +-
 libproto/maildir/folder.c                          |    2 +-
 libproto/mailer/prog.c                             |    2 +-
 libproto/mailer/remote.c                           |    6 +-
 libproto/mailer/sendmail.c                         |    6 +-
 libproto/mailer/smtp.c                             |    4 +-
 libproto/mailer/smtp_auth.c                        |    9 -
 libproto/mbox/folder.c                             |    2 +-
 libproto/mh/folder.c                               |    2 +-
 libproto/nntp/folder.c                             |    4 +-
 libproto/pop/folder.c                              |    4 +-
 libproto/pop/mbox.c                                |    2 +-
 maidag/deliver.c                                   |   15 -
 mu/wicket.c                                        |   34 +-
 python/libmu_py/url.c                              |    8 +-
 62 files changed, 1801 insertions(+), 1595 deletions(-)
 delete mode 100644 libmailutils/base/url.c
 copy libmailutils/string/{cpystr.c => xdecode.c} (57%)
 copy libmailutils/{diag => url}/Makefile.am (72%)
 create mode 100644 libmailutils/url/accessor.h
 create mode 100644 libmailutils/url/copy.c
 create mode 100644 libmailutils/url/create.c
 create mode 100644 libmailutils/url/decode.c
 copy libproto/nntp/url.c => libmailutils/url/destroy.c (51%)
 copy libproto/nntp/url.c => libmailutils/url/dup.c (61%)
 create mode 100644 libmailutils/url/expand.c
 copy libmailutils/{base/freeitem.c => url/flag.c} (75%)
 create mode 100644 libmailutils/url/get-auth.c
 create mode 100644 libmailutils/url/get-host.c
 create mode 100644 libmailutils/url/get-param.c
 create mode 100644 libmailutils/url/get-path.c
 create mode 100644 libmailutils/url/get-portstr.c
 copy libproto/pop/url.c => libmailutils/url/get-query.c (52%)
 create mode 100644 libmailutils/url/get-scheme.c
 copy libproto/nntp/url.c => libmailutils/url/get-secret.c (66%)
 create mode 100644 libmailutils/url/get-user.c
 create mode 100644 libmailutils/url/match.c
 copy libproto/nntp/url.c => libmailutils/url/port.c (62%)
 copy libproto/nntp/url.c => libmailutils/url/scheme.c (60%)
 copy libmailutils/{mailbox/hdrfirst.c => url/uplevel.c} (51%)
 copy libmailutils/{base/freeitem.c => url/urlstr.c} (82%)

diff --git a/configure.ac b/configure.ac
index 27ff3f6..690171b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1387,6 +1387,7 @@ AC_CONFIG_FILES([
  libmailutils/server/Makefile
  libmailutils/string/Makefile
  libmailutils/stream/Makefile
+ libmailutils/url/Makefile
  libmailutils/Makefile
  messages/Makefile
  mh/Makefile
diff --git a/doc/texinfo/url.texi b/doc/texinfo/url.texi
index 267a89f..1399731 100644
--- a/doc/texinfo/url.texi
+++ b/doc/texinfo/url.texi
@@ -186,7 +186,7 @@ for any particular scheme.
 @deftypefun  int mu_url_get_host (const mu_url_t, char *, size_t, size_t *)
 @end deftypefun
 
address@hidden  int mu_url_get_port (const mu_url_t, long *)
address@hidden  int mu_url_get_port (const mu_url_t, unsigned *)
 @end deftypefun
 
 @deftypefun  int mu_url_get_path (const mu_url_t, char *, size_t, size_t *)
diff --git a/imap4d/imap4d.c b/imap4d/imap4d.c
index c80af2b..cbadb83 100644
--- a/imap4d/imap4d.c
+++ b/imap4d/imap4d.c
@@ -172,7 +172,7 @@ parse_preauth_scheme (mu_debug_t debug, const char *scheme, 
mu_url_t url)
   else if (strcmp (scheme, "ident") == 0)
     {
       struct servent *sp;
-      long n;
+      unsigned n;
       if (url && mu_url_get_port (url, &n) == 0)
        ident_port = (short) n;
       else if ((sp = getservbyname ("auth", "tcp")))
@@ -219,13 +219,6 @@ cb_preauth (mu_debug_t debug, void *data, 
mu_config_value_t *val)
          mu_diag_funcall (MU_DIAG_ERROR, "mu_url_create", val->v.string, rc);
          return 1;
        }
-      rc = mu_url_parse (url);
-      if (rc)
-       {
-         mu_cfg_format_error (debug, MU_DEBUG_ERROR,
-                              "%s: %s", val->v.string, mu_strerror (rc));
-         return 1;
-       }
 
       rc = mu_url_aget_scheme (url, &scheme);
       if (rc)
diff --git a/include/mailutils/auth.h b/include/mailutils/auth.h
index b3b7be3..3433b61 100644
--- a/include/mailutils/auth.h
+++ b/include/mailutils/auth.h
@@ -78,8 +78,10 @@ int mu_file_wicket_create (mu_wicket_t *pwicket, const char 
*filename);
 
 struct mu_debug_locus;  
 int mu_wicket_stream_match_url (mu_stream_t stream, struct mu_debug_locus *loc,
-                               mu_url_t url, mu_url_t *pticket_url);
+                               mu_url_t url, int parse_flags,
+                               mu_url_t *pticket_url);
 int mu_wicket_file_match_url (const char *name, mu_url_t url,
+                             int parse_flags,
                              mu_url_t *pticket_url);
 
   
diff --git a/include/mailutils/cpp/url.h b/include/mailutils/cpp/url.h
index dd7d065..b3b7138 100644
--- a/include/mailutils/cpp/url.h
+++ b/include/mailutils/cpp/url.h
@@ -42,7 +42,7 @@ class Url
   ~Url ();
 
   void parse ();
-  long get_port ();
+  unsigned get_port ();
   std::string get_scheme ();
   std::string get_user ();
   std::string get_auth ();
diff --git a/include/mailutils/stream.h b/include/mailutils/stream.h
index d951f34..bb14186 100644
--- a/include/mailutils/stream.h
+++ b/include/mailutils/stream.h
@@ -176,14 +176,14 @@ int mu_streamref_create_abridged (mu_stream_t *pref, 
mu_stream_t str,
 int mu_streamref_create (mu_stream_t *pref, mu_stream_t str);
 
 int mu_tcp_stream_create_with_source_ip (mu_stream_t *stream,
-                                        const char *host, int port,
+                                        const char *host, unsigned port,
                                         unsigned long source_ip,
                                         int flags);
 int mu_tcp_stream_create_with_source_host (mu_stream_t *stream,
-                                          const char *host, int port,
+                                          const char *host, unsigned port,
                                           const char *source_host,
                                           int flags);
-int mu_tcp_stream_create (mu_stream_t *stream, const char *host, int port,
+int mu_tcp_stream_create (mu_stream_t *stream, const char *host, unsigned port,
                          int flags);
 
 /* Transcript output levels */
diff --git a/include/mailutils/sys/url.h b/include/mailutils/sys/url.h
index f782bb0..8e80197 100644
--- a/include/mailutils/sys/url.h
+++ b/include/mailutils/sys/url.h
@@ -35,7 +35,8 @@ struct _mu_url
   mu_secret_t secret;
   char  *auth;
   char  *host;
-  long  port;
+  short port;
+  char  *portstr;
   char  *path;
   char  **fvpairs;
   int   fvcount;
@@ -53,7 +54,8 @@ struct _mu_url
   int   (*_get_secret) (const mu_url_t, mu_secret_t *);
   int   (*_get_auth)   (const mu_url_t, char *, size_t, size_t *);
   int   (*_get_host)   (const mu_url_t, char *, size_t, size_t *);
-  int   (*_get_port)   (const mu_url_t, long *);
+  int   (*_get_port)   (const mu_url_t, unsigned *);
+  int   (*_get_portstr)(const mu_url_t, char *, size_t, size_t *);
   int   (*_get_path)   (const mu_url_t, char *, size_t, size_t *);
   int   (*_get_query)  (const mu_url_t, char *, size_t, size_t *);
   int   (*_uplevel)    (const mu_url_t, mu_url_t *);
diff --git a/include/mailutils/url.h b/include/mailutils/url.h
index b8745bb..dc4801d 100644
--- a/include/mailutils/url.h
+++ b/include/mailutils/url.h
@@ -25,14 +25,15 @@
 extern "C" {
 #endif
 
-#define MU_URL_USER   0x0001 /* Has a user part */
-#define MU_URL_SECRET 0x0002 /* Has a secret (password) part */
-#define MU_URL_AUTH   0x0004 /* Has auth part */
-#define MU_URL_HOST   0x0008 /* Has host part */
-#define MU_URL_PORT   0x0010 /* Has port part */  
-#define MU_URL_PATH   0x0020 /* Has path */
-#define MU_URL_PARAM  0x0040 /* Has parameters */
-#define MU_URL_QUERY  0x0080 /* Has query */
+#define MU_URL_SCHEME 0x0001
+#define MU_URL_USER   0x0002 /* Has a user part */
+#define MU_URL_SECRET 0x0004 /* Has a secret (password) part */
+#define MU_URL_AUTH   0x0008 /* Has auth part */
+#define MU_URL_HOST   0x0010 /* Has host part */
+#define MU_URL_PORT   0x0020 /* Has port part */  
+#define MU_URL_PATH   0x0040 /* Has path */
+#define MU_URL_PARAM  0x0080 /* Has parameters */
+#define MU_URL_QUERY  0x0100 /* Has query */
   
 #define MU_URL_CRED (MU_URL_USER | MU_URL_SECRET | MU_URL_AUTH)  
   /* Has some of authentication credentials */
@@ -45,6 +46,28 @@ extern "C" {
    MU_URL_PARAM | \
    MU_URL_QUERY)
 
+  /* Parser flags */
+#define MU_URL_PARSE_HEXCODE      0x0001  /* Decode % notations (RFC 1738,
+                                            section 2.2) */
+#define MU_URL_PARSE_HIDEPASS     0x0002  /* Hide password in the URL */
+#define MU_URL_PARSE_PORTSRV      0x0004  /* Use getservbyname to determine
+                                            port number */
+#define MU_URL_PARSE_PORTWC       0x0008  /* Allow wildcard (*) as a port
+                                           number (for tickets) */
+#define MU_URL_PARSE_PIPE         0x0010  /* Translate "| ..." to
+                                           "prog://..." */
+#define MU_URL_PARSE_SLASH        0x0020  /* Translate "/..." to
+                                            "file:///..." */
+
+#define MU_URL_PARSE_DEFAULT \
+  (MU_URL_PARSE_HEXCODE|MU_URL_PARSE_HIDEPASS|MU_URL_PARSE_PORTSRV|\
+   MU_URL_PARSE_PIPE|MU_URL_PARSE_SLASH)
+#define MU_URL_PARSE_ALL (MU_URL_PARSE_DEFAULT|MU_URL_PARSE_PORTWC)  
+  
+int mu_url_create_hint (mu_url_t *purl, const char *str, int flags,
+                       mu_url_t hint);
+int mu_url_copy_hints (mu_url_t url, mu_url_t hint);
+  
 int  mu_url_create    (mu_url_t *, const char *name);
 int  mu_url_dup       (mu_url_t old_url, mu_url_t *new_url);
 int  mu_url_uplevel   (mu_url_t url, mu_url_t *upurl);
@@ -53,7 +76,6 @@ int mu_url_get_flags (mu_url_t, int *);
 int mu_url_has_flag (mu_url_t, int);  
   
 void mu_url_destroy   (mu_url_t *);
-int  mu_url_parse     (mu_url_t);
 
 int mu_url_sget_scheme  (const mu_url_t, const char **);
 int mu_url_aget_scheme  (const mu_url_t, char **);  
@@ -80,7 +102,11 @@ int mu_url_get_path  (const mu_url_t, char *, size_t, 
size_t *);
 int mu_url_sget_query (const mu_url_t url, size_t *qc, char ***qv);
 int mu_url_aget_query (const mu_url_t url, size_t *qc, char ***qv);
 
-int mu_url_get_port    (const mu_url_t, long *);
+int mu_url_sget_portstr  (const mu_url_t, const char **);
+int mu_url_aget_portstr  (const mu_url_t, char **);  
+int mu_url_get_portstr   (const mu_url_t, char *, size_t, size_t *);
+  
+int mu_url_get_port    (const mu_url_t, unsigned *);
 
 int mu_url_sget_fvpairs (const mu_url_t url, size_t *fvc, char ***fvp);
 int mu_url_aget_fvpairs (const mu_url_t url, size_t *pfvc, char ***pfvp);
@@ -101,11 +127,9 @@ int mu_url_is_same_path   (mu_url_t, mu_url_t);
 int mu_url_is_same_host   (mu_url_t, mu_url_t);
 int mu_url_is_same_port   (mu_url_t, mu_url_t);
 
-char *mu_url_decode_len (const char *s, size_t len);  
-char *mu_url_decode     (const char *s);
-
 int mu_url_matches_ticket   (mu_url_t ticket, mu_url_t url, int *wcn);  
-int mu_url_init (mu_url_t url, int port, const char *scheme);
+
+int mu_url_decode (mu_url_t url);
   
 #ifdef __cplusplus
 }
diff --git a/include/mailutils/util.h b/include/mailutils/util.h
index 3af373c..9d3fff4 100644
--- a/include/mailutils/util.h
+++ b/include/mailutils/util.h
@@ -42,7 +42,8 @@ int mu_unre_set_regex (const char *str, int caseflag, char 
**errp);
 int mu_unre_subject  (const char *subject, const char **new_subject);
 int mu_is_proto (const char *p);
 int mu_mh_delim (const char *str);
-
+void mu_str_url_decode_inline (char *str);
+int mu_str_url_decode (char **ptr, const char *s);
 
   /* ----------------------- */
   /* Date & time functions   */
diff --git a/libmailutils/Makefile.am b/libmailutils/Makefile.am
index f13085f..454962b 100644
--- a/libmailutils/Makefile.am
+++ b/libmailutils/Makefile.am
@@ -17,7 +17,7 @@
 # <http://www.gnu.org/licenses/>.
 
 SUBDIRS = auth base address cfg diag filter mailbox mailer mime\
- server string stream . tests 
+ server string stream url . tests 
 
 lib_LTLIBRARIES = libmailutils.la
 
@@ -36,7 +36,8 @@ libmailutils_la_LIBADD = \
  mime/libmime.la\
  server/libserver.la\
  string/libstring.la\
- stream/libstream.la
+ stream/libstream.la\
+ url/liburl.la
 
 libmailutils_la_LDFLAGS = -version-info @VI_CURRENT@:@VI_REVISION@:@VI_AGE@
 
diff --git a/libmailutils/base/Makefile.am b/libmailutils/base/Makefile.am
index 196344b..c51c947 100644
--- a/libmailutils/base/Makefile.am
+++ b/libmailutils/base/Makefile.am
@@ -61,7 +61,6 @@ libbase_la_SOURCES = \
  tempfile.c\
  ticket.c\
  tilde.c\
- url.c\
  usremail.c\
  vartab.c\
  version.c\
diff --git a/libmailutils/base/registrar.c b/libmailutils/base/registrar.c
index da43bff..fc31b90 100644
--- a/libmailutils/base/registrar.c
+++ b/libmailutils/base/registrar.c
@@ -220,9 +220,7 @@ mu_registrar_lookup (const char *name, int flags,
   rc = mu_url_create (&url, name);
   if (rc)
     return rc;
-  rc = mu_url_parse (url);
-  if (rc == 0)
-    rc = mu_registrar_lookup_url (url, flags, precord, pflags);
+  rc = mu_registrar_lookup_url (url, flags, precord, pflags);
   mu_url_destroy (&url);
   return rc;
 }
diff --git a/libmailutils/base/url.c b/libmailutils/base/url.c
deleted file mode 100644
index 96345f0..0000000
--- a/libmailutils/base/url.c
+++ /dev/null
@@ -1,1254 +0,0 @@
-/* GNU Mailutils -- a suite of utilities for electronic mail
-   Copyright (C) 1999, 2000, 2001, 2007, 2008, 2009, 2010 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.
-
-   This library 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.
-
-   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/>. */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <ctype.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-#ifdef HAVE_STRINGS_H
-# include <strings.h>
-#endif
-
-#include <mailutils/util.h>
-#include <mailutils/errno.h>
-#include <mailutils/argcv.h>
-#include <mailutils/secret.h>
-#include <mailutils/cctype.h>
-#include <mailutils/cstr.h>
-#include <mailutils/sys/url.h>
-
-#define AC2(a,b) a ## b
-#define AC4(a,b,c,d) a ## b ## c ## d
-
-static int url_parse0 (mu_url_t, char *, size_t *poff, int *decode);
-
-static int
-parse_query (const char *query,
-            char *delim,
-            int *pargc, char ***pargv, const char **pend)
-{
-  size_t count, i;
-  char **v;
-  const char *p;
-
-  for (p = query, count = 0; ; count++)
-    {
-      size_t len = strcspn (p, delim);
-      p += len;
-      if (!*p || *p == delim[1])
-       break;
-      p++;
-    }
-
-  if (pend)
-    *pend = p;
-  if (p == query)
-    return 0;
-  count++;
-
-  v = calloc (count + 1, sizeof (v[0]));
-  for (i = 0, p = query; i < count; i++)
-    {
-      size_t len = strcspn (p, delim);
-      v[i] = mu_url_decode_len (p, len);
-      if (v[i] == NULL)
-       {
-         mu_argcv_free (i, v);
-         return 1;
-       }
-      p += len + 1;
-    }
-  v[i] = NULL;
-
-  *pargc = count;
-  *pargv = v;
-  return 0;
-}
-
-int
-mu_url_create (mu_url_t *purl, const char *name)
-{
-  mu_url_t url = calloc (1, sizeof (*url));
-  if (url == NULL)
-    return ENOMEM;
-
-  url->name = strdup (name);
-  if (url->name == NULL)
-    {
-      free (url);
-      return ENOMEM;
-    }
-  *purl = url;
-  return 0;
-}
-
-static char **
-argcv_copy (size_t argc, char **argv)
-{
-  size_t i;
-  char **nv = calloc (argc + 1, sizeof (nv[0]));
-  if (!nv)
-    return NULL;
-  for (i = 0; i < argc; i++)
-    if ((nv[i] = strdup (argv[i])) == NULL)
-      {
-       mu_argcv_free (i, nv);
-       free (nv);
-       return NULL;
-      }
-  return nv;
-}
-
-static int
-mu_url_copy0 (mu_url_t old_url, mu_url_t new_url)
-{
-  const char *str;
-  size_t argc;
-  char **argv;
-  int rc;
-  mu_secret_t sec;
-
-#define URLCOPY(what)                                          \
-  do                                                           \
-    {                                                          \
-      rc = AC2(mu_url_sget_,what) (old_url, &str);             \
-      if (rc == 0)                                             \
-       {                                                       \
-         if ((new_url->what = strdup (str)) == NULL)           \
-           return ENOMEM;                                      \
-       }                                                       \
-      else if (rc != MU_ERR_NOENT)                             \
-       return rc;                                              \
-    }                                                          \
-  while (0);
-
-  URLCOPY (scheme);
-  URLCOPY (user);
-
-  rc = mu_url_get_secret (old_url, &sec);
-  if (rc == MU_ERR_NOENT)
-    new_url->secret = NULL;
-  else if (rc)
-    return rc;
-  else
-    {
-      rc = mu_secret_dup (sec, &new_url->secret);
-      if (rc)
-       return rc;
-    }
-  
-  URLCOPY (auth);
-  URLCOPY (host);
-  new_url->port = old_url->port;
-  URLCOPY (path);
-
-  rc = mu_url_sget_fvpairs (old_url, &argc, &argv);
-  if (rc == 0 && argc)
-    {
-      if ((new_url->fvpairs = argcv_copy (argc, argv)) == NULL)
-       return ENOMEM;
-      new_url->fvcount = argc;
-    }
-
-  rc = mu_url_sget_query (old_url, &argc, &argv);
-  if (rc == 0 && argc)
-    {
-      if ((new_url->qargv = argcv_copy (argc, argv)) == NULL)
-       return ENOMEM;
-      new_url->qargc = argc;
-    }
-  new_url->flags = old_url->flags;
-  return 0;
-#undef URLCOPY
-}
-
-int
-mu_url_dup (mu_url_t old_url, mu_url_t *new_url)
-{
-  mu_url_t url;
-  int rc = mu_url_create (&url, mu_url_to_string (old_url));
-
-  if (rc)
-    return rc;
-
-  rc = mu_url_copy0 (old_url, url);
-  if (rc == 0)
-    *new_url = url;
-  else
-    mu_url_destroy (&url);
-  return rc;
-}
-
-int
-mu_url_uplevel (mu_url_t url, mu_url_t *upurl)
-{
-  int rc;
-  char *p;
-  mu_url_t new_url;
-
-  if (url->_uplevel)
-    return url->_uplevel (url, upurl);
-
-  if (!url->path)
-    return MU_ERR_NOENT;
-  p = strrchr (url->path, '/');
-
-  rc = mu_url_dup (url, &new_url);
-  if (rc == 0)
-    {
-      if (!p || p == url->path)
-       {
-         free (new_url->path);
-         new_url->path = NULL;
-       }
-      else
-       {
-         size_t size = p - url->path;
-         new_url->path = realloc (new_url->path, size + 1);
-         if (!new_url->path)
-           {
-             mu_url_destroy (&new_url);
-             return ENOMEM;
-           }
-         memcpy (new_url->path, url->path, size);
-         new_url->path[size] = 0;
-       }
-      *upurl = new_url;
-    }
-  return rc;
-}
-
-void
-mu_url_destroy (mu_url_t * purl)
-{
-  if (purl && *purl)
-    {
-      mu_url_t url = (*purl);
-
-      if (url->_destroy)
-       url->_destroy (url);
-
-      if (url->name)
-       free (url->name);
-
-      if (url->scheme)
-       free (url->scheme);
-
-      if (url->user)
-       free (url->user);
-
-      mu_secret_destroy (&url->secret);
-
-      if (url->auth)
-       free (url->auth);
-
-      if (url->host)
-       free (url->host);
-
-      if (url->path)
-       free (url->path);
-
-      if (url->fvcount)
-       mu_argcv_free (url->fvcount, url->fvpairs);
-
-      mu_argcv_free (url->qargc, url->qargv);
-
-      free (url);
-
-      *purl = NULL;
-    }
-}
-
-int
-mu_url_parse (mu_url_t url)
-{
-  int err = 0;
-  char *n = NULL;
-  struct _mu_url u;
-  size_t pstart;
-  mu_secret_t newsec;
-  int want_decode;
-  
-  if (!url || !url->name)
-    return EINVAL;
-
-  memset (&u, 0, sizeof u);
-  /* can't have been parsed already */
-  if (url->flags)
-    return EINVAL;
-
-  n = strdup (url->name);
-
-  if (!n)
-    return ENOMEM;
-
-  err = url_parse0 (&u, n, &pstart, &want_decode);
-
-  if (!err)
-    {
-      if (u.secret)
-       {
-         /* Obfuscate the password */
-#define PASS_REPL "***"
-#define PASS_REPL_LEN (sizeof (PASS_REPL) - 1)
-         size_t plen = mu_secret_length (u.secret);
-         size_t nlen = strlen (url->name);
-         size_t len = nlen - plen + PASS_REPL_LEN + 1;
-         char *newname;
-
-         memset (url->name + pstart, 0, plen);
-         if (len > nlen + 1)
-           {
-             newname = realloc (url->name, len);
-             if (!newname)
-               goto CLEANUP;
-             url->name = newname;
-           }
-         else
-           newname = url->name;
-         memmove (newname + pstart + PASS_REPL_LEN, newname + pstart + plen,
-                  nlen - (pstart + plen) + 1);
-         memcpy (newname + pstart, PASS_REPL, PASS_REPL_LEN);
-       }
-
-      /* Dup the strings we found. We wouldn't have to do this
-        if we did a single alloc of the source url name, and
-        kept it around. It's also a good time to do hex decoding,
-        though.
-       */
-
-#define UALLOC(X,f)                                                    \
-      if (u.X && u.X[0])                                               \
-       {                                                               \
-         url->X = want_decode ? mu_url_decode (u.X) : strdup (u.X);    \
-         if (!url->X)                                                  \
-           {                                                           \
-             err = ENOMEM;                                             \
-             goto CLEANUP;                                             \
-           }                                                           \
-         url->flags |= f;                                              \
-       }                                                               \
-      else                                                             \
-       {                                                               \
-         /* Set zero-length strings to NULL. */                        \
-         url->X = NULL;                                                \
-       }
-
-      UALLOC (scheme, 0);
-      UALLOC (user, MU_URL_USER);
-
-      if (u.secret)
-       {
-         char *pass = mu_url_decode (mu_secret_password (u.secret));
-         err = mu_secret_create (&newsec, pass, strlen (pass));
-         memset (pass, 0, strlen (pass));
-         mu_secret_destroy (&u.secret);
-         if (err)
-           goto CLEANUP;
-
-         url->secret = newsec;
-         url->flags |= MU_URL_SECRET;
-       }
-
-      UALLOC (auth, MU_URL_AUTH);
-      UALLOC (host, MU_URL_HOST);
-      UALLOC (path, MU_URL_PATH);
-
-#undef UALLOC
-      url->fvcount = u.fvcount;
-      url->fvpairs = u.fvpairs;
-      if (u.fvcount)
-       url->flags |= MU_URL_PARAM;
-         
-      url->qargc = u.qargc;
-      url->qargv = u.qargv;
-      if (u.qargc)
-       url->flags |= MU_URL_QUERY;
-
-      url->port = u.port;
-      if (u.port)
-       url->flags |= MU_URL_PORT;
-    }
-
-CLEANUP:
-  memset (n, 0, strlen (n));
-  free (n);
-
-  if (err)
-    {
-#define UFREE(X) if (X) { free(X); X = 0; }
-
-      UFREE (url->scheme);
-      UFREE (url->user);
-      mu_secret_destroy (&u.secret);
-      UFREE (url->auth);
-      UFREE (url->host);
-      UFREE (url->path);
-      mu_argcv_free (url->fvcount, url->fvpairs);
-      mu_argcv_free (url->qargc, url->qargv);
-#undef UFREE
-    }
-
-  return err;
-}
-
-/*
-
-Syntax, condensed from RFC 1738, and extended with the ;auth=
-of RFC 2384 (for POP) and RFC 2192 (for IMAP):
-
-url =
-    scheme ":" [ "//"
-
-    [ user [ ( ":" password ) | ( ";auth=" auth ) ] "@" ]
-
-    host [ ":" port ]
-
-    [ ( "/" urlpath ) | ( "?" query ) ] ]
-
-All hell will break loose in this parser if the user/pass/auth
-portion is missing, and the urlpath has any @ or : characters
-in it. A imap mailbox, say, named after the email address of
-the person the mail is from:
-
-  imap://imap.uniserve.com/address@hidden
-
-Is this required to be % quoted, though? I hope so!
-
-*/
-
-static int
-url_parse0 (mu_url_t u, char *name, size_t *poff, int *decode)
-{
-  char *start = name;
-  char *p;                     /* pointer into name */
-
-  /* reject the obvious */
-  if (name == NULL)
-    return EINVAL;
-
-  if (name[0] == '/')
-    {
-      u->scheme = "file";
-      *decode = 0;
-    }
-  else if (name[0] == '|')
-    {
-      int rc;
-      u->scheme = "prog";
-      *decode = 0;
-      rc = mu_argcv_get (name + 1, NULL, NULL, &u->qargc, &u->qargv);
-      if (rc == 0)
-       {
-         u->path = strdup (u->qargv[0]);
-         if (!u->path)
-           rc = ENOMEM;
-       }
-      return rc;
-    }
-  else
-    {
-      *decode = 1;
-      /* Parse out the SCHEME. */
-      p = strchr (name, ':');
-      if (p == NULL)
-       return MU_ERR_PARSE;
-
-      *p++ = 0;
-
-      u->scheme = name;
-
-      /* RFC 1738, section 2.1, lower the scheme case */
-      for (; name < p; name++)
-       *name = mu_tolower (*name);
-
-      name = p;
-    }
-
-  /* Check for nothing following the scheme. */
-  if (!*name)
-    return 0;
-
-  if (strncmp (name, "//", 2) == 0)
-    {
-      name += 2;
-
-      if (name[0] == '/')
-       {
-         u->path = name;
-         p = u->path + strcspn (u->path, ";?");
-       }
-      else
-       {
-         /* Split into LHS and RHS of the '@', and then parse each side. */
-         u->host = strchr (name, '@');
-         if (u->host == NULL)
-           u->host = name;
-         else
-           {
-             char *pass = NULL;
-
-             /* Parse the LHS into an identification/authentication pair. */
-             *u->host++ = 0;
-
-             u->user = name;
-
-             /* Try to split the user into a:
-                <user>:<password>
-                or
-                <user>:<password>;AUTH=<auth>
-             */
-
-             for (; *name; name++)
-               {
-                 if (*name == ':')
-                   {
-                     *name++ = 0;
-                     pass = name;
-                     *poff = pass - start;
-                   }
-                 else if (*name == ';')
-                   {
-                     /* Make sure it's the auth token. */
-                     if (mu_c_strncasecmp (name + 1, "auth=", 5) == 0)
-                       {
-                         *name++ = 0;
-                         name += 5;
-                         u->auth = name;
-                         break;
-                       }
-                   }
-               }
-
-             if (pass)
-               {
-                 if (mu_secret_create (&u->secret, pass, strlen (pass)))
-                   return ENOMEM;
-                 else
-                   /* Obfuscate password */
-                   memset (pass, 0, strlen (pass));
-               }
-           }
-
-         /* Parse the host and port from the RHS. */
-         p = strchr (u->host, ':');
-         if (p)
-           {
-             *p++ = 0;
-             u->port = strtol (p, &p, 10);
-
-             /* Check for garbage after the port: we should be on the start
-                of a path, a query, or at the end of the string. */
-             if (*p && strcspn (p, "/?") != 0)
-               return MU_ERR_PARSE;
-           }
-         else
-           p = u->host + strcspn (u->host, ";/?");
-       }
-    }
-  else
-    {
-      u->path = name;
-      p = u->path + strcspn (u->path, ";?");
-    }
-
-  /* Either way, if we're not at a nul, we're at a path or query. */
-  if (u->path == NULL && *p == '/')
-    {
-      /* found a path */
-      *p++ = 0;
-      u->path = p;
-      p = u->path + strcspn (u->path, ";?");
-    }
-
-  if (*p == ';')
-    {
-      *p++ = 0;
-      if (parse_query (p, ";?", &u->fvcount, &u->fvpairs, (const char **)&p))
-       return ENOMEM;
-    }
-
-  if (*p == '?')
-    {
-      /* found a query */
-      *p++ = 0;
-      if (parse_query (p, "&", &u->qargc, &u->qargv, NULL))
-       return ENOMEM;
-    }
-
-  return 0;
-}
-
-
-/* General accessors: */
-#define ACCESSOR(action,field) AC4(mu_url_,action,_,field)
-
-#define DECL_SGET(field)                                                 \
-int                                                                      \
-ACCESSOR(sget,field) (mu_url_t url, char const **sptr)                   \
-{                                                                        \
-  if (url == NULL)                                                       \
-    return EINVAL;                                                       \
-  if (!url->field)                                                       \
-    {                                                                    \
-      if (url->AC2(_get_,field))                                         \
-       {                                                                 \
-         size_t n;                                                       \
-         char *buf;                                                      \
-                                                                         \
-         int status = url->AC2(_get_,field) (url, NULL, 0, &n);          \
-         if (status)                                                     \
-           return status;                                                \
-                                                                         \
-         buf = malloc (n + 1);                                           \
-         if (!buf)                                                       \
-           return ENOMEM;                                                \
-                                                                         \
-         status = url->AC2(_get_,field) (url, buf, n + 1, NULL);         \
-         if (status)                                     \
-           return status;                                                \
-                                                                         \
-         if (buf[0])                                                     \
-           {                                                             \
-              url->field = mu_url_decode (buf);                          \
-              free (buf);                                                \
-           }                                                             \
-         else                                                            \
-           url->field = buf;                                             \
-         if (!url->field)                                                \
-           return ENOMEM;                                                \
-       }                                                                 \
-      else                                                               \
-       return MU_ERR_NOENT;                                              \
-    }                                                                    \
-  *sptr = url->field;                                                    \
-  return 0;                                                              \
-}
-
-#define DECL_GET(field)                                                        
  \
-int                                                                      \
-ACCESSOR(get,field) (mu_url_t url, char *buf, size_t len, size_t *n)      \
-{                                                                        \
-  size_t i;                                                              \
-  const char *str;                                                       \
-  int status = ACCESSOR(sget, field) (url, &str);                        \
-                                                                         \
-  if (status)                                                            \
-    return status;                                                       \
-                                                                         \
-  i = mu_cpystr (buf, str, len);                                         \
-  if (n)                                                                 \
-    *n = i;                                                              \
-  return 0;                                                              \
-}
-
-#define DECL_AGET(field)                                                 \
-int                                                                      \
-ACCESSOR(aget, field) (mu_url_t url, char **buf)                         \
-{                                                                        \
-  const char *str;                                                       \
-  int status = ACCESSOR(sget, field) (url, &str);                        \
-                                                                         \
-  if (status)                                                            \
-    return status;                                                       \
-                                                                         \
-  if (str)                                                               \
-    {                                                                    \
-      *buf = strdup (str);                                               \
-      if (!*buf)                                                         \
-       status = ENOMEM;                                                  \
-    }                                                                    \
-  else                                                                   \
-    *buf = NULL;                                                         \
-  return status;                                                         \
-}
-
-#define DECL_CMP(field)                                                        
  \
-int                                                                      \
-ACCESSOR(is_same,field) (mu_url_t url1, mu_url_t url2)                   \
-{                                                                        \
-  const char *s1, *s2;                                                   \
-  int status1, status2;                                                        
  \
-                                                                         \
-  status1 = ACCESSOR(sget, field) (url1, &s1);                           \
-  if (status1 && status1 != MU_ERR_NOENT)                                \
-    return 0;                                                            \
-  status2 = ACCESSOR(sget, field) (url2, &s2);                           \
-  if (status2 && status2 != MU_ERR_NOENT)                                \
-    return 0;                                                            \
-                                                                         \
-  if (status1 || status2)                                                \
-    return status1 == status2; /* Both fields are missing */             \
-  return mu_c_strcasecmp (s1, s2) == 0;                                        
  \
-}
-
-#define DECL_ACCESSORS(field)                                            \
-DECL_SGET(field)                                                         \
-DECL_GET(field)                                                                
  \
-DECL_AGET(field)                                                          \
-DECL_CMP(field)
-
-
-/* Declare particular accessors */
-DECL_ACCESSORS (scheme)
-DECL_ACCESSORS (user)
-DECL_ACCESSORS (auth)
-DECL_ACCESSORS (host)
-DECL_ACCESSORS (path)
-
-int
-mu_url_get_secret (const mu_url_t url, mu_secret_t *psecret)
-{
-  if (url->_get_secret)
-    return url->_get_secret (url, psecret);
-  if (url->secret == NULL)
-    return MU_ERR_NOENT;
-  mu_secret_ref (url->secret);
-  *psecret = url->secret;
-  return 0;
-}
-
-int
-mu_url_sget_query (const mu_url_t url, size_t *qc, char ***qv)
-{
-  if (url == NULL)
-    return EINVAL;
-  /* See FIXME below */
-  *qc = url->qargc;
-  *qv = url->qargv;
-  return 0;
-}
-
-int
-mu_url_aget_query (const mu_url_t url, size_t *qc, char ***qv)
-{
-  size_t qargc, i;
-  char **qargv;
-  char **qcopy;
-
-  int rc = mu_url_sget_fvpairs (url, &qargc, &qargv);
-  if (rc)
-    return rc;
-
-  qcopy = calloc (qargc + 1, sizeof (qcopy[0]));
-  if (!qcopy)
-    return errno;
-  for (i = 0; i < qargc; i++)
-    {
-      if (!(qcopy[i] = strdup (qargv[i])))
-       {
-         mu_argcv_free (i, qcopy);
-         return errno;
-       }
-    }
-  qcopy[i] = NULL;
-  *qc = qargc;
-  *qv = qcopy;
-  return 0;
-}
-
-/* field-value pairs accessors */
-int
-mu_url_sget_fvpairs (const mu_url_t url, size_t *fvc, char ***fvp)
-{
-  if (url == NULL)
-    return EINVAL;
-  /* FIXME: no _get_fvpairs method, but the method stuff needs to be rewritten
-     anyway */
-  *fvc = url->fvcount;
-  *fvp = url->fvpairs;
-  return 0;
-}
-
-int
-mu_url_sget_param (const mu_url_t url, const char *param, const char **val)
-{
-  size_t fvc;
-  char **fvp;
-  int status = mu_url_sget_fvpairs (url, &fvc, &fvp);
-
-  if (status)
-    return status;
-
-  if (fvc)
-    {
-      size_t i;
-      
-      for (i = 0; i < fvc; i++)
-       {
-         const char *p;
-         char *q;
-
-         for (p = param, q = fvp[i]; *p && *q && *p == *q; p++, q++)
-           ;
-         if (*p == 0)
-           {
-             if (*q == 0)
-               {
-                 if (val)
-                   *val = q;
-                 return 0;
-               }
-             else if (*q == '=')
-               {
-                 if (val)
-                   *val = q + 1;
-                 return 0;
-               }
-           }
-       }
-    }
- 
-  return MU_ERR_NOENT;
-}
-  
-int
-mu_url_aget_fvpairs (const mu_url_t url, size_t *pfvc, char ***pfvp)
-{
-  size_t fvc, i;
-  char **fvp;
-  char **fvcopy;
-
-  int rc = mu_url_sget_fvpairs (url, &fvc, &fvp);
-  if (rc)
-    return rc;
-
-  fvcopy = calloc (fvc + 1, sizeof (fvcopy[0]));
-  if (!fvcopy)
-    return errno;
-  for (i = 0; i < fvc; i++)
-    {
-      if (!(fvcopy[i] = strdup (fvp[i])))
-       {
-         mu_argcv_free (i, fvcopy);
-         return errno;
-       }
-    }
-  fvcopy[i] = NULL;
-  *pfvc = fvc;
-  *pfvp = fvcopy;
-  return 0;
-}
-
-int
-mu_url_aget_param (const mu_url_t url, const char *param, char **val)
-{
-  const char *s;
-  int status = mu_url_sget_param (url, param, &s);
-
-  if (status == 0)
-    {
-      *val = strdup (s);
-      if (!*val)
-       status = ENOMEM;
-    }
-  return status;
-}
-
-int
-mu_url_get_port (const mu_url_t url, long *pport)
-{
-  if (url == NULL)
-    return EINVAL;
-  if (url->_get_port)
-    return url->_get_port (url, pport);
-  *pport = url->port;
-  return 0;
-}
-
-const char *
-mu_url_to_string (const mu_url_t url)
-{
-  if (url == NULL || url->name == NULL)
-    return "";
-  return url->name;
-}
-
-int
-mu_url_set_scheme (mu_url_t url, const char *scheme)
-{
-  char *p;
-  if (!url || !scheme)
-    return EINVAL;
-  p = realloc (url->scheme, strlen (scheme) + 1);
-  if (!p)
-    return ENOMEM;
-  strcpy (url->scheme, scheme);
-  return 0;
-}
-
-int
-mu_url_is_scheme (mu_url_t url, const char *scheme)
-{
-  if (url && scheme && url->scheme 
-      && mu_c_strcasecmp (url->scheme, scheme) == 0)
-    return 1;
-
-  return 0;
-}
-
-int
-mu_url_is_same_port (mu_url_t url1, mu_url_t url2)
-{
-  long p1 = 0, p2 = 0;
-
-  mu_url_get_port (url1, &p1);
-  mu_url_get_port (url2, &p2);
-  return (p1 == p2);
-}
-
-/* From RFC 1738, section 2.2 */
-char *
-mu_url_decode_len (const char *s, size_t len)
-{
-  char *d;
-  const char *eos = s + len;
-  int i;
-
-  d = malloc (len + 1);
-  if (!d)
-    return NULL;
-
-  for (i = 0; s < eos; i++)
-    {
-      if (*s != '%')
-       {
-         d[i] = *s;
-         s++;
-       }
-      else
-       {
-         unsigned long ul = 0;
-
-         s++;
-
-         /* don't check return value, it's correctly coded, or it's not,
-            in which case we just skip the garbage, this is a decoder,
-            not an AI project */
-
-         mu_hexstr2ul (&ul, s, 2);
-
-         s += 2;
-
-         d[i] = (char) ul;
-       }
-    }
-
-  d[i] = 0;
-
-  return d;
-}
-
-char *
-mu_url_decode (const char *s)
-{
-  return mu_url_decode_len (s, strlen (s));
-}
-
-#define is_wildcard(s) ((s)[0] == '*' && s[1] == 0)
-
-#define WEIGHT_SCHEME 3
-#define WEIGHT_USER   4
-#define WEIGHT_HOST   2
-#define WEIGHT_PORT   1
-
-int
-mu_url_matches_ticket (mu_url_t ticket, mu_url_t url, int *pwc)
-{
-  int wcnt = 0;
-                                             
-  if (is_wildcard (ticket->scheme))
-    wcnt += WEIGHT_SCHEME;
-  else if (mu_c_strcasecmp (ticket->scheme, url->scheme))
-    return 0;
-
-  if (ticket->flags & MU_URL_HOST)
-    {
-      if (is_wildcard (ticket->host))
-       wcnt += WEIGHT_HOST;
-      else if (url->flags & MU_URL_HOST)
-       {
-         if (mu_c_strcasecmp (ticket->host, url->host))
-           /* FIXME: Compare IP addresses */
-           return 0;
-       }
-      else
-       return 0;
-    }
-  else
-    wcnt += WEIGHT_HOST;
-
-  if (ticket->flags & MU_URL_PORT)
-    {
-      /* FIXME: No way to put a wildcard in the ticket file */
-      if (url->port & MU_URL_PORT)
-       {
-         if (ticket->port != url->port)
-           return 0;
-         else
-           wcnt += WEIGHT_PORT;
-       }
-    }
-  else
-    wcnt += WEIGHT_PORT;
-  
-  if (ticket->flags & MU_URL_USER)
-    {
-      if (is_wildcard (ticket->user))
-       wcnt += WEIGHT_USER;
-      
-      /* If ticket has a user or pass, but url doesn't, that's OK, we were
-        looking for this info. But if url does have a user/pass, it
-        must match the ticket. */
-      else if (url->flags & MU_URL_USER)
-       {
-         if (strcmp (ticket->user, url->user))
-           return 0;
-       }
-    }
-  else
-    wcnt += WEIGHT_USER;
-  
-  /* Guess it matches. */
-  if (pwc)
-    *pwc = wcnt;
-  return 1;
-}
-
-int
-mu_url_init (mu_url_t url, int port, const char *scheme)
-{
-  int status = 0;
-
-  url->_destroy = NULL;
-
-  status = mu_url_parse (url);
-  if (status)
-    return status;
-
-  if (!mu_url_is_scheme (url, scheme))
-    return EINVAL;
-
-  if (url->port == 0)
-    url->port = port;
-
-  return status;
-}
-
-/* Default mailbox path generator */
-static char *
-_url_path_default (const char *spooldir, const char *user, int unused)
-{
-  return mu_make_file_name (spooldir, user);
-}
-
-/* Hashed indexing */
-static char *
-_url_path_hashed (const char *spooldir, const char *user, int param)
-{
-  int i;
-  int ulen = strlen (user);
-  char *mbox;
-  unsigned hash;
-
-  if (param > ulen)
-    param = ulen;
-  for (i = 0, hash = 0; i < param; i++)
-    hash += user[i];
-
-  mbox = malloc (ulen + strlen (spooldir) + 5);
-  sprintf (mbox, "%s/%02X/%s", spooldir, hash % 256, user);
-  return mbox;
-}
-
-static int transtab[] = {
-  'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
-  'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
-  'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
-  'y', 'z', 'a', 'b', 'c', 'd', 'e', 'f',
-  'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
-  'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
-  'w', 'x', 'y', 'z', 'a', 'b', 'c', 'd',
-  'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
-  'm', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
-  'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
-  'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
-  'x', 'y', 'z', 'b', 'c', 'd', 'e', 'f',
-  'g', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
-  'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
-  'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
-  'x', 'y', 'z', 'b', 'c', 'd', 'e', 'f',
-  'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
-  'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q',
-  'r', 's', 't', 'u', 'v', 'w', 'x', 'y',
-  'z', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
-  'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
-  'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
-  'x', 'y', 'z', 'a', 'b', 'c', 'd', 'e',
-  'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
-  'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
-  'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
-  'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
-  'y', 'z', 'b', 'c', 'd', 'e', 'f', 'g',
-  'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
-  'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
-  'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
-  'y', 'z', 'b', 'c', 'd', 'e', 'f', 'g'
-};
-
-/* Forward Indexing */
-static char *
-_url_path_index (const char *spooldir, const char *iuser, int index_depth)
-{
-  const unsigned char* user = (const unsigned char*) iuser;
-  int i, ulen = strlen (iuser);
-  char *mbox, *p;
-
-  if (ulen == 0)
-    return NULL;
-
-  mbox = malloc (ulen + strlen (spooldir) + 2*index_depth + 2);
-  strcpy (mbox, spooldir);
-  p = mbox + strlen (mbox);
-  for (i = 0; i < index_depth && i < ulen; i++)
-    {
-      *p++ = '/';
-      *p++ = transtab[ user[i] ];
-    }
-  for (; i < index_depth; i++)
-    {
-      *p++ = '/';
-      *p++ = transtab[ user[ulen-1] ];
-    }
-  *p++ = '/';
-  strcpy (p, iuser);
-  return mbox;
-}
-
-/* Reverse Indexing */
-static char *
-_url_path_rev_index (const char *spooldir, const char *iuser, int index_depth)
-{
-  const unsigned char* user = (const unsigned char*) iuser;
-  int i, ulen = strlen (iuser);
-  char *mbox, *p;
-
-  if (ulen == 0)
-    return NULL;
-
-  mbox = malloc (ulen + strlen (spooldir) + 2*index_depth + 1);
-  strcpy (mbox, spooldir);
-  p = mbox + strlen (mbox);
-  for (i = 0; i < index_depth && i < ulen; i++)
-    {
-      *p++ = '/';
-      *p++ = transtab[ user[ulen - i - 1] ];
-    }
-  for (; i < index_depth; i++)
-    {
-      *p++ = '/';
-      *p++ = transtab[ user[0] ];
-    }
-  *p++ = '/';
-  strcpy (p, iuser);
-  return mbox;
-}
-
-static int
-rmselector (const char *p, void *data MU_ARG_UNUSED)
-{
-  return strncmp (p, "type=", 5) == 0
-        || strncmp (p, "user=", 5) == 0
-        || strncmp (p, "param=", 6) == 0;
-}
-
-int
-mu_url_expand_path (mu_url_t url)
-{
-  size_t i;
-  char *user = NULL;
-  int param = 0;
-  char *p;
-  char *(*fun) (const char *, const char *, int) = _url_path_default;
-
-  if (url->fvcount == 0)
-    return 0;
-
-  for (i = 0; i < url->fvcount; i++)
-    {
-      p = url->fvpairs[i];
-      if (strncmp (p, "type=", 5) == 0)
-       {
-         char *type = p + 5;
-
-         if (strcmp (type, "hash") == 0)
-           fun = _url_path_hashed;
-         else if (strcmp (type, "index") == 0)
-           fun = _url_path_index;
-         else if (strcmp (type, "rev-index") == 0)
-           fun = _url_path_rev_index;
-         else
-           return MU_ERR_NOENT;
-       }
-      else if (strncmp (p, "user=", 5) == 0)
-       {
-         user = p + 5;
-       }
-      else if (strncmp (p, "param=", 6) == 0)
-       {
-         param = strtoul (p + 6, NULL, 0);
-       }
-    }
-
-  if (user)
-    {
-      char *p = fun (url->path, user, param);
-      if (p)
-       {
-         free (url->path);
-         url->path = p;
-       }
-      mu_argcv_remove (&url->fvcount, &url->fvpairs, rmselector, NULL);
-    }
-  else
-    return MU_ERR_NOENT;
-
-  return 0;
-}
-
-int
-mu_url_get_flags (mu_url_t url, int *pf)
-{
-  if (!url || !pf)
-    return EINVAL;
-  *pf = url->flags;
-  return 0;
-}
-
-int
-mu_url_has_flag (mu_url_t url, int flags)
-{
-  if (!url)
-    return 0;
-  return url->flags & flags;
-}
-
diff --git a/libmailutils/base/wicket.c b/libmailutils/base/wicket.c
index 3e808c0..afdb875 100644
--- a/libmailutils/base/wicket.c
+++ b/libmailutils/base/wicket.c
@@ -180,7 +180,9 @@ file_ticket_get_cred (mu_ticket_t ticket, mu_url_t url, 
const char *challenge,
 
   if (!ft->tickurl)
     {
-      int rc = mu_wicket_file_match_url (ft->filename, url, &ft->tickurl);
+      int rc = mu_wicket_file_match_url (ft->filename, url,
+                                        MU_URL_PARSE_ALL,
+                                        &ft->tickurl);
       if (rc)
        return rc;
     }
@@ -245,7 +247,8 @@ _file_wicket_get_ticket (mu_wicket_t wicket, void *data,
   
 int
 mu_wicket_stream_match_url (mu_stream_t stream, struct mu_debug_locus *loc,
-                           mu_url_t url, mu_url_t *pticket_url)
+                           mu_url_t url, int parse_flags,
+                           mu_url_t *pticket_url)
 {
   int rc;
   mu_url_t u = NULL;
@@ -270,20 +273,13 @@ mu_wicket_stream_match_url (mu_stream_t stream, struct 
mu_debug_locus *loc,
       if (*p == 0 || *p == '#')
        continue;
       
-      if ((err = mu_url_create (&u, p)) != 0)
+      if ((err = mu_url_create_hint (&u, p, parse_flags, NULL)) != 0)
        {
          /* Skip erroneous entry */
          mu_error (_("%s:%u: cannot create URL: %s"),
                    loc->file, loc->line, mu_strerror (err));
          continue;
        }
-      if ((err = mu_url_parse (u)) != 0)
-       {
-         mu_error (_("%s:%u: cannot parse URL: %s"),
-                   loc->file, loc->line, mu_strerror (err));
-         mu_url_destroy (&u);
-         continue;
-       }
 
       if (!mu_url_has_flag (u, MU_URL_USER|MU_URL_SECRET))
        {
@@ -326,6 +322,7 @@ mu_wicket_stream_match_url (mu_stream_t stream, struct 
mu_debug_locus *loc,
 
 int
 mu_wicket_file_match_url (const char *name, mu_url_t url,
+                         int parse_flags,
                          mu_url_t *pticket_url)
 {
   mu_stream_t stream;
@@ -337,7 +334,8 @@ mu_wicket_file_match_url (const char *name, mu_url_t url,
     return rc;
   loc.file = name;
   loc.line = 0;
-  rc = mu_wicket_stream_match_url (stream, &loc, url, pticket_url);
+  rc = mu_wicket_stream_match_url (stream, &loc, url, parse_flags,
+                                  pticket_url);
   mu_stream_close (stream);
   mu_stream_destroy (&stream);
   return rc;
diff --git a/libmailutils/mailbox/folder.c b/libmailutils/mailbox/folder.c
index f6e75c0..fe91823 100644
--- a/libmailutils/mailbox/folder.c
+++ b/libmailutils/mailbox/folder.c
@@ -157,9 +157,7 @@ mu_folder_create (mu_folder_t *pfolder, const char *name)
   rc = mu_url_create (&url, name);
   if (rc)
     return rc;
-  rc = mu_url_parse (url);
-  if (rc == 0)
-    rc = mu_folder_create_from_record (pfolder, url, NULL);
+  rc = mu_folder_create_from_record (pfolder, url, NULL);
   if (rc)
     mu_url_destroy (&url);
   return rc;
diff --git a/libmailutils/mailbox/mailbox.c b/libmailutils/mailbox/mailbox.c
index d95ce2d..0677e88 100644
--- a/libmailutils/mailbox/mailbox.c
+++ b/libmailutils/mailbox/mailbox.c
@@ -185,9 +185,7 @@ _create_mailbox (mu_mailbox_t *pmbox, const char *name)
   status = mu_url_create (&url, name);
   if (status)
     return status;
-  status = mu_url_parse (url);
-  if (status == 0)
-    status = _create_mailbox0 (pmbox, url, name);
+  status = _create_mailbox0 (pmbox, url, name);
   if (status)
     mu_url_destroy (&url);
   return status;
@@ -224,9 +222,7 @@ mu_mailbox_create_from_record (mu_mailbox_t *pmbox, 
mu_record_t record,
   rc = mu_url_create (&url, name);
   if (rc)
     return rc;
-  rc = mu_url_parse (url);
-  if (rc == 0)
-    rc = _mailbox_create_from_record (pmbox, record, url, name);
+  rc = _mailbox_create_from_record (pmbox, record, url, name);
   if (rc)
     mu_url_destroy (&url);
   return rc;
diff --git a/libmailutils/mailer/mailer.c b/libmailutils/mailer/mailer.c
index 59559eb..01fb6d3 100644
--- a/libmailutils/mailer/mailer.c
+++ b/libmailutils/mailer/mailer.c
@@ -168,9 +168,7 @@ mu_mailer_create (mu_mailer_t * pmailer, const char *name)
   status = mu_url_create (&url, name);
   if (status)
     return status;
-  status = mu_url_parse (url);
-  if (status == 0)
-    status = mu_mailer_create_from_url (pmailer, url);
+  status = mu_mailer_create_from_url (pmailer, url);
   if (status)
     mu_url_destroy (&url);
   return status;
diff --git a/libmailutils/mime/mimehdr.c b/libmailutils/mime/mimehdr.c
index 7bc801b..863566c 100644
--- a/libmailutils/mime/mimehdr.c
+++ b/libmailutils/mime/mimehdr.c
@@ -29,8 +29,6 @@
 #include <mailutils/message.h>
 #include <mailutils/header.h>
 #include <mailutils/stream.h>
-#include <mailutils/url.h> /* FIXME: for mu_url_decode, which should
-                             be renamed! */
 #include <mailutils/mime.h>
 #include <mailutils/filter.h>
 #include <mailutils/util.h>
@@ -480,9 +478,9 @@ mu_mimehdr_decode_param (const char *value, int flags,
     }
   else
     {
-      decoded = mu_url_decode (value);
-      if (!decoded)
-       return ENOMEM;
+      rc = mu_str_url_decode (&decoded, value);
+      if (rc)
+       return rc;
   
       if ((flags & MU_MIMEHDR_CSINFO)
          && (lang = strchr (decoded, '\''))
diff --git a/libmailutils/stream/tcp.c b/libmailutils/stream/tcp.c
index b53511a..c719be8 100644
--- a/libmailutils/stream/tcp.c
+++ b/libmailutils/stream/tcp.c
@@ -27,6 +27,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#include <limits.h>
 
 #include <sys/socket.h>
 #include <sys/types.h>
@@ -52,7 +53,7 @@ struct _tcp_instance
   struct _mu_stream stream;
   int          fd;
   char                 *host;
-  int          port;
+  unsigned short port;
   int          state;
   unsigned long        address;
   unsigned long source_addr;
@@ -304,7 +305,7 @@ _create_tcp_stream (int flags)
 
 int
 mu_tcp_stream_create_with_source_ip (mu_stream_t *pstream,
-                                    const char *host, int port,
+                                    const char *host, unsigned port,
                                     unsigned long source_ip,
                                     int flags)
 {
@@ -315,7 +316,7 @@ mu_tcp_stream_create_with_source_ip (mu_stream_t *pstream,
   if (host == NULL)
     return MU_ERR_TCP_NO_HOST;
 
-  if (port < 1)
+  if (port > USHRT_MAX)
     return MU_ERR_TCP_NO_PORT;
 
   tcp = _create_tcp_stream (flags | MU_STREAM_RDWR);
@@ -341,7 +342,7 @@ mu_tcp_stream_create_with_source_ip (mu_stream_t *pstream,
 
 int
 mu_tcp_stream_create_with_source_host (mu_stream_t *stream,
-                                      const char *host, int port,
+                                      const char *host, unsigned port,
                                       const char *source_host,
                                       int flags)
 {
@@ -354,7 +355,7 @@ mu_tcp_stream_create_with_source_host (mu_stream_t *stream,
 }
        
 int
-mu_tcp_stream_create (mu_stream_t *stream, const char *host, int port,
+mu_tcp_stream_create (mu_stream_t *stream, const char *host, unsigned port,
                      int flags)
 {
   return mu_tcp_stream_create_with_source_ip (stream, host, port,
diff --git a/libmailutils/string/Makefile.am b/libmailutils/string/Makefile.am
index 3f11ade..485df4a 100644
--- a/libmailutils/string/Makefile.am
+++ b/libmailutils/string/Makefile.am
@@ -34,6 +34,7 @@ libstring_la_SOURCES = \
  asprintf.c\
  muctype.c\
  vasnprintf.c\
- mkfilename.c
+ mkfilename.c\
+ xdecode.c
 
 INCLUDES = @MU_LIB_COMMON_INCLUDES@ -I/libmailutils
diff --git a/libmailutils/string/cpystr.c b/libmailutils/string/xdecode.c
similarity index 57%
copy from libmailutils/string/cpystr.c
copy to libmailutils/string/xdecode.c
index 9671c70..e802bf6 100644
--- a/libmailutils/string/cpystr.c
+++ b/libmailutils/string/xdecode.c
@@ -21,20 +21,53 @@
 #endif
 
 #include <string.h>
+#include <mailutils/errno.h>
 #include <mailutils/util.h>
 
-/* Smart strncpy that always add the null and returns the number of bytes
-   written.  */
-size_t
-mu_cpystr (char *dst, const char *src, size_t size)
+/* From RFC 1738, section 2.2 */
+void
+mu_str_url_decode_inline (char *s)
 {
-  size_t len = src ? strlen (src) : 0 ;
-  if (dst == NULL || size == 0)
-    return len;
-  if (len >= size)
-    len = size - 1;
-  memcpy (dst, src, len);
-  dst[len] = '\0';
-  return len;
+  char *d;
+
+  d = strchr (s, '%');
+  if (!d)
+    return;
+
+  for (s = d; *s; )
+    {
+      if (*s != '%')
+       {
+         *d++ = *s++;
+       }
+      else
+       {
+         unsigned long ul = 0;
+
+         s++;
+
+         /* don't check return value, it's correctly coded, or it's not,
+            in which case we just skip the garbage, this is a decoder,
+            not an AI project */
+
+         mu_hexstr2ul (&ul, s, 2);
+
+         s += 2;
+
+         *d++ = (char) ul;
+       }
+    }
+
+  *d = 0;
 }
 
+int
+mu_str_url_decode (char **ptr, const char *s)
+{
+  char *d = strdup (s);
+  if (!d)
+    return ENOMEM;
+  mu_str_url_decode_inline (d);
+  *ptr = d;
+  return 0;
+}
diff --git a/libmailutils/tests/url-parse.c b/libmailutils/tests/url-parse.c
index 92fd4f1..c87753c 100644
--- a/libmailutils/tests/url-parse.c
+++ b/libmailutils/tests/url-parse.c
@@ -77,7 +77,7 @@ int
 main ()
 {
   char str[1024];
-  long port = 0;
+  unsigned port = 0;
   mu_url_t u = NULL;
 
   while (fgets (str, sizeof (str), stdin) != NULL)
@@ -95,11 +95,6 @@ main ()
                    str, rc, mu_strerror (rc));
           exit (1);
         }
-      if ((rc = mu_url_parse (u)) != 0)
-        {
-          fprintf (stderr, "%s\n", mu_errname (rc));
-          continue;
-        }
 
       GET_AND_PRINT (scheme, u, buf, rc);
       GET_AND_PRINT (user, u, buf, rc);
@@ -127,7 +122,7 @@ main ()
          mu_error ("cannot get %s: %s", "port", mu_strerror (rc));     
          exit (1);                                     
         }                                               
-      printf ("port %ld\n", port);
+      printf ("port %hu\n", port);
       
       GET_AND_PRINT (path, u, buf, rc);
       print_fvpairs (u);
diff --git a/libmailutils/tests/wicket.c b/libmailutils/tests/wicket.c
index b6215cb..57857da 100644
--- a/libmailutils/tests/wicket.c
+++ b/libmailutils/tests/wicket.c
@@ -38,15 +38,10 @@ match_string (const char *str)
               str, rc, mu_strerror (rc));
       return;
     }
-  if ((rc = mu_url_parse (u)) != 0)
-    {
-      fprintf (stderr, "%s\n", mu_errname (rc));
-      return;
-    }
   MU_ASSERT (mu_stream_seek (stream, 0, MU_SEEK_SET, NULL));
   loc.file = name;
   loc.line = 0;
-  rc = mu_wicket_stream_match_url (stream, &loc, u, &url);
+  rc = mu_wicket_stream_match_url (stream, &loc, u, MU_URL_PARSE_ALL, &url);
   switch (rc)
     {
     case 0:
diff --git a/libmailutils/diag/Makefile.am b/libmailutils/url/Makefile.am
similarity index 72%
copy from libmailutils/diag/Makefile.am
copy to libmailutils/url/Makefile.am
index f2dae72..51e3e64 100644
--- a/libmailutils/diag/Makefile.am
+++ b/libmailutils/url/Makefile.am
@@ -15,28 +15,31 @@
 # Public License along with this library.  If not, see
 # <http://www.gnu.org/licenses/>.
 
-noinst_LTLIBRARIES = libdiag.la
-
-libdiag_la_SOURCES = \
- debug.c\
- diag.c\
- gdebug.c\
- muerror.c\
- muerrno.c\
- syslog.c\
- dbgstderr.c\
- dbgsyslog.c
+noinst_LTLIBRARIES = liburl.la
+
+liburl_la_SOURCES = \
+ accessor.h\
+ copy.c\
+ create.c\
+ decode.c\
+ destroy.c\
+ dup.c\
+ expand.c\
+ flag.c\
+ get-auth.c\
+ get-host.c\
+ get-param.c\
+ get-path.c\
+ get-portstr.c\
+ get-query.c\
+ get-scheme.c\
+ get-secret.c\
+ get-user.c\
+ match.c\
+ port.c\
+ scheme.c\
+ uplevel.c\
+ urlstr.c
 
 INCLUDES = @MU_LIB_COMMON_INCLUDES@ -I/libmailutils
 
-EXTRA_DIST = \
- errors\
- muerrno.cin
-
-BUILT_SOURCES = muerrno.c
-
-muerrno.c: errors muerrno.cin
-       $(AWK) -f $(mu_aux_dir)/generr.awk $^ > $@
-
-
-
diff --git a/libmailutils/url/accessor.h b/libmailutils/url/accessor.h
new file mode 100644
index 0000000..de38711
--- /dev/null
+++ b/libmailutils/url/accessor.h
@@ -0,0 +1,143 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+   Copyright (C) 2010 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.
+
+   This library 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.
+
+   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/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+
+#include <mailutils/types.h>
+#include <mailutils/errno.h>
+#include <mailutils/util.h>
+#include <mailutils/cstr.h>
+#include <mailutils/sys/url.h>
+
+/* General accessors: */
+#define AC2(a,b) a ## b
+#define METHOD(pfx,part) AC2(pfx,part)
+#define AC4(a,b,c,d) a ## b ## c ## d
+#define ACCESSOR(action,field) AC4(mu_url_,action,_,field)
+
+/* Define a `static get' accessor */
+int
+ACCESSOR(sget,URL_PART) (mu_url_t url, char const **sptr)
+{
+  if (url == NULL)
+    return EINVAL;
+  if (!url->URL_PART)
+    {
+      if (url->METHOD(_get_,URL_PART))
+       {
+         size_t n;
+         char *buf;
+
+         int status = url->METHOD(_get_,URL_PART) (url, NULL, 0, &n);
+         if (status)
+           return status;
+
+         buf = malloc (n + 1);
+         if (!buf)
+           return ENOMEM;
+
+         status = url->METHOD(_get_,URL_PART) (url, buf, n + 1, NULL);
+         if (status)
+           return status;
+
+         if (buf[0])
+           {
+             /* FIXME */
+             status = mu_str_url_decode (&url->URL_PART, buf);
+             if (status)
+               {
+                  free (buf);
+                  return status;
+               }
+           }
+         else
+           url->URL_PART = buf;
+         if (!url->URL_PART)
+           return ENOMEM;
+       }
+      else
+       return MU_ERR_NOENT;
+    }
+  *sptr = url->URL_PART;
+  return 0;
+}
+
+/* Define a `get' accessor */
+int
+ACCESSOR(get,URL_PART) (mu_url_t url, char *buf, size_t len, size_t *n)
+{
+  size_t i;
+  const char *str;
+  int status = ACCESSOR(sget, URL_PART) (url, &str);
+
+  if (status)
+    return status;
+
+  i = mu_cpystr (buf, str, len);
+  if (n)
+    *n = i;
+  return 0;
+}
+
+/* Define an `allocated get' accessor */
+int
+ACCESSOR(aget, URL_PART) (mu_url_t url, char **buf)
+{
+  const char *str;
+  int status = ACCESSOR(sget, URL_PART) (url, &str);
+
+  if (status)
+    return status;
+
+  if (str)
+    {
+      *buf = strdup (str);
+      if (!*buf)
+       status = ENOMEM;
+    }
+  else
+    *buf = NULL;
+  return status;
+}
+
+/* Define a comparator */
+int
+ACCESSOR(is_same,URL_PART) (mu_url_t url1, mu_url_t url2)
+{
+  const char *s1, *s2;
+  int status1, status2;
+
+  status1 = ACCESSOR(sget, URL_PART) (url1, &s1);
+  if (status1 && status1 != MU_ERR_NOENT)
+    return 0;
+  status2 = ACCESSOR(sget, URL_PART) (url2, &s2);
+  if (status2 && status2 != MU_ERR_NOENT)
+    return 0;
+
+  if (status1 || status2)
+    return status1 == status2; /* Both fields are missing */
+  return mu_c_strcasecmp (s1, s2) == 0;
+}
diff --git a/libmailutils/url/copy.c b/libmailutils/url/copy.c
new file mode 100644
index 0000000..7190b42
--- /dev/null
+++ b/libmailutils/url/copy.c
@@ -0,0 +1,145 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+   Copyright (C) 2010 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.
+
+   This library 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.
+
+   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/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <errno.h>
+#include <string.h>
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+
+#include <mailutils/types.h>
+#include <mailutils/argcv.h>
+#include <mailutils/secret.h>
+#include <mailutils/util.h>
+#include <mailutils/sys/url.h>
+
+struct copy_tab
+{
+  int mask;
+  int (*fun) (mu_url_t, mu_url_t, size_t);
+  size_t off;
+};
+
+static int
+_url_copy_str (mu_url_t dest_url, mu_url_t src_url, size_t off)
+{
+  char **dest = (char**) ((char*) dest_url + off);
+  char *src = *(char**) ((char*) src_url + off);
+  char *p = strdup (src);
+  if (!p)
+    return ENOMEM;
+  *dest = p;
+  return 0;
+}
+  
+static int
+_url_copy_secret (mu_url_t dest, mu_url_t src, size_t off)
+{
+  return mu_secret_dup (src->secret, &dest->secret);
+}
+
+static int
+_url_copy_port (mu_url_t dest, mu_url_t src, size_t off)
+{
+  if (src->portstr)
+    {
+      dest->portstr = strdup (src->portstr);
+      if (!dest->portstr)
+       return ENOMEM;
+    }
+  dest->port = src->port;
+  return 0;
+}
+
+static char **
+argcv_copy (size_t argc, char **argv)
+{
+  size_t i;
+  char **nv = calloc (argc + 1, sizeof (nv[0]));
+  if (!nv)
+    return NULL;
+  for (i = 0; i < argc; i++)
+    if ((nv[i] = strdup (argv[i])) == NULL)
+      {
+       mu_argcv_free (i, nv);
+       free (nv);
+       return NULL;
+      }
+  return nv;
+}
+
+static int
+_url_copy_param (mu_url_t dest, mu_url_t src, size_t off)
+{
+  if ((dest->fvpairs = argcv_copy (src->fvcount, src->fvpairs)) == NULL)
+    return ENOMEM;
+  dest->fvcount = src->fvcount;
+  return 0;
+}
+
+static int
+_url_copy_query (mu_url_t dest, mu_url_t src, size_t off)
+{
+  if ((dest->qargv = argcv_copy (src->qargc, src->qargv)) == NULL)
+    return ENOMEM;
+  dest->qargc = src->qargc;
+  return 0;
+}
+
+static struct copy_tab copy_tab[] = {
+  { MU_URL_SCHEME, _url_copy_str, mu_offsetof (struct _mu_url, scheme) },
+  { MU_URL_USER,   _url_copy_str, mu_offsetof (struct _mu_url, user) },
+  { MU_URL_SECRET, _url_copy_secret, 0 },
+  { MU_URL_AUTH,   _url_copy_str, mu_offsetof (struct _mu_url, auth) },
+  { MU_URL_HOST,   _url_copy_str, mu_offsetof (struct _mu_url, host) },
+  { MU_URL_PORT,   _url_copy_port, 0 },
+  { MU_URL_PATH,   _url_copy_str, mu_offsetof (struct _mu_url, path) },
+  { MU_URL_PARAM,  _url_copy_param, 0 },
+  { MU_URL_QUERY,  _url_copy_query, 0 }
+};
+
+int
+mu_url_copy_hints (mu_url_t url, mu_url_t hint)
+{
+  int i;
+
+  if (!url)
+    return EINVAL;
+  if (!hint)
+    return 0;
+  for (i = 0; i < MU_ARRAY_SIZE (copy_tab); i++)
+    {
+      if (!(url->flags & copy_tab[i].mask) &&
+         (hint->flags & copy_tab[i].mask))
+       {
+         int rc = copy_tab[i].fun (url, hint, copy_tab[i].off);
+         if (rc)
+           return rc;
+         url->flags |= copy_tab[i].mask;
+       }
+    }
+  return 0;
+}
+
+    
+
+
+
diff --git a/libmailutils/url/create.c b/libmailutils/url/create.c
new file mode 100644
index 0000000..674a524
--- /dev/null
+++ b/libmailutils/url/create.c
@@ -0,0 +1,525 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+   Copyright (C) 2010 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.
+
+   This library 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.
+
+   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/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#include <netdb.h>
+#include <arpa/inet.h>
+#include <limits.h>
+
+#include <mailutils/util.h>
+#include <mailutils/errno.h>
+#include <mailutils/argcv.h>
+#include <mailutils/secret.h>
+#include <mailutils/cstr.h>
+#include <mailutils/sys/url.h>
+
+struct mu_url_ctx
+{
+  int flags;
+  const char *input;
+  const char *cur;
+  mu_url_t url;
+
+  size_t passoff;
+  
+  char *tokbuf;
+  size_t toksize;
+  size_t toklen;
+};
+
+static int
+getkn (struct mu_url_ctx *ctx, char *delim)
+{
+  size_t n;
+
+  if (*ctx->cur == 0)
+    return -1;
+  n = strcspn (ctx->cur, delim);
+  if (n > ctx->toksize)
+    {
+      char *p = realloc (ctx->tokbuf, n + 1);
+      if (!p)
+       return ENOENT;
+      ctx->toksize = n + 1;
+      ctx->tokbuf = p;
+    }
+  memcpy (ctx->tokbuf, ctx->cur, n);
+  ctx->tokbuf[n] = 0;
+  ctx->toklen = n;
+  ctx->cur += n;
+  return 0;
+}
+
+#define INIT_ARRAY_SIZE 16
+
+static int
+expand_array (size_t *pwc, char ***pwv, int incr)
+{
+  size_t wc = *pwc;
+  char **wv = *pwv;
+
+  if (!wv)
+    {
+      wv = calloc (INIT_ARRAY_SIZE, sizeof (wv[0]));
+      wc = INIT_ARRAY_SIZE;
+    }
+  else
+    {
+      if (incr)
+       wc += incr;
+      else
+       {
+         size_t newsize = wc * 2;
+         if (newsize < wc)
+           return ENOMEM;
+         wc = newsize;
+       }
+      wv = realloc (wv, sizeof (wv[0]) * wc);
+    }
+  if (!wv)
+    return ENOMEM;
+  *pwv = wv;
+  *pwc = wc;
+  return 0;
+}
+  
+static int
+parse_param (struct mu_url_ctx *ctx, char *delim, int *pargc, char ***pargv)
+{
+  int rc;
+  size_t wc = 0, wn = 0;
+  char **wv = NULL;
+
+  while ((rc = getkn (ctx, delim)) == 0)
+    {
+      if (wn == wc)
+       {
+         rc = expand_array (&wc, &wv, 0);
+         if (rc)
+           break;
+       }
+      wv[wn] = strdup (ctx->tokbuf);
+      if (!wv[wn])
+       {
+         rc = ENOMEM;
+         break;
+       }
+      wn++;
+      if (*ctx->cur != delim[0])
+       break;
+      ctx->cur++;
+    }
+
+  if (rc == 0)
+    {
+      if (wn == wc)
+       {
+         rc = expand_array (&wc, &wv, 1);
+         if (rc)
+           {
+             mu_argcv_free (wc, wv);
+             return ENOMEM;
+           }
+         wv[wn] = NULL;
+       }
+
+      *pargv = realloc (wv, sizeof (wv[0]) * (wn + 1));
+      *pargc = wn;
+    }
+  else
+    mu_argcv_free (wc, wv);
+
+  return rc;
+}
+
+static int
+_mu_url_ctx_parse_query (struct mu_url_ctx *ctx)
+{
+  int rc;
+  
+  ctx->cur++;
+  rc = parse_param (ctx, "&", &ctx->url->qargc, &ctx->url->qargv);
+  if (rc == 0 && ctx->url->qargc)
+    ctx->url->flags |= MU_URL_QUERY;
+  return rc;
+}
+
+static int
+_mu_url_ctx_parse_param (struct mu_url_ctx *ctx)
+{
+  int rc;
+  
+  ctx->cur++;
+  rc = parse_param (ctx, ";?", &ctx->url->fvcount, &ctx->url->fvpairs);
+  if (rc)
+    return rc;
+  if (ctx->url->fvcount)
+    ctx->url->flags |= MU_URL_PARAM;
+  if (*ctx->cur == '?')
+    return _mu_url_ctx_parse_query (ctx);
+  return 0;
+}
+
+static int
+str_assign (char **ptr, const char *str)
+{
+  *ptr = strdup (str);
+  if (!*ptr)
+    return ENOMEM;
+  return 0;
+}
+
+static int
+_mu_url_ctx_parse_path (struct mu_url_ctx *ctx)
+{
+  int rc;
+  mu_url_t url = ctx->url;
+  
+  rc = getkn (ctx, ";?");
+  if (rc)
+    return rc;
+  rc = str_assign (&url->path, ctx->tokbuf);
+  if (rc == 0)
+    url->flags |= MU_URL_PATH;
+  if (*ctx->cur == ';')
+    return _mu_url_ctx_parse_param (ctx);
+  if (*ctx->cur == '?')
+    return _mu_url_ctx_parse_query (ctx);
+  return 0;
+}
+
+static int
+_mu_url_ctx_parse_host (struct mu_url_ctx *ctx, int has_host)
+{
+  int rc;
+  mu_url_t url = ctx->url;
+  
+  rc = getkn (ctx, ":/;?");
+  if (rc)
+    return rc;
+
+  if (ctx->toklen)
+    {
+      rc = str_assign (&url->host, ctx->tokbuf);
+      if (rc)
+       return rc;
+      url->flags |= MU_URL_HOST;
+      has_host = 1;
+    }
+
+  if (*ctx->cur == ':')
+    {
+      ctx->cur++;
+      has_host = 1;
+
+      rc = getkn (ctx, "/;?");
+      if (rc)
+       return rc;
+      
+      rc = str_assign (&url->portstr, ctx->tokbuf);
+      if (rc)
+       return rc;
+      url->flags |= MU_URL_PORT;
+    }
+
+  if (*ctx->cur == '/')
+    {
+      if (has_host)
+       ctx->cur++;
+      return _mu_url_ctx_parse_path (ctx);
+    }
+  
+  if (*ctx->cur == ';')
+    return _mu_url_ctx_parse_param (ctx);
+
+  if (*ctx->cur == '?')
+    return _mu_url_ctx_parse_query (ctx);
+  return 0;
+}
+
+static int
+_mu_url_ctx_parse_cred (struct mu_url_ctx *ctx)
+{
+  int rc, has_cred;
+  mu_url_t url = ctx->url;
+  const char *save = ctx->cur;
+  
+  rc = getkn (ctx, "@");
+  if (rc)
+    return rc;
+  has_cred = *ctx->cur == '@';
+  /* restore the pointer */
+  ctx->cur = save;  
+  if (has_cred)
+    {
+      /* Try to split the user into a:
+        <user>:<password>
+        or
+        <user>:<password>;AUTH=<auth>
+      */
+      rc = getkn (ctx, ":;@");
+      if (rc)
+       return rc;
+
+      if (ctx->toklen)
+       {
+         rc = str_assign (&url->user, ctx->tokbuf);
+         if (rc)
+           return rc;
+         url->flags |= MU_URL_USER;
+       }
+      
+      if (*ctx->cur == ':')
+       {
+         ctx->cur++;
+         ctx->passoff = ctx->cur - ctx->input;
+         
+         rc = getkn (ctx, ";@");
+         if (rc)
+           return rc;
+
+         if (ctx->toklen)
+           {
+             if (mu_secret_create (&url->secret, ctx->tokbuf, ctx->toklen))
+               return ENOMEM;
+             else
+               /* Clear password */
+               memset (ctx->tokbuf, 0, ctx->toklen);
+             url->flags |= MU_URL_SECRET;
+           }
+       }
+      if (*ctx->cur == ';')
+       {
+         ctx->cur++;
+
+         rc = getkn (ctx, "@");
+         if (rc)
+           return rc;
+         
+         /* Make sure it's the auth token. */
+         if (mu_c_strncasecmp (ctx->tokbuf, "auth=", 5) == 0)
+           {
+             rc = str_assign (&url->auth, ctx->tokbuf + 5);
+             if (rc)
+               return rc;
+             url->flags |= MU_URL_AUTH;
+           }
+       }
+
+      /* Skip @ sign */
+      ctx->cur++;
+    }
+  return _mu_url_ctx_parse_host (ctx, has_cred);
+}
+
+int
+_mu_url_ctx_parse (struct mu_url_ctx *ctx)
+{
+  int rc;
+  mu_url_t url = ctx->url;
+  
+  /* Parse the scheme part */
+  rc = getkn (ctx, ":/");
+  if (rc)
+    return rc;
+  if (*ctx->cur == ':')
+    {
+      rc = str_assign (&url->scheme, ctx->tokbuf);
+      if (rc)
+       return rc;
+      url->flags |= MU_URL_SCHEME;
+      ctx->cur++;
+    }
+
+  if (*ctx->cur == 0)
+    return 0;
+
+  if (ctx->cur[0] == '/' && ctx->cur[1] == '/')
+    {
+      ctx->cur += 2;
+      return _mu_url_ctx_parse_cred (ctx);
+    }
+
+  return _mu_url_ctx_parse_path (ctx);
+}
+
+static int
+_mu_url_create_internal (struct mu_url_ctx *ctx, mu_url_t hint)
+{
+  int rc;
+  mu_url_t url = ctx->url;
+
+  if ((ctx->flags & MU_URL_PARSE_PIPE) && ctx->input[0] == '|')
+    {
+      rc = str_assign (&url->scheme, "prog");
+      if (rc)
+       return rc;
+      url->flags |= MU_URL_SCHEME;
+      ctx->flags &= ~MU_URL_PARSE_HEXCODE;
+      rc = mu_argcv_get (ctx->input + 1, NULL, NULL, &url->qargc, &url->qargv);
+      if (rc == 0)
+       {
+         url->flags |= MU_URL_QUERY;
+         rc = str_assign (&url->path, url->qargv[0]);
+         if (rc == 0)
+           url->flags |= MU_URL_PATH;
+       }
+    }
+  else if ((ctx->flags & MU_URL_PARSE_SLASH) && ctx->input[0] == '/')
+    {
+      rc = str_assign (&url->scheme, "file");
+      if (rc)
+       return rc;
+      url->flags |= MU_URL_SCHEME;
+      ctx->flags &= ~MU_URL_PARSE_HEXCODE;
+      rc = str_assign (&url->path, ctx->input);
+      if (rc == 0)
+       url->flags |= MU_URL_PATH;
+    }
+  else
+    rc = _mu_url_ctx_parse (ctx);
+  
+  if (rc)
+    return rc;
+
+  if (hint)
+    {
+      /* Fill in missing values */
+      rc = mu_url_copy_hints (url, hint);
+      if (rc)
+       return rc;
+    }
+
+  if (!(url->flags & MU_URL_SCHEME))
+    return MU_ERR_URL_MISS_PARTS;
+  
+  /* RFC 1738, section 2.1, lower the scheme case */
+  mu_strlower (url->scheme);
+
+  if ((url->flags & MU_URL_PORT) && url->port == 0)
+    {
+      /* Convert port string to number */
+      unsigned long n;
+      char *p;
+      
+      n = strtoul (url->portstr, &p, 10);
+      if (*p)
+       {
+         if (ctx->flags & MU_URL_PARSE_PORTSRV)
+           {
+             /* FIXME: Another proto? */
+             struct servent *sp = getservbyname (url->portstr, "tcp");
+             if (!sp)
+               return MU_ERR_TCP_NO_PORT; //FIXME: Error code?
+             url->port = ntohs (sp->s_port);
+           }
+         else
+           return MU_ERR_TCP_NO_PORT;
+       }
+      else if (n > USHRT_MAX)
+       return ERANGE;
+      else
+       url->port = n;
+    }
+
+  if (ctx->flags & MU_URL_PARSE_HEXCODE)
+    {
+      /* Decode the %XX notations */
+      rc = mu_url_decode (url);
+      if (rc)
+       return rc;
+    }
+  
+  if ((url->flags & MU_URL_SECRET) &&
+      (ctx->flags & MU_URL_PARSE_HIDEPASS))
+    {
+      /* Obfuscate the password */
+#define PASS_REPL "***"
+#define PASS_REPL_LEN (sizeof (PASS_REPL) - 1)
+      size_t plen = mu_secret_length (url->secret);
+      size_t nlen = strlen (url->name);
+      size_t len = nlen - plen + PASS_REPL_LEN + 1;
+      char *newname;
+      
+      memset (url->name + ctx->passoff, 0, plen);
+      if (len > nlen + 1)
+       {
+         newname = realloc (url->name, len);
+         if (!newname)
+           return rc;
+         url->name = newname;
+       }
+      else
+       newname = url->name;
+      memmove (newname + ctx->passoff + PASS_REPL_LEN,
+              newname + ctx->passoff + plen,
+              nlen - (ctx->passoff + plen) + 1);
+      memcpy (newname + ctx->passoff, PASS_REPL, PASS_REPL_LEN);
+    }
+
+  return 0;
+}
+
+int
+mu_url_create_hint (mu_url_t *purl, const char *str, int flags,
+                   mu_url_t hint)
+{
+  int rc;
+  struct mu_url_ctx ctx;
+  mu_url_t url = calloc (1, sizeof (*url));
+  if (url == NULL)
+    return ENOMEM;
+  url->name = strdup (str);
+  if (!url->name)
+    {
+      free (url);
+      return ENOMEM;
+    }
+  memset (&ctx, 0, sizeof (ctx));
+  ctx.flags = flags;
+  ctx.input = str;
+  ctx.cur = ctx.input;
+  ctx.url = url;
+  rc = _mu_url_create_internal (&ctx, hint);
+  free (ctx.tokbuf);
+  if (rc)
+    mu_url_destroy (&url);
+  else
+    *purl = url;
+  return rc;
+}
+      
+int
+mu_url_create (mu_url_t *purl, const char *str)
+{
+  return mu_url_create_hint (purl, str,
+                            MU_URL_PARSE_HEXCODE |
+                            MU_URL_PARSE_HIDEPASS |
+                            MU_URL_PARSE_PORTSRV |
+                            MU_URL_PARSE_PIPE |
+                            MU_URL_PARSE_SLASH, NULL);
+}
diff --git a/libmailutils/url/decode.c b/libmailutils/url/decode.c
new file mode 100644
index 0000000..9aca0e2
--- /dev/null
+++ b/libmailutils/url/decode.c
@@ -0,0 +1,118 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+   Copyright (C) 2010 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.
+
+   This library 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.
+
+   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/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+
+#include <mailutils/types.h>
+#include <mailutils/util.h>
+#include <mailutils/secret.h>
+#include <mailutils/sys/url.h>
+
+struct decode_tab
+{
+  int mask;
+  int (*fun) (mu_url_t, size_t);
+  size_t off;
+};
+
+static int
+_url_dec_str (mu_url_t url, size_t off)
+{
+  char **pptr = (char**) ((char*) url + off);
+  mu_str_url_decode_inline (*pptr);
+  return 0;
+}
+
+static int
+_url_dec_param (mu_url_t url, size_t off)
+{
+  int i;
+
+  for (i = 0; i < url->fvcount; i++)
+    mu_str_url_decode_inline (url->fvpairs[i]);
+  return 0;
+}
+
+static int
+_url_dec_query (mu_url_t url, size_t off)
+{
+  int i;
+
+  for (i = 0; i < url->qargc; i++)
+    mu_str_url_decode_inline (url->qargv[i]);
+  return 0;
+}
+
+static int
+_url_dec_secret (mu_url_t url, size_t off)
+{
+  char *pass;
+  mu_secret_t newsec;
+  int rc;
+
+  rc = mu_str_url_decode (&pass, mu_secret_password (url->secret));
+  if (rc)
+    return rc;
+  rc = mu_secret_create (&newsec, pass, strlen (pass));
+  memset (pass, 0, strlen (pass));
+  free (pass);
+  if (rc)
+    return rc;
+  mu_secret_destroy (&url->secret);
+  url->secret = newsec;
+  return 0;
+}
+
+static struct decode_tab decode_tab[] = {
+  { MU_URL_SCHEME, _url_dec_str, mu_offsetof (struct _mu_url, scheme) },
+  { MU_URL_USER,   _url_dec_str, mu_offsetof (struct _mu_url, user) },
+  { MU_URL_SECRET, _url_dec_secret },
+  { MU_URL_AUTH,   _url_dec_str, mu_offsetof (struct _mu_url, auth) },
+  { MU_URL_HOST,   _url_dec_str, mu_offsetof (struct _mu_url, host) },
+  { MU_URL_PATH,   _url_dec_str, mu_offsetof (struct _mu_url, path) },
+  { MU_URL_PARAM,  _url_dec_param, 0 },
+  { MU_URL_QUERY,  _url_dec_query, 0 }
+};
+
+int
+mu_url_decode (mu_url_t url)
+{
+  int i;
+
+  if (!url)
+    return EINVAL;
+  for (i = 0; i < MU_ARRAY_SIZE (decode_tab); i++)
+    {
+      if (url->flags & decode_tab[i].mask)
+       {
+         int rc = decode_tab[i].fun (url, decode_tab[i].off);
+         if (rc)
+           return rc;
+       }
+    }
+  return 0;
+}
+
diff --git a/libproto/nntp/url.c b/libmailutils/url/destroy.c
similarity index 51%
copy from libproto/nntp/url.c
copy to libmailutils/url/destroy.c
index 3870107..a46dc31 100644
--- a/libproto/nntp/url.c
+++ b/libmailutils/url/destroy.c
@@ -1,5 +1,5 @@
 /* GNU Mailutils -- a suite of utilities for electronic mail
-   Copyright (C) 2004, 2007, 2010 Free Software Foundation, Inc.
+   Copyright (C) 2010 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
@@ -12,39 +12,63 @@
    Lesser 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
+   Public License along with this library.  If not, see 
    <http://www.gnu.org/licenses/>. */
 
 #ifdef HAVE_CONFIG_H
 # include <config.h>
 #endif
 
-#ifdef ENABLE_NNTP
-
 #include <errno.h>
 #include <stdlib.h>
 #include <string.h>
-#include <errno.h>
 #ifdef HAVE_STRINGS_H
 # include <strings.h>
 #endif
 
-#include <mailutils/nntp.h>
-
+#include <mailutils/types.h>
+#include <mailutils/argcv.h>
+#include <mailutils/secret.h>
+#include <mailutils/errno.h>
 #include <mailutils/sys/url.h>
 
-/*
-  POP URL:
-  nntp://<host>:<port>/<newsgroup-name>/<article-number>
-*/
-
-int
-_nntp_url_init (mu_url_t url)
+void
+mu_url_destroy (mu_url_t * purl)
 {
-  if (url->port == 0)
-    url->port = MU_NNTP_DEFAULT_PORT;
+  if (purl && *purl)
+    {
+      mu_url_t url = (*purl);
 
-  return status;
-}
+      if (url->_destroy)
+       url->_destroy (url);
 
-#endif
+      if (url->name)
+       free (url->name);
+
+      if (url->scheme)
+       free (url->scheme);
+
+      if (url->user)
+       free (url->user);
+
+      mu_secret_destroy (&url->secret);
+
+      if (url->auth)
+       free (url->auth);
+
+      if (url->host)
+       free (url->host);
+
+      if (url->path)
+       free (url->path);
+
+      if (url->fvcount)
+       mu_argcv_free (url->fvcount, url->fvpairs);
+
+      mu_argcv_free (url->qargc, url->qargv);
+
+      free (url);
+
+      *purl = NULL;
+    }
+}
diff --git a/libproto/nntp/url.c b/libmailutils/url/dup.c
similarity index 61%
copy from libproto/nntp/url.c
copy to libmailutils/url/dup.c
index 3870107..d9a7383 100644
--- a/libproto/nntp/url.c
+++ b/libmailutils/url/dup.c
@@ -1,5 +1,5 @@
 /* GNU Mailutils -- a suite of utilities for electronic mail
-   Copyright (C) 2004, 2007, 2010 Free Software Foundation, Inc.
+   Copyright (C) 2010 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
@@ -12,39 +12,45 @@
    Lesser 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
+   Public License along with this library.  If not, see 
    <http://www.gnu.org/licenses/>. */
 
 #ifdef HAVE_CONFIG_H
 # include <config.h>
 #endif
 
-#ifdef ENABLE_NNTP
-
 #include <errno.h>
 #include <stdlib.h>
 #include <string.h>
-#include <errno.h>
 #ifdef HAVE_STRINGS_H
 # include <strings.h>
 #endif
 
-#include <mailutils/nntp.h>
-
+#include <mailutils/types.h>
+#include <mailutils/util.h>
 #include <mailutils/sys/url.h>
 
-/*
-  POP URL:
-  nntp://<host>:<port>/<newsgroup-name>/<article-number>
-*/
-
 int
-_nntp_url_init (mu_url_t url)
+mu_url_dup (mu_url_t old_url, mu_url_t *new_url)
 {
-  if (url->port == 0)
-    url->port = MU_NNTP_DEFAULT_PORT;
-
-  return status;
+  int rc;
+  mu_url_t url = calloc (1, sizeof (*url));
+
+  if (!url)
+    return ENOMEM;
+  url->name = strdup (old_url->name);
+  if (!url->name)
+    {
+      free (url);
+      return ENOMEM;
+    }
+  
+  rc = mu_url_copy_hints (url, old_url);
+  if (rc)
+    {
+      mu_url_destroy (&url);
+      return rc;
+    }
+  *new_url = url;
+  return 0;
 }
-
-#endif
diff --git a/libmailutils/url/expand.c b/libmailutils/url/expand.c
new file mode 100644
index 0000000..bb2ef95
--- /dev/null
+++ b/libmailutils/url/expand.c
@@ -0,0 +1,216 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+   Copyright (C) 2010 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.
+
+   This library 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.
+
+   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/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+
+#include <mailutils/types.h>
+#include <mailutils/util.h>
+#include <mailutils/errno.h>
+#include <mailutils/argcv.h>
+#include <mailutils/sys/url.h>
+
+/* Default mailbox path generator */
+static char *
+_url_path_default (const char *spooldir, const char *user, int unused)
+{
+  return mu_make_file_name (spooldir, user);
+}
+
+/* Hashed indexing */
+static char *
+_url_path_hashed (const char *spooldir, const char *user, int param)
+{
+  int i;
+  int ulen = strlen (user);
+  char *mbox;
+  unsigned hash;
+
+  if (param > ulen)
+    param = ulen;
+  for (i = 0, hash = 0; i < param; i++)
+    hash += user[i];
+
+  mbox = malloc (ulen + strlen (spooldir) + 5);
+  sprintf (mbox, "%s/%02X/%s", spooldir, hash % 256, user);
+  return mbox;
+}
+
+static int transtab[] = {
+  'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
+  'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
+  'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
+  'y', 'z', 'a', 'b', 'c', 'd', 'e', 'f',
+  'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
+  'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
+  'w', 'x', 'y', 'z', 'a', 'b', 'c', 'd',
+  'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
+  'm', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
+  'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
+  'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
+  'x', 'y', 'z', 'b', 'c', 'd', 'e', 'f',
+  'g', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
+  'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
+  'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
+  'x', 'y', 'z', 'b', 'c', 'd', 'e', 'f',
+  'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
+  'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q',
+  'r', 's', 't', 'u', 'v', 'w', 'x', 'y',
+  'z', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
+  'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
+  'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
+  'x', 'y', 'z', 'a', 'b', 'c', 'd', 'e',
+  'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
+  'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
+  'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
+  'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
+  'y', 'z', 'b', 'c', 'd', 'e', 'f', 'g',
+  'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
+  'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
+  'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
+  'y', 'z', 'b', 'c', 'd', 'e', 'f', 'g'
+};
+
+/* Forward Indexing */
+static char *
+_url_path_index (const char *spooldir, const char *iuser, int index_depth)
+{
+  const unsigned char* user = (const unsigned char*) iuser;
+  int i, ulen = strlen (iuser);
+  char *mbox, *p;
+
+  if (ulen == 0)
+    return NULL;
+
+  mbox = malloc (ulen + strlen (spooldir) + 2*index_depth + 2);
+  strcpy (mbox, spooldir);
+  p = mbox + strlen (mbox);
+  for (i = 0; i < index_depth && i < ulen; i++)
+    {
+      *p++ = '/';
+      *p++ = transtab[ user[i] ];
+    }
+  for (; i < index_depth; i++)
+    {
+      *p++ = '/';
+      *p++ = transtab[ user[ulen-1] ];
+    }
+  *p++ = '/';
+  strcpy (p, iuser);
+  return mbox;
+}
+
+/* Reverse Indexing */
+static char *
+_url_path_rev_index (const char *spooldir, const char *iuser, int index_depth)
+{
+  const unsigned char* user = (const unsigned char*) iuser;
+  int i, ulen = strlen (iuser);
+  char *mbox, *p;
+
+  if (ulen == 0)
+    return NULL;
+
+  mbox = malloc (ulen + strlen (spooldir) + 2*index_depth + 1);
+  strcpy (mbox, spooldir);
+  p = mbox + strlen (mbox);
+  for (i = 0; i < index_depth && i < ulen; i++)
+    {
+      *p++ = '/';
+      *p++ = transtab[ user[ulen - i - 1] ];
+    }
+  for (; i < index_depth; i++)
+    {
+      *p++ = '/';
+      *p++ = transtab[ user[0] ];
+    }
+  *p++ = '/';
+  strcpy (p, iuser);
+  return mbox;
+}
+
+static int
+rmselector (const char *p, void *data MU_ARG_UNUSED)
+{
+  return strncmp (p, "type=", 5) == 0
+        || strncmp (p, "user=", 5) == 0
+        || strncmp (p, "param=", 6) == 0;
+}
+
+int
+mu_url_expand_path (mu_url_t url)
+{
+  size_t i;
+  char *user = NULL;
+  int param = 0;
+  char *p;
+  char *(*fun) (const char *, const char *, int) = _url_path_default;
+
+  if (url->fvcount == 0)
+    return 0;
+
+  for (i = 0; i < url->fvcount; i++)
+    {
+      p = url->fvpairs[i];
+      if (strncmp (p, "type=", 5) == 0)
+       {
+         char *type = p + 5;
+
+         if (strcmp (type, "hash") == 0)
+           fun = _url_path_hashed;
+         else if (strcmp (type, "index") == 0)
+           fun = _url_path_index;
+         else if (strcmp (type, "rev-index") == 0)
+           fun = _url_path_rev_index;
+         else
+           return MU_ERR_NOENT;
+       }
+      else if (strncmp (p, "user=", 5) == 0)
+       {
+         user = p + 5;
+       }
+      else if (strncmp (p, "param=", 6) == 0)
+       {
+         param = strtoul (p + 6, NULL, 0);
+       }
+    }
+
+  if (user)
+    {
+      char *p = fun (url->path, user, param);
+      if (p)
+       {
+         free (url->path);
+         url->path = p;
+       }
+      mu_argcv_remove (&url->fvcount, &url->fvpairs, rmselector, NULL);
+    }
+  else
+    return MU_ERR_NOENT;
+
+  return 0;
+}
+
diff --git a/libmailutils/base/freeitem.c b/libmailutils/url/flag.c
similarity index 75%
copy from libmailutils/base/freeitem.c
copy to libmailutils/url/flag.c
index ad382a4..bf06f68 100644
--- a/libmailutils/base/freeitem.c
+++ b/libmailutils/url/flag.c
@@ -18,11 +18,23 @@
 #ifdef HAVE_CONFIG_H
 # include <config.h>
 #endif
-#include <stdlib.h>
 
-/* Default destroy_item function. */
-void
-mu_list_free_item (void *item)
+#include <errno.h>
+#include <mailutils/sys/url.h>
+
+int
+mu_url_get_flags (mu_url_t url, int *pf)
+{
+  if (!url || !pf)
+    return EINVAL;
+  *pf = url->flags;
+  return 0;
+}
+
+int
+mu_url_has_flag (mu_url_t url, int flags)
 {
-  free (item);
+  if (!url)
+    return 0;
+  return url->flags & flags;
 }
diff --git a/libmailutils/url/get-auth.c b/libmailutils/url/get-auth.c
new file mode 100644
index 0000000..b9650a5
--- /dev/null
+++ b/libmailutils/url/get-auth.c
@@ -0,0 +1,3 @@
+#define URL_PART auth
+#include "accessor.h"
+
diff --git a/libmailutils/url/get-host.c b/libmailutils/url/get-host.c
new file mode 100644
index 0000000..6de6b56
--- /dev/null
+++ b/libmailutils/url/get-host.c
@@ -0,0 +1,2 @@
+#define URL_PART host
+#include "accessor.h"
diff --git a/libmailutils/url/get-param.c b/libmailutils/url/get-param.c
new file mode 100644
index 0000000..c2be823
--- /dev/null
+++ b/libmailutils/url/get-param.c
@@ -0,0 +1,131 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+   Copyright (C) 2010 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.
+
+   This library 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.
+
+   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/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+
+#include <mailutils/types.h>
+#include <mailutils/errno.h>
+#include <mailutils/argcv.h>
+#include <mailutils/sys/url.h>
+
+/* field-value pairs accessors */
+int
+mu_url_sget_fvpairs (const mu_url_t url, size_t *fvc, char ***fvp)
+{
+  if (url == NULL)
+    return EINVAL;
+  /* FIXME: no _get_fvpairs method, but the method stuff needs to be rewritten
+     anyway */
+  *fvc = url->fvcount;
+  *fvp = url->fvpairs;
+  return 0;
+}
+
+int
+mu_url_sget_param (const mu_url_t url, const char *param, const char **val)
+{
+  size_t fvc;
+  char **fvp;
+  int status = mu_url_sget_fvpairs (url, &fvc, &fvp);
+
+  if (status)
+    return status;
+
+  if (fvc)
+    {
+      size_t i;
+      
+      for (i = 0; i < fvc; i++)
+       {
+         const char *p;
+         char *q;
+
+         for (p = param, q = fvp[i]; *p && *q && *p == *q; p++, q++)
+           ;
+         if (*p == 0)
+           {
+             if (*q == 0)
+               {
+                 if (val)
+                   *val = q;
+                 return 0;
+               }
+             else if (*q == '=')
+               {
+                 if (val)
+                   *val = q + 1;
+                 return 0;
+               }
+           }
+       }
+    }
+ 
+  return MU_ERR_NOENT;
+}
+  
+int
+mu_url_aget_fvpairs (const mu_url_t url, size_t *pfvc, char ***pfvp)
+{
+  size_t fvc, i;
+  char **fvp;
+  char **fvcopy;
+
+  int rc = mu_url_sget_fvpairs (url, &fvc, &fvp);
+  if (rc)
+    return rc;
+
+  fvcopy = calloc (fvc + 1, sizeof (fvcopy[0]));
+  if (!fvcopy)
+    return errno;
+  for (i = 0; i < fvc; i++)
+    {
+      if (!(fvcopy[i] = strdup (fvp[i])))
+       {
+         mu_argcv_free (i, fvcopy);
+         return errno;
+       }
+    }
+  fvcopy[i] = NULL;
+  *pfvc = fvc;
+  *pfvp = fvcopy;
+  return 0;
+}
+
+int
+mu_url_aget_param (const mu_url_t url, const char *param, char **val)
+{
+  const char *s;
+  int status = mu_url_sget_param (url, param, &s);
+
+  if (status == 0)
+    {
+      *val = strdup (s);
+      if (!*val)
+       status = ENOMEM;
+    }
+  return status;
+}
+
diff --git a/libmailutils/url/get-path.c b/libmailutils/url/get-path.c
new file mode 100644
index 0000000..3f906b9
--- /dev/null
+++ b/libmailutils/url/get-path.c
@@ -0,0 +1,2 @@
+#define URL_PART path
+#include "accessor.h"
diff --git a/libmailutils/url/get-portstr.c b/libmailutils/url/get-portstr.c
new file mode 100644
index 0000000..9b211bf
--- /dev/null
+++ b/libmailutils/url/get-portstr.c
@@ -0,0 +1,2 @@
+#define URL_PART portstr
+#include "accessor.h"
diff --git a/libproto/pop/url.c b/libmailutils/url/get-query.c
similarity index 52%
copy from libproto/pop/url.c
copy to libmailutils/url/get-query.c
index f528064..cf74922 100644
--- a/libproto/pop/url.c
+++ b/libmailutils/url/get-query.c
@@ -1,6 +1,5 @@
 /* GNU Mailutils -- a suite of utilities for electronic mail
-   Copyright (C) 1999, 2000, 2001, 2003, 2007, 2008, 2010 Free Software
-   Foundation, Inc.
+   Copyright (C) 2010 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
@@ -13,52 +12,61 @@
    Lesser 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
+   Public License along with this library.  If not, see 
    <http://www.gnu.org/licenses/>. */
 
 #ifdef HAVE_CONFIG_H
 # include <config.h>
 #endif
 
-#ifdef ENABLE_POP
-
 #include <errno.h>
 #include <stdlib.h>
 #include <string.h>
-#include <errno.h>
 #ifdef HAVE_STRINGS_H
 # include <strings.h>
 #endif
 
+#include <mailutils/types.h>
+#include <mailutils/errno.h>
+#include <mailutils/argcv.h>
 #include <mailutils/sys/url.h>
-#include <mailutils/sys/registrar.h>
-
-/*
-  POP URLs:
-    pop://[<user>[;AUTH=<auth>address@hidden<host>[:<port>]
-    pop://[<user>[:address@hidden<host>[:<port>]
-*/
 
 int
-_url_pop_init (mu_url_t url)
+mu_url_sget_query (const mu_url_t url, size_t *qc, char ***qv)
 {
-  if (url->port == 0)
-    url->port = MU_POP_PORT;
+  if (url == NULL)
+    return EINVAL;
+  /* See FIXME below */
+  *qc = url->qargc;
+  *qv = url->qargv;
   return 0;
 }
 
-/*
-  POPS URLs:
-    pops://[<user>[;AUTH=<auth>address@hidden<host>[:<port>]
-    pops://[<user>[:address@hidden<host>[:<port>]
-*/
-
 int
-_url_pops_init (mu_url_t url)
+mu_url_aget_query (const mu_url_t url, size_t *qc, char ***qv)
 {
-  if (url->port == 0)
-    url->port = MU_POPS_PORT;
+  size_t qargc, i;
+  char **qargv;
+  char **qcopy;
+
+  int rc = mu_url_sget_fvpairs (url, &qargc, &qargv);
+  if (rc)
+    return rc;
+
+  qcopy = calloc (qargc + 1, sizeof (qcopy[0]));
+  if (!qcopy)
+    return errno;
+  for (i = 0; i < qargc; i++)
+    {
+      if (!(qcopy[i] = strdup (qargv[i])))
+       {
+         mu_argcv_free (i, qcopy);
+         return errno;
+       }
+    }
+  qcopy[i] = NULL;
+  *qc = qargc;
+  *qv = qcopy;
   return 0;
 }
 
-#endif /* ENABLE_POP */
diff --git a/libmailutils/url/get-scheme.c b/libmailutils/url/get-scheme.c
new file mode 100644
index 0000000..983902e
--- /dev/null
+++ b/libmailutils/url/get-scheme.c
@@ -0,0 +1,2 @@
+#define URL_PART scheme
+#include "accessor.h"
diff --git a/libproto/nntp/url.c b/libmailutils/url/get-secret.c
similarity index 66%
copy from libproto/nntp/url.c
copy to libmailutils/url/get-secret.c
index 3870107..34fb229 100644
--- a/libproto/nntp/url.c
+++ b/libmailutils/url/get-secret.c
@@ -1,5 +1,5 @@
 /* GNU Mailutils -- a suite of utilities for electronic mail
-   Copyright (C) 2004, 2007, 2010 Free Software Foundation, Inc.
+   Copyright (C) 2010 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
@@ -12,39 +12,33 @@
    Lesser 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
+   Public License along with this library.  If not, see 
    <http://www.gnu.org/licenses/>. */
 
 #ifdef HAVE_CONFIG_H
 # include <config.h>
 #endif
 
-#ifdef ENABLE_NNTP
-
 #include <errno.h>
 #include <stdlib.h>
 #include <string.h>
-#include <errno.h>
 #ifdef HAVE_STRINGS_H
 # include <strings.h>
 #endif
 
-#include <mailutils/nntp.h>
-
+#include <mailutils/types.h>
+#include <mailutils/errno.h>
+#include <mailutils/secret.h>
 #include <mailutils/sys/url.h>
 
-/*
-  POP URL:
-  nntp://<host>:<port>/<newsgroup-name>/<article-number>
-*/
-
 int
-_nntp_url_init (mu_url_t url)
+mu_url_get_secret (const mu_url_t url, mu_secret_t *psecret)
 {
-  if (url->port == 0)
-    url->port = MU_NNTP_DEFAULT_PORT;
-
-  return status;
+  if (url->_get_secret)
+    return url->_get_secret (url, psecret);
+  if (url->secret == NULL)
+    return MU_ERR_NOENT;
+  mu_secret_ref (url->secret);
+  *psecret = url->secret;
+  return 0;
 }
-
-#endif
diff --git a/libmailutils/url/get-user.c b/libmailutils/url/get-user.c
new file mode 100644
index 0000000..5a3ab79
--- /dev/null
+++ b/libmailutils/url/get-user.c
@@ -0,0 +1,2 @@
+#define URL_PART user
+#include "accessor.h"
diff --git a/libmailutils/url/match.c b/libmailutils/url/match.c
new file mode 100644
index 0000000..4932f45
--- /dev/null
+++ b/libmailutils/url/match.c
@@ -0,0 +1,102 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+   Copyright (C) 2010 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.
+
+   This library 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.
+
+   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/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+
+#include <mailutils/types.h>
+#include <mailutils/cstr.h>
+#include <mailutils/sys/url.h>
+
+#define is_wildcard(s) ((s)[0] == '*' && s[1] == 0)
+
+#define WEIGHT_SCHEME 3
+#define WEIGHT_USER   4
+#define WEIGHT_HOST   2
+#define WEIGHT_PORT   1
+
+int
+mu_url_matches_ticket (mu_url_t ticket, mu_url_t url, int *pwc)
+{
+  int wcnt = 0;
+                                             
+  if (is_wildcard (ticket->scheme))
+    wcnt += WEIGHT_SCHEME;
+  else if (mu_c_strcasecmp (ticket->scheme, url->scheme))
+    return 0;
+
+  if (ticket->flags & MU_URL_HOST)
+    {
+      if (is_wildcard (ticket->host))
+       wcnt += WEIGHT_HOST;
+      else if (url->flags & MU_URL_HOST)
+       {
+         if (mu_c_strcasecmp (ticket->host, url->host))
+           /* FIXME: Compare IP addresses */
+           return 0;
+       }
+      else
+       return 0;
+    }
+  else
+    wcnt += WEIGHT_HOST;
+
+  if (ticket->flags & MU_URL_PORT)
+    {
+      if (is_wildcard (ticket->portstr))
+       wcnt += WEIGHT_PORT;
+      else if (url->port & MU_URL_PORT)
+       {
+         if (ticket->port != url->port)
+           return 0;
+         else
+           wcnt += WEIGHT_PORT;
+       }
+    }
+  else
+    wcnt += WEIGHT_PORT;
+  
+  if (ticket->flags & MU_URL_USER)
+    {
+      if (is_wildcard (ticket->user))
+       wcnt += WEIGHT_USER;
+      
+      /* If ticket has a user or pass, but url doesn't, that's OK, we were
+        looking for this info. But if url does have a user/pass, it
+        must match the ticket. */
+      else if (url->flags & MU_URL_USER)
+       {
+         if (strcmp (ticket->user, url->user))
+           return 0;
+       }
+    }
+  else
+    wcnt += WEIGHT_USER;
+  
+  /* Guess it matches. */
+  if (pwc)
+    *pwc = wcnt;
+  return 1;
+}
diff --git a/libproto/nntp/url.c b/libmailutils/url/port.c
similarity index 62%
copy from libproto/nntp/url.c
copy to libmailutils/url/port.c
index 3870107..88b7dd1 100644
--- a/libproto/nntp/url.c
+++ b/libmailutils/url/port.c
@@ -1,5 +1,5 @@
 /* GNU Mailutils -- a suite of utilities for electronic mail
-   Copyright (C) 2004, 2007, 2010 Free Software Foundation, Inc.
+   Copyright (C) 2010 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
@@ -12,39 +12,42 @@
    Lesser 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
+   Public License along with this library.  If not, see 
    <http://www.gnu.org/licenses/>. */
 
 #ifdef HAVE_CONFIG_H
 # include <config.h>
 #endif
 
-#ifdef ENABLE_NNTP
-
 #include <errno.h>
 #include <stdlib.h>
 #include <string.h>
-#include <errno.h>
 #ifdef HAVE_STRINGS_H
 # include <strings.h>
 #endif
 
-#include <mailutils/nntp.h>
-
+#include <mailutils/types.h>
+#include <mailutils/cstr.h>
 #include <mailutils/sys/url.h>
 
-/*
-  POP URL:
-  nntp://<host>:<port>/<newsgroup-name>/<article-number>
-*/
+int
+mu_url_get_port (const mu_url_t url, unsigned *pport)
+{
+  if (url == NULL)
+    return EINVAL;
+  if (url->_get_port)
+    return url->_get_port (url, pport);
+  *pport = url->port;
+  return 0;
+}
 
 int
-_nntp_url_init (mu_url_t url)
+mu_url_is_same_port (mu_url_t url1, mu_url_t url2)
 {
-  if (url->port == 0)
-    url->port = MU_NNTP_DEFAULT_PORT;
+  unsigned p1 = 0, p2 = 0;
 
-  return status;
+  mu_url_get_port (url1, &p1);
+  mu_url_get_port (url2, &p2);
+  return (p1 == p2);
 }
 
-#endif
diff --git a/libproto/nntp/url.c b/libmailutils/url/scheme.c
similarity index 60%
copy from libproto/nntp/url.c
copy to libmailutils/url/scheme.c
index 3870107..e68fa91 100644
--- a/libproto/nntp/url.c
+++ b/libmailutils/url/scheme.c
@@ -1,5 +1,5 @@
 /* GNU Mailutils -- a suite of utilities for electronic mail
-   Copyright (C) 2004, 2007, 2010 Free Software Foundation, Inc.
+   Copyright (C) 2010 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
@@ -12,39 +12,44 @@
    Lesser 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
+   Public License along with this library.  If not, see 
    <http://www.gnu.org/licenses/>. */
 
 #ifdef HAVE_CONFIG_H
 # include <config.h>
 #endif
 
-#ifdef ENABLE_NNTP
-
 #include <errno.h>
 #include <stdlib.h>
 #include <string.h>
-#include <errno.h>
 #ifdef HAVE_STRINGS_H
 # include <strings.h>
 #endif
 
-#include <mailutils/nntp.h>
-
+#include <mailutils/types.h>
+#include <mailutils/cstr.h>
 #include <mailutils/sys/url.h>
 
-/*
-  POP URL:
-  nntp://<host>:<port>/<newsgroup-name>/<article-number>
-*/
+int
+mu_url_set_scheme (mu_url_t url, const char *scheme)
+{
+  char *p;
+  if (!url || !scheme)
+    return EINVAL;
+  p = realloc (url->scheme, strlen (scheme) + 1);
+  if (!p)
+    return ENOMEM;
+  strcpy (url->scheme, scheme);
+  return 0;
+}
 
 int
-_nntp_url_init (mu_url_t url)
+mu_url_is_scheme (mu_url_t url, const char *scheme)
 {
-  if (url->port == 0)
-    url->port = MU_NNTP_DEFAULT_PORT;
+  if (url && scheme && url->scheme 
+      && mu_c_strcasecmp (url->scheme, scheme) == 0)
+    return 1;
 
-  return status;
+  return 0;
 }
 
-#endif
diff --git a/libmailutils/mailbox/hdrfirst.c b/libmailutils/url/uplevel.c
similarity index 51%
copy from libmailutils/mailbox/hdrfirst.c
copy to libmailutils/url/uplevel.c
index 363021f..749fe1f 100644
--- a/libmailutils/mailbox/hdrfirst.c
+++ b/libmailutils/url/uplevel.c
@@ -12,37 +12,60 @@
    Lesser 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
+   Public License along with this library.  If not, see 
    <http://www.gnu.org/licenses/>. */
 
 #ifdef HAVE_CONFIG_H
 # include <config.h>
 #endif
 
+#include <errno.h>
 #include <stdlib.h>
+#include <string.h>
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+
 #include <mailutils/types.h>
-#include <mailutils/header.h>
 #include <mailutils/errno.h>
+#include <mailutils/sys/url.h>
 
 int
-mu_header_sget_firstof (mu_header_t hdr, char **names,
-                       const char **pval, int *pidx)
+mu_url_uplevel (mu_url_t url, mu_url_t *upurl)
 {
-  int status;
-  const char *s = NULL;
-  int i;
-  
-  for (i = 0; names[i]; i++)
+  int rc;
+  char *p;
+  mu_url_t new_url;
+
+  if (url->_uplevel)
+    return url->_uplevel (url, upurl);
+
+  if (!url->path)
+    return MU_ERR_NOENT;
+  p = strrchr (url->path, '/');
+
+  rc = mu_url_dup (url, &new_url);
+  if (rc == 0)
     {
-      status = mu_header_sget_value (hdr, names[i], &s);
-      if (status == 0 && *s != 0)
+      if (!p || p == url->path)
+       {
+         free (new_url->path);
+         new_url->path = NULL;
+       }
+      else
        {
-         if (pval)
-           *pval = s;
-         if (pidx)
-           *pidx = i;
-         return 0;
+         size_t size = p - url->path;
+         new_url->path = realloc (new_url->path, size + 1);
+         if (!new_url->path)
+           {
+             mu_url_destroy (&new_url);
+             return ENOMEM;
+           }
+         memcpy (new_url->path, url->path, size);
+         new_url->path[size] = 0;
        }
+      *upurl = new_url;
     }
-  return MU_ERR_NOENT;
+  return rc;
 }
+
diff --git a/libmailutils/base/freeitem.c b/libmailutils/url/urlstr.c
similarity index 82%
copy from libmailutils/base/freeitem.c
copy to libmailutils/url/urlstr.c
index ad382a4..31e5197 100644
--- a/libmailutils/base/freeitem.c
+++ b/libmailutils/url/urlstr.c
@@ -19,10 +19,13 @@
 # include <config.h>
 #endif
 #include <stdlib.h>
+#include <mailutils/types.h>
+#include <mailutils/sys/url.h>
 
-/* Default destroy_item function. */
-void
-mu_list_free_item (void *item)
+const char *
+mu_url_to_string (const mu_url_t url)
 {
-  free (item);
+  if (url == NULL || url->name == NULL)
+    return "";
+  return url->name;
 }
diff --git a/libmu_cpp/url.cc b/libmu_cpp/url.cc
index 9c9353c..fe7aedc 100644
--- a/libmu_cpp/url.cc
+++ b/libmu_cpp/url.cc
@@ -54,19 +54,17 @@ Url :: ~Url ()
 void
 Url :: parse ()
 {
-  int status = mu_url_parse (url);
-  if (status)
-    throw Exception ("Url::parse", status);
+  /* FIXME: Remove */
 }
 
-long
+unsigned
 Url :: get_port ()
 {
-  long port;
+  unsigned port;
   int status = mu_url_get_port (url, &port);
   if (status)
     throw Exception ("Url::get_port", status);
-  return port;
+  return (unsigned short) port;
 }
 
 std::string
diff --git a/libproto/imap/folder.c b/libproto/imap/folder.c
index ed5ba54..ce15084 100644
--- a/libproto/imap/folder.c
+++ b/libproto/imap/folder.c
@@ -67,7 +67,7 @@ static struct _mu_record _imap_record =
   MU_IMAP_PRIO,
   MU_IMAP_SCHEME,
   MU_RECORD_DEFAULT,
-  MU_URL_CRED | MU_URL_INET | MU_URL_PATH,
+  MU_URL_SCHEME | MU_URL_CRED | MU_URL_INET | MU_URL_PATH,
   MU_URL_HOST,
   _url_imap_init,     /* url entry.  */
   _mailbox_imap_init, /* Mailbox entry.  */
@@ -91,7 +91,7 @@ static struct _mu_record _imaps_record =
   MU_IMAP_PRIO,
   MU_IMAPS_SCHEME,
   MU_RECORD_DEFAULT,
-  MU_URL_CRED | MU_URL_INET | MU_URL_PATH | MU_URL_PARAM,
+  MU_URL_SCHEME | MU_URL_CRED | MU_URL_INET | MU_URL_PATH | MU_URL_PARAM,
   MU_URL_HOST,
   _url_imaps_init,     /* url entry.  */
   _mailbox_imaps_init, /* Mailbox entry.  */
@@ -629,7 +629,7 @@ folder_imap_open (mu_folder_t folder, int flags)
 {
   f_imap_t f_imap = folder->data;
   const char *host;
-  long port = f_imap->imaps ? MU_IMAPS_PORT : MU_IMAP_PORT;
+  unsigned port = f_imap->imaps ? MU_IMAPS_PORT : MU_IMAP_PORT;
   int status = 0;
 
   /* If we are already open for business, noop.  */
diff --git a/libproto/maildir/folder.c b/libproto/maildir/folder.c
index 657dfa5..d53c526 100644
--- a/libproto/maildir/folder.c
+++ b/libproto/maildir/folder.c
@@ -99,7 +99,7 @@ static struct _mu_record _maildir_record =
   MU_MAILDIR_PRIO,
   MU_MAILDIR_SCHEME,
   MU_RECORD_LOCAL,
-  MU_URL_PATH,
+  MU_URL_SCHEME | MU_URL_PATH,
   MU_URL_PATH,
   mu_url_expand_path, /* Url init.  */
   _mailbox_maildir_init, /* Mailbox init.  */
diff --git a/libproto/mailer/prog.c b/libproto/mailer/prog.c
index d026177..6a3c615 100644
--- a/libproto/mailer/prog.c
+++ b/libproto/mailer/prog.c
@@ -47,7 +47,7 @@ static struct _mu_record _prog_record =
   MU_RECORD_DEFAULT,
   /* FIXME: MU_URL_USER could be used to request running with this
      user privileges. */
-  MU_URL_PATH | MU_URL_QUERY, 
+  MU_URL_SCHEME | MU_URL_PATH | MU_URL_QUERY, 
   MU_URL_PATH,
   _url_prog_init,    /* url init.  */
   _mu_mailer_mailbox_init,  /* Mailbox entry.  */
diff --git a/libproto/mailer/remote.c b/libproto/mailer/remote.c
index ae96cee..7198571 100644
--- a/libproto/mailer/remote.c
+++ b/libproto/mailer/remote.c
@@ -76,7 +76,7 @@ static struct _mu_record _mu_remote_smtp_record = {
   MU_SMTP_PRIO,
   "remote+smtp",
   MU_RECORD_DEFAULT,
-  MU_URL_CRED | MU_URL_INET | MU_URL_PATH | MU_URL_PARAM,
+  MU_URL_SCHEME | MU_URL_CRED | MU_URL_INET | MU_URL_PATH | MU_URL_PARAM,
   MU_URL_HOST,
   _url_remote_smtp_init,       /* url init.  */
   _mu_mailer_mailbox_init,      /* Mailbox init.  */
@@ -108,7 +108,7 @@ static struct _mu_record _mu_remote_sendmail_record =
   MU_SENDMAIL_PRIO,
   "remote+sendmail",
   MU_RECORD_DEFAULT,
-  MU_URL_PATH,
+  MU_URL_SCHEME | MU_URL_PATH,
   MU_URL_PATH,
   _url_remote_sendmail_init,    /* url init.  */
   _mu_mailer_mailbox_init,      /* Mailbox entry.  */
@@ -137,7 +137,7 @@ static struct _mu_record _mu_remote_prog_record =
   MU_PROG_PRIO,
   "remote+prog",
   MU_RECORD_DEFAULT,
-  MU_URL_CRED | MU_URL_PATH | MU_URL_QUERY,
+  MU_URL_SCHEME | MU_URL_CRED | MU_URL_PATH | MU_URL_QUERY,
   MU_URL_PATH,
   _url_remote_prog_init,    /* url init.  */
   _mu_mailer_mailbox_init,  /* Mailbox entry.  */
diff --git a/libproto/mailer/sendmail.c b/libproto/mailer/sendmail.c
index f1ba068..7ab01a0 100644
--- a/libproto/mailer/sendmail.c
+++ b/libproto/mailer/sendmail.c
@@ -271,9 +271,9 @@ static struct _mu_record _sendmail_record =
   MU_SENDMAIL_PRIO,
   MU_SENDMAIL_SCHEME,
   MU_RECORD_DEFAULT,
-  MU_URL_PATH,
-  0, /* Nothing is required in the URL, except scheme. Missing path means
-       using PATH_SENDMAIL. */
+  MU_URL_SCHEME | MU_URL_PATH,
+  MU_URL_SCHEME, /* Nothing is required in the URL, except scheme. 
+                    Missing path means using PATH_SENDMAIL. */
   _url_sendmail_init,    /* url init.  */
   _mu_mailer_mailbox_init,     /* Mailbox entry.  */
   _mu_mailer_sendmail_init, /* Mailer entry.  */
diff --git a/libproto/mailer/smtp.c b/libproto/mailer/smtp.c
index 5b48fce..7196288 100644
--- a/libproto/mailer/smtp.c
+++ b/libproto/mailer/smtp.c
@@ -65,7 +65,7 @@ static struct _mu_record _smtp_record = {
   MU_SMTP_PRIO,
   MU_SMTP_SCHEME,
   MU_RECORD_DEFAULT,
-  MU_URL_CRED | MU_URL_INET | MU_URL_PARAM,
+  MU_URL_SCHEME | MU_URL_CRED | MU_URL_INET | MU_URL_PARAM,
   MU_URL_HOST,
   _url_smtp_init,              /* url init.  */
   _mu_mailer_mailbox_init,     /* Mailbox init.  */
@@ -113,7 +113,7 @@ static int
 smtp_open (mu_mailer_t mailer, int flags)
 {
   const char *host, *auth;
-  long port;
+  unsigned port;
   struct _smtp_mailer *smtp_mailer = mailer->data;
   int rc;
   size_t parmc = 0;
diff --git a/libproto/mailer/smtp_auth.c b/libproto/mailer/smtp_auth.c
index 48b5a91..a0d8a87 100644
--- a/libproto/mailer/smtp_auth.c
+++ b/libproto/mailer/smtp_auth.c
@@ -77,15 +77,6 @@ _mu_smtp_fixup_params (mu_smtp_t smtp)
       return rc;
     }
 
-  rc = mu_url_parse (url);
-  if (rc)
-    {
-      mu_diag_output (MU_DIAG_ERROR, "cannot parse URL: %s",
-                     mu_strerror (rc));
-      mu_url_destroy (&url);
-      return rc;
-    }
-
   if (!(flags & _HAS_USERNAME))
     {
       rc = mu_url_sget_user (url, &str);
diff --git a/libproto/mbox/folder.c b/libproto/mbox/folder.c
index c6a9d51..95506e3 100644
--- a/libproto/mbox/folder.c
+++ b/libproto/mbox/folder.c
@@ -101,7 +101,7 @@ static struct _mu_record _mbox_record =
   MU_MBOX_PRIO,
   MU_MBOX_SCHEME,
   MU_RECORD_LOCAL,
-  MU_URL_PATH,
+  MU_URL_SCHEME | MU_URL_PATH,
   MU_URL_PATH,
   mu_url_expand_path, /* URL init.  */
   _mailbox_mbox_init, /* Mailbox init.  */
diff --git a/libproto/mh/folder.c b/libproto/mh/folder.c
index f5feb1f..90291d0 100644
--- a/libproto/mh/folder.c
+++ b/libproto/mh/folder.c
@@ -139,7 +139,7 @@ static struct _mu_record _mh_record =
   MU_MH_PRIO,
   MU_MH_SCHEME,
   MU_RECORD_LOCAL,
-  MU_URL_PATH,
+  MU_URL_SCHEME | MU_URL_PATH,
   MU_URL_PATH,
   mu_url_expand_path, /* Url init.  */
   _mailbox_mh_init, /* Mailbox init.  */
diff --git a/libproto/nntp/folder.c b/libproto/nntp/folder.c
index 071ffae..cac6fb3 100644
--- a/libproto/nntp/folder.c
+++ b/libproto/nntp/folder.c
@@ -46,7 +46,7 @@ static struct _mu_record _nntp_record =
   MU_NNTP_PRIO,
   MU_NNTP_URL_SCHEME,
   MU_RECORD_DEFAULT,
-  MU_URL_CRED | MU_URL_INET | MU_URL_PATH,
+  MU_URL_SCHEME | MU_URL_CRED | MU_URL_INET | MU_URL_PATH,
   MU_URL_HOST,
   _nntp_url_init, /* Url init.  */
   _nntp_mailbox_init, /* Mailbox init.  */
@@ -104,7 +104,7 @@ nntp_folder_open (mu_folder_t folder, int flags)
   f_nntp_t f_nntp = folder->data;
   mu_stream_t carrier = NULL;
   const char *host;
-  long port = MU_NNTP_DEFAULT_PORT; /* default nntp port.  */
+  unsigned port = MU_NNTP_DEFAULT_PORT; /* default nntp port.  */
   int status = 0;
 
   /* If we are already open for business, noop.  */
diff --git a/libproto/pop/folder.c b/libproto/pop/folder.c
index 59ad1cc..4a26dbe 100644
--- a/libproto/pop/folder.c
+++ b/libproto/pop/folder.c
@@ -48,7 +48,7 @@ static struct _mu_record _pop_record =
   MU_POP_PRIO,
   MU_POP_SCHEME,
   MU_RECORD_DEFAULT,
-  MU_URL_CRED | MU_URL_INET | MU_URL_PARAM,
+  MU_URL_SCHEME | MU_URL_CRED | MU_URL_INET | MU_URL_PARAM,
   MU_URL_HOST,
   _url_pop_init, /* Url init.  */
   _mailbox_pop_init, /* Mailbox init.  */
@@ -69,7 +69,7 @@ static struct _mu_record _pops_record =
   MU_POP_PRIO,
   MU_POPS_SCHEME,
   MU_RECORD_DEFAULT,
-  MU_URL_CRED | MU_URL_INET,
+  MU_URL_SCHEME | MU_URL_CRED | MU_URL_INET,
   MU_URL_HOST,
   _url_pops_init, /* Url init.  */
   _mailbox_pops_init, /* Mailbox init.  */
diff --git a/libproto/pop/mbox.c b/libproto/pop/mbox.c
index 6865f6f..9b658bc 100644
--- a/libproto/pop/mbox.c
+++ b/libproto/pop/mbox.c
@@ -105,7 +105,7 @@ pop_open (mu_mailbox_t mbox, int flags)
   struct _pop3_mailbox *mpd = mbox->data;
   int status;
   const char *host;
-  long port = mpd->pops ? MU_POPS_PORT : MU_POP_PORT;
+  unsigned port = mpd->pops ? MU_POPS_PORT : MU_POP_PORT;
   mu_stream_t stream;
   
   /* Sanity checks. */
diff --git a/maidag/deliver.c b/maidag/deliver.c
index 5a65259..25a7ab6 100644
--- a/maidag/deliver.c
+++ b/maidag/deliver.c
@@ -385,13 +385,6 @@ do_delivery (mu_url_t url, mu_message_t msg, const char 
*name, char **errp)
                        auth->mailbox, mu_strerror (status));
          return exit_code = EX_UNAVAILABLE;
        }
-      status = mu_url_parse (url);
-      if (status)
-       {
-         maidag_error (_("error parsing URL %s: %s"),
-                       auth->mailbox, mu_strerror (status));
-         return exit_code = EX_UNAVAILABLE;
-       }
     }      
 
   status = mu_mailbox_create_from_url (&mbox, url);
@@ -437,14 +430,6 @@ deliver_to_url (mu_message_t msg, char *dest_id, char 
**errp)
                    mu_strerror (status));
       return EX_NOUSER;
     }
-  status = mu_url_parse (url);
-  if (status)
-    {
-      maidag_error (_("%s: cannot parse url: %s"), dest_id,
-                   mu_strerror (status));
-      mu_url_destroy (&url);
-      return EX_NOUSER;
-    }
   status = mu_url_sget_user (url, &name);
   if (status == MU_ERR_NOENT)
     name = NULL;
diff --git a/mu/wicket.c b/mu/wicket.c
index 2615cdf..2ea8eec 100644
--- a/mu/wicket.c
+++ b/mu/wicket.c
@@ -75,6 +75,10 @@ wicket_match (mu_stream_t stream, const char *str)
   int rc, ret;
   mu_url_t u, url;
   struct mu_debug_locus loc;
+  int flags = MU_URL_PARSE_ALL;
+
+  if (wicket_verbose > 2)
+    flags &= ~MU_URL_PARSE_HIDEPASS;
   
   rc = mu_url_create (&u, str);
   if (rc)
@@ -82,12 +86,6 @@ wicket_match (mu_stream_t stream, const char *str)
       mu_diag_funcall (MU_DIAG_ERROR, "mu_url_create", str, rc);
       return 2;
     }
-  rc = mu_url_parse (u);
-  if (rc)
-    {
-      mu_diag_funcall (MU_DIAG_ERROR, "mu_url_parse", str, rc);
-      return 2;
-    }
 
   rc = mu_stream_seek (stream, 0, MU_SEEK_SET, NULL);
   if (rc)
@@ -97,7 +95,7 @@ wicket_match (mu_stream_t stream, const char *str)
     }
   loc.file = wicket_file;
   loc.line = 0;
-  rc = mu_wicket_stream_match_url (stream, &loc, u, &url);
+  rc = mu_wicket_stream_match_url (stream, &loc, u, flags, &url);
   switch (rc)
     {
     case 0:
@@ -106,27 +104,7 @@ wicket_match (mu_stream_t stream, const char *str)
        {
          printf ("%s: %s:%d", str, loc.file, loc.line);
          if (wicket_verbose > 1)
-           {
-             printf (": %s", mu_url_to_string (url));
-             if (wicket_verbose > 2)
-               {
-                 mu_secret_t s;
-                 rc = mu_url_get_secret (url, &s);
-                 if (rc == 0)
-                   {
-                     printf (": %s", mu_secret_password (s));
-                     mu_secret_password_unref (s);
-                     mu_secret_unref (s);
-                   }
-                 else if (rc == MU_ERR_NOENT)
-                   printf (": [%s]", _("no password"));
-                 else
-                   {
-                     printf (": [error: %s]", mu_strerror (rc));
-                     ret = 2;
-                   }
-               }
-           }
+           printf (": %s", mu_url_to_string (url));
          putchar ('\n');
        }
       break;
diff --git a/python/libmu_py/url.c b/python/libmu_py/url.c
index f1b7eee..0d7875e 100644
--- a/python/libmu_py/url.c
+++ b/python/libmu_py/url.c
@@ -102,6 +102,7 @@ api_url_destroy (PyObject *self, PyObject *args)
   return _ro (Py_None);
 }
 
+/* FIXME: Remove */
 static PyObject *
 api_url_parse (PyObject *self, PyObject *args)
 {
@@ -111,22 +112,21 @@ api_url_parse (PyObject *self, PyObject *args)
   if (!PyArg_ParseTuple (args, "O!", &PyUrlType, &py_url))
     return NULL;
 
-  status = mu_url_parse (py_url->url);
-  return _ro (PyInt_FromLong (status));
+  return _ro (0);
 }
 
 static PyObject *
 api_url_get_port (PyObject *self, PyObject *args)
 {
   int status;
-  long port;
+  unsigned port;
   PyUrl *py_url;
 
   if (!PyArg_ParseTuple (args, "O!", &PyUrlType, &py_url))
     return NULL;
 
   status = mu_url_get_port (py_url->url, &port);
-  return status_object (status, PyInt_FromLong (port));
+  return status_object (status, PyInt_FromLong ((long)port));
 }
 
 static PyObject *


hooks/post-receive
-- 
GNU Mailutils



reply via email to

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