Exemplo n.º 1
0
static int _http_download_file(const char * hostname, const char * remotename, int * size, const char * proxyprotocol, const char * proxyname, const char * proxyport, int recursion)
{
	char * buf;
	char headers[4096];
	char * nextChar = headers;
	int statusCode;
	struct in_addr serverAddress;
	struct pollfd polls;
	int sock;
	int rc;
	union {
		struct sockaddr_in in;
		struct sockaddr sa;
	} destPort;
	const char * header_content_length = "Content-Length: ";
	const char * header_location = "Location: http://";
	const char * http_server_name;
	int http_server_port;

	if (proxyprotocol) {
		http_server_name = proxyname;
		http_server_port = atoi(proxyport);
	} else {
		http_server_name = hostname;
		http_server_port = 80;
	}		

	log_message("HTTP: connecting to server %s:%i (%s)",
		    http_server_name, http_server_port,
		    proxyprotocol ? "proxy" : "no proxy");

	if ((rc = get_host_address(http_server_name, &serverAddress))) return rc;

	sock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
	if (sock < 0) {
		return FTPERR_FAILED_CONNECT;
	}

	destPort.in.sin_family = AF_INET;
	destPort.in.sin_port = htons(http_server_port);
	destPort.in.sin_addr = serverAddress;

	if (connect(sock, &destPort.sa, sizeof(destPort.in))) {
		close(sock);
		return FTPERR_FAILED_CONNECT;
	}

        if (proxyprotocol)
		asprintf(&buf, "GET %s://%s%s HTTP/1.0\r\nHost: %s\r\n\r\n", proxyprotocol, hostname, remotename, hostname);
	else
		asprintf(&buf, "GET %s HTTP/1.0\r\nHost: %s\r\n\r\n", remotename, hostname);

	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';
	statusCode = 0;
	while (!strstr(headers, "\r\n\r\n")) {
		polls.fd = sock;
		polls.events = POLLIN;
		rc = poll(&polls, 1, TIMEOUT_SECS*1000);

		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 (!statusCode && strstr(headers, "\r\n")) {
			char * start, * end;

			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';
                        log_message("HTTP: server response '%s'", start);
			if (streq(start, "404")) {
				close(sock);
				return FTPERR_FILE_NOT_FOUND;
			} 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;
			}

			*end = ' ';
		}
	}

	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
		*size = 0;

	return sock;
}
Exemplo n.º 2
0
	SocketHostAddress get_remote_host_address(int32 fd)
	{
		SocketInetAddress inetaddr = get_remote_inet_address(fd);
		return get_host_address(inetaddr);
	}
Exemplo n.º 3
0
int ftp_open_connection(const char * host, const char * name, const char * password, const char * proxy)
{
	int sock;
	struct in_addr serverAddress;
	union {
		struct sockaddr_in in;
		struct sockaddr sa;
	} destPort;
	int rc;
	int port = 21;
	std::string proxyname;

	if (!strcmp(name, "")) {
		name = "anonymous";
		password = "******";
	}

	if (strcmp(proxy, "")) {
		proxyname.append(name).append("@").append(host);
		name = proxyname.c_str();
		host = proxy;
	}

	if ((rc = get_host_address(host, &serverAddress))) return rc;

	sock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
	if (sock < 0) {
		return FTPERR_FAILED_CONNECT;
	}

	destPort.in.sin_family = AF_INET;
	destPort.in.sin_port = htons(port);
	destPort.in.sin_addr = serverAddress;

	if (connect(sock, &destPort.sa, sizeof(destPort.in))) {
		close(sock);
		return FTPERR_FAILED_CONNECT;
	}

	/* ftpCheckResponse() assumes the socket is nonblocking */
	if (fcntl(sock, F_SETFL, O_NONBLOCK)) {
		close(sock);
		return FTPERR_FAILED_CONNECT;
	}

	if ((rc = ftp_check_response(sock, NULL))) {
		return rc;     
	}

	if ((rc = ftp_command(sock, "USER", name))) {
		close(sock);
		return rc;
	}

	if ((rc = ftp_command(sock, "PASS", password))) {
		close(sock);
		return rc;
	}

	if ((rc = ftp_command(sock, "TYPE", "I"))) {
		close(sock);
		return rc;
	}

	return sock;
}
Exemplo n.º 4
0
	SocketHostAddress get_host_address(const SocketInetAddress& addr)
	{
		return get_host_address(addr.GetRawSockAddr());
	}