/* @(#)http.c 1.4 95/09/16 */

/*
 * Copyright (c) 1994, 1995 by Wayne C. Gramlich.  All rights reserved.
 *
 * Permission to use, copy, modify, distribute, and sell this software
 * for any purpose is hereby granted without fee provided that the above
 * copyright notice and this permission are retained.  The author makes
 * no representations about the suitability of this software for any purpose.
 * It is provided "as is" without express or implied warranty.
 */

/* LINTLIBRARY */

#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stdlib.h>

#include "error_extern.h"
#include "memory_extern.h"
#include "text_extern.h"
#include "str_extern.h"
#include "url_extern.h"

extern FILE *fdopen(int, const char *);

/*
 * http_url_read(url, errors)
 *	This routine will read the document point to via {url} and return
 *	it as a {Text} object.  If any errors occur, {(Text)0} is returned
 *	and {errors} is updated to include the reason why.
 */
Text
http_url_read(
    Url url,
    Errors errors)
{
    struct sockaddr_in address;
    Str full_path;
    struct hostent *host_entry;
    FILE *in_file;
    Str message;
    FILE *out_file;
    unsigned port;
    int sock;
    Text text;

    message = (Str)0;
    if (!url_is_http(url)) {
	message =
	  str_printf("Protocol in '%s' is not supported!\n", url_str(url));
	goto error_return;
    }

    /* Lookup the internet address: */
    host_entry = gethostbyname((char *)url_host_name(url));
    if (host_entry == (struct hostent *)0) {
	message = str_printf("Could not find internet address for '%s'!\n",
	  url_host_name(url));
	goto error_return;
    }
    memory_copy((void *)&address.sin_addr,
      (void *)host_entry->h_addr, host_entry->h_length);
    address.sin_family = AF_INET;
    port = url_port(url);
    if (port == 0) {
	port = 80;	/* HTTP protocol port number; won't ever change! */
    }
    address.sin_port = port;
    
    /* Open the connection: */
    sock = socket(PF_INET, SOCK_STREAM, 0);
    if (sock < 0) {
	message = str_printf("Could not get a socket (errno=%d)!", errno); 
	goto error_return;
    }
    if (connect(sock, (struct sockaddr *)&address, sizeof address) < 0) {
	message = str_printf("Could not open connection (errno=%d)!", errno);
	goto error_return;
    }

    /* Set up input and output files: */
    in_file = fdopen(sock, "r");
    out_file = fdopen(sock, "w");
    if ((in_file == (FILE *)0) || (out_file == (FILE *)0)) {
	message = str_printf("fdopen failed!");
	goto error_return;
    }

    full_path = url_str_full_path(url);
    (void)fprintf(out_file, "GET %s\r\n", (char *)full_path);
    (void)fflush(out_file);
    text = text_read(in_file);
    (void)fclose(in_file);
    (void)fclose(out_file);
    return text;

    /* Errors are dealt with here. */
  error_return:
    assert(message != (Str)0);
    errors_append(errors, message);
    return (Text)0;
}


