aboutsummaryrefslogtreecommitdiffstats
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
parent56e71b85f39dfbaba906658189c086fb6f4e7349 (diff)
Initial support for editing packets inside wireshark.
svn path=/trunk/; revision=36841
-rw-r--r--gtk/menus.c21
-rw-r--r--gtk/new_packet_list.c2
-rw-r--r--gtk/packet_win.c165
-rw-r--r--gtk/packet_win.h2
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.
*/