diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2010-10-26 13:00:52 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2010-10-26 13:36:28 +0300 |
commit | 3327a23a49e532c068972a0b2d64021361540f7b (patch) | |
tree | b2d6508005ac8343a54638142c4f8234f7202441 | |
parent | 6203ae65f53758a4b893e6e176be7c153a31bef0 (diff) | |
download | mailutils-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.
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; |