Hi.
I'm using apache as proxy server to access the internet. Unfortunately,
rpm still tries to open a "real" ftp connection for 'ftp://...' urls,
even when a proxy is given.
So i modified the openpkg rpm sources. There are two new settings:
'l_force_httpproxy' and 'l_noproxy'.
If 'l_force_httpproxy' is set to any value, the http proxy is also used
for urls of the form "ftp://...".
'l_noproxy' holds a comma separated list of hosts/domains where no
proxy should be used (independent from l_force_httpproxy).
Example settings, e.g. in $HOME/.rpmmacros:
%_httpproxy myProxy.local.domain
%l_force_httpproxy 1
%l_noproxy localhost,local.domain
--
Matthias Kurz; Fuldastr. 3; D-28199 Bremen; VOICE +49 421 53 600 47
>> Im pr�motorischen Cortex kann jeder ein Held sein. (bdw) <<
diff -u -r rpm-4.0.2-opkg/rpmio/rpmio.c rpm-4.0.2-mk/rpmio/rpmio.c
--- rpm-4.0.2-opkg/rpmio/rpmio.c Mon Mar 12 19:20:29 2001
+++ rpm-4.0.2-mk/rpmio/rpmio.c Mon Dec 30 16:53:30 2002
@@ -1325,7 +1325,7 @@
const char * path;
int port;
int rc;
- char * req;
+ char * req, * h;
size_t len;
int retrying = 0;
@@ -1362,23 +1362,30 @@
req = alloca(len);
*req = '\0';
+ /* if forceHttpProxy is given, the "Host:"-part is left up to the Proxy */
+ len = sizeof("Host: y:z\r\n") + strlen(host) + 20;
+ h = alloca(len);
+ *h = '\0';
+ if (!u->forceHttpProxy)
+ sprintf(h, "Host: %s:%d\n\n", host, port);
+
if (!strcmp(httpCmd, "PUT")) {
sprintf(req, "\
%s %s HTTP/1.%d\r\n\
User-Agent: rpm/%s\r\n\
-Host: %s:%d\r\n\
+%s\
Accept: text/plain\r\n\
Transfer-Encoding: chunked\r\n\
\r\n\
-", httpCmd, path, (u->httpVersion ? 1 : 0), VERSION, host, port);
+", httpCmd, path, (u->httpVersion ? 1 : 0), VERSION, h);
} else {
sprintf(req, "\
%s %s HTTP/1.%d\r\n\
User-Agent: rpm/%s\r\n\
-Host: %s:%d\r\n\
+%s\
Accept: text/plain\r\n\
\r\n\
-", httpCmd, path, (u->httpVersion ? 1 : 0), VERSION, host, port);
+", httpCmd, path, (u->httpVersion ? 1 : 0), VERSION, h);
}
if (_ftp_debug)
diff -u -r rpm-4.0.2-opkg/rpmio/rpmurl.h rpm-4.0.2-mk/rpmio/rpmurl.h
--- rpm-4.0.2-opkg/rpmio/rpmurl.h Mon Dec 11 19:41:27 2000
+++ rpm-4.0.2-mk/rpmio/rpmurl.h Mon Dec 30 14:36:03 2002
@@ -35,6 +35,7 @@
const char * proxyu; /*!< FTP: proxy user */
const char * proxyh; /*!< FTP/HTTP: proxy host */
int proxyp; /*!< FTP/HTTP: proxy port */
+ int forceHttpProxy; /*!< FTP over HTTP proxy */
int port;
int urltype;
FD_t ctrl; /*!< control channel */
@@ -87,8 +88,41 @@
*/
void urlFreeCache(void);
+
+/**
+ * Checks whether host is equal to or ends in an entry from l_noproxy.
+ * @param host host name
+ * @return 1 if entry found, 0 if not
+ */
+int noProxy(const char *host);
+
+/**
+ * Return host that should be used as ftp proxy. Checks also for l_noproxy.
+ * @param host host name (checked against l_noproxy if not NULL)
+ * @return host to use as proxy, NULL if none
+ */
+char *getFtpProxy(const char *host);
+
+/**
+ * Return host that should be used as http proxy. Checks also for l_noproxy.
+ * @param host host name (checked against l_noproxy if not NULL)
+ * @return host to use as proxy, NULL if none
+ */
+char *getHttpProxy(const char *host);
+
+/**
+ * Check, whether l_force_HttpProxy is defined. Makes only sense, if there
+ * is also a _httpproxy setting !
+ * Either url or host name must be NULL.
+ * @param url url
+ * @param host host name
+ * @return 1 if defined, 0 if not
+ */
+int forceHttpProxy(const char *url, const char *host);
+
/**
* Return type of URL.
+ * Lie (return URL_IS_HTTP), when l_forceHttpProxy is set
* @param url url string
* @return type of url
*/
diff -u -r rpm-4.0.2-opkg/rpmio/url.c rpm-4.0.2-mk/rpmio/url.c
--- rpm-4.0.2-opkg/rpmio/url.c Mon Dec 11 19:41:27 2000
+++ rpm-4.0.2-mk/rpmio/url.c Mon Dec 30 14:44:10 2002
@@ -54,6 +54,7 @@
return NULL;
memset(u, 0, sizeof(*u));
u->proxyp = -1;
+ u->forceHttpProxy = 0;
u->port = -1;
u->urltype = URL_IS_UNKNOWN;
u->ctrl = NULL;
@@ -217,6 +218,7 @@
/* Perform one-time FTP initialization */
if (u->urltype == URL_IS_FTP) {
+ int ignoreProxy = noProxy(u->host);
if (mustAsk || (u->user != NULL && u->password == NULL)) {
char * prompt;
@@ -227,8 +229,8 @@
u->password = xstrdup(u->password); /* XXX xstrdup has side effects. */
}
- if (u->proxyh == NULL) {
- const char *proxy = rpmExpand("%{_ftpproxy}", NULL);
+ if (u->proxyh == NULL && !ignoreProxy) {
+ const char *proxy = getFtpProxy(NULL);
if (proxy && *proxy != '%') {
const char *uu = (u->user ? u->user : "anonymous");
char *nu = xmalloc(strlen(uu) + sizeof("@") + strlen(u->host));
@@ -239,7 +241,7 @@
free((void *)proxy);
}
- if (u->proxyp < 0) {
+ if (u->proxyp < 0 && !ignoreProxy) {
const char *proxy = rpmExpand("%{_ftpport}", NULL);
if (proxy && *proxy != '%') {
char *end;
@@ -257,15 +259,18 @@
/* Perform one-time HTTP initialization */
if (u->urltype == URL_IS_HTTP) {
+ int ignoreProxy = noProxy(u->host);
- if (u->proxyh == NULL) {
- const char *proxy = rpmExpand("%{_httpproxy}", NULL);
- if (proxy && *proxy != '%')
+ if (u->proxyh == NULL && !ignoreProxy) {
+ const char *proxy = getHttpProxy(NULL);
+ if (proxy && *proxy != '%') {
u->proxyh = xstrdup(proxy);
+ u->forceHttpProxy = forceHttpProxy(NULL, u->host);
+ }
free((void *)proxy);
}
- if (u->proxyp < 0) {
+ if (u->proxyp < 0 && !ignoreProxy) {
const char *proxy = rpmExpand("%{_httpport}", NULL);
if (proxy && *proxy != '%') {
char *end;
@@ -296,6 +301,92 @@
{ NULL, URL_IS_UNKNOWN }
};
+/* l_noproxy is a comma-separated list of hosts/domains where no proxy
+ * should be used. E.g. with l_noproxy == "localhost,local-domain.org",
+ * no proxy will be used for hosts with names equal to "localhost" or
+ * "local-domain.org" or ending in ".localhost" or ".local-domain.org"
+ */
+int noProxy(const char *host)
+{
+ char *noProxy = rpmExpand("%{l_noproxy}", NULL), *eStart, *eEnd, *dot;
+ int hLen, eLen;
+
+ if (noProxy == NULL || *noProxy == '%') {
+ free((void *)noProxy);
+ return 0;
+ }
+
+ eStart = noProxy;
+ hLen = strlen(host);
+ do {
+ eEnd = strchr(eStart, ',');
+ if (eEnd != NULL) {
+ *eEnd = '\0';
+ eLen = eEnd - eStart;
+ } else {
+ eLen = strlen(eStart);
+ }
+ if (eLen <= hLen) {
+ if (eLen == hLen && strcasecmp(eStart, host) == 0) {
+ free((void *)noProxy);
+ return 1;
+ } else {
+ dot = (char *)host; /* discard 'const', avoid compiler
+ * warning for next statement */
+ dot = &dot[hLen-eLen-1];
+ if (*dot == '.' && strcasecmp(eStart, dot+1) == 0) {
+ free((void *)noProxy);
+ return 1;
+ }
+ }
+ }
+ if (eEnd != NULL) eStart = eEnd + 1;
+ } while (eEnd != NULL);
+ free((void *)noProxy);
+ return 0;
+}
+
+char *getFtpProxy(const char *host)
+{
+ if (host && noProxy(host)) return NULL;
+ return rpmExpand("%{_ftpproxy}", NULL);
+}
+
+char *getHttpProxy(const char *host)
+{
+ if (host && noProxy(host)) return NULL;
+ return rpmExpand("%{_httpproxy}", NULL);
+}
+
+int forceHttpProxy(const char *url, const char *host)
+{
+ char *rcEntryForce = rpmExpand("%{l_force_httpproxy}", NULL);
+ int set;
+
+ set = (rcEntryForce && *rcEntryForce != '%');
+ free((void *)rcEntryForce);
+ if (!set) return 0;
+
+ if (host != NULL) {
+ set = !noProxy(host);
+ } else {
+ char *myUrl = strdup(url), *hStart, *hEnd;
+
+ set = 0;
+ hStart = strchr(myUrl, '/');
+ if (hStart != NULL && hStart[1] == '/') {
+ hStart += 2;
+ hEnd = strchr(hStart, '/');
+ if (hEnd != NULL) *hEnd = '\0';
+ hEnd = strchr(hStart, ':');
+ if (hEnd != NULL) *hEnd = '\0';
+ set = !noProxy(hStart);
+ }
+ free((void *)myUrl);
+ }
+ return set;
+}
+
urltype urlIsURL(const char * url) {
struct urlstring *us;
@@ -303,6 +394,9 @@
for (us = urlstrings; us->leadin != NULL; us++) {
if (strncmp(url, us->leadin, strlen(us->leadin)))
continue;
+ if (us->ret == URL_IS_FTP && forceHttpProxy(url, NULL)) {
+ return URL_IS_HTTP;
+ }
return us->ret;
}
}
@@ -326,8 +420,10 @@
break;
case URL_IS_HTTP:
case URL_IS_PATH:
- url += sizeof("file://") - 1;
+ /* caution: -> forceHttpProxy; better 2 times strchr(url, '/') */
+ /* url += sizeof("file://") - 1; */
path = strchr(url, '/');
+ if (path != NULL && path[1] == '/') path = strchr(path+2, '/');
if (path == NULL) path = url + strlen(url);
break;
case URL_IS_UNKNOWN:
@@ -373,7 +469,12 @@
/* Item was service. Save service and go for the rest ...*/
if (*se && (se != s) && se[-1] == ':' && se[0] == '/' && se[1] == '/') {
se[-1] = '\0';
- u->service = xstrdup(s);
+ switch (u->urltype) {
+ case URL_IS_HTTP:
+ u->service = xstrdup("http"); break;
+ default:
+ u->service = xstrdup(s);
+ }
se += 2; /* skip over "//" */
s = se++;
continue;