
/* Bluefish HTML Editor
 * network.c - Open from Web, save to Web, send as E-mail?
 *
 * Copyright (C) 1999 Neil Millar
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * To add:	Catch errors
 *			Redirection
 */


#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <gtk/gtk.h>
#include "bluefish.h"
#include "interface.h"
#include "network.h"
#include "widgets.h"

extern void add_to_statusbar (gchar *);
extern void insert_text (gchar *, gchar *);
extern void file_close (GtkWidget * widget, gpointer data);

gint port = 80;
gint sockfd;
gint closed = 0;

gint
open_web (gchar * address)
{
  gchar *server;
  gchar *ip_address;
  gchar *page_location;
  gchar *status_string;
  gchar *temp_ptr;
  gint num_bytes;
  gint first_time = 0;
  gint doc_size = 0;
  gint going = 0;
  gint received;
  gchar buf[1024];
  gchar temp_buf[1024];
  gchar send_buf[512];
  struct sockaddr_in their_addr;

  server = extract_address (address);
  if (server == "secure")
    return 1;
  else if (server == "undefined")
    return 2;

  page_location = extract_filename (address, server);
#ifdef DEBUG
  g_print ("open_web, Page location is %s\n", page_location);
#endif
  if (page_location == NULL)
    {
      page_location = g_malloc0 (16);
      sprintf (page_location, "/");
    }

  add_to_statusbar ("Resolving address");
  ip_address = resolve (server);
  flush_queue ();
  if (ip_address == "1")
    return 3;
#ifdef DEBUG
  g_print ("open_web, IP address of %s is %s\n", server, ip_address);
#endif
  if ((sockfd = socket (AF_INET, SOCK_STREAM, 0)) == -1)
    return 4;

/*
 *  Even if we identify ourselves as HTTP 1.0 compliant (Yeah right!),
 *	servers still need the Host: for multiple names per IP
 *	e.g. www.millar.u-net.com :) 
 */

  sprintf (send_buf,
	   "GET %s HTTP/1.0\r\nUser-Agent: %s\r\nHost:%s\r\n\r\n",
	   page_location, CURRENT_VERSION_NAME, server);
  their_addr.sin_family = AF_INET;
  their_addr.sin_port = htons (port);
  their_addr.sin_addr.s_addr = inet_addr (ip_address);
  bzero (&(their_addr.sin_zero), 8);
  if (connect (sockfd, (struct sockaddr *) &their_addr, sizeof (struct
								sockaddr))
      == -1)
      return 5;
#ifdef DEBUG
  g_print ("open_web, Connected\n");
#endif
  num_bytes = send (sockfd, send_buf, strlen (send_buf), 0);

  if (num_bytes == -1)
    return 6;
  else if (num_bytes != strlen (send_buf))
    return 7;

  bzero (buf, 1024);
#ifdef DEBUG
  g_print ("open_web, Sent: %s\n", send_buf);
#endif

  if ((current_document->filename == NULL && current_document->modified ==
       FALSE && g_list_length (documentlist) == 2))
    {
#ifdef DEBUG
      g_print ("open_web, no new document created\n");
#endif
    }
  else
    {
      current_document = new_document ();
#ifdef DEBUG
      g_print ("open_web, new document created\n");
#endif
    }
  gtk_text_freeze ((GtkText *) current_document->textbox);
  add_to_statusbar ("Retrieving file, press ESC to cancel download");
/* Re-using num_bytes for the number of received bytes */
  status_string = g_malloc0 (200);
  num_bytes = 0;

  /* make the socket non-blocking so we can call flush_queue() 
     when there is no data.
     If you don't call flush_queue() a key_press event (ESC) will
     not stop the download since the whole program (including
     gtk_main() will be blocked until there is some data on the 
     filedescriptor again
   */
  fcntl (sockfd, F_SETFL, O_NONBLOCK);

  going = 1;
  while (going)
    {
      received = recvfrom (sockfd, buf, 1023, 0, NULL, 0);
      if (received == 0)
	{
#ifdef DEBUG
	  g_print ("open_web, received=%d --> end of file\n", received);
#endif
	  going = 0;
	}
      else if (received == -1)
	{

	  /* check the gtk and gdk events (ESC pressed?) */
	  flush_queue ();
	  /* Has the user cancelled the d/l? */
	  if (closed == 1)
	    {
#ifdef DEBUG
	      g_print ("open_web, closed=%d, stopping the download\n", closed);
#endif
	      add_to_statusbar ("User aborted download");
	      closed = 0;
	      going = 0;
	      return 9;
	    }
#ifdef DEBUG
	  g_print ("open_web, no data waiting (received=%d) --> sleep\n", received);
#endif
	  /* do we need the sleep() call here?
	     if we don't cpu usage will probably go up to 100%
	     since the loop will run on flush_queue() till there is
	     some data on the socket again
	   */
	  sleep (1);
	}
      else if (received > 0)
	{
#ifdef DEBUG
	  g_print ("open_web, received=%d, >0\n", received);
#endif

/* If it's the first loop, check some stuff (Expected doc length etc.) */
	  if (first_time == 0)
	    {

/* Do you remember the ...*/
	      first_time = 1;
/* 302 Error: Relocation */
	      temp_ptr = strstr (buf, "Location:");
	      if (temp_ptr != NULL)
		{
		  temp_ptr += strlen ("Location:");
		  strcpy (temp_buf, temp_ptr);
#ifdef DEBUG
		  g_print ("open_web, Relocated to: %s\n", temp_buf);
#endif
/* Recurses, if it wasn't for those pesky kids */
		  /* open_web(temp_buf); */
		}

/* How long is this document supposed to be? */
	      temp_ptr = strstr (buf, "Content-Length:");
	      if (temp_ptr != NULL)
		{
		  temp_ptr += strlen ("Content-Length:");
		  doc_size = atoi (temp_ptr);
#ifdef DEBUG
		  g_print ("open_web, Got length: %d\n", doc_size);
#endif
		}
/* Send all the headers to the bit bucket in the sky */
	      bzero (temp_buf, 1024);
	      strcpy (temp_buf, buf);
	      temp_ptr = strchr (temp_buf, '<');
	      bzero (buf, 1024);
	      if (temp_ptr == NULL)
		{
/* The first < wasn't in this chunk, let's go round again */
		  strcpy (buf, "");
		  first_time = 0;
		}
	      else
		{
		  strcpy (buf, temp_ptr);
		}
	    }
	  gtk_text_insert ( GTK_TEXT(current_document->textbox), NULL, NULL, NULL,
		   buf, -1);
	  num_bytes = num_bytes + strlen (buf);
	  bzero (buf, 1024);

	  if (doc_size == 0)
	    sprintf (status_string,
		     "Retrieving file, %d bytes received", num_bytes);
	  else
	    sprintf (status_string,
		     "Retrieving file, %d bytes of %d bytes received",
		     num_bytes, doc_size);

	  add_to_statusbar (status_string);
	  flush_queue ();
	}

    }
  g_free (status_string);

  close (sockfd);
  gtk_text_thaw ((GtkText *) current_document->textbox);
#ifdef DEBUG
  g_print ("open_web, document thawed, end\n");
#endif
  return 0;
}

gint
send_email (gchar * address)
{
  /* This space for rent */
  return 0;
}

gchar *
resolve (gchar * address)
{

  struct hostent *h;
  if ((h = gethostbyname (address)) == NULL)
    return "1";

  return inet_ntoa (*(struct in_addr *) h->h_addr_list[0]);
}

gchar *
extract_address (gchar * address)
{
/* Find the name of the server and return string, set global port int */
  gint string_size;
  gchar *begin_ptr;
  gchar *temp_ptr;
  static gchar *return_string;

  return_string = g_malloc0 (256);

  if (strlen (address) == 0)
    {
      return "undefined";
    }

  begin_ptr = &address[0];
  temp_ptr = strstr (address, "http");

  if (temp_ptr != NULL)
    {
      temp_ptr += 4;
      switch (temp_ptr[0])
	{
	case 's':
	  return "secure";
	  break;
	case ':':
	  temp_ptr += 3;
	  begin_ptr = temp_ptr;
	  break;
	default:
	  return "undefined";
	}
    }

/* Check for port number */

  temp_ptr = strchr (begin_ptr, ':');
  if (temp_ptr != NULL)
    {
/* Could that be? Yes it is! The lesser spotted pointer increment */
      temp_ptr++;
      port = atoi (temp_ptr);
#ifdef DEBUG
      g_print ("extract_address, Got a port: %d\n", port);
#endif
      temp_ptr--;
    }
  else
    {
      port = 80;
      temp_ptr = strchr (begin_ptr, '/');

/* if no path e.g. www.millar.u-net.com */

      if (temp_ptr == NULL)
	return begin_ptr;
    }

  string_size = strlen (begin_ptr) - strlen (temp_ptr);
  strncat (return_string, begin_ptr, string_size);
#ifdef DEBUG
  g_print ("extract_address, Return string is %s\n", return_string);
#endif
  return return_string;
}

gchar *
extract_filename (gchar * address, gchar * server)
{
/* Take URL, return file location */
  gchar *temp_ptr;
  gint server_size;

  server_size = strlen (server);
  temp_ptr = address;
  temp_ptr += server_size;

  if (temp_ptr[0] == '/')
    return temp_ptr;
  else
    {
      address = temp_ptr;
      temp_ptr = strchr (address, '/');
      return temp_ptr;
    }
}
