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 /gtk/packet_win.c | |
parent | 56e71b85f39dfbaba906658189c086fb6f4e7349 (diff) |
Initial support for editing packets inside wireshark.
svn path=/trunk/; revision=36841
Diffstat (limited to 'gtk/packet_win.c')
-rw-r--r-- | gtk/packet_win.c | 165 |
1 files changed, 164 insertions, 1 deletions
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 |