diff options
Diffstat (limited to 'mdk-stage1/url.c')
| -rw-r--r-- | mdk-stage1/url.c | 89 | 
1 files changed, 68 insertions, 21 deletions
| diff --git a/mdk-stage1/url.c b/mdk-stage1/url.c index 6187a6195..14f1e25d6 100644 --- a/mdk-stage1/url.c +++ b/mdk-stage1/url.c @@ -1,7 +1,7 @@  /* - * Guillaume Cottenceau (gc@mandrakesoft.com) + * Guillaume Cottenceau (gc)   * - * Copyright 2000 Mandrakesoft + * Copyright 2000 Mandriva   *   * This software may be freely redistributed under the terms of the GNU   * public license. @@ -32,6 +32,7 @@  #include <stdio.h>  #include <stdlib.h>  #include <string.h> +#include <strings.h>  #include <sys/socket.h>  #include <sys/time.h>  #include <sys/types.h> @@ -45,12 +46,14 @@  #include "dns.h"  #include "log.h"  #include "tools.h" +#include "utils.h"  #include "url.h"  #define TIMEOUT_SECS 60  #define BUFFER_SIZE 4096 +#define HTTP_MAX_RECURSION 5  static int ftp_check_response(int sock, char ** str) @@ -134,13 +137,7 @@ static int ftp_command(int sock, char * command, char * param)  	char buf[500];  	int rc; -	strcpy(buf, command); -	if (param) { -		strcat(buf, " "); -		strcat(buf, param); -	} -	 -	strcat(buf, "\r\n"); +	snprintf(buf, sizeof(buf), "%s%s%s\r\n", command, param ? " " : "", param ? param : "");  	if (write(sock, buf, strlen(buf)) != (ssize_t)strlen(buf)) {  		return FTPERR_SERVER_IO_ERROR; @@ -401,18 +398,20 @@ char *str_ftp_error(int error)  } -int http_download_file(char * hostname, char * remotename, int * size, char * proxyprotocol, char * proxyname, char * proxyport) +static int _http_download_file(char * hostport, char * remotename, int * size, char * proxyprotocol, char * proxyname, char * proxyport, int recursion)  {  	char * buf; +	char * hostname = strdup(hostport);  	char headers[4096];  	char * nextChar = headers; -	int checkedCode; +	int statusCode;  	struct in_addr serverAddress;  	struct pollfd polls;  	int sock;  	int rc;  	struct sockaddr_in destPort; -	char * header_content_length = "Content-Length: "; +	const char * header_content_length = "Content-Length: "; +	const char * header_location = "Location: http://";  	char * http_server_name;  	int http_server_port; @@ -420,8 +419,15 @@ int http_download_file(char * hostname, char * remotename, int * size, char * pr  		http_server_name = proxyname;  		http_server_port = atoi(proxyport);  	} else { -		http_server_name = hostname; -		http_server_port = 80; +		char *port = strchr(hostname, ':'); +		if (port) { +			*port = '\0'; +			http_server_name = hostname; +			http_server_port = atoi(++port); +		} else { +			http_server_name = hostname; +			http_server_port = 80; +		}  	}		  	log_message("HTTP: connecting to server %s:%i (%s)", @@ -432,6 +438,7 @@ int http_download_file(char * hostname, char * remotename, int * size, char * pr  	sock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);  	if (sock < 0) { +		free(hostname);  		return FTPERR_FAILED_CONNECT;  	} @@ -441,13 +448,15 @@ int http_download_file(char * hostname, char * remotename, int * size, char * pr  	if (connect(sock, (struct sockaddr *) &destPort, sizeof(destPort))) {  		close(sock); +		free(hostname);  		return FTPERR_FAILED_CONNECT;  	} -        buf = proxyprotocol ? asprintf_("GET %s://%s%s HTTP/0.9\r\nHost: %s\r\n\r\n", proxyprotocol, hostname, remotename, hostname) -                            : asprintf_("GET %s HTTP/0.9\r\nHost: %s\r\n\r\n", remotename, hostname); +        buf = proxyprotocol ? asprintf_("GET %s://%s%s HTTP/1.0\r\nHost: %s\r\n\r\n", proxyprotocol, hostname, remotename, hostname) +                            : asprintf_("GET %s HTTP/1.0\r\nHost: %s\r\n\r\n", remotename, hostname);  	write(sock, buf, strlen(buf)); +	free(hostname);  	/* This is fun; read the response a character at a time until we: @@ -455,7 +464,7 @@ int http_download_file(char * hostname, char * remotename, int * size, char * pr  	   2) Get a \r\n\r\n, which means we're done */  	*nextChar = '\0'; -	checkedCode = 0; +	statusCode = 0;  	while (!strstr(headers, "\r\n\r\n")) {  		polls.fd = sock;  		polls.events = POLLIN; @@ -482,10 +491,9 @@ int http_download_file(char * hostname, char * remotename, int * size, char * pr  			return FTPERR_SERVER_IO_ERROR;  		} -		if (!checkedCode && strstr(headers, "\r\n")) { +		if (!statusCode && strstr(headers, "\r\n")) {  			char * start, * end; -			checkedCode = 1;  			start = headers;  			while (!isspace(*start) && *start) start++;  			if (!*start) { @@ -503,10 +511,15 @@ int http_download_file(char * hostname, char * remotename, int * size, char * pr  			*end = '\0';                          log_message("HTTP: server response '%s'", start); -			if (!strcmp(start, "404")) { +			if (streq(start, "404")) {  				close(sock);  				return FTPERR_FILE_NOT_FOUND; -			} else if (strcmp(start, "200")) { +			} else if (streq(start, "302")) { +				log_message("HTTP: found, but document has moved"); +				statusCode = 302; +			} else if (streq(start, "200")) { +				statusCode = 200; +			} else {  				close(sock);  				return FTPERR_BAD_SERVER_RESPONSE;  			} @@ -515,6 +528,34 @@ int http_download_file(char * hostname, char * remotename, int * size, char * pr  		}  	} +	if (statusCode == 302) { +		if (recursion >= HTTP_MAX_RECURSION) { +			log_message("HTTP: too many levels of recursion, aborting"); +			close(sock); +			return FTPERR_UNKNOWN; +		} +		if ((buf = strstr(headers, header_location))) { +			char * found_host; +			char *found_file; +			found_host = buf + strlen(header_location); +			if ((found_file = index(found_host, '/'))) { +				if ((buf = index(found_file, '\r'))) { +					buf[0] = '\0'; +					remotename = strdup(found_file); +					found_file[0] = '\0'; +					hostname = strdup(found_host); +					log_message("HTTP: redirected to new host \"%s\" and file \"%s\"", hostname, remotename); +				} +			} +			 +		} +		/* +		 * don't fail if new URL can't be parsed, +		 * asking the same URL may work if the DNS server are doing round-robin +		 */ +		return _http_download_file(hostname, remotename, size, proxyprotocol, proxyname, proxyport, recursion + 1); +	} +  	if ((buf = strstr(headers, header_content_length)))  		*size = charstar_to_int(buf + strlen(header_content_length));  	else @@ -522,3 +563,9 @@ int http_download_file(char * hostname, char * remotename, int * size, char * pr  	return sock;  } + + +int http_download_file(char * hostname, char * remotename, int * size, char * proxyprotocol, char * proxyname, char * proxyport) +{ +	return _http_download_file(hostname, remotename, size, proxyprotocol, proxyname, proxyport, 0); +} | 
