summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2010-10-26 13:00:52 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2010-10-26 13:36:28 +0300
commit3327a23a49e532c068972a0b2d64021361540f7b (patch)
treeb2d6508005ac8343a54638142c4f8234f7202441
parent6203ae65f53758a4b893e6e176be7c153a31bef0 (diff)
downloadmailutils-3327a23a49e532c068972a0b2d64021361540f7b.tar.gz
mailutils-3327a23a49e532c068972a0b2d64021361540f7b.tar.bz2
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.
-rw-r--r--configure.ac1
-rw-r--r--doc/texinfo/url.texi2
-rw-r--r--imap4d/imap4d.c9
-rw-r--r--include/mailutils/auth.h4
-rw-r--r--include/mailutils/cpp/url.h2
-rw-r--r--include/mailutils/stream.h6
-rw-r--r--include/mailutils/sys/url.h6
-rw-r--r--include/mailutils/url.h52
-rw-r--r--include/mailutils/util.h3
-rw-r--r--libmailutils/Makefile.am5
-rw-r--r--libmailutils/base/Makefile.am1
-rw-r--r--libmailutils/base/registrar.c4
-rw-r--r--libmailutils/base/url.c1254
-rw-r--r--libmailutils/base/wicket.c20
-rw-r--r--libmailutils/mailbox/folder.c4
-rw-r--r--libmailutils/mailbox/mailbox.c8
-rw-r--r--libmailutils/mailer/mailer.c4
-rw-r--r--libmailutils/mime/mimehdr.c8
-rw-r--r--libmailutils/stream/tcp.c11
-rw-r--r--libmailutils/string/Makefile.am3
-rw-r--r--libmailutils/string/xdecode.c73
-rw-r--r--libmailutils/tests/url-parse.c9
-rw-r--r--libmailutils/tests/wicket.c7
-rw-r--r--libmailutils/url/Makefile.am45
-rw-r--r--libmailutils/url/accessor.h143
-rw-r--r--libmailutils/url/copy.c145
-rw-r--r--libmailutils/url/create.c525
-rw-r--r--libmailutils/url/decode.c118
-rw-r--r--libmailutils/url/destroy.c74
-rw-r--r--libmailutils/url/dup.c56
-rw-r--r--libmailutils/url/expand.c216
-rw-r--r--libmailutils/url/flag.c40
-rw-r--r--libmailutils/url/get-auth.c3
-rw-r--r--libmailutils/url/get-host.c2
-rw-r--r--libmailutils/url/get-param.c131
-rw-r--r--libmailutils/url/get-path.c2
-rw-r--r--libmailutils/url/get-portstr.c2
-rw-r--r--libmailutils/url/get-query.c72
-rw-r--r--libmailutils/url/get-scheme.c2
-rw-r--r--libmailutils/url/get-secret.c44
-rw-r--r--libmailutils/url/get-user.c2
-rw-r--r--libmailutils/url/match.c102
-rw-r--r--libmailutils/url/port.c53
-rw-r--r--libmailutils/url/scheme.c55
-rw-r--r--libmailutils/url/uplevel.c71
-rw-r--r--libmailutils/url/urlstr.c31
-rw-r--r--libmu_cpp/url.cc10
-rw-r--r--libproto/imap/folder.c6
-rw-r--r--libproto/maildir/folder.c2
-rw-r--r--libproto/mailer/prog.c2
-rw-r--r--libproto/mailer/remote.c6
-rw-r--r--libproto/mailer/sendmail.c6
-rw-r--r--libproto/mailer/smtp.c4
-rw-r--r--libproto/mailer/smtp_auth.c9
-rw-r--r--libproto/mbox/folder.c2
-rw-r--r--libproto/mh/folder.c2
-rw-r--r--libproto/nntp/folder.c4
-rw-r--r--libproto/pop/folder.c4
-rw-r--r--libproto/pop/mbox.c2
-rw-r--r--maidag/deliver.c15
-rw-r--r--mu/wicket.c34
-rw-r--r--python/libmu_py/url.c8
62 files changed, 2126 insertions, 1420 deletions
diff --git a/configure.ac b/configure.ac
index 27ff3f64a..690171bcf 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 267a89f7a..139973131 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
-@deftypefun int mu_url_get_port (const mu_url_t, long *)
+@deftypefun 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 c80af2b7e..cbadb83d7 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 b3b7be357..3433b6173 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 dd7d06578..b3b71387f 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 d951f3425..bb141860f 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 f782bb0c8..8e8019714 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 b8745bbe9..dc4801dd2 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 3af373cc6..9d3fff40c 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 f13085f32..454962bd3 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 196344bb7..c51c947be 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 da43bff5e..fc31b90b9 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 96345f056..000000000
--- 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;