Commit 3327a23a 3327a23a49e532c068972a0b2d64021361540f7b by Sergey Poznyakoff

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.
1 parent 6203ae65
Showing 62 changed files with 2126 additions and 1420 deletions
......@@ -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
......
......@@ -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 *)
......
......@@ -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)
......
......@@ -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);
......
......@@ -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 ();
......
......@@ -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 */
......
......@@ -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 *);
......
......@@ -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
}
......
......@@ -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 */
......
......@@ -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@
......
......@@ -61,7 +61,6 @@ libbase_la_SOURCES = \
tempfile.c\
ticket.c\
tilde.c\
url.c\
usremail.c\
vartab.c\
version.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;
}
......
/* 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;
}
......@@ -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;
......
......@@ -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;
......
......@@ -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;
......
......@@ -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;
......
......@@ -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, '\''))
......
......@@ -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,
......
......@@ -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
......
/* 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;
}
......@@ -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);
......
......@@ -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:
......
# 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
/* 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;
}
/* 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;
}
/* 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);
}
/* 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;
}
/* 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;
}
}
/* 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;
}
/* 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;
}
/* 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;
}
#define URL_PART auth
#include "accessor.h"
#define URL_PART host
#include "accessor.h"
/* 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;
}
#define URL_PART path
#include "accessor.h"
#define URL_PART portstr
#include "accessor.h"
/* 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;
}
#define URL_PART scheme
#include "accessor.h"
/* 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;
}
#define URL_PART user
#include "accessor.h"
/* 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;
}
/* 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);
}
/* 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;
}
/* 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;
}
/* 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;
}
......@@ -54,19 +54,17 @@ Url :: ~Url ()
void
Url :: parse ()
{
int status = mu_url_parse (url);
if (status)
throw Exception ("Url::parse", status);
/* FIXME: Remove */
}
long
unsigned
Url :: get_port ()
{
long port;
unsigned port;
int status = mu_url_get_port (url, &port);
if (status)
throw Exception ("Url::get_port", status);
return port;
return (unsigned short) port;
}
std::string
......
......@@ -67,7 +67,7 @@ static struct _mu_record _imap_record =
MU_IMAP_PRIO,
MU_IMAP_SCHEME,
MU_RECORD_DEFAULT,
MU_URL_CRED | MU_URL_INET | MU_URL_PATH,
MU_URL_SCHEME | MU_URL_CRED | MU_URL_INET | MU_URL_PATH,
MU_URL_HOST,
_url_imap_init, /* url entry. */
_mailbox_imap_init, /* Mailbox entry. */
......@@ -91,7 +91,7 @@ static struct _mu_record _imaps_record =
MU_IMAP_PRIO,
MU_IMAPS_SCHEME,
MU_RECORD_DEFAULT,
MU_URL_CRED | MU_URL_INET | MU_URL_PATH | MU_URL_PARAM,
MU_URL_SCHEME | MU_URL_CRED | MU_URL_INET | MU_URL_PATH | MU_URL_PARAM,
MU_URL_HOST,
_url_imaps_init, /* url entry. */
_mailbox_imaps_init, /* Mailbox entry. */
......@@ -629,7 +629,7 @@ folder_imap_open (mu_folder_t folder, int flags)
{
f_imap_t f_imap = folder->data;
const char *host;
long port = f_imap->imaps ? MU_IMAPS_PORT : MU_IMAP_PORT;
unsigned port = f_imap->imaps ? MU_IMAPS_PORT : MU_IMAP_PORT;
int status = 0;
/* If we are already open for business, noop. */
......
......@@ -99,7 +99,7 @@ static struct _mu_record _maildir_record =
MU_MAILDIR_PRIO,
MU_MAILDIR_SCHEME,
MU_RECORD_LOCAL,
MU_URL_PATH,
MU_URL_SCHEME | MU_URL_PATH,
MU_URL_PATH,
mu_url_expand_path, /* Url init. */
_mailbox_maildir_init, /* Mailbox init. */
......
......@@ -47,7 +47,7 @@ static struct _mu_record _prog_record =
MU_RECORD_DEFAULT,
/* FIXME: MU_URL_USER could be used to request running with this
user privileges. */
MU_URL_PATH | MU_URL_QUERY,
MU_URL_SCHEME | MU_URL_PATH | MU_URL_QUERY,
MU_URL_PATH,
_url_prog_init, /* url init. */
_mu_mailer_mailbox_init, /* Mailbox entry. */
......
......@@ -76,7 +76,7 @@ static struct _mu_record _mu_remote_smtp_record = {
MU_SMTP_PRIO,
"remote+smtp",
MU_RECORD_DEFAULT,
MU_URL_CRED | MU_URL_INET | MU_URL_PATH | MU_URL_PARAM,
MU_URL_SCHEME | MU_URL_CRED | MU_URL_INET | MU_URL_PATH | MU_URL_PARAM,
MU_URL_HOST,
_url_remote_smtp_init, /* url init. */
_mu_mailer_mailbox_init, /* Mailbox init. */
......@@ -108,7 +108,7 @@ static struct _mu_record _mu_remote_sendmail_record =
MU_SENDMAIL_PRIO,
"remote+sendmail",
MU_RECORD_DEFAULT,
MU_URL_PATH,
MU_URL_SCHEME | MU_URL_PATH,
MU_URL_PATH,
_url_remote_sendmail_init, /* url init. */
_mu_mailer_mailbox_init, /* Mailbox entry. */
......@@ -137,7 +137,7 @@ static struct _mu_record _mu_remote_prog_record =
MU_PROG_PRIO,
"remote+prog",
MU_RECORD_DEFAULT,
MU_URL_CRED | MU_URL_PATH | MU_URL_QUERY,
MU_URL_SCHEME | MU_URL_CRED | MU_URL_PATH | MU_URL_QUERY,
MU_URL_PATH,
_url_remote_prog_init, /* url init. */
_mu_mailer_mailbox_init, /* Mailbox entry. */
......
......@@ -271,9 +271,9 @@ static struct _mu_record _sendmail_record =
MU_SENDMAIL_PRIO,
MU_SENDMAIL_SCHEME,
MU_RECORD_DEFAULT,
MU_URL_PATH,
0, /* Nothing is required in the URL, except scheme. Missing path means
using PATH_SENDMAIL. */
MU_URL_SCHEME | MU_URL_PATH,
MU_URL_SCHEME, /* Nothing is required in the URL, except scheme.
Missing path means using PATH_SENDMAIL. */
_url_sendmail_init, /* url init. */
_mu_mailer_mailbox_init, /* Mailbox entry. */
_mu_mailer_sendmail_init, /* Mailer entry. */
......
......@@ -65,7 +65,7 @@ static struct _mu_record _smtp_record = {
MU_SMTP_PRIO,
MU_SMTP_SCHEME,
MU_RECORD_DEFAULT,
MU_URL_CRED | MU_URL_INET | MU_URL_PARAM,
MU_URL_SCHEME | MU_URL_CRED | MU_URL_INET | MU_URL_PARAM,
MU_URL_HOST,
_url_smtp_init, /* url init. */
_mu_mailer_mailbox_init, /* Mailbox init. */
......@@ -113,7 +113,7 @@ static int
smtp_open (mu_mailer_t mailer, int flags)
{
const char *host, *auth;
long port;
unsigned port;
struct _smtp_mailer *smtp_mailer = mailer->data;
int rc;
size_t parmc = 0;
......
......@@ -77,15 +77,6 @@ _mu_smtp_fixup_params (mu_smtp_t smtp)
return rc;
}
rc = mu_url_parse (url);
if (rc)
{
mu_diag_output (MU_DIAG_ERROR, "cannot parse URL: %s",
mu_strerror (rc));
mu_url_destroy (&url);
return rc;
}
if (!(flags & _HAS_USERNAME))
{
rc = mu_url_sget_user (url, &str);
......
......@@ -101,7 +101,7 @@ static struct _mu_record _mbox_record =
MU_MBOX_PRIO,
MU_MBOX_SCHEME,
MU_RECORD_LOCAL,
MU_URL_PATH,
MU_URL_SCHEME | MU_URL_PATH,
MU_URL_PATH,
mu_url_expand_path, /* URL init. */
_mailbox_mbox_init, /* Mailbox init. */
......
......@@ -139,7 +139,7 @@ static struct _mu_record _mh_record =
MU_MH_PRIO,
MU_MH_SCHEME,
MU_RECORD_LOCAL,
MU_URL_PATH,
MU_URL_SCHEME | MU_URL_PATH,
MU_URL_PATH,
mu_url_expand_path, /* Url init. */
_mailbox_mh_init, /* Mailbox init. */
......
......@@ -46,7 +46,7 @@ static struct _mu_record _nntp_record =
MU_NNTP_PRIO,
MU_NNTP_URL_SCHEME,
MU_RECORD_DEFAULT,
MU_URL_CRED | MU_URL_INET | MU_URL_PATH,
MU_URL_SCHEME | MU_URL_CRED | MU_URL_INET | MU_URL_PATH,
MU_URL_HOST,
_nntp_url_init, /* Url init. */
_nntp_mailbox_init, /* Mailbox init. */
......@@ -104,7 +104,7 @@ nntp_folder_open (mu_folder_t folder, int flags)
f_nntp_t f_nntp = folder->data;
mu_stream_t carrier = NULL;
const char *host;
long port = MU_NNTP_DEFAULT_PORT; /* default nntp port. */
unsigned port = MU_NNTP_DEFAULT_PORT; /* default nntp port. */
int status = 0;
/* If we are already open for business, noop. */
......
......@@ -48,7 +48,7 @@ static struct _mu_record _pop_record =
MU_POP_PRIO,
MU_POP_SCHEME,
MU_RECORD_DEFAULT,
MU_URL_CRED | MU_URL_INET | MU_URL_PARAM,
MU_URL_SCHEME | MU_URL_CRED | MU_URL_INET | MU_URL_PARAM,
MU_URL_HOST,
_url_pop_init, /* Url init. */
_mailbox_pop_init, /* Mailbox init. */
......@@ -69,7 +69,7 @@ static struct _mu_record _pops_record =
MU_POP_PRIO,
MU_POPS_SCHEME,
MU_RECORD_DEFAULT,
MU_URL_CRED | MU_URL_INET,
MU_URL_SCHEME | MU_URL_CRED | MU_URL_INET,
MU_URL_HOST,
_url_pops_init, /* Url init. */
_mailbox_pops_init, /* Mailbox init. */
......
......@@ -105,7 +105,7 @@ pop_open (mu_mailbox_t mbox, int flags)
struct _pop3_mailbox *mpd = mbox->data;
int status;
const char *host;
long port = mpd->pops ? MU_POPS_PORT : MU_POP_PORT;
unsigned port = mpd->pops ? MU_POPS_PORT : MU_POP_PORT;
mu_stream_t stream;
/* Sanity checks. */
......
......@@ -385,13 +385,6 @@ do_delivery (mu_url_t url, mu_message_t msg, const char *name, char **errp)
auth->mailbox, mu_strerror (status));
return exit_code = EX_UNAVAILABLE;
}
status = mu_url_parse (url);
if (status)
{
maidag_error (_("error parsing URL %s: %s"),
auth->mailbox, mu_strerror (status));
return exit_code = EX_UNAVAILABLE;
}
}
status = mu_mailbox_create_from_url (&mbox, url);
......@@ -437,14 +430,6 @@ deliver_to_url (mu_message_t msg, char *dest_id, char **errp)
mu_strerror (status));
return EX_NOUSER;
}
status = mu_url_parse (url);
if (status)
{
maidag_error (_("%s: cannot parse url: %s"), dest_id,
mu_strerror (status));
mu_url_destroy (&url);
return EX_NOUSER;
}
status = mu_url_sget_user (url, &name);
if (status == MU_ERR_NOENT)
name = NULL;
......
......@@ -75,6 +75,10 @@ wicket_match (mu_stream_t stream, const char *str)
int rc, ret;
mu_url_t u, url;
struct mu_debug_locus loc;
int flags = MU_URL_PARSE_ALL;
if (wicket_verbose > 2)
flags &= ~MU_URL_PARSE_HIDEPASS;
rc = mu_url_create (&u, str);
if (rc)
......@@ -82,12 +86,6 @@ wicket_match (mu_stream_t stream, const char *str)
mu_diag_funcall (MU_DIAG_ERROR, "mu_url_create", str, rc);
return 2;
}
rc = mu_url_parse (u);
if (rc)
{
mu_diag_funcall (MU_DIAG_ERROR, "mu_url_parse", str, rc);
return 2;
}
rc = mu_stream_seek (stream, 0, MU_SEEK_SET, NULL);
if (rc)
......@@ -97,7 +95,7 @@ wicket_match (mu_stream_t stream, const char *str)
}
loc.file = wicket_file;
loc.line = 0;
rc = mu_wicket_stream_match_url (stream, &loc, u, &url);
rc = mu_wicket_stream_match_url (stream, &loc, u, flags, &url);
switch (rc)
{
case 0:
......@@ -106,27 +104,7 @@ wicket_match (mu_stream_t stream, const char *str)
{
printf ("%s: %s:%d", str, loc.file, loc.line);
if (wicket_verbose > 1)
{
printf (": %s", mu_url_to_string (url));
if (wicket_verbose > 2)
{
mu_secret_t s;
rc = mu_url_get_secret (url, &s);
if (rc == 0)
{
printf (": %s", mu_secret_password (s));
mu_secret_password_unref (s);
mu_secret_unref (s);
}
else if (rc == MU_ERR_NOENT)
printf (": [%s]", _("no password"));
else
{
printf (": [error: %s]", mu_strerror (rc));
ret = 2;
}
}
}
printf (": %s", mu_url_to_string (url));
putchar ('\n');
}
break;
......
......@@ -102,6 +102,7 @@ api_url_destroy (PyObject *self, PyObject *args)
return _ro (Py_None);
}
/* FIXME: Remove */
static PyObject *
api_url_parse (PyObject *self, PyObject *args)
{
......@@ -111,22 +112,21 @@ api_url_parse (PyObject *self, PyObject *args)
if (!PyArg_ParseTuple (args, "O!", &PyUrlType, &py_url))
return NULL;
status = mu_url_parse (py_url->url);
return _ro (PyInt_FromLong (status));
return _ro (0);
}
static PyObject *
api_url_get_port (PyObject *self, PyObject *args)
{
int status;
long port;
unsigned port;
PyUrl *py_url;
if (!PyArg_ParseTuple (args, "O!", &PyUrlType, &py_url))
return NULL;
status = mu_url_get_port (py_url->url, &port);
return status_object (status, PyInt_FromLong (port));
return status_object (status, PyInt_FromLong ((long)port));
}
static PyObject *
......