Commit 4ef89f34 4ef89f34158d37b3e2aed8cdc39a64c7c84a270c by Sergey Poznyakoff

Change handling of URL query part.

Queries are now parsed into arguments and returned as arrays
of arguments.

* libproto/include/url0.h (struct _mu_url): Replace query with
array of query arguments.
* include/mailutils/url.h (mu_url_dup): New proto.
(mu_url_get_query): Remove.
(mu_url_sget_query, mu_url_aget_query): Return query split into
arguments.
(mu_url_set_scheme): New function.
(mu_url_decode_len): New function.
* mailbox/url.c (mu_url_dup): New function.
(mu_url_get_query): Remove.
(mu_url_sget_query, mu_url_aget_query): Return query split into
arguments.
(mu_url_set_scheme): New function.
(mu_url_decode_len): New function.
* libproto/remote/mbox.c (remote_mbox_init): Use parsed out URL,
instead of the full URL string.

* examples/url-parse.c: Change query output.
* mailbox/testsuite/Urls: Reflect changes to url-parse.  Add new
testcases.

* libproto/imap/url.c, libproto/pop/url.c: Reflect changes to URL
functions.
1 parent 966f07cc
......@@ -56,6 +56,23 @@ print_fvpairs (mu_url_t url)
printf ("\tparam[%d] <%s>\n", i, fvp[i]);
}
static void
print_query (mu_url_t url)
{
size_t qargc, i;
char **qargv;
int rc = mu_url_sget_query (url, &qargc, &qargv);
if (rc)
{
mu_error ("cannot get query: %s", mu_strerror (rc));
exit (1);
}
if (qargc == 0)
return;
for (i = 0; i < qargc; i++)
printf ("\tquery[%d] <%s>\n", i, qargv[i]);
}
int
main ()
{
......@@ -101,7 +118,7 @@ main ()
GET_AND_PRINT (path, u, buf, rc);
print_fvpairs (u);
GET_AND_PRINT (query, u, buf, rc);
print_query (u);
mu_url_destroy (&u);
......
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 1999, 2000, 2001, 2005, 2007 Free Software Foundation, Inc.
Copyright (C) 1999, 2000, 2001, 2005, 2007,
2008 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
......@@ -26,6 +27,8 @@ extern "C" {
#endif
extern int mu_url_create (mu_url_t *, const char *name);
extern int mu_url_dup (mu_url_t old_url, mu_url_t *new_url);
extern void mu_url_destroy (mu_url_t *);
extern int mu_url_parse (mu_url_t);
......@@ -53,9 +56,8 @@ extern int mu_url_sget_path (const mu_url_t, const char **);
extern int mu_url_aget_path (const mu_url_t, char **);
extern int mu_url_get_path (const mu_url_t, char *, size_t, size_t *);
extern int mu_url_sget_query (const mu_url_t, const char **);
extern int mu_url_aget_query (const mu_url_t, char **);
extern int mu_url_get_query (const mu_url_t, char *, size_t, size_t *);
extern int mu_url_sget_query (const mu_url_t url, size_t *qc, char ***qv);
extern int mu_url_aget_query (const mu_url_t url, size_t *qc, char ***qv);
extern int mu_url_get_port (const mu_url_t, long *);
......@@ -65,6 +67,8 @@ int mu_url_aget_fvpairs (const mu_url_t url, size_t *pfvc, char ***pfvp);
extern int mu_url_expand_path (mu_url_t url);
extern const char *mu_url_to_string (const mu_url_t);
extern int mu_url_set_scheme (mu_url_t url, const char *scheme);
extern int mu_url_is_scheme (mu_url_t, const char *scheme);
extern int mu_url_is_same_scheme (mu_url_t, mu_url_t);
......@@ -73,6 +77,7 @@ extern int mu_url_is_same_path (mu_url_t, mu_url_t);
extern int mu_url_is_same_host (mu_url_t, mu_url_t);
extern int mu_url_is_same_port (mu_url_t, mu_url_t);
extern char *mu_url_decode_len (const char *s, size_t len);
extern char *mu_url_decode (const char *s);
extern int mu_url_is_ticket (mu_url_t ticket, mu_url_t url);
......
......@@ -54,7 +54,7 @@ _url_imap_init (mu_url_t url)
url->_destroy = url_imap_destroy;
if(!url->host || url->query)
if (!url->host || url->qargc)
return EINVAL;
/* fill in default auth, if necessary */
......@@ -85,7 +85,7 @@ _url_imaps_init (mu_url_t url)
url->_destroy = url_imap_destroy;
if (!url->host || url->query)
if (!url->host || url->qargc)
return EINVAL;
/* fill in default auth, if necessary */
......
......@@ -42,7 +42,9 @@ struct _mu_url
char *path;
char **fvpairs;
int fvcount;
char *query;
char **qargv;
int qargc;
void *data;
......
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 1999, 2000, 2001, 2003, 2007 Free Software Foundation, Inc.
Copyright (C) 1999, 2000, 2001, 2003, 2007,
2008 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
......@@ -55,7 +56,7 @@ _url_pop_init (mu_url_t url)
url->_destroy = url_pop_destroy;
/* not valid in pop url */
if (url->path || url->query || !url->host)
if (url->path || url->qargc || !url->host)
return EINVAL;
return 0;
......@@ -77,7 +78,7 @@ _url_pops_init (mu_url_t url)
url->_destroy = url_pop_destroy;
/* not valid in pops url */
if (url->path || url->query || !url->host)
if (url->path || url->qargc || !url->host)
return EINVAL;
return 0;
......
......@@ -206,29 +206,43 @@ remote_mbox_init (mu_mailbox_t mailbox)
const char *s, *p;
int rc;
mu_mailer_t mailer;
mu_url_t url;
if (mailbox == NULL)
return EINVAL;
s = mu_url_to_string (mailbox->url);
MU_DEBUG1 (mailbox->debug, MU_DEBUG_TRACE1, "remote_mbox_init (%s)\n", s);
MU_DEBUG1 (mailbox->debug, MU_DEBUG_TRACE1,
"remote_mbox_init (%s)\n", mu_url_to_string (mailbox->url));
rc = mu_url_sget_scheme (mailbox->url, &s);
if (rc)
return rc;
p = strchr (s, '+');
if (!p)
{
MU_DEBUG2 (mailbox->debug, MU_DEBUG_ERROR,
"remote_mbox_init(%s): invalid url: %s\n", s,
"remote_mbox_init(%s): invalid url: %s\n",
mu_url_to_string (mailbox->url),
mu_strerror (rc));
return MU_ERR_MAILER_BAD_URL;
}
p++;
rc = mu_mailer_create (&mailer, p);
rc = mu_url_dup (mailbox->url, &url);
if (rc)
return rc;
rc = mu_url_set_scheme (url, p + 1);
if (rc)
{
mu_url_destroy (&url);
return rc;
}
rc = mu_mailer_create_from_url (&mailer, url);
if (rc)
{
MU_DEBUG2 (mailbox->debug, MU_DEBUG_ERROR,
"remote_mbox_init(%s): cannot create mailer: %s\n",
s, mu_strerror (rc));
mu_url_to_string (url), mu_strerror (rc));
mu_url_destroy (&url);
return rc;
}
......
# This file is part of Mailutils testsuite.
# Copyright (C) 2002, 2007 Free Software Foundation
# Copyright (C) 2002, 2007, 2008 Free Software Foundation
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
......@@ -25,7 +25,6 @@ scheme: => SUCCESS
host <>
port 0
path <>
query <>
scheme:/absolute/path => SUCCESS
scheme <scheme>
......@@ -35,7 +34,6 @@ scheme:/absolute/path => SUCCESS
host <>
port 0
path </absolute/path>
query <>
scheme:relative/path => SUCCESS
scheme <scheme>
......@@ -45,7 +43,6 @@ scheme:relative/path => SUCCESS
host <>
port 0
path <relative/path>
query <>
scheme:///absolute/path => SUCCESS
scheme <scheme>
......@@ -55,7 +52,6 @@ scheme:///absolute/path => SUCCESS
host <>
port 0
path </absolute/path>
query <>
scheme://%75%73%65%72:%70%61%73%73@%68%6f%73%74 => SUCCESS
scheme <scheme>
......@@ -65,7 +61,6 @@ scheme://%75%73%65%72:%70%61%73%73@%68%6f%73%74 => SUCCESS
host <hest>
port 0
path <>
query <>
ftp://user:pass@host//a/path => SUCCESS
scheme <ftp>
......@@ -75,7 +70,6 @@ ftp://user:pass@host//a/path => SUCCESS
host <host>
port 0
path </a/path>
query <>
ftp://:pass@host//a/path => SUCCESS
scheme <ftp>
......@@ -85,7 +79,6 @@ ftp://:pass@host//a/path => SUCCESS
host <host>
port 0
path </a/path>
query <>
ftp://user:@host//a/path => SUCCESS
scheme <ftp>
......@@ -95,7 +88,6 @@ ftp://user:@host//a/path => SUCCESS
host <host>
port 0
path </a/path>
query <>
ftp://user:pass@//a/path => SUCCESS
scheme <ftp>
......@@ -105,7 +97,6 @@ ftp://user:pass@//a/path => SUCCESS
host <>
port 0
path </a/path>
query <>
ftp://user:@//a/path => SUCCESS
scheme <ftp>
......@@ -115,7 +106,6 @@ ftp://user:@//a/path => SUCCESS
host <>
port 0
path </a/path>
query <>
ftp://:@host//a/path => SUCCESS
scheme <ftp>
......@@ -125,7 +115,6 @@ ftp://:@host//a/path => SUCCESS
host <host>
port 0
path </a/path>
query <>
ftp://:pass@//a/path => SUCCESS
scheme <ftp>
......@@ -135,7 +124,6 @@ ftp://:pass@//a/path => SUCCESS
host <>
port 0
path </a/path>
query <>
ftp://:@//a/path => SUCCESS
scheme <ftp>
......@@ -145,7 +133,6 @@ ftp://:@//a/path => SUCCESS
host <>
port 0
path </a/path>
query <>
ftp://://a/path => SUCCESS
scheme <ftp>
......@@ -155,7 +142,6 @@ ftp://://a/path => SUCCESS
host <>
port 0
path </a/path>
query <>
ftp://@//a/path => SUCCESS
scheme <ftp>
......@@ -165,7 +151,6 @@ ftp://@//a/path => SUCCESS
host <>
port 0
path </a/path>
query <>
ftp:/a/path => SUCCESS
scheme <ftp>
......@@ -175,7 +160,6 @@ ftp:/a/path => SUCCESS
host <>
port 0
path </a/path>
query <>
ftp://user:pass@host/a/path => SUCCESS
scheme <ftp>
......@@ -185,7 +169,6 @@ ftp://user:pass@host/a/path => SUCCESS
host <host>
port 0
path <a/path>
query <>
ftp://:pass@host/a/path => SUCCESS
scheme <ftp>
......@@ -195,7 +178,6 @@ ftp://:pass@host/a/path => SUCCESS
host <host>
port 0
path <a/path>
query <>
ftp://user:@host/a/path => SUCCESS
scheme <ftp>
......@@ -205,7 +187,6 @@ ftp://user:@host/a/path => SUCCESS
host <host>
port 0
path <a/path>
query <>
ftp://user:pass@/a/path => SUCCESS
scheme <ftp>
......@@ -215,7 +196,6 @@ ftp://user:pass@/a/path => SUCCESS
host <>
port 0
path <a/path>
query <>
ftp://user:@/a/path => SUCCESS
scheme <ftp>
......@@ -225,7 +205,6 @@ ftp://user:@/a/path => SUCCESS
host <>
port 0
path <a/path>
query <>
ftp://:@host/a/path => SUCCESS
scheme <ftp>
......@@ -235,7 +214,6 @@ ftp://:@host/a/path => SUCCESS
host <host>
port 0
path <a/path>
query <>
ftp://:pass@/a/path => SUCCESS
scheme <ftp>
......@@ -245,7 +223,6 @@ ftp://:pass@/a/path => SUCCESS
host <>
port 0
path <a/path>
query <>
ftp://:@/a/path => SUCCESS
scheme <ftp>
......@@ -255,7 +232,6 @@ ftp://:@/a/path => SUCCESS
host <>
port 0
path <a/path>
query <>
ftp://:/a/path => SUCCESS
scheme <ftp>
......@@ -265,7 +241,6 @@ ftp://:/a/path => SUCCESS
host <>
port 0
path <a/path>
query <>
ftp://@/a/path => SUCCESS
scheme <ftp>
......@@ -275,7 +250,6 @@ ftp://@/a/path => SUCCESS
host <>
port 0
path <a/path>
query <>
ftp:///a/path => SUCCESS
scheme <ftp>
......@@ -285,7 +259,6 @@ ftp:///a/path => SUCCESS
host <>
port 0
path </a/path>
query <>
pop://pop.example.net => SUCCESS
scheme <pop>
......@@ -295,7 +268,6 @@ pop://pop.example.net => SUCCESS
host <pop.example.net>
port 0
path <>
query <>
pop://user@pop.example.net => SUCCESS
scheme <pop>
......@@ -305,7 +277,6 @@ pop://user@pop.example.net => SUCCESS
host <pop.example.net>
port 0
path <>
query <>
pop://user:passwd@pop.example.net => SUCCESS
scheme <pop>
......@@ -315,7 +286,6 @@ pop://user:passwd@pop.example.net => SUCCESS
host <pop.example.net>
port 0
path <>
query <>
pop://user;auth=*@pop.example.net => SUCCESS
scheme <pop>
......@@ -325,7 +295,6 @@ pop://user;auth=*@pop.example.net => SUCCESS
host <pop.example.net>
port 0
path <>
query <>
pop://pop.example.net:111 => SUCCESS
scheme <pop>
......@@ -335,7 +304,6 @@ pop://pop.example.net:111 => SUCCESS
host <pop.example.net>
port 111
path <>
query <>
pop://user@pop.example.net:111 => SUCCESS
scheme <pop>
......@@ -345,7 +313,6 @@ pop://user@pop.example.net:111 => SUCCESS
host <pop.example.net>
port 111
path <>
query <>
pop://user:passwd@pop.example.net:111 => SUCCESS
scheme <pop>
......@@ -355,7 +322,6 @@ pop://user:passwd@pop.example.net:111 => SUCCESS
host <pop.example.net>
port 111
path <>
query <>
pop://user;auth=*@pop.example.net:111 => SUCCESS
scheme <pop>
......@@ -365,7 +331,6 @@ pop://user;auth=*@pop.example.net:111 => SUCCESS
host <pop.example.net>
port 111
path <>
query <>
imap://imap.example.net => SUCCESS
scheme <imap>
......@@ -375,7 +340,6 @@ imap://imap.example.net => SUCCESS
host <imap.example.net>
port 0
path <>
query <>
imap://user@imap.example.net => SUCCESS
scheme <imap>
......@@ -385,7 +349,6 @@ imap://user@imap.example.net => SUCCESS
host <imap.example.net>
port 0
path <>
query <>
imap://user:passwd@imap.example.net => SUCCESS
scheme <imap>
......@@ -395,7 +358,6 @@ imap://user:passwd@imap.example.net => SUCCESS
host <imap.example.net>
port 0
path <>
query <>
imap://user;auth=*@imap.example.net => SUCCESS
scheme <imap>
......@@ -405,7 +367,6 @@ imap://user;auth=*@imap.example.net => SUCCESS
host <imap.example.net>
port 0
path <>
query <>
imap://imap.example.net:111 => SUCCESS
scheme <imap>
......@@ -415,7 +376,6 @@ imap://imap.example.net:111 => SUCCESS
host <imap.example.net>
port 111
path <>
query <>
imap://user@imap.example.net:111 => SUCCESS
scheme <imap>
......@@ -425,7 +385,6 @@ imap://user@imap.example.net:111 => SUCCESS
host <imap.example.net>
port 111
path <>
query <>
imap://user:passwd@imap.example.net:111 => SUCCESS
scheme <imap>
......@@ -435,7 +394,6 @@ imap://user:passwd@imap.example.net:111 => SUCCESS
host <imap.example.net>
port 111
path <>
query <>
imap://user;auth=*@imap.example.net:111 => SUCCESS
scheme <imap>
......@@ -445,7 +403,6 @@ imap://user;auth=*@imap.example.net:111 => SUCCESS
host <imap.example.net>
port 111
path <>
query <>
imap://imap.example.net/mbox => SUCCESS
scheme <imap>
......@@ -455,7 +412,6 @@ imap://imap.example.net/mbox => SUCCESS
host <imap.example.net>
port 0
path <mbox>
query <>
imap://user@imap.example.net/mbox => SUCCESS
scheme <imap>
......@@ -465,7 +421,6 @@ imap://user@imap.example.net/mbox => SUCCESS
host <imap.example.net>
port 0
path <mbox>
query <>
imap://user:passwd@imap.example.net/mbox => SUCCESS
scheme <imap>
......@@ -475,7 +430,6 @@ imap://user:passwd@imap.example.net/mbox => SUCCESS
host <imap.example.net>
port 0
path <mbox>
query <>
imap://user;auth=*@imap.example.net/mbox => SUCCESS
scheme <imap>
......@@ -485,7 +439,6 @@ imap://user;auth=*@imap.example.net/mbox => SUCCESS
host <imap.example.net>
port 0
path <mbox>
query <>
imap://imap.example.net:111/mbox => SUCCESS
scheme <imap>
......@@ -495,7 +448,6 @@ imap://imap.example.net:111/mbox => SUCCESS
host <imap.example.net>
port 111
path <mbox>
query <>
imap://user@imap.example.net:111/mbox => SUCCESS
scheme <imap>
......@@ -505,7 +457,6 @@ imap://user@imap.example.net:111/mbox => SUCCESS
host <imap.example.net>
port 111
path <mbox>
query <>
imap://user:passwd@imap.example.net:111/mbox => SUCCESS
scheme <imap>
......@@ -515,7 +466,6 @@ imap://user:passwd@imap.example.net:111/mbox => SUCCESS
host <imap.example.net>
port 111
path <mbox>
query <>
imap://user;auth=*@imap.example.net:111/mbox => SUCCESS
scheme <imap>
......@@ -525,7 +475,6 @@ imap://user;auth=*@imap.example.net:111/mbox => SUCCESS
host <imap.example.net>
port 111
path <mbox>
query <>
imap://imap.example.net/mbox/user@host => SUCCESS
scheme <imap>
......@@ -535,7 +484,6 @@ imap://imap.example.net/mbox/user@host => SUCCESS
host <host>
port 0
path <>
query <>
imap://user@imap.example.net/mbox/user@host => SUCCESS
scheme <imap>
......@@ -545,7 +493,6 @@ imap://user@imap.example.net/mbox/user@host => SUCCESS
host <imap.example.net>
port 0
path <mbox/user@host>
query <>
imap://user:passwd@imap.example.net/mbox/user@host => SUCCESS
scheme <imap>
......@@ -555,7 +502,6 @@ imap://user:passwd@imap.example.net/mbox/user@host => SUCCESS
host <imap.example.net>
port 0
path <mbox/user@host>
query <>
imap://user;auth=*@imap.example.net/mbox/user@host => SUCCESS
scheme <imap>
......@@ -565,7 +511,6 @@ imap://user;auth=*@imap.example.net/mbox/user@host => SUCCESS
host <imap.example.net>
port 0
path <mbox/user@host>
query <>
imap://imap.example.net:111/mbox/user@host => SUCCESS
scheme <imap>
......@@ -575,7 +520,6 @@ imap://imap.example.net:111/mbox/user@host => SUCCESS
host <host>
port 0
path <>
query <>
imap://user@imap.example.net:111/mbox/user@host => SUCCESS
scheme <imap>
......@@ -585,7 +529,6 @@ imap://user@imap.example.net:111/mbox/user@host => SUCCESS
host <imap.example.net>
port 111
path <mbox/user@host>
query <>
imap://user:passwd@imap.example.net:111/mbox/user@host => SUCCESS
scheme <imap>
......@@ -595,7 +538,6 @@ imap://user:passwd@imap.example.net:111/mbox/user@host => SUCCESS
host <imap.example.net>
port 111
path <mbox/user@host>
query <>
imap://user;auth=*@imap.example.net:111/mbox/user@host => SUCCESS
scheme <imap>
......@@ -605,7 +547,6 @@ imap://user;auth=*@imap.example.net:111/mbox/user@host => SUCCESS
host <imap.example.net>
port 111
path <mbox/user@host>
query <>
ftp://ftp.example.org/mbox/user%40host => SUCCESS
scheme <ftp>
......@@ -615,7 +556,6 @@ ftp://ftp.example.org/mbox/user%40host => SUCCESS
host <ftp.example.org>
port 0
path <mbox/user@host>
query <>
ftp://ftp.example.org:111/mbox/user%40host => SUCCESS
scheme <ftp>
......@@ -625,7 +565,6 @@ ftp://ftp.example.org:111/mbox/user%40host => SUCCESS
host <ftp.example.org>
port 111
path <mbox/user@host>
query <>
ftp://ftp.example.org:111/mbox/user%40host;type=pass => SUCCESS
scheme <ftp>
......@@ -636,7 +575,6 @@ ftp://ftp.example.org:111/mbox/user%40host;type=pass => SUCCESS
port 111
path <mbox/user@host>
param[0] <type=pass>
query <>
mbox:/var/spool/mail;type=index;param=2;user=gray => SUCCESS
scheme <mbox>
......@@ -649,7 +587,6 @@ mbox:/var/spool/mail;type=index;param=2;user=gray => SUCCESS
param[0] <type=index>
param[1] <param=2>
param[2] <user=gray>
query <>
mbox:///var/spool/mail;type=index;param=2;user=gray => SUCCESS
scheme <mbox>
......@@ -662,6 +599,31 @@ mbox:///var/spool/mail;type=index;param=2;user=gray => SUCCESS
param[0] <type=index>
param[1] <param=2>
param[2] <user=gray>
query <>
http:///gnu.org.ua/home/gray?prog&arg1&arg2
scheme <http>
user <>
passwd <>
auth <>
host <gnu.org.ua>
port 0
path <home/gray>
query[0] <prog>
query[1] <arg1>
query[2] <arg2>
http:///gnu.org.ua/home/gray;foo=bar;baz=qux?prog&arg%201&arg%202
scheme <http>
user <>
passwd <>
auth <>
host <gnu.org.ua>
port 0
path <home/gray>
param[0] <foo=bar>
param[1] <baz=qux>
query[0] <prog>
query[1] <arg 1>
query[2] <arg 2>
# NOTE: This file must end with an empty line
......
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 1999, 2000, 2001, 2007 Free Software Foundation, Inc.
Copyright (C) 1999, 2000, 2001, 2007, 2008 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
......@@ -33,14 +33,56 @@
#include <mailutils/argcv.h>
#include <url0.h>
/*
TODO: implement functions to create a url and encode it properly.
*/
#define AC2(a,b) a ## b
#define AC4(a,b,c,d) a ## b ## c ## d
static int url_parse0 (mu_url_t, char *);
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_create (mu_url_t *purl, const char *name)
{
mu_url_t url = calloc (1, sizeof (*url));
if (url == NULL)
......@@ -56,6 +98,89 @@ mu_url_create (mu_url_t * purl, const char *name)
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;
#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);
URLCOPY (passwd);
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;
}
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;
}
void
mu_url_destroy (mu_url_t * purl)
{
......@@ -90,8 +215,7 @@ mu_url_destroy (mu_url_t * purl)
if (url->fvcount)
mu_argcv_free (url->fvcount, url->fvpairs);
if (url->query)
free (url->query);
mu_argcv_free (url->qargc, url->qargv);
free (url);
......@@ -112,7 +236,7 @@ mu_url_parse (mu_url_t url)
memset (&u, 0, sizeof u);
/* can't have been parsed already */
if (url->scheme || url->user || url->passwd || url->auth ||
url->host || url->path || url->query)
url->host || url->path || url->qargc)
return EINVAL;
n = strdup (url->name);
......@@ -148,10 +272,14 @@ mu_url_parse (mu_url_t url)
UALLOC (auth);
UALLOC (host);
UALLOC (path);
UALLOC (query);
#undef UALLOC
url->fvcount = u.fvcount;
url->fvpairs = u.fvpairs;
url->qargc = u.qargc;
url->qargv = u.qargv;
url->port = u.port;
}
......@@ -168,7 +296,8 @@ CLEANUP:
UFREE (url->auth);
UFREE (url->host);
UFREE (url->path);
UFREE (url->query);
mu_argcv_free (url->fvcount, url->fvpairs);
mu_argcv_free (url->qargc, url->qargv);
#undef UFREE
}
......@@ -213,6 +342,19 @@ url_parse0 (mu_url_t u, char *name)
{
u->scheme = "file";
}
else if (name[0] == '|')
{
int rc;
u->scheme = "prog";
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
{
/* Parse out the SCHEME. */
......@@ -318,15 +460,16 @@ url_parse0 (mu_url_t u, char *name)
if (*p == ';')
{
*p++ = 0;
mu_argcv_get_np (p, strlen (p), ";", "?", 0,
&u->fvcount, &u->fvpairs, &p);
if (parse_query (p, ";?", &u->fvcount, &u->fvpairs, (const char **)&p))
return ENOMEM;
}
if (*p == '?')
{
/* found a query */
*p++ = 0;
u->query = p;
if (parse_query (p, "&", &u->qargc, &u->qargv, NULL))
return ENOMEM;
}
return 0;
......@@ -334,8 +477,6 @@ url_parse0 (mu_url_t u, char *name)
/* General accessors: */
#define AC2(a,b) a ## b
#define AC4(a,b,c,d) a ## b ## c ## d
#define ACCESSOR(action,field) AC4(mu_url_,action,_,field)
#define DECL_SGET(field) \
......@@ -453,7 +594,45 @@ DECL_ACCESSORS (passwd)
DECL_ACCESSORS (auth)
DECL_ACCESSORS (host)
DECL_ACCESSORS (path)
DECL_ACCESSORS (query)
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
......@@ -507,7 +686,6 @@ mu_url_get_port (const mu_url_t url, long *pport)
return 0;
}
const char *
mu_url_to_string (const mu_url_t url)
{
......@@ -517,6 +695,19 @@ mu_url_to_string (const mu_url_t url)
}
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 && strcasecmp (url->scheme, scheme) == 0)
......@@ -537,12 +728,13 @@ mu_url_is_same_port (mu_url_t url1, mu_url_t url2)
/* From RFC 1738, section 2.2 */
char *
mu_url_decode (const char *s)
mu_url_decode_len (const char *s, size_t len)
{
char *d = strdup (s);
const char *eos = s + strlen (s);
char *d;
const char *eos = s + len;
int i;
d = malloc (len + 1);
if (!d)
return NULL;
......@@ -576,6 +768,12 @@ mu_url_decode (const char *s)
return d;
}
char *
mu_url_decode (const char *s)
{
return mu_url_decode_len (s, strlen (s));
}
static int
defined (const char *s)
{
......