2000-08-28 02:34:02 +08:00
|
|
|
/** \ingroup rpmio
|
|
|
|
* \file rpmio/url.c
|
|
|
|
*/
|
|
|
|
|
1999-07-04 07:36:35 +08:00
|
|
|
#include "system.h"
|
|
|
|
|
2007-10-30 09:56:34 +08:00
|
|
|
#include <assert.h>
|
1999-07-04 07:36:35 +08:00
|
|
|
#include <netinet/in.h>
|
2010-01-05 17:26:14 +08:00
|
|
|
#include <netdb.h>
|
1999-07-04 07:36:35 +08:00
|
|
|
|
2007-12-08 20:02:32 +08:00
|
|
|
#include <rpm/rpmmacro.h>
|
|
|
|
#include <rpm/rpmlog.h>
|
|
|
|
#include <rpm/rpmurl.h>
|
|
|
|
#include <rpm/rpmio.h>
|
2008-04-11 16:18:25 +08:00
|
|
|
#include <rpm/argv.h>
|
|
|
|
#include <rpm/rpmstring.h>
|
1999-07-04 07:36:35 +08:00
|
|
|
|
2000-12-13 04:03:45 +08:00
|
|
|
#include "debug.h"
|
|
|
|
|
2000-02-24 13:41:47 +08:00
|
|
|
#ifndef IPPORT_FTP
|
|
|
|
#define IPPORT_FTP 21
|
|
|
|
#endif
|
1999-12-06 05:22:45 +08:00
|
|
|
#ifndef IPPORT_HTTP
|
|
|
|
#define IPPORT_HTTP 80
|
|
|
|
#endif
|
2004-11-04 21:29:11 +08:00
|
|
|
#ifndef IPPORT_HTTPS
|
|
|
|
#define IPPORT_HTTPS 443
|
|
|
|
#endif
|
2004-11-29 05:14:41 +08:00
|
|
|
#ifndef IPPORT_PGPKEYSERVER
|
|
|
|
#define IPPORT_PGPKEYSERVER 11371
|
|
|
|
#endif
|
1999-12-06 05:22:45 +08:00
|
|
|
|
2007-10-30 09:56:34 +08:00
|
|
|
#define URLMAGIC 0xd00b1ed0
|
|
|
|
#define URLSANE(u) assert(u && u->magic == URLMAGIC)
|
|
|
|
|
2007-09-17 15:31:18 +08:00
|
|
|
urlinfo urlNew()
|
1999-10-31 00:43:29 +08:00
|
|
|
{
|
1999-11-02 22:33:14 +08:00
|
|
|
urlinfo u;
|
1999-10-31 00:43:29 +08:00
|
|
|
if ((u = xmalloc(sizeof(*u))) == NULL)
|
|
|
|
return NULL;
|
|
|
|
memset(u, 0, sizeof(*u));
|
|
|
|
u->proxyp = -1;
|
|
|
|
u->port = -1;
|
1999-11-24 08:03:54 +08:00
|
|
|
u->urltype = URL_IS_UNKNOWN;
|
1999-11-10 04:57:38 +08:00
|
|
|
u->magic = URLMAGIC;
|
2007-09-17 15:31:18 +08:00
|
|
|
return u;
|
1999-10-31 00:43:29 +08:00
|
|
|
}
|
1999-09-18 05:51:23 +08:00
|
|
|
|
2007-09-17 15:31:18 +08:00
|
|
|
urlinfo urlFree(urlinfo u)
|
1999-07-04 07:36:35 +08:00
|
|
|
{
|
1999-11-10 04:57:38 +08:00
|
|
|
URLSANE(u);
|
2008-03-25 02:44:48 +08:00
|
|
|
u->url = _free(u->url);
|
|
|
|
u->scheme = _free(u->scheme);
|
|
|
|
u->user = _free(u->user);
|
|
|
|
u->password = _free(u->password);
|
|
|
|
u->host = _free(u->host);
|
|
|
|
u->portstr = _free(u->portstr);
|
|
|
|
u->proxyu = _free(u->proxyu);
|
|
|
|
u->proxyh = _free(u->proxyh);
|
2001-05-04 05:00:18 +08:00
|
|
|
|
2007-09-11 22:48:54 +08:00
|
|
|
u = _free(u);
|
1999-11-10 04:57:38 +08:00
|
|
|
return NULL;
|
1999-07-04 07:36:35 +08:00
|
|
|
}
|
|
|
|
|
2001-10-15 11:22:10 +08:00
|
|
|
/**
|
|
|
|
*/
|
1999-10-31 00:43:29 +08:00
|
|
|
static struct urlstring {
|
2008-03-07 01:27:19 +08:00
|
|
|
const char const * leadin;
|
1999-10-31 00:43:29 +08:00
|
|
|
urltype ret;
|
2008-03-07 01:27:19 +08:00
|
|
|
} const urlstrings[] = {
|
1999-10-31 00:43:29 +08:00
|
|
|
{ "file://", URL_IS_PATH },
|
|
|
|
{ "ftp://", URL_IS_FTP },
|
2004-11-29 05:14:41 +08:00
|
|
|
{ "hkp://", URL_IS_HKP },
|
1999-10-31 00:43:29 +08:00
|
|
|
{ "http://", URL_IS_HTTP },
|
2004-11-04 21:29:11 +08:00
|
|
|
{ "https://", URL_IS_HTTPS },
|
1999-10-31 00:43:29 +08:00
|
|
|
{ NULL, URL_IS_UNKNOWN }
|
|
|
|
};
|
|
|
|
|
2001-06-06 03:26:22 +08:00
|
|
|
urltype urlIsURL(const char * url)
|
|
|
|
{
|
2008-03-07 01:27:19 +08:00
|
|
|
const struct urlstring *us;
|
1999-10-31 00:43:29 +08:00
|
|
|
|
1999-11-13 01:20:49 +08:00
|
|
|
if (url && *url) {
|
|
|
|
for (us = urlstrings; us->leadin != NULL; us++) {
|
2009-08-31 16:15:16 +08:00
|
|
|
if (!rstreqn(url, us->leadin, strlen(us->leadin)))
|
1999-11-13 01:20:49 +08:00
|
|
|
continue;
|
|
|
|
return us->ret;
|
|
|
|
}
|
2009-08-31 16:15:16 +08:00
|
|
|
if (rstreq(url, "-"))
|
2009-07-14 16:15:30 +08:00
|
|
|
return URL_IS_DASH;
|
1999-10-31 00:43:29 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return URL_IS_UNKNOWN;
|
|
|
|
}
|
|
|
|
|
1999-11-20 02:19:41 +08:00
|
|
|
/* Return path portion of url (or pointer to NUL if url == NULL) */
|
2000-08-28 02:34:02 +08:00
|
|
|
urltype urlPath(const char * url, const char ** pathp)
|
1999-11-13 01:20:49 +08:00
|
|
|
{
|
1999-11-19 02:07:46 +08:00
|
|
|
const char *path;
|
|
|
|
int urltype;
|
1999-11-13 01:20:49 +08:00
|
|
|
|
1999-11-19 02:07:46 +08:00
|
|
|
path = url;
|
|
|
|
urltype = urlIsURL(url);
|
1999-11-13 01:20:49 +08:00
|
|
|
switch (urltype) {
|
|
|
|
case URL_IS_FTP:
|
1999-11-24 08:03:54 +08:00
|
|
|
url += sizeof("ftp://") - 1;
|
|
|
|
path = strchr(url, '/');
|
|
|
|
if (path == NULL) path = url + strlen(url);
|
1999-11-13 01:20:49 +08:00
|
|
|
break;
|
|
|
|
case URL_IS_PATH:
|
1999-11-24 08:03:54 +08:00
|
|
|
url += sizeof("file://") - 1;
|
|
|
|
path = strchr(url, '/');
|
|
|
|
if (path == NULL) path = url + strlen(url);
|
1999-11-13 01:20:49 +08:00
|
|
|
break;
|
2004-11-29 05:14:41 +08:00
|
|
|
case URL_IS_HKP:
|
|
|
|
url += sizeof("hkp://") - 1;
|
|
|
|
path = strchr(url, '/');
|
|
|
|
if (path == NULL) path = url + strlen(url);
|
|
|
|
break;
|
2004-11-04 21:29:11 +08:00
|
|
|
case URL_IS_HTTP:
|
|
|
|
url += sizeof("http://") - 1;
|
|
|
|
path = strchr(url, '/');
|
|
|
|
if (path == NULL) path = url + strlen(url);
|
|
|
|
break;
|
|
|
|
case URL_IS_HTTPS:
|
|
|
|
url += sizeof("https://") - 1;
|
|
|
|
path = strchr(url, '/');
|
|
|
|
if (path == NULL) path = url + strlen(url);
|
|
|
|
break;
|
1999-11-13 01:20:49 +08:00
|
|
|
case URL_IS_UNKNOWN:
|
1999-11-24 08:03:54 +08:00
|
|
|
if (path == NULL) path = "";
|
1999-11-13 01:20:49 +08:00
|
|
|
break;
|
|
|
|
case URL_IS_DASH:
|
|
|
|
path = "";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (pathp)
|
|
|
|
*pathp = path;
|
|
|
|
return urltype;
|
|
|
|
}
|
|
|
|
|
1999-07-04 07:36:35 +08:00
|
|
|
/*
|
|
|
|
* Split URL into components. The URL can look like
|
2004-11-06 00:00:31 +08:00
|
|
|
* scheme://user:password@host:port/path
|
2007-06-25 15:40:14 +08:00
|
|
|
* or as in RFC2732 for IPv6 address
|
|
|
|
* service://user:password@[ip:v6:ad:dr:es:s]:port/path
|
1999-07-04 07:36:35 +08:00
|
|
|
*/
|
1999-11-02 22:33:14 +08:00
|
|
|
int urlSplit(const char * url, urlinfo *uret)
|
1999-07-04 07:36:35 +08:00
|
|
|
{
|
1999-11-02 22:33:14 +08:00
|
|
|
urlinfo u;
|
1999-07-04 07:36:35 +08:00
|
|
|
char *myurl;
|
|
|
|
char *s, *se, *f, *fe;
|
|
|
|
|
|
|
|
if (uret == NULL)
|
|
|
|
return -1;
|
2007-09-17 15:31:18 +08:00
|
|
|
if ((u = urlNew()) == NULL)
|
1999-07-04 07:36:35 +08:00
|
|
|
return -1;
|
|
|
|
|
1999-09-21 11:22:53 +08:00
|
|
|
if ((se = s = myurl = xstrdup(url)) == NULL) {
|
2007-09-17 15:31:18 +08:00
|
|
|
u = urlFree(u);
|
1999-07-04 07:36:35 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
1999-09-21 11:22:53 +08:00
|
|
|
u->url = xstrdup(url);
|
1999-11-24 08:03:54 +08:00
|
|
|
u->urltype = urlIsURL(url);
|
1999-07-04 07:36:35 +08:00
|
|
|
|
1999-10-21 05:40:10 +08:00
|
|
|
while (1) {
|
1999-07-04 07:36:35 +08:00
|
|
|
/* Point to end of next item */
|
|
|
|
while (*se && *se != '/') se++;
|
2004-11-06 00:00:31 +08:00
|
|
|
/* Item was scheme. Save scheme and go for the rest ...*/
|
1999-11-19 02:07:46 +08:00
|
|
|
if (*se && (se != s) && se[-1] == ':' && se[0] == '/' && se[1] == '/') {
|
1999-07-04 07:36:35 +08:00
|
|
|
se[-1] = '\0';
|
2004-11-06 00:00:31 +08:00
|
|
|
u->scheme = xstrdup(s);
|
1999-07-04 07:36:35 +08:00
|
|
|
se += 2; /* skip over "//" */
|
|
|
|
s = se++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
1999-12-13 05:14:05 +08:00
|
|
|
/* Item was everything-but-path. Continue parse on rest */
|
1999-07-04 07:36:35 +08:00
|
|
|
*se = '\0';
|
|
|
|
break;
|
1999-10-21 05:40:10 +08:00
|
|
|
}
|
1999-07-04 07:36:35 +08:00
|
|
|
|
|
|
|
/* Look for ...@host... */
|
|
|
|
fe = f = s;
|
|
|
|
while (*fe && *fe != '@') fe++;
|
|
|
|
if (*fe == '@') {
|
|
|
|
s = fe + 1;
|
|
|
|
*fe = '\0';
|
|
|
|
/* Look for user:password@host... */
|
|
|
|
while (fe > f && *fe != ':') fe--;
|
|
|
|
if (*fe == ':') {
|
|
|
|
*fe++ = '\0';
|
1999-09-21 11:22:53 +08:00
|
|
|
u->password = xstrdup(fe);
|
1999-07-04 07:36:35 +08:00
|
|
|
}
|
1999-09-21 11:22:53 +08:00
|
|
|
u->user = xstrdup(f);
|
1999-07-04 07:36:35 +08:00
|
|
|
}
|
|
|
|
|
2007-06-25 15:40:14 +08:00
|
|
|
/* Look for ...host:port or [v6addr]:port*/
|
1999-07-04 07:36:35 +08:00
|
|
|
fe = f = s;
|
2007-06-25 15:40:14 +08:00
|
|
|
if (strchr(fe, '[') && strchr(fe, ']'))
|
|
|
|
{
|
|
|
|
fe = strchr(f, ']');
|
|
|
|
*f++ = '\0';
|
|
|
|
*fe++ = '\0';
|
|
|
|
}
|
1999-07-04 07:36:35 +08:00
|
|
|
while (*fe && *fe != ':') fe++;
|
|
|
|
if (*fe == ':') {
|
|
|
|
*fe++ = '\0';
|
1999-09-21 11:22:53 +08:00
|
|
|
u->portstr = xstrdup(fe);
|
1999-07-04 07:36:35 +08:00
|
|
|
if (u->portstr != NULL && u->portstr[0] != '\0') {
|
|
|
|
char *end;
|
|
|
|
u->port = strtol(u->portstr, &end, 0);
|
|
|
|
if (!(end && *end == '\0')) {
|
2007-10-09 19:49:02 +08:00
|
|
|
rpmlog(RPMLOG_ERR, _("url port must be a number\n"));
|
2001-05-04 05:00:18 +08:00
|
|
|
myurl = _free(myurl);
|
2007-09-17 15:31:18 +08:00
|
|
|
u = urlFree(u);
|
1999-07-04 07:36:35 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
1999-09-21 11:22:53 +08:00
|
|
|
u->host = xstrdup(f);
|
1999-07-04 07:36:35 +08:00
|
|
|
|
2004-11-06 00:00:31 +08:00
|
|
|
if (u->port < 0 && u->scheme != NULL) {
|
1999-09-18 05:51:23 +08:00
|
|
|
struct servent *serv;
|
2004-11-29 05:14:41 +08:00
|
|
|
/* HACK hkp:// might lookup "pgpkeyserver" */
|
2004-11-06 00:00:31 +08:00
|
|
|
serv = getservbyname(u->scheme, "tcp");
|
1999-09-23 02:17:41 +08:00
|
|
|
if (serv != NULL)
|
1999-09-18 05:51:23 +08:00
|
|
|
u->port = ntohs(serv->s_port);
|
1999-11-24 08:03:54 +08:00
|
|
|
else if (u->urltype == URL_IS_FTP)
|
1999-07-04 07:36:35 +08:00
|
|
|
u->port = IPPORT_FTP;
|
2004-11-29 05:14:41 +08:00
|
|
|
else if (u->urltype == URL_IS_HKP)
|
|
|
|
u->port = IPPORT_PGPKEYSERVER;
|
1999-11-24 08:03:54 +08:00
|
|
|
else if (u->urltype == URL_IS_HTTP)
|
1999-07-04 07:36:35 +08:00
|
|
|
u->port = IPPORT_HTTP;
|
2004-11-04 21:29:11 +08:00
|
|
|
else if (u->urltype == URL_IS_HTTPS)
|
|
|
|
u->port = IPPORT_HTTPS;
|
1999-07-04 07:36:35 +08:00
|
|
|
}
|
|
|
|
|
2001-05-04 05:00:18 +08:00
|
|
|
myurl = _free(myurl);
|
1999-07-04 07:36:35 +08:00
|
|
|
if (uret) {
|
|
|
|
*uret = u;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2008-04-11 16:18:25 +08:00
|
|
|
|
2001-06-06 03:26:22 +08:00
|
|
|
int urlGetFile(const char * url, const char * dest)
|
|
|
|
{
|
2008-04-11 16:18:25 +08:00
|
|
|
char *cmd = NULL;
|
|
|
|
const char *target = NULL;
|
|
|
|
char *urlhelper = NULL;
|
1999-07-04 07:36:35 +08:00
|
|
|
int rc;
|
2008-04-11 16:18:25 +08:00
|
|
|
pid_t pid, wait;
|
1999-07-04 07:36:35 +08:00
|
|
|
|
2008-04-11 16:18:25 +08:00
|
|
|
urlhelper = rpmExpand("%{?_urlhelper}", NULL);
|
1999-07-04 07:36:35 +08:00
|
|
|
|
1999-12-13 01:46:22 +08:00
|
|
|
if (dest == NULL) {
|
2008-04-11 16:18:25 +08:00
|
|
|
urlPath(url, &target);
|
|
|
|
} else {
|
|
|
|
target = dest;
|
1999-12-13 01:46:22 +08:00
|
|
|
}
|
1999-07-04 07:36:35 +08:00
|
|
|
|
2008-04-11 16:18:25 +08:00
|
|
|
/* XXX TODO: sanity checks like target == dest... */
|
1999-07-04 07:36:35 +08:00
|
|
|
|
2008-04-11 16:18:25 +08:00
|
|
|
rasprintf(&cmd, "%s %s %s\n", urlhelper, target, url);
|
|
|
|
urlhelper = _free(urlhelper);
|
1999-07-04 07:36:35 +08:00
|
|
|
|
2008-04-11 16:18:25 +08:00
|
|
|
if ((pid = fork()) == 0) {
|
|
|
|
ARGV_t argv = NULL;
|
|
|
|
argvSplit(&argv, cmd, " ");
|
|
|
|
execvp(argv[0], argv);
|
2008-11-04 17:09:31 +08:00
|
|
|
exit(127); /* exit with 127 for compatibility with bash(1) */
|
2008-04-11 16:18:25 +08:00
|
|
|
}
|
|
|
|
wait = waitpid(pid, &rc, 0);
|
|
|
|
cmd = _free(cmd);
|
1999-07-04 07:36:35 +08:00
|
|
|
|
|
|
|
return rc;
|
2008-04-11 16:18:25 +08:00
|
|
|
|
1999-07-04 07:36:35 +08:00
|
|
|
}
|