From f0e1aa6917a14f5641e43cf944cacb2e1aa83223 Mon Sep 17 00:00:00 2001 From: des Date: Tue, 18 Dec 2007 11:03:07 +0000 Subject: 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 MFC after: 3 weeks --- lib/libfetch/common.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ lib/libfetch/common.h | 1 + lib/libfetch/ftp.c | 12 +++++++----- lib/libfetch/http.c | 8 +++++--- 4 files changed, 63 insertions(+), 8 deletions(-) (limited to 'lib/libfetch') diff --git a/lib/libfetch/common.c b/lib/libfetch/common.c index dc9eee0..936524f 100644 --- a/lib/libfetch/common.c +++ b/lib/libfetch/common.c @@ -33,8 +33,10 @@ __FBSDID("$FreeBSD$"); #include #include #include + #include +#include #include #include #include @@ -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 + * ). + */ +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); +} diff --git a/lib/libfetch/common.h b/lib/libfetch/common.h index 2382eb0..05bee03 100644 --- a/lib/libfetch/common.h +++ b/lib/libfetch/common.h @@ -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) diff --git a/lib/libfetch/ftp.c b/lib/libfetch/ftp.c index bac5c72..4316346e 100644 --- a/lib/libfetch/ftp.c +++ b/lib/libfetch/ftp.c @@ -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); } diff --git a/lib/libfetch/http.c b/lib/libfetch/http.c index 909b91c..c89f5f1 100644 --- a/lib/libfetch/http.c +++ b/lib/libfetch/http.c @@ -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 @@ ouch: 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); -- cgit v1.1