aboutsummaryrefslogtreecommitdiff
path: root/lib/url.c
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2015-12-31 13:59:18 +0200
committerSergey Poznyakoff <gray@gnu.org.ua>2015-12-31 15:58:17 +0200
commit00e6c3c3ed06a258a02943fc49fa7c528025d747 (patch)
tree52530660be48fb5f4611bcc9393886bab8a70b72 /lib/url.c
parent7f204cc788de3e03a51087b1273deb5b59288cf2 (diff)
downloadpies-00e6c3c3ed06a258a02943fc49fa7c528025d747.tar.gz
pies-00e6c3c3ed06a258a02943fc49fa7c528025d747.tar.bz2
Command-line control interface.
* configure.ac (DEFAULT_CONTROL_URL): New subst variable. * grecs: Upgrade. * ident/pam.c (overwrite_and_free): Free ptr. * lib/Makefile.am: Add new sources. * src/addrfmt.c: Move to lib/addrfmt.c * lib/grecsasrt.c: New file. * lib/grecsasrt.h: New file. * lib/mkfilename.c: New file. * lib/netrc.c: New file. * lib/pp.c: New file. * lib/split3.c: New file. * src/url.c: Move from lib/url.c (pies_url_free_user, pies_url_free_passwd): New finctions. * lib/libpies.h (strsplit3): New proto. (pies_url_create, pies_url_destroy) (pies_url_get_arg, pies_url_copy) (pies_url_free_user, pies_url_free_passwd) (netrc_scan) (pp_add_option, pp_command_line, mkfilename) (sockaddr_to_str, sockaddr_to_astr): New protos * src/Makefile.am (bin_PROGRAMS): New program: piesctl (pies_SOURCES): Remove addrfmt.c and url.c. (noinst_HEADERS, BUILT_SOURCES): Add piesctl-cl.h * src/cmdline.opt: Use pp_* function family to build preprocessor command line. * src/ctl.c (http_header_hash): Use case-insensitive hashing. (ctlio_finalize_reply): Don't close connection after sending 401 response. (input): Remove ws and wsflags. All uses changed. (input_append): Use strsplit3 to parse the request line. * src/pies.c: Use pp_* function family to build preprocessor command line. Move assert_, mkfilename and _cb+_url functions into libpies. * src/pies.h (pies_sockaddr_storage): Move to libpies.h * src/piesctl.c: New file. * src/piesctl-cl.opt: New file.
Diffstat (limited to 'lib/url.c')
-rw-r--r--lib/url.c360
1 files changed, 360 insertions, 0 deletions
diff --git a/lib/url.c b/lib/url.c
new file mode 100644
index 0000000..41f5c04
--- /dev/null
+++ b/lib/url.c
@@ -0,0 +1,360 @@
+/* This file is part of GNU Pies
+ Copyright (C) 2009, 2010, 2013, 2015 Sergey Poznyakoff
+
+ GNU Pies is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ GNU Pies 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Pies. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <netdb.h>
+#include <string.h>
+#include <errno.h>
+#include <limits.h>
+#include "libpies.h"
+#include <wordsplit.h>
+
+/* scheme://[user[:password]@][host[:port]/]path[;arg=str[;arg=str...]
+*/
+
+static int
+alloc_string_len (char **sptr, const char *start, size_t len)
+{
+ *sptr = malloc (len + 1);
+ if (!*sptr)
+ return 1;
+ memcpy (*sptr, start, len);
+ (*sptr)[len] = 0;
+ return 0;
+}
+
+static int
+alloc_string (char **sptr, const char *start, const char *end)
+{
+ size_t len = end ? end - start : strlen (start);
+ return alloc_string_len (sptr, start, len);
+}
+
+static int
+url_parse_args (struct pies_url *url, char **str)
+{
+ struct wordsplit ws;
+
+ ws.ws_delim = ";";
+ if (wordsplit (*str, &ws, WRDSF_NOVAR | WRDSF_NOCMD | WRDSF_DELIM))
+ return 1;
+ url->argc = ws.ws_wordc;
+ url->argv = ws.ws_wordv;
+ return 0;
+}
+
+static int
+url_parse_path (struct pies_url *url, char **str)
+{
+ char *p;
+
+ p = strchr (*str, ';');
+ if (!p)
+ p = *str + strlen (*str);
+ if (alloc_string (&url->path, *str, p))
+ return 1;
+ *str = p;
+ if (*p)
+ ++*str;
+ return url_parse_args (url, str);
+}
+
+/* On input str points at the beginning of host part */
+static int
+url_parse_host (struct pies_url *url, char **str)
+{
+ char *s = *str;
+ size_t len = strcspn (s, "/:");
+
+ if (s[len] == ':')
+ {
+ char *start = s + len + 1;
+ char *q;
+ unsigned long n = strtoul (start, &q, 10);
+ if (n > USHRT_MAX)
+ return 1;
+ if ((*q && !strchr ("/;", *q)))
+ {
+ char *proto = url->proto_s ? url->proto_s : "tcp";
+ size_t size = strcspn (start, "/;");
+ struct servent *serv;
+
+ alloc_string_len (&url->port_s, start, size);
+ serv = getservbyname (url->port_s, proto);
+ if (!serv)
+ return 1;
+ url->port = ntohs (serv->s_port);
+ *str = start + size;
+ }
+ else
+ {
+ alloc_string_len (&url->port_s, start, q - start);
+ url->port = n;
+ *str = q;
+ }
+ }
+ else
+ *str = s + len;
+ if (alloc_string_len (&url->host, s, len))
+ return 1;
+ if (**str)
+ {
+ if (*(*str)++ == '/')
+ return url_parse_path (url, str);
+ else
+ return url_parse_args (url, str);
+ }
+ return 0;
+}
+
+/* On input str points past the mech:// part */
+static int
+url_parse_user (struct pies_url *url, char **str)
+{
+ if (**str == '/')
+ return url_parse_path (url, str);
+ else
+ {
+ size_t len = strcspn (*str, ":;@/");
+ char *p = *str + len;
+
+ switch (*p)
+ {
+ case ';':
+ case ':':
+ len = strcspn (p + 1, "@/:");
+ if (p[len + 1] == '@')
+ {
+ if (alloc_string_len (&url->passwd, p + 1, len))
+ return 1;
+ if (alloc_string (&url->user, *str, p))
+ return 1;
+ *str = p + len + 2;
+ }
+ break;
+
+ case '@':
+ if (alloc_string (&url->user, *str, p))
+ return 1;
+ url->passwd = NULL;
+ *str = p + 1;
+ }
+ return url_parse_host (url, str);
+ }
+}
+
+static int
+url_parse_scheme (struct pies_url *url, const char *str)
+{
+ size_t len;
+ char *p;
+
+ if (!str)
+ {
+ errno = EINVAL;
+ return 1;
+ }
+
+ len = strcspn (str, ":+");
+ if (!str[len])
+ {
+ errno = EINVAL;
+ return 1;
+ }
+
+ alloc_string_len (&url->scheme, str, len);
+
+ str += len;
+
+ if (*str == '+')
+ {
+ struct protoent *proto;
+
+ len = strcspn (++str, ":");
+ if (str[len] == 0)
+ {
+ errno = EINVAL;
+ return 1;
+ }
+ alloc_string_len (&url->proto_s, str, len);
+ str += len;
+ proto = getprotobyname (url->proto_s);
+ if (!proto)
+ {
+ errno = EINVAL;
+ return 1;
+ }
+ url->proto = proto->p_proto;
+ }
+ else
+ url->proto = 0;
+
+ /* Skip slashes */
+ p = (char*) str + 1;
+ if (memcmp (p, "//", 2))
+ {
+ errno = EINVAL;
+ return 1;
+ }
+ p += 2;
+ return url_parse_user (url, &p);
+}
+
+void
+pies_url_free_user (struct pies_url *url)
+{
+ if (url->user)
+ {
+ free (url->user);
+ url->user = NULL;
+ }
+}
+
+void
+pies_url_free_passwd (struct pies_url *url)
+{
+ if (url->passwd)
+ {
+ memset (url->passwd, 0, strlen (url->passwd));
+ free (url->passwd);
+ url->passwd = NULL;
+ }
+}
+
+void
+pies_url_destroy (struct pies_url **purl)
+{
+ int i;
+ if (purl && *purl)
+ {
+ struct pies_url *url = *purl;
+
+ free (url->string);
+ free (url->scheme);
+ free (url->host);
+ free (url->port_s);
+ free (url->proto_s);
+ free (url->path);
+ pies_url_free_user (url);
+ pies_url_free_passwd (url);
+ for (i = 0; i < url->argc; i++)
+ free (url->argv[i]);
+ free (url->argv);
+ free (url);
+ *purl = NULL;
+ }
+}
+
+static int
+strasgn (char **dst, char *src)
+{
+ if (!src)
+ *dst = NULL;
+ else
+ {
+ *dst = strdup (src);
+ if (!*dst)
+ return 1;
+ }
+ return 0;
+}
+
+static int
+do_url_copy (struct pies_url *dest, struct pies_url *src)
+{
+#define STRASGN(a,b) if (strasgn (a, b)) return -1;
+ size_t i;
+
+ STRASGN (&dest->string, src->string);
+ STRASGN (&dest->scheme, src->scheme);
+ STRASGN (&dest->host, src->host);
+ STRASGN (&dest->port_s, src->port_s);
+ dest->port = src->port;
+ STRASGN (&dest->proto_s, src->proto_s);
+ dest->proto = src->proto;
+ STRASGN (&dest->path, src->path);
+ STRASGN (&dest->user, src->user);
+ STRASGN (&dest->passwd, src->passwd);
+ dest->argv = calloc (src->argc + 1, sizeof (dest->argv[0]));
+ if (!dest->argv)
+ return -1;
+ for (i = 0; i < src->argc; i++)
+ {
+ if (!(dest->argv[i] = strdup (src->argv[0])))
+ {
+ dest->argc = i;
+ return -1;
+ }
+ }
+ dest->argv[i] = NULL;
+ dest->argc = i;
+ return 0;
+#undef STRASGN
+}
+
+int
+pies_url_copy (struct pies_url **purl, struct pies_url *src)
+{
+ struct pies_url *dest = malloc (sizeof (*dest));
+
+ if (!dest)
+ return -1;
+ memset (dest, 0, sizeof (*dest));
+ if (do_url_copy (dest, src))
+ {
+ pies_url_destroy (&dest);
+ return -1;
+ }
+ *purl = dest;
+ return 0;
+}
+
+int
+pies_url_create (struct pies_url **purl, const char *str)
+{
+ int rc;
+ struct pies_url *url;
+
+ url = malloc (sizeof (*url));
+ if (!url)
+ return 1;
+ memset (url, 0, sizeof (*url));
+ rc = url_parse_scheme (url, str);
+ if (rc)
+ pies_url_destroy (&url);
+ else
+ {
+ url->string = strdup (str);
+ *purl = url;
+ }
+ return rc;
+}
+
+const char *
+pies_url_get_arg (struct pies_url *url, const char *argname)
+{
+ int i;
+ size_t arglen = strlen (argname);
+ for (i = 0; i < url->argc; i++)
+ {
+ size_t len = strcspn (url->argv[i], "=");
+ if (len == arglen && memcmp (url->argv[i], argname, arglen) == 0)
+ return url->argv[i] + len + 1;
+ }
+ return NULL;
+}

Return to:

Send suggestions and report system problems to the System administrator.