Add support for the NO_PROXY / no_proxy environment variable as used by

lynx, curl etc.  Note that this patch differs significantly from that
in the PR, as the submitter refined it after submitting the PR.

PR:		110388
Submitted by:	Alexander Pohoyda <alexander.pohoyda@gmx.net>
MFC after:	3 weeks
This commit is contained in:
Dag-Erling Smørgrav 2007-12-18 11:03:07 +00:00
parent 836e34eeae
commit 62a2681c93
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=174752
4 changed files with 63 additions and 8 deletions

View File

@ -33,8 +33,10 @@ __FBSDID("$FreeBSD$");
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/uio.h>
#include <netinet/in.h>
#include <ctype.h>
#include <errno.h>
#include <netdb.h>
#include <pwd.h>
@ -734,3 +736,51 @@ fetch_netrc_auth(struct url *url)
fclose(f);
return (-1);
}
/*
* The no_proxy environment variable specifies a set of domains for
* which the proxy should not be consulted; the contents is a comma-,
* or space-separated list of domain names. A single asterisk will
* override all proxy variables and no transactions will be proxied
* (for compatability with lynx and curl, see the discussion at
* <http://curl.haxx.se/mail/archive_pre_oct_99/0009.html>).
*/
int
fetch_no_proxy_match(const char *host)
{
const char *no_proxy, *p, *q;
size_t h_len, d_len;
if ((no_proxy = getenv("NO_PROXY")) == NULL &&
(no_proxy = getenv("no_proxy")) == NULL)
return (0);
/* asterisk matches any hostname */
if (strcmp(no_proxy, "*") == 0)
return (1);
h_len = strlen(host);
p = no_proxy;
do {
/* position p at the beginning of a domain suffix */
while (*p == ',' || isspace((int)*p))
p++;
/* position q at the first separator character */
for (q = p; *q; ++q)
if (*q == ',' || isspace((int)*q))
break;
d_len = q - p;
if (d_len > 0 && h_len > d_len &&
strncasecmp(host + h_len - d_len,
p, d_len) == 0) {
/* domain name matches */
return (1);
}
p = q + 1;
} while (*q);
return (0);
}

View File

@ -90,6 +90,7 @@ int fetch_close(conn_t *);
int fetch_add_entry(struct url_ent **, int *, int *,
const char *, struct url_stat *);
int fetch_netrc_auth(struct url *url);
int fetch_no_proxy_match(const char *);
#define ftp_seterr(n) fetch_seterr(ftp_errlist, n)
#define http_seterr(n) fetch_seterr(http_errlist, n)

View File

@ -1057,13 +1057,15 @@ ftp_cached_connect(struct url *url, struct url *purl, const char *flags)
* Check the proxy settings
*/
static struct url *
ftp_get_proxy(const char *flags)
ftp_get_proxy(struct url * url, const char *flags)
{
struct url *purl;
char *p;
if (flags != NULL && strchr(flags, 'd') != NULL)
return (NULL);
if (fetch_no_proxy_match(url->host))
return (NULL);
if (((p = getenv("FTP_PROXY")) || (p = getenv("ftp_proxy")) ||
(p = getenv("HTTP_PROXY")) || (p = getenv("http_proxy"))) &&
*p && (purl = fetchParseURL(p)) != NULL) {
@ -1140,7 +1142,7 @@ ftp_request(struct url *url, const char *op, struct url_stat *us,
FILE *
fetchXGetFTP(struct url *url, struct url_stat *us, const char *flags)
{
return (ftp_request(url, "RETR", us, ftp_get_proxy(flags), flags));
return (ftp_request(url, "RETR", us, ftp_get_proxy(url, flags), flags));
}
/*
@ -1158,9 +1160,8 @@ fetchGetFTP(struct url *url, const char *flags)
FILE *
fetchPutFTP(struct url *url, const char *flags)
{
return (ftp_request(url, CHECK_FLAG('a') ? "APPE" : "STOR", NULL,
ftp_get_proxy(flags), flags));
ftp_get_proxy(url, flags), flags));
}
/*
@ -1171,9 +1172,10 @@ fetchStatFTP(struct url *url, struct url_stat *us, const char *flags)
{
FILE *f;
f = ftp_request(url, "STAT", us, ftp_get_proxy(flags), flags);
f = ftp_request(url, "STAT", us, ftp_get_proxy(url, flags), flags);
if (f == NULL)
return (-1);
fclose(f);
return (0);
}

View File

@ -719,13 +719,15 @@ http_connect(struct url *URL, struct url *purl, const char *flags)
}
static struct url *
http_get_proxy(const char *flags)
http_get_proxy(struct url * url, const char *flags)
{
struct url *purl;
char *p;
if (flags != NULL && strchr(flags, 'd') != NULL)
return (NULL);
if (fetch_no_proxy_match(url->host))
return (NULL);
if (((p = getenv("HTTP_PROXY")) || (p = getenv("http_proxy"))) &&
*p && (purl = fetchParseURL(p))) {
if (!*purl->scheme)
@ -1168,7 +1170,7 @@ http_request(struct url *URL, const char *op, struct url_stat *us,
FILE *
fetchXGetHTTP(struct url *URL, struct url_stat *us, const char *flags)
{
return (http_request(URL, "GET", us, http_get_proxy(flags), flags));
return (http_request(URL, "GET", us, http_get_proxy(URL, flags), flags));
}
/*
@ -1198,7 +1200,7 @@ fetchStatHTTP(struct url *URL, struct url_stat *us, const char *flags)
{
FILE *f;
f = http_request(URL, "HEAD", us, http_get_proxy(flags), flags);
f = http_request(URL, "HEAD", us, http_get_proxy(URL, flags), flags);
if (f == NULL)
return (-1);
fclose(f);