/*
   Auteur: Bertrand Massot

   Saisir une URL ou une IP dans la zone de texte,
   presser Entrée: un socket se connecte et récupère
   l'en-tête HTTP du serveur avec une requête HEAD.
*/

#include <gtk/gtk.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
#include <arpa/inet.h>

GtkWidget *TxtData;
static void TxtIP_ENTER_Pressed(GtkWidget *widget, GtkWidget *entry);

/*******************************************************************************
 Point d'entrée ================================================================
 ******************************************************************************/
int main(int argc, char **argv)
{
  GtkWidget *Fen, *vbox, *TxtIP;
  gtk_init(&argc, &argv);

  // Fenêtre 
  Fen = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    g_signal_connect(G_OBJECT(Fen),"destroy",G_CALLBACK(gtk_main_quit),NULL);
    gtk_container_set_border_width (GTK_CONTAINER (Fen), 4);
    gtk_window_set_default_size(GTK_WINDOW(Fen), 400, 400);
    gtk_window_set_position (GTK_WINDOW (Fen), GTK_WIN_POS_CENTER);
    vbox = gtk_vbox_new (FALSE, 0);
    gtk_container_add (GTK_CONTAINER (Fen), vbox);
    gtk_widget_show (vbox);
  // Textbox IP/serveur
  TxtIP = gtk_entry_new ();
    gtk_entry_set_max_length (GTK_ENTRY (TxtIP), 50);
    g_signal_connect (G_OBJECT (TxtIP), "activate",
		      G_CALLBACK(TxtIP_ENTER_Pressed),(gpointer)TxtIP);
    gtk_entry_set_text (GTK_ENTRY (TxtIP), "127.0.0.1");
    gtk_editable_select_region (GTK_EDITABLE (TxtIP),0,
				GTK_ENTRY (TxtIP)->text_length);
    gtk_box_pack_start (GTK_BOX (vbox), TxtIP, FALSE, TRUE, 0);
  // Textbox messages
  TxtData = gtk_text_view_new();
    gtk_box_pack_start (GTK_BOX (vbox), TxtData, TRUE, TRUE, 4);

  gtk_widget_show_all(Fen);

  gtk_main();
  return 0;
}

/*******************************************************************************
 * Presser Entrée pour se connecter ============================================
 ******************************************************************************/
static void TxtIP_ENTER_Pressed(GtkWidget *widget, GtkWidget *entry)
{
  int sk = -1;				// descripteur socket
  struct sockaddr_in ServAddr;		// addresse du serveur
  struct hostent *serveurEnt;		// description serveur
  unsigned long hostAddr;		// addr du serveur
  int i=1;
  const gchar *serveur = NULL;		// www.truc.com ou IP
  const gchar *req     = NULL;		// Requête HTTP
  const gchar *sUTF8   = NULL;		// Paquet réponse en UTF8
  char buf[2048];			// en locale
  GtkTextBuffer *pTx;
  GtkTextIter iStart;

  serveur = gtk_entry_get_text (GTK_ENTRY(entry));
  pTx     = gtk_text_view_get_buffer(GTK_TEXT_VIEW(TxtData));
  gtk_text_buffer_get_start_iter(pTx, &iStart);
  sUTF8 = g_strdup_printf("[Connection à  %s] ", serveur);
  gtk_text_buffer_insert (pTx, &iStart, sUTF8, -1);

  bzero(&ServAddr,sizeof(ServAddr));
  hostAddr = inet_addr(serveur); // convertit IP en entier long

  if ( (long)hostAddr != (long)-1)
    bcopy(&hostAddr, &ServAddr.sin_addr, sizeof(hostAddr));
  else  // un nom a été donné, pas une IP
  {
    serveurEnt = gethostbyname(serveur);
    if (serveurEnt==NULL)
    {
     gtk_text_buffer_insert(pTx,&iStart,"> gethostbyname = NULL\n\n",-1);
     return;
    }
    bcopy(serveurEnt->h_addr,&ServAddr.sin_addr, serveurEnt->h_length);
  }
  ServAddr.sin_port = htons(80); // Port 80 pour HTTP
  ServAddr.sin_family = AF_INET;
  if ( (sk = socket(AF_INET,SOCK_STREAM,0)) < 0)
  {
   gtk_text_buffer_insert(pTx, &iStart,"> Problème création socket.\n\n",-1);
   return;
  }

  if (connect(sk,(struct sockaddr *)&ServAddr, sizeof(ServAddr)) < 0)
  {
   gtk_text_buffer_insert (pTx, &iStart, "> Problème sur connect().\n\n", -1);
   return;
  }

  sUTF8 = g_strdup_printf("(%s)\n", inet_ntoa(ServAddr.sin_addr));
  gtk_text_buffer_insert (pTx, &iStart, sUTF8, -1);

  req = g_strdup_printf("HEAD / HTTP/1.1\r\n"
                        "Host:%s\r\n\r\n", serveur);
  i = send(sk, req, strlen(req), 0);
  i = recv(sk, buf, sizeof(buf), 0);
  if (i)
  {
    buf[i]=0;
    sUTF8 = g_locale_to_utf8(buf,i,NULL,NULL,NULL);
    gtk_text_buffer_insert (pTx, &iStart, sUTF8, -1);
  }
  close(sk);
  gtk_text_buffer_insert (pTx, &iStart, g_strdup("> Socket fermé.\n"), -1);
}