aboutsummaryrefslogtreecommitdiffstats
path: root/gtk/packet_win.c
diff options
context:
space:
mode:
authorJakub Zawadzki <darkjames-ws@darkjames.pl>2011-04-24 21:19:41 +0000
committerJakub Zawadzki <darkjames-ws@darkjames.pl>2011-04-24 21:19:41 +0000
commit06ad060901921574b5a4884d94659e00896fc03b (patch)
tree101d4f3d5ab98864fafab2dec746df4556bbba48 /gtk/packet_win.c
parent56e71b85f39dfbaba906658189c086fb6f4e7349 (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.c165
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