/*
    ettercap -- gtk main interface

    Copyright (C) 2001  ALoR <alor@users.sourceforge.net>, NaGA <crwm@freemail.it>
    GTK+ 2.0 interface by daten <daten@dnetc.org>

    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.
*/

#include <ec_main.h>

#include <gtk/gtk.h>

#include <stdarg.h>

#include <ec_version.h>
#include <ec_gtk.h>
#include <ec_gtk_sniff.h>
#include <ec_gtk_passive.h>
#include <ec_gtk_factory.h>
#include <ec_gtk_splash.h>
#include <ec_gtk_sniff_data.h>
#include <ec_gtk_plugins.h>
#include <ec_gtk_icons.h>
#include <ec_inet.h>
#include <ec_buffer.h>
#include <ec_fingerprint.h>
#include <ec_doppleganger.h>
#include <ec_thread.h>

#ifdef PERMIT_PLUGINS
   #include <ec_gtk_plugins.h>
   #include <ec_plugins.h>
#endif

// prototyping...
void Ginterface_Testing(void);
void Ginterface_InitTitle(char *ip, char *mac, char *subnet);
void Ginterface_Screen_Init(void);
void Ginterface_Screen_Close(void);
void Ginterface_WExit(char *buffer);
void Ginterface_Run(void);
void Ginterface_InitList(void);
void Ginterface_Connect(void);
void Ginterface_PopUp(char *question, ...);  /* for messages, controlled by user */
void Ginterface_PopUpN(char *notice);        /* for notices, controlled by program */
void Ginterface_PopUpNP(char *notice);       /* notices with progress bars */
char Ginterface_PopUpQ(char *question, ...); /* for yes/no questions */
void Ginterface_RefreshList(void);
void Ginterface_Manual(void);
void Ginterface_About(void);
void Ginterface_HelpWindow(char *help[]);
void Ginterface_OldStyleSniff(short mode);
void Ginterface_CheckForPoisoner(void);
void Ginterface_FingerPrint(void);
void Ginterface_EntryRemoval(void);
void Ginterface_OnlyPoison(void);

void Ginterface_ToolBar(GtkItemFactory *host_menu);
void Ginterface_Callback(gpointer data, guint action, GtkWidget *widget);
void Ginterface_SwitchPage(GtkNotebook *notebook, GtkNotebookPage *page, gint page_num, gpointer user_data);
void Ginterface_SelectItem(GtkTreeView *treeview, gpointer arg1, GtkTreeViewColumn *arg2, gpointer data);
void Ginterface_PointItem (GtkWidget *widget, gpointer data);
void Ginterface_EditTop(int which, char *message);
void Ginterface_ClearTop(void);
void Ginterface_AppendTop(int which, char *message);
void Ginterface_EditBottom(int which, char *message);
void Ginterface_ClearBottom(void);
void Ginterface_AppendBottom(int which, char *message);
void Ginterface_CheckImgPath(char *path);

#ifndef HAVE_FORM
void trim_buffer(char *buffer, char trim);
#endif

// global variables for Interface...
GtkWidget *window;       // the main window
GtkWidget *notebook;     // for tabs
GtkWidget *frame[3];     // frames for the 3 main areas, 0 top, 1 middle, 2 bottom
GtkWidget *mainbox[6];   // host list, arp sniff, ip sniff, mac sniff, passive mode
GtkWidget *tablabel[6];
GtkItemFactory *main_menu;
GtkAccelGroup *accel_group = NULL;
GtkWidget *tb_label[9];  // top left, top middle, top right, middle left, ... bottom right
GtkWidget *tb_table;     // top frame layout
GtkWidget *bb_label[2];  // tow text rows in bottom box
GtkWidget *ec_table;     // main layout
GtkWidget *arrows;       // arrows in top frame

// for the host lists
GtkWidget         *h_scrolled;
GtkListStore      *h_list[2];
GtkTreeIter        h_iter[2];
GtkCellRenderer   *h_renderer;
GtkTreeViewColumn *h_column;
GtkWidget         *h_treeview[2];
GtkTreeSelection  *h_selection[2];

extern GtkWidget *s_scrolled;  // for sniffer modes
extern GtkWidget *splash_pbar; // progress bar
extern GtkWidget *o_win;       // plugin output window

int gBase_Pointer = 0;
int gSource_Pointer = 0;
int gDest_Pointer = 0;
int *gPointer = &gSource_Pointer;
int Sel_Number;

char title_bottom_window[100];
char title_main_window[100];
char title_top_window[100];
char image_path[100];

// -------------------------------------------


void Ginterface_InitTitle(char *ip, char *mac, char *subnet)
{
   DEBUG_MSG("Ginterface_InitTitle [%s] [%s] [%s]", ip, mac, subnet);

   if (Options.silent)
   {
      snprintf(title_main_window, 100, " ??? hosts in this LAN (%s : %s) ", ip, subnet);
      snprintf(title_bottom_window, 100, " Your IP: %s MAC: %s Iface: %s Link: not tested", ip, mac, Options.netiface);
   }
   else
   {
      char link_type[10];
      short type;

      switch(type = Inet_CheckSwitch())
      {
         case 0: strcpy(link_type, "unknown");
                 break;
         case 1: strcpy(link_type, "HUB");
                 break;
         case 2: strcpy(link_type, "SWITCH");
                 break;
      }
      snprintf(title_main_window, 100, " %3d hosts in this LAN (%s : %s) ", number_of_hosts_in_lan, ip, subnet);
      snprintf(title_bottom_window, 100, " Your IP: %s MAC: %s Iface: %s Link: %s ", ip, mac, Options.netiface, link_type);
   }
   snprintf(title_top_window, 100, " %s %s ", PROGRAM, VERSION);
}

void Ginterface_Screen_Init(void)
{
   GtkWidget *seperator, *box, *menubar;
   GdkPixbuf *pixbuf;

   DEBUG_MSG("Ginterface_Screen_Init");
   
   /* formerly set image paths, now just used for About data */
   Ginterface_CheckImgPath(DATA_PATH);

   Ginterface_InitTitle(Host_In_LAN[0].ip, Host_In_LAN[0].mac, Inet_MySubnet());

   /* create the main window, set it up */
   window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
   gtk_window_set_title(GTK_WINDOW (window), title_top_window);
   g_signal_connect (G_OBJECT (window), "delete_event", G_CALLBACK (Ginterface_WExit), NULL);
   gtk_container_set_border_width( GTK_CONTAINER (window), 0);
   gtk_window_set_default_size(GTK_WINDOW (window), 640, 420);
   gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_CENTER);

   /* create the table */
   ec_table = gtk_table_new (4, 1, FALSE);   /* 4 rows, 1 column, not same height */
   gtk_container_add (GTK_CONTAINER (window), ec_table);
   gtk_widget_show(ec_table);

   /* toolbars setup after frames so certain widgets get initialized first */

   /* setup the top table frame */
   /* ------------------------- */ 
   frame[0] = gtk_frame_new(title_top_window);
   gtk_frame_set_label_align(GTK_FRAME (frame[0]), 0.5, 0.5);
   gtk_table_attach (GTK_TABLE (ec_table), frame[0], 0, 1, 1, 2,  GTK_FILL | GTK_EXPAND, 0, 10, 10);
   gtk_widget_show(frame[0]);

   tb_table = gtk_table_new (4, 3, FALSE);
   gtk_container_add (GTK_CONTAINER (frame[0]), tb_table);
  
   /* source label */ 
   tb_label[0] = gtk_label_new ("       ");
   gtk_misc_set_alignment(GTK_MISC (tb_label[0]), 0, 0);
   gtk_table_attach (GTK_TABLE (tb_table), tb_label[0], 0, 1, 0, 1, GTK_FILL, 0, 5, 0);
   gtk_widget_show (tb_label[0]);

   /* source ip */
   tb_label[1] = gtk_label_new ("               ");
   gtk_misc_set_alignment(GTK_MISC (tb_label[1]), 1, 0);
   gtk_table_attach (GTK_TABLE (tb_table), tb_label[1], 1, 2, 0, 1, GTK_FILL, 0, 5, 0);
   gtk_widget_show (tb_label[1]);

   /* source mac */
   tb_label[2] = gtk_label_new ("                 ");
   gtk_misc_set_alignment(GTK_MISC (tb_label[2]), 0, 0);
   gtk_table_attach (GTK_TABLE (tb_table), tb_label[2], 3, 4, 0, 1, GTK_FILL, 0, 5, 0);
   gtk_widget_show (tb_label[2]);

   /* arrows */
   pixbuf = gdk_pixbuf_new_from_inline (-1, arrows_icon, FALSE, NULL);
   arrows = gtk_image_new_from_pixbuf(pixbuf);
   gtk_table_attach (GTK_TABLE (tb_table), arrows, 2, 3, 0, 3, GTK_FILL, 0, 0, 0);

   /* middle row */
   tb_label[3] = gtk_label_new ("       ");
   gtk_misc_set_alignment(GTK_MISC (tb_label[3]), 0, 0);
   gtk_table_attach (GTK_TABLE (tb_table), tb_label[3], 0, 1, 1, 2, GTK_FILL, 0, 5, 0);
   gtk_widget_show (tb_label[3]);

   tb_label[4] = gtk_label_new ("       ");
   gtk_misc_set_alignment(GTK_MISC (tb_label[4]), 1, 0);
   gtk_table_attach (GTK_TABLE (tb_table), tb_label[4], 1, 2, 1, 2, GTK_FILL, 0, 5, 0);
   gtk_widget_show (tb_label[4]);

   tb_label[5] = gtk_label_new ("       ");
   gtk_misc_set_alignment(GTK_MISC (tb_label[5]), 0, 0);
   gtk_table_attach (GTK_TABLE (tb_table), tb_label[5], 3, 4, 1, 2, GTK_FILL, 0, 5, 0);
   gtk_widget_show (tb_label[5]);

   /* dest label */
   tb_label[6] = gtk_label_new ("       ");
   gtk_misc_set_alignment(GTK_MISC (tb_label[6]), 0, 0);
   gtk_table_attach (GTK_TABLE (tb_table), tb_label[6], 0, 1, 2, 3, GTK_FILL, 0, 5, 0);
   gtk_widget_show (tb_label[6]);

   /* dest ip */
   tb_label[7] = gtk_label_new ("               ");
   gtk_misc_set_alignment(GTK_MISC (tb_label[7]), 1, 0);
   gtk_table_attach (GTK_TABLE (tb_table), tb_label[7], 1, 2, 2, 3, GTK_FILL, 0, 5, 0);
   gtk_widget_show (tb_label[7]);

   /* dest mac */
   tb_label[8] = gtk_label_new ("                 ");
   gtk_misc_set_alignment(GTK_MISC (tb_label[8]), 0, 0);
   gtk_table_attach (GTK_TABLE (tb_table), tb_label[8], 3, 4, 2, 3, GTK_FILL, 0, 5, 0);
   gtk_widget_show (tb_label[8]);

   gtk_widget_show(tb_table);

   /* setup the middle table row */
   /* -------------------------- */

   frame[1] = gtk_frame_new(title_main_window);
   gtk_frame_set_label_align(GTK_FRAME (frame[1]), 0.5, 0.5);
   gtk_table_attach (GTK_TABLE (ec_table), frame[1], 0, 1, 2, 3, GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 10, 0);

   /* make the notebook to hold the pages */
   notebook = gtk_notebook_new();
   gtk_notebook_set_tab_pos (GTK_NOTEBOOK (notebook), GTK_POS_BOTTOM);
   gtk_container_add (GTK_CONTAINER (frame[1]), notebook);
   g_signal_connect (G_OBJECT (notebook), "switch-page", G_CALLBACK (Ginterface_SwitchPage), (gpointer) ec_table);

   /* make the pages, with one (reused) label and box each */
   /* host list */
   tablabel[0] = gtk_label_new_with_mnemonic ("Host List");
   mainbox[0] = gtk_hbox_new(FALSE, 0);
   gtk_notebook_append_page(GTK_NOTEBOOK (notebook), mainbox[0], tablabel[0]);
   gtk_widget_show (tablabel[0]);
   gtk_widget_show (mainbox[0]);

   /* arp sniff */
   tablabel[1] = gtk_label_new ("ARP Sniff");
   gtk_widget_set_sensitive (GTK_WIDGET (tablabel[1]), FALSE);
   mainbox[1] = gtk_hbox_new(FALSE, 0);
   gtk_notebook_append_page(GTK_NOTEBOOK (notebook), mainbox[1], tablabel[1]);
   gtk_widget_show (tablabel[1]);
   gtk_widget_show (mainbox[1]);

   /* ip sniff */
   tablabel[2] = gtk_label_new ("IP Sniff");
   mainbox[2] = gtk_hbox_new(FALSE, 0);
   gtk_notebook_append_page(GTK_NOTEBOOK (notebook), mainbox[2], tablabel[2]);
   gtk_widget_show (tablabel[2]);
   gtk_widget_show (mainbox[2]);

   /* mac sniff*/
   tablabel[3] = gtk_label_new ("MAC Sniff");
   mainbox[3] = gtk_hbox_new(FALSE, 0);
   gtk_notebook_append_page(GTK_NOTEBOOK (notebook), mainbox[3], tablabel[3]);
   gtk_widget_show (tablabel[3]);
   gtk_widget_show (mainbox[3]);
   
   /* passive */
   tablabel[4] = gtk_label_new ("Passive");
   mainbox[4] = gtk_hbox_new(FALSE, 0);
   gtk_notebook_append_page(GTK_NOTEBOOK (notebook), mainbox[4], tablabel[4]);
   gtk_widget_show (tablabel[4]);
   gtk_widget_show (mainbox[4]);

#ifdef PERMIT_PLUGINS
   /* plugins */
   tablabel[5] = gtk_label_new ("Plugins");
   mainbox[5] = gtk_hbox_new(FALSE, 0);
   gtk_notebook_append_page(GTK_NOTEBOOK (notebook), mainbox[5], tablabel[5]);
   gtk_widget_show (tablabel[5]);
   gtk_widget_show (mainbox[5]);
#endif

   /* make the scrolled window */
   h_scrolled = gtk_scrolled_window_new(NULL, NULL);
   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (h_scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
   gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (h_scrolled), GTK_SHADOW_IN);
   gtk_box_pack_start (GTK_BOX (mainbox[0]),  h_scrolled, TRUE, TRUE, 0);
   gtk_widget_show (h_scrolled);

   /* make the first list */
   h_treeview[0] = gtk_tree_view_new ();
   gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (h_treeview[0]), FALSE);
   gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (h_treeview[0]), FALSE);
      /* add the number column */
   h_renderer = gtk_cell_renderer_text_new ();
   h_renderer->xalign = 0.0;
   h_column = gtk_tree_view_column_new_with_attributes ("#", h_renderer, "text", 0, NULL);
   gtk_tree_view_column_set_sort_column_id (h_column, 0);
   gtk_tree_view_append_column (GTK_TREE_VIEW(h_treeview[0]), h_column);
      /* add the source column */
   h_renderer = gtk_cell_renderer_text_new ();
   h_renderer->xalign = 1.0;
   h_column = gtk_tree_view_column_new_with_attributes ("Source", h_renderer, "text", 1, NULL);
   gtk_tree_view_column_set_sort_column_id (h_column, 1);
   gtk_tree_view_append_column (GTK_TREE_VIEW(h_treeview[0]), h_column);
      /* additional column for padding */
   h_renderer = gtk_cell_renderer_text_new ();
   h_column = gtk_tree_view_column_new_with_attributes ("", h_renderer, "text", 2, NULL);
   gtk_tree_view_column_set_sort_column_id (h_column, 2);
   gtk_tree_view_append_column (GTK_TREE_VIEW(h_treeview[0]), h_column);
      /* connect signals */
   h_selection[0] = gtk_tree_view_get_selection (GTK_TREE_VIEW (h_treeview[0]));
   gtk_tree_selection_set_mode (h_selection[0], GTK_SELECTION_SINGLE);
   g_signal_connect (G_OBJECT (h_selection[0]), "changed", G_CALLBACK (Ginterface_PointItem), "Source");
   g_signal_connect (G_OBJECT (h_treeview[0]), "row_activated", G_CALLBACK (Ginterface_SelectItem), (gpointer) "Source");
      /* add it and display it */
   gtk_container_add (GTK_CONTAINER (h_scrolled), h_treeview[0]);
   gtk_widget_show(h_treeview[0]);

   /* make a seperator for between the lists */
   seperator = gtk_vseparator_new();
   gtk_box_pack_start (GTK_BOX (mainbox[0]), seperator, FALSE, TRUE, 5);
   gtk_widget_show(seperator);

   /* make the scrolled window */
   h_scrolled = gtk_scrolled_window_new(NULL, NULL);
   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (h_scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
   gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (h_scrolled), GTK_SHADOW_IN);
   gtk_box_pack_start (GTK_BOX (mainbox[0]),  h_scrolled, TRUE, TRUE, 0);
   gtk_widget_show (h_scrolled);

   /* make the second list */
   h_treeview[1] = gtk_tree_view_new ();
   gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (h_treeview[1]), FALSE);
   gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (h_treeview[1]), FALSE);
      /* add the number column */
   h_renderer = gtk_cell_renderer_text_new ();
   h_renderer->xalign = 0.0;
   h_column = gtk_tree_view_column_new_with_attributes ("Destination", h_renderer, "text", 0, NULL);
   gtk_tree_view_column_set_sort_column_id (h_column, 0);
   gtk_tree_view_append_column (GTK_TREE_VIEW(h_treeview[1]), h_column);
      /* add the dest column */
   h_renderer = gtk_cell_renderer_text_new ();
   h_renderer->xalign = 1.0;
   h_column = gtk_tree_view_column_new_with_attributes ("Destination", h_renderer, "text", 1, NULL);
   gtk_tree_view_column_set_sort_column_id (h_column, 1);
   gtk_tree_view_append_column (GTK_TREE_VIEW(h_treeview[1]), h_column);
      /* additional column for padding */
   h_renderer = gtk_cell_renderer_text_new ();
   h_column = gtk_tree_view_column_new_with_attributes ("", h_renderer, "text", 2, NULL);
   gtk_tree_view_column_set_sort_column_id (h_column, 2);
   gtk_tree_view_append_column (GTK_TREE_VIEW(h_treeview[1]), h_column);
      /* connect signals */
   h_selection[1] = gtk_tree_view_get_selection (GTK_TREE_VIEW (h_treeview[1]));
   gtk_tree_selection_set_mode (h_selection[1], GTK_SELECTION_SINGLE);
   g_signal_connect (G_OBJECT (h_selection[1]), "changed", G_CALLBACK (Ginterface_PointItem), "Dest");
   g_signal_connect (G_OBJECT (h_treeview[1]), "row_activated", G_CALLBACK (Ginterface_SelectItem), (gpointer) "Dest");
      /* add it and display it */
   gtk_container_add (GTK_CONTAINER (h_scrolled), h_treeview[1]);
   gtk_widget_show(h_treeview[1]);

   /*** ettercap call, initialize the list ***/
   Ginterface_InitList();

   gtk_tree_view_set_model(GTK_TREE_VIEW (h_treeview[0]), GTK_TREE_MODEL (h_list[0]));
   gtk_tree_view_set_model(GTK_TREE_VIEW (h_treeview[1]), GTK_TREE_MODEL (h_list[1]));

   gtk_widget_show(frame[1]);
   gtk_widget_show(notebook);

   /* setup the bottom table row */
   /* -------------------------- */
   frame[2] = gtk_frame_new(title_bottom_window);
   gtk_frame_set_label_align(GTK_FRAME (frame[2]), 0.5, 0.5);
   gtk_table_attach (GTK_TABLE (ec_table), frame[2], 0, 1, 3, 4, GTK_FILL | GTK_EXPAND, 0, 10, 10);
   gtk_widget_show(frame[2]);

   box = gtk_vbox_new(FALSE, 0);
   gtk_container_add (GTK_CONTAINER (frame[2]), box);

   bb_label[0] = gtk_label_new("                                   ");
   bb_label[1] = gtk_label_new("                                   ");

   gtk_misc_set_alignment(GTK_MISC (bb_label[0]), 0, 0);
   gtk_misc_set_alignment(GTK_MISC (bb_label[1]), 0, 0);

   gtk_container_add(GTK_CONTAINER (box), bb_label[0]);
   gtk_container_add(GTK_CONTAINER (box), bb_label[1]);

   gtk_widget_show(bb_label[0]);
   gtk_widget_show(bb_label[1]);
   gtk_widget_show(box);

   accel_group = gtk_accel_group_new();
   main_menu = gtk_item_factory_new (GTK_TYPE_MENU_BAR, "<main>", accel_group);
   gtk_window_add_accel_group(GTK_WINDOW (window), accel_group);

   Ginterface_ToolBar(main_menu);

   menubar = gtk_item_factory_get_widget (main_menu, "<main>");
   gtk_table_attach (GTK_TABLE (ec_table), menubar, 0, 1, 0, 1, GTK_FILL | GTK_EXPAND, 0, 0, 0);
   gtk_widget_show (menubar);

   gtk_widget_show(window);

   DEBUG_MSG("Ginterface_Screen_Init -- INIZIALIZED");
}

void Ginterface_ToolBar(GtkItemFactory *host_menu) {
   static GtkItemFactoryEntry action_menu[] = {
      MENU_COMMON
      { "/Action", NULL, NULL, 0, "<Branch>", NULL},
      { "/Action/Only Poison", "j", Ginterface_Callback, 'j', "<StockItem>", GTK_STOCK_YES },
      { "/Action/Delete Entry", "d", Ginterface_Callback, 'd', "<StockItem>", GTK_STOCK_DELETE },
      { "/Action/Packet Forge", "x", Ginterface_Callback, 'x', "<StockItem>", GTK_STOCK_PREFERENCES },
      { "/Action/Fingerprint", "f", Ginterface_Callback, 'f', "<ImageItem>", finger_icon },
      { "/Action/Check for Poisoner", "c", Ginterface_Callback, 'c', "<ImageItem>", search_icon },
      { "/Action/Refresh List", "r", Ginterface_Callback, 'r', "<StockItem>", GTK_STOCK_REFRESH},
      { "/Action/Clear Selections", "at", Ginterface_Callback, '@', "<StockItem>", GTK_STOCK_CLEAR},
      { "/Action/Save Host List", "k", Ginterface_Callback, 'k', "<StockItem>", GTK_STOCK_SAVE },
      { "/Help", NULL, NULL, 0, "<LastBranch>", NULL},
      { "/Help/_Manual", NULL, Ginterface_Manual, 0, "<StockItem>", GTK_STOCK_HELP},
      { "/Help/_About", NULL, Ginterface_About, 0, "<StockItem>", GTK_STOCK_DIALOG_INFO}
   };
   gint num_items = 0;

   DEBUG_MSG("Ginterface_ToolBar");

   gtk_item_factory_delete_item(host_menu, "/Quit");
   gtk_item_factory_delete_item(host_menu, "/Sniff");
   gtk_item_factory_delete_item(host_menu, "/View");
   gtk_item_factory_delete_item(host_menu, "/Action");
   gtk_item_factory_delete_item(host_menu, "/Help");

   num_items = sizeof (action_menu) / sizeof (action_menu[0]);
   gtk_item_factory_create_items (host_menu, num_items, action_menu, NULL);
}


void Ginterface_InitList(void)
{
   gint j = 0;
   char line[100];

   DEBUG_MSG("Ginterface_InitList");

   g_signal_handlers_block_by_func (G_OBJECT (h_selection[0]), G_CALLBACK (Ginterface_PointItem), "Source");
   g_signal_handlers_block_by_func (G_OBJECT (h_selection[1]), G_CALLBACK (Ginterface_PointItem), "Dest");

   /* if the lists exist, clear them, otherwise create them */
   /* ----------------------------------------------------- */
   if(h_list[0] != NULL)
      gtk_list_store_clear (GTK_LIST_STORE (h_list[0]));
   else
      h_list[0] = gtk_list_store_new (3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);

   if(h_list[1] != NULL)
      gtk_list_store_clear (GTK_LIST_STORE (h_list[1]));
   else
      h_list[1] = gtk_list_store_new (3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);

   if (number_of_hosts_in_lan == 0) return;

   /* populate the lists */
   /* ------------------ */
   for(j = 0; j < number_of_hosts_in_lan; j++) {
      sprintf(line, "%3d) ", j+1);

      gtk_list_store_append (h_list[0], &h_iter[0]);
      gtk_list_store_set (h_list[0], &h_iter[0], 
                      0, line,
                      1, Host_In_LAN[j].ip,
                      2, " ", -1);

      gtk_list_store_append (h_list[1], &h_iter[1]);
      gtk_list_store_set (h_list[1], &h_iter[1], 
                      0, line, 
                      1, Host_In_LAN[j].ip,
                      2, " ", -1);
   }

   g_signal_handlers_unblock_by_func (G_OBJECT (h_selection[0]), G_CALLBACK (Ginterface_PointItem), "Source");
   g_signal_handlers_unblock_by_func (G_OBJECT (h_selection[1]), G_CALLBACK (Ginterface_PointItem), "Dest");
}

/* this is similar to SelectItem, but doesn't setup Host_Source/Host_Dest or affect the top box */
void Ginterface_PointItem (GtkWidget *widget, gpointer data)
{
   GtkTreeIter iter;
   GtkTreeModel *model;
   gchar temp[150], *lineptr;
   int line;

   DEBUG_MSG("Ginterface_PointItem");

   if (gtk_tree_selection_get_selected (GTK_TREE_SELECTION (widget), &model, &iter)) {
      gtk_tree_model_get (model, &iter, 0, &lineptr, -1);
      if(lineptr == NULL || strlen(lineptr) < 4)
         return;
      sscanf(lineptr, "%i) ", &line);
      g_free (lineptr);
   }

   if(strcmp(data, "Source") == 0) {
      gSource_Pointer = line - 1;
      snprintf(temp, 150, "Host: %s (%s) : %s", Host_In_LAN[gSource_Pointer].name, 
               Host_In_LAN[gSource_Pointer].ip, Host_In_LAN[gSource_Pointer].mac);      
      Ginterface_EditBottom(0, temp);
   } else {
      gDest_Pointer  = line - 1;
      snprintf(temp, 150, "Host: %s (%s) : %s", Host_In_LAN[gDest_Pointer].name, 
               Host_In_LAN[gDest_Pointer].ip, Host_In_LAN[gDest_Pointer].mac);
      Ginterface_EditBottom(1, temp);
   }
}

void Ginterface_SelectItem(GtkTreeView *treeview, gpointer arg1, GtkTreeViewColumn *arg2, gpointer data)
{
   GtkTreeIter iter;
   GtkTreeModel *model;
   gchar *lineptr;
   gint line = 0;

   DEBUG_MSG("Ginterface_SelectItem");

   if(strcmp((char *)data, "Source") == 0) {
      if (gtk_tree_selection_get_selected (GTK_TREE_SELECTION (h_selection[0]), &model, &iter)) {
         gtk_tree_model_get (model, &iter, 0, &lineptr, -1);
         line = atoi(strtok(lineptr, ")"));
      }

      if(line < 1)
         return;

      gSource_Pointer = line - 1;
      Ginterface_EditTop(0, "Source:");
      Ginterface_EditTop(1, Host_In_LAN[gSource_Pointer].ip);
      Ginterface_EditTop(2, Host_In_LAN[gSource_Pointer].mac);
      memcpy(&Host_Source, &Host_In_LAN[gSource_Pointer], sizeof(HOST) );
   } else if(strcmp((char *)data, "Dest") == 0) {
      if (gtk_tree_selection_get_selected (GTK_TREE_SELECTION (h_selection[1]), &model, &iter)) {
         gtk_tree_model_get (model, &iter, 0, &lineptr, -1);
         line = atoi(strtok(lineptr, ")"));
      }

      if(line < 1)
         return;

      gDest_Pointer = line - 1;

      Ginterface_EditTop(6, "Dest:");
      Ginterface_EditTop(7, Host_In_LAN[gDest_Pointer].ip);
      Ginterface_EditTop(8, Host_In_LAN[gDest_Pointer].mac);
      memcpy(&Host_Dest, &Host_In_LAN[gDest_Pointer], sizeof(HOST) );
   }

   /* if ARP mode is disabled, enable it now that a source or dest has been selected */
   if(!GTK_WIDGET_SENSITIVE (tablabel[1]))
      gtk_widget_set_sensitive (GTK_WIDGET (tablabel[1]), TRUE);

}

void Ginterface_PopUp(char *question, ...)
{
   GtkWidget *dialog, *label;
   char message[150];
   va_list ap;

   DEBUG_MSG("Ginterface_PopUp");

   va_start(ap, question);
   vsnprintf(message, 150, question, ap);
   va_end(ap);

   /* Create the widgets */
   dialog = gtk_dialog_new_with_buttons ("ettercap", GTK_WINDOW (window), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_OK, GTK_RESPONSE_NONE, NULL);
   label = gtk_label_new (message);

   /* Ensure that the dialog box is destroyed when the user responds. */
   g_signal_connect_swapped (GTK_OBJECT (dialog), "response", G_CALLBACK (gtk_widget_destroy), GTK_OBJECT (dialog));

   gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER);

   /* Add the label, and show everything we've added to the dialog. */
   gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox), label);
   gtk_widget_show_all (dialog);
}

void Ginterface_PopUpN(char *notice)
{
   static GtkWidget *dialog, *label;

   DEBUG_MSG("Ginterface_PopUpN");
   
   if(notice) {
      dialog = gtk_dialog_new_with_buttons ("ettercap - notice", GTK_WINDOW (window), GTK_DIALOG_DESTROY_WITH_PARENT, NULL);
      label = gtk_label_new (notice);
      
      /* make it appear in the middle of the screen */
      gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER);

      /* remove the seperator since we wont need it */
      gtk_dialog_set_has_separator (GTK_DIALOG(dialog), FALSE);

      /* remove the borders and such as well.. */
      gtk_window_set_decorated (GTK_WINDOW (dialog), FALSE);

      gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox), label);
      gtk_widget_show(label); 
      gtk_widget_show_all (dialog);
   } else {
      if(!dialog) return;
      gtk_widget_destroy(dialog);
      dialog = NULL;
   }

   while (g_main_iteration(FALSE)); /* update gui */
}

/* same as previous but with a global progress bar that's manipulated by Parser_StatusBar */
void Ginterface_PopUpNP(char *notice)
{
   static GtkWidget *dialog, *label;

   DEBUG_MSG("Ginterface_PopUpNP");
  
   if(notice) {
      dialog = gtk_dialog_new_with_buttons ("ettercap - notice", GTK_WINDOW (window), GTK_DIALOG_DESTROY_WITH_PARENT, NULL);
      gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER);
      gtk_dialog_set_has_separator (GTK_DIALOG(dialog), FALSE);
      gtk_window_set_decorated (GTK_WINDOW (dialog), FALSE);

      label = gtk_label_new (notice);
      gtk_misc_set_alignment(GTK_MISC (label), 0, 0);
      gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), label, FALSE, FALSE, 0);

      splash_pbar = gtk_progress_bar_new ();
      gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), splash_pbar, FALSE, FALSE, 0);

      gtk_widget_show_all (dialog);
   } else {
      if(!dialog) return;
      gtk_widget_destroy(dialog);
      dialog = NULL;
   }

   while (g_main_iteration(FALSE)); /* update gui */
}

char Ginterface_PopUpQ(char *question, ...)
{
   GtkWidget *dialog, *label;
   char answer;
   int response;
   char message[150];
   va_list ap;

   DEBUG_MSG("Ginterface_PopUpQ");
   
   va_start(ap, question);
   vsnprintf(message, 150, question, ap);
   va_end(ap);
   
   dialog = gtk_dialog_new_with_buttons ("Question", GTK_WINDOW (window), 
                   GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, 
                   GTK_STOCK_YES, GTK_RESPONSE_YES, GTK_STOCK_NO, GTK_RESPONSE_NO, NULL);
   label = gtk_label_new (message);

   gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER);

   gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox), label);
   gtk_widget_show(label);

   response = gtk_dialog_run (GTK_DIALOG (dialog));

   if(response == -8)   // yes
      answer = 'y';
   else
      answer = 'n';

   gtk_widget_destroy (dialog);

   DEBUG_MSG("Ginterface_PopUpQ returns -- %c", answer); 
   return(answer); 
}

void Ginterface_RefreshList(void)
{
   DEBUG_MSG("Ginterface_RefreshList");

   Ginterface_PopUpNP( "updating the list..." );

   /* refresh the list */
   number_of_hosts_in_lan = Inet_HostInLAN();
   gSource_Pointer = gDest_Pointer = 0;
   gBase_Pointer = 0;
   sprintf(title_main_window, " %3d", number_of_hosts_in_lan);
   title_main_window[4] = ' ';
   gtk_frame_set_label (GTK_FRAME (frame[1]), title_main_window);

   Ginterface_InitList();
   Ginterface_PopUpNP(NULL);
}

void Ginterface_Manual (void)
{
   FILE *manpage;
   GtkWidget *dialog, *scrolled, *textview;
   GtkTextBuffer *buffer;
   gchar message[100];

   DEBUG_MSG("Ginterface_Manual");

   dialog = gtk_dialog_new_with_buttons ("Ettercap Manual", GTK_WINDOW (window), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_CLOSE, GTK_RESPONSE_NONE, NULL);
   gtk_window_set_default_size(GTK_WINDOW (dialog), 520, 300);
   gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER);
   g_signal_connect_swapped (GTK_OBJECT (dialog), "response", G_CALLBACK (gtk_widget_destroy), GTK_OBJECT (dialog));

   /* make the scrolled window */
   scrolled = gtk_scrolled_window_new(NULL, NULL);
   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
   gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox), scrolled);
   gtk_widget_show (scrolled);

   /* make the Text View window */
   textview = gtk_text_view_new();
   gtk_text_view_set_editable(GTK_TEXT_VIEW (textview), FALSE);
   gtk_text_view_set_left_margin(GTK_TEXT_VIEW (textview), 10);
   gtk_text_view_set_right_margin(GTK_TEXT_VIEW (textview), 10);
   gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled), textview);
   gtk_widget_show(textview);

   buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (textview));

   DEBUG_MSG("Ginterface_Manual - running: man ettercap | col -b");
   manpage = popen("man ettercap | col -b", "r");

   if(manpage == NULL) {
      Ginterface_PopUp ("Failed to execute 'man ettercap | col -b'.\n");
      return;
   }

   while(fgets(message, sizeof(message), manpage))
      gtk_text_buffer_insert_at_cursor(GTK_TEXT_BUFFER (buffer), g_locale_to_utf8 (message, strlen(message), NULL, NULL, NULL), -1);

   fclose(manpage);

   gtk_widget_show (dialog);
}

void Ginterface_About (void)
{
   GtkWidget *dialog, *image, *label, *book, *box, *scrolled, *textview;
   GdkPixbuf *pixbuf;
   GtkTextBuffer *buffer;
   GtkTextIter iter;
   FILE *infile;
   gchar line[100];
   gchar *aboutstring = "A multipurpose sniffer/interceptor/logger for switched LAN.\n\n"
                        "http://ettercap.sourceforge.net/\n\n"
                        "Copyright (C) 2002\n"
                        "ALoR <alor@users.sourceforge.net>\n"
                        "NaGA <crwm@freemail.it>\n";

   DEBUG_MSG("Ginterface_About");

   dialog = gtk_dialog_new_with_buttons ("About Ettercap", GTK_WINDOW (window), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_CLOSE, GTK_RESPONSE_NONE, NULL);
   gtk_window_set_default_size(GTK_WINDOW (dialog), 450, 400);
   gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER);
   g_signal_connect_swapped (GTK_OBJECT (dialog), "response", G_CALLBACK (gtk_widget_destroy), GTK_OBJECT (dialog));

#if DEVEL_RELEASE == 1
   snprintf (line, sizeof(line), "%s %s beta %s", PROGRAM, VERSION, RELEASE_DATE);
#else
   snprintf (line, sizeof(line), "%s %s", PROGRAM, VERSION);
#endif

   label = gtk_label_new (line);
   gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
   gtk_misc_set_padding (GTK_MISC (label), 0, 5);
   gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), label, FALSE, FALSE, 0);
   gtk_widget_show(label);

   book = gtk_notebook_new();
   gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), book, TRUE, TRUE, 0);
   gtk_widget_show(book);

   label = gtk_label_new ("About");
   box = gtk_vbox_new(FALSE, 0);
   gtk_notebook_append_page(GTK_NOTEBOOK (book), box, label);

   pixbuf = gdk_pixbuf_new_from_inline (-1, ettercap_logo, FALSE, NULL);
   image = gtk_image_new_from_pixbuf(pixbuf);
   gtk_box_pack_start (GTK_BOX(box), image, FALSE, FALSE, 0);
   gtk_widget_show(image);

   label = gtk_label_new (aboutstring);
   gtk_box_pack_start (GTK_BOX(box), label, FALSE, FALSE, 0);
   gtk_widget_show(label);

   snprintf(line, sizeof(line), "%s/AUTHORS", image_path);
   infile = fopen(line, "r");
   if(infile != NULL) {
      label = gtk_label_new ("Authors");
      box = gtk_vbox_new(FALSE, 0);
      gtk_notebook_append_page(GTK_NOTEBOOK (book), box, label);

      scrolled = gtk_scrolled_window_new(NULL, NULL);
      gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);  
      gtk_box_pack_start (GTK_BOX(box), scrolled, TRUE, TRUE, 0);
      gtk_widget_show(scrolled);

      textview = gtk_text_view_new();
      gtk_text_view_set_editable(GTK_TEXT_VIEW (textview), FALSE);
      gtk_text_view_set_left_margin(GTK_TEXT_VIEW (textview), 10);
      gtk_text_view_set_right_margin(GTK_TEXT_VIEW (textview), 10);
      gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled), textview);
      gtk_widget_show(textview);
   
      buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (textview));

      while(fgets(line, sizeof(line), infile)) {
         gtk_text_buffer_get_end_iter(GTK_TEXT_BUFFER (buffer), &iter);
         gtk_text_buffer_insert(GTK_TEXT_BUFFER (buffer), &iter,  g_locale_to_utf8 (line, strlen(line), NULL, NULL, NULL), -1);
      }
      fclose(infile);
   }

   /* just have to change the filename and tab-label, rest is same as last */
   snprintf(line, sizeof(line), "%s/THANKS", image_path);
   infile = fopen(line, "r");
   if(infile != NULL) {
      label = gtk_label_new ("Thanks");
      box = gtk_vbox_new(FALSE, 0);
      gtk_notebook_append_page(GTK_NOTEBOOK (book), box, label);

      scrolled = gtk_scrolled_window_new(NULL, NULL);
      gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
      gtk_box_pack_start (GTK_BOX(box), scrolled, TRUE, TRUE, 0);
      gtk_widget_show(scrolled);

      textview = gtk_text_view_new();
      gtk_text_view_set_editable(GTK_TEXT_VIEW (textview), FALSE);
      gtk_text_view_set_left_margin(GTK_TEXT_VIEW (textview), 10);
      gtk_text_view_set_right_margin(GTK_TEXT_VIEW (textview), 10);
      gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled), textview);
      gtk_widget_show(textview);

      buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (textview));

      while(fgets(line, sizeof(line), infile)) {
         gtk_text_buffer_get_end_iter(GTK_TEXT_BUFFER (buffer), &iter);
         gtk_text_buffer_insert(GTK_TEXT_BUFFER (buffer), &iter,  g_locale_to_utf8 (line, strlen(line), NULL, NULL, NULL), -1);
      }
      fclose(infile);
   }
      
   gtk_widget_show_all (dialog);
}

void Ginterface_HelpWindow(char *help[])
{
   char **counter, message[1024] = "";
   GtkWidget *dialog, *label;

   DEBUG_MSG("Ginterface_HelpWindow");

   /* Create the widgets */
   dialog = gtk_dialog_new_with_buttons ("Help Window", GTK_WINDOW (window), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_CLOSE, GTK_RESPONSE_NONE, NULL);

   /* build a single multiline string for the label */
   for (counter = help; *counter; counter++) {
      strcat(message, *counter);
      strcat(message, "\n");
   }

   label = gtk_label_new (g_locale_to_utf8 (message, strlen(message), NULL, NULL, NULL));

   /* Ensure that the dialog box is destroyed when the user responds. */
   g_signal_connect_swapped (GTK_OBJECT (dialog), "response", G_CALLBACK (gtk_widget_destroy), GTK_OBJECT (dialog));

   gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER);

   /* Add the label, and show everything we've added to the dialog. */
   gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox), label);
   gtk_widget_show_all (dialog);
}


void Ginterface_Connect(void)
{

   DEBUG_MSG("Ginterface_Connect");

   if ( (!strcmp(Host_Source.ip, "")) && (!strcmp(Host_Dest.ip, "")) ) {
      Ginterface_PopUp("Before sniffing select AT LEAST source OR destination !!");
   } else if ( (!strcmp(Host_Source.ip, Inet_MyIPAddress())) || (!strcmp(Host_Dest.ip, Inet_MyIPAddress())) ) {
      Ginterface_PopUp("You CAN'T arpsniff yourself !!");
   } else if ( !strcmp(Host_Source.ip, Host_Dest.ip) ) {
      Ginterface_PopUp("SOURCE and DEST (ip) must be different !!");
   } else if (Options.dumpfile && !Options.writedump) {
      Ginterface_PopUp("You CAN'T arpsniff from a file !!");
   } else {
      char answer;

      if (Options.silent || Options.arpsniff)  answer = 'y';
      else answer = Ginterface_PopUpQ("Do you really want to poison the ARP cache of the targets ?");

      if ((answer == 'y') || (answer == 'Y'))
      {
         Ginterface_EditTop(0, "Source:");

         if (strcmp(Host_Source.ip,""))
            Ginterface_EditTop(1, Host_Source.ip);
         else
            Ginterface_EditTop(1, "ANY");

         Ginterface_EditTop(6, "Dest:");

         if (strcmp(Host_Dest.ip,""))
            Ginterface_EditTop(7, Host_Dest.ip);
         else
            Ginterface_EditTop(7, "ANY");

         Ginterface_EditTop(5, "doppleganger ");

         if ( number_of_hosts_in_lan == 1 && ((!strcmp(Host_Source.ip, "")) || (!strcmp(Host_Dest.ip, ""))) )
            Ginterface_AppendTop(5, "- illithid (Public ARP) - ");
         else
            Ginterface_AppendTop(5, "- illithid (ARP Based) - ");

         Ginterface_AppendTop(5, PROGRAM);

         if ( number_of_hosts_in_lan == 1 && ((!strcmp(Host_Source.ip, "")) || (!strcmp(Host_Dest.ip, ""))) )
            Ginterface_Sniff_Run(PUBLICARP);   // with HALF duplex ARP poisoning
         else
            Ginterface_Sniff_Run(ARPBASED);   // with FULL duplex ARP poisoning
      }
   }
}



void Ginterface_OldStyleSniff(short mode)
{

   DEBUG_MSG("Ginterface_OldStyleSniff -- mode = %d -- [%s] [%s]", mode, Host_Source.ip, Host_Dest.ip);

   if ( !strcmp(Host_Source.ip, Host_Dest.ip) && strcmp(Host_Source.ip, "") )
      Ginterface_PopUp("SOURCE and DEST (ip) must be different !!");
   else if ( !strcmp(Host_Source.mac, Host_Dest.mac) && strcmp(Host_Source.mac, ""))
      Ginterface_PopUp("SOURCE and DEST (mac) must be different !!");
   else
   {
      Ginterface_EditTop(0, "Source:");

      if (mode)
      {
         if (strcmp(Host_Source.mac,""))
            Ginterface_EditTop(1, Host_Source.mac);
         else
            Ginterface_EditTop(1, "ANY");
      } else {
         if (strcmp(Host_Source.ip,""))
            Ginterface_EditTop(1, Host_Source.ip);
         else
            Ginterface_EditTop(1, "ANY");
      }

      Ginterface_EditTop(6, "Dest:");

      if (mode) 
      {
         if (strcmp(Host_Dest.mac,""))
            Ginterface_EditTop(7, Host_Dest.mac);
         else
            Ginterface_EditTop(7, "ANY");
      } else {
         if (strcmp(Host_Dest.ip,""))
            Ginterface_EditTop(7, Host_Dest.ip);
         else
            Ginterface_EditTop(7, "ANY");
      }

      if (!Options.writedump && Options.dumpfile) {
         Ginterface_EditTop(5, "OffLine sniffing [");
         Ginterface_AppendTop(5, Options.dumpfile);
         Ginterface_AppendTop(5, "]");
      } else if (mode) {
         Ginterface_EditTop(5, "illithid (MAC based) - ");
         Ginterface_AppendTop(5, PROGRAM);
      } else {
         Ginterface_EditTop(5, "illithid (IP based) - ");
         Ginterface_AppendTop(5, PROGRAM);
      }

      if (mode)
         Ginterface_Sniff_Run(MACBASED);   // no ARP poisoning
      else
         Ginterface_Sniff_Run(IPBASED);    // no ARP poisoning
   }
}

void Ginterface_OnlyPoison(void)
{
   GtkWidget *dialog, *label;
   DEBUG_MSG("Ginterface_OnlyPoison");

   if ( (!strcmp(Host_Source.ip, "")) && (!strcmp(Host_Dest.ip, "")) )
      Ginterface_PopUp("Before poison select AT LEAST source OR destination !!");
   else if ( (!strcmp(Host_Source.ip, Inet_MyIPAddress())) || (!strcmp(Host_Dest.ip, Inet_MyIPAddress())) )
      Ginterface_PopUp("You CAN'T poison yourself !!");
   else if ( !strcmp(Host_Source.ip, Host_Dest.ip) )
      Ginterface_PopUp("SOURCE and DEST (ip) must be different !!");
   else
   {
      int i;
      gchar message[512];
      pthread_t Dopple_pid = 0;
      
      for(i=0; i<number_of_hosts_in_lan; i++)
      {
        if ( !strcmp(Host_Source.ip, Host_In_LAN[i].ip) )
           strlcpy(Host_Source.mac, Host_In_LAN[i].mac, sizeof(Host_Source.mac));
        if ( !strcmp(Host_Dest.ip, Host_In_LAN[i].ip) )
           strlcpy(Host_Dest.mac, Host_In_LAN[i].mac, sizeof(Host_Dest.mac));
      }

      if ( !strcmp(Host_Source.mac, "") && !strcmp(Host_Dest.mac, "") )
        Error_msg("Doppelganger needs at least one valid mac address !!\n\n(the ip was not found in the list)");

      Dopple_pid = Doppleganger_Run(Options.netiface, Host_Source.ip, Host_Dest.ip, Host_Source.mac, Host_Dest.mac);

      // make modal window, STOP button   
      dialog = gtk_dialog_new_with_buttons ("", GTK_WINDOW (window), GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
                                 GTK_STOCK_CLOSE, GTK_RESPONSE_NONE, NULL);
      gtk_window_set_decorated ( GTK_WINDOW(dialog), FALSE );

      sprintf(message, "Poisoning - %s [%s] -- %s [%s]\nClick \"Close\" to stop...\n", Host_Source.ip, Host_Source.mac, Host_Dest.ip, Host_Dest.mac);
      label = gtk_label_new (message);
      gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox), label);
      gtk_widget_show(label);

      gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER);

      gtk_dialog_run (GTK_DIALOG (dialog));
     
      Ginterface_PopUpN("Shutting down all threads...\n");
      
      ECThread_destroy(Dopple_pid);

      Ginterface_PopUpN(NULL);
                                                                                                      
      gtk_main_quit();
   }
   
   DEBUG_MSG("Ginterface_OnlyPoison -- END");
}

   
void Ginterface_CheckForPoisoner(void)
{
   SniffingHost *SniffList;
   int i;
   short found = 0;

   DEBUG_MSG("Ginterface_CheckForPoisoner");

   if (number_of_hosts_in_lan == 1)
   {
      Ginterface_PopUp("You cannot check the lan in silent mode");
      return;
   }

   Ginterface_PopUpN("Checking for poisoners...");

   SniffList = Inet_NoSniff();

   for (i=0; ; i++)
   {
      if (SniffList[i].mode == 0) break;
      if (SniffList[i].mode == 1)
      {
         found = 1;
         Ginterface_PopUp("%s is replying for %s", Host_In_LAN[SniffList[i].Host_Index1].ip, Host_In_LAN[SniffList[i].Host_Index2].ip);
      }

      if (SniffList[i].mode == 2)
      {
         found = 1;
         Ginterface_PopUp("MAC of %s and %s are identical !",Host_In_LAN[SniffList[i].Host_Index1].ip,Host_In_LAN[SniffList[i].Host_Index2].ip);
      }
   }

   if (!found)
      Ginterface_PopUp("No poisoners found in this lan (seems to be safe)");

   free(SniffList);
   Ginterface_PopUpN(NULL);
}



void Ginterface_FingerPrint(void)
{
   GtkWidget *dialog, *label, *f_table;
   char *mac_finger;
   char *long_os_fingers;
   char line[100];

   DEBUG_MSG("Ginterface_FingerPrint -- [%s] [%s]", Host_In_LAN[*gPointer].ip, Host_In_LAN[*gPointer].mac );

   Ginterface_PopUpN ("Fingerprinting ...");

   long_os_fingers = strdup(Fingerprint_OS(Host_In_LAN[*gPointer].ip) );
   mac_finger = strdup(Fingerprint_MAC(Host_In_LAN[*gPointer].mac));

   Ginterface_PopUpN (NULL);

   sprintf(line, "FingerPrint %s", Host_In_LAN[*gPointer].ip);
   dialog = gtk_dialog_new_with_buttons (line, GTK_WINDOW (window), GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, 
                                          GTK_STOCK_OK, GTK_RESPONSE_NONE, NULL);
   // g_signal_connect_swapped (GTK_OBJECT (dialog), "response", G_CALLBACK (gtk_widget_destroy), GTK_OBJECT (dialog));
   f_table = gtk_table_new (2, 2, FALSE); 
   gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox), f_table);
   gtk_widget_show(f_table);

   label = gtk_label_new("Operating System:");
   gtk_misc_set_alignment (GTK_MISC (label), 0, 0);   /* align to top left of cell */
   gtk_table_attach (GTK_TABLE (f_table), label, 0, 1, 0, 1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 10, 5); 
   gtk_widget_show(label);

   label = gtk_label_new("Network Adapter :");
   gtk_misc_set_alignment (GTK_MISC (label), 0, 0);   /* align to top left of cell */
   gtk_table_attach (GTK_TABLE (f_table), label, 0, 1, 1, 2, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 10, 5);
   gtk_widget_show(label);

   label = gtk_label_new(long_os_fingers);
   gtk_misc_set_alignment (GTK_MISC (label), 0, 0);   /* align to top left of cell */
   gtk_table_attach (GTK_TABLE (f_table), label, 1, 2, 0, 1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 10, 5);
   gtk_widget_show(label);

   label = gtk_label_new(mac_finger);
   gtk_misc_set_alignment (GTK_MISC (label), 0, 0);   /* align to top left of cell */
   gtk_table_attach(GTK_TABLE (f_table), label, 1, 2, 1, 2, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 10, 5);
   gtk_widget_show(label);

   DEBUG_MSG("Ginterface_FingerPrint");   

   gtk_dialog_run (GTK_DIALOG (dialog));

   gtk_widget_destroy (dialog);
   free(long_os_fingers);
   free(mac_finger);
}



void Ginterface_EntryRemoval(void)
{
   DEBUG_MSG("Ginterface_EntryRemoval -- %d", *gPointer);

   if (*gPointer == 0 || number_of_hosts_in_lan == 1)
   {
      Ginterface_PopUp("You cannot remove yourself from the list !!");
      return;
   }

   if (*gPointer < number_of_hosts_in_lan-1)
      memmove(&Host_In_LAN[*gPointer], &Host_In_LAN[*gPointer+1], (number_of_hosts_in_lan-1-*gPointer)*sizeof(HOST));
   else
      *gPointer = *gPointer - 1;

   number_of_hosts_in_lan--;

   Host_In_LAN = realloc(Host_In_LAN, number_of_hosts_in_lan*sizeof(HOST));
   if (Host_In_LAN == NULL)
      Error_msg("ec_gtk:%d realloc() | ERRNO : %d | %s", __LINE__, errno, strerror(errno));

}

void Ginterface_EditTop(int which, char *message)
{
   /* 'which' is the cell number:  */
   /*--------------------------------
   |   0   | <--\  |   1   |   2
   ---------    |  ------------------
   |   3   |    |--|   4   |   5
   ---------    |  ------------------
   |   6   | <--/  |   7   |   8
   --------------------------------*/

   gtk_label_set_text (GTK_LABEL (tb_label[which]), message);
}

void Ginterface_ClearTop(void)
{
   DEBUG_MSG("Ginterface_ClearTop");
   gtk_label_set_text(GTK_LABEL (tb_label[0]), "       ");
   gtk_label_set_text(GTK_LABEL (tb_label[1]), "       ");
   gtk_label_set_text(GTK_LABEL (tb_label[2]), "       ");
   gtk_label_set_text(GTK_LABEL (tb_label[3]), "       ");
   gtk_label_set_text(GTK_LABEL (tb_label[4]), "       ");
   gtk_label_set_text(GTK_LABEL (tb_label[5]), "       ");
   gtk_label_set_text(GTK_LABEL (tb_label[6]), "       ");
   gtk_label_set_text(GTK_LABEL (tb_label[7]), "       ");
   gtk_label_set_text(GTK_LABEL (tb_label[8]), "       ");
}

void Ginterface_AppendTop(int which, char *message)
{
   gchar *contents, *line;

   DEBUG_MSG("Ginterface_AppendTop");

   contents = strdup( gtk_label_get_text (GTK_LABEL (tb_label[which])) );
   line = (gchar *)g_malloc(strlen(contents) + strlen(message) + 1);

   if(line == NULL)
      return;
   
   strcpy(line, contents);
   strcat(line, message);
   
   gtk_label_set_text (GTK_LABEL (tb_label[which]), line);

   g_free(line);
}

void Ginterface_EditBottom(int which, char *message)
{
   DEBUG_MSG("Ginterface_EditBottom");
   gtk_label_set_text (GTK_LABEL (bb_label[which]), message);
}

void Ginterface_ClearBottom(void)
{
   DEBUG_MSG("Ginterface_ClearBottom");
   gtk_label_set_text (GTK_LABEL (bb_label[0]), " ");
   gtk_label_set_text (GTK_LABEL (bb_label[1]), " ");
}

void Ginterface_AppendBottom(int which, char *message)
{
   gchar *contents, *line;

   DEBUG_MSG("Ginterface_AppendBottom");

   contents = strdup( gtk_label_get_text (GTK_LABEL (bb_label[which])) );
   line = (gchar *)g_malloc(strlen(contents) + strlen(message) + 1);

   if(line == NULL)
      return;
 
   strcpy(line, contents);
   strcat(line, message);
 
   gtk_label_set_text (GTK_LABEL (bb_label[which]), line);

   g_free(line);
}

void Ginterface_Run(void)
{
   DEBUG_MSG("Ginterface_Run");
   Ginterface_Splash_Init();
   Ginterface_Splash_Show();

   if (Options.arpsniff)
      gtk_notebook_set_current_page(GTK_NOTEBOOK (notebook), 1);
   else if (Options.macsniff)
      gtk_notebook_set_current_page(GTK_NOTEBOOK (notebook), 3);
   else if (Options.sniff)
      gtk_notebook_set_current_page(GTK_NOTEBOOK (notebook), 2);
   else if (Options.passive)
      gtk_notebook_set_current_page(GTK_NOTEBOOK (notebook), 4);
   #ifdef PERMIT_PLUGINS
   else if (Options.plugin)
      gtk_notebook_set_current_page(GTK_NOTEBOOK (notebook), 5);
   #endif

   if (Options.silent && !(Options.sniff || Options.macsniff || Options.arpsniff))
      Options.silent = 0;

   if (Options.hoststofile)
      Ginterface_PopUp("Host list dumped into file: %s", Inet_Save_Host_List());

   /* main interface loop, doesn't return until program is done */
   gtk_main();
}

void Ginterface_Callback(gpointer data, guint action, GtkWidget *widget) {
      switch (action)
      {
         case 'A':
         case 'a':
            gtk_notebook_set_current_page(GTK_NOTEBOOK (notebook), 1);
            break;
         case 'M':
         case 'm':
            gtk_notebook_set_current_page(GTK_NOTEBOOK (notebook), 3);
            break;
         case 'S':
         case 's':
            gtk_notebook_set_current_page(GTK_NOTEBOOK (notebook), 2);
            break;
         case 'O':
         case 'o':
            gtk_notebook_set_current_page(GTK_NOTEBOOK (notebook), 4);
            break;
#ifdef PERMIT_PLUGINS
         case 'P':
         case 'p':
            gtk_notebook_set_current_page(GTK_NOTEBOOK (notebook), 5);
            break;
#endif

         case 'C':
         case 'c':
            Ginterface_CheckForPoisoner();
            break;
         case 'F':
         case 'f':
            Ginterface_FingerPrint();
            break;    
         case '@':    
            // clear selections
            memset(&Host_Source, 0, sizeof(HOST));
            memset(&Host_Dest, 0, sizeof(HOST));
            gtk_widget_set_sensitive (GTK_WIDGET (tablabel[1]), FALSE);                           Ginterface_ClearTop();
            break;                                                                             case 'X':
         case 'x':
            Ginterface_Factory_Run();
            break;                                                                             case 'D':
         case 'd':
            Ginterface_EntryRemoval();
            Ginterface_InitList();
            break;
         case 'J':
         case 'j':
            Ginterface_OnlyPoison(); /* never returns */
            break;
         case 'H':
         case 'h':
            {
            static char *help[] = {
               "[qQ][F10] - quit",
               "[return]  - select the IP",
               "[space]   - deselect the IPs",
               "[tab]     - switch between source and dest",
               "[aA]      - ARP poisoning based sniffing ",
               "             . for sniffing on switched LAN",
               "             . for man-in-the-middle technique",
               "[sS]      - IP based sniffing",
               "[mM]      - MAC based sniffing",
               "[jJ]      - Only poisoning - no sniffing",
               "[dD]      - delete an entry from the list",
               "[xX]      - Packet Forge",
               "[pP]      - run a plugin",
               "[fF]      - OS fingerprint",
               "[oO]      - passive host identification",
               "[cC]      - check for other poisoner...",
               "[rR]      - refresh the list",
               "[kK]      - save host list to a file",
               "[hH]      - this help screen",
               NULL};
            Ginterface_HelpWindow(help);
            }
            break;
         case 'R':
         case 'r':
            Ginterface_RefreshList();
            Ginterface_InitList();
            break;
         case 'K':
         case 'k':
            Ginterface_PopUp("Host list dumped to file: %s", Inet_Save_Host_List());
            break;
         case 'q':
         case 'Q':
            if(gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook)) != 0) {
               gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), 0);             
            } else {
               char answer;
               DEBUG_MSG("Ginterface_Run_END");
               answer = Ginterface_PopUpQ("Do you really want to exit?");
               if ((answer == 'y') || (answer == 'Y'))
                  Ginterface_WExit("They are safe!!  for now... ");
            }
            break;
      }
}

void Ginterface_SwitchPage(GtkNotebook *notebook, GtkNotebookPage *page, gint page_num, gpointer user_data) {
   static int notebook_page;

   DEBUG_MSG("Ginterface_SwitchPage - current page: %i, new page: %i", notebook_page, page_num);

   /* if newpage and oldpage are the same, don't do anything */
   if(notebook_page == page_num)
      return;
   
   /* see which mode we're leaving */
   switch (notebook_page) {
      case 0:
         break;
      case 1:
      case 2:
      case 3:
         if(s_scrolled)
            gtk_container_remove (GTK_CONTAINER (mainbox[notebook_page]), s_scrolled);
         Ginterface_Sniff_Stop();
         break;
      case 4:
         Ginterface_Passive_Stop();
         Ginterface_InitList();
         break;
#ifdef PERMIT_PLUGINS
      case 5:
         Ginterface_Plugins_Stop();
         break;
#endif
   }

   /* update current page */
   notebook_page = page_num;

   /* and which mode to change too */
   switch (page_num) {
      case 0:
         if(GTK_WIDGET_VISIBLE(arrows))
            gtk_widget_hide(arrows);
         Ginterface_ToolBar(main_menu);
         memset(&Host_Source, 0, sizeof(HOST));
         memset(&Host_Dest, 0, sizeof(HOST));
         Ginterface_ClearTop();
         Ginterface_ClearBottom();
         break;

      case 1:
         if(!GTK_WIDGET_VISIBLE(arrows))
            gtk_widget_show (arrows);
         Ginterface_Sniff_ToolBar(main_menu);
         Options.arpsniff = 1;
         Options.sniff = 0;
         Options.macsniff = 0;
         Ginterface_Connect();
         break;

      case 2:
         if(!GTK_WIDGET_VISIBLE(arrows))
            gtk_widget_show (arrows);
         Ginterface_Sniff_ToolBar(main_menu);
         Options.arpsniff = 0;
         Options.sniff = 1;
         Options.macsniff = 0;
         Ginterface_OldStyleSniff(0);
         break;

      case 3:
         if(!GTK_WIDGET_VISIBLE(arrows))
            gtk_widget_show (arrows);
         Ginterface_Sniff_ToolBar(main_menu);
         Options.arpsniff = 0;
         Options.sniff = 0;
         Options.macsniff = 1;
         Ginterface_OldStyleSniff(1);
         break;
      case 4:
         Ginterface_ClearTop();
         if(!GTK_WIDGET_VISIBLE(arrows))
            gtk_widget_show (arrows);
         Ginterface_Passive_ToolBar(main_menu);
         Ginterface_Passive_Run();
         break;
#ifdef PERMIT_PLUGINS
      case 5:
         if(GTK_WIDGET_VISIBLE(arrows))
            gtk_widget_hide(arrows);
         Ginterface_Plugins_ToolBar(main_menu);
         Ginterface_ClearTop();
         Ginterface_ClearBottom();
         Ginterface_Plugins_Run();
         break;
#endif
   }
}

/* figure out if ettercap was installed properly, if not, use images in local dir */
void Ginterface_CheckImgPath(char *path)
{
   FILE *testimg;
   char line[200];

   snprintf(line, sizeof(line), "%s/AUTHORS", path);
   testimg = fopen(line, "r");

   if(testimg == NULL)
      snprintf(image_path, sizeof(image_path), ".");
   else {
      snprintf(image_path, sizeof(image_path), "%s", path);
      fclose(testimg);
   }
}

void Ginterface_Screen_Close(void)
{
   gint page = -1;
   DEBUG_MSG("Ginterface_Screen_Close");

   page = gtk_notebook_get_current_page(GTK_NOTEBOOK (notebook));
   
   if(page > 0)
      gtk_notebook_set_current_page(GTK_NOTEBOOK (notebook), 0);

   while (g_main_iteration(FALSE)); /* update gui */

   gtk_main_quit();
}

void Ginterface_WExit(char *buffer)
{
   DEBUG_MSG("Ginterface_WExit -- [%s]", buffer);

   if (Options.gtk) Ginterface_Screen_Close();

   fprintf(stdout, "\n\n");
   fprintf(stdout, "\033[01m\033[1m%s %s brought from the dark side of the net by ALoR, NaGA and daten...\033[0m\n\n", PROGRAM, VERSION);
   fprintf(stdout, "\033[01m\033[1mmay the packets be with you...\033[0m\n\n");
   fprintf(stdout, "\n%s\n\n", buffer);
}

#ifndef HAVE_FORM
void trim_buffer(char *buffer, char trim)
{
   int i;

   for(i = strlen(buffer)-1; i >= 0; i--)
      if (buffer[i] == trim) buffer[i] = 0;
      else break;
}
#endif

/* EOF */

// vim:ts=3:expandtab

