2 * Routines for printing packet analysis trees.
6 * Gilbert Ramirez <gram@alumni.rice.edu>
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
10 * Copyright 1998 Gerald Combs
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
33 #include <glib/gprintf.h>
35 #include <epan/epan.h>
36 #include <epan/epan_dissect.h>
37 #include <epan/to_str.h>
38 #include <epan/tvbuff.h>
39 #include <epan/packet.h>
40 #include <ftypes/ftypes-int.h>
41 #include <epan/emem.h>
42 #include <epan/expert.h>
44 #include <epan/packet-range.h>
48 #include "version_info.h"
49 #include <wsutil/file_util.h>
50 #include <epan/charsets.h>
51 #include <epan/dissectors/packet-data.h>
52 #include <epan/dissectors/packet-frame.h>
53 #include <epan/filesystem.h>
55 #define PDML_VERSION "0"
56 #define PSML_VERSION "0"
60 print_stream_t
*stream
;
63 print_dissections_e print_dissections
;
64 gboolean print_hex_for_data
;
65 packet_char_enc encoding
;
77 output_fields_t
*fields
;
81 struct _output_fields
{
82 gboolean print_header
;
87 GHashTable
*field_indicies
;
88 GPtrArray
**field_values
;
90 gboolean includes_col_fields
;
93 GHashTable
*output_only_tables
= NULL
;
95 static gboolean write_headers
= FALSE
;
97 static const gchar
*get_field_hex_value(GSList
*src_list
, field_info
*fi
);
98 static void proto_tree_print_node(proto_node
*node
, gpointer data
);
99 static void proto_tree_write_node_pdml(proto_node
*node
, gpointer data
);
100 static const guint8
*get_field_data(GSList
*src_list
, field_info
*fi
);
101 static void write_pdml_field_hex_value(write_pdml_data
*pdata
, field_info
*fi
);
102 static gboolean
print_hex_data_buffer(print_stream_t
*stream
, const guchar
*cp
,
103 guint length
, packet_char_enc encoding
);
104 static void ps_clean_string(char *out
, const char *in
,
106 static void print_escaped_xml(FILE *fh
, const char *unescaped_string
);
108 static void print_pdml_geninfo(proto_tree
*tree
, FILE *fh
);
110 static void proto_tree_get_node_field_values(proto_node
*node
, gpointer data
);
113 open_print_dest(gboolean to_file
, const char *dest
)
117 /* Open the file or command for output */
119 fh
= ws_fopen(dest
, "w");
121 fh
= popen(dest
, "w");
127 close_print_dest(gboolean to_file
, FILE *fh
)
129 /* Close the file or command */
131 return (fclose(fh
) == 0);
133 return (pclose(fh
) == 0);
136 #define MAX_PS_LINE_LENGTH 256
139 proto_tree_print(print_args_t
*print_args
, epan_dissect_t
*edt
,
140 print_stream_t
*stream
)
144 /* Create the output */
146 data
.stream
= stream
;
148 data
.src_list
= edt
->pi
.data_src
;
149 data
.encoding
= (packet_char_enc
)edt
->pi
.fd
->flags
.encoding
;
150 data
.print_dissections
= print_args
->print_dissections
;
151 /* If we're printing the entire packet in hex, don't
152 print uninterpreted data fields in hex as well. */
153 data
.print_hex_for_data
= !print_args
->print_hex
;
156 proto_tree_children_foreach(edt
->tree
, proto_tree_print_node
, &data
);
160 #define MAX_INDENT 160
162 /* Print a tree's data, and any child nodes. */
164 proto_tree_print_node(proto_node
*node
, gpointer data
)
166 field_info
*fi
= PNODE_FINFO(node
);
167 print_data
*pdata
= (print_data
*) data
;
169 gchar label_str
[ITEM_LABEL_LENGTH
];
172 /* dissection with an invisible proto tree? */
175 /* Don't print invisible entries. */
176 if (PROTO_ITEM_IS_HIDDEN(node
))
179 /* Give up if we've already gotten an error. */
183 /* was a free format label produced? */
185 label_ptr
= fi
->rep
->representation
;
187 else { /* no, make a generic label */
188 label_ptr
= label_str
;
189 proto_item_fill_label(fi
, label_str
);
192 if (PROTO_ITEM_IS_GENERATED(node
))
193 label_ptr
= g_strconcat("[", label_ptr
, "]", NULL
);
195 pdata
->success
= print_line(pdata
->stream
, pdata
->level
, label_ptr
);
197 if (PROTO_ITEM_IS_GENERATED(node
))
204 * If -O is specified, only display the protocols which are in the
205 * lookup table. Only check on the first level: once we start printing
206 * a tree, print the rest of the subtree. Otherwise we won't print
207 * subitems whose abbreviation doesn't match the protocol--for example
208 * text items (whose abbreviation is simply "text").
210 if ((output_only_tables
!= NULL
) && (pdata
->level
== 0)
211 && (g_hash_table_lookup(output_only_tables
, fi
->hfinfo
->abbrev
) == NULL
)) {
215 /* If it's uninterpreted data, dump it (unless our caller will
216 be printing the entire packet in hex). */
217 if ((fi
->hfinfo
->id
== proto_data
) && (pdata
->print_hex_for_data
)) {
219 * Find the data for this field.
221 pd
= get_field_data(pdata
->src_list
, fi
);
223 if (!print_line(pdata
->stream
, 0, "")) {
224 pdata
->success
= FALSE
;
227 if (!print_hex_data_buffer(pdata
->stream
, pd
,
228 fi
->length
, pdata
->encoding
)) {
229 pdata
->success
= FALSE
;
235 /* If we're printing all levels, or if this node is one with a
236 subtree and its subtree is expanded, recurse into the subtree,
238 g_assert((fi
->tree_type
>= -1) && (fi
->tree_type
< num_tree_types
));
239 if ((pdata
->print_dissections
== print_dissections_expanded
) ||
240 ((pdata
->print_dissections
== print_dissections_as_displayed
) &&
241 (fi
->tree_type
>= 0) && tree_expanded(fi
->tree_type
))) {
242 if (node
->first_child
!= NULL
) {
244 proto_tree_children_foreach(node
,
245 proto_tree_print_node
, pdata
);
253 #define PDML2HTML_XSL "pdml2html.xsl"
255 write_pdml_preamble(FILE *fh
, const gchar
*filename
)
257 time_t t
= time(NULL
);
258 char *ts
= asctime(localtime(&t
));
260 ts
[strlen(ts
)-1] = 0; /* overwrite \n */
262 fputs("<?xml version=\"1.0\"?>\n", fh
);
263 fputs("<?xml-stylesheet type=\"text/xsl\" href=\"" PDML2HTML_XSL
"\"?>\n", fh
);
264 fprintf(fh
, "<!-- You can find " PDML2HTML_XSL
" in %s or at http://anonsvn.wireshark.org/trunk/wireshark/" PDML2HTML_XSL
". -->\n", get_datafile_dir());
265 fputs("<pdml version=\"" PDML_VERSION
"\" ", fh
);
266 fprintf(fh
, "creator=\"%s/%s\" time=\"%s\" capture_file=\"%s\">\n", PACKAGE
, VERSION
, ts
, filename
? filename
: "");
270 proto_tree_write_pdml(epan_dissect_t
*edt
, FILE *fh
)
272 write_pdml_data data
;
274 /* Create the output */
277 data
.src_list
= edt
->pi
.data_src
;
280 fprintf(fh
, "<packet>\n");
282 /* Print a "geninfo" protocol as required by PDML */
283 print_pdml_geninfo(edt
->tree
, fh
);
285 proto_tree_children_foreach(edt
->tree
, proto_tree_write_node_pdml
,
288 fprintf(fh
, "</packet>\n\n");
291 /* Write out a tree's data, and any child nodes, as PDML */
293 proto_tree_write_node_pdml(proto_node
*node
, gpointer data
)
295 field_info
*fi
= PNODE_FINFO(node
);
296 write_pdml_data
*pdata
= (write_pdml_data
*) data
;
297 const gchar
*label_ptr
;
298 gchar label_str
[ITEM_LABEL_LENGTH
];
299 char *dfilter_string
;
302 gboolean wrap_in_fake_protocol
;
304 /* dissection with an invisible proto tree? */
307 /* Will wrap up top-level field items inside a fake protocol wrapper to
308 preserve the PDML schema */
309 wrap_in_fake_protocol
=
310 (((fi
->hfinfo
->type
!= FT_PROTOCOL
) ||
311 (fi
->hfinfo
->id
== proto_data
)) &&
312 (pdata
->level
== 0));
314 /* Indent to the correct level */
315 for (i
= -1; i
< pdata
->level
; i
++) {
316 fputs(" ", pdata
->fh
);
319 if (wrap_in_fake_protocol
) {
320 /* Open fake protocol wrapper */
321 fputs("<proto name=\"fake-field-wrapper\">\n", pdata
->fh
);
323 /* Indent to increased level before writing out field */
325 for (i
= -1; i
< pdata
->level
; i
++) {
326 fputs(" ", pdata
->fh
);
330 /* Text label. It's printed as a field with no name. */
331 if (fi
->hfinfo
->id
== hf_text_only
) {
334 label_ptr
= fi
->rep
->representation
;
340 /* Show empty name since it is a required field */
341 fputs("<field name=\"", pdata
->fh
);
342 fputs("\" show=\"", pdata
->fh
);
343 print_escaped_xml(pdata
->fh
, label_ptr
);
345 fprintf(pdata
->fh
, "\" size=\"%d", fi
->length
);
346 if (node
->parent
&& node
->parent
->finfo
&& (fi
->start
< node
->parent
->finfo
->start
)) {
347 fprintf(pdata
->fh
, "\" pos=\"%d", node
->parent
->finfo
->start
+ fi
->start
);
349 fprintf(pdata
->fh
, "\" pos=\"%d", fi
->start
);
352 fputs("\" value=\"", pdata
->fh
);
353 write_pdml_field_hex_value(pdata
, fi
);
355 if (node
->first_child
!= NULL
) {
356 fputs("\">\n", pdata
->fh
);
359 fputs("\"/>\n", pdata
->fh
);
363 /* Uninterpreted data, i.e., the "Data" protocol, is
364 * printed as a field instead of a protocol. */
365 else if (fi
->hfinfo
->id
== proto_data
) {
367 /* Write out field with data */
368 fputs("<field name=\"data\" value=\"", pdata
->fh
);
369 write_pdml_field_hex_value(pdata
, fi
);
370 fputs("\">\n", pdata
->fh
);
372 /* Normal protocols and fields */
374 if ((fi
->hfinfo
->type
== FT_PROTOCOL
) && (fi
->hfinfo
->id
!= proto_expert
)) {
375 fputs("<proto name=\"", pdata
->fh
);
378 fputs("<field name=\"", pdata
->fh
);
380 print_escaped_xml(pdata
->fh
, fi
->hfinfo
->abbrev
);
384 * http://www.nbee.org/doku.php?id=netpdl:pdml_specification
386 * the show fields contains things in 'human readable' format
387 * showname: contains only the name of the field
388 * show: contains only the data of the field
389 * showdtl: contains additional details of the field data
390 * showmap: contains mappings of the field data (e.g. the hostname to an IP address)
392 * XXX - the showname shouldn't contain the field data itself
393 * (like it's contained in the fi->rep->representation).
394 * Unfortunately, we don't have the field data representation for
395 * all fields, so this isn't currently possible */
396 fputs("\" showname=\"", pdata
->fh
);
397 print_escaped_xml(pdata
->fh
, fi
->hfinfo
->name
);
401 fputs("\" showname=\"", pdata
->fh
);
402 print_escaped_xml(pdata
->fh
, fi
->rep
->representation
);
405 label_ptr
= label_str
;
406 proto_item_fill_label(fi
, label_str
);
407 fputs("\" showname=\"", pdata
->fh
);
408 print_escaped_xml(pdata
->fh
, label_ptr
);
411 if (PROTO_ITEM_IS_HIDDEN(node
))
412 fprintf(pdata
->fh
, "\" hide=\"yes");
414 fprintf(pdata
->fh
, "\" size=\"%d", fi
->length
);
415 if (node
->parent
&& node
->parent
->finfo
&& (fi
->start
< node
->parent
->finfo
->start
)) {
416 fprintf(pdata
->fh
, "\" pos=\"%d", node
->parent
->finfo
->start
+ fi
->start
);
418 fprintf(pdata
->fh
, "\" pos=\"%d", fi
->start
);
420 /* fprintf(pdata->fh, "\" id=\"%d", fi->hfinfo->id);*/
422 /* show, value, and unmaskedvalue attributes */
423 switch (fi
->hfinfo
->type
)
428 fputs("\" show=\"\" value=\"", pdata
->fh
);
431 /* XXX - this is a hack until we can just call
432 * fvalue_to_string_repr() for *all* FT_* types. */
433 dfilter_string
= proto_construct_match_selected_string(fi
,
435 if (dfilter_string
!= NULL
) {
436 chop_len
= strlen(fi
->hfinfo
->abbrev
) + 4; /* for " == " */
438 /* XXX - Remove double-quotes. Again, once we
439 * can call fvalue_to_string_repr(), we can
440 * ask it not to produce the version for
441 * display-filters, and thus, no
443 if (dfilter_string
[strlen(dfilter_string
)-1] == '"') {
444 dfilter_string
[strlen(dfilter_string
)-1] = '\0';
448 fputs("\" show=\"", pdata
->fh
);
449 print_escaped_xml(pdata
->fh
, &dfilter_string
[chop_len
]);
453 * XXX - should we omit "value" for any fields?
454 * What should we do for fields whose length is 0?
455 * They might come from a pseudo-header or from
456 * the capture header (e.g., time stamps), or
457 * they might be generated fields.
459 if (fi
->length
> 0) {
460 fputs("\" value=\"", pdata
->fh
);
462 if (fi
->hfinfo
->bitmask
!=0) {
463 switch (fi
->value
.ftype
->ftype
) {
468 fprintf(pdata
->fh
, "%X", (guint
) fvalue_get_sinteger(&fi
->value
));
475 fprintf(pdata
->fh
, "%X", fvalue_get_uinteger(&fi
->value
));
479 g_fprintf(pdata
->fh
, "%" G_GINT64_MODIFIER
"X",
480 fvalue_get_integer64(&fi
->value
));
483 g_assert_not_reached();
485 fputs("\" unmaskedvalue=\"", pdata
->fh
);
486 write_pdml_field_hex_value(pdata
, fi
);
489 write_pdml_field_hex_value(pdata
, fi
);
494 if (node
->first_child
!= NULL
) {
495 fputs("\">\n", pdata
->fh
);
497 else if (fi
->hfinfo
->id
== proto_data
) {
498 fputs("\">\n", pdata
->fh
);
501 fputs("\"/>\n", pdata
->fh
);
505 /* We always print all levels for PDML. Recurse here. */
506 if (node
->first_child
!= NULL
) {
508 proto_tree_children_foreach(node
,
509 proto_tree_write_node_pdml
, pdata
);
513 /* Take back the extra level we added for fake wrapper protocol */
514 if (wrap_in_fake_protocol
) {
518 if (node
->first_child
!= NULL
) {
519 /* Indent to correct level */
520 for (i
= -1; i
< pdata
->level
; i
++) {
521 fputs(" ", pdata
->fh
);
523 /* Close off current element */
524 /* Data and expert "protocols" use simple tags */
525 if ((fi
->hfinfo
->id
!= proto_data
) && (fi
->hfinfo
->id
!= proto_expert
)) {
526 if (fi
->hfinfo
->type
== FT_PROTOCOL
) {
527 fputs("</proto>\n", pdata
->fh
);
530 fputs("</field>\n", pdata
->fh
);
533 fputs("</field>\n", pdata
->fh
);
537 /* Close off fake wrapper protocol */
538 if (wrap_in_fake_protocol
) {
539 fputs("</proto>\n", pdata
->fh
);
543 /* Print info for a 'geninfo' pseudo-protocol. This is required by
544 * the PDML spec. The information is contained in Wireshark's 'frame' protocol,
545 * but we produce a 'geninfo' protocol in the PDML to conform to spec.
546 * The 'frame' protocol follows the 'geninfo' protocol in the PDML. */
548 print_pdml_geninfo(proto_tree
*tree
, FILE *fh
)
550 guint32 num
, len
, caplen
;
552 GPtrArray
*finfo_array
;
553 field_info
*frame_finfo
;
555 /* Get frame protocol's finfo. */
556 finfo_array
= proto_find_finfo(tree
, proto_frame
);
557 if (g_ptr_array_len(finfo_array
) < 1) {
560 frame_finfo
= (field_info
*)finfo_array
->pdata
[0];
561 g_ptr_array_free(finfo_array
, TRUE
);
563 /* frame.number --> geninfo.num */
564 finfo_array
= proto_find_finfo(tree
, hf_frame_number
);
565 if (g_ptr_array_len(finfo_array
) < 1) {
568 num
= fvalue_get_uinteger(&((field_info
*)finfo_array
->pdata
[0])->value
);
569 g_ptr_array_free(finfo_array
, TRUE
);
571 /* frame.frame_len --> geninfo.len */
572 finfo_array
= proto_find_finfo(tree
, hf_frame_len
);
573 if (g_ptr_array_len(finfo_array
) < 1) {
576 len
= fvalue_get_uinteger(&((field_info
*)finfo_array
->pdata
[0])->value
);
577 g_ptr_array_free(finfo_array
, TRUE
);
579 /* frame.cap_len --> geninfo.caplen */
580 finfo_array
= proto_find_finfo(tree
, hf_frame_capture_len
);
581 if (g_ptr_array_len(finfo_array
) < 1) {
584 caplen
= fvalue_get_uinteger(&((field_info
*)finfo_array
->pdata
[0])->value
);
585 g_ptr_array_free(finfo_array
, TRUE
);
587 /* frame.time --> geninfo.timestamp */
588 finfo_array
= proto_find_finfo(tree
, hf_frame_arrival_time
);
589 if (g_ptr_array_len(finfo_array
) < 1) {
592 timestamp
= (nstime_t
*)fvalue_get(&((field_info
*)finfo_array
->pdata
[0])->value
);
593 g_ptr_array_free(finfo_array
, TRUE
);
595 /* Print geninfo start */
597 " <proto name=\"geninfo\" pos=\"0\" showname=\"General information\" size=\"%u\">\n",
598 frame_finfo
->length
);
600 /* Print geninfo.num */
602 " <field name=\"num\" pos=\"0\" show=\"%u\" showname=\"Number\" value=\"%x\" size=\"%u\"/>\n",
603 num
, num
, frame_finfo
->length
);
605 /* Print geninfo.len */
607 " <field name=\"len\" pos=\"0\" show=\"%u\" showname=\"Frame Length\" value=\"%x\" size=\"%u\"/>\n",
608 len
, len
, frame_finfo
->length
);
610 /* Print geninfo.caplen */
612 " <field name=\"caplen\" pos=\"0\" show=\"%u\" showname=\"Captured Length\" value=\"%x\" size=\"%u\"/>\n",
613 caplen
, caplen
, frame_finfo
->length
);
615 /* Print geninfo.timestamp */
617 " <field name=\"timestamp\" pos=\"0\" show=\"%s\" showname=\"Captured Time\" value=\"%d.%09d\" size=\"%u\"/>\n",
618 abs_time_to_str(timestamp
, ABSOLUTE_TIME_LOCAL
, TRUE
), (int) timestamp
->secs
, timestamp
->nsecs
, frame_finfo
->length
);
620 /* Print geninfo end */
626 write_pdml_finale(FILE *fh
)
628 fputs("</pdml>\n", fh
);
632 write_psml_preamble(FILE *fh
)
634 fputs("<?xml version=\"1.0\"?>\n", fh
);
635 fputs("<psml version=\"" PSML_VERSION
"\" ", fh
);
636 fprintf(fh
, "creator=\"%s/%s\">\n", PACKAGE
, VERSION
);
637 write_headers
= TRUE
;
641 proto_tree_write_psml(epan_dissect_t
*edt
, FILE *fh
)
645 /* if this is the first packet, we have to create the PSML structure output */
647 fprintf(fh
, "<structure>\n");
649 for (i
= 0; i
< edt
->pi
.cinfo
->num_cols
; i
++) {
650 fprintf(fh
, "<section>");
651 print_escaped_xml(fh
, edt
->pi
.cinfo
->col_title
[i
]);
652 fprintf(fh
, "</section>\n");
655 fprintf(fh
, "</structure>\n\n");
657 write_headers
= FALSE
;
660 fprintf(fh
, "<packet>\n");
662 for (i
= 0; i
< edt
->pi
.cinfo
->num_cols
; i
++) {
663 fprintf(fh
, "<section>");
664 print_escaped_xml(fh
, edt
->pi
.cinfo
->col_data
[i
]);
665 fprintf(fh
, "</section>\n");
668 fprintf(fh
, "</packet>\n\n");
672 write_psml_finale(FILE *fh
)
674 fputs("</psml>\n", fh
);
678 write_csv_preamble(FILE *fh _U_
)
680 write_headers
= TRUE
;
683 static gchar
*csv_massage_str(const gchar
*source
, const gchar
*exceptions
)
688 csv_str
= g_strescape(source
, exceptions
);
690 while ( (tmp_str
= strstr(tmp_str
, "\\\"")) != NULL
)
695 static void csv_write_str(const char *str
, char sep
, FILE *fh
)
699 csv_str
= csv_massage_str(str
, NULL
);
700 fprintf(fh
, "\"%s\"%c", csv_str
, sep
);
705 proto_tree_write_csv(epan_dissect_t
*edt
, FILE *fh
)
709 /* if this is the first packet, we have to write the CSV header */
711 for (i
= 0; i
< edt
->pi
.cinfo
->num_cols
- 1; i
++)
712 csv_write_str(edt
->pi
.cinfo
->col_title
[i
], ',', fh
);
713 csv_write_str(edt
->pi
.cinfo
->col_title
[i
], '\n', fh
);
714 write_headers
= FALSE
;
717 for (i
= 0; i
< edt
->pi
.cinfo
->num_cols
- 1; i
++)
718 csv_write_str(edt
->pi
.cinfo
->col_data
[i
], ',', fh
);
719 csv_write_str(edt
->pi
.cinfo
->col_data
[i
], '\n', fh
);
723 write_csv_finale(FILE *fh _U_
)
729 write_carrays_preamble(FILE *fh _U_
)
735 proto_tree_write_carrays(guint32 num
, FILE *fh
, epan_dissect_t
*edt
)
737 guint32 i
= 0, src_num
= 0;
744 struct data_source
*src
;
746 for (src_le
= edt
->pi
.data_src
; src_le
!= NULL
; src_le
= src_le
->next
) {
747 memset(ascii
, 0, sizeof(ascii
));
748 src
= (struct data_source
*)src_le
->data
;
749 tvb
= get_data_source_tvb(src
);
750 length
= tvb_length(tvb
);
754 cp
= tvb_get_ptr(tvb
, 0, length
);
756 name
= get_data_source_name(src
);
758 fprintf(fh
, "/* %s */\n", name
);
760 fprintf(fh
, "static const unsigned char pkt%u_%u[%u] = {\n",
761 num
, src_num
, length
);
763 fprintf(fh
, "static const unsigned char pkt%u[%u] = {\n",
768 for (i
= 0; i
< length
; i
++) {
769 fprintf(fh
, "0x%02x", *(cp
+ i
));
770 ascii
[i
% 8] = isprint(*(cp
+ i
)) ? *(cp
+ i
) : '.';
772 if (i
== (length
- 1)) {
777 for ( j
= 0; j
< 8 - rem
; j
++ )
780 fprintf(fh
, " /* %s */\n};\n\n", ascii
);
784 if (!((i
+ 1) % 8)) {
785 fprintf(fh
, ", /* %s */\n", ascii
);
786 memset(ascii
, 0, sizeof(ascii
));
796 write_carrays_finale(FILE *fh _U_
)
802 * Find the data source for a specified field, and return a pointer
803 * to the data in it. Returns NULL if the data is out of bounds.
805 /* XXX: What am I missing ?
806 * Why bother searching for fi->ds_tvb for the matching tvb
807 * in the data_source list ?
808 * IOW: Why not just use fi->ds_tvb for the arg to tvb_get_ptr() ?
811 static const guint8
*
812 get_field_data(GSList
*src_list
, field_info
*fi
)
816 gint length
, tvbuff_length
;
817 struct data_source
*src
;
819 for (src_le
= src_list
; src_le
!= NULL
; src_le
= src_le
->next
) {
820 src
= (struct data_source
*)src_le
->data
;
821 src_tvb
= get_data_source_tvb(src
);
822 if (fi
->ds_tvb
== src_tvb
) {
826 * XXX - a field can have a length that runs past
827 * the end of the tvbuff. Ideally, that should
828 * be fixed when adding an item to the protocol
829 * tree, but checking the length when doing
830 * that could be expensive. Until we fix that,
831 * we'll do the check here.
833 tvbuff_length
= tvb_length_remaining(src_tvb
,
835 if (tvbuff_length
< 0) {
839 if (length
> tvbuff_length
)
840 length
= tvbuff_length
;
841 return tvb_get_ptr(src_tvb
, fi
->start
, length
);
844 g_assert_not_reached();
845 return NULL
; /* not found */
848 /* Print a string, escaping out certain characters that need to
849 * escaped out for XML. */
851 print_escaped_xml(FILE *fh
, const char *unescaped_string
)
856 for (p
= unescaped_string
; *p
!= '\0'; p
++) {
874 if (g_ascii_isprint(*p
))
877 g_snprintf(temp_str
, sizeof(temp_str
), "\\x%x", (guint8
)*p
);
885 write_pdml_field_hex_value(write_pdml_data
*pdata
, field_info
*fi
)
893 if (fi
->length
> tvb_length_remaining(fi
->ds_tvb
, fi
->start
)) {
894 fprintf(pdata
->fh
, "field length invalid!");
898 /* Find the data for this field. */
899 pd
= get_field_data(pdata
->src_list
, fi
);
902 /* Print a simple hex dump */
903 for (i
= 0 ; i
< fi
->length
; i
++) {
904 fprintf(pdata
->fh
, "%02x", pd
[i
]);
910 print_hex_data(print_stream_t
*stream
, epan_dissect_t
*edt
)
912 gboolean multiple_sources
;
919 struct data_source
*src
;
922 * Set "multiple_sources" iff this frame has more than one
923 * data source; if it does, we need to print the name of
924 * the data source before printing the data from the
927 multiple_sources
= (edt
->pi
.data_src
->next
!= NULL
);
929 for (src_le
= edt
->pi
.data_src
; src_le
!= NULL
;
930 src_le
= src_le
->next
) {
931 src
= (struct data_source
*)src_le
->data
;
932 tvb
= get_data_source_tvb(src
);
933 if (multiple_sources
) {
934 name
= get_data_source_name(src
);
935 line
= g_strdup_printf("%s:", name
);
936 print_line(stream
, 0, line
);
939 length
= tvb_length(tvb
);
942 cp
= tvb_get_ptr(tvb
, 0, length
);
943 if (!print_hex_data_buffer(stream
, cp
, length
,
944 (packet_char_enc
)edt
->pi
.fd
->flags
.encoding
))
951 * This routine is based on a routine created by Dan Lasley
952 * <DLASLEY@PROMUS.com>.
954 * It was modified for Wireshark by Gilbert Ramirez and others.
957 #define MAX_OFFSET_LEN 8 /* max length of hex offset of bytes */
958 #define BYTES_PER_LINE 16 /* max byte values printed on a line */
959 #define HEX_DUMP_LEN (BYTES_PER_LINE*3)
960 /* max number of characters hex dump takes -
961 2 digits plus trailing blank */
962 #define DATA_DUMP_LEN (HEX_DUMP_LEN + 2 + BYTES_PER_LINE)
963 /* number of characters those bytes take;
964 3 characters per byte of hex dump,
965 2 blanks separating hex from ASCII,
966 1 character per byte of ASCII dump */
967 #define MAX_LINE_LEN (MAX_OFFSET_LEN + 2 + DATA_DUMP_LEN)
968 /* number of characters per line;
969 offset, 2 blanks separating offset
970 from data dump, data dump */
973 print_hex_data_buffer(print_stream_t
*stream
, const guchar
*cp
,
974 guint length
, packet_char_enc encoding
)
976 register unsigned int ad
, i
, j
, k
, l
;
978 gchar line
[MAX_LINE_LEN
+ 1];
979 unsigned int use_digits
;
981 static gchar binhex
[16] = {
982 '0', '1', '2', '3', '4', '5', '6', '7',
983 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
986 * How many of the leading digits of the offset will we supply?
987 * We always supply at least 4 digits, but if the maximum offset
988 * won't fit in 4 digits, we use as many digits as will be needed.
990 if (((length
- 1) & 0xF0000000) != 0)
991 use_digits
= 8; /* need all 8 digits */
992 else if (((length
- 1) & 0x0F000000) != 0)
993 use_digits
= 7; /* need 7 digits */
994 else if (((length
- 1) & 0x00F00000) != 0)
995 use_digits
= 6; /* need 6 digits */
996 else if (((length
- 1) & 0x000F0000) != 0)
997 use_digits
= 5; /* need 5 digits */
999 use_digits
= 4; /* we'll supply 4 digits */
1005 while (i
< length
) {
1006 if ((i
& 15) == 0) {
1008 * Start of a new line.
1014 c
= (ad
>> (l
*4)) & 0xF;
1015 line
[j
++] = binhex
[c
];
1019 memset(line
+j
, ' ', DATA_DUMP_LEN
);
1022 * Offset in line of ASCII dump.
1024 k
= j
+ HEX_DUMP_LEN
+ 2;
1027 line
[j
++] = binhex
[c
>>4];
1028 line
[j
++] = binhex
[c
&0xf];
1030 if (encoding
== PACKET_CHAR_ENC_CHAR_EBCDIC
) {
1031 c
= EBCDIC_to_ASCII1(c
);
1033 line
[k
++] = ((c
>= ' ') && (c
< 0x7f)) ? c
: '.';
1035 if (((i
& 15) == 0) || (i
== length
)) {
1037 * We'll be starting a new line, or
1038 * we're finished printing this buffer;
1039 * dump out the line we've constructed,
1040 * and advance the offset.
1043 if (!print_line(stream
, 0, line
))
1052 void ps_clean_string(char *out
, const char *in
, int outbuf_size
)
1062 for (rd
= 0, wr
= 0 ; wr
< outbuf_size
; rd
++, wr
++ ) {
1083 /* Some formats need stuff at the beginning of the output */
1085 print_preamble(print_stream_t
*self
, gchar
*filename
, const char *version_string
)
1087 return self
->ops
->print_preamble
? (self
->ops
->print_preamble
)(self
, filename
, version_string
) : TRUE
;
1091 print_line(print_stream_t
*self
, int indent
, const char *line
)
1093 return (self
->ops
->print_line
)(self
, indent
, line
);
1096 /* Insert bookmark */
1098 print_bookmark(print_stream_t
*self
, const gchar
*name
, const gchar
*title
)
1100 return self
->ops
->print_bookmark
? (self
->ops
->print_bookmark
)(self
, name
, title
) : TRUE
;
1104 new_page(print_stream_t
*self
)
1106 return self
->ops
->new_page
? (self
->ops
->new_page
)(self
) : TRUE
;
1109 /* Some formats need stuff at the end of the output */
1111 print_finale(print_stream_t
*self
)
1113 return self
->ops
->print_finale
? (self
->ops
->print_finale
)(self
) : TRUE
;
1117 destroy_print_stream(print_stream_t
*self
)
1119 return self
->ops
->destroy
? (self
->ops
->destroy
)(self
) : TRUE
;
1128 print_line_text(print_stream_t
*self
, int indent
, const char *line
)
1130 static char spaces
[MAX_INDENT
];
1133 output_text
*output
= (output_text
*)self
->data
;
1134 unsigned int num_spaces
;
1136 /* should be space, if NUL -> initialize */
1140 for (i
= 0; i
< MAX_INDENT
; i
++)
1144 /* Prepare the tabs for printing, depending on tree level */
1145 num_spaces
= indent
* 4;
1146 if (num_spaces
> MAX_INDENT
)
1147 num_spaces
= MAX_INDENT
;
1149 ret
= fwrite(spaces
, 1, num_spaces
, output
->fh
);
1150 if (ret
== num_spaces
) {
1151 fputs(line
, output
->fh
);
1152 putc('\n', output
->fh
);
1154 return !ferror(output
->fh
);
1158 new_page_text(print_stream_t
*self
)
1160 output_text
*output
= (output_text
*)self
->data
;
1162 fputs("\f", output
->fh
);
1163 return !ferror(output
->fh
);
1167 destroy_text(print_stream_t
*self
)
1169 output_text
*output
= (output_text
*)self
->data
;
1172 ret
= close_print_dest(output
->to_file
, output
->fh
);
1178 static const print_stream_ops_t print_text_ops
= {
1179 NULL
, /* preamble */
1181 NULL
, /* bookmark */
1187 static print_stream_t
*
1188 print_stream_text_alloc(gboolean to_file
, FILE *fh
)
1190 print_stream_t
*stream
;
1191 output_text
*output
;
1193 output
= (output_text
*)g_malloc(sizeof *output
);
1194 output
->to_file
= to_file
;
1196 stream
= (print_stream_t
*)g_malloc(sizeof (print_stream_t
));
1197 stream
->ops
= &print_text_ops
;
1198 stream
->data
= output
;
1204 print_stream_text_new(gboolean to_file
, const char *dest
)
1208 fh
= open_print_dest(to_file
, dest
);
1212 return print_stream_text_alloc(to_file
, fh
);
1216 print_stream_text_stdio_new(FILE *fh
)
1218 return print_stream_text_alloc(TRUE
, fh
);
1227 print_preamble_ps(print_stream_t
*self
, gchar
*filename
, const char *version_string
)
1229 output_ps
*output
= (output_ps
*)self
->data
;
1230 char psbuffer
[MAX_PS_LINE_LENGTH
]; /* static sized buffer! */
1232 print_ps_preamble(output
->fh
);
1234 fputs("%% the page title\n", output
->fh
);
1235 ps_clean_string(psbuffer
, filename
, MAX_PS_LINE_LENGTH
);
1236 fprintf(output
->fh
, "/ws_pagetitle (%s - Wireshark " VERSION
"%s) def\n", psbuffer
, version_string
);
1237 fputs("\n", output
->fh
);
1238 return !ferror(output
->fh
);
1242 print_line_ps(print_stream_t
*self
, int indent
, const char *line
)
1244 output_ps
*output
= (output_ps
*)self
->data
;
1245 char psbuffer
[MAX_PS_LINE_LENGTH
]; /* static sized buffer! */
1247 ps_clean_string(psbuffer
, line
, MAX_PS_LINE_LENGTH
);
1248 fprintf(output
->fh
, "%d (%s) putline\n", indent
, psbuffer
);
1249 return !ferror(output
->fh
);
1253 print_bookmark_ps(print_stream_t
*self
, const gchar
*name
, const gchar
*title
)
1255 output_ps
*output
= (output_ps
*)self
->data
;
1256 char psbuffer
[MAX_PS_LINE_LENGTH
]; /* static sized buffer! */
1259 * See the Adobe "pdfmark reference":
1261 * http://partners.adobe.com/asn/acrobat/docs/pdfmark.pdf
1263 * The pdfmark stuff tells code that turns PostScript into PDF
1264 * things that it should do.
1266 * The /OUT stuff creates a bookmark that goes to the
1267 * destination with "name" as the name and "title" as the title.
1269 * The "/DEST" creates the destination.
1271 ps_clean_string(psbuffer
, title
, MAX_PS_LINE_LENGTH
);
1272 fprintf(output
->fh
, "[/Dest /%s /Title (%s) /OUT pdfmark\n", name
,
1274 fputs("[/View [/XYZ -4 currentpoint matrix currentmatrix matrix defaultmatrix\n",
1276 fputs("matrix invertmatrix matrix concatmatrix transform exch pop 20 add null]\n",
1278 fprintf(output
->fh
, "/Dest /%s /DEST pdfmark\n", name
);
1279 return !ferror(output
->fh
);
1283 new_page_ps(print_stream_t
*self
)
1285 output_ps
*output
= (output_ps
*)self
->data
;
1287 fputs("formfeed\n", output
->fh
);
1288 return !ferror(output
->fh
);
1292 print_finale_ps(print_stream_t
*self
)
1294 output_ps
*output
= (output_ps
*)self
->data
;
1296 print_ps_finale(output
->fh
);
1297 return !ferror(output
->fh
);
1301 destroy_ps(print_stream_t
*self
)
1303 output_ps
*output
= (output_ps
*)self
->data
;
1306 ret
= close_print_dest(output
->to_file
, output
->fh
);
1312 static const print_stream_ops_t print_ps_ops
= {
1321 static print_stream_t
*
1322 print_stream_ps_alloc(gboolean to_file
, FILE *fh
)
1324 print_stream_t
*stream
;
1327 output
= (output_ps
*)g_malloc(sizeof *output
);
1328 output
->to_file
= to_file
;
1330 stream
= (print_stream_t
*)g_malloc(sizeof (print_stream_t
));
1331 stream
->ops
= &print_ps_ops
;
1332 stream
->data
= output
;
1338 print_stream_ps_new(gboolean to_file
, const char *dest
)
1342 fh
= open_print_dest(to_file
, dest
);
1346 return print_stream_ps_alloc(to_file
, fh
);
1350 print_stream_ps_stdio_new(FILE *fh
)
1352 return print_stream_ps_alloc(TRUE
, fh
);
1355 output_fields_t
* output_fields_new(void)
1357 output_fields_t
* fields
= g_new(output_fields_t
, 1);
1358 fields
->print_header
= FALSE
;
1359 fields
->separator
= '\t';
1360 fields
->occurrence
= 'a';
1361 fields
->aggregator
= ',';
1362 fields
->fields
= NULL
; /*Do lazy initialisation */
1363 fields
->field_indicies
= NULL
;
1364 fields
->field_values
= NULL
;
1365 fields
->quote
='\0';
1366 fields
->includes_col_fields
= FALSE
;
1370 gsize
output_fields_num_fields(output_fields_t
* fields
)
1374 if (NULL
== fields
->fields
) {
1377 return fields
->fields
->len
;
1381 void output_fields_free(output_fields_t
* fields
)
1385 if (NULL
!= fields
->fields
) {
1388 if (NULL
!= fields
->field_indicies
) {
1389 /* Keys are stored in fields->fields, values are
1392 g_hash_table_destroy(fields
->field_indicies
);
1395 if (NULL
!= fields
->field_values
) {
1396 g_free(fields
->field_values
);
1399 for(i
= 0; i
< fields
->fields
->len
; ++i
) {
1400 gchar
* field
= (gchar
*)g_ptr_array_index(fields
->fields
,i
);
1403 g_ptr_array_free(fields
->fields
, TRUE
);
1409 #define COLUMN_FIELD_FILTER "_ws.col."
1411 void output_fields_add(output_fields_t
*fields
, const gchar
*field
)
1419 if (NULL
== fields
->fields
) {
1420 fields
->fields
= g_ptr_array_new();
1423 field_copy
= g_strdup(field
);
1425 g_ptr_array_add(fields
->fields
, field_copy
);
1427 /* See if we have a column as a field entry */
1428 if (!strncmp(field
, COLUMN_FIELD_FILTER
, strlen(COLUMN_FIELD_FILTER
)))
1429 fields
->includes_col_fields
= TRUE
;
1433 gboolean
output_fields_set_option(output_fields_t
*info
, gchar
*option
)
1435 const gchar
*option_name
;
1436 const gchar
*option_value
;
1441 if ('\0' == *option
) {
1442 return FALSE
; /* Is this guarded against by option parsing? */
1444 option_name
= strtok(option
, "=");
1448 option_value
= option
+ strlen(option_name
) + 1;
1449 if (0 == strcmp(option_name
, "header")) {
1450 switch (NULL
== option_value
? '\0' : *option_value
) {
1452 info
->print_header
= FALSE
;
1455 info
->print_header
= TRUE
;
1463 if (0 == strcmp(option_name
, "separator")) {
1464 switch (NULL
== option_value
? '\0' : *option_value
) {
1468 switch (*++option_value
) {
1470 info
->separator
= '\t';
1473 info
->separator
= ' ';
1476 info
->separator
= '\\';
1480 info
->separator
= *option_value
;
1486 if (0 == strcmp(option_name
, "occurrence")) {
1487 switch (NULL
== option_value
? '\0' : *option_value
) {
1491 info
->occurrence
= *option_value
;
1499 if (0 == strcmp(option_name
, "aggregator")) {
1500 switch (NULL
== option_value
? '\0' : *option_value
) {
1504 switch (*++option_value
) {
1506 info
->aggregator
= ' ';
1509 info
->aggregator
= '\\';
1513 info
->aggregator
= *option_value
;
1519 if (0 == strcmp(option_name
, "quote")) {
1520 switch (NULL
== option_value
? '\0' : *option_value
) {
1521 default: /* Fall through */
1541 void output_fields_list_options(FILE *fh
)
1543 fprintf(fh
, "TShark: The available options for field output \"E\" are:\n");
1544 fputs("header=y|n Print field abbreviations as first line of output (def: N: no)\n", fh
);
1545 fputs("separator=/t|/s|<character> Set the separator to use;\n \"/t\" = tab, \"/s\" = space (def: /t: tab)\n", fh
);
1546 fputs("occurrence=f|l|a Select the occurrence of a field to use;\n \"f\" = first, \"l\" = last, \"a\" = all (def: a: all)\n", fh
);
1547 fputs("aggregator=,|/s|<character> Set the aggregator to use;\n \",\" = comma, \"/s\" = space (def: ,: comma)\n", fh
);
1548 fputs("quote=d|s|n Print either d: double-quotes, s: single quotes or \n n: no quotes around field values (def: n: none)\n", fh
);
1551 gboolean
output_fields_has_cols(output_fields_t
* fields
)
1554 return fields
->includes_col_fields
;
1557 void write_fields_preamble(output_fields_t
* fields
, FILE *fh
)
1563 g_assert(fields
->fields
);
1565 if (!fields
->print_header
) {
1569 for(i
= 0; i
< fields
->fields
->len
; ++i
) {
1570 const gchar
* field
= (const gchar
*)g_ptr_array_index(fields
->fields
,i
);
1572 fputc(fields
->separator
, fh
);
1579 static void format_field_values(output_fields_t
* fields
, gpointer field_index
, const gchar
* value
)
1584 if ((NULL
== value
) || ('\0' == *value
))
1587 /* Unwrap change made to disambiguiate zero / null */
1588 indx
= GPOINTER_TO_UINT(field_index
) - 1;
1590 if (fields
->field_values
[indx
] == NULL
) {
1591 fields
->field_values
[indx
] = g_ptr_array_new();
1594 /* Essentially: fieldvalues[indx] is a 'GPtrArray *' with each array entry */
1595 /* pointing to a string which is (part of) the final output string. */
1597 fv_p
= fields
->field_values
[indx
];
1599 switch (fields
->occurrence
) {
1601 /* print the value of only the first occurrence of the field */
1602 if (g_ptr_array_len(fv_p
) != 0)
1606 /* print the value of only the last occurrence of the field */
1607 g_ptr_array_set_size(fv_p
, 0);
1610 /* print the value of all accurrences of the field */
1611 /* If not the first, add the 'aggregator' */
1612 if (g_ptr_array_len(fv_p
) > 0) {
1613 g_ptr_array_add(fv_p
, (gpointer
)ep_strdup_printf("%c", fields
->aggregator
));
1617 g_assert_not_reached();
1621 g_ptr_array_add(fv_p
, (gpointer
)value
);
1624 static void proto_tree_get_node_field_values(proto_node
*node
, gpointer data
)
1626 write_field_data_t
*call_data
;
1628 gpointer field_index
;
1630 call_data
= (write_field_data_t
*)data
;
1631 fi
= PNODE_FINFO(node
);
1633 /* dissection with an invisible proto tree? */
1636 field_index
= g_hash_table_lookup(call_data
->fields
->field_indicies
, fi
->hfinfo
->abbrev
);
1637 if (NULL
!= field_index
) {
1638 format_field_values(call_data
->fields
, field_index
,
1639 get_node_field_value(fi
, call_data
->edt
) /* static or ep_alloc'd string */
1644 if (node
->first_child
!= NULL
) {
1645 proto_tree_children_foreach(node
, proto_tree_get_node_field_values
,
1650 void proto_tree_write_fields(output_fields_t
*fields
, epan_dissect_t
*edt
, column_info
*cinfo
, FILE *fh
)
1655 gpointer field_index
;
1657 write_field_data_t data
;
1660 g_assert(fields
->fields
);
1664 data
.fields
= fields
;
1667 if (NULL
== fields
->field_indicies
) {
1668 /* Prepare a lookup table from string abbreviation for field to its index. */
1669 fields
->field_indicies
= g_hash_table_new(g_str_hash
, g_str_equal
);
1672 while (i
< fields
->fields
->len
) {
1673 gchar
*field
= (gchar
*)g_ptr_array_index(fields
->fields
, i
);
1674 /* Store field indicies +1 so that zero is not a valid value,
1675 * and can be distinguished from NULL as a pointer.
1678 g_hash_table_insert(fields
->field_indicies
, field
, GUINT_TO_POINTER(i
));
1682 /* Array buffer to store values for this packet */
1683 /* Allocate an array for the 'GPtrarray *' the first time */
1684 /* ths function is invoked for a file; */
1685 /* Any and all 'GPtrArray *' are freed (after use) each */
1686 /* time (each packet) this function is invoked for a flle. */
1687 /* XXX: ToDo: use packet-scope'd memory & (if/when implemented) wmem ptr_array */
1688 if (NULL
== fields
->field_values
)
1689 fields
->field_values
= g_new0(GPtrArray
*, fields
->fields
->len
); /* free'd in output_fields_free() */
1691 proto_tree_children_foreach(edt
->tree
, proto_tree_get_node_field_values
,
1694 if (fields
->includes_col_fields
) {
1695 for (col
= 0; col
< cinfo
->num_cols
; col
++) {
1696 /* Prepend COLUMN_FIELD_FILTER as the field name */
1697 col_name
= ep_strdup_printf("%s%s", COLUMN_FIELD_FILTER
, cinfo
->col_title
[col
]);
1698 field_index
= g_hash_table_lookup(fields
->field_indicies
, col_name
);
1700 if (NULL
!= field_index
) {
1701 format_field_values(fields
, field_index
, cinfo
->col_data
[col
]);
1706 for(i
= 0; i
< fields
->fields
->len
; ++i
) {
1708 fputc(fields
->separator
, fh
);
1710 if (NULL
!= fields
->field_values
[i
]) {
1713 fv_p
= fields
->field_values
[i
];
1714 if (fields
->quote
!= '\0') {
1715 fputc(fields
->quote
, fh
);
1718 /* Output the array of (partial) field values */
1719 for (j
= 0; j
< g_ptr_array_len(fv_p
); j
++ ) {
1720 fputs((gchar
*)g_ptr_array_index(fv_p
, j
), fh
);
1722 if (fields
->quote
!= '\0') {
1723 fputc(fields
->quote
, fh
);
1725 g_ptr_array_free(fv_p
, TRUE
); /* get ready for the next packet */
1726 fields
->field_values
[i
] = NULL
;
1731 void write_fields_finale(output_fields_t
* fields _U_
, FILE *fh _U_
)
1736 /* Returns an ep_alloced string or a static constant*/
1737 const gchar
* get_node_field_value(field_info
* fi
, epan_dissect_t
* edt
)
1739 if (fi
->hfinfo
->id
== hf_text_only
) {
1743 return fi
->rep
->representation
;
1746 return get_field_hex_value(edt
->pi
.data_src
, fi
);
1749 else if (fi
->hfinfo
->id
== proto_data
) {
1750 /* Uninterpreted data, i.e., the "Data" protocol, is
1751 * printed as a field instead of a protocol. */
1752 return get_field_hex_value(edt
->pi
.data_src
, fi
);
1755 /* Normal protocols and fields */
1756 gchar
*dfilter_string
;
1759 switch (fi
->hfinfo
->type
)
1762 /* Print out the full details for the protocol. */
1764 return fi
->rep
->representation
;
1766 /* Just print out the protocol abbreviation */
1767 return fi
->hfinfo
->abbrev
;
1770 /* Return "1" so that the presence of a field of type
1771 * FT_NONE can be checked when using -T fields */
1774 /* XXX - this is a hack until we can just call
1775 * fvalue_to_string_repr() for *all* FT_* types. */
1776 dfilter_string
= proto_construct_match_selected_string(fi
,
1778 if (dfilter_string
!= NULL
) {
1779 chop_len
= strlen(fi
->hfinfo
->abbrev
) + 4; /* for " == " */
1781 /* XXX - Remove double-quotes. Again, once we
1782 * can call fvalue_to_string_repr(), we can
1783 * ask it not to produce the version for
1784 * display-filters, and thus, no
1786 if (dfilter_string
[strlen(dfilter_string
)-1] == '"') {
1787 dfilter_string
[strlen(dfilter_string
)-1] = '\0';
1791 return &(dfilter_string
[chop_len
]);
1793 return get_field_hex_value(edt
->pi
.data_src
, fi
);
1800 get_field_hex_value(GSList
*src_list
, field_info
*fi
)
1807 if (fi
->length
> tvb_length_remaining(fi
->ds_tvb
, fi
->start
)) {
1808 return "field length invalid!";
1811 /* Find the data for this field. */
1812 pd
= get_field_data(src_list
, fi
);
1819 const int chars_per_byte
= 2;
1821 len
= chars_per_byte
* fi
->length
;
1822 buffer
= ep_alloc_array(gchar
, len
+ 1);
1823 buffer
[len
] = '\0'; /* Ensure NULL termination in bad cases */
1825 /* Print a simple hex dump */
1826 for (i
= 0 ; i
< fi
->length
; i
++) {
1827 g_snprintf(p
, chars_per_byte
+1, "%02x", pd
[i
]);
1828 p
+= chars_per_byte
;