summaryrefslogtreecommitdiff
path: root/libmailutils
diff options
context:
space:
mode:
Diffstat (limited to 'libmailutils')
-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
37 files changed, 2038 insertions, 1307 deletions
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;
- }
- 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/alain@qnx.com
-
-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 3e808c0ea..afdb87512 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 f6e75c03d..fe918230e 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 d95ce2d96..0677e88ff 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 59559ebe8..01fb6d31e 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 7bc801b2c..863566c25 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 b53511a94..c719be81f 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 3f11adef4..485df4a67 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/xdecode.c b/libmailutils/string/xdecode.c
new file mode 100644
index 000000000..e802bf67c
--- /dev/null
+++ b/libmailutils/string/xdecode.c
@@ -0,0 +1,73 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 1999, 2000, 2001, 2002, 2003, 2005, 2006, 2007, 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/>. */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+#include <mailutils/errno.h>
+#include <mailutils/util.h>
+
+/* From RFC 1738, section 2.2 */
+void
+mu_str_url_decode_inline (char *s)
+{
+ 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 92fd4f166..c87753c05 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 b6215cbf9..57857dafc 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/url/Makefile.am b/libmailutils/url/Makefile.am
new file mode 100644
index 000000000..51e3e6483
--- /dev/null
+++ b/libmailutils/url/Makefile.am
@@ -0,0 +1,45 @@
+# 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/>.
+
+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
+
diff --git a/libmailutils/url/accessor.h b/libmailutils/url/accessor.h
new file mode 100644
index 000000000..de3871152
--- /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 000000000..7190b4212
--- /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 000000000..674a52469
--- /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 000000000..9aca0e217
--- /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/libmailutils/url/destroy.c b/libmailutils/url/destroy.c
new file mode 100644
index 000000000..a46dc3150
--- /dev/null
+++ b/libmailutils/url/destroy.c
@@ -0,0 +1,74 @@
+/* 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/argcv.h>
+#include <mailutils/secret.h>
+#include <mailutils/errno.h>
+#include <mailutils/sys/url.h>
+
+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;
+ }
+}
diff --git a/libmailutils/url/dup.c b/libmailutils/url/dup.c
new file mode 100644
index 000000000..d9a738341
--- /dev/null
+++ b/libmailutils/url/dup.c
@@ -0,0 +1,56 @@
+/* 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/sys/url.h>
+
+int
+mu_url_dup (mu_url_t old_url, mu_url_t *new_url)
+{
+ 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;
+}
diff --git a/libmailutils/url/expand.c b/libmailutils/url/expand.c
new file mode 100644
index 000000000..bb2ef9584
--- /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/url/flag.c b/libmailutils/url/flag.c
new file mode 100644
index 000000000..bf06f6884
--- /dev/null
+++ b/libmailutils/url/flag.c
@@ -0,0 +1,40 @@
+/* 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 <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)
+{
+ 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 000000000..b9650a53c
--- /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 000000000..6de6b564e
--- /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 000000000..c2be8234b
--- /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 000000000..3f906b9b1
--- /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 000000000..9b211bf8f
--- /dev/null
+++ b/libmailutils/url/get-portstr.c
@@ -0,0 +1,2 @@
+#define URL_PART portstr
+#include "accessor.h"
diff --git a/libmailutils/url/get-query.c b/libmailutils/url/get-query.c
new file mode 100644
index 000000000..cf74922da
--- /dev/null
+++ b/libmailutils/url/get-query.c
@@ -0,0 +1,72 @@
+/* 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>
+
+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;
+}
+
diff --git a/libmailutils/url/get-scheme.c b/libmailutils/url/get-scheme.c
new file mode 100644
index 000000000..983902ea4
--- /dev/null
+++ b/libmailutils/url/get-scheme.c
@@ -0,0 +1,2 @@
+#define URL_PART scheme
+#include "accessor.h"
diff --git a/libmailutils/url/get-secret.c b/libmailutils/url/get-secret.c
new file mode 100644
index 000000000..34fb2291b
--- /dev/null
+++ b/libmailutils/url/get-secret.c
@@ -0,0 +1,44 @@
+/* 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/secret.h>
+#include <mailutils/sys/url.h>
+
+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;
+}
diff --git a/libmailutils/url/get-user.c b/libmailutils/url/get-user.c
new file mode 100644
index 000000000..5a3ab791f
--- /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 000000000..4932f4577
--- /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/libmailutils/url/port.c b/libmailutils/url/port.c
new file mode 100644
index 000000000..88b7dd136
--- /dev/null
+++ b/libmailutils/url/port.c
@@ -0,0 +1,53 @@
+/* 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>
+
+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
+mu_url_is_same_port (mu_url_t url1, mu_url_t url2)
+{
+ unsigned p1 = 0, p2 = 0;
+
+ mu_url_get_port (url1, &p1);
+ mu_url_get_port (url2, &p2);
+ return (p1 == p2);
+}
+
diff --git a/libmailutils/url/scheme.c b/libmailutils/url/scheme.c
new file mode 100644
index 000000000..e68fa9192
--- /dev/null
+++ b/libmailutils/url/scheme.c
@@ -0,0 +1,55 @@
+/* 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>
+
+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;
+}
+
diff --git a/libmailutils/url/uplevel.c b/libmailutils/url/uplevel.c
new file mode 100644
index 000000000..749fe1fae
--- /dev/null
+++ b/libmailutils/url/uplevel.c
@@ -0,0 +1,71 @@
+/* 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/sys/url.h>
+
+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;
+}
+
diff --git a/libmailutils/url/urlstr.c b/libmailutils/url/urlstr.c
new file mode 100644
index 000000000..31e5197f8
--- /dev/null
+++ b/libmailutils/url/urlstr.c
@@ -0,0 +1,31 @@
+/* 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 <stdlib.h>
+#include <mailutils/types.h>
+#include <mailutils/sys/url.h>
+
+const char *
+mu_url_to_string (const mu_url_t url)
+{
+ if (url == NULL || url->name == NULL)
+ return "";
+ return url->name;
+}

Return to:

Send suggestions and report system problems to the System administrator.