From 63981c8b35850162aa047982e370a041f29a6dc3 Mon Sep 17 00:00:00 2001 From: Jakub Zawadzki Date: Thu, 12 May 2011 19:47:49 +0000 Subject: [PATCH] Packet editor: support for saving changed frames. svn path=/trunk/; revision=37099 --- cfile.h | 3 +++ epan/frame_data.h | 8 ++++++++ file.c | 22 +++++++++++++++++++++ gtk/packet_win.c | 50 +++++++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 81 insertions(+), 2 deletions(-) diff --git a/cfile.h b/cfile.h index 83d2309267..163f4ca426 100644 --- a/cfile.h +++ b/cfile.h @@ -108,6 +108,9 @@ typedef struct _capture_file { gint current_row; /* Row number for current frame */ epan_dissect_t *edt; /* Protocol dissection for currently selected packet */ field_info *finfo_selected; /* Field info for currently selected field */ +#ifdef WANT_PACKET_EDITOR + GTree *edited_frames; /* BST with modified frames */ +#endif } capture_file; extern void cap_file_init(capture_file *cf); diff --git a/epan/frame_data.h b/epan/frame_data.h index f472fd7d0f..2947d09bf7 100644 --- a/epan/frame_data.h +++ b/epan/frame_data.h @@ -65,6 +65,14 @@ typedef struct _frame_data { nstime_t del_cap_ts; /**< Delta timestamp to previous captured frame (yes, it can be negative) */ } frame_data; +#ifdef WANT_PACKET_EDITOR +/* XXX, where this struct should go? */ +typedef struct { + union wtap_pseudo_header ph; /**< Modified pseudo header */ + char *pd; /**< Modified packet data */ +} modified_frame_data; +#endif + /** * A data source. * Has a tvbuff and a name. diff --git a/file.c b/file.c index e9d9b23be8..b114844a6c 100644 --- a/file.c +++ b/file.c @@ -396,6 +396,12 @@ cf_reset_state(capture_file *cf) free_frame_data_sequence(cf->frames); cf->frames = NULL; } +#ifdef WANT_PACKET_EDITOR + if (cf->edited_frames) { + g_tree_destroy(cf->edited_frames); + cf->edited_frames = NULL; + } +#endif cf_unselect_packet(cf); /* nothing to select */ cf->first_displayed = 0; cf->last_displayed = 0; @@ -1517,6 +1523,22 @@ cf_read_frame_r(capture_file *cf, frame_data *fdata, gchar *err_info; char errmsg_errno[1024+1]; +#ifdef WANT_PACKET_EDITOR + /* if fdata->file_off == -1 it means packet was edited, and we must find data inside edited_frames tree */ + if (G_UNLIKELY(fdata->file_off == -1)) { + const modified_frame_data *frame = (const modified_frame_data *) g_tree_lookup(cf->edited_frames, GINT_TO_POINTER(fdata->num)); + + if (!frame) { + simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "fdata->file_off == -1, but can't find modified frame!"); + return FALSE; + } + + *pseudo_header = frame->ph; + memcpy(pd, frame->pd, fdata->cap_len); + return TRUE; + } +#endif + if (!wtap_seek_read(cf->wth, fdata->file_off, pseudo_header, pd, fdata->cap_len, &err, &err_info)) { switch (err) { diff --git a/gtk/packet_win.c b/gtk/packet_win.c index d78f1aa8ef..6355e1fa58 100644 --- a/gtk/packet_win.c +++ b/gtk/packet_win.c @@ -824,6 +824,36 @@ edit_pkt_win_key_pressed_cb(GtkWidget *win _U_, GdkEventKey *event, gpointer use } return TRUE; } + +static void +edit_pkt_destroy_new_window(GtkObject *object _U_, gpointer user_data) +{ + /* like destroy_new_window, but without freeding DataPtr->pd */ + struct PacketWinData *DataPtr = user_data; + + detail_windows = g_list_remove(detail_windows, DataPtr); + epan_dissect_cleanup(&(DataPtr->edt)); + g_free(DataPtr); + + /* XXX, notify main packet list that packet should be redisplayed */ +} + +static gint g_direct_compare_func(gconstpointer a, gconstpointer b, gpointer user_data _U_) { + if (a > b) + return 1; + else if (a < b) + return -1; + else + return 0; +} + +static void modifed_frame_data_free(gpointer data) { + modified_frame_data *mfd = (modified_frame_data *) data; + + g_free(mfd->pd); + g_free(mfd); +} + #endif /* WANT_PACKET_EDITOR */ void new_packet_window(GtkWidget *w _U_, gboolean editable _U_) @@ -915,9 +945,10 @@ void new_packet_window(GtkWidget *w _U_, gboolean editable _U_) g_signal_connect(main_w, "key-press-event", G_CALLBACK(edit_pkt_win_key_pressed_cb), DataPtr); /* XXX, popup-menu instead of row-activated? */ g_signal_connect(tree_view, "row-activated", G_CALLBACK(edit_pkt_tree_row_activated_cb), DataPtr); - } + g_signal_connect(main_w, "destroy", G_CALLBACK(edit_pkt_destroy_new_window), DataPtr); + } else #endif - g_signal_connect(main_w, "destroy", G_CALLBACK(destroy_new_window), DataPtr); + g_signal_connect(main_w, "destroy", G_CALLBACK(destroy_new_window), DataPtr); /* draw the protocol tree & print hex data */ add_byte_views(&(DataPtr->edt), tree_view, DataPtr->bv_nb_ptr); @@ -927,6 +958,21 @@ void new_packet_window(GtkWidget *w _U_, gboolean editable _U_) DataPtr->pd_offset = 0; DataPtr->pd_bitoffset = 0; gtk_widget_show(main_w); + +#ifdef WANT_PACKET_EDITOR + if (editable && DataPtr->frame->cap_len != 0) { + /* XXX, there's no Save button here, so lets assume packet is always edited */ + modified_frame_data *mfd = g_malloc(sizeof(modified_frame_data)); + + mfd->pd = DataPtr->pd; + mfd->ph = DataPtr->pseudo_header; + + if (cfile.edited_frames == NULL) + cfile.edited_frames = g_tree_new_full(g_direct_compare_func, NULL, NULL, modifed_frame_data_free); + g_tree_insert(cfile.edited_frames, GINT_TO_POINTER(DataPtr->frame->num), mfd); + DataPtr->frame->file_off = -1; + } +#endif } static void