5 * Routines to modify dissector tables on the fly.
7 * By David Hampton <dhampton@mac.com>
8 * Copyright 2001 David Hampton
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 #include <gdk/gdkkeysyms.h>
28 #if GTK_CHECK_VERSION(3,0,0)
29 # include <gdk/gdkkeysyms-compat.h>
32 #include <epan/packet.h>
33 #include <epan/epan_dissect.h>
34 #include <epan/decode_as.h>
35 #include <epan/dissectors/packet-dcerpc.h>
37 #include "ui/decode_as_utils.h"
38 #include "ui/simple_dialog.h"
39 #include "ui/utf8_entities.h"
41 #include "ui/gtk/main.h"
42 #include "ui/gtk/decode_as_dlg.h"
43 #include "ui/gtk/dlg_utils.h"
44 #include "ui/gtk/gui_utils.h"
45 #include "ui/gtk/help_dlg.h"
46 #include "ui/gtk/old-gtk-compat.h"
47 #include "ui/gtk/packet_win.h"
51 /**************************************************/
52 /* Typedefs & Enums */
53 /**************************************************/
55 #define E_DECODE_MIN_HEIGHT 300
56 #define E_NOTEBOOK "notebook"
58 #define E_COMBO_BOX_MULTIVALUE "combo_box_multivalue"
60 #define E_PAGE_DECODE_AS_DATA "decode_as_data"
63 * Columns for a "Display" list
65 #define E_LIST_D_TABLE 0
66 #define E_LIST_D_SELECTOR 1
67 #define E_LIST_D_INITIAL 2
68 #define E_LIST_D_CURRENT 3
69 #define E_LIST_D_MAX E_LIST_D_CURRENT
70 #define E_LIST_D_COLUMNS (E_LIST_D_MAX + 1)
73 * Columns for a "Select" list.
74 * Note that most of these columns aren't displayed; they're attached
75 * to the row of the table as additional information.
77 #define E_LIST_S_PROTO_NAME 0
78 #define E_LIST_S_TABLE 1
79 /* The following is for debugging in decode_add_to_list */
80 #define E_LIST_S_MAX E_LIST_S_TABLE
81 #define E_LIST_S_COLUMNS (E_LIST_S_MAX + 1)
83 #define E_PAGE_LIST "notebook_page_list"
84 #define E_PAGE_TABLE "notebook_page_table_name"
85 #define E_PAGE_TITLE "notebook_page_title"
86 #define E_PAGE_VALUE "notebook_page_value"
88 #define E_PAGE_ACTION "notebook_page_action"
90 /**************************************************/
91 /* File Global Variables */
92 /**************************************************/
95 * Keep a static pointer to the current "Decode As" window. This is
96 * kept so that if somebody tries to do "Tools:Decode As" while
97 * there's already a "Decode As" window up, we just pop up the
98 * existing one, rather than creating a new one.
100 static GtkWidget *decode_w = NULL;
103 * A static pointer to the current "Decode As:Show" window. This is
104 * kept so that if somebody tries to do clock the "Show Current"
105 * button or select the "Display:User Specified Decodes" menu item
106 * while there's already a "Decode As:Show" window up, we just pop up
107 * the existing one, rather than creating a new one.
109 static GtkWidget *decode_show_w = NULL;
112 * A list of the dialog items that only have meaning when the user has
113 * selected the "Decode" radio button. When the "Do not decode"
114 * button is selected these items should be dimmed.
116 GSList *decode_dimmable = NULL;
119 * Remember the "action" radio button that is currently selected in
120 * the dialog. This value is initialized when the dialog is created,
121 * modified in a callback routine, and read in the routine that
122 * handles a click in the "OK" button for the dialog.
124 enum action_type requested_action = (enum action_type)-1;
127 /**************************************************/
128 /* Global Functions */
129 /**************************************************/
131 /**************************************************/
132 /* Saving "Decode As" */
133 /**************************************************/
136 * Data structure to hold information of the "Decode As" entry.
146 * A typedef for the "Decode As" entry.
148 typedef struct da_entry da_entry_t;
151 * Container that holds the entries of the "Decode As"
153 GSList *da_entries = NULL;
156 * Save entries into preferences.
159 write_da_entry(gpointer item, gpointer user_data)
161 da_entry_t *entry = (da_entry_t *)item;
162 FILE *daf = (FILE *)user_data;
163 gchar *selector_str = g_strdup_printf("%d", entry->selector);
165 decode_as_write_entry(daf, entry->table, selector_str, entry->initial, entry->current);
166 g_free(selector_str);
170 * Free memory used by the da_entry
173 free_da_entry(gpointer item, gpointer user_data _U_)
175 da_entry_t *entry = (da_entry_t *)item;
176 g_free(entry->table);
177 g_free(entry->initial);
178 g_free(entry->current);
182 /**************************************************/
183 /* Show Changed Dissectors */
184 /**************************************************/
186 #define SORT_ALPHABETICAL 0
189 sort_iter_compare_func (GtkTreeModel *model,
194 gint sortcol = GPOINTER_TO_INT(user_data);
198 case SORT_ALPHABETICAL:
200 gchar *name1, *name2;
201 gtk_tree_model_get(model, a, 0, &name1, -1);
202 gtk_tree_model_get(model, b, 0, &name2, -1);
203 if (name1 == NULL || name2 == NULL)
205 if (name1 == NULL && name2 == NULL)
206 break; /* both equal => ret = 0 */
207 ret = (name1 == NULL) ? -1 : 1;
211 ret = g_ascii_strcasecmp(name1,name2);
218 g_return_val_if_reached(0);
225 decode_add_to_show_list (gpointer list_data,
226 const gchar *table_name,
227 gchar *selector_name,
228 const gchar *initial_proto_name,
229 const gchar *current_proto_name)
231 const gchar *text[E_LIST_D_COLUMNS];
235 store = (GtkListStore *)list_data;
237 text[E_LIST_D_TABLE] = table_name;
238 text[E_LIST_D_SELECTOR] = selector_name;
239 text[E_LIST_D_INITIAL] = initial_proto_name;
240 text[E_LIST_D_CURRENT] = current_proto_name;
241 gtk_list_store_append(store, &iter);
242 gtk_list_store_set(store, &iter, E_LIST_D_TABLE, text[E_LIST_D_TABLE],
243 E_LIST_D_SELECTOR, text[E_LIST_D_SELECTOR],
244 E_LIST_D_INITIAL, text[E_LIST_D_INITIAL],
245 E_LIST_D_CURRENT, text[E_LIST_D_CURRENT], -1);
250 * This routine creates one entry in the list of protocol dissector
251 * that have been changed. It is called by the g_hash_foreach routine
252 * once for each changed entry in a dissector table.
254 * @param table_name The table name in which this dissector is found.
256 * @param key A pointer to the key for this entry in the dissector
257 * hash table. This is generally the numeric selector of the
258 * protocol, i.e. the ethernet type code, IP port number, TCP port
261 * @param value A pointer to the value for this entry in the dissector
262 * hash table. This is an opaque pointer that can only be handed back
263 * to routine in the file packet.c
265 * @param user_data A pointer to the list in which this information
269 decode_build_show_list (const gchar *table_name, ftenum_t selector_type,
270 gpointer key, gpointer value, gpointer user_data)
272 dissector_handle_t current, initial;
273 const gchar *current_proto_name, *initial_proto_name;
274 gchar *selector_name;
278 entry = g_new(da_entry_t,1);
283 current = dtbl_entry_get_handle((dtbl_entry_t *)value);
285 current_proto_name = DECODE_AS_NONE;
287 current_proto_name = dissector_handle_get_short_name(current);
288 initial = dtbl_entry_get_initial_handle((dtbl_entry_t *)value);
290 initial_proto_name = DECODE_AS_NONE;
292 initial_proto_name = dissector_handle_get_short_name(initial);
294 switch (selector_type) {
300 switch (get_dissector_table_base(table_name)) {
303 g_snprintf(string1, sizeof(string1), "%u", GPOINTER_TO_UINT(key));
307 switch (get_dissector_table_selector_type(table_name)) {
310 g_snprintf(string1, sizeof(string1), "0x%02x", GPOINTER_TO_UINT(key));
314 g_snprintf(string1, sizeof(string1), "0x%04x", GPOINTER_TO_UINT(key));
318 g_snprintf(string1, sizeof(string1), "0x%06x", GPOINTER_TO_UINT(key));
322 g_snprintf(string1, sizeof(string1), "0x%08x", GPOINTER_TO_UINT(key));
326 g_assert_not_reached();
332 g_snprintf(string1, sizeof(string1), "%#o", GPOINTER_TO_UINT(key));
335 selector_name = string1;
340 selector_name = (gchar *)key;
344 g_assert_not_reached();
345 selector_name = NULL;
349 decode_add_to_show_list (
351 get_dissector_table_ui_name(table_name),
356 entry->table = g_strdup(table_name);
357 entry->selector = GPOINTER_TO_UINT(key);
358 entry->initial = g_strdup(initial_proto_name);
359 entry->current = g_strdup(current_proto_name);
360 da_entries = g_slist_append(da_entries, entry);
365 * This routine is called when the user clicks the "OK" button in
366 * the "Decode As:Show..." dialog window. This routine destroys the
367 * dialog box and performs other housekeeping functions.
369 * @param ok_bt A pointer to the "OK" button.
371 * @param parent_w A pointer to the dialog window.
374 decode_show_ok_cb (GtkWidget *ok_bt _U_, gpointer parent_w)
376 window_destroy(GTK_WIDGET(parent_w));
381 * This routine is called when the user clicks the "Clear" button in
382 * the "Decode As:Show..." dialog window. This routine resets all the
383 * dissector values and then destroys the dialog box and performs
384 * other housekeeping functions.
386 * @param clear_bt A pointer to the "Clear" button.
388 * @param parent_w A pointer to the dialog window.
391 decode_show_clear_cb (GtkWidget *clear_bt _U_, gpointer parent_w)
395 redissect_all_packet_windows();
397 window_destroy(GTK_WIDGET(parent_w));
399 decode_show_cb(NULL, NULL);
404 * This routine is called when the user clicks the X at the top right end in
405 * the "Decode As:Show..." dialog window. This routine simply calls the
406 * ok routine as if the user had clicked the ok button.
408 * @param win A pointer to the dialog box.
410 * @param event A pointer to the event struct
412 * @param user_data Unused
415 decode_show_delete_cb (GtkWidget *win _U_, GdkEvent *event _U_, gpointer user_data _U_)
417 decode_show_ok_cb(NULL, decode_show_w);
423 * This routine is called at the destruction of the "Decode As:Show"
424 * dialog box. It clears the pointer maintained by this file, so that
425 * the next time the user clicks the "Decode As:Show" button a new
426 * dialog box will be created.
428 * @param win A pointer to the dialog box.
430 * @param user_data Unused
433 decode_show_destroy_cb (GtkWidget *win _U_, gpointer user_data _U_)
435 /* Note that we no longer have a "Decode As:Show" dialog box. */
436 decode_show_w = NULL;
438 /* Clear saved "Decode As" entries. */
439 g_slist_foreach(da_entries, free_da_entry, NULL);
440 g_slist_free(da_entries);
446 * This routine saves the current "Decode As"-entries into the
451 * @param user_data Unused
454 decode_show_save_cb (GtkWidget *win _U_, gpointer user_data _U_)
456 FILE *daf = decode_as_open();
460 g_slist_foreach(da_entries, write_da_entry, daf);
465 /* add a single binding to the Show list */
467 decode_dcerpc_add_show_list_single(gpointer data, gpointer user_data)
472 decode_dcerpc_bind_values_t *binding = (decode_dcerpc_bind_values_t *)data;
474 g_snprintf(string1, sizeof(string1), "ctx_id: %u", binding->ctx_id);
476 decode_add_to_show_list (
481 binding->ifname->str);
485 * This routine creates the "Decode As:Show" dialog box. This dialog box
486 * shows the user which protocols have had their dissectors changed.
490 * @param user_data Unused
493 decode_show_cb (GtkWidget *w _U_, gpointer user_data _U_)
495 GtkWidget *main_vb, *bbox, *ok_bt, *clear_bt, *save_bt, *help_bt, *scrolled_window;
496 const gchar *titles[E_LIST_D_COLUMNS] = {
497 "Table", "Value", "Initial", "Current"
502 GtkCellRenderer *renderer;
503 GtkTreeViewColumn *tc;
506 if (decode_show_w != NULL) {
507 /* There's already a "Decode As" dialog box; reactivate it. */
508 reactivate_window(decode_show_w);
512 decode_show_w = dlg_window_new("Wireshark: Decode As: Show");
513 /* Provide a minimum of a couple of rows worth of data */
514 gtk_window_set_default_size(GTK_WINDOW(decode_show_w), -1, E_DECODE_MIN_HEIGHT);
516 /* Container for each row of widgets */
517 main_vb = ws_gtk_box_new(GTK_ORIENTATION_VERTICAL, 2, FALSE);
518 gtk_container_set_border_width(GTK_CONTAINER(main_vb), 5);
519 gtk_container_add(GTK_CONTAINER(decode_show_w), main_vb);
521 /* Initialize list */
522 store = gtk_list_store_new(E_LIST_D_COLUMNS, G_TYPE_STRING,
523 G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
524 list = GTK_TREE_VIEW(tree_view_new(GTK_TREE_MODEL(store)));
525 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(list), TRUE);
526 gtk_tree_view_set_headers_clickable(GTK_TREE_VIEW(list), FALSE);
527 gtk_tree_selection_set_mode(gtk_tree_view_get_selection(list),
530 for (column = 0; column < E_LIST_D_COLUMNS; column++) {
531 renderer = gtk_cell_renderer_text_new();
532 tc = gtk_tree_view_column_new_with_attributes(titles[column],
535 gtk_tree_view_column_set_sizing(tc, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
536 gtk_tree_view_column_set_resizable(tc, TRUE);
537 gtk_tree_view_append_column(list, tc);
541 dissector_all_tables_foreach_changed(decode_build_show_list, store);
542 g_object_unref(G_OBJECT(store));
543 decode_dcerpc_add_show_list(decode_dcerpc_add_show_list_single, store);
545 /* Put list into a scrolled window */
546 scrolled_window = scrolled_window_new(NULL, NULL);
547 /* this will result to set the width of the dialog to the required size */
548 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
549 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
550 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled_window),
552 gtk_container_add(GTK_CONTAINER(scrolled_window),
554 gtk_box_pack_start(GTK_BOX(main_vb), scrolled_window, TRUE, TRUE, 0);
557 bbox = dlg_button_row_new(GTK_STOCK_OK, GTK_STOCK_CLEAR, GTK_STOCK_SAVE, GTK_STOCK_HELP, NULL);
558 gtk_box_pack_start(GTK_BOX(main_vb), bbox, FALSE, FALSE, 0);
559 gtk_widget_show(bbox);
561 ok_bt = (GtkWidget *)g_object_get_data(G_OBJECT(bbox), GTK_STOCK_OK);
562 g_signal_connect(ok_bt, "clicked", G_CALLBACK(decode_show_ok_cb), decode_show_w);
564 clear_bt = (GtkWidget *)g_object_get_data(G_OBJECT(bbox), GTK_STOCK_CLEAR);
565 g_signal_connect(clear_bt, "clicked", G_CALLBACK(decode_show_clear_cb), decode_show_w);
567 save_bt = (GtkWidget *)g_object_get_data(G_OBJECT(bbox), GTK_STOCK_SAVE);
568 g_signal_connect(save_bt, "clicked", G_CALLBACK(decode_show_save_cb), decode_show_w);
570 help_bt =(GtkWidget *) g_object_get_data(G_OBJECT(bbox), GTK_STOCK_HELP);
571 g_signal_connect(help_bt, "clicked", G_CALLBACK(topic_cb), (gpointer)HELP_DECODE_AS_SHOW_DIALOG);
573 /* set ok as default, this button won't change anything */
574 window_set_cancel_button(decode_show_w, ok_bt, NULL);
576 g_signal_connect(decode_show_w, "delete_event", G_CALLBACK(decode_show_delete_cb), NULL);
577 g_signal_connect(decode_show_w, "destroy", G_CALLBACK(decode_show_destroy_cb), NULL);
579 gtk_widget_set_sensitive(clear_bt,
580 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter));
582 gtk_widget_show_all(decode_show_w);
583 window_present(decode_show_w);
587 /**************************************************/
588 /* Modify the dissector routines */
589 /**************************************************/
592 /**************************************************/
593 /* Action routines for the "Decode As..." dialog */
594 /* - called when the OK button pressed */
595 /* - one per notebook page */
596 /**************************************************/
601 * Print debugging information about tree view selection. Extract all
602 * information from the tree view entry that was selected and print it to
605 * @param tree_view The tree view to dump.
607 * @param leadin A string to print at the start of each line.
610 decode_debug (GtkTreeView *tree_view, gchar *leadin)
613 GtkTreeSelection *selection;
615 char *string, *text[E_LIST_S_COLUMNS];
616 dissector_handle_t handle;
618 selection = gtk_tree_view_get_selection(tree_view);
620 if (gtk_tree_selection_get_selected(selection, NULL, &iter)){
621 store = GTK_LIST_STORE(gtk_tree_view_get_model(tree_view));
622 gtk_tree_model_get(GTK_TREE_MODEL(store), &iter,
623 E_LIST_S_PROTO_NAME, &text[E_LIST_S_PROTO_NAME],
624 E_LIST_S_TABLE, &text[E_LIST_S_TABLE],
625 E_LIST_S_TABLE+1, &handle,
627 string = g_strdup_printf("%s list: <put handle here>, name %s, table %s",
628 leadin, text[E_LIST_S_PROTO_NAME],
629 text[E_LIST_S_TABLE]);
631 string = g_strdup_printf("%s list row (none), aka do not decode", leadin);
633 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK, string);
640 * This routine is called when the user clicks the "OK" button in the
641 * "Decode As..." dialog window and a 'simple' page is foremost.
642 * This routine takes care of making any changes requested to the
643 * dissector tables. This routine is currently used for IP and
644 * Ethertypes. Any 'single change' notebook page can use this
647 * @param notebook_pg A pointer to the "network" notebook page.
650 decode_simple (GtkWidget *notebook_pg)
652 GtkWidget *list, *combo_box;
653 GtkTreeSelection *selection;
657 gchar *table_name, *abbrev;
658 dissector_handle_t handle;
659 guint value_loop, *selector_type;
660 gpointer ptr, value_ptr;
661 gint requested_index = 0;
662 gboolean add_reset_list = FALSE;
664 list = (GtkWidget *)g_object_get_data(G_OBJECT(notebook_pg), E_PAGE_LIST);
665 if (requested_action == E_DECODE_NO)
666 gtk_tree_selection_unselect_all(gtk_tree_view_get_selection(GTK_TREE_VIEW(list)));
668 entry = (decode_as_t *)g_object_get_data(G_OBJECT(notebook_pg), E_PAGE_DECODE_AS_DATA);
669 table_name = (gchar *)g_object_get_data(G_OBJECT(notebook_pg), E_PAGE_TABLE);
671 /* (sub)dissector selection */
672 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(list));
673 if (gtk_tree_selection_get_selected(selection, &model, &iter) == FALSE)
678 gtk_tree_model_get(model, &iter, E_LIST_S_PROTO_NAME, &abbrev,
679 E_LIST_S_TABLE+1, &handle, -1);
682 if (entry->num_items > 1)
684 combo_box = (GtkWidget *)g_object_get_data(G_OBJECT(notebook_pg), E_COMBO_BOX_MULTIVALUE);
685 if (!ws_combo_box_get_active_pointer(GTK_COMBO_BOX(combo_box), &ptr))
686 g_assert_not_reached(); /* Programming error if no active item in combo_box */
687 requested_index = GPOINTER_TO_INT(ptr);
690 /* Apply values to dissector table (stored in entry) */
691 for (value_loop = 0; value_loop < entry->values[requested_index].num_values; value_loop++)
693 value_ptr = entry->values[requested_index].build_values[value_loop](&cfile.edt->pi);
694 if (abbrev != NULL && strcmp(abbrev, "(default)") == 0) {
695 add_reset_list = entry->reset_value(table_name, value_ptr);
697 add_reset_list = entry->change_value(table_name, value_ptr, &handle, abbrev);
700 if (add_reset_list) {
701 selector_type = g_new(guint,1);
702 *selector_type = GPOINTER_TO_UINT(value_ptr);
703 decode_build_reset_list(g_strdup(table_name), FT_UINT32, selector_type, NULL, NULL);
711 /**************************************************/
712 /* Signals from the "Decode As..." dialog */
713 /**************************************************/
716 * This routine is called when the user clicks the "OK" button in the
717 * "Decode As..." dialog window. This routine calls various helper
718 * routines to set/clear dissector values as requested by the user.
719 * These routines accumulate information on what actions they have
720 * taken, and this summary information is printed by this routine.
721 * This routine then destroys the dialog box and performs other
722 * housekeeping functions.
724 * @param ok_bt A pointer to the "OK" button.
726 * @param parent_w A pointer to the dialog window.
729 decode_ok_cb (GtkWidget *ok_bt _U_, gpointer parent_w)
731 GtkWidget *notebook, *notebook_pg;
732 void (* func)(GtkWidget *);
736 /* Call the right routine for the page that was currently in front. */
737 notebook = (GtkWidget *)g_object_get_data(G_OBJECT(parent_w), E_NOTEBOOK);
738 page_num = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
739 notebook_pg = gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook), page_num);
741 func = (void (*)(GtkWidget *))g_object_get_data(G_OBJECT(notebook_pg), E_PAGE_ACTION);
744 /* Free any values that used dynamic memory */
745 entry = (decode_as_t *)g_object_get_data(G_OBJECT(notebook_pg), E_PAGE_DECODE_AS_DATA);
746 if ((entry->num_items == 1) && (entry->free_func != NULL))
747 entry->free_func(g_object_get_data(G_OBJECT(notebook_pg), E_PAGE_VALUE));
749 window_destroy(GTK_WIDGET(parent_w));
750 g_slist_free(decode_dimmable);
751 decode_dimmable = NULL;
754 redissect_all_packet_windows();
758 * This routine is called when the user clicks the "Apply" button in the
759 * "Decode As..." dialog window. This routine calls various helper
760 * routines to set/clear dissector values as requested by the user.
761 * These routines accumulate information on what actions they have
762 * taken, and this summary information is printed by this routine.
764 * @param apply_bt A pointer to the "Apply" button.
766 * @param parent_w A pointer to the dialog window.
769 decode_apply_cb (GtkWidget *apply_bt _U_, gpointer parent_w)
771 GtkWidget *notebook, *notebook_pg;
772 void (* func)(GtkWidget *);
775 /* Call the right routine for the page that was currently in front. */
776 notebook = (GtkWidget *)g_object_get_data(G_OBJECT(parent_w), E_NOTEBOOK);
777 page_num = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
778 notebook_pg = gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook), page_num);
780 func = (void (*)(GtkWidget *))g_object_get_data(G_OBJECT(notebook_pg), E_PAGE_ACTION);
784 redissect_all_packet_windows();
788 * This routine is called when the user clicks the "Close" button in
789 * the "Decode As..." dialog window. This routine then destroys the
790 * dialog box and performs other housekeeping functions.
792 * @param close_bt A pointer to the "Close" button.
794 * @param parent_w A pointer to the dialog window.
797 decode_close_cb (GtkWidget *close_bt _U_, gpointer parent_w)
799 GtkWidget *notebook, *notebook_pg;
803 /* Call the right routine for the page that was currently in front. */
804 notebook = (GtkWidget *)g_object_get_data(G_OBJECT(parent_w), E_NOTEBOOK);
805 page_num = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
806 notebook_pg = gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook), page_num);
808 /* Free any values that used dynamic memory */
809 entry = (decode_as_t *)g_object_get_data(G_OBJECT(notebook_pg), E_PAGE_DECODE_AS_DATA);
810 if ((entry->num_items == 1) && (entry->free_func != NULL))
811 entry->free_func(g_object_get_data(G_OBJECT(notebook_pg), E_PAGE_VALUE));
813 window_destroy(GTK_WIDGET(parent_w));
814 g_slist_free(decode_dimmable);
815 decode_dimmable = NULL;
820 * This routine is called when the user clicks the "Close" button in
821 * the "Decode As..." dialog window. This routine simply calls the
822 * close routine as if the user had clicked the close button instead
823 * of the close button.
825 * @param decode_w_lcl A pointer to the dialog box.
827 * @param event A pointer to the GdkEvent struct
829 * @param user_data Unused
832 decode_delete_cb (GtkWidget *decode_w_lcl, GdkEvent *event _U_, gpointer user_data _U_)
834 decode_close_cb(NULL, decode_w_lcl);
840 * This routine is called at the destruction of the "Decode As..."
841 * dialog box. It clears the pointer maintained by this file, so that
842 * the next time the user selects the "Decode As..." menu item a new
843 * dialog box will be created.
845 * @param win A pointer to the dialog box.
847 * @param user_data Unused
852 decode_destroy_cb (GtkWidget *win _U_, gpointer user_data _U_)
854 /* Note that we no longer have a "Decode As" dialog box. */
860 * This routine is called when the user clicks the "Clear" button in
861 * the "Decode As..." dialog window. This routine resets all the
862 * dissector values and performs other housekeeping functions.
864 * @param clear_bt A pointer to the "Clear" button.
866 * @param user_data Unused
869 decode_clear_cb(GtkWidget *clear_bt _U_, gpointer user_data _U_)
873 redissect_all_packet_windows();
878 /**************************************************/
879 /* Dialog setup - radio buttons */
880 /**************************************************/
883 * Update the requested action field of the dialog. This routine is
884 * called by GTK when either of the two radio buttons in the dialog is
887 * @param w The radio button that was clicked.
889 * @param user_data The enum value assigned to this radio button. This
890 * will be either E_DECODE_YES or E_DECODE_NO
893 decode_update_action (GtkWidget *w _U_, gpointer user_data)
898 requested_action = (enum action_type)GPOINTER_TO_INT(user_data);
899 enable = (requested_action == E_DECODE_YES);
900 for (tmp = decode_dimmable; tmp; tmp = g_slist_next(tmp)) {
901 gtk_widget_set_sensitive((GtkWidget *)tmp->data, enable);
906 * This routine is called to create the "Decode" and "Do not decode"
907 * radio buttons. These buttons are installed into a vbox, and set up
910 * @return GtkWidget * A pointer to the vbox containing the buttons
913 decode_add_yes_no (void)
915 GtkWidget *format_vb, *radio_button;
918 format_vb = ws_gtk_box_new(GTK_ORIENTATION_VERTICAL, 2, FALSE);
920 radio_button = gtk_radio_button_new_with_label(NULL, "Decode");
921 format_grp = gtk_radio_button_get_group(GTK_RADIO_BUTTON(radio_button));
922 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio_button), TRUE);
923 g_signal_connect(radio_button, "clicked", G_CALLBACK(decode_update_action),
924 GINT_TO_POINTER(E_DECODE_YES));
925 gtk_box_pack_start(GTK_BOX(format_vb), radio_button, FALSE, FALSE, 0);
927 radio_button = gtk_radio_button_new_with_label(format_grp, "Do not decode");
928 g_signal_connect(radio_button, "clicked", G_CALLBACK(decode_update_action),
929 GINT_TO_POINTER(E_DECODE_NO));
930 gtk_box_pack_start(GTK_BOX(format_vb), radio_button, FALSE, FALSE, 0);
935 /**************************************************/
936 /* Dialog setup - simple combo_boxes */
937 /**************************************************/
940 * This routine is called to pack an combo_box into an aligment, so
941 * that it doesn't expand vertically to fill up the space available to
944 * @param combo_box A pointer to the option menu to be so packed.
946 * @return GtkWidget * A pointer to the newly created alignment.
949 decode_add_pack_combo_box (GtkWidget *combo_box)
951 GtkWidget *alignment;
953 alignment = gtk_alignment_new(0.0f, 0.5f, 0.0f, 0.0f);
954 gtk_container_add(GTK_CONTAINER(alignment), combo_box);
961 * This routine is called to add a selection combo_box to
962 * the dialog box. The combo_box choices are determined by the dissector.
963 * The default choice for the combo_box is also determined by the dissector.
965 * @param page A pointer notebook page that will contain all
966 * widgets created by this routine.
967 * @param entry Decode As structure used to setup combo_box
969 * @return GtkWidget * A pointer to the newly created alignment into
970 * which we've packed the newly created combo_box.
973 decode_add_multivalue_combo_box (GtkWidget *page, decode_as_t *entry)
975 GtkWidget *combo_box, *alignment;
977 gchar prompt[MAX_DECODE_AS_PROMPT_LEN];
979 combo_box = ws_combo_box_new_text_and_pointer();
981 for (value = 0; value < entry->num_items; value++)
983 entry->values[value].label_func(&cfile.edt->pi, prompt);
984 ws_combo_box_append_text_and_pointer(GTK_COMBO_BOX(combo_box), prompt, GINT_TO_POINTER(value));
987 ws_combo_box_set_active(GTK_COMBO_BOX(combo_box), entry->default_index_value);
988 g_object_set_data(G_OBJECT(page), E_COMBO_BOX_MULTIVALUE, combo_box);
990 alignment = decode_add_pack_combo_box(combo_box);
994 /*************************************************/
995 /* Dialog setup - list based menus */
996 /*************************************************/
998 struct handle_lookup_info {
999 dissector_handle_t handle;
1004 lookup_handle(GtkTreeModel *model, GtkTreePath *path _U_, GtkTreeIter *iter,
1007 dissector_handle_t handle;
1008 struct handle_lookup_info *hli = (struct handle_lookup_info *)user_data;
1010 gtk_tree_model_get(model, iter, E_LIST_S_TABLE+1, &handle, -1);
1011 if (hli->handle == handle) {
1019 * This routine creates one entry in the list of protocol dissector
1020 * that can be used. It is called by the dissector_table_foreach_handle
1021 * routine once for each entry in a dissector table's list of handles
1022 * for dissectors that could be used in that table. It guarantees unique
1023 * entries by iterating over the list of entries build up to this point,
1024 * looking for a duplicate name. If there is no duplicate, then this
1025 * entry is added to the list of possible dissectors.
1027 * @param table_name The name of the dissector table currently
1030 * @param proto_name The protocol name
1032 * @param value The dissector handle for this entry. This is an opaque
1033 * pointer that can only be handed back to routines in the file packet.c
1035 * @param user_data A data block passed into each instance of this
1036 * routine. It contains information from the caller of the foreach
1037 * routine, specifying information about the dissector table and where
1038 * to store any information generated by this routine.
1041 decode_add_to_list (const gchar *table_name, const gchar *proto_name, gpointer value, gpointer user_data)
1043 const gchar *text[E_LIST_S_COLUMNS];
1045 GtkListStore *store;
1047 struct handle_lookup_info hli;
1049 g_assert(user_data);
1052 list = (GtkTreeView *)user_data;
1054 hli.handle = (dissector_handle_t)value;
1056 store = GTK_LIST_STORE(gtk_tree_view_get_model(list));
1057 gtk_tree_model_foreach(GTK_TREE_MODEL(store), lookup_handle, &hli);
1058 /* We already have an entry for this handle.
1059 * XXX - will this ever happen? */
1060 if (hli.found) return;
1062 text[E_LIST_S_PROTO_NAME] = proto_name;
1063 text[E_LIST_S_TABLE] = table_name;
1064 gtk_list_store_append(store, &iter);
1065 gtk_list_store_set(store, &iter,
1066 E_LIST_S_PROTO_NAME, text[E_LIST_S_PROTO_NAME],
1067 E_LIST_S_TABLE, text[E_LIST_S_TABLE],
1068 E_LIST_S_TABLE+1, value, -1);
1072 decode_list_button_press_cb(GtkWidget *list, GdkEventButton *event, gpointer user_data _U_)
1074 if (event->type == GDK_2BUTTON_PRESS) {
1075 GtkWidget *main_w = gtk_widget_get_toplevel(list);
1077 decode_ok_cb (NULL, main_w);
1084 decode_list_key_release_cb(GtkWidget *list, GdkEventKey *event, gpointer user_data _U_)
1086 if (event->keyval == GDK_Return || event->keyval == GDK_KP_Enter) {
1087 GtkWidget *main_w = gtk_widget_get_toplevel(list);
1089 decode_ok_cb (NULL, main_w);
1096 * This routine starts the creation of a List on a notebook page. It
1097 * creates both a scrolled window and a list, adds the list to the
1098 * window, and attaches the list as a data object on the page.
1100 * @param page A pointer to the notebook page being created.
1102 * @param list_p Will be filled in with the address of a newly
1105 * @param scrolled_win_p Will be filled in with the address of a newly
1106 * created GtkScrolledWindow.
1109 decode_list_menu_start(GtkWidget *page, GtkWidget **list_p,
1110 GtkWidget **scrolled_win_p)
1113 GtkListStore *store;
1114 GtkCellRenderer *renderer;
1115 GtkTreeViewColumn *tc;
1116 GtkTreeSortable *sortable;
1118 store = gtk_list_store_new(E_LIST_S_COLUMNS+1, G_TYPE_STRING,
1119 G_TYPE_STRING, G_TYPE_POINTER);
1120 g_object_set_data(G_OBJECT(decode_w), "sctp_data", store);
1121 list = GTK_TREE_VIEW(tree_view_new(GTK_TREE_MODEL(store)));
1122 g_object_unref(G_OBJECT(store));
1123 sortable = GTK_TREE_SORTABLE(store);
1124 gtk_tree_sortable_set_sort_func(sortable, SORT_ALPHABETICAL, sort_iter_compare_func, GINT_TO_POINTER(SORT_ALPHABETICAL), NULL);
1125 gtk_tree_sortable_set_sort_column_id(sortable, SORT_ALPHABETICAL, GTK_SORT_ASCENDING);
1126 gtk_tree_view_set_headers_clickable(list, FALSE);
1128 gtk_tree_view_set_headers_visible(list, FALSE);
1130 renderer = gtk_cell_renderer_text_new();
1131 tc = gtk_tree_view_column_new_with_attributes("Short Name", renderer,
1132 "text", E_LIST_S_PROTO_NAME,
1134 gtk_tree_view_column_set_sizing(tc, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
1135 gtk_tree_view_append_column(list, tc);
1136 g_object_set_data(G_OBJECT(page), E_PAGE_LIST, list);
1138 *scrolled_win_p = scrolled_window_new(NULL, NULL);
1139 /* this will result to set the width of the dialog to the required size */
1140 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(*scrolled_win_p),
1141 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1142 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(*scrolled_win_p),
1144 gtk_container_add(GTK_CONTAINER(*scrolled_win_p), GTK_WIDGET(list));
1146 *list_p = GTK_WIDGET(list);
1150 * This routine finishes the creation of a List on a notebook page.
1151 * It adds the default entry, sets the default entry as the
1152 * highlighted entry, and sorts the List.
1154 * @param list A pointer the the List to finish.
1157 decode_list_menu_finish(GtkWidget *list)
1159 const gchar *text[E_LIST_S_COLUMNS];
1160 GtkListStore *store;
1163 text[E_LIST_S_PROTO_NAME] = "(default)";
1164 text[E_LIST_S_TABLE] = DECODE_AS_NONE;
1165 store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(list)));
1166 gtk_list_store_prepend(store, &iter);
1167 gtk_list_store_set(store, &iter,
1168 E_LIST_S_PROTO_NAME, text[E_LIST_S_PROTO_NAME],
1169 E_LIST_S_TABLE, text[E_LIST_S_TABLE],
1170 E_LIST_S_TABLE+1, NULL, -1);
1172 gtk_tree_selection_select_iter(gtk_tree_view_get_selection(GTK_TREE_VIEW(list)), &iter);
1173 g_signal_connect(list, "button_press_event", G_CALLBACK(decode_list_button_press_cb), NULL);
1174 g_signal_connect(list, "key_release_event", G_CALLBACK(decode_list_key_release_cb), NULL);
1178 * This routine is called to add the dissector selection list to a
1179 * notebook page. This scrolled list contains an entry labeled
1180 * "default", and an entry for each protocol that has had a dissector
1181 * registered. The default choice for the list is set to the
1182 * "default" choice, which will return the protocol/port selections to
1183 * their original dissector(s).
1185 * @param page A pointer to the notebook page currently being created.
1187 * @param entry Decode As structure used to build this (list) menu.
1189 * @return GtkWidget * A pointer to the newly created list within a
1193 decode_add_simple_menu (GtkWidget *page, decode_as_t *entry)
1195 GtkWidget *scrolled_window;
1198 decode_list_menu_start(page, &list, &scrolled_window);
1199 entry->populate_list(entry->table_name, decode_add_to_list, list);
1200 decode_list_menu_finish(list);
1201 return(scrolled_window);
1205 /**************************************************/
1207 /**************************************************/
1210 * This routine creates a sample notebook page in the dialog box.
1211 * This notebook page provides a prompt specifying what is being
1212 * changed and its current value (e.g. "IP Protocol number (17)"), and
1213 * a list specifying all the available choices. The list of choices
1214 * is conditionally enabled, based upon the setting of the
1215 * "decode"/"do not decode" radio buttons.
1217 * @param entry Decode As structure used to build this page
1219 * @return GtkWidget * A pointer to the notebook page created by this
1223 decode_add_simple_page (decode_as_t *entry)
1225 GtkWidget *page, *label, *scrolled_window, *combo_box;
1226 gchar prompt[MAX_DECODE_AS_PROMPT_LEN];
1228 page = ws_gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5, FALSE);
1229 g_object_set_data(G_OBJECT(page), E_PAGE_ACTION, decode_simple);
1230 g_object_set_data(G_OBJECT(page), E_PAGE_TABLE, (gchar *) entry->table_name);
1231 g_object_set_data(G_OBJECT(page), E_PAGE_DECODE_AS_DATA, (gchar *)entry);
1233 if (entry->num_items == 1)
1235 g_object_set_data(G_OBJECT(page), E_PAGE_VALUE, entry->values[0].build_values[0](&cfile.edt->pi));
1237 /* Always enabled */
1238 entry->values->label_func(&cfile.edt->pi, prompt);
1239 label = gtk_label_new(prompt);
1240 gtk_box_pack_start(GTK_BOX(page), label, FALSE, FALSE, 0);
1244 /* Always enabled */
1245 if (entry->pre_value_str)
1247 label = gtk_label_new(entry->pre_value_str);
1248 gtk_box_pack_start(GTK_BOX(page), label, FALSE, FALSE, 0);
1250 combo_box = decode_add_multivalue_combo_box(page, entry);
1251 gtk_box_pack_start(GTK_BOX(page), combo_box, FALSE, FALSE, 0);
1253 if (entry->post_value_str)
1255 label = gtk_label_new(entry->post_value_str);
1256 gtk_box_pack_start(GTK_BOX(page), label, FALSE, FALSE, 0);
1260 /* Conditionally enabled - only when decoding packets */
1261 scrolled_window = decode_add_simple_menu(page, entry);
1262 gtk_box_pack_start(GTK_BOX(page), scrolled_window, TRUE, TRUE, 0);
1263 decode_dimmable = g_slist_prepend(decode_dimmable, scrolled_window);
1269 * This routine indicates whether we'd actually have any pages in the
1270 * notebook in a "Decode As" dialog box; if there wouldn't be, we
1271 * inactivate the menu item for "Decode As".
1276 wmem_list_frame_t * protos = wmem_list_head(cfile.edt->pi.layers);
1278 const char* proto_name;
1281 dissector_table_t sub_dissectors;
1283 while (protos != NULL)
1285 proto_id = GPOINTER_TO_INT(wmem_list_frame_data(protos));
1286 proto_name = proto_get_protocol_filter_name(proto_id);
1288 list_entry = decode_as_list;
1289 while (list_entry != NULL) {
1290 entry = (decode_as_t *)list_entry->data;
1291 if (!strcmp(proto_name, entry->name))
1293 sub_dissectors = find_dissector_table(entry->table_name);
1294 if (sub_dissectors != NULL)
1298 list_entry = g_list_next(list_entry);
1301 protos = wmem_list_frame_next(protos);
1309 * This routine creates the bulk of the "Decode As" dialog box. All
1310 * items created by this routine are packed as pages into a notebook.
1311 * There will be a page for each protocol layer that can be changed.
1313 * @param format_hb A pointer to the widget in which the notebook
1314 * should be installed.
1317 decode_add_notebook (GtkWidget *format_hb)
1319 GtkWidget *notebook, *page, *label;
1320 wmem_list_frame_t * protos = wmem_list_head(cfile.edt->pi.layers);
1322 const char* proto_name;
1325 dissector_table_t sub_dissectors;
1327 /* Start a nootbook for flipping between sets of changes */
1328 notebook = gtk_notebook_new();
1329 gtk_box_pack_start(GTK_BOX(format_hb), notebook, TRUE, TRUE, 0);
1330 g_object_set_data(G_OBJECT(decode_w), E_NOTEBOOK, notebook);
1332 while (protos != NULL)
1334 proto_id = GPOINTER_TO_INT(wmem_list_frame_data(protos));
1335 proto_name = proto_get_protocol_filter_name(proto_id);
1337 list_entry = decode_as_list;
1338 while (list_entry != NULL) {
1339 entry = (decode_as_t *)list_entry->data;
1340 if (!strcmp(proto_name, entry->name))
1342 sub_dissectors = find_dissector_table(entry->table_name);
1343 if (sub_dissectors != NULL)
1345 page = decode_add_simple_page(entry);
1346 label = gtk_label_new(entry->title);
1347 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page, label);
1351 list_entry = g_list_next(list_entry);
1354 protos = wmem_list_frame_next(protos);
1357 /* Select the last added page (selects first by default) */
1358 /* Notebook must be visible for set_page to work. */
1359 gtk_widget_show_all(notebook);
1360 gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), -1);
1365 * This routine creates the "Decode As" dialog box. This dialog box
1366 * asks the user which protocol to use for decoding the currently
1367 * selected packet. This will affect the last packet that we called a
1368 * dissection routine on belongs (this might be the most recently
1369 * selected packet, or it might be the last packet in the file).
1371 * This routine uses an auxiliary function to create the bulk of the
1372 * dialog box, and then hand crafts the button box at the bottom of
1377 * @param user_data Unused
1380 decode_as_cb (GtkWidget * w _U_, gpointer user_data _U_)
1382 GtkWidget *main_vb, *format_hb, *bbox, *ok_bt, *close_bt, *help_bt, *button;
1383 GtkWidget *button_vb, *apply_bt;
1385 if (decode_w != NULL) {
1386 /* There's already a "Decode As" dialog box; reactivate it. */
1387 reactivate_window(decode_w);
1391 requested_action = E_DECODE_YES;
1392 decode_w = dlg_window_new("Wireshark: Decode As");
1393 /* Provide a minimum of a couple of rows worth of data */
1394 gtk_window_set_default_size(GTK_WINDOW(decode_w), -1, E_DECODE_MIN_HEIGHT);
1396 /* Container for each row of widgets */
1397 main_vb = ws_gtk_box_new(GTK_ORIENTATION_VERTICAL, 2, FALSE);
1398 gtk_container_set_border_width(GTK_CONTAINER(main_vb), 5);
1399 gtk_container_add(GTK_CONTAINER(decode_w), main_vb);
1401 /* First row - Buttons and Notebook */
1402 format_hb = ws_gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5, FALSE);
1403 gtk_box_pack_start(GTK_BOX(main_vb), format_hb, TRUE, TRUE, 10);
1405 button_vb = decode_add_yes_no();
1406 gtk_box_pack_start(GTK_BOX(format_hb), button_vb, FALSE, FALSE, 10);
1408 button = gtk_button_new_with_label("Show Current");
1409 g_signal_connect(button, "clicked", G_CALLBACK(decode_show_cb), NULL);
1410 gtk_widget_set_can_default(button, TRUE);
1411 gtk_box_pack_end(GTK_BOX(button_vb), button, FALSE, FALSE, 0);
1412 gtk_widget_set_tooltip_text(button, "Open a dialog showing the current settings.\n"
1413 "Note you need to select and press apply first to be able to save the current setting");
1415 button = gtk_button_new_from_stock(GTK_STOCK_CLEAR);
1416 g_signal_connect(button, "clicked", G_CALLBACK(decode_clear_cb), NULL);
1417 gtk_widget_set_can_default(button, TRUE);
1418 gtk_box_pack_end(GTK_BOX(button_vb), button, FALSE, FALSE, 0);
1419 gtk_widget_set_tooltip_text(button, "Clear ALL settings.");
1421 decode_add_notebook(format_hb);
1424 bbox = dlg_button_row_new(GTK_STOCK_OK, GTK_STOCK_APPLY, GTK_STOCK_CLOSE, GTK_STOCK_HELP, NULL);
1425 gtk_box_pack_start(GTK_BOX(main_vb), bbox, FALSE, FALSE, 0);
1426 gtk_widget_show(bbox);
1428 ok_bt = (GtkWidget *)g_object_get_data(G_OBJECT(bbox), GTK_STOCK_OK);
1429 g_signal_connect(ok_bt, "clicked", G_CALLBACK(decode_ok_cb), decode_w);
1430 gtk_widget_set_tooltip_text(ok_bt, "Apply current setting, close dialog and redissect packets.");
1432 apply_bt = (GtkWidget *)g_object_get_data(G_OBJECT(bbox), GTK_STOCK_APPLY);
1433 g_signal_connect(apply_bt, "clicked", G_CALLBACK(decode_apply_cb), decode_w);
1434 gtk_widget_set_tooltip_text(apply_bt, "Apply current setting, redissect packets and keep dialog open.");
1436 close_bt = (GtkWidget *)g_object_get_data(G_OBJECT(bbox), GTK_STOCK_CLOSE);
1437 window_set_cancel_button(decode_w, close_bt, NULL);
1438 g_signal_connect(close_bt, "clicked", G_CALLBACK(decode_close_cb), decode_w);
1439 gtk_widget_set_tooltip_text(close_bt, "Close the dialog, don't redissect packets.");
1441 help_bt = (GtkWidget *)g_object_get_data(G_OBJECT(bbox), GTK_STOCK_HELP);
1442 g_signal_connect(help_bt, "clicked", G_CALLBACK(topic_cb), (gpointer)HELP_DECODE_AS_DIALOG);
1444 gtk_widget_grab_default(ok_bt);
1446 g_signal_connect(decode_w, "delete_event", G_CALLBACK(decode_delete_cb), NULL);
1447 g_signal_connect(decode_w, "destroy", G_CALLBACK(decode_destroy_cb), NULL);
1449 gtk_widget_show_all(decode_w);
1450 window_present(decode_w);