diff options
author | Jakub Zawadzki <darkjames-ws@darkjames.pl> | 2011-04-24 21:19:41 +0000 |
---|---|---|
committer | Jakub Zawadzki <darkjames-ws@darkjames.pl> | 2011-04-24 21:19:41 +0000 |
commit | 06ad060901921574b5a4884d94659e00896fc03b (patch) | |
tree | 101d4f3d5ab98864fafab2dec746df4556bbba48 | |
parent | 56e71b85f39dfbaba906658189c086fb6f4e7349 (diff) |
Initial support for editing packets inside wireshark.
svn path=/trunk/; revision=36841
-rw-r--r-- | gtk/menus.c | 21 | ||||
-rw-r--r-- | gtk/new_packet_list.c | 2 | ||||
-rw-r--r-- | gtk/packet_win.c | 165 | ||||
-rw-r--r-- | gtk/packet_win.h | 2 |
4 files changed, 187 insertions, 3 deletions
diff --git a/gtk/menus.c b/gtk/menus.c index 1ee6f1b317..27e73f8f82 100644 --- a/gtk/menus.c +++ b/gtk/menus.c @@ -368,6 +368,18 @@ build_conversation_filter(int action, gboolean show_dialog) return buf; } +static void +new_window_cb(GtkWidget *widget) +{ + new_packet_window(widget, FALSE); +} + +static void +edit_window_cb(GtkWidget *widget) +{ + new_packet_window(widget, TRUE); +} + static void conversation_cb(GtkAction *a _U_, gpointer data _U_, int action) { @@ -1050,6 +1062,8 @@ static const char *ui_desc_menubar = " <menuitem name='FindNextTimeReference' action='/Edit/FindNextTimeReference'/>\n" " <menuitem name='FindPreviousTimeReference' action='/Edit/FindPreviousTimeReference'/>\n" " <separator/>\n" +" <menuitem name='EditPacket' action='/Edit/EditPacket'/>\n" +" <separator/>\n" " <menuitem name='ConfigurationProfiles' action='/Edit/ConfigurationProfiles'/>\n" " <menuitem name='Preferences' action='/Edit/Preferences'/>\n" " </menu>\n" @@ -1418,6 +1432,7 @@ static const GtkActionEntry main_menu_bar_entries[] = { { "/Edit/ConfigurationProfiles", NULL, "_Configuration Profiles...", "<shift><control>A", NULL, G_CALLBACK(profile_dialog_cb) }, { "/Edit/Preferences", GTK_STOCK_PREFERENCES, "_Preferences...", "<shift><control>P", NULL, G_CALLBACK(menus_prefs_cb) }, + { "/Edit/EditPacket", NULL, "_Edit Packet", NULL, NULL, G_CALLBACK(edit_window_cb) }, { "/View/TimeDisplayFormat", NULL, "_Time Display Format", NULL, NULL, NULL }, @@ -1782,6 +1797,8 @@ static GtkItemFactoryEntry menu_items[] = {"/Edit/Find Next Time Reference", "<alt><control>N", GTK_MENU_FUNC(reftime_frame_cb), REFTIME_FIND_NEXT, NULL, NULL,}, {"/Edit/Find Previous Time Reference", "<alt><control>B", GTK_MENU_FUNC(reftime_frame_cb), REFTIME_FIND_PREV, NULL, NULL,}, {"/Edit/<separator>", NULL, NULL, 0, "<Separator>", NULL,}, + {"/Edit/Edit packet", NULL, GTK_MENU_FUNC(edit_window_cb), 0, NULL, NULL, }, + {"/Edit/<separator>", NULL, NULL, 0, "<Separator>", NULL,}, {"/Edit/_Configuration Profiles...", "<shift><control>A", GTK_MENU_FUNC(profile_dialog_cb), 0, NULL, NULL,}, {"/Edit/_Preferences...", "<shift><control>P", GTK_MENU_FUNC(prefs_page_cb), PREFS_PAGE_USER_INTERFACE, "<StockItem>", GTK_STOCK_PREFERENCES,}, @@ -5991,6 +6008,8 @@ set_menus_for_selected_packet(capture_file *cf) set_menu_sensitivity(ui_manager_main_menubar, "/Menubar/EditMenu/IgnorePacket", frame_selected); + set_menu_sensitivity(ui_manager_main_menubar, "/Menubar/EditMenu/EditPacket", + frame_selected); #else /* MAIN_MENU_USE_UIMANAGER */ set_menu_sensitivity_old("/Edit/Mark All Displayed Packets (toggle)", cf->displayed_count > 0); @@ -6004,6 +6023,8 @@ set_menus_for_selected_packet(capture_file *cf) set_menu_sensitivity_old("/Edit/Ignore Packet (toggle)", frame_selected); + set_menu_sensitivity_old("/Edit/Edit packet", + frame_selected); #endif /* MAIN_MENU_USE_UIMANAGER */ set_menu_sensitivity(ui_manager_packet_list_menu, "/PacketListMenuPopup/IgnorePacket", frame_selected); diff --git a/gtk/new_packet_list.c b/gtk/new_packet_list.c index 630485fe29..a43c84c356 100644 --- a/gtk/new_packet_list.c +++ b/gtk/new_packet_list.c @@ -1253,7 +1253,7 @@ static void new_packet_list_double_click_cb(GtkTreeView *treeview, GtkTreePath *path _U_, GtkTreeViewColumn *col _U_, gpointer userdata _U_) { - new_window_cb(GTK_WIDGET(treeview)); + new_packet_window(GTK_WIDGET(treeview), FALSE); } gboolean diff --git a/gtk/packet_win.c b/gtk/packet_win.c index ebfe333c86..167c6a4d37 100644 --- a/gtk/packet_win.c +++ b/gtk/packet_win.c @@ -40,6 +40,7 @@ #endif #include <gtk/gtk.h> +#include <gdk/gdkkeysyms.h> #include <string.h> @@ -64,6 +65,7 @@ #include "gtk/keys.h" #include "gtk/gtkglobals.h" #include "gtk/gui_utils.h" +#include "gtk/recent.h" /* Data structure holding information about a packet-detail window. */ @@ -77,6 +79,9 @@ struct PacketWinData { GtkWidget *bv_nb_ptr; field_info *finfo_selected; epan_dissect_t *edt; + + int pd_offset; + int pd_bitoffset; }; /* List of all the packet-detail windows popped up. */ @@ -118,7 +123,127 @@ button_press_handler(GtkWidget *widget, GdkEvent *event, gpointer data _U_) return FALSE; } -void new_window_cb(GtkWidget *w _U_) +static gboolean +edit_pkt_win_key_pressed_cb(GtkWidget *win _U_, GdkEventKey *event, gpointer user_data) +{ + struct PacketWinData *DataPtr = (struct PacketWinData*)user_data; + field_info faked_finfo; + int val = -1; + GSList *src_le; + + switch (recent.gui_bytes_view) { + case BYTES_HEX: + if (event->keyval >= 'a' && event->keyval <= 'f') + val = (event->keyval - 'a') + 10; + else if (event->keyval >= 'A' && event->keyval <= 'F') + val = (event->keyval - 'A') + 10; + else if (event->keyval >= '0' && event->keyval <= '9') + val = (event->keyval - '0'); + else if (event->keyval == GDK_Left) + DataPtr->pd_bitoffset -= 4; + else if (event->keyval == GDK_Right) + DataPtr->pd_bitoffset += 4; + else + return FALSE; + + if (val != -1) { + /* Lazy... + * XXX Allow (DataPtr->pd_bitoffset % 4) != 0 ? */ + if (DataPtr->pd_bitoffset < 4) { + DataPtr->pd[DataPtr->pd_offset] = (DataPtr->pd[DataPtr->pd_offset] & 0x0f) | (val << 4); + DataPtr->pd_bitoffset = 4; + } else { + DataPtr->pd[DataPtr->pd_offset] = (DataPtr->pd[DataPtr->pd_offset] & 0xf0) | val; + DataPtr->pd_bitoffset = 8; + } + /* DataPtr->pd_bitoffset += 4; */ + } + break; + + case BYTES_BITS: + if (event->keyval == '0' || event->keyval == '1') + val = (event->keyval != '0'); + else if (event->keyval == GDK_Left) + DataPtr->pd_bitoffset -= 1; + else if (event->keyval == GDK_Right) + DataPtr->pd_bitoffset += 1; + else + return FALSE; + + if (val != -1) { + if (val) + DataPtr->pd[DataPtr->pd_offset] |= (1 << (7-DataPtr->pd_bitoffset)); + else + DataPtr->pd[DataPtr->pd_offset] &= ~(1 << (7-DataPtr->pd_bitoffset)); + DataPtr->pd_bitoffset += 1; + } + break; + + default: + g_assert_not_reached(); + return FALSE; + } + + while (DataPtr->pd_bitoffset >= 8) { + DataPtr->pd_offset += 1; + DataPtr->pd_bitoffset -= 8; + } + while (DataPtr->pd_bitoffset < 0) { + DataPtr->pd_offset -= 1; + DataPtr->pd_bitoffset += 8; + } + + if (DataPtr->pd_offset < 0) { + DataPtr->pd_offset = DataPtr->frame->cap_len-1; + /* XXX, last bit/octect? */ + } + + if ((guint)DataPtr->pd_offset >= DataPtr->frame->cap_len) + DataPtr->pd_offset = 0; + + /* redissect if changed */ + if (val != -1) { + /* XXX, can be optimized? */ + epan_dissect_free(DataPtr->edt); + DataPtr->edt = epan_dissect_new(TRUE, TRUE); + epan_dissect_run(DataPtr->edt, &DataPtr->pseudo_header, DataPtr->pd, DataPtr->frame, &cfile.cinfo); + add_byte_views(DataPtr->edt, DataPtr->tree_view, DataPtr->bv_nb_ptr); + proto_tree_draw(DataPtr->edt->tree, DataPtr->tree_view); + } + + /* hack, fake finfo, point to DataPtr->pd_offset */ + faked_finfo.appendix_length = 0; + faked_finfo.start = DataPtr->pd_offset; + faked_finfo.length = 1; + faked_finfo.hfinfo = NULL; + faked_finfo.flags = 0; + faked_finfo.ds_tvb = NULL; + /* XXX, in bitview bitmask single bit. */ + + for (src_le = DataPtr->edt->pi.data_src; src_le != NULL; src_le = src_le->next) { + const data_source *src = src_le->data; + tvbuff_t *tvb = src->tvb; + + src = src_le->data; + + if (tvb && tvb->real_data == DataPtr->pd) { + faked_finfo.ds_tvb = tvb; + break; + } + } + + if (faked_finfo.ds_tvb != NULL) { + GtkWidget *byte_view; + + set_notebook_page(DataPtr->bv_nb_ptr, faked_finfo.ds_tvb); + byte_view = get_notebook_bv_ptr(DataPtr->bv_nb_ptr); + if (byte_view) + packet_hex_print(byte_view, DataPtr->pd, DataPtr->frame, &faked_finfo, DataPtr->frame->cap_len); + } + return TRUE; +} + +void new_packet_window(GtkWidget *w _U_, gboolean editable) { #define NewWinTitleLen 1000 char Title[NewWinTitleLen] = ""; @@ -202,6 +327,9 @@ void new_window_cb(GtkWidget *w _U_) g_signal_connect(gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view)), "changed", G_CALLBACK(new_tree_view_selection_changed_cb), DataPtr); g_signal_connect(tree_view, "button_press_event", G_CALLBACK(button_press_handler), NULL); + if (editable && DataPtr->frame->cap_len != 0) { + g_signal_connect(main_w, "key-press-event", G_CALLBACK(edit_pkt_win_key_pressed_cb), DataPtr); + } g_signal_connect(main_w, "destroy", G_CALLBACK(destroy_new_window), DataPtr); /* draw the protocol tree & print hex data */ @@ -209,6 +337,8 @@ void new_window_cb(GtkWidget *w _U_) proto_tree_draw(DataPtr->edt->tree, tree_view); DataPtr->finfo_selected = NULL; + DataPtr->pd_offset = 0; + DataPtr->pd_bitoffset = 0; gtk_widget_show(main_w); } @@ -254,6 +384,39 @@ new_tree_view_selection_changed_cb(GtkTreeSelection *sel, gpointer user_data) } DataPtr->finfo_selected = finfo; + + DataPtr->pd_offset = 0; + DataPtr->pd_bitoffset = 0; + + if (!FI_GET_FLAG(finfo, FI_GENERATED) && + finfo->ds_tvb && finfo->ds_tvb->real_data >= DataPtr->pd && finfo->ds_tvb->real_data <= DataPtr->pd + DataPtr->frame->cap_len) + { + /* I haven't really test if TVB subsets works, but why not? :> */ + int pd_offset = DataPtr->pd - finfo->ds_tvb->real_data; + + /* some code from packet_hex_print */ + int finfo_offset = finfo->start; + int finfo_len = finfo->length; + + if (!(finfo_offset >= 0 && finfo_len > 0)) { + finfo_offset = finfo->appendix_start; + finfo_len = finfo->appendix_length; + } + /* Don't care about things like bitmask or LE/BE, just point DataPtr->tvb_[bit]offset to proper offsets. + * TODO: We might want to add another dialog to edit only selected value. + */ + + if (finfo_offset >= 0 && finfo_len > 0) { + DataPtr->pd_offset = pd_offset + finfo_offset; + DataPtr->pd_bitoffset = 0; + } + + if (DataPtr->pd_offset < 0) + DataPtr->pd_offset = 0; + if ((guint)DataPtr->pd_offset >= DataPtr->frame->cap_len) + DataPtr->pd_offset = 0; + } + packet_hex_print(byte_view, data, DataPtr->frame, finfo, len); } else diff --git a/gtk/packet_win.h b/gtk/packet_win.h index ce42b10e57..1f4f0f5a88 100644 --- a/gtk/packet_win.h +++ b/gtk/packet_win.h @@ -35,7 +35,7 @@ * * @param widget parent widget (unused) */ -extern void new_window_cb(GtkWidget *widget); +extern void new_packet_window(GtkWidget *widget, gboolean editable); /** Destroy all popup packet windows. */ |