nexmon – Rev 1

Subversion Repositories:
Rev:
/* dissector_tables_dlg.c
 * dissector_tables_dlg   2010 Anders Broman
 *
 * Wireshark - Network traffic analyzer
 * By Gerald Combs <gerald@wireshark.org>
 * Copyright 1998 Gerald Combs
 *
 * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include "config.h"

#include <string.h>


#include <epan/packet.h>

#include <gtk/gtk.h>
#include "ui/gtk/gui_utils.h"
#include "ui/gtk/dlg_utils.h"
#include "ui/gtk/dissector_tables_dlg.h"

static GtkWidget  *dissector_tables_dlg_w = NULL;

/* The columns */
enum
{
    TABLE_UI_NAME_COL,
    TABLE_SHORT_NAME_COL,
    N_COLUMNS
};

static void
win_destroy_cb(GtkWindow *win _U_, gpointer data _U_)
{

    if (dissector_tables_dlg_w != NULL) {
        window_destroy(dissector_tables_dlg_w);
        dissector_tables_dlg_w = NULL;
    }


}

/*
 * For a dissector table, put
 * its short name and its
 * descriptive name in the treeview.
 */

struct dissector_tables_tree_info {
    GtkWidget       *tree;
    GtkTreeIter     iter;
    GtkTreeIter     new_iter;
};

typedef struct dissector_tables_tree_info dissector_tables_tree_info_t;

static gint
ui_sort_func(GtkTreeModel *model,
             GtkTreeIter  *a,
             GtkTreeIter  *b,
             gpointer      user_data)
{
    gchar *stra, *strb;

    /* The col to get data from is in userdata */
    gint data_column = GPOINTER_TO_INT(user_data);

    gtk_tree_model_get(model, a, data_column, &stra, -1);
    gtk_tree_model_get(model, b, data_column, &strb, -1);

    return strcmp(stra, strb);
}


/*
 * Struct to hold the pointer to the trees
 * for dissector tables.
 */
struct dissector_tables_trees {
    GtkWidget       *str_tree_wgt;
    GtkWidget       *uint_tree_wgt;
    GtkWidget       *custom_tree_wgt;
    GtkWidget       *heuristic_tree_wgt;
};

typedef struct dissector_tables_trees dissector_tables_trees_t;

static void
proto_add_to_list(dissector_tables_tree_info_t *tree_info,
                  GtkTreeStore *store,
                  const gchar  *str,
                  const gchar  *proto_name)
{
    gtk_tree_store_insert_with_values(store, &tree_info->new_iter, &tree_info->iter, G_MAXINT,
                                      TABLE_UI_NAME_COL,    str,
                                      TABLE_SHORT_NAME_COL, proto_name,
                                      -1);
}

static void
decode_proto_add_to_list (const gchar *table_name _U_, ftenum_t selector_type,
                          gpointer key, gpointer value, gpointer user_data)
{
    GtkTreeStore       *store;
    const gchar        *proto_name;
    dtbl_entry_t       *dtbl_entry;
    dissector_handle_t  handle;
    guint32             port;
    gchar              *int_str;
    const gchar        *dissector_name_str;
    dissector_tables_tree_info_t *tree_info;

    tree_info = (dissector_tables_tree_info_t *)user_data;
    dtbl_entry = (dtbl_entry_t*)value;
    handle = dtbl_entry_get_handle(dtbl_entry);
    proto_name = dissector_handle_get_short_name(handle);

    store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(tree_info->tree)));

    switch (selector_type) {

        case FT_UINT8:
        case FT_UINT16:
        case FT_UINT24:
        case FT_UINT32:
            port = GPOINTER_TO_UINT(key);
            /* Hack: Use fixed width rj str so alpha sort (strcmp) will sort field numerically */
            int_str = g_strdup_printf ("%10d", port);
            proto_add_to_list(tree_info, store, int_str, proto_name);
            g_free (int_str);
            break;

        case FT_STRING:
        case FT_STRINGZ:
        case FT_UINT_STRING:
        case FT_STRINGZPAD:
            proto_add_to_list(tree_info, store, (const gchar*)key, proto_name);
            break;

        case FT_BYTES:
        case FT_GUID:
            dissector_name_str = dissector_handle_get_dissector_name(handle);
            if (dissector_name_str == NULL)
                dissector_name_str = "<Unknown>";
            proto_add_to_list(tree_info, store, dissector_name_str, proto_name);
            break;

        default:
            g_assert_not_reached();
    }

}

static void
table_name_add_to_list(dissector_tables_tree_info_t  *tree_info,
                       GtkWidget  *tree_view,
                       const char *table_name,
                       const char *ui_name)
{
    GtkTreeStore *store;

    tree_info->tree = tree_view;
    store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(tree_view))); /* Get store */

    gtk_tree_store_insert_with_values(store, &tree_info->iter, NULL, G_MAXINT,
                                      TABLE_UI_NAME_COL,    ui_name,
                                      TABLE_SHORT_NAME_COL, table_name,
                                      -1);
}

static void
display_heur_dissector_table_entries(const char *table_name _U_,
    struct heur_dtbl_entry *dtbl_entry, gpointer user_data)
{
    dissector_tables_tree_info_t *tree_info  = (dissector_tables_tree_info_t*)user_data;
    GtkTreeStore                 *store;

    if (dtbl_entry->protocol) {

        store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(tree_info->tree))); /* Get store */
        proto_add_to_list(tree_info, store,
                          (gchar *)proto_get_protocol_long_name(dtbl_entry->protocol),
                          proto_get_protocol_short_name(dtbl_entry->protocol));
    }else{
        g_warning("no protocol info");
    }


}

static void
display_heur_dissector_table_names(const char *table_name, struct heur_dissector_list *list, gpointer w)
{
    dissector_tables_trees_t      *dis_tbl_trees;
    dissector_tables_tree_info_t  *tree_info;

    tree_info = g_new(dissector_tables_tree_info_t, 1);
    dis_tbl_trees = (dissector_tables_trees_t*)w;

    table_name_add_to_list(tree_info, dis_tbl_trees->heuristic_tree_wgt, "", table_name);

    if (list) {
        heur_dissector_table_foreach(table_name, display_heur_dissector_table_entries, tree_info);
    }

}

static void
display_dissector_table_names(const char *table_name, const char *ui_name, void *w)
{
    dissector_tables_trees_t      *dis_tbl_trees;
    dissector_tables_tree_info_t  *tree_info;
    ftenum_t                       selector_type = get_dissector_table_selector_type(table_name);

    tree_info = g_new(dissector_tables_tree_info_t, 1);
    dis_tbl_trees = (dissector_tables_trees_t*)w;

    switch (selector_type) {
        case FT_UINT8:
        case FT_UINT16:
        case FT_UINT24:
        case FT_UINT32:
            table_name_add_to_list(tree_info, dis_tbl_trees->uint_tree_wgt, table_name, ui_name);
            break;
        case FT_STRING:
        case FT_STRINGZ:
        case FT_UINT_STRING:
        case FT_STRINGZPAD:
            table_name_add_to_list(tree_info, dis_tbl_trees->str_tree_wgt, table_name, ui_name);
            break;
        case FT_BYTES:
        case FT_GUID:
            table_name_add_to_list(tree_info, dis_tbl_trees->custom_tree_wgt, table_name, ui_name);
            break;
        default:
            break;
    }
    dissector_table_foreach(table_name, decode_proto_add_to_list, tree_info);

    g_free(tree_info);
}

static GtkWidget *
init_table(void)
{
    GtkTreeStore      *store;
    GtkWidget         *tree;
    GtkTreeView       *tree_view;
    GtkTreeViewColumn *column;
    GtkCellRenderer   *renderer;
    GtkTreeSortable   *sortable;

    /* Create the store */
    store = gtk_tree_store_new (N_COLUMNS,      /* Total number of columns */
                               G_TYPE_STRING,   /* Table              */
                               G_TYPE_STRING);  /* Table              */

    /* Create a view */
    tree = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));
    tree_view = GTK_TREE_VIEW(tree);
    sortable = GTK_TREE_SORTABLE(store);

    /* Speed up the list display */
    gtk_tree_view_set_fixed_height_mode(tree_view, TRUE);

    /* Setup the sortable columns */
    gtk_tree_view_set_headers_clickable(GTK_TREE_VIEW (tree), FALSE);

    /* The view now holds a reference.  We can get rid of our own reference */
    g_object_unref (G_OBJECT (store));

    /* Create the first column, associating the "text" attribute of the
     * cell_renderer to the first column of the model */
    renderer = gtk_cell_renderer_text_new ();
    column = gtk_tree_view_column_new_with_attributes ("UI name", renderer, "text", TABLE_UI_NAME_COL, NULL);
    gtk_tree_sortable_set_sort_func(sortable, TABLE_UI_NAME_COL,
                                    ui_sort_func, GINT_TO_POINTER(TABLE_UI_NAME_COL), NULL);
    gtk_tree_view_column_set_sort_column_id(column, TABLE_UI_NAME_COL);
    gtk_tree_view_column_set_resizable(column, TRUE);
    gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
    gtk_tree_view_column_set_min_width(column, 80);
    gtk_tree_view_column_set_fixed_width(column, 330);
    gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column);

    renderer = gtk_cell_renderer_text_new ();
    column = gtk_tree_view_column_new_with_attributes ("Short name", renderer, "text", TABLE_SHORT_NAME_COL, NULL);
    gtk_tree_sortable_set_sort_func(sortable, TABLE_SHORT_NAME_COL,
                                    ui_sort_func, GINT_TO_POINTER(TABLE_SHORT_NAME_COL), NULL);
    gtk_tree_view_column_set_sort_column_id(column, TABLE_SHORT_NAME_COL);
    gtk_tree_view_column_set_resizable(column, TRUE);
    gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
    gtk_tree_view_column_set_min_width(column, 80);
    gtk_tree_view_column_set_fixed_width(column, 100);
    gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column);

    return tree;

}

static void
dissector_tables_dlg_init(void)
{
    dissector_tables_trees_t dis_tbl_trees;
    GtkWidget       *vbox;
    GtkWidget       *hbox;
    GtkWidget       *main_nb;
    GtkWidget       *scrolled_window;
    GtkTreeSortable *sortable;
    GtkWidget       *temp_page, *tmp;

    dissector_tables_dlg_w = dlg_window_new("Dissector tables");  /* transient_for top_level */
    gtk_window_set_destroy_with_parent (GTK_WINDOW(dissector_tables_dlg_w), TRUE);
    gtk_window_set_default_size(GTK_WINDOW(dissector_tables_dlg_w), 700, 300);

    vbox=ws_gtk_box_new(GTK_ORIENTATION_VERTICAL, 3, FALSE);
    gtk_container_add(GTK_CONTAINER(dissector_tables_dlg_w), vbox);
    gtk_container_set_border_width(GTK_CONTAINER(vbox), 12);

    main_nb = gtk_notebook_new();
    gtk_box_pack_start(GTK_BOX(vbox), main_nb, TRUE, TRUE, 0);

    /* String tables */
    temp_page = ws_gtk_box_new(GTK_ORIENTATION_VERTICAL, 6, FALSE);
    tmp = gtk_label_new("String tables");
    gtk_widget_show(tmp);
    hbox =  ws_gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 3, FALSE);
    gtk_box_pack_start(GTK_BOX (hbox), tmp, TRUE, TRUE, 0);
    gtk_notebook_append_page(GTK_NOTEBOOK(main_nb), temp_page, hbox);

    scrolled_window = scrolled_window_new(NULL, NULL);
    dis_tbl_trees.str_tree_wgt = init_table();
    gtk_widget_show(dis_tbl_trees.str_tree_wgt);
    gtk_container_add(GTK_CONTAINER(scrolled_window), dis_tbl_trees.str_tree_wgt);
    gtk_box_pack_start(GTK_BOX(temp_page), scrolled_window, TRUE, TRUE, 0);
    gtk_widget_show(scrolled_window);

    /* uint tables */
    temp_page = ws_gtk_box_new(GTK_ORIENTATION_VERTICAL, 6, FALSE);
    tmp = gtk_label_new("Integer tables");
    gtk_widget_show(tmp);
    hbox = ws_gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 3, FALSE);
    gtk_box_pack_start(GTK_BOX (hbox), tmp, TRUE, TRUE, 0);
    gtk_notebook_append_page(GTK_NOTEBOOK(main_nb), temp_page, hbox);

    scrolled_window = scrolled_window_new(NULL, NULL);
    dis_tbl_trees.uint_tree_wgt = init_table();
    gtk_widget_show(dis_tbl_trees.uint_tree_wgt);
    gtk_container_add(GTK_CONTAINER(scrolled_window), dis_tbl_trees.uint_tree_wgt);
    gtk_box_pack_start(GTK_BOX(temp_page), scrolled_window, TRUE, TRUE, 0);
    gtk_widget_show(scrolled_window);

    /* custom tables */
    temp_page = ws_gtk_box_new(GTK_ORIENTATION_VERTICAL, 6, FALSE);
    tmp = gtk_label_new("Custom tables");
    gtk_widget_show(tmp);
    hbox = ws_gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 3, FALSE);
    gtk_box_pack_start(GTK_BOX (hbox), tmp, TRUE, TRUE, 0);
    gtk_notebook_append_page(GTK_NOTEBOOK(main_nb), temp_page, hbox);

    scrolled_window = scrolled_window_new(NULL, NULL);
    dis_tbl_trees.custom_tree_wgt = init_table();
    gtk_widget_show(dis_tbl_trees.custom_tree_wgt);
    gtk_container_add(GTK_CONTAINER(scrolled_window), dis_tbl_trees.custom_tree_wgt);
    gtk_box_pack_start(GTK_BOX(temp_page), scrolled_window, TRUE, TRUE, 0);
    gtk_widget_show(scrolled_window);

    /* heuristic tables */
    temp_page = ws_gtk_box_new(GTK_ORIENTATION_VERTICAL, 6, FALSE);
    tmp = gtk_label_new("Heuristic tables");
    gtk_widget_show(tmp);
    hbox = ws_gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 3, FALSE);
    gtk_box_pack_start(GTK_BOX(hbox), tmp, TRUE, TRUE, 0);
    gtk_notebook_append_page(GTK_NOTEBOOK(main_nb), temp_page, hbox);

    scrolled_window = scrolled_window_new(NULL, NULL);
    dis_tbl_trees.heuristic_tree_wgt = init_table();
    gtk_widget_show(dis_tbl_trees.heuristic_tree_wgt);
    gtk_container_add(GTK_CONTAINER(scrolled_window), dis_tbl_trees.heuristic_tree_wgt);
    gtk_box_pack_start(GTK_BOX(temp_page), scrolled_window, TRUE, TRUE, 0);
    gtk_widget_show(scrolled_window);

    /* We must display TOP LEVEL Widget before calling init_table() */
    gtk_widget_show_all(dissector_tables_dlg_w);
    g_signal_connect(dissector_tables_dlg_w, "destroy", G_CALLBACK(win_destroy_cb), NULL);

    /* Fill the table with data */
    dissector_all_tables_foreach_table(display_dissector_table_names, &dis_tbl_trees, NULL);

    dissector_all_heur_tables_foreach_table(display_heur_dissector_table_names, (gpointer)&dis_tbl_trees, NULL);

    sortable = GTK_TREE_SORTABLE(gtk_tree_view_get_model(GTK_TREE_VIEW(dis_tbl_trees.str_tree_wgt)));
    gtk_tree_sortable_set_sort_column_id(sortable, TABLE_UI_NAME_COL, GTK_SORT_ASCENDING);

    sortable = GTK_TREE_SORTABLE(gtk_tree_view_get_model(GTK_TREE_VIEW(dis_tbl_trees.uint_tree_wgt)));
    gtk_tree_sortable_set_sort_column_id(sortable, TABLE_UI_NAME_COL, GTK_SORT_ASCENDING);

    sortable = GTK_TREE_SORTABLE(gtk_tree_view_get_model(GTK_TREE_VIEW(dis_tbl_trees.custom_tree_wgt)));
    gtk_tree_sortable_set_sort_column_id(sortable, TABLE_UI_NAME_COL, GTK_SORT_ASCENDING);

    sortable = GTK_TREE_SORTABLE(gtk_tree_view_get_model(GTK_TREE_VIEW(dis_tbl_trees.heuristic_tree_wgt)));
    gtk_tree_sortable_set_sort_column_id(sortable, TABLE_UI_NAME_COL, GTK_SORT_ASCENDING);

}

void
dissector_tables_dlg_cb(GtkWidget *w _U_, gpointer d _U_)
{
    if (dissector_tables_dlg_w) {
        reactivate_window(dissector_tables_dlg_w);
    } else {
        dissector_tables_dlg_init();
    }
}

/*
 * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
 *
 * Local variables:
 * c-basic-offset: 4
 * tab-width: 8
 * indent-tabs-mode: nil
 * End:
 *
 * vi: set shiftwidth=4 tabstop=8 expandtab:
 * :indentSize=4:tabSize=8:noTabs=true:
 */