"Fossies" - the Fresh Open Source Software Archive

Member "firestarter-1.0.3/src/hitview.c" (29 Jan 2005, 26616 Bytes) of package /linux/misc/old/firestarter-1.0.3.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "hitview.c" see the Fossies "Dox" file reference documentation.

    1 /*---[ hitview.c ]-----------------------------------------------------
    2  * Copyright (C) 2002-2004 Tomas Junnonen (majix@sci.fi)
    3  *
    4  * This program is free software; you can redistribute it and/or modify
    5  * it under the terms of the GNU General Public License as published by
    6  * the Free Software Foundation; either version 2 of the License, or
    7  * (at your option) any later version.
    8  *
    9  * The Events page and related functions
   10  *--------------------------------------------------------------------*/
   11 
   12 #include <config.h>
   13 #include <gnome.h>
   14 #include <libgnomevfs/gnome-vfs.h>
   15 
   16 #include "firestarter.h"
   17 #include "globals.h"
   18 #include "hitview.h"
   19 #include "util.h"
   20 #include "menus.h"
   21 #include "preferences.h"
   22 #include "statusview.h"
   23 #include "logread.h"
   24 #include "scriptwriter.h"
   25 
   26 #define COLOR_SERIOUS_HIT "#bd1f00"
   27 #define COLOR_BROADCAST_HIT "#6d6d6d"
   28 
   29 static GtkListStore *hitstore;
   30 static GtkWidget *hitview;
   31 static Hit *last_hit = NULL;
   32 static GnomeVFSAsyncHandle *hitview_ghandle = (GnomeVFSAsyncHandle*)NULL;
   33 
   34 const Hit *
   35 get_last_hit (void)
   36 {
   37     return last_hit;
   38 }
   39 
   40 gboolean
   41 hitview_reload_in_progress (void)
   42 {
   43     return (hitview_ghandle != NULL);
   44 }
   45 
   46 void
   47 hitview_abort_reload_callback (GnomeVFSAsyncHandle *handle, GnomeVFSResult result, gpointer data)
   48 {
   49     Parse *info = data;
   50     if (result != GNOME_VFS_OK) {
   51         g_warning ("Close error");
   52     }
   53     g_free (info->buffer);
   54     g_pattern_spec_free (info->pattern);
   55     g_free (info);
   56     hitview_ghandle = (GnomeVFSAsyncHandle*)NULL;
   57 
   58     menus_update_events_reloading (FALSE, gui_get_active_view () == EVENTS_VIEW);
   59     printf ("Finished reading events list\n");
   60 }
   61 
   62 /* [ create_text_column ]
   63  * Convinience funtion for creating a text column for a treeview
   64  */
   65 static GtkTreeViewColumn *
   66 create_text_column (gint number, gchar * title)
   67 {
   68     GtkTreeViewColumn *column;
   69     GtkCellRenderer *renderer;
   70 
   71     renderer = gtk_cell_renderer_text_new ();
   72     column = gtk_tree_view_column_new_with_attributes (title, renderer,
   73                                                        "text", number,
   74                                                        "foreground", HITCOL_COLOR,
   75                                                        NULL);
   76     return column;
   77 }
   78 
   79 /* [ hitview_clear ]
   80  * Clears the log CList
   81  */
   82 void
   83 hitview_clear (void)
   84 {
   85     if (status_get_state () == STATUS_HIT)
   86         status_set_state (STATUS_RUNNING);
   87 
   88     menus_events_clear_enabled (FALSE);
   89     menus_events_save_enabled (FALSE);
   90     gtk_list_store_clear (hitstore);
   91     if (last_hit != NULL) {
   92         free_hit (last_hit);
   93         last_hit = NULL;
   94     }
   95     gtk_tree_view_columns_autosize (GTK_TREE_VIEW (hitview));
   96     status_events_reset ();
   97 }
   98 
   99 /* [ unselect_all ]
  100  * Unselect all entries in the hitview
  101  */
  102 static void
  103 unselect_all (void)
  104 {
  105     GtkTreeSelection *s;
  106 
  107     s = gtk_tree_view_get_selection (GTK_TREE_VIEW (hitview));
  108     gtk_tree_selection_unselect_all (s);
  109 }
  110 
  111 /* [ has_selected ]
  112  * Return true if there are entries selected in the hitview
  113  */
  114 static gboolean
  115 has_selected (void)
  116 {
  117     GtkTreeSelection *selection;
  118     GtkTreeIter iter;
  119     gboolean has_selected;
  120 
  121     selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (hitview));
  122     has_selected = gtk_tree_selection_get_selected (selection, NULL, &iter);
  123 
  124     return has_selected;
  125 }
  126 
  127 /* [ scroll_to_hit ]
  128  * Scroll the hitview to the hit iter points to. Only works in ascending sort mode
  129  */
  130 static void
  131 scroll_to_hit (GtkTreeIter *iter)
  132 {
  133     static GtkTreeModel *model = NULL;
  134     gint colid;
  135     GtkSortType order;
  136     GtkTreePath *last;
  137 
  138     if (model == NULL)
  139         model = gtk_tree_view_get_model (GTK_TREE_VIEW (hitview));
  140 
  141     last = gtk_tree_model_get_path (model, iter);
  142     gtk_tree_sortable_get_sort_column_id (GTK_TREE_SORTABLE (model), &colid, &order);
  143 
  144     if (order == GTK_SORT_ASCENDING)
  145         gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (hitview), last, NULL, TRUE, 1.0, 1.0);
  146 
  147      gtk_tree_path_free (last);
  148 }
  149 
  150 /* [ compare_to_last_hit ]
  151  * Loosely compare a hit to the previous one. Return true if they are similiar
  152  */
  153 static gboolean
  154 compare_to_last_hit (Hit *new)
  155 {
  156     const Hit *old = get_last_hit ();
  157     gboolean same = TRUE;
  158 
  159     if (old == NULL || new == NULL)
  160         return FALSE;
  161     
  162     /* Going from most likely to differ to least */
  163     if (strcmp (new->port, old->port) != 0) {
  164         same = FALSE;
  165     }
  166     else if (strcmp (new->protocol, old->protocol) != 0) {
  167         same = FALSE;
  168     }
  169     else if (strcmp (new->source, old->source) != 0) {
  170         same = FALSE;
  171     }
  172     else if (strcmp (new->destination, old->destination) != 0) {
  173         same = FALSE;
  174     }
  175 /*  else if (strcmp (new->in, old->in) == 0)
  176         same = FALSE;
  177     else if (strcmp (new->out, old->out) == 0)
  178         same = FALSE;
  179 */
  180     return same;
  181 }
  182 
  183 /* [ hit_is_for_me ]
  184  * Test if the destination of a hit matches the external interface IP
  185  */
  186 static gboolean
  187 hit_is_for_me (Hit *h)
  188 {
  189     static gchar *myip = NULL;
  190     
  191     if (myip == NULL) {
  192         myip = get_ip_of_interface (preferences_get_string (PREFS_FW_EXT_IF));
  193     }
  194 
  195     return (strcmp (myip, h->destination) == 0);
  196 }
  197 
  198 /* [ hit_is_serious ]
  199  * Test if a hit is classified as serious
  200  */
  201 static gboolean
  202 hit_is_serious (Hit *h)
  203 {
  204     return (hit_is_for_me (h) && atoi (h->port) < 1024);
  205 }
  206 
  207 /* [ hit_is_broadcast ]
  208  * Test if the hit is a broadcasted message
  209  */
  210 static gboolean
  211 hit_is_broadcast (Hit *h)
  212 {
  213     return (g_str_has_suffix (h->destination, ".255"));
  214 }
  215 
  216 static gboolean
  217 hit_is_outbound (Hit *h)
  218 {
  219     return g_str_equal (h->direction, "Outbound");
  220 }
  221 
  222 static gboolean
  223 hit_is_inbound (Hit *h)
  224 {
  225     return g_str_equal (h->direction, "Inbound");
  226 }
  227 
  228 /* [ hitview_append_hit ]
  229  * Append a hit to the hitlist, return true if successful
  230  */
  231 gboolean
  232 hitview_append_hit (Hit *h)
  233 {
  234     GtkTreeIter iter;
  235     static gchar *color_serious = COLOR_SERIOUS_HIT;
  236     static gchar *color_broadcast = COLOR_BROADCAST_HIT;
  237     gchar *color = NULL;
  238 
  239     if (preferences_get_bool (PREFS_SKIP_REDUNDANT))
  240         if (compare_to_last_hit (h)) {
  241             /* printf ("Hit filtered: Redundant\n"); */
  242             return FALSE;
  243         }
  244 
  245     if (preferences_get_bool (PREFS_SKIP_NOT_FOR_FIREWALL))
  246         if (!hit_is_for_me (h) && !hit_is_outbound (h)) {
  247             /* printf ("Hit filtered: Someone else's problem \n"); */
  248             return FALSE;
  249         }
  250 
  251     if (hit_is_broadcast (h)) {
  252         color = color_broadcast;
  253     } else if (hit_is_serious (h)) {
  254         color = color_serious;
  255         if (hit_is_outbound (h))
  256             status_serious_event_out_inc ();
  257         else
  258             status_serious_event_in_inc ();
  259     }
  260 
  261     if (hit_is_outbound (h)) {
  262         status_event_out_inc ();
  263         g_free (h->direction);
  264         h->direction = g_strdup (_("Outbound")); /* Localize the direction */
  265     } else if (hit_is_inbound (h)) {
  266         status_event_in_inc ();
  267         g_free (h->direction);
  268         h->direction = g_strdup (_("Inbound"));
  269     } else {
  270         g_free (h->direction);
  271         h->direction = g_strdup (_("Unknown"));
  272     }
  273 
  274     gtk_list_store_append (hitstore, &iter);
  275     gtk_list_store_set (hitstore, &iter,
  276                         HITCOL_TIME,        h->time,
  277                 HITCOL_DIRECTION,   h->direction,
  278                         HITCOL_IN,          h->in,
  279                         HITCOL_OUT,         h->out,
  280                         HITCOL_PORT,        h->port,
  281                         HITCOL_SOURCE,      h->source,
  282                         HITCOL_DESTINATION, h->destination,
  283                         HITCOL_LENGTH,      h->length,
  284                         HITCOL_TOS,         h->tos,
  285                         HITCOL_PROTOCOL,    h->protocol,
  286                         HITCOL_SERVICE,     h->service,
  287                 HITCOL_COLOR,       color,
  288                         -1);
  289 
  290     if (!has_selected ())
  291         scroll_to_hit (&iter);
  292 
  293     if (last_hit != NULL) {
  294         free_hit (last_hit);
  295     }
  296     last_hit = copy_hit (h);
  297 
  298     menus_events_clear_enabled (TRUE);
  299     menus_events_save_enabled (TRUE);
  300 
  301     /* Fixes a glitch in the view's rendering that causes
  302        text to jump around when mouse moves over an entry */
  303     if (!hitview_reload_in_progress ())
  304         gtk_tree_view_columns_autosize (GTK_TREE_VIEW (hitview));
  305 
  306     return TRUE;
  307 }
  308 
  309 /* [ gvfs_open_callback ]
  310  * Open and read the file asynchronously
  311  */
  312 static void
  313 gvfs_open_callback (GnomeVFSAsyncHandle *handle, GnomeVFSResult result, gpointer data)
  314 {
  315     Parse *info = g_new (Parse, 1);
  316     GnomeVFSFileInfo *file_info;
  317 
  318     if (result != GNOME_VFS_OK) {
  319         g_warning ("Failed to open file for async reading");
  320         g_free (info);
  321         return;
  322     }
  323     file_info = gnome_vfs_file_info_new ();
  324 
  325     if (gnome_vfs_get_file_info((gchar *)data, file_info, GNOME_VFS_FILE_INFO_DEFAULT) != GNOME_VFS_OK) {
  326         g_warning ("File info error");
  327         g_free (info);
  328         return;
  329     }
  330 
  331     info->size = file_info->size;
  332     info->bytes_read = 0;
  333     info->buffer = g_new (gchar, FILE_BUF+1);
  334     info->pattern = g_pattern_spec_new ("* IN=* OUT=* SRC=* ");
  335     info->continuous = FALSE;
  336     gnome_vfs_file_info_unref (file_info);
  337     gnome_vfs_async_read (handle, info->buffer, FILE_BUF, logread_async_read_callback, info);
  338 }
  339 
  340 void
  341 hitview_reload_cancel (void)
  342 {
  343     printf ("Canceled reload of events list\n");
  344     gnome_vfs_async_cancel (hitview_ghandle);
  345     menus_update_events_reloading (FALSE, gui_get_active_view () == EVENTS_VIEW);
  346     hitview_ghandle = (GnomeVFSAsyncHandle*)NULL;
  347 }
  348 
  349 /* [ hitview_reload ]
  350  * Loads the entire kernel log file into the hitlist
  351  */
  352 void
  353 hitview_reload (void)
  354 {   
  355     const gchar *path;
  356 
  357      /* If a new reload request comes while the previous operation is still pending, cancel it */
  358     if (hitview_reload_in_progress ()) {    
  359         gnome_vfs_async_cancel (hitview_ghandle);
  360     }
  361 
  362     path = get_system_log_path ();
  363 
  364     if (!g_file_test (path, G_FILE_TEST_EXISTS)) {
  365         gchar *error = g_strdup_printf ("Error reading system log %s, file does not exist", path);
  366         show_error (error);
  367         g_free (error);
  368         return;
  369     }
  370 
  371     hitview_clear ();
  372     gnome_vfs_async_open (&hitview_ghandle, path, GNOME_VFS_OPEN_READ, GNOME_VFS_PRIORITY_DEFAULT, 
  373                               gvfs_open_callback, (gpointer)path);
  374 
  375     menus_update_events_reloading (TRUE, gui_get_active_view () == EVENTS_VIEW);
  376 }
  377 
  378 /* [ create_hitlist_model ]
  379  * Creates the list for storage of hits
  380  */
  381 static GtkTreeModel *
  382 create_hitlist_model (void)
  383 {
  384     hitstore = gtk_list_store_new (NUM_HITCOLUMNS,
  385         G_TYPE_STRING,
  386         G_TYPE_STRING,
  387         G_TYPE_STRING,
  388         G_TYPE_STRING,
  389         G_TYPE_STRING,
  390         G_TYPE_STRING,
  391         G_TYPE_STRING,
  392         G_TYPE_STRING,
  393         G_TYPE_STRING,
  394         G_TYPE_STRING,
  395         G_TYPE_STRING,
  396         G_TYPE_STRING);
  397 
  398     return GTK_TREE_MODEL (hitstore);
  399 }
  400 
  401 /* [ hitview_toggle_column_visibility ]
  402  * Negate the visibility of a column
  403  */
  404 void
  405 hitview_toggle_column_visibility (GtkWidget *widget, gint colnum)
  406 {
  407     GtkTreeViewColumn *column;
  408     gboolean visible;
  409 
  410     g_assert (colnum < NUM_HITCOLUMNS);
  411 
  412     if (hitview == NULL)
  413         return;
  414 
  415     column = gtk_tree_view_get_column (GTK_TREE_VIEW (hitview), colnum);
  416     visible = !gtk_tree_view_column_get_visible (column);
  417     gtk_tree_view_column_set_visible(column, visible);
  418 
  419     switch (colnum) {
  420       case 0: preferences_set_bool (PREFS_HITVIEW_TIME_COL, visible); break;
  421       case 1: preferences_set_bool (PREFS_HITVIEW_DIRECTION_COL, visible); break;
  422       case 2: preferences_set_bool (PREFS_HITVIEW_IN_COL, visible); break;
  423       case 3: preferences_set_bool (PREFS_HITVIEW_OUT_COL, visible); break;
  424       case 4: preferences_set_bool (PREFS_HITVIEW_PORT_COL, visible); break;
  425       case 5: preferences_set_bool (PREFS_HITVIEW_SOURCE_COL, visible); break;
  426       case 6: preferences_set_bool (PREFS_HITVIEW_DESTINATION_COL, visible); break;
  427       case 7: preferences_set_bool (PREFS_HITVIEW_LENGTH_COL, visible); break;
  428       case 8: preferences_set_bool (PREFS_HITVIEW_TOS_COL, visible); break;
  429       case 9: preferences_set_bool (PREFS_HITVIEW_PROTOCOL_COL, visible); break;
  430       case 10: preferences_set_bool (PREFS_HITVIEW_SERVICE_COL, visible); break;
  431     }
  432 }
  433 
  434 /* [ hitview_add_columns ]
  435  * Add the columns to the hit TreeView
  436  */
  437 static void
  438 hitview_add_columns (GtkTreeView *treeview)
  439 {
  440     GtkTreeViewColumn *column;
  441     gboolean visible;
  442 
  443     /* column for time */
  444     column = create_text_column (HITCOL_TIME, _("Time"));
  445     gtk_tree_view_column_set_sort_column_id (column, HITCOL_TIME);
  446     gtk_tree_view_append_column (treeview, column);
  447     visible = preferences_get_bool (PREFS_HITVIEW_TIME_COL);
  448     gtk_tree_view_column_set_visible (column, visible);
  449 
  450     /* column for direction */
  451     column = create_text_column (HITCOL_DIRECTION, _("Direction"));
  452     gtk_tree_view_column_set_sort_column_id (column, HITCOL_DIRECTION);
  453     gtk_tree_view_append_column (treeview, column);
  454     visible = preferences_get_bool (PREFS_HITVIEW_DIRECTION_COL);
  455     gtk_tree_view_column_set_visible (column, visible);
  456 
  457     /* column for in device */
  458     column = create_text_column (HITCOL_IN, _("In"));
  459     gtk_tree_view_column_set_sort_column_id (column, HITCOL_IN);
  460     gtk_tree_view_append_column (treeview, column);
  461     visible = preferences_get_bool (PREFS_HITVIEW_IN_COL);
  462     gtk_tree_view_column_set_visible (column, visible);
  463 
  464     /* column for out device */
  465     column = create_text_column (HITCOL_OUT, _("Out"));
  466     gtk_tree_view_column_set_sort_column_id (column, HITCOL_OUT);
  467     gtk_tree_view_append_column (treeview, column);
  468     visible = preferences_get_bool (PREFS_HITVIEW_OUT_COL);
  469     gtk_tree_view_column_set_visible (column, visible);
  470 
  471     /* column for port */
  472     column = create_text_column (HITCOL_PORT, _("Port"));
  473     gtk_tree_view_column_set_sort_column_id (column, HITCOL_PORT);
  474     gtk_tree_view_append_column (treeview, column);
  475     visible = preferences_get_bool (PREFS_HITVIEW_PORT_COL);
  476     gtk_tree_view_column_set_visible (column, visible);
  477 
  478     /* column for source */
  479     column = create_text_column (HITCOL_SOURCE, _("Source"));
  480     gtk_tree_view_column_set_sort_column_id (column, HITCOL_SOURCE);
  481     gtk_tree_view_append_column (treeview, column);
  482     visible = preferences_get_bool (PREFS_HITVIEW_SOURCE_COL);
  483     gtk_tree_view_column_set_visible (column, visible);
  484 
  485     /* column for destination */
  486     column = create_text_column (HITCOL_DESTINATION, _("Destination"));
  487     gtk_tree_view_column_set_sort_column_id (column, HITCOL_DESTINATION);
  488     gtk_tree_view_append_column (treeview, column);
  489     visible = preferences_get_bool (PREFS_HITVIEW_DESTINATION_COL);
  490     gtk_tree_view_column_set_visible (column, visible);
  491     
  492     /* column for packet length */
  493     column = create_text_column (HITCOL_LENGTH, _("Length"));
  494     gtk_tree_view_column_set_sort_column_id (column, HITCOL_LENGTH);
  495     gtk_tree_view_append_column (treeview, column);
  496     visible = preferences_get_bool (PREFS_HITVIEW_LENGTH_COL);
  497     gtk_tree_view_column_set_visible (column, visible);
  498 
  499     /* column for ToS */
  500     column = create_text_column (HITCOL_TOS, _("TOS"));
  501     gtk_tree_view_column_set_sort_column_id (column, HITCOL_TOS);
  502     gtk_tree_view_append_column (treeview, column);
  503     visible = preferences_get_bool (PREFS_HITVIEW_TOS_COL);
  504     gtk_tree_view_column_set_visible (column, visible);
  505 
  506     /* column for protocol */
  507     column = create_text_column (HITCOL_PROTOCOL, _("Protocol"));
  508     gtk_tree_view_column_set_sort_column_id (column, HITCOL_PROTOCOL);
  509     gtk_tree_view_append_column (treeview, column); 
  510     visible = preferences_get_bool (PREFS_HITVIEW_PROTOCOL_COL);
  511     gtk_tree_view_column_set_visible (column, visible);
  512 
  513     /* column for service */
  514     column = create_text_column (HITCOL_SERVICE, _("Service"));
  515     gtk_tree_view_column_set_sort_column_id (column, HITCOL_SERVICE);
  516     gtk_tree_view_append_column (treeview, column); 
  517     visible = preferences_get_bool (PREFS_HITVIEW_SERVICE_COL);
  518     gtk_tree_view_column_set_visible (column, visible);
  519 }
  520 
  521 /* [ get_hit ]
  522  * Retrieve the specific hit iter points to
  523  */
  524 static Hit *
  525 get_hit (GtkTreeModel *model,
  526          GtkTreeIter iter)
  527 {
  528     Hit *h = g_new (Hit, 1);
  529 
  530     gtk_tree_model_get (model, &iter,
  531                         HITCOL_TIME,        &h->time,
  532                 HITCOL_DIRECTION,   &h->direction,
  533                         HITCOL_IN,          &h->in,
  534                         HITCOL_OUT,         &h->out,
  535                         HITCOL_PORT,        &h->port,
  536                         HITCOL_SOURCE,      &h->source,
  537                         HITCOL_DESTINATION, &h->destination,
  538                         HITCOL_LENGTH,      &h->length,
  539                         HITCOL_TOS,         &h->tos,
  540                         HITCOL_PROTOCOL,    &h->protocol,
  541                         HITCOL_SERVICE,     &h->service,
  542                         -1);
  543 
  544     return h; 
  545 }
  546 
  547 /* [ hit_activated_cb ]
  548  * Callback for selecting a row in the hit view
  549  * TODO: Default action for hits? Hit->Rule helper maybe.
  550  */
  551 static void 
  552 hit_activated_cb (GtkTreeView *treeview,
  553                  GtkTreePath *path,
  554                  GtkTreeViewColumn *arg2,
  555                  gpointer data)
  556 {
  557     GtkTreeModel *model;
  558     GtkTreeIter iter;
  559     Hit *h;
  560 
  561     model = gtk_tree_view_get_model (treeview);
  562     gtk_tree_model_get_iter (model, &iter, path);
  563     h = get_hit (model, iter);
  564 
  565     print_hit (h);
  566     free_hit (h);
  567 
  568     unselect_all ();
  569 }
  570 
  571 /* [ hitview_get_selected_hit ]
  572  * Get the hit that is currently selected in the hitview
  573  */
  574 Hit *
  575 hitview_get_selected_hit (void)
  576 {
  577     GtkTreeSelection *selection;
  578     GtkTreeModel *model;
  579     GtkTreeIter iter;
  580     Hit *h = NULL;
  581     gboolean has_selected;
  582 
  583     selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (hitview));
  584 
  585     has_selected = gtk_tree_selection_get_selected (selection,
  586                                                     NULL,
  587                                                     &iter);
  588     if (has_selected) {
  589         model = gtk_tree_view_get_model (GTK_TREE_VIEW (hitview));
  590         h = get_hit (model, iter);
  591     }
  592 
  593     return h;
  594 }
  595 
  596 GList *
  597 hitview_get_all_hits (void)
  598 {
  599     GList *hits = NULL;
  600     Hit *h;
  601     GtkTreeModel *model;
  602     GtkTreeIter iter;
  603 
  604     model = gtk_tree_view_get_model (GTK_TREE_VIEW (hitview));
  605     if (gtk_tree_model_get_iter_first (model, &iter)) {
  606         do {
  607             h = get_hit (model, iter);
  608             hits = g_list_append (hits, h);
  609         } while (gtk_tree_model_iter_next (model, &iter));
  610     } else
  611         printf ("Error compiling list of hits\n");
  612 
  613     return hits;
  614 }
  615 
  616 /* [ hitview_button_press_cb ]
  617  * Pop up an menu when right clicking the hitview
  618  */
  619 static gboolean
  620 hitview_button_press_cb (GtkWidget* widget, GdkEventButton* event)
  621 {
  622     gboolean retval = FALSE;
  623     Hit *h;
  624     GtkWidget *menu;
  625 
  626     /* Clear hit state */
  627     if (status_get_state () == STATUS_HIT)
  628         status_set_state (STATUS_RUNNING);
  629 
  630     h = hitview_get_selected_hit ();
  631     if (h == NULL)
  632         return retval;
  633     else if (hit_is_outbound (h))
  634         menu = menus_get_events_outbound_context_menu ();
  635     else
  636         menu = menus_get_events_inbound_context_menu ();
  637 
  638     switch (event->button) {
  639         case 1: break;
  640         
  641         case 3: gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, 
  642                                 event->button, event->time);
  643             retval = TRUE;
  644             break;
  645     }
  646 
  647     g_free (h);
  648     return retval;
  649 }
  650 
  651 /* [ append_filter_file ]
  652  * Append data to a events filter file
  653  */
  654 static gboolean
  655 append_filter_file (gchar *path, gchar *data)
  656 {
  657     GIOChannel* out;
  658     GError *error = NULL;
  659 
  660     out = g_io_channel_new_file (path, "a", &error);
  661 
  662     if (out == NULL) {
  663         g_printerr ("Error reading file %s: %s\n", path, error->message);
  664         return FALSE;
  665     }
  666 
  667     if (g_io_channel_write_chars (out, data, -1, NULL, &error) == G_IO_STATUS_NORMAL) {
  668         g_io_channel_shutdown (out, TRUE, &error);
  669         return TRUE;
  670     } else {
  671         g_io_channel_shutdown (out, FALSE, &error);
  672         return FALSE;
  673     }
  674 }
  675 /* [ disable_events_selected_source ]
  676  * Disable events from the selected source
  677  */
  678 void
  679 hitview_disable_events_selected_source (void)
  680 {
  681     Hit *h;
  682     gchar *data;
  683 
  684     h = hitview_get_selected_hit ();
  685     if (h == NULL)
  686         return;
  687 
  688     data = g_strconcat (h->source, "\n", NULL);
  689     append_filter_file (FIRESTARTER_FILTER_HOSTS_SCRIPT, data);
  690     g_free (h);
  691     g_free (data);
  692 
  693     restart_firewall_if_active ();
  694 }
  695 
  696 void
  697 hitview_disable_events_selected_port (void)
  698 {
  699     Hit *h;
  700     gchar *data;
  701 
  702     h = hitview_get_selected_hit ();
  703     if (h == NULL)
  704         return;
  705 
  706     data = g_strconcat (h->port, "\n", NULL);
  707     append_filter_file (FIRESTARTER_FILTER_PORTS_SCRIPT, data);
  708     g_free (h);
  709     g_free (data);
  710 
  711     restart_firewall_if_active ();
  712 }
  713 
  714 void
  715 hitview_allow_host (void)
  716 {
  717     Hit *h;
  718 
  719     h = hitview_get_selected_hit ();
  720     if (h == NULL)
  721         return;
  722 
  723     if (hit_is_outbound (h))
  724         policyview_create_rule (RULETYPE_OUTBOUND_ALLOW_TO, h);
  725     else
  726         policyview_create_rule (RULETYPE_INBOUND_ALLOW_FROM, h);
  727 
  728     g_free (h);
  729 }
  730 
  731 void
  732 hitview_allow_service (void)
  733 {
  734     Hit *h;
  735 
  736     h = hitview_get_selected_hit ();
  737     if (h == NULL)
  738         return;
  739 
  740     if (hit_is_outbound (h))
  741         policyview_create_rule (RULETYPE_OUTBOUND_ALLOW_SERVICE, h);
  742     else
  743         policyview_create_rule (RULETYPE_INBOUND_ALLOW_SERVICE, h);
  744 
  745     g_free (h);
  746 }
  747 
  748 void
  749 hitview_allow_service_from (void)
  750 {
  751     Hit *h;
  752 
  753     h = hitview_get_selected_hit ();
  754     if (h == NULL)
  755         return;
  756 
  757     if (hit_is_outbound (h))
  758         policyview_create_rule (RULETYPE_OUTBOUND_ALLOW_SERVICE_FROM, h);
  759     else
  760         policyview_create_rule (RULETYPE_INBOUND_ALLOW_SERVICE_FROM, h);
  761 
  762     g_free (h);
  763 }
  764 
  765 /* [ lookup_selected_hit ]
  766  * Resolve the IP address/hostname from the selected line in hitview
  767  */
  768 void
  769 hitview_lookup_selected_hit (void)
  770 {
  771     GtkTreeSelection *selection;
  772     GtkTreeIter iter;
  773     static GtkTreeModel *model = NULL;
  774     gchar *source, *destination;
  775     gchar *hostname = NULL;
  776 
  777     selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (hitview));
  778     if (!gtk_tree_selection_get_selected (selection, NULL, &iter))
  779         return;
  780 
  781     if (!model)
  782         model = gtk_tree_view_get_model (GTK_TREE_VIEW (hitview));
  783 
  784     gtk_tree_model_get (model, &iter,
  785                         HITCOL_SOURCE, &source,
  786                 HITCOL_DESTINATION, &destination,
  787                         -1);
  788     hostname = lookup_ip (source);
  789     if (hostname != NULL)
  790         gtk_list_store_set (hitstore, &iter,
  791                             HITCOL_SOURCE, hostname,
  792                            -1);
  793     hostname = lookup_ip (destination);
  794     if (hostname != NULL)
  795         gtk_list_store_set (hitstore, &iter,
  796                             HITCOL_DESTINATION, hostname,
  797                            -1);
  798 
  799     gtk_tree_view_columns_autosize (GTK_TREE_VIEW (hitview));
  800     g_free (source);
  801     g_free (destination);
  802 }
  803 
  804 /* [ month_number ]
  805  * Convert a three letter month identifier to a number
  806  */
  807 static int
  808 month_number (gchar *month)
  809 {
  810     int num = 0;
  811 
  812     if (strcmp (month, "Jan") == 0)
  813         num = 1;
  814     else if (strcmp (month, "Feb") == 0)
  815         num = 2;
  816     else if (strcmp (month, "Mar") == 0)
  817         num = 3;
  818     else if (strcmp (month, "Apr") == 0)
  819         num = 4;
  820     else if (strcmp (month, "May") == 0)
  821         num = 5;
  822     else if (strcmp (month, "Jun") == 0)
  823         num = 6;
  824     else if (strcmp (month, "Jul") == 0)
  825         num = 7;
  826     else if (strcmp (month, "Aug") == 0)
  827         num = 8;
  828     else if (strcmp (month, "Sep") == 0)
  829         num = 9;
  830     else if (strcmp (month, "Oct") == 0)
  831         num = 10;
  832     else if (strcmp (month, "Nov") == 0)
  833         num = 11;
  834     else if (strcmp (month, "Dec") == 0)
  835         num = 12;
  836 
  837     return num;
  838 }
  839 
  840 /* [ time_sort_func ]
  841  * Function for sorting the time column
  842  */
  843 static int
  844 time_sort_func (GtkTreeModel *model, 
  845             GtkTreeIter  *a, 
  846             GtkTreeIter  *b, 
  847             gpointer      user_data)
  848 {
  849     enum { MONTH, DATE, CLOCK };
  850 
  851     gchar *data1, *data2;
  852     gchar **time1, **time2;
  853     gint month1, month2;
  854     gint day1, day2;
  855     gint sort = 0;
  856 
  857     gtk_tree_model_get (model, a, HITCOL_TIME, &data1, -1);
  858     gtk_tree_model_get (model, b, HITCOL_TIME, &data2, -1);
  859 
  860     time1 = g_strsplit (data1, " ", 3);
  861     time2 = g_strsplit (data2, " ", 3);
  862 
  863     month1 = month_number (time1[MONTH]);
  864     month2 = month_number (time2[MONTH]); 
  865 
  866     /* Compare first month, then the day, and last the clock */
  867     if (month1 != month2)
  868         sort = ((month1 < month2) ? -1:1);
  869     else {
  870         day1 = atoi (time1[DATE]);
  871         day2 = atoi (time2[DATE]);
  872 
  873         if (day1 != day2)
  874             sort = ((day1 < day2) ? -1:1);
  875         else
  876             sort = strcasecmp (time1[CLOCK], time2[CLOCK]);
  877     }
  878 
  879     g_free (data1);
  880     g_free (data2);
  881     g_strfreev (time1);
  882     g_strfreev (time2);
  883 
  884     return sort;
  885 }
  886 
  887 /* [ num_sort_func ]
  888  * Function for sorting a (text) column with only numbers in it
  889  */
  890 static int
  891 num_sort_func (GtkTreeModel *model, 
  892            GtkTreeIter  *a, 
  893            GtkTreeIter  *b, 
  894            gpointer      column)
  895 {
  896     gchar *data1, *data2;
  897     gint n1, n2;
  898 
  899     gtk_tree_model_get (model, a, (gint)column, &data1, -1);
  900     gtk_tree_model_get (model, b, (gint)column, &data2, -1);
  901 
  902     n1 = atoi (data1);
  903     n2 = atoi (data2);
  904 
  905     g_free (data1);
  906     g_free (data2);
  907 
  908     if (n1 == n2)
  909         return 0;
  910     else
  911         return ((n1 < n2) ? -1:1);
  912 }
  913 
  914 /* [ copy_selected_hit ]
  915  * Copy the selected hit to the clipboard
  916  */
  917 void
  918 copy_selected_hit (void)
  919 {
  920     Hit *h;
  921     gchar *text;
  922     GtkClipboard *cb;
  923 
  924     h = hitview_get_selected_hit ();
  925 
  926     if (h == NULL)
  927         return;
  928 
  929     cb = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
  930 
  931     text = g_strconcat (
  932         "Time: ", h->time,
  933         " Source: ", h->source,
  934         " Destination: ", h->destination,
  935         " In IF: ", h->in,
  936         " Out IF: ", h->out,
  937         " Port: ", h->port,
  938         " Length: ", h->length,
  939         " ToS: ", h->tos,
  940         " Protocol: ", h->protocol,
  941         " Service: ", h->service,
  942         NULL);
  943 
  944     gtk_clipboard_set_text (cb, text, strlen (text));
  945     g_free (text);
  946     free_hit (h);
  947 }
  948 
  949 /* [ create_hitview_page ]
  950  * Create the hitview
  951  */
  952 GtkWidget *
  953 create_hitview_page (void)
  954 {
  955     GtkWidget *hitpagebox;
  956     GtkTreeModel *hitmodel;
  957     GtkWidget *scrolledwin;
  958     GtkWidget *frame;
  959     GtkWidget *label;
  960 
  961     hitpagebox = gtk_vbox_new (FALSE, 0);
  962     hitmodel = create_hitlist_model ();
  963     hitview = gtk_tree_view_new_with_model (hitmodel);
  964 
  965     frame = gtk_frame_new (NULL);
  966     label = gtk_label_new (NULL);
  967     gtk_label_set_markup (GTK_LABEL (label), g_strconcat (
  968         "<b>", _("Blocked Connections"), "</b>", NULL));
  969     gtk_frame_set_label_widget (GTK_FRAME (frame), label);
  970     gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);
  971     gtk_box_pack_start (GTK_BOX (hitpagebox), frame, FALSE, FALSE, GNOME_PAD_SMALL);
  972 
  973     scrolledwin = gtk_scrolled_window_new (NULL, NULL);
  974     gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwin),
  975                                     GTK_POLICY_NEVER,
  976                                     GTK_POLICY_ALWAYS);
  977 
  978     gtk_box_pack_start (GTK_BOX (hitpagebox), scrolledwin, TRUE, TRUE, 0);
  979 
  980     /* Pack the treeview into the scrolled window  */
  981     gtk_container_add (GTK_CONTAINER (scrolledwin), hitview);
  982     hitview_add_columns (GTK_TREE_VIEW (hitview));
  983     gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (hitview), TRUE);
  984     gtk_tree_view_set_search_column (GTK_TREE_VIEW (hitview),
  985         HITCOL_TIME);
  986 
  987     g_signal_connect (G_OBJECT (hitview), "button_press_event",
  988                       G_CALLBACK (hitview_button_press_cb), NULL);
  989     g_signal_connect (G_OBJECT (hitview), "row-activated",
  990                       G_CALLBACK (hit_activated_cb), NULL);
  991 
  992     /* The list is by default sorted by time */
  993     gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (hitmodel), HITCOL_TIME, GTK_SORT_ASCENDING);
  994 
  995     /* Some of the columns need special functions for sorting */
  996     gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (hitmodel), HITCOL_TIME,
  997                                      time_sort_func, NULL, NULL);
  998 
  999     gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (hitmodel), HITCOL_PORT,
 1000                                      num_sort_func, (gpointer)HITCOL_PORT, NULL);
 1001 
 1002     gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (hitmodel), HITCOL_LENGTH,
 1003                                      num_sort_func, (gpointer)HITCOL_LENGTH, NULL);
 1004 
 1005     g_object_unref (G_OBJECT (hitmodel));
 1006 
 1007     /* Default icon states */
 1008     menus_events_clear_enabled (FALSE);
 1009     menus_events_save_enabled (FALSE);
 1010 
 1011     gtk_widget_show_all (hitpagebox);
 1012     return hitpagebox;
 1013 }