aff3936f9e48c7e4c6c8d75564fe465e9de7013f
[metze/wireshark/wip.git] / ui / gtk / dissector_tables_dlg.c
1 /* dissector_tables_dlg.c
2  * dissector_tables_dlg   2010 Anders Broman
3  *
4  * Wireshark - Network traffic analyzer
5  * By Gerald Combs <gerald@wireshark.org>
6  * Copyright 1998 Gerald Combs
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21  */
22
23 #include "config.h"
24
25 #include <string.h>
26
27
28 #include <epan/packet.h>
29
30 #include <gtk/gtk.h>
31 #include "ui/gtk/gui_utils.h"
32 #include "ui/gtk/dlg_utils.h"
33 #include "ui/gtk/dissector_tables_dlg.h"
34
35 static GtkWidget  *dissector_tables_dlg_w = NULL;
36
37 /* The columns */
38 enum
39 {
40     TABLE_UI_NAME_COL,
41     TABLE_SHORT_NAME_COL,
42     N_COLUMNS
43 };
44
45 static void
46 win_destroy_cb(GtkWindow *win _U_, gpointer data _U_)
47 {
48
49     if (dissector_tables_dlg_w != NULL) {
50         window_destroy(dissector_tables_dlg_w);
51         dissector_tables_dlg_w = NULL;
52     }
53
54
55 }
56
57 /*
58  * For a dissector table, put
59  * its short name and its
60  * descriptive name in the treeview.
61  */
62
63 struct dissector_tables_tree_info {
64     GtkWidget       *tree;
65     GtkTreeIter     iter;
66     GtkTreeIter     new_iter;
67 };
68
69 typedef struct dissector_tables_tree_info dissector_tables_tree_info_t;
70
71 static gint
72 ui_sort_func(GtkTreeModel *model,
73              GtkTreeIter  *a,
74              GtkTreeIter  *b,
75              gpointer      user_data)
76 {
77     gchar *stra, *strb;
78
79     /* The col to get data from is in userdata */
80     gint data_column = GPOINTER_TO_INT(user_data);
81
82     gtk_tree_model_get(model, a, data_column, &stra, -1);
83     gtk_tree_model_get(model, b, data_column, &strb, -1);
84
85     return strcmp(stra, strb);
86 }
87
88
89 /*
90  * Struct to hold the pointer to the trees
91  * for dissector tables.
92  */
93 struct dissector_tables_trees {
94     GtkWidget       *str_tree_wgt;
95     GtkWidget       *uint_tree_wgt;
96     GtkWidget       *custom_tree_wgt;
97     GtkWidget       *heuristic_tree_wgt;
98 };
99
100 typedef struct dissector_tables_trees dissector_tables_trees_t;
101
102 static void
103 proto_add_to_list(dissector_tables_tree_info_t *tree_info,
104                   GtkTreeStore *store,
105                   gchar        *str,
106                   const gchar  *proto_name)
107 {
108     gtk_tree_store_insert_with_values(store, &tree_info->new_iter, &tree_info->iter, G_MAXINT,
109                                       TABLE_UI_NAME_COL,    str,
110                                       TABLE_SHORT_NAME_COL, proto_name,
111                                       -1);
112 }
113
114 static void
115 decode_proto_add_to_list (const gchar *table_name _U_, ftenum_t selector_type,
116                           gpointer key, gpointer value, gpointer user_data)
117 {
118     GtkTreeStore       *store;
119     const gchar        *proto_name;
120     dtbl_entry_t       *dtbl_entry;
121     dissector_handle_t  handle;
122     guint32             port;
123     gchar              *str;
124     dissector_tables_tree_info_t *tree_info;
125
126     tree_info = (dissector_tables_tree_info_t *)user_data;
127     dtbl_entry = (dtbl_entry_t*)value;
128     handle = dtbl_entry_get_handle(dtbl_entry);
129     proto_name = dissector_handle_get_short_name(handle);
130
131     store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(tree_info->tree)));
132
133     switch (selector_type) {
134
135         case FT_UINT8:
136         case FT_UINT16:
137         case FT_UINT24:
138         case FT_UINT32:
139             port = GPOINTER_TO_UINT(key);
140             /* Hack: Use fixed width rj str so alpha sort (strcmp) will sort field numerically */
141             str = g_strdup_printf ("%10d", port);
142             proto_add_to_list(tree_info, store, str, proto_name);
143             g_free (str);
144             break;
145
146         case FT_STRING:
147         case FT_STRINGZ:
148         case FT_UINT_STRING:
149         case FT_STRINGZPAD:
150             str = (gchar*) key;
151             proto_add_to_list(tree_info, store, str, proto_name);
152             break;
153
154         case FT_BYTES:
155         case FT_GUID:
156             str = (gchar*)dissector_handle_get_dissector_name(handle);
157             if (str == NULL)
158             {
159                 str = (gchar*)"<Unknown>";
160             }
161             proto_add_to_list(tree_info, store, str, proto_name);
162             break;
163
164         default:
165             g_assert_not_reached();
166     }
167
168 }
169
170 static void
171 table_name_add_to_list(dissector_tables_tree_info_t  *tree_info,
172                        GtkWidget  *tree_view,
173                        const char *table_name,
174                        const char *ui_name)
175 {
176     GtkTreeStore *store;
177
178     tree_info->tree = tree_view;
179     store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(tree_view))); /* Get store */
180
181     gtk_tree_store_insert_with_values(store, &tree_info->iter, NULL, G_MAXINT,
182                                       TABLE_UI_NAME_COL,    ui_name,
183                                       TABLE_SHORT_NAME_COL, table_name,
184                                       -1);
185 }
186
187 static void
188 display_heur_dissector_table_entries(const char *table_name _U_,
189     struct heur_dtbl_entry *dtbl_entry, gpointer user_data)
190 {
191     dissector_tables_tree_info_t *tree_info  = (dissector_tables_tree_info_t*)user_data;
192     GtkTreeStore                 *store;
193
194     if (dtbl_entry->protocol) {
195
196         store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(tree_info->tree))); /* Get store */
197         proto_add_to_list(tree_info, store,
198                           (gchar *)proto_get_protocol_long_name(dtbl_entry->protocol),
199                           proto_get_protocol_short_name(dtbl_entry->protocol));
200     }else{
201         g_warning("no protocol info");
202     }
203
204
205 }
206
207 static void
208 display_heur_dissector_table_names(const char *table_name, struct heur_dissector_list *list, gpointer w)
209 {
210     dissector_tables_trees_t      *dis_tbl_trees;
211     dissector_tables_tree_info_t  *tree_info;
212
213     tree_info = g_new(dissector_tables_tree_info_t, 1);
214     dis_tbl_trees = (dissector_tables_trees_t*)w;
215
216     table_name_add_to_list(tree_info, dis_tbl_trees->heuristic_tree_wgt, "", table_name);
217
218     if (list) {
219         heur_dissector_table_foreach(table_name, display_heur_dissector_table_entries, tree_info);
220     }
221
222 }
223
224 static void
225 display_dissector_table_names(const char *table_name, const char *ui_name, void *w)
226 {
227     dissector_tables_trees_t      *dis_tbl_trees;
228     dissector_tables_tree_info_t  *tree_info;
229     ftenum_t                       selector_type = get_dissector_table_selector_type(table_name);
230
231     tree_info = g_new(dissector_tables_tree_info_t, 1);
232     dis_tbl_trees = (dissector_tables_trees_t*)w;
233
234     switch (selector_type) {
235         case FT_UINT8:
236         case FT_UINT16:
237         case FT_UINT24:
238         case FT_UINT32:
239             table_name_add_to_list(tree_info, dis_tbl_trees->uint_tree_wgt, table_name, ui_name);
240             break;
241         case FT_STRING:
242         case FT_STRINGZ:
243         case FT_UINT_STRING:
244         case FT_STRINGZPAD:
245             table_name_add_to_list(tree_info, dis_tbl_trees->str_tree_wgt, table_name, ui_name);
246             break;
247         case FT_BYTES:
248         case FT_GUID:
249             table_name_add_to_list(tree_info, dis_tbl_trees->custom_tree_wgt, table_name, ui_name);
250             break;
251         default:
252             break;
253     }
254     dissector_table_foreach(table_name, decode_proto_add_to_list, tree_info);
255
256     g_free(tree_info);
257 }
258
259 static GtkWidget *
260 init_table(void)
261 {
262     GtkTreeStore      *store;
263     GtkWidget         *tree;
264     GtkTreeView       *tree_view;
265     GtkTreeViewColumn *column;
266     GtkCellRenderer   *renderer;
267     GtkTreeSortable   *sortable;
268
269     /* Create the store */
270     store = gtk_tree_store_new (N_COLUMNS,      /* Total number of columns */
271                                G_TYPE_STRING,   /* Table              */
272                                G_TYPE_STRING);  /* Table              */
273
274     /* Create a view */
275     tree = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));
276     tree_view = GTK_TREE_VIEW(tree);
277     sortable = GTK_TREE_SORTABLE(store);
278
279     /* Speed up the list display */
280     gtk_tree_view_set_fixed_height_mode(tree_view, TRUE);
281
282     /* Setup the sortable columns */
283     gtk_tree_view_set_headers_clickable(GTK_TREE_VIEW (tree), FALSE);
284
285     /* The view now holds a reference.  We can get rid of our own reference */
286     g_object_unref (G_OBJECT (store));
287
288     /* Create the first column, associating the "text" attribute of the
289      * cell_renderer to the first column of the model */
290     renderer = gtk_cell_renderer_text_new ();
291     column = gtk_tree_view_column_new_with_attributes ("UI name", renderer, "text", TABLE_UI_NAME_COL, NULL);
292     gtk_tree_sortable_set_sort_func(sortable, TABLE_UI_NAME_COL,
293                                     ui_sort_func, GINT_TO_POINTER(TABLE_UI_NAME_COL), NULL);
294     gtk_tree_view_column_set_sort_column_id(column, TABLE_UI_NAME_COL);
295     gtk_tree_view_column_set_resizable(column, TRUE);
296     gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
297     gtk_tree_view_column_set_min_width(column, 80);
298     gtk_tree_view_column_set_fixed_width(column, 330);
299     gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column);
300
301     renderer = gtk_cell_renderer_text_new ();
302     column = gtk_tree_view_column_new_with_attributes ("Short name", renderer, "text", TABLE_SHORT_NAME_COL, NULL);
303     gtk_tree_sortable_set_sort_func(sortable, TABLE_SHORT_NAME_COL,
304                                     ui_sort_func, GINT_TO_POINTER(TABLE_SHORT_NAME_COL), NULL);
305     gtk_tree_view_column_set_sort_column_id(column, TABLE_SHORT_NAME_COL);
306     gtk_tree_view_column_set_resizable(column, TRUE);
307     gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
308     gtk_tree_view_column_set_min_width(column, 80);
309     gtk_tree_view_column_set_fixed_width(column, 100);
310     gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column);
311
312     return tree;
313
314 }
315
316 static void
317 dissector_tables_dlg_init(void)
318 {
319     dissector_tables_trees_t dis_tbl_trees;
320     GtkWidget       *vbox;
321     GtkWidget       *hbox;
322     GtkWidget       *main_nb;
323     GtkWidget       *scrolled_window;
324     GtkTreeSortable *sortable;
325     GtkWidget       *temp_page, *tmp;
326
327     dissector_tables_dlg_w = dlg_window_new("Dissector tables");  /* transient_for top_level */
328     gtk_window_set_destroy_with_parent (GTK_WINDOW(dissector_tables_dlg_w), TRUE);
329     gtk_window_set_default_size(GTK_WINDOW(dissector_tables_dlg_w), 700, 300);
330
331     vbox=ws_gtk_box_new(GTK_ORIENTATION_VERTICAL, 3, FALSE);
332     gtk_container_add(GTK_CONTAINER(dissector_tables_dlg_w), vbox);
333     gtk_container_set_border_width(GTK_CONTAINER(vbox), 12);
334
335     main_nb = gtk_notebook_new();
336     gtk_box_pack_start(GTK_BOX(vbox), main_nb, TRUE, TRUE, 0);
337
338     /* String tables */
339     temp_page = ws_gtk_box_new(GTK_ORIENTATION_VERTICAL, 6, FALSE);
340     tmp = gtk_label_new("String tables");
341     gtk_widget_show(tmp);
342     hbox =  ws_gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 3, FALSE);
343     gtk_box_pack_start(GTK_BOX (hbox), tmp, TRUE, TRUE, 0);
344     gtk_notebook_append_page(GTK_NOTEBOOK(main_nb), temp_page, hbox);
345
346     scrolled_window = scrolled_window_new(NULL, NULL);
347     dis_tbl_trees.str_tree_wgt = init_table();
348     gtk_widget_show(dis_tbl_trees.str_tree_wgt);
349     gtk_container_add(GTK_CONTAINER(scrolled_window), dis_tbl_trees.str_tree_wgt);
350     gtk_box_pack_start(GTK_BOX(temp_page), scrolled_window, TRUE, TRUE, 0);
351     gtk_widget_show(scrolled_window);
352
353     /* uint tables */
354     temp_page = ws_gtk_box_new(GTK_ORIENTATION_VERTICAL, 6, FALSE);
355     tmp = gtk_label_new("Integer tables");
356     gtk_widget_show(tmp);
357     hbox = ws_gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 3, FALSE);
358     gtk_box_pack_start(GTK_BOX (hbox), tmp, TRUE, TRUE, 0);
359     gtk_notebook_append_page(GTK_NOTEBOOK(main_nb), temp_page, hbox);
360
361     scrolled_window = scrolled_window_new(NULL, NULL);
362     dis_tbl_trees.uint_tree_wgt = init_table();
363     gtk_widget_show(dis_tbl_trees.uint_tree_wgt);
364     gtk_container_add(GTK_CONTAINER(scrolled_window), dis_tbl_trees.uint_tree_wgt);
365     gtk_box_pack_start(GTK_BOX(temp_page), scrolled_window, TRUE, TRUE, 0);
366     gtk_widget_show(scrolled_window);
367
368     /* custom tables */
369     temp_page = ws_gtk_box_new(GTK_ORIENTATION_VERTICAL, 6, FALSE);
370     tmp = gtk_label_new("Custom tables");
371     gtk_widget_show(tmp);
372     hbox = ws_gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 3, FALSE);
373     gtk_box_pack_start(GTK_BOX (hbox), tmp, TRUE, TRUE, 0);
374     gtk_notebook_append_page(GTK_NOTEBOOK(main_nb), temp_page, hbox);
375
376     scrolled_window = scrolled_window_new(NULL, NULL);
377     dis_tbl_trees.custom_tree_wgt = init_table();
378     gtk_widget_show(dis_tbl_trees.custom_tree_wgt);
379     gtk_container_add(GTK_CONTAINER(scrolled_window), dis_tbl_trees.custom_tree_wgt);
380     gtk_box_pack_start(GTK_BOX(temp_page), scrolled_window, TRUE, TRUE, 0);
381     gtk_widget_show(scrolled_window);
382
383     /* heuristic tables */
384     temp_page = ws_gtk_box_new(GTK_ORIENTATION_VERTICAL, 6, FALSE);
385     tmp = gtk_label_new("Heuristic tables");
386     gtk_widget_show(tmp);
387     hbox = ws_gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 3, FALSE);
388     gtk_box_pack_start(GTK_BOX(hbox), tmp, TRUE, TRUE, 0);
389     gtk_notebook_append_page(GTK_NOTEBOOK(main_nb), temp_page, hbox);
390
391     scrolled_window = scrolled_window_new(NULL, NULL);
392     dis_tbl_trees.heuristic_tree_wgt = init_table();
393     gtk_widget_show(dis_tbl_trees.heuristic_tree_wgt);
394     gtk_container_add(GTK_CONTAINER(scrolled_window), dis_tbl_trees.heuristic_tree_wgt);
395     gtk_box_pack_start(GTK_BOX(temp_page), scrolled_window, TRUE, TRUE, 0);
396     gtk_widget_show(scrolled_window);
397
398     /* We must display TOP LEVEL Widget before calling init_table() */
399     gtk_widget_show_all(dissector_tables_dlg_w);
400     g_signal_connect(dissector_tables_dlg_w, "destroy", G_CALLBACK(win_destroy_cb), NULL);
401
402     /* Fill the table with data */
403     dissector_all_tables_foreach_table(display_dissector_table_names, &dis_tbl_trees, NULL);
404
405     dissector_all_heur_tables_foreach_table(display_heur_dissector_table_names, (gpointer)&dis_tbl_trees, NULL);
406
407     sortable = GTK_TREE_SORTABLE(gtk_tree_view_get_model(GTK_TREE_VIEW(dis_tbl_trees.str_tree_wgt)));
408     gtk_tree_sortable_set_sort_column_id(sortable, TABLE_UI_NAME_COL, GTK_SORT_ASCENDING);
409
410     sortable = GTK_TREE_SORTABLE(gtk_tree_view_get_model(GTK_TREE_VIEW(dis_tbl_trees.uint_tree_wgt)));
411     gtk_tree_sortable_set_sort_column_id(sortable, TABLE_UI_NAME_COL, GTK_SORT_ASCENDING);
412
413     sortable = GTK_TREE_SORTABLE(gtk_tree_view_get_model(GTK_TREE_VIEW(dis_tbl_trees.custom_tree_wgt)));
414     gtk_tree_sortable_set_sort_column_id(sortable, TABLE_UI_NAME_COL, GTK_SORT_ASCENDING);
415
416     sortable = GTK_TREE_SORTABLE(gtk_tree_view_get_model(GTK_TREE_VIEW(dis_tbl_trees.heuristic_tree_wgt)));
417     gtk_tree_sortable_set_sort_column_id(sortable, TABLE_UI_NAME_COL, GTK_SORT_ASCENDING);
418
419 }
420
421 void
422 dissector_tables_dlg_cb(GtkWidget *w _U_, gpointer d _U_)
423 {
424     if (dissector_tables_dlg_w) {
425         reactivate_window(dissector_tables_dlg_w);
426     } else {
427         dissector_tables_dlg_init();
428     }
429 }
430
431 /*
432  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
433  *
434  * Local variables:
435  * c-basic-offset: 4
436  * tab-width: 8
437  * indent-tabs-mode: nil
438  * End:
439  *
440  * vi: set shiftwidth=4 tabstop=8 expandtab:
441  * :indentSize=4:tabSize=8:noTabs=true:
442  */