On Tue, Aug 07, 2012 at 11:50:26AM -0400, Eric P. Mangold wrote: > Sorry for the top-post > > I was wondering if some of you (active) 'ftp' maintainers could evaluate my > patch below. > > I posted this to the list ages ago, and tried following up with some former > committers on the ftp code, but for whatever reason I never received any > communication at all. > > It is a very simple patch, if someone could review it, and let me know if > this is OK or not. > > I would apprciate it. > > original message follows... > > Hi, > > I was trying to use the 'ftp' program to retrieve the following URL: > > https://pypi.python.org/packages/source/p/pip/pip-1.0.2.tar.gz#md5=47ec6ff3f6d962696fe08d4c8264ad49 > > Which fails because it considers the fragment as part of the path, and > so the server returns 404. These type of links are quite common these > days and so it would be nice if 'ftp' would handle them. > > This is my first patch to OpenBSD, so please let me know if there is > anyhthing else I can do to get this feature implemented. The patch is > very simple, and I think, correct, as '#' is an "unsafe" character, and > must always be URL-encoded if it is to appear literally in a URL and > not be interpreted as the start of a fragment identifier. >
I would prefer this to be done on the path processing block, if possible. Just make sure you test the scheme for http/https, sorry for slacking on the revision. Could you give it a try ? if (isfileurl) { path = host; } else { path = strchr(host, '/'); /* Find path */ if (EMPTYSTRING(path)) { if (outfile) { /* No slash, but */ path=strchr(host,'\0'); /* we have outfile. */ goto noslash; } if (isftpurl) goto noftpautologin; warnx("No `/' after host (use -o): %s", origline); goto cleanup_url_get; } *path++ = '\0'; ================> probably here if (EMPTYSTRING(path) && !outfile) { if (isftpurl) goto noftpautologin; warnx("No filename after host (use -o): %s", origline); goto cleanup_url_get; } } > Regards, > Eric P. Mangold > > Index: fetch.c > =================================================================== > RCS file: /cvs/src/usr.bin/ftp/fetch.c,v > retrieving revision 1.103 > diff -u -r1.103 fetch.c > --- fetch.c 25 Aug 2010 20:32:37 -0000 1.103 > +++ fetch.c 29 Oct 2011 03:34:02 -0000 > @@ -205,6 +205,11 @@ > if (newline == NULL) > errx(1, "Can't allocate memory to parse URL"); > if (strncasecmp(newline, HTTP_URL, sizeof(HTTP_URL) - 1) == 0) { > + /* Remove any trailing fragment identifier from the HTTP URL. > + * Fragments (HTTP anchors) are identified by a hash char > ('#'), > + * as per RFC 3986. */ > + newline = strsep(&newline, "#"); > + > host = newline + sizeof(HTTP_URL) - 1; > #ifndef SMALL > scheme = HTTP_URL; > @@ -221,6 +226,11 @@ > #ifndef SMALL > scheme = FILE_URL; > } else if (strncasecmp(newline, HTTPS_URL, sizeof(HTTPS_URL) - 1) == > 0) { > + /* Remove any trailing fragment identifier from the HTTPS > URL. > + * Fragments (HTTP anchors) are identified by a hash char > ('#'), > + * as per RFC 3986. */ > + newline = strsep(&newline, "#"); > + > host = newline + sizeof(HTTPS_URL) - 1; > ishttpsurl = 1; > scheme = HTTPS_URL; > > > On Mon, Aug 06, 2012 at 10:56:28PM +0200, Christiano F. Haesbaert wrote: > > Please ignore the other thread, it takes ages for me to open my sent box > > over gprs, so I'm opening a new one. > > > > > > Index: fetch.c > > =================================================================== > > RCS file: /cvs/src/usr.bin/ftp/fetch.c,v > > retrieving revision 1.105 > > diff -d -u -p -r1.105 fetch.c > > --- fetch.c 30 Apr 2012 13:41:26 -0000 1.105 > > +++ fetch.c 6 Aug 2012 20:49:51 -0000 > > @@ -177,7 +177,7 @@ url_get(const char *origline, const char > > { > > char pbuf[NI_MAXSERV], hbuf[NI_MAXHOST], *cp, *portnum, *path, ststr[4]; > > char *hosttail, *cause = "unknown", *newline, *host, *port, *buf = NULL; > > - char *epath, *redirurl, *loctail; > > + char *epath, *redirurl, *loctail, *h, *p; > > int error, i, isftpurl = 0, isfileurl = 0, isredirect = 0, rval = -1; > > struct addrinfo hints, *res0, *res, *ares = NULL; > > const char * volatile savefile; > > @@ -191,7 +191,7 @@ url_get(const char *origline, const char > > size_t len, wlen; > > #ifndef SMALL > > char *sslpath = NULL, *sslhost = NULL; > > - char *locbase, *full_host = NULL; > > + char *locbase, *full_host = NULL, *auth = NULL; > > const char *scheme; > > int ishttpsurl = 0; > > SSL_CTX *ssl_ctx = NULL; > > @@ -228,7 +228,20 @@ url_get(const char *origline, const char > > #endif /* !SMALL */ > > } else > > errx(1, "url_get: Invalid URL '%s'", newline); > > - > > +#ifndef SMALL > > + /* Look for auth header */ > > + if (proxyenv == NULL && > > + (!strcmp(scheme, HTTP_URL) || !strcmp(scheme, HTTPS_URL))) { > > + if ((p = strchr(host, '@')) != NULL) { > > + *p = 0; /* Kill @ */ > > + if ((auth = calloc(1, 64)) == NULL) > > + err(1, "Can't allocate memory for > > authorization"); > > + if (b64_ntop(host, strlen(host), auth, 64) == -1) > > + errx(1, "error in base64 encoding"); > > + host = p + 1; > > + } > > + } > > +#endif /* SMALL */ > > if (isfileurl) { > > path = host; > > } else { > > @@ -639,14 +652,19 @@ again: > > restart_point = 0; > > } > > #endif /* !SMALL */ > > - ftp_printf(fin, ssl, "GET /%s %s\r\nHost: ", epath, > > #ifndef SMALL > > - restart_point ? "HTTP/1.1\r\nConnection: close" : > > -#endif /* !SMALL */ > > - "HTTP/1.0"); > > + if (auth) { > > + ftp_printf(fin, ssl, > > + "GET /%s %s\r\nAuthorization: Basic %s\r\nHost: ", > > + epath, restart_point ? > > + "HTTP/1.1\r\nConnection: close" : "HTTP/1.0", > > + auth); > > + free(auth); > > + } else > > +#endif /* SMALL */ > > + ftp_printf(fin, ssl, "GET /%s %s\r\nHost: ", epath, > > + "HTTP/1.0"); > > if (strchr(host, ':')) { > > - char *h, *p; > > - > > /* > > * strip off scoped address portion, since it's > > * local to node > > Index: ftp.1 > > =================================================================== > > RCS file: /cvs/src/usr.bin/ftp/ftp.1,v > > retrieving revision 1.82 > > diff -d -u -p -r1.82 ftp.1 > > --- ftp.1 30 Apr 2012 13:41:26 -0000 1.82 > > +++ ftp.1 6 Aug 2012 20:22:14 -0000 > > @@ -61,7 +61,8 @@ > > .Op Fl o Ar output > > .Op Fl s Ar srcaddr > > .Sm off > > -.No http:// Ar host Oo : Ar port > > +.No http:// Oo Ar user : password No @ > > +.Oc Ar host Oo : Ar port > > .Oc No / Ar file > > .Sm on > > .Ar ... > > @@ -71,7 +72,8 @@ > > .Op Fl o Ar output > > .Op Fl s Ar srcaddr > > .Sm off > > -.No https:// Ar host Oo : Ar port > > +.No https:// Oo Ar user : password No @ > > +.Oc Ar host Oo : Ar port > > .Oc No / Ar file > > .Sm on > > .Ar ... > > @@ -1278,12 +1280,12 @@ isn't defined, log in as > > .Ar user > > with a password of > > .Ar password . > > -.It http://host[:port]/file > > +.It http://[user:password@]host[:port]/file > > An HTTP URL, retrieved using the HTTP protocol. > > If > > .Ev http_proxy > > is defined, it is used as a URL to an HTTP proxy server. > > -.It https://host[:port]/file > > +.It https://[user:password@]host[:port]/file > > An HTTPS URL, retrieved using the HTTPS protocol. > > If > > .Ev http_proxy > > Index: main.c > > =================================================================== > > RCS file: /cvs/src/usr.bin/ftp/main.c,v > > retrieving revision 1.83 > > diff -d -u -p -r1.83 main.c > > --- main.c 19 May 2012 02:04:22 -0000 1.83 > > +++ main.c 6 Aug 2012 19:54:15 -0000 > > @@ -775,12 +775,14 @@ usage(void) > > #endif /* !SMALL */ > > "[-o output] " > > #ifndef SMALL > > - "[-s srcaddr] " > > + "[-s srcaddr]\n" > > + " " > > #endif /* !SMALL */ > > - "http://host[:port]/file ...\n" > > + "http://[user:password@]host[:port]/file ...\n" > > #ifndef SMALL > > - " %s [-C] [-c cookie] [-o output] [-s srcaddr] " > > - "https://host[:port]/file\n" > > + " %s [-C] [-c cookie] [-o output] [-s srcaddr]\n" > > + " " > > + "https://[user:password@]host[:port]/file\n" > > " ...\n" > > #endif /* !SMALL */ > > " %s "