/* packet_panes.c
* Routines for GTK+ packet display (packet details and hex dump panes)
*
- * $Id$
- *
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
#include "config.h"
-#include <ctype.h>
-
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>
#if GTK_CHECK_VERSION(3,0,0)
#include <epan/packet.h>
#include <epan/charsets.h>
#include <epan/prefs.h>
-#include <epan/filesystem.h>
-
-#include "../isprint.h"
+#include <wsutil/filesystem.h>
#include "ui/alert_box.h"
#include "ui/last_open_dir.h"
#include "ui/ui_util.h"
#include <wsutil/file_util.h>
+#include <wsutil/str_util.h>
#include "ui/gtk/keys.h"
#include "ui/gtk/color_utils.h"
#define E_BYTE_VIEW_TVBUFF_KEY "byte_view_tvbuff"
#define E_BYTE_VIEW_START_KEY "byte_view_start"
#define E_BYTE_VIEW_END_KEY "byte_view_end"
-#define E_BYTE_VIEW_MASK_KEY "byte_view_mask"
+#define E_BYTE_VIEW_MASK_LO_KEY "byte_view_mask_lo"
+#define E_BYTE_VIEW_MASK_HI_KEY "byte_view_mask_hi"
#define E_BYTE_VIEW_MASKLE_KEY "byte_view_mask_le"
#define E_BYTE_VIEW_APP_START_KEY "byte_view_app_start"
#define E_BYTE_VIEW_APP_END_KEY "byte_view_app_end"
+#define E_BYTE_VIEW_PROTO_START_KEY "byte_view_proto_start"
+#define E_BYTE_VIEW_PROTO_END_KEY "byte_view_proto_end"
#define E_BYTE_VIEW_ENCODE_KEY "byte_view_encode"
/* Get the current text window for the notebook. */
if (byte_view_tvb == NULL)
return NULL;
- if ((*data_len = tvb_length(byte_view_tvb))) {
+ if ((*data_len = tvb_captured_length(byte_view_tvb))) {
data_ptr = tvb_get_ptr(byte_view_tvb, 0, -1);
return data_ptr;
} else
}
}
+/* Expand trees (and any subtrees they may have) whose ett_ shows them as
+ * expanded.
+ * Callers should block calls to expand_tree() to avoid useless recursion.
+ */
+static void
+check_expand_trees(GtkTreeView *tree_view, GtkTreeModel *model, GtkTreePath *path,
+ GtkTreeIter *iter, gboolean scroll_it, gboolean expand_parent)
+{
+ /* code inspired by gtk_tree_model_foreach_helper */
+
+ field_info *fi;
+
+ do {
+ GtkTreeIter child;
+
+ if (gtk_tree_model_iter_children(model, &child, iter)) {
+ gtk_tree_model_get(model, iter, 1, &fi, -1);
+
+ if (tree_expanded(fi->tree_type)) {
+ if (expand_parent)
+ gtk_tree_view_expand_row(tree_view, path, FALSE);
+
+ if (scroll_it)
+ gtk_tree_view_scroll_to_cell(tree_view, path, NULL, TRUE, (prefs.gui_auto_scroll_percentage/100.0f), 0.0f);
+
+ /* try to expand children only when parent is expanded */
+ gtk_tree_path_down(path);
+ check_expand_trees(tree_view, model, path, &child, scroll_it, TRUE);
+ gtk_tree_path_up(path);
+ }
+ }
+
+ gtk_tree_path_next(path);
+ } while (gtk_tree_model_iter_next(model, iter));
+}
+
static void
expand_tree(GtkTreeView *tree_view, GtkTreeIter *iter,
- GtkTreePath *path _U_, gpointer user_data _U_)
+ GtkTreePath *path, gpointer user_data _U_)
{
field_info *finfo;
GtkTreeModel *model;
* Nodes with "finfo->tree_type" of -1 have no ett_ value, and
* are thus presumably leaf nodes and cannot be expanded.
*/
- if (finfo->tree_type != -1) {
- g_assert(finfo->tree_type >= 0 &&
- finfo->tree_type < num_tree_types);
- tree_is_expanded[finfo->tree_type] = TRUE;
+ if (finfo->tree_type != -1)
+ tree_expanded_set(finfo->tree_type, TRUE);
+
+ if (finfo->tree_type != -1 && path) {
+ /* Expand any subtrees that the user had left open */
+ g_signal_handlers_block_by_func(tree_view, expand_tree, NULL);
+ check_expand_trees(tree_view, model, path, iter, FALSE, FALSE);
+ g_signal_handlers_unblock_by_func(tree_view, expand_tree, NULL);
}
}
* Nodes with "finfo->tree_type" of -1 have no ett_ value, and
* are thus presumably leaf nodes and cannot be collapsed.
*/
- if (finfo->tree_type != -1) {
- g_assert(finfo->tree_type >= 0 &&
- finfo->tree_type < num_tree_types);
- tree_is_expanded[finfo->tree_type] = FALSE;
- }
+ if (finfo->tree_type != -1)
+ tree_expanded_set(finfo->tree_type, FALSE);
}
struct field_lookup_info {
gtk_tree_path_free(path);
}
- /* Refresh the display so that the expanded trees are visible */
- proto_tree_draw(tree, GTK_WIDGET(tree_view));
-
/* select our field's row */
gtk_tree_selection_select_path(gtk_tree_view_get_selection(tree_view),
first_path);
{
GSList *src_le;
struct data_source *src;
+ char* src_name;
/*
* Get rid of all the old notebook tabs.
*/
for (src_le = edt->pi.data_src; src_le != NULL; src_le = src_le->next) {
src = (struct data_source *)src_le->data;
- add_byte_tab(byte_nb_ptr, get_data_source_name(src), get_data_source_tvb(src), edt->tree,
+ src_name = get_data_source_name(src);
+ add_byte_tab(byte_nb_ptr, src_name, get_data_source_tvb(src), edt->tree,
tree_view);
+ wmem_free(NULL, src_name);
}
/*
g_string_append_printf(hex_str," %02x",*data_p);
if(append_text) {
- g_string_append_printf(char_str,"%c",isprint(*data_p) ? *data_p : '.');
+ g_string_append_printf(char_str,"%c",g_ascii_isprint(*data_p) ? *data_p : '.');
}
++data_p;
gchar to_append;
/* Copy printable characters, newlines, and (horizontal) tabs. */
- if(isprint(*data_p)) {
+ if(g_ascii_isprint(*data_p)) {
to_append = *data_p;
} else if(*data_p==0x0a) {
to_append = '\n';
void
savehex_cb(GtkWidget * w _U_, gpointer data _U_)
{
- win32_export_raw_file(GDK_WINDOW_HWND(gtk_widget_get_window(top_level)));
+ win32_export_raw_file(GDK_WINDOW_HWND(gtk_widget_get_window(top_level)), &cfile);
return;
}
#else
static void
packet_hex_update(GtkWidget *bv, const guint8 *pd, int len, int bstart,
- int bend, guint32 bmask, int bmask_le,
- int astart, int aend, int encoding)
+ int bend, guint64 bmask, int bmask_le,
+ int astart, int aend,
+ int pstart, int pend,
+ packet_char_enc encoding)
+{
+ bytes_view_set_encoding(BYTES_VIEW(bv), encoding);
+ bytes_view_set_format(BYTES_VIEW(bv), recent.gui_bytes_view);
+ bytes_view_set_data(BYTES_VIEW(bv), pd, len);
+
+ bytes_view_set_highlight_style(BYTES_VIEW(bv), prefs.gui_hex_dump_highlight_style);
+
+ bytes_view_set_highlight(BYTES_VIEW(bv), bstart, bend, bmask, bmask_le);
+ bytes_view_set_highlight_extra(BYTES_VIEW(bv), BYTE_VIEW_HIGHLIGHT_APPENDIX, astart, aend);
+ bytes_view_set_highlight_extra(BYTES_VIEW(bv), BYTE_VIEW_HIGHLIGHT_PROTOCOL, pstart, pend);
+
+ if (bstart != -1 && bend != -1)
+ bytes_view_scroll_to_byte(BYTES_VIEW(bv), bstart);
+ bytes_view_refresh(BYTES_VIEW(bv));
+}
+
+static field_info *
+get_top_finfo(proto_node *node, field_info *finfo)
{
- bytes_view_set_encoding(BYTES_VIEW(bv), encoding);
- bytes_view_set_format(BYTES_VIEW(bv), recent.gui_bytes_view);
- bytes_view_set_data(BYTES_VIEW(bv), pd, len);
+ proto_node *child;
+ field_info *top;
+
+ if (node == NULL)
+ return NULL;
+ if (PNODE_FINFO(node) == finfo) {
+ top = finfo;
- bytes_view_set_highlight_style(BYTES_VIEW(bv), prefs.gui_hex_dump_highlight_style);
+ while (node && node->parent) {
+ field_info *fi;
- bytes_view_set_highlight(BYTES_VIEW(bv), bstart, bend, bmask, bmask_le);
- bytes_view_set_highlight_appendix(BYTES_VIEW(bv), astart, aend);
+ node = node->parent;
+
+ fi = PNODE_FINFO(node);
+ if (fi && fi->ds_tvb == finfo->ds_tvb)
+ top = fi;
+ }
+
+ return top;
+ }
+
+ for (child = node->first_child; child; child = child->next) {
+ top = get_top_finfo(child, finfo);
+ if (top)
+ return top;
+ }
- if (bstart != -1 && bend != -1)
- bytes_view_scroll_to_byte(BYTES_VIEW(bv), bstart);
- bytes_view_refresh(BYTES_VIEW(bv));
+ return NULL;
}
void
/* to redraw the display if preferences change. */
int bstart = -1, bend = -1, blen = -1;
- guint32 bmask = 0x00; int bmask_le = 0;
+ guint64 bmask = 0x00; int bmask_le = 0;
int astart = -1, aend = -1, alen = -1;
-
+ int pstart = -1, pend = -1, plen = -1;
if (finfo != NULL) {
+ proto_tree *tree = (proto_tree *)g_object_get_data(G_OBJECT(bv), E_BYTE_VIEW_TREE_PTR);
+ field_info *top_finfo;
if (cfile.search_in_progress && (cfile.hex || (cfile.string && cfile.packet_data))) {
/* In the hex view, only highlight the target bytes or string. The entire
bstart = finfo->start;
}
- /* bmask = finfo->hfinfo->bitmask << finfo->hfinfo->bitshift; */ /* (value & mask) >> shift */
+ /* bmask = finfo->hfinfo->bitmask << hfinfo_bitshift(finfo->hfinfo); */ /* (value & mask) >> shift */
if (finfo->hfinfo) bmask = finfo->hfinfo->bitmask;
astart = finfo->appendix_start;
alen = finfo->appendix_length;
+ top_finfo = get_top_finfo(tree, finfo);
+ /* it's possible to have top_finfo == finfo, no problem right now */
+ if (top_finfo) {
+ pstart = top_finfo->start;
+ plen = top_finfo->length;
+ }
+
if (FI_GET_FLAG(finfo, FI_LITTLE_ENDIAN))
bmask_le = 1;
else if (FI_GET_FLAG(finfo, FI_BIG_ENDIAN))
/* XXX, mask has only 32 bit, later we can store bito&bitc, and use them (which should be faster) */
if (bitt > 0 && bitt < 32) {
- bmask = ((1 << bitc) - 1) << ((8-bitt) & 7);
+ bmask = ((G_GUINT64_CONSTANT(1) << bitc) - 1) << ((8-bitt) & 7);
bmask_le = 0; /* ? */
}
}
}
- if (bstart >= 0 && blen > 0 && (guint)bstart < len) {
+ if (pstart >= 0 && plen > 0 && (guint)pstart < len)
+ pend = pstart + plen;
+
+ if (bstart >= 0 && blen > 0 && (guint)bstart < len)
bend = bstart + blen;
- }
- if (astart >= 0 && alen > 0 && (guint)astart < len) {
+
+ if (astart >= 0 && alen > 0 && (guint)astart < len)
aend = astart + alen;
- }
if (bend == -1 && aend != -1) {
bstart = astart;
/* don't exceed the end of available data */
if (aend != -1 && (guint)aend > len) aend = len;
if (bend != -1 && (guint)bend > len) bend = len;
+ if (pend != -1 && (guint)pend > len) pend = len;
/* save the information needed to redraw the text */
/* should we save the fd & finfo pointers instead ?? */
g_object_set_data(G_OBJECT(bv), E_BYTE_VIEW_START_KEY, GINT_TO_POINTER(bstart));
g_object_set_data(G_OBJECT(bv), E_BYTE_VIEW_END_KEY, GINT_TO_POINTER(bend));
- g_object_set_data(G_OBJECT(bv), E_BYTE_VIEW_MASK_KEY, GINT_TO_POINTER(bmask));
+ g_object_set_data(G_OBJECT(bv), E_BYTE_VIEW_MASK_LO_KEY, GINT_TO_POINTER((guint32) bmask));
+ g_object_set_data(G_OBJECT(bv), E_BYTE_VIEW_MASK_HI_KEY, GINT_TO_POINTER((guint32)(bmask >> 32)));
g_object_set_data(G_OBJECT(bv), E_BYTE_VIEW_MASKLE_KEY, GINT_TO_POINTER(bmask_le));
g_object_set_data(G_OBJECT(bv), E_BYTE_VIEW_APP_START_KEY, GINT_TO_POINTER(astart));
g_object_set_data(G_OBJECT(bv), E_BYTE_VIEW_APP_END_KEY, GINT_TO_POINTER(aend));
+ g_object_set_data(G_OBJECT(bv), E_BYTE_VIEW_PROTO_START_KEY, GINT_TO_POINTER(pstart));
+ g_object_set_data(G_OBJECT(bv), E_BYTE_VIEW_PROTO_END_KEY, GINT_TO_POINTER(pend));
g_object_set_data(G_OBJECT(bv), E_BYTE_VIEW_ENCODE_KEY,
GUINT_TO_POINTER((guint)fd->flags.encoding));
/* stig: it should be done only for bitview... */
if (recent.gui_bytes_view != BYTES_BITS)
bmask = 0x00;
- packet_hex_update(bv, pd, len, bstart, bend, bmask, bmask_le, astart, aend, fd->flags.encoding);
+ packet_hex_update(bv, pd, len, bstart, bend, bmask, bmask_le, astart, aend, pstart, pend, (packet_char_enc)fd->flags.encoding);
}
void
/* to redraw the display if preferences change. */
int bstart = offset, bend = (bstart != -1) ? offset+1 : -1;
- guint32 bmask=0; int bmask_le = 0;
+ guint64 bmask=0; int bmask_le = 0;
int astart = -1, aend = -1;
+ int pstart = -1, pend = -1;
switch (recent.gui_bytes_view) {
case BYTES_HEX:
break;
case BYTES_BITS:
- bmask = (1 << (7-bitoffset));
+ bmask = (G_GUINT64_CONSTANT(1) << (7-bitoffset));
break;
default:
/* save the information needed to redraw the text */
g_object_set_data(G_OBJECT(bv), E_BYTE_VIEW_START_KEY, GINT_TO_POINTER(bstart));
g_object_set_data(G_OBJECT(bv), E_BYTE_VIEW_END_KEY, GINT_TO_POINTER(bend));
- g_object_set_data(G_OBJECT(bv), E_BYTE_VIEW_MASK_KEY, GINT_TO_POINTER(bmask));
+ g_object_set_data(G_OBJECT(bv), E_BYTE_VIEW_MASK_LO_KEY, GINT_TO_POINTER((guint32) bmask));
+ g_object_set_data(G_OBJECT(bv), E_BYTE_VIEW_MASK_HI_KEY, GINT_TO_POINTER((guint32)(bmask >> 32)));
g_object_set_data(G_OBJECT(bv), E_BYTE_VIEW_MASKLE_KEY, GINT_TO_POINTER(bmask_le));
g_object_set_data(G_OBJECT(bv), E_BYTE_VIEW_APP_START_KEY, GINT_TO_POINTER(astart));
g_object_set_data(G_OBJECT(bv), E_BYTE_VIEW_APP_END_KEY, GINT_TO_POINTER(aend));
g_object_set_data(G_OBJECT(bv), E_BYTE_VIEW_ENCODE_KEY,
GUINT_TO_POINTER((guint)fd->flags.encoding));
+ g_object_set_data(G_OBJECT(bv), E_BYTE_VIEW_PROTO_START_KEY, GINT_TO_POINTER(pstart));
+ g_object_set_data(G_OBJECT(bv), E_BYTE_VIEW_PROTO_END_KEY, GINT_TO_POINTER(pend));
- packet_hex_update(bv, pd, len, bstart, bend, bmask, bmask_le, astart, aend, fd->flags.encoding);
+ packet_hex_update(bv, pd, len, bstart, bend, bmask, bmask_le, astart, aend, pstart, pend, (packet_char_enc)fd->flags.encoding);
}
/*
void
packet_hex_reprint(GtkWidget *bv)
{
- int start, end, mask, mask_le, encoding;
+ int start, end, mask_le;
+ packet_char_enc encoding;
int astart, aend;
+ int pstart, pend;
+ guint64 mask;
const guint8 *data;
guint len = 0;
start = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(bv), E_BYTE_VIEW_START_KEY));
end = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(bv), E_BYTE_VIEW_END_KEY));
- mask = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(bv), E_BYTE_VIEW_MASK_KEY));
+ mask = (guint64) GPOINTER_TO_INT(g_object_get_data(G_OBJECT(bv), E_BYTE_VIEW_MASK_HI_KEY)) << 32 |
+ GPOINTER_TO_INT(g_object_get_data(G_OBJECT(bv), E_BYTE_VIEW_MASK_LO_KEY));
mask_le = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(bv), E_BYTE_VIEW_MASKLE_KEY));
astart = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(bv), E_BYTE_VIEW_APP_START_KEY));
aend = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(bv), E_BYTE_VIEW_APP_END_KEY));
+ pstart = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(bv), E_BYTE_VIEW_PROTO_START_KEY));
+ pend = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(bv), E_BYTE_VIEW_PROTO_END_KEY));
data = get_byte_view_data_and_length(bv, &len);
g_assert(data != NULL);
- encoding = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(bv), E_BYTE_VIEW_ENCODE_KEY));
+ encoding = (packet_char_enc) GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(bv), E_BYTE_VIEW_ENCODE_KEY));
/* stig: it should be done only for bitview... */
if (recent.gui_bytes_view != BYTES_BITS)
mask = 0x00;
- packet_hex_update(bv, data, len, start, end, mask, mask_le, astart, aend, encoding);
+ packet_hex_update(bv, data, len, start, end, mask, mask_le, astart, aend, pstart, pend, encoding);
}
/* List of all protocol tree widgets, so we can globally set the selection
if(colors_ok) {
return;
}
-#if 0
- /* Allocating collor isn't necessary? */
- get_color(&expert_color_chat);
- get_color(&expert_color_note);
- get_color(&expert_color_warn);
- get_color(&expert_color_error);
- get_color(&expert_color_foreground);
-#endif
expert_color_comment_str = gdk_color_to_string(&expert_color_comment);
expert_color_chat_str = gdk_color_to_string(&expert_color_chat);
expert_color_note_str = gdk_color_to_string(&expert_color_note);
expert_color_error_str = gdk_color_to_string(&expert_color_error);
expert_color_foreground_str = gdk_color_to_string(&expert_color_foreground);
-#if 0
- get_color(&hidden_proto_item);
-#endif
colors_ok = TRUE;
}
expand_all_tree(proto_tree *protocol_tree _U_, GtkWidget *tree_view)
{
int i;
- for(i=0; i < num_tree_types; i++) {
- tree_is_expanded[i] = TRUE;
- }
+
+ for(i=0; i < num_tree_types; i++)
+ tree_expanded_set(i, TRUE);
+
gtk_tree_view_expand_all(GTK_TREE_VIEW(tree_view));
}
collapse_all_tree(proto_tree *protocol_tree _U_, GtkWidget *tree_view)
{
int i;
- for(i=0; i < num_tree_types; i++) {
- tree_is_expanded[i] = FALSE;
- }
+
+ for(i=0; i < num_tree_types; i++)
+ tree_expanded_set(i, FALSE);
+
gtk_tree_view_collapse_all(GTK_TREE_VIEW(tree_view));
}
cf_goto_frame(&cfile, fi->value.value.uinteger);
}
if(FI_GET_FLAG(fi, FI_URL) && IS_FT_STRING(fi->hfinfo->type)) {
- url = fvalue_to_string_repr(&fi->value, FTREPR_DISPLAY, NULL);
+ url = fvalue_to_string_repr(NULL, &fi->value, FTREPR_DISPLAY, fi->hfinfo->display);
if(url){
browser_open_url(url);
- g_free(url);
+ wmem_free(NULL, url);
}
}
}
return TRUE;
}
-static gboolean
-expand_finfos(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
-{
- GtkTreeView *tree_view = (GtkTreeView *) data;
- field_info *fi;
-
- if (!gtk_tree_model_iter_has_child(model, iter))
- return FALSE;
-
- gtk_tree_model_get(model, iter, 1, &fi, -1);
-
- g_assert(fi->tree_type >= 0 && fi->tree_type < num_tree_types);
-
- if (tree_is_expanded[fi->tree_type])
- gtk_tree_view_expand_to_path(tree_view, path);
- else
- gtk_tree_view_collapse_row(tree_view, path);
- return FALSE;
-}
-
void
proto_tree_draw_resolve(proto_tree *protocol_tree, GtkWidget *tree_view, const e_addr_resolve *resolv)
{
ProtoTreeModel *model;
+ GtkTreePath *path;
+ GtkTreeIter iter;
model = proto_tree_model_new(protocol_tree, prefs.display_hidden_proto_items);
if (resolv)
proto_tree_model_force_resolv(PROTO_TREE_MODEL(model), resolv);
gtk_tree_view_set_model(GTK_TREE_VIEW(tree_view), GTK_TREE_MODEL(model));
- gtk_tree_model_foreach(GTK_TREE_MODEL(model), expand_finfos, GTK_TREE_VIEW(tree_view));
+ g_signal_handlers_block_by_func(tree_view, expand_tree, NULL);
+
+ /* modified version of gtk_tree_model_foreach */
+ path = gtk_tree_path_new_first();
+ if (gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, path))
+ check_expand_trees(GTK_TREE_VIEW(tree_view), GTK_TREE_MODEL(model),
+ path, &iter, prefs.gui_auto_scroll_on_expand, TRUE);
+ gtk_tree_path_free(path);
+
+ g_signal_handlers_unblock_by_func(tree_view, expand_tree, NULL);
+
g_object_unref(G_OBJECT(model));
}
}
void
-select_bytes_view (GtkWidget *w _U_, gpointer data _U_, gint view)
+select_bytes_view (GtkWidget *w _U_, gpointer data _U_, bytes_view_type view)
{
if (recent.gui_bytes_view != view) {
recent.gui_bytes_view = view;
redraw_packet_bytes_all();
}
}
+
+/*
+ * Editor modelines - http://www.wireshark.org/tools/modelines.html
+ *
+ * Local variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vi: set shiftwidth=4 tabstop=8 expandtab:
+ * :indentSize=4:tabSize=8:noTabs=true:
+ */