/*
    ettercap -- gtk interface for data injector and filtering form

    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>

#ifdef HAVE_CTYPE_H
   #include <ctype.h>
#endif


#include <ec_gtk.h>
#include <ec_gtk_sniff_data.h>
#include <ec_decodedata.h>
#include <ec_filterdrop.h>
#include <ec_parser.h>

/* if FORM is defined, ec_interface_form provides trim_buffer */
/* otherwise, a copy of trim_buffer will be provided by ec_gtk */
#ifdef HAVE_FORM
extern void trim_buffer(char *buffer, char trim);
#endif

// protos...
void Ginterface_Inject_FilterTopStatus(void);
void Ginterface_Inject_FilterStatus(void);
int Ginterface_Inject_Run(u_char *inject_data, char proto, char *app);
int Ginterface_Inject_Filter(DROP_FILTER *filters);
void Ginterface_Inject_SetFilter(short mode);
void Ginterface_Inject_FilterStatus();
void Ginterface_Inject_EditFilters(DROP_FILTER *FA_ptr);
void Ginterface_Inject_EditFilters_InitList(DROP_FILTER *FA_ptr);
void Ginterface_Inject_EditFilters_PointItem(GtkWidget *widget, gpointer data);
void Ginterface_Inject_SelectItem(GtkTreeView *treeview, gpointer arg1, GtkTreeViewColumn *arg2, gpointer data);

void Toggle_Source_Filters(GtkWidget *button, gpointer *data);
void Toggle_Dest_Filters(GtkWidget *button, gpointer *data);
void Edit_Source_Filters(GtkWidget *button, gpointer *data);
void Edit_Dest_Filters(GtkWidget *button, gpointer *data);

void Ginterface_Inject_Callback(GtkWidget *widget, gpointer data);
void Ginterface_Inject_ChainWindow (DROP_FILTER *FA_ptr);
void Ginterface_Inject_CloseChainWindow (GtkWidget *widget, gpointer data);

// global variables
GtkWidget *filter_window, *filter_label[2], *itable, *c_treeview;
GtkListStore *filterlist = NULL;
GtkTreeSelection *c_select;
GtkTreeIter c_listiter;
extern GtkWidget *window;

DROP_FILTER *gFA_ptr;

int gFil_Number;
int gFil_Base_Pointer = 0;
int gFil_Pointer = 0;
short inject_mode;   /* global mode for file */

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


int Ginterface_Inject_Run(u_char *inject_data, char proto, char *app)
{
   GtkWidget *dialog, *textview;
   GtkTextBuffer *textbuf = NULL;
   char inject_sequence[MAX_INJECT];
   int len = 0;
   char response, temp[100];

   DEBUG_MSG("Ginterface_Inject_Run -- %c %s", proto, app);

   sprintf(temp, "Type characters to be injected (max %d):", MAX_INJECT);
   dialog = gtk_dialog_new_with_buttons (temp, GTK_WINDOW (window), GTK_DIALOG_DESTROY_WITH_PARENT, 
            "Send", GTK_RESPONSE_YES, "Cancel", GTK_RESPONSE_NO, NULL);
   textview = gtk_text_view_new();
   textbuf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (textview));
   gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), textview, TRUE, TRUE, 0);
   gtk_widget_show(textview);

   response = gtk_dialog_run(GTK_DIALOG (dialog));

   if(response == -8) {
      GtkTextIter start, end;
      gtk_text_buffer_get_bounds(textbuf, &start, &end);

      strcpy(inject_sequence, gtk_text_buffer_get_text(textbuf, &start, &end, FALSE));
      DEBUG_MSG("Ginterface_Inject_Run -- inject_sequence len -- [%d]", strlen(inject_sequence));

      len = FilterDrop_strescape(inject_data, inject_sequence);
      DEBUG_MSG("Ginterface_Inject_Run -- inject_data len -- [%d]", len);
   }

   return len;
}


void Ginterface_Inject_FilterTopStatus(void)
{
   Ginterface_EditTop(2, "Filter: ");

   if (filter_on_source || filter_on_dest)
   {
      Ginterface_AppendTop(2, "ON ");
   }
   else
   {
      Ginterface_AppendTop(2, "OFF");
   }
}

void Ginterface_Inject_FilterStatus(void)
{

   DEBUG_MSG("Ginterface_Inject_FilterStatus -- source %d : dest %d", filter_on_source, filter_on_dest);

   switch(filter_on_source)
   {
      case 1:  gtk_label_set_text(GTK_LABEL(filter_label[0]), "ON ");
               break;

      case 0:  gtk_label_set_text(GTK_LABEL(filter_label[0]), "OFF");
               break;
   }
   switch(filter_on_dest)
   {
      case 1:  gtk_label_set_text(GTK_LABEL(filter_label[1]), "ON ");
               break;

      case 0:  gtk_label_set_text(GTK_LABEL(filter_label[1]), "OFF");
               break;
   }
   Ginterface_Inject_FilterTopStatus();
}



void Ginterface_Inject_SetFilter(short mode)
{
   GtkWidget *button;

   DEBUG_MSG("Ginterface_Inject_SetFilter");

   inject_mode = mode;

   // gFil_Number = dimY;

   filter_window = gtk_dialog_new_with_buttons ("Filters :", GTK_WINDOW (window), GTK_DIALOG_DESTROY_WITH_PARENT, "Close", GTK_RESPONSE_CLOSE, NULL);
   g_signal_connect_swapped (GTK_OBJECT (filter_window), "response", G_CALLBACK (gtk_widget_destroy), GTK_OBJECT (filter_window));
   itable = gtk_table_new(2, 3, FALSE);
   gtk_box_pack_start (GTK_BOX(GTK_DIALOG(filter_window)->vbox), itable, TRUE, TRUE, 0);
   gtk_widget_show (itable);

   button = gtk_button_new_with_mnemonic ("_S] Filters on Source : ");
   g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (Toggle_Source_Filters), &mode);
   gtk_table_attach ( GTK_TABLE (itable), button, 0, 1, 0, 1, 0, 0, 5, 5);
   gtk_widget_show (button);

   button = gtk_button_new_with_mnemonic ("_D] Filters on Dest   : ");
   g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (Toggle_Dest_Filters), &mode);
   gtk_table_attach ( GTK_TABLE (itable), button, 0, 1, 1, 2, 0, 0, 5, 5);
   gtk_widget_show (button);

   filter_label[0] = gtk_label_new("   ");
   gtk_table_attach ( GTK_TABLE (itable), filter_label[0], 1, 2, 0, 1, 0, 0, 5, 5);
   gtk_widget_show(filter_label[0]);

   filter_label[1] = gtk_label_new("   ");
   gtk_table_attach ( GTK_TABLE (itable), filter_label[1], 1, 2, 1, 2, 0, 0, 5, 5);
   gtk_widget_show(filter_label[1]);

   Ginterface_Inject_FilterStatus();

   button = gtk_button_new_with_mnemonic ("_W] Edit filter chain");
   g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (Edit_Source_Filters), &mode);
   gtk_table_attach ( GTK_TABLE (itable), button, 2, 3, 0, 1, 0, 0, 5, 5);
   gtk_widget_show (button);

   button = gtk_button_new_with_mnemonic ("_E] Edit filter chain");
   g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (Edit_Dest_Filters), &mode);
   gtk_table_attach ( GTK_TABLE (itable), button, 2, 3, 1, 2, 0, 0, 5, 5);
   gtk_widget_show (button);

   Parser_LoadFilters(""); // what does this do?

   gtk_widget_show (filter_window);
}

void Toggle_Source_Filters(GtkWidget *button, gpointer *data) {
   if (!filter_on_source && !Filter_Array_Source)
   {
      Ginterface_PopUp("The Source chain is empty !!");
   }
   else if (FilterDrop_CheckMode(Filter_Array_Source, inject_mode))
   {
      Ginterface_PopUp("The chain contains filter(s) that can be used only in ARPBASED mode !!");
   }
   else
   {
      if (!filter_on_source)
         switch(FilterDrop_Validation(Filter_Array_Source))
         {
            case 1:
               Ginterface_PopUp("CAUTION: the filter chain contains a loop...\nettercap may hang up. please review your filter chain...");
               break;
            case 2:
               Ginterface_PopUp("CAUTION: filter with a jump outside the chain !!!\nettercap will sig fault. review your filter chain immediately !");
               return;
               break;
         }
      filter_on_source = (filter_on_source) ? 0 : 1;
   }

   Ginterface_Inject_FilterStatus();
}

void Toggle_Dest_Filters(GtkWidget *button, gpointer *data) {

   if (!filter_on_dest && !Filter_Array_Dest)
   {
      Ginterface_PopUp("The Dest chain is empty !!");
   }
   else if (FilterDrop_CheckMode(Filter_Array_Dest, inject_mode))
   {
      Ginterface_PopUp("The chain contains filter(s) that can be used only in ARPBASED mode !!");
   }
   else
   {
      if (!filter_on_dest)
         switch(FilterDrop_Validation(Filter_Array_Dest))
         {
            case 1:
               Ginterface_PopUp("CAUTION: the filter chain contains a loop...\nettercap may hang up. please review your filter chain...");
               break;
            case 2:
               Ginterface_PopUp("CAUTION: filter with a jump outside the chain !!!\nettercap will sig fault. review your filter chain immediately !");
               return;
               break;
         }
      filter_on_dest = (filter_on_dest) ? 0 : 1;
   }

   Ginterface_Inject_FilterStatus();
}

void Edit_Source_Filters(GtkWidget *button, gpointer *data) {
   filter_on_source = 0;
   Ginterface_Inject_EditFilters(Filter_Array_Source);
      switch(FilterDrop_Validation(Filter_Array_Source))
      {
         case 1:
            Ginterface_PopUp("CAUTION: the source filter chain contains a loop...\nettercap may hang up. please review your filter chain...");
            break;
         case 2:
            Ginterface_PopUp("CAUTION: filter with a jump outside the chain !!!\nettercap will sig fault. review your filter chain immediately !");
            return;
            break;
      }
   Ginterface_Inject_FilterStatus();
}

void Edit_Dest_Filters(GtkWidget *button, gpointer *data) {
   filter_on_dest = 0;
   Ginterface_Inject_EditFilters(Filter_Array_Dest);
      switch(FilterDrop_Validation(Filter_Array_Dest))
      {
         case 1:
            Ginterface_PopUp("CAUTION: the dest filter chain contains a loop...\nettercap may hang up. please review your filter chain...");
            break;
         case 2:
            Ginterface_PopUp("CAUTION: filter with a jump outside the chain !!!\nettercap will sig fault. review your filter chain immediately !");
            return;
            break;
      }
   Ginterface_Inject_FilterStatus();
}

int Ginterface_Inject_Filter(DROP_FILTER *filters)
{
   GtkWidget *popup, *entry[6], *label, *itable, *textview[2], *scrolled;
   GtkTextBuffer *textbuf[2];
   // 0 Proto, 1 Source Port, 2 Dest Port, 3 action, 4 match, 5 no match
   int finished = 0;
   int status = 0;
   char tmp[10];

   DEBUG_MSG("Ginterface_Inject_Filter");

   popup = gtk_dialog_new_with_buttons ("Edit Filter", GTK_WINDOW (window), GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
                                 "Set Filter", GTK_RESPONSE_YES, "Cancel", GTK_RESPONSE_NO, NULL);
   gtk_window_set_position (GTK_WINDOW (popup), GTK_WIN_POS_CENTER);

   itable = gtk_table_new (6, 8, FALSE);
   gtk_container_add (GTK_CONTAINER (GTK_DIALOG(popup)->vbox), itable);
   gtk_widget_show(itable);

   label = gtk_label_new_with_mnemonic ("_Proto: ");
   gtk_table_attach (GTK_TABLE (itable), label, 0, 1, 0, 1, GTK_FILL | GTK_EXPAND, 0, 0, 0);
   gtk_widget_show(label);

   entry[0] = gtk_entry_new ();
   gtk_entry_set_width_chars(GTK_ENTRY (entry[0]), 3);
   gtk_table_attach (GTK_TABLE (itable), entry[0], 1, 2, 0, 1, GTK_FILL | GTK_EXPAND, 0, 0, 0);
   gtk_label_set_mnemonic_widget(GTK_LABEL (label), GTK_WIDGET (entry[0]));
   gtk_widget_show(entry[0]);

   label = gtk_label_new_with_mnemonic ("_Source port :");
   gtk_table_attach (GTK_TABLE (itable), label, 2, 3, 0, 1, GTK_FILL | GTK_EXPAND, 0, 0, 0);
   gtk_widget_show(label);

   entry[1] = gtk_entry_new ();
   gtk_entry_set_width_chars(GTK_ENTRY (entry[1]), 5);
   gtk_table_attach (GTK_TABLE (itable), entry[1], 3, 4, 0, 1, GTK_FILL | GTK_EXPAND, 0, 0, 0);
   gtk_label_set_mnemonic_widget(GTK_LABEL (label), GTK_WIDGET (entry[1]));
   gtk_widget_show(entry[1]);

   label = gtk_label_new_with_mnemonic ("_Dest port :");
   gtk_table_attach (GTK_TABLE (itable), label, 4, 5, 0, 1, GTK_FILL | GTK_EXPAND, 0, 0, 0);
   gtk_widget_show(label);

   entry[2] = gtk_entry_new ();
   gtk_entry_set_width_chars(GTK_ENTRY (entry[2]), 5);
   gtk_table_attach (GTK_TABLE (itable), entry[2], 5, 6, 0, 1, GTK_FILL | GTK_EXPAND, 0, 0, 0);
   gtk_label_set_mnemonic_widget(GTK_LABEL (label), GTK_WIDGET (entry[2]));
   gtk_widget_show(entry[2]);

   label = gtk_label_new_with_mnemonic ("Searc_h :");
   gtk_table_attach (GTK_TABLE (itable), label, 0, 6, 1, 2, GTK_FILL | GTK_EXPAND, 0, 0, 0);
   gtk_widget_show(label);

   scrolled = gtk_scrolled_window_new(NULL, NULL);
   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
   gtk_table_attach (GTK_TABLE (itable), scrolled, 0, 6, 2, 3, GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 0, 0);
   gtk_widget_show (scrolled);

   textview[0] = gtk_text_view_new ();
   textbuf[0] = gtk_text_view_get_buffer (GTK_TEXT_VIEW (textview[0]));
   gtk_container_add(GTK_CONTAINER (scrolled), textview[0]);
   gtk_label_set_mnemonic_widget(GTK_LABEL (label), GTK_WIDGET (textview[0]));
   gtk_widget_show(textview[0]);
   
   label = gtk_label_new_with_mnemonic ("_Action (Drop/Replace/Log) :");
   gtk_table_attach (GTK_TABLE (itable), label, 0, 3, 3, 4, GTK_FILL | GTK_EXPAND, 0, 0, 0);
   gtk_widget_show(label);

   entry[3] = gtk_entry_new ();
   gtk_entry_set_width_chars(GTK_ENTRY (entry[3]), 7);
   gtk_table_attach (GTK_TABLE (itable), entry[3], 3, 6, 3, 4, GTK_FILL | GTK_EXPAND, 0, 0, 0);
   gtk_widget_show(entry[3]);

   label = gtk_label_new_with_mnemonic ("_Replace :");
   gtk_table_attach (GTK_TABLE (itable), label, 0, 6, 4, 5, GTK_FILL | GTK_EXPAND, 0, 0, 0);
   gtk_widget_show(label);

   scrolled = gtk_scrolled_window_new(NULL, NULL);
   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
   gtk_table_attach (GTK_TABLE (itable), scrolled, 0, 6, 5, 6, GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 0, 0);
   gtk_widget_show (scrolled);

   textview[1] = gtk_text_view_new ();
   textbuf[1] = gtk_text_view_get_buffer (GTK_TEXT_VIEW (textview[1]));
   gtk_container_add(GTK_CONTAINER (scrolled), textview[1]);
   gtk_label_set_mnemonic_widget(GTK_LABEL (label), GTK_WIDGET (textview[1]));
   gtk_widget_show(textview[1]);

   label = gtk_label_new_with_mnemonic ("Goto if _match         :");
   gtk_table_attach (GTK_TABLE (itable), label, 0, 3, 6, 7, GTK_FILL | GTK_EXPAND, 0, 0, 0);
   gtk_widget_show(label);

   entry[4] = gtk_entry_new ();
   gtk_entry_set_width_chars(GTK_ENTRY (entry[4]), 3);
   gtk_table_attach (GTK_TABLE (itable), entry[4], 3, 6, 6, 7, GTK_FILL | GTK_EXPAND, 0, 0, 0);
   gtk_label_set_mnemonic_widget(GTK_LABEL (label), GTK_WIDGET (entry[4]));
   gtk_widget_show(entry[4]);

   label = gtk_label_new_with_mnemonic ("Goto if does_n't match :");  
   gtk_table_attach (GTK_TABLE (itable), label, 0, 3, 7, 8, GTK_FILL | GTK_EXPAND, 0, 0, 0);
   gtk_widget_show(label);

   entry[5] = gtk_entry_new ();
   gtk_entry_set_width_chars(GTK_ENTRY (entry[5]), 3);
   gtk_table_attach (GTK_TABLE (itable), entry[5], 3, 6, 7, 8, GTK_FILL | GTK_EXPAND, 0, 0, 0);
   gtk_label_set_mnemonic_widget(GTK_LABEL (label), GTK_WIDGET (entry[5]));
   gtk_widget_show(entry[5]);

   if (filters[gFil_Pointer].proto == 'T')
      snprintf(tmp, sizeof(tmp), "TCP");
   else if (filters[gFil_Pointer].proto == 'U')
      snprintf(tmp, sizeof(tmp), "UDP");
   else 
      snprintf(tmp, sizeof(tmp), "   ");
   gtk_entry_set_text(GTK_ENTRY (entry[0]), tmp);

   snprintf(tmp, sizeof(tmp), "%d",  filters[gFil_Pointer].source);
   gtk_entry_set_text(GTK_ENTRY (entry[1]), tmp);
   snprintf(tmp, sizeof(tmp), "%d",  filters[gFil_Pointer].dest);
   gtk_entry_set_text(GTK_ENTRY (entry[2]), tmp);
   gtk_text_buffer_insert_at_cursor(GTK_TEXT_BUFFER (textbuf[0]), filters[gFil_Pointer].display_search, -1);
   snprintf(tmp, sizeof(tmp), "%c",  filters[gFil_Pointer].type);
   gtk_entry_set_text(GTK_ENTRY (entry[3]), tmp);
   gtk_text_buffer_insert_at_cursor(GTK_TEXT_BUFFER (textbuf[1]), filters[gFil_Pointer].display_replace, -1);

   snprintf(tmp, sizeof(tmp), "%d",  filters[gFil_Pointer].go_to);
   if (!strcmp(tmp, "-1"))
      gtk_entry_set_text(GTK_ENTRY (entry[4]), "   ");
   else
      gtk_entry_set_text(GTK_ENTRY (entry[4]), tmp);

   snprintf(tmp, sizeof(tmp), "%d",  filters[gFil_Pointer].else_go_to);
   if (!strcmp(tmp, "-1"))
      gtk_entry_set_text(GTK_ENTRY (entry[5]), "   ");
   else
      gtk_entry_set_text(GTK_ENTRY (entry[5]), tmp);

   finished = gtk_dialog_run(GTK_DIALOG (popup));

   if (finished == -8) {
      GtkTextIter start[2], end[2];
      char tmp_search[MAX_FILTER+1];

      gtk_text_buffer_get_bounds(textbuf[0], &start[0], &end[0]);
      gtk_text_buffer_get_bounds(textbuf[1], &start[1], &end[1]);

      pthread_mutex_lock(&filter_mutex);

      memset(&filters[gFil_Pointer], 0, sizeof(DROP_FILTER));

      memcpy(&filters[gFil_Pointer].proto, gtk_entry_get_text(GTK_ENTRY (entry[0])), 1);
      filters[gFil_Pointer].proto = toupper(filters[gFil_Pointer].proto);

      filters[gFil_Pointer].source = atoi(gtk_entry_get_text(GTK_ENTRY (entry[1])));
      filters[gFil_Pointer].dest = atoi(gtk_entry_get_text(GTK_ENTRY (entry[2])));

      memcpy(&filters[gFil_Pointer].display_search, gtk_text_buffer_get_text(textbuf[0], &start[0], &end[0], FALSE), MAX_FILTER);
      trim_buffer(filters[gFil_Pointer].display_search, ' ');
      filters[gFil_Pointer].wildcard = FilterDrop_ParseWildcard(tmp_search, filters->display_search, sizeof(tmp_search));
      filters[gFil_Pointer].slen = FilterDrop_strescape(filters[gFil_Pointer].search, tmp_search);

      memcpy(&filters[gFil_Pointer].display_replace, gtk_text_buffer_get_text(textbuf[1], &start[1], &end[1], FALSE), MAX_FILTER);
      trim_buffer(filters[gFil_Pointer].display_replace, ' ');
      filters[gFil_Pointer].rlen = FilterDrop_strescape(filters[gFil_Pointer].replace, filters[gFil_Pointer].display_replace);

      memcpy(&filters[gFil_Pointer].type, gtk_entry_get_text(GTK_ENTRY (entry[3])), 1);
      filters[gFil_Pointer].type = toupper(filters[gFil_Pointer].type);

      if (!strcmp(gtk_entry_get_text(GTK_ENTRY (entry[4])), "   "))
         filters[gFil_Pointer].go_to = -1;
      else
         filters[gFil_Pointer].go_to = atoi(gtk_entry_get_text(GTK_ENTRY (entry[4])));

      if (!strcmp(gtk_entry_get_text(GTK_ENTRY (entry[5])), "   "))
         filters[gFil_Pointer].else_go_to = -1;
      else
         filters[gFil_Pointer].else_go_to = atoi(gtk_entry_get_text(GTK_ENTRY (entry[5])));

      pthread_mutex_unlock(&filter_mutex);

      status = 1;
   }

   gtk_widget_destroy (popup);

   return status;
}

void Ginterface_Inject_EditFilters_InitList(DROP_FILTER *FA_ptr)
{
   int j;
   int num_filter;

   if (FA_ptr == Filter_Array_Source)
      num_filter = Filter_Source;
   else
      num_filter = Filter_Dest;

   if (gFil_Pointer >= num_filter) gFil_Pointer = num_filter-1;

   if(filterlist)
      gtk_list_store_clear(filterlist);
   else {
      filterlist = gtk_list_store_new (1, G_TYPE_STRING);
      gtk_tree_view_set_model (GTK_TREE_VIEW (c_treeview), GTK_TREE_MODEL (filterlist));
   }

   if (num_filter == 0)
   {
      gtk_list_store_append (filterlist, &c_listiter);
      gtk_list_store_set (filterlist, &c_listiter, 0, "NO FILTER IN THIS CHAIN", -1);
   } else {
      for(j=gFil_Base_Pointer; j<num_filter; j++)
      {
         gtk_list_store_append (filterlist, &c_listiter);
         gtk_list_store_set (filterlist, &c_listiter, 0, Parser_PrintFilter(FA_ptr, j), -1);
      }
   }
}

void Ginterface_Inject_ChainWindow (DROP_FILTER *FA_ptr)
{
   GtkWidget *chain_dialog;
   GtkCellRenderer *renderer;
   GtkTreeViewColumn *column;
   GtkWidget *box, *button, *scrolled = NULL;

   chain_dialog = gtk_dialog_new_with_buttons ("Filters :", GTK_WINDOW (window), GTK_DIALOG_DESTROY_WITH_PARENT, "Close", GTK_RESPONSE_CLOSE, NULL);
   gtk_window_set_default_size(GTK_WINDOW (chain_dialog), 300, 200);
   g_signal_connect (GTK_OBJECT (chain_dialog), "response", G_CALLBACK (Ginterface_Inject_CloseChainWindow), NULL);

   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(GTK_DIALOG(chain_dialog)->vbox),  scrolled, TRUE, TRUE, 0);
   gtk_widget_show (scrolled);

   c_treeview = gtk_tree_view_new ();
   gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (c_treeview), FALSE);
   /* add the column */
   renderer = gtk_cell_renderer_text_new ();
   column = gtk_tree_view_column_new_with_attributes ("Chains", renderer, "text", 0, NULL);
   gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(c_treeview), FALSE);
   gtk_tree_view_column_set_sort_column_id (column, 0);
   gtk_tree_view_append_column (GTK_TREE_VIEW (c_treeview), column);
   /* connect signals */
   c_select = gtk_tree_view_get_selection (GTK_TREE_VIEW (c_treeview));
   gtk_tree_selection_set_mode (c_select, GTK_SELECTION_SINGLE);
   g_signal_connect (G_OBJECT (c_select), "changed", G_CALLBACK (Ginterface_Inject_EditFilters_PointItem), NULL);
   g_signal_connect (G_OBJECT (c_treeview), "row_activated", G_CALLBACK (Ginterface_Inject_SelectItem), "!");
   /* add it and display it */
   gtk_container_add(GTK_CONTAINER (scrolled), c_treeview);
   gtk_widget_show(c_treeview);

   box = gtk_hbox_new(TRUE, 5);

   button = gtk_button_new_with_mnemonic ("_Add");
   gtk_box_pack_start (GTK_BOX(box), button, FALSE, TRUE, 0);
   g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (Ginterface_Inject_Callback), "a");
   gtk_widget_show (button);

   button = gtk_button_new_with_mnemonic ("_Delete");
   gtk_box_pack_start (GTK_BOX(box), button, FALSE, TRUE, 0);
   g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (Ginterface_Inject_Callback), "d");
   gtk_widget_show (button);

   button = gtk_button_new_with_mnemonic ("_Save");
   gtk_box_pack_start (GTK_BOX(box), button, FALSE, TRUE, 0);
   g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (Ginterface_Inject_Callback), "s");
   gtk_widget_show (button);

   gtk_box_pack_start (GTK_BOX(GTK_DIALOG(chain_dialog)->vbox), box, FALSE, TRUE, 0);
   gtk_widget_show(box);

   Ginterface_Inject_EditFilters_InitList(FA_ptr);

   gtk_widget_show(chain_dialog);
}

void Ginterface_Inject_EditFilters_PointItem(GtkWidget *widget, gpointer data) /* DROP_FILTER *FA_ptr, char direction) */
{
   GtkTreeIter iter;
   GtkTreeModel *model;
   gchar *lineptr;

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

/* the row_activated signal requires a function in this form, even though we don't need all the args */
void Ginterface_Inject_SelectItem(GtkTreeView *treeview, gpointer arg1, GtkTreeViewColumn *arg2, gpointer data)
{
   Ginterface_Inject_Callback(GTK_WIDGET (treeview), (gpointer) data);
}

void Ginterface_Inject_EditFilters(DROP_FILTER *FA_ptr)
{
   DEBUG_MSG("Ginterface_Inject_EditFilters");

   gFA_ptr = FA_ptr;

   gFil_Pointer = gFil_Base_Pointer = 0;

   Ginterface_Inject_ChainWindow(FA_ptr);
}

void Ginterface_Inject_Callback(GtkWidget *widget, gpointer data)
{
   gchar action = '!';

   sscanf(data, "%c", &action);

   switch (action)
      {
         case '!':
                  Ginterface_Inject_Filter(gFA_ptr);
                  if (gFA_ptr[gFil_Pointer].slen == 0 && gFA_ptr[gFil_Pointer].type == 'R')
                  {
                     Ginterface_PopUp("NOT a good idea setting a zero length search string with Replace method...\nplease re-Edit this filter or ettercap will hang up on it !!");
                     if (gFA_ptr == Filter_Array_Source)  // safe disable the filter chain
                        filter_on_source = 0;
                     else
                        filter_on_dest = 0;
                  }
                  Ginterface_Inject_EditFilters_InitList(gFA_ptr);
                  break;
         case 'A':
         case 'a':
                  if (gFA_ptr == Filter_Array_Source)
                  {
                     FilterDrop_AddFilter(Filter_Array_Source);
                     gFA_ptr = Filter_Array_Source;
                  }
                  else if (gFA_ptr == Filter_Array_Dest)
                  {
                     FilterDrop_AddFilter(Filter_Array_Dest);
                     gFA_ptr = Filter_Array_Dest;
                  }
                  Ginterface_Inject_EditFilters_InitList(gFA_ptr);
                  break;
         case 'D':
         case 'd':
                  FilterDrop_DelFilter(gFA_ptr, gFil_Pointer);
                  Ginterface_Inject_EditFilters_InitList(gFA_ptr);
                  break;

         case 'S':
         case 's':
                  FilterDrop_SaveFilter();
                  Ginterface_PopUp("Filter chain saved !");
                  break;
         case 'H':
         case 'h':{
                     static char *help[] = {
                        "[qQ][F10] - quit",
                        "[return]  - edit the selected filter",
                        "[dD]      - Delete the filter",
                        "[aA]      - Add a new filter",
                        "[sS]      - Save the filters chain",
                        NULL};
                     Ginterface_HelpWindow(help);
                  }
                  break;
      }
}

void Ginterface_Inject_CloseChainWindow (GtkWidget *widget, gpointer data)
{
   if (Ginterface_PopUpQ("Do you want to save the filters chain (y/n)?")=='y')
      FilterDrop_SaveFilter();

   // g_signal_handlers_block_by_func (G_OBJECT (c_select), G_CALLBACK (Ginterface_Inject_EditFilters_PointItem), NULL);

   gtk_widget_destroy (widget);
   g_free(filterlist);
   filterlist = NULL;

   Parser_LoadFilters("");
   return;
}

/* EOF */

// vim:ts=3:expandtab

