diff -uNpr anaconda-orig/loader2/ftp.c anaconda/loader2/ftp.c --- anaconda-orig/loader2/ftp.c 2005-03-01 23:52:39.126295819 -0500 +++ anaconda/loader2/ftp.c 2005-03-01 23:52:59.354142766 -0500 @@ -432,129 +432,3 @@ const char *ftpStrerror(int errorNumber, } } -/* extraHeaders is either NULL or a string with extra headers separated by '\r\n', ending with - * '\r\n' - */ -int httpGetFileDesc(char * hostname, int port, char * remotename, char *extraHeaders) { - char * buf; - struct timeval timeout; - char headers[4096]; - char * nextChar = headers; - char *realhost; - char *hstr; - int checkedCode; - struct in_addr serverAddress; - int sock; - int rc; - struct sockaddr_in destPort; - fd_set readSet; - - realhost = hostname; - if (port < 0) { - char *colonptr = strchr(hostname, ':'); - if (colonptr != NULL) { - int realhostlen = colonptr - hostname; - port = atoi(colonptr + 1); - realhost = alloca (realhostlen + 1); - memcpy (realhost, hostname, realhostlen); - realhost[realhostlen] = '\0'; - } else { - port = 80; - } - } - - if ((rc = getHostAddress(realhost, &serverAddress))) return rc; - - sock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); - if (sock < 0) { - return FTPERR_FAILED_CONNECT; - } - - destPort.sin_family = AF_INET; - destPort.sin_port = htons(port); - destPort.sin_addr = serverAddress; - - if (connect(sock, (struct sockaddr *) &destPort, sizeof(destPort))) { - close(sock); - return FTPERR_FAILED_CONNECT; - } - - if (extraHeaders) - hstr = extraHeaders; - else - hstr = ""; - - buf = alloca(strlen(remotename) + strlen(realhost) + strlen(hstr) + 25); - sprintf(buf, "GET %s HTTP/1.0\r\nHost: %s\r\n%s\r\n", remotename, realhost, hstr); - rc = write(sock, buf, strlen(buf)); - - /* This is fun; read the response a character at a time until we: - - 1) Get our first \r\n; which lets us check the return code - 2) Get a \r\n\r\n, which means we're done */ - - *nextChar = '\0'; - checkedCode = 0; - while (!strstr(headers, "\r\n\r\n")) { - FD_ZERO(&readSet); - FD_SET(sock, &readSet); - - timeout.tv_sec = TIMEOUT_SECS; - timeout.tv_usec = 0; - - rc = select(sock + 1, &readSet, NULL, NULL, &timeout); - if (rc == 0) { - close(sock); - return FTPERR_SERVER_TIMEOUT; - } else if (rc < 0) { - close(sock); - return FTPERR_SERVER_IO_ERROR; - } - - if (read(sock, nextChar, 1) != 1) { - close(sock); - return FTPERR_SERVER_IO_ERROR; - } - - nextChar++; - *nextChar = '\0'; - - if (nextChar - headers == sizeof(headers)) { - close(sock); - return FTPERR_SERVER_IO_ERROR; - } - - if (!checkedCode && strstr(headers, "\r\n")) { - char * start, * end; - - checkedCode = 1; - start = headers; - while (!isspace(*start) && *start) start++; - if (!*start) { - close(sock); - return FTPERR_SERVER_IO_ERROR; - } - start++; - - end = start; - while (!isspace(*end) && *end) end++; - if (!*end) { - close(sock); - return FTPERR_SERVER_IO_ERROR; - } - - *end = '\0'; - if (!strcmp(start, "404")) { - close(sock); - return FTPERR_FILE_NOT_FOUND; - } else if (strcmp(start, "200")) { - close(sock); - return FTPERR_BAD_SERVER_RESPONSE; - } - - *end = ' '; - } - } - - return sock; -} diff -uNpr anaconda-orig/loader2/ftp.h anaconda/loader2/ftp.h --- anaconda-orig/loader2/ftp.h 2005-03-01 23:52:39.114297093 -0500 +++ anaconda/loader2/ftp.h 2005-03-01 23:52:59.354142766 -0500 @@ -23,6 +23,4 @@ int ftpGetFile(int sock, char * remotena int ftpGetFileDesc(int sock, char * remotename); int ftpGetFileDone(int sock); -int httpGetFileDesc(char * hostname, int port, char * remotename, char *extraHeaders); - #endif diff -uNpr anaconda-orig/loader2/http.c anaconda/loader2/http.c --- anaconda-orig/loader2/http.c 1969-12-31 19:00:00.000000000 -0500 +++ anaconda/loader2/http.c 2005-03-01 23:58:30.582446794 -0500 @@ -0,0 +1,271 @@ +/* + * http.c - http code + * + * HTTP Authorization from Wget from Free Software Foundation, Inc. + * + * Based on ftp.c by: + * Erik Troan + * Matt Wilson + * Jeremy Katz + * + * Copyright 1997 - 2002 Red Hat, Inc. + * + * This software may be freely redistributed under the terms of the GNU + * General Public License. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + + +#define HAVE_ALLOCA_H 1 +#define HAVE_NETINET_IN_SYSTM_H 1 +#define HAVE_SYS_SOCKET_H 1 +#define USE_ALT_DNS 1 + +#if HAVE_ALLOCA_H +# include +#endif + +#if HAVE_SYS_SOCKET_H +# include +#endif + +#if HAVE_NETINET_IN_SYSTM_H +# include +# include +#endif + +#if ! HAVE_HERRNO +extern int h_errno; +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define TIMEOUT_SECS 60 + +#if defined(USE_ALT_DNS) && USE_ALT_DNS +#include "../isys/dns.h" +#endif + +#include "ftp.h" +#include "http.h" + +static void httpBase64Encode(const char *s, char *store, int length); +static char * httpBasicAuthenticationEncode(const char *user, const char *passwd, const char *header); + +/* Authorization support: We support one authorization schemes: + 'Basic' scheme, consisting of base64-ing USER:PASSWORD string; +*/ + +/* How many bytes it will take to store LEN bytes in base64. */ +#define BASE64_LENGTH(len) (4 * (((len) + 2) / 3)) + +/* Encode the string S of length LENGTH to base64 format and place it + to STORE. STORE will be 0-terminated, and must point to a writable + buffer of at least 1+BASE64_LENGTH(length) bytes. */ +static void +httpBase64Encode(const char *s, char *store, int length) { + /* Conversion table. */ + static char tbl[64] = { + 'A','B','C','D','E','F','G','H', + 'I','J','K','L','M','N','O','P', + 'Q','R','S','T','U','V','W','X', + 'Y','Z','a','b','c','d','e','f', + 'g','h','i','j','k','l','m','n', + 'o','p','q','r','s','t','u','v', + 'w','x','y','z','0','1','2','3', + '4','5','6','7','8','9','+','/' + }; + int i; + unsigned char *p = (unsigned char *)store; + + /* Transform the 3x8 bits to 4x6 bits, as required by base64. */ + for (i = 0; i < length; i += 3) { + *p++ = tbl[s[0] >> 2]; + *p++ = tbl[((s[0] & 3) << 4) + (s[1] >> 4)]; + *p++ = tbl[((s[1] & 0xf) << 2) + (s[2] >> 6)]; + *p++ = tbl[s[2] & 0x3f]; + s += 3; + } + + /* Pad the result if necessary... */ + if (i == length + 1) + *(p - 1) = '='; + else if (i == length + 2) + *(p - 1) = *(p - 2) = '='; + /* ...and zero-terminate it. */ + *p = '\0'; +} + +/* Create the authentication header contents for the `Basic' scheme. + This is done by encoding the string `USER:PASS' in base64 and + prepending `HEADER: Basic ' to it. */ +static char * +httpBasicAuthenticationEncode(const char *user, const char *passwd, + const char *header) { + char *t1, *t2, *res; + int len1 = strlen (user) + 1 + strlen (passwd); + int len2 = BASE64_LENGTH (len1); + + t1 = (char *)alloca (len1 + 1); + sprintf (t1, "%s:%s", user, passwd); + t2 = (char *)alloca (1 + len2); + httpBase64Encode (t1, t2, len1); + res = (char *)xmalloc (len2 + 11 + strlen (header)); + sprintf (res, "%s: Basic %s\r\n", header, t2); + + return res; +} + +/* extraHeaders is either NULL or a string with extra headers separated by '\r\n', ending with + * '\r\n' + */ +int httpGetFileDesc(char * hostname, int port, char * remotename, char *extraHeaders, + char * login, char * password) { + char * buf; + struct timeval timeout; + char headers[4096]; + char * nextChar = headers; + char *realhost; + char *hstr; + char *auth; + int checkedCode; + struct in_addr serverAddress; + int sock; + int rc; + struct sockaddr_in destPort; + fd_set readSet; + + realhost = hostname; + if (port < 0) { + char *colonptr = strchr(hostname, ':'); + if (colonptr != NULL) { + int realhostlen = colonptr - hostname; + port = atoi(colonptr + 1); + realhost = alloca (realhostlen + 1); + memcpy (realhost, hostname, realhostlen); + realhost[realhostlen] = '\0'; + } else { + port = 80; + } + } + + if ((rc = getHostAddress(realhost, &serverAddress))) return rc; + + sock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); + if (sock < 0) { + return FTPERR_FAILED_CONNECT; + } + + destPort.sin_family = AF_INET; + destPort.sin_port = htons(port); + destPort.sin_addr = serverAddress; + + if (connect(sock, (struct sockaddr *) &destPort, sizeof(destPort))) { + close(sock); + return FTPERR_FAILED_CONNECT; + } + + if (extraHeaders) + hstr = extraHeaders; + else + hstr = ""; + + if (login && password) + auth = httpBasicAuthenticationEncode(login, password, "Authorization"); + else + auth = ""; + + buf = alloca(strlen(remotename) + strlen(realhost) + strlen(hstr) + strlen(auth) + 25); + sprintf(buf, "GET %s HTTP/1.0\r\nHost: %s\r\n%s%s\r\n", remotename, realhost, hstr, auth); + rc = write(sock, buf, strlen(buf)); + + /* This is fun; read the response a character at a time until we: + + 1) Get our first \r\n; which lets us check the return code + 2) Get a \r\n\r\n, which means we're done */ + + *nextChar = '\0'; + checkedCode = 0; + while (!strstr(headers, "\r\n\r\n")) { + FD_ZERO(&readSet); + FD_SET(sock, &readSet); + + timeout.tv_sec = TIMEOUT_SECS; + timeout.tv_usec = 0; + + rc = select(sock + 1, &readSet, NULL, NULL, &timeout); + if (rc == 0) { + close(sock); + return FTPERR_SERVER_TIMEOUT; + } else if (rc < 0) { + close(sock); + return FTPERR_SERVER_IO_ERROR; + } + + if (read(sock, nextChar, 1) != 1) { + close(sock); + return FTPERR_SERVER_IO_ERROR; + } + + nextChar++; + *nextChar = '\0'; + + if (nextChar - headers == sizeof(headers)) { + close(sock); + return FTPERR_SERVER_IO_ERROR; + } + + if (!checkedCode && strstr(headers, "\r\n")) { + char * start, * end; + + checkedCode = 1; + start = headers; + while (!isspace(*start) && *start) start++; + if (!*start) { + close(sock); + return FTPERR_SERVER_IO_ERROR; + } + start++; + + end = start; + while (!isspace(*end) && *end) end++; + if (!*end) { + close(sock); + return FTPERR_SERVER_IO_ERROR; + } + + *end = '\0'; + if (!strcmp(start, "404")) { + close(sock); + return FTPERR_FILE_NOT_FOUND; + } else if (strcmp(start, "200")) { + close(sock); + return FTPERR_BAD_SERVER_RESPONSE; + } + + *end = ' '; + } + } + + return sock; +} diff -uNpr anaconda-orig/loader2/http.h anaconda/loader2/http.h --- anaconda-orig/loader2/http.h 1969-12-31 19:00:00.000000000 -0500 +++ anaconda/loader2/http.h 2005-03-01 23:53:05.408495936 -0500 @@ -0,0 +1,8 @@ +#ifndef H_HTTP +#define H_HTTP + +#include "urls.h" + +int httpGetFileDesc(char * hostname, int port, char * remotename, char *extraHeaders); + +#endif diff -uNpr anaconda-orig/loader2/urls.c anaconda/loader2/urls.c --- anaconda-orig/loader2/urls.c 2005-03-01 23:52:39.122296244 -0500 +++ anaconda/loader2/urls.c 2005-03-01 23:53:14.735497350 -0500 @@ -30,6 +30,7 @@ #include "../isys/dns.h" #include "ftp.h" +#include "http.h" #include "lang.h" #include "loader.h" #include "loadermisc.h" @@ -46,25 +47,7 @@ int convertURLToUI(char *url, struct iur if (!strncmp("ftp://", url, 6)) { ui->protocol = URL_METHOD_FTP; - url += 6; - - /* There could be a username/password on here */ - if ((chptr = strchr(url, '@'))) { - if ((chptr = strchr(url, ':'))) { - *chptr = '\0'; - ui->login = strdup(url); - url = chptr + 1; - - chptr = strchr(url, '@'); - *chptr = '\0'; - ui->password = strdup(url); - url = chptr + 1; - } else { - *chptr = '\0'; - ui->login = strdup(url); - url = chptr + 1; - } - } + url += 6; } else if (!strncmp("http://", url, 7)) { ui->protocol = URL_METHOD_HTTP; url +=7; @@ -73,6 +56,24 @@ int convertURLToUI(char *url, struct iur return -1; } + /* There could be a username/password on here */ + if ((chptr = strchr(url, '@'))) { + if ((chptr = strchr(url, ':'))) { + *chptr = '\0'; + ui->login = strdup(url); + url = chptr + 1; + + chptr = strchr(url, '@'); + *chptr = '\0'; + ui->password = strdup(url); + url = chptr + 1; + } else { + *chptr = '\0'; + ui->login = strdup(url); + url = chptr + 1; + } + } + /* url is left pointing at the hostname */ chptr = strchr(url, '/'); *chptr = '\0'; @@ -185,7 +186,7 @@ int urlinstStartTransfer(struct iurlinfo return -1; } } else { - fd = httpGetFileDesc(ui->address, -1, buf, extraHeaders); + fd = httpGetFileDesc(ui->address, -1, buf, extraHeaders, ui->login, ui->password); if (fd < 0) { if (!silentErrors) newtWinMessage(_("Error"), _("OK"),