From 3327a23a49e532c068972a0b2d64021361540f7b Mon Sep 17 00:00:00 2001 From: Sergey Poznyakoff Date: Tue, 26 Oct 2010 13:00:52 +0300 Subject: 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): 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. --- libmailutils/url/Makefile.am | 45 ++++ libmailutils/url/accessor.h | 143 +++++++++++ libmailutils/url/copy.c | 145 ++++++++++++ libmailutils/url/create.c | 525 +++++++++++++++++++++++++++++++++++++++++ libmailutils/url/decode.c | 118 +++++++++ libmailutils/url/destroy.c | 74 ++++++ libmailutils/url/dup.c | 56 +++++ libmailutils/url/expand.c | 216 +++++++++++++++++ libmailutils/url/flag.c | 40 ++++ libmailutils/url/get-auth.c | 3 + libmailutils/url/get-host.c | 2 + libmailutils/url/get-param.c | 131 ++++++++++ libmailutils/url/get-path.c | 2 + libmailutils/url/get-portstr.c | 2 + libmailutils/url/get-query.c | 72 ++++++ libmailutils/url/get-scheme.c | 2 + libmailutils/url/get-secret.c | 44 ++++ libmailutils/url/get-user.c | 2 + libmailutils/url/match.c | 102 ++++++++ libmailutils/url/port.c | 53 +++++ libmailutils/url/scheme.c | 55 +++++ libmailutils/url/uplevel.c | 71 ++++++ libmailutils/url/urlstr.c | 31 +++ 23 files changed, 1934 insertions(+) create mode 100644 libmailutils/url/Makefile.am create mode 100644 libmailutils/url/accessor.h create mode 100644 libmailutils/url/copy.c create mode 100644 libmailutils/url/create.c create mode 100644 libmailutils/url/decode.c create mode 100644 libmailutils/url/destroy.c create mode 100644 libmailutils/url/dup.c create mode 100644 libmailutils/url/expand.c create mode 100644 libmailutils/url/flag.c create mode 100644 libmailutils/url/get-auth.c create mode 100644 libmailutils/url/get-host.c create mode 100644 libmailutils/url/get-param.c create mode 100644 libmailutils/url/get-path.c create mode 100644 libmailutils/url/get-portstr.c create mode 100644 libmailutils/url/get-query.c create mode 100644 libmailutils/url/get-scheme.c create mode 100644 libmailutils/url/get-secret.c create mode 100644 libmailutils/url/get-user.c create mode 100644 libmailutils/url/match.c create mode 100644 libmailutils/url/port.c create mode 100644 libmailutils/url/scheme.c create mode 100644 libmailutils/url/uplevel.c create mode 100644 libmailutils/url/urlstr.c (limited to 'libmailutils/url') 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 +# . + +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 + . */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#ifdef HAVE_STRINGS_H +# include +#endif + +#include +#include +#include +#include +#include + +/* 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 + . */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#ifdef HAVE_STRINGS_H +# include +#endif + +#include +#include +#include +#include +#include + +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 + . */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include +#ifdef HAVE_STRINGS_H +# include +#endif +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +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: + : + or + :;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 + . */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#ifdef HAVE_STRINGS_H +# include +#endif + +#include +#include +#include +#include + +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 + . */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#ifdef HAVE_STRINGS_H +# include +#endif + +#include +#include +#include +#include +#include + +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 + . */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#ifdef HAVE_STRINGS_H +# include +#endif + +#include +#include +#include + +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 + . */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include +#ifdef HAVE_STRINGS_H +# include +#endif + +#include +#include +#include +#include +#include + +/* 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 + . */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + +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 + . */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#ifdef HAVE_STRINGS_H +# include +#endif + +#include +#include +#include +#include + +/* 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 + . */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#ifdef HAVE_STRINGS_H +# include +#endif + +#include +#include +#include +#include + +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 + . */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#ifdef HAVE_STRINGS_H +# include +#endif + +#include +#include +#include +#include + +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 + . */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#ifdef HAVE_STRINGS_H +# include +#endif + +#include +#include +#include + +#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 + . */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#ifdef HAVE_STRINGS_H +# include +#endif + +#include +#include +#include + +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 + . */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#ifdef HAVE_STRINGS_H +# include +#endif + +#include +#include +#include + +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 + . */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#ifdef HAVE_STRINGS_H +# include +#endif + +#include +#include +#include + +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 + . */ + +#ifdef HAVE_CONFIG_H +# include +#endif +#include +#include +#include + +const char * +mu_url_to_string (const mu_url_t url) +{ + if (url == NULL || url->name == NULL) + return ""; + return url->name; +} -- cgit v1.2.1