/*
    ettercap -- gtk interface for passive scanning of the LAN

    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 <sys/types.h>
#include <sys/stat.h>
#if defined(HAVE_SYS_POLL_H)
   #include <sys/poll.h>
#elif defined (HAVE_POLL_H)
   #include <poll.h>
#endif

#include <ec_version.h>
#include <ec_gtk.h>
#include <ec_decodedata.h>
#include <ec_dryad.h>
#include <ec_inet.h>
#include <ec_inet_forge.h>
#include <ec_inet_structures.h>
#include <ec_buffer.h>
#include <ec_logtofile.h>
#include <ec_fingerprint.h>
#include <ec_thread.h>

// protos...
void Ginterface_Passive_ToolBar(GtkItemFactory *host_menu);
void Ginterface_Passive_Callback(gpointer data, guint action, GtkWidget *widget);
void Ginterface_Passive_Run(void);
void Ginterface_Passive_PointItem(GtkWidget *widget, gpointer data);
void Ginterface_Passive_SelectItem(GtkTreeView *treeview, gpointer arg1, GtkTreeViewColumn *arg2, gpointer data);
void Ginterface_Passive_UpdateList(void);
gboolean Ginterface_Passive_RefreshList(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data);
void Ginterface_Passive_MakeReport(char mode);
void Ginterface_Passive_ShowDetails(int i);
void Ginterface_Passive_Submit(GtkWidget *widget, gpointer data);
void Ginterface_Passive_Showname(void);
void Ginterface_Passive_Stop(void);
gboolean Ginterface_Passive_WatchList(gpointer data);

// global variables
pthread_t Dryad_pid;

GtkListStore *liststore;
GtkTreeIter listiter;
GtkCellRenderer *renderer;
GtkTreeViewColumn *column;
GtkWidget *treeview, *scrolled;
GtkTreeSelection *selection;

extern short LeftMargin;

int gHost_Pointer = 0;
int list_bottom = 0;
int id_watch;
extern int Sel_Number;
char gshowname = 0;

extern char read_from_dump_flag;  // from inet

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

/* this function adds any new entries to the list and calls gtk_tree_model_foreach to update old ones */
void Ginterface_Passive_UpdateList(void)
{
   int j;
   
   DEBUG_MSG("Ginterface_Passive_UpdateList");

   /* if we haven't made a list yet, make one */
   if(!liststore) {
      liststore = gtk_list_store_new (4, G_TYPE_INT, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
      gtk_tree_view_set_model (GTK_TREE_VIEW (treeview), GTK_TREE_MODEL (liststore));
   }

   for(j = list_bottom; j < number_of_passive_hosts; j++)
   {
      gtk_list_store_append (GTK_LIST_STORE (liststore), &listiter);
      gtk_list_store_set (GTK_LIST_STORE (liststore), &listiter, 
                        0, j+1, 
                        1, (gshowname && strcmp(Passive_Host[j].name, "")) ? Passive_Host[j].name : Passive_Host[j].ip,
                        2, Passive_Host[j].type,
                        3, Passive_Host[j].os, -1);
      ++list_bottom;
   }

   gtk_tree_model_foreach(GTK_TREE_MODEL (liststore), Ginterface_Passive_RefreshList, NULL);
}      

/* this is called by gtk_tree_model_foreach() on each element of the list store */
gboolean Ginterface_Passive_RefreshList(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
{
   int line, j;
   gchar name[256], type[5], os[256]; /* fix these sizes */

   gtk_tree_model_get (model, iter, 
                        0, &line, 
                        1, name, 
                        2, type,
                        3, os, -1);

   j = line - 1;

   if((strcmp(name, (gshowname && strcmp(Passive_Host[j].name, "")) ? Passive_Host[j].name : Passive_Host[j].ip) == 0) &&
      (strcmp(type, Passive_Host[j].type) == 0) &&
      (strcmp(os, Passive_Host[j].os) == 0))
      return(FALSE);

   gtk_list_store_set (GTK_LIST_STORE (model), iter, 
                        0, j+1,
                        1, (gshowname && strcmp(Passive_Host[j].name, "")) ? Passive_Host[j].name : Passive_Host[j].ip,
                        2, Passive_Host[j].type,
                        3, Passive_Host[j].os, -1);

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

   return(FALSE);
}

/* callback function, don't use it directly */
void Ginterface_Passive_PointItem(GtkWidget *widget, gpointer data)
{
   GtkTreeIter iter;
   GtkTreeModel *model;
   gchar temp[150];
   int line;

   if (number_of_passive_hosts == 0) return;   /* no connection... no action... ;) */

   if (gtk_tree_selection_get_selected (GTK_TREE_SELECTION (widget), &model, &iter)) {
      gtk_tree_model_get (model, &iter, 0, &line, -1);
      // line = atoi(strtok(lineptr, ")"));
   } else return;

   gHost_Pointer = line - 1;

   if (Passive_Host[gHost_Pointer].os[0] == 0 && Passive_Host[gHost_Pointer].os[1] != 0)
   {
      snprintf(temp, 150, "UNKNOWN FINGERPRINT : %s\n",  Passive_Host[gHost_Pointer].fingerprint);
      Ginterface_EditBottom(0, temp);
      snprintf(temp, 150, "THE NEAREST IS      : %s", Passive_Host[gHost_Pointer].os + 1);
      Ginterface_EditBottom(1, temp);
   }
}

/* selection callback, wrapper to passive_callback */
void Ginterface_Passive_SelectItem(GtkTreeView *treeview, gpointer arg1, GtkTreeViewColumn *arg2, gpointer data)
{
   Ginterface_Passive_Callback(NULL, (guint) '!', GTK_WIDGET (treeview));
}

void Ginterface_Passive_MakeReport(char mode)
{
   char *file;

   DEBUG_MSG("Ginterface_Passive_MakeReport");

   Ginterface_PopUpN("Making report...");

   Decodedata_Passive_SortList();
   file = LogToFile_MakePassiveReport(mode);

   Ginterface_PopUpN(NULL);

   Ginterface_PopUp("Report stored in %s", file);
}

void Ginterface_Passive_ShowDetails(int i)
{
   GtkWidget *dialog, *table, *label, *button, *box;
   char found = 0, temp[150];
   struct open_ports *current;

   DEBUG_MSG("Ginterface_Passive_ShowDetails");

   dialog = gtk_dialog_new_with_buttons ("Host Details :", GTK_WINDOW (window), GTK_DIALOG_DESTROY_WITH_PARENT,
                                         GTK_STOCK_OK, GTK_RESPONSE_NONE, NULL);

   /* make and pack the table */
   table = gtk_table_new (12, 2, FALSE);
   gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox), table);
   gtk_widget_show (table);

   /* make the labels on the left */
   /* --------------------------- */
   label = gtk_label_new ("IP Address  : ");
   gtk_misc_set_alignment(GTK_MISC (label), 0, 0);
   gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 0, 1);
   gtk_widget_show (label);

   label = gtk_label_new ("MAC address : ");
   gtk_misc_set_alignment(GTK_MISC (label), 0, 0);
   gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 1, 2);
   gtk_widget_show (label);

   label = gtk_label_new ("Hostname    : ");
   gtk_misc_set_alignment(GTK_MISC (label), 0, 0);
   gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 2, 3);
   gtk_widget_show (label);

   if (!strcmp(Passive_Host[i].type, "GW")) {
      snprintf(temp, 150, " **** THIS HOST IS A GATEWAY FOR IPs LIKE %s ****", Passive_Host[i].gwforthis);
      label = gtk_label_new (temp);
      gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 2, 3, 4);
      gtk_widget_show(label);
   } else if (!strcmp(Passive_Host[i].type, "RT")) {
      label = gtk_label_new (" **** THIS HOST ACTS AS A ROUTER FOR THE LAN ****");
      gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 2, 3, 4);
      gtk_widget_show(label);
   } else if (!strcmp(Passive_Host[i].type, "NL")) {
      label = gtk_label_new (" **** THIS HOST DOESN'T BELONG TO THE NETMASK ****");
      gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 2, 3, 4);
      gtk_widget_show(label);
   }

   if (Passive_Host[i].os[0] == 0 && Passive_Host[i].os[1] != 0) {
      label = gtk_label_new ("Unknown Fingerprint: ");
      gtk_misc_set_alignment(GTK_MISC (label), 0, 0);
      gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 4, 5);
      gtk_widget_show (label);

      label = gtk_label_new (Passive_Host[i].fingerprint);
      gtk_label_set_selectable (GTK_LABEL (label), TRUE);
      gtk_misc_set_alignment(GTK_MISC (label), 0, 0);
      gtk_table_attach_defaults (GTK_TABLE (table), label, 1, 2, 4, 5);
      gtk_widget_show(label);

      label = gtk_label_new ("The Nearest Is     : ");
      gtk_misc_set_alignment(GTK_MISC (label), 0, 0);
      gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 5, 6);
      gtk_widget_show (label);

      label = gtk_label_new (Passive_Host[i].os + 1);
      gtk_label_set_selectable (GTK_LABEL (label), TRUE);
      gtk_misc_set_alignment(GTK_MISC (label), 0, 0);
      gtk_table_attach_defaults (GTK_TABLE (table), label, 1, 2, 5, 6);
      gtk_widget_show(label);

      button = gtk_button_new_with_mnemonic ("_Click here if you know the right OS");
      gtk_table_attach (GTK_TABLE (table), button, 0, 2, 6, 7, 0, 0, 0, 0);
      gtk_widget_show (button);
      g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (Ginterface_Passive_Submit), (gpointer)i);
      /* connect signal to Ginterface_Passive_Submit(i); */
   } else {
      label = gtk_label_new ("Fingerprint : ");
      gtk_misc_set_alignment(GTK_MISC (label), 0, 0);
      gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 4, 5);
      gtk_widget_show (label);

      label = gtk_label_new (Passive_Host[i].fingerprint);
      gtk_label_set_selectable (GTK_LABEL (label), TRUE);
      gtk_misc_set_alignment(GTK_MISC (label), 0, 0);
      gtk_table_attach_defaults (GTK_TABLE (table), label, 1, 2, 4, 5);
      gtk_widget_show(label);

      label = gtk_label_new ("Operating System : ");
      gtk_misc_set_alignment(GTK_MISC (label), 0, 0);
      gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 5, 6);
      gtk_widget_show (label);

      label = gtk_label_new (Passive_Host[i].os);
      gtk_label_set_selectable (GTK_LABEL (label), TRUE);
      gtk_misc_set_alignment(GTK_MISC (label), 0, 0);
      gtk_table_attach_defaults (GTK_TABLE (table), label, 1, 2, 5, 6);
      gtk_widget_show(label);
   }   

   label = gtk_label_new ("Network Adapter  : ");
   gtk_misc_set_alignment(GTK_MISC (label), 0, 0);
   gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 7, 8);
   gtk_widget_show (label);

   label = gtk_label_new ("Distance in HOP  : ");
   gtk_misc_set_alignment(GTK_MISC (label), 0, 0);
   gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 8, 9);
   gtk_widget_show (label);

   label = gtk_label_new ("Open Ports (tcp) : ");
   gtk_misc_set_alignment(GTK_MISC (label), 0, 0);
   gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 9, 10);
   gtk_widget_show (label);

   label = gtk_label_new ("Open Ports (udp) : ");
   gtk_misc_set_alignment(GTK_MISC (label), 0, 0);
   gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 10, 11);
   gtk_widget_show (label);

   /* make the entries on the right            */
   /* ---------------------------------------- */
   label = gtk_label_new (Passive_Host[i].ip);
   gtk_label_set_selectable (GTK_LABEL (label), TRUE);
   gtk_misc_set_alignment(GTK_MISC (label), 0, 0);
   gtk_table_attach_defaults (GTK_TABLE (table), label, 1, 2, 0, 1);
   gtk_widget_show(label);

   label = gtk_label_new (Passive_Host[i].mac);
   gtk_label_set_selectable (GTK_LABEL (label), TRUE);
   gtk_misc_set_alignment(GTK_MISC (label), 0, 0);
   gtk_table_attach_defaults (GTK_TABLE (table), label, 1, 2, 1, 2);
   gtk_widget_show(label);

   label = gtk_label_new (Inet_HostName(Passive_Host[i].ip));
   gtk_label_set_selectable (GTK_LABEL (label), TRUE);
   gtk_misc_set_alignment(GTK_MISC (label), 0, 0);
   gtk_table_attach_defaults (GTK_TABLE (table), label, 1, 2, 2, 3);
   gtk_widget_show(label);

   /* fingerprint and OS entries handled in label section */

   label = gtk_label_new (Fingerprint_MAC(Passive_Host[i].mac));
   gtk_label_set_selectable (GTK_LABEL (label), TRUE);
   gtk_misc_set_alignment(GTK_MISC (label), 0, 0);
   gtk_table_attach_defaults (GTK_TABLE (table), label, 1, 2, 7, 8);
   gtk_widget_show(label);

   snprintf(temp, sizeof(temp), "%i", Passive_Host[i].hop);

   label = gtk_label_new (temp);
   gtk_label_set_selectable (GTK_LABEL (label), TRUE);
   gtk_misc_set_alignment(GTK_MISC (label), 0, 0);
   gtk_table_attach_defaults (GTK_TABLE (table), label, 1, 2, 8, 9);
   gtk_widget_show(label);

   if (!LIST_EMPTY(&Passive_Host[i].tcp_ports)) {
      box = gtk_vbox_new(TRUE, 0);

      LIST_FOREACH(current, &Passive_Host[i].tcp_ports, next) {
         if (strcmp(current->banner, "")) found = 1;
         snprintf(temp, sizeof(temp), "%-5d  %s", current->port, Decodedata_GetType('T', current->port, current->port));

         label = gtk_label_new (temp);
         gtk_label_set_selectable (GTK_LABEL (label), TRUE);
         gtk_misc_set_alignment(GTK_MISC (label), 0, 0);
         gtk_box_pack_start (GTK_BOX (box), label, TRUE, TRUE, 0);
         gtk_widget_show(label);
      }

      gtk_table_attach_defaults (GTK_TABLE (table), box, 1, 2, 9, 10);
      gtk_widget_show(box);
   } else {
      label = gtk_label_new ("NONE");
      gtk_label_set_selectable (GTK_LABEL (label), TRUE);
      gtk_misc_set_alignment(GTK_MISC (label), 0, 0);
      gtk_table_attach_defaults (GTK_TABLE (table), label, 1, 2, 9, 10);
      gtk_widget_show(label);
   }

   if (!LIST_EMPTY(&Passive_Host[i].udp_ports))
   {
      box = gtk_vbox_new(TRUE, 0);

      LIST_FOREACH(current, &Passive_Host[i].udp_ports, next)
      {
         snprintf(temp, sizeof(temp), "%-5d  %s", current->port, Decodedata_GetType('U', current->port, current->port) );
         label = gtk_label_new (temp);
         gtk_label_set_selectable (GTK_LABEL (label), TRUE);
         gtk_misc_set_alignment(GTK_MISC (label), 0, 0);
         gtk_box_pack_start (GTK_BOX (box), label, TRUE, TRUE, 0);
         gtk_widget_show(label);
      }

      gtk_table_attach_defaults (GTK_TABLE (table), box, 1, 2, 10, 11);
      gtk_widget_show(box);
   } else {
      label = gtk_label_new ("NONE");
      gtk_label_set_selectable (GTK_LABEL (label), TRUE);
      gtk_misc_set_alignment(GTK_MISC (label), 0, 0);
      gtk_table_attach_defaults (GTK_TABLE (table), label, 1, 2, 10, 11);
      gtk_widget_show(label);
   }

   if (found && !LIST_EMPTY(&Passive_Host[i].tcp_ports))
   {
      label = gtk_label_new ("TCP Services Banner: ");
      gtk_misc_set_alignment(GTK_MISC (label), 0, 0);
      gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 11, 12);
      gtk_widget_show(label);

      box = gtk_vbox_new(TRUE, 0);

      LIST_FOREACH(current, &Passive_Host[i].tcp_ports, next)
      {
         if (!strlen(current->banner)) continue;
         snprintf(temp, sizeof(temp), " %-5d  %s", current->port, current->banner );
         label = gtk_label_new (temp);
         gtk_label_set_selectable (GTK_LABEL (label), TRUE);
         gtk_misc_set_alignment(GTK_MISC (label), 0, 0);
         gtk_box_pack_start (GTK_BOX (box), label, TRUE, TRUE, 0);
         gtk_widget_show(label);
      }

      gtk_table_attach_defaults (GTK_TABLE (table), box, 1, 2, 11, 12);
      gtk_widget_show(box);
   }

   gtk_dialog_run (GTK_DIALOG (dialog));
   gtk_widget_destroy(dialog);
}



void Ginterface_Passive_Showname(void)
{
   if (gshowname)
   {
      gshowname = 0;
      Ginterface_Passive_UpdateList();
      return;
   }
   else
   {
      int i;

      Ginterface_PopUpN("resolving hostnames...");

      gshowname = 1;
      for(i=0; i<number_of_passive_hosts; i++)
      {
         if ( !strcmp(Passive_Host[i].name, "") ) {
            strlcpy(Passive_Host[i].name, Inet_HostName(Passive_Host[i].ip), sizeof(Passive_Host[i].name));

	         gtk_list_store_set (GTK_LIST_STORE (liststore), &listiter,
                        0, i+1,
                        1, (gshowname && strcmp(Passive_Host[i].name, "")) ? Passive_Host[i].name : Passive_Host[i].ip,
                        2, Passive_Host[i].type,
                        3, Passive_Host[i].os, -1);
         }
      }

      Ginterface_PopUpN(NULL);
   }
}


void Ginterface_Passive_Submit(GtkWidget *widget, gpointer data)
{
   GtkWidget *dialog, *label, *entry;
   FILE *f_os, *f_temp;
   char *fingerprint, *ip;
   socket_handle sock;
   int i;
   int j = (int)data;
   char OS[60];
   char getmsg[500];
   char data2[100], line[200];
   int  response;
   char host[] = "ettercap.sourceforge.net";
   char page[] = "/index.php?s=stuff&p=fingerprint";

   DEBUG_MSG("Ginterface_Passive_Submit -- [%s]", Passive_Host[j].fingerprint);

   fingerprint = strdup(Passive_Host[j].fingerprint);
   ip = strdup(Passive_Host[j].ip);

   dialog = gtk_dialog_new_with_buttons("Fingerprint submitter", GTK_WINDOW (window), GTK_DIALOG_DESTROY_WITH_PARENT,
                           "Submit", GTK_RESPONSE_OK, "Cancel", GTK_RESPONSE_CANCEL, NULL);

   label = gtk_label_new ("You are submitting a new fingerprint...");
   gtk_box_pack_start_defaults (GTK_BOX (GTK_DIALOG(dialog)->vbox), label);
   gtk_widget_show(label);

   snprintf(line, 200, "Please enter the Operating System of %s\nIts fingerprint is : %s", ip, fingerprint);   
   label = gtk_label_new (line);
   gtk_box_pack_start_defaults (GTK_BOX (GTK_DIALOG(dialog)->vbox), label);
   gtk_widget_show(label);

   entry = gtk_entry_new ();
   gtk_entry_set_max_length (GTK_ENTRY (entry), 60);
   gtk_entry_set_width_chars (GTK_ENTRY (entry), 60);
   gtk_box_pack_start_defaults (GTK_BOX (GTK_DIALOG(dialog)->vbox), entry);
   gtk_widget_show(entry);

   response = gtk_dialog_run(GTK_DIALOG (dialog));

   fprintf(stderr, "DEBUG: response = %i\n", response);

   if(response != -5) {
      gtk_widget_destroy (dialog);
      return;
   }

   memset(OS, 0, sizeof(OS));
   
   strcpy(OS, gtk_entry_get_text (GTK_ENTRY (entry)));

   if ( !strcmp(OS, "") || !strcmp(fingerprint, "") )
      return;

   DEBUG_MSG("Ginterface_Passive_Submit - remote - %s %s", fingerprint, OS);

   for (i=0; i<60; i++)
      if (OS[i] == ' ') OS[i] = '+';

   snprintf(data2, sizeof(data2), "&finger=%s&os=%s", fingerprint, OS);

   gtk_widget_destroy (dialog);

   dialog = gtk_dialog_new_with_buttons("Fingerprint submitter", GTK_WINDOW (window), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_CLOSE, GTK_RESPONSE_NONE, NULL);
   g_signal_connect_swapped (GTK_OBJECT (dialog), "response", G_CALLBACK (gtk_widget_destroy), GTK_OBJECT (dialog));
   gtk_widget_show(dialog);   /* show it right away so messages pop up live */
   
   while (g_main_iteration(FALSE)); /* update gui */

   snprintf(line, 200, "Connecting to http://%s...", host);
   label = gtk_label_new (line);
   gtk_box_pack_start_defaults (GTK_BOX (GTK_DIALOG(dialog)->vbox), label);
   gtk_widget_show(label);

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

   sock = Inet_OpenSocket(host, 80);

   snprintf(line, 200, "Submitting the fingerprint to %s...", page);
   label = gtk_label_new (line);
   gtk_box_pack_start_defaults (GTK_BOX (GTK_DIALOG(dialog)->vbox), label);
   gtk_widget_show(label);

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

   snprintf(getmsg, sizeof(getmsg), "GET %s%s HTTP/1.0\r\n"
                                    "Host: %s\r\n"
                                    "User-Agent: %s (%s).\r\n"
                                    "\r\n", page, data2, host, PROGRAM, VERSION );

   DEBUG_MSG("Ginterface_Passive_Submit -- %s", getmsg);

   Inet_Http_Send(sock, getmsg);
   Inet_CloseSocket(sock);

   snprintf(line, 200, "New fingerprint submitted to the ettercap website...");
   label = gtk_label_new (line);
   gtk_box_pack_start_defaults (GTK_BOX (GTK_DIALOG(dialog)->vbox), label);
   gtk_widget_show(label);

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

   for (i=0; i<60; i++)
      if (OS[i] == '+') OS[i] = ' ';

   strlcpy(Passive_Host[j].os, OS, 60);

   DEBUG_MSG("Ginterface_Passive_Submit - local - [%s] [%s] [%s]", fingerprint, OS, Passive_Host[j].os);

   f_os = fopen( "./" OS_FILE, "r");
   if (f_os == NULL)
   {
      f_os = fopen( DATA_PATH "/" OS_FILE, "r");
      if (f_os == NULL)
         Error_msg("\nCan't find " OS_FILE " in ./ or " DATA_PATH);
   }

   f_temp = tmpfile();
   fchmod(fileno(f_temp), 0700);

   while(fgets (data2, 99, f_os))
   {

      if ( strchr(data2, '#') || !strlen(data2))
      {
         fprintf(f_temp, "%s", data2);
         continue;
      }

      if (strcmp(data2, fingerprint) < 0)
         fprintf(f_temp, "%s", data2);
      else
      {
         if (strlen(OS)) fprintf(f_temp, "%s:%.60s\n", fingerprint, OS);
         memset(OS, 0, sizeof(OS));
         fprintf(f_temp, "%s", data2);
      }
   }
   rewind(f_temp);
   fclose(f_os);

   f_os = fopen( "./" OS_FILE, "w");
   if (f_os == NULL)
      f_os = fopen( DATA_PATH "/" OS_FILE, "w");

   while(fgets (data2, 100, f_temp))
   {
      fprintf(f_os, "%s", data2);
   }

   fclose(f_temp);
   fclose(f_os);

   snprintf(line, 200, "New fingerprint added to the local database...\nYou may close this window.");
   label = gtk_label_new (line);
   gtk_box_pack_start_defaults (GTK_BOX (GTK_DIALOG(dialog)->vbox), label);
   gtk_widget_show(label);

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

   /* user can close dialog */

   free(fingerprint);
   free(ip);
}

void Ginterface_Passive_Run(void)
{
   char line[150];

   DEBUG_MSG("Ginterface_Passive_Run");

   Ginterface_EditTop(0, "Source:");
   Ginterface_EditTop(1, "ANY");
   Ginterface_EditTop(6, "Dest:");
   Ginterface_EditTop(7, "ANY");
   if (!Options.writedump && Options.dumpfile) {
      snprintf(line, 150, "dryad (OffLine from [%s]) ", Options.dumpfile);
      Ginterface_EditTop(5, line);
   } else {
      Ginterface_EditTop(5, "dryad (passive scanning) - ");
      Ginterface_AppendTop(5, PROGRAM);
   }

   number_of_passive_hosts = 0;
   list_bottom = 0;

   /* 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 (mainbox[4]), scrolled);
   gtk_widget_show (scrolled);

   treeview = gtk_tree_view_new ();
   gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (treeview), FALSE);
      /* add the column */
   renderer = gtk_cell_renderer_text_new ();
   column = gtk_tree_view_column_new_with_attributes ("#", renderer, "text", 0, NULL);
   gtk_tree_view_column_set_sort_column_id (column, 0);
   gtk_tree_view_column_set_resizable (column, FALSE);
   gtk_tree_view_append_column (GTK_TREE_VIEW(treeview), column);
      /* add the column */
   renderer = gtk_cell_renderer_text_new ();
   column = gtk_tree_view_column_new_with_attributes ("Host", renderer, "text", 1, NULL);
   gtk_tree_view_column_set_sort_column_id (column, 1);
   gtk_tree_view_column_set_resizable (column, TRUE);
   gtk_tree_view_append_column (GTK_TREE_VIEW(treeview), column);
      /* add the column */
   renderer = gtk_cell_renderer_text_new ();
   column = gtk_tree_view_column_new_with_attributes ("Type", renderer, "text", 2, NULL);
   gtk_tree_view_column_set_sort_column_id (column, 2);
   gtk_tree_view_column_set_resizable (column, TRUE);
   gtk_tree_view_append_column (GTK_TREE_VIEW(treeview), column);
      /* add the column */
   renderer = gtk_cell_renderer_text_new ();
   column = gtk_tree_view_column_new_with_attributes ("Operating System", renderer, "text", 3, NULL);
   gtk_tree_view_column_set_sort_column_id (column, 3);
   gtk_tree_view_column_set_resizable (column, TRUE);
   gtk_tree_view_append_column (GTK_TREE_VIEW(treeview), column);
      /* connect signals */
   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
   gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
   g_signal_connect (G_OBJECT (selection), "changed", G_CALLBACK (Ginterface_Passive_PointItem), NULL);
   g_signal_connect (G_OBJECT (treeview), "row_activated", G_CALLBACK (Ginterface_Passive_SelectItem), NULL);
      /* add it and display it */
   gtk_container_add(GTK_CONTAINER (scrolled), treeview);
   gtk_widget_show(treeview);

   Dryad_pid = Dryad_Run();

   /* initialize the list */
   Ginterface_Passive_UpdateList();

   id_watch = g_timeout_add(300, Ginterface_Passive_WatchList, NULL);
}

gboolean Ginterface_Passive_WatchList(gpointer data)
{
   if(number_of_passive_hosts < 0)
      return FALSE;

   if (pass_list_modified) {
      Ginterface_Passive_UpdateList();
      pass_list_modified = 0;
   }

   return TRUE;
}

void Ginterface_Passive_Stop() 
{
   g_source_remove(id_watch);
   gtk_container_remove(GTK_CONTAINER (mainbox[4]), scrolled);
   if(liststore)
      g_free(liststore);
   liststore = NULL;
   gdk_flush();
   ECThread_destroy(Dryad_pid);
   Decodedata_FreePassiveList();
   number_of_passive_hosts = -1;
   gHost_Pointer = 0;
   gshowname = 0;
   Options.passive = 0;
   read_from_dump_flag = 0;  /* permit a new scan of the offline file */
   DEBUG_MSG("Ginterface_Passive_END");
}

void Ginterface_Passive_ToolBar(GtkItemFactory *host_menu) {
   static GtkItemFactoryEntry action_menu[] = {
      MENU_COMMON
      { "/Action", "h", NULL, 0, "<Branch>", NULL},
      { "/Action/Show Name or IP", "d", Ginterface_Passive_Callback, 'd', "<ToggleItem>", GTK_STOCK_CONVERT },
      { "/Action/Log to a file (Local IP)", "l", Ginterface_Passive_Callback, 'l', "<StockItem>", GTK_STOCK_SAVE },
      { "/Action/Log to a file (All)", "<control>l", Ginterface_Passive_Callback, 'L', "<StockItem>", GTK_STOCK_SAVE_AS},
      { "/Action/Convert to startup hostlist", "c", Ginterface_Passive_Callback, 'c', "<StockItem>", GTK_STOCK_NEW},
      { "/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, "/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_Passive_Callback(gpointer data, guint action, GtkWidget *widget) {
   switch (action) {
      case '!':
         if (Passive_Host[gHost_Pointer].ip == NULL) break;   // no host
         Ginterface_Passive_ShowDetails(gHost_Pointer);
         break;
      case 'S':
      case 's':
         Decodedata_Passive_SortList();
         Ginterface_Passive_UpdateList();
         break;
      case 'L':
      case 'l':
         Ginterface_Passive_MakeReport(action);
         break;
      case 'D':
      case 'd':
         Ginterface_Passive_Showname();
         Ginterface_Passive_UpdateList();
         break;
      case 'H':
      case 'h':{
            static char *help[] = {
               "[qQ][F10] - quit",
               "[return]  - show details for the selected host",
               "[dD]      - toggle show name or IP",
               "[l ]      - log collected info to a file (only local IP)",
               "[L ]      - log all collected info to a file",
               "[sS]      - sort the list",
               "[cC]      - convert the list into the startup host list",
               NULL};
            Ginterface_HelpWindow(help);
         }
         break;
      case 'C':
      case 'c':
         if (number_of_connections >= 0)
         {
            Ginterface_PopUp("Cannot convert form connection list interface");
            break;
         }
         Decodedata_Passive_SortList();
         Decodedata_ConvertPassiveToHost();
         gtk_notebook_set_current_page(GTK_NOTEBOOK (notebook), 0);
         break;
      case 'q':
      case 'Q':
         DEBUG_MSG("Ginterface_Run_END");
         {
            char answer;
            answer = Ginterface_PopUpQ("Do you really want to exit?");
            if ((answer == 'y') || (answer == 'Y')) {
               gtk_widget_hide(window);
               Ginterface_Passive_Stop();
               Ginterface_WExit("They are safe!!  for now... ");
            }
         }
         break;
   }
}


/* EOF */

// vim:ts=3:expandtab


