Split the low-level print stream code into a separate file.
[metze/wireshark/wip.git] / epan / print.c
1 /* print.c
2  * Routines for printing packet analysis trees.
3  *
4  * Gilbert Ramirez <gram@alumni.rice.edu>
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs <gerald@wireshark.org>
8  * Copyright 1998 Gerald Combs
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23  */
24
25 #include "config.h"
26
27 #include <stdio.h>
28 #include <string.h>
29
30 #include <glib.h>
31 #include <glib/gprintf.h>
32
33 #include <epan/epan.h>
34 #include <epan/epan_dissect.h>
35 #include <epan/to_str.h>
36 #include <epan/tvbuff.h>
37 #include <epan/packet.h>
38 #include <ftypes/ftypes-int.h>
39 #include <epan/emem.h>
40 #include <epan/expert.h>
41
42 #include <epan/packet-range.h>
43 #include <epan/print.h>
44 #include "version_info.h"
45 #include <epan/charsets.h>
46 #include <epan/dissectors/packet-data.h>
47 #include <epan/dissectors/packet-frame.h>
48 #include <wsutil/filesystem.h>
49
50 #define PDML_VERSION "0"
51 #define PSML_VERSION "0"
52
53 typedef struct {
54     int                  level;
55     print_stream_t      *stream;
56     gboolean             success;
57     GSList              *src_list;
58     print_dissections_e  print_dissections;
59     gboolean             print_hex_for_data;
60     packet_char_enc      encoding;
61     epan_dissect_t      *edt;
62 } print_data;
63
64 typedef struct {
65     int             level;
66     FILE           *fh;
67     GSList         *src_list;
68     epan_dissect_t *edt;
69 } write_pdml_data;
70
71 typedef struct {
72     output_fields_t *fields;
73     epan_dissect_t  *edt;
74 } write_field_data_t;
75
76 struct _output_fields {
77     gboolean     print_header;
78     gchar        separator;
79     gchar        occurrence;
80     gchar        aggregator;
81     GPtrArray   *fields;
82     GHashTable  *field_indicies;
83     GPtrArray  **field_values;
84     gchar        quote;
85     gboolean     includes_col_fields;
86 };
87
88 GHashTable *output_only_tables = NULL;
89
90 static gboolean write_headers = FALSE;
91
92 static gchar *get_field_hex_value(GSList *src_list, field_info *fi);
93 static void proto_tree_print_node(proto_node *node, gpointer data);
94 static void proto_tree_write_node_pdml(proto_node *node, gpointer data);
95 static const guint8 *get_field_data(GSList *src_list, field_info *fi);
96 static void write_pdml_field_hex_value(write_pdml_data *pdata, field_info *fi);
97 static gboolean print_hex_data_buffer(print_stream_t *stream, const guchar *cp,
98                                       guint length, packet_char_enc encoding);
99 static void print_escaped_xml(FILE *fh, const char *unescaped_string);
100
101 static void print_pdml_geninfo(proto_tree *tree, FILE *fh);
102
103 static void proto_tree_get_node_field_values(proto_node *node, gpointer data);
104
105 gboolean
106 proto_tree_print(print_args_t *print_args, epan_dissect_t *edt,
107                  print_stream_t *stream)
108 {
109     print_data data;
110
111     /* Create the output */
112     data.level              = 0;
113     data.stream             = stream;
114     data.success            = TRUE;
115     data.src_list           = edt->pi.data_src;
116     data.encoding           = (packet_char_enc)edt->pi.fd->flags.encoding;
117     data.print_dissections  = print_args->print_dissections;
118     /* If we're printing the entire packet in hex, don't
119        print uninterpreted data fields in hex as well. */
120     data.print_hex_for_data = !print_args->print_hex;
121     data.edt                = edt;
122
123     proto_tree_children_foreach(edt->tree, proto_tree_print_node, &data);
124     return data.success;
125 }
126
127 /* Print a tree's data, and any child nodes. */
128 static void
129 proto_tree_print_node(proto_node *node, gpointer data)
130 {
131     field_info   *fi    = PNODE_FINFO(node);
132     print_data   *pdata = (print_data*) data;
133     const guint8 *pd;
134     gchar         label_str[ITEM_LABEL_LENGTH];
135     gchar        *label_ptr;
136
137     /* dissection with an invisible proto tree? */
138     g_assert(fi);
139
140     /* Don't print invisible entries. */
141     if (PROTO_ITEM_IS_HIDDEN(node))
142         return;
143
144     /* Give up if we've already gotten an error. */
145     if (!pdata->success)
146         return;
147
148     /* was a free format label produced? */
149     if (fi->rep) {
150         label_ptr = fi->rep->representation;
151     }
152     else { /* no, make a generic label */
153         label_ptr = label_str;
154         proto_item_fill_label(fi, label_str);
155     }
156
157     if (PROTO_ITEM_IS_GENERATED(node))
158         label_ptr = g_strconcat("[", label_ptr, "]", NULL);
159
160     pdata->success = print_line(pdata->stream, pdata->level, label_ptr);
161
162     if (PROTO_ITEM_IS_GENERATED(node))
163         g_free(label_ptr);
164
165     if (!pdata->success)
166         return;
167
168     /*
169      * If -O is specified, only display the protocols which are in the
170      * lookup table.  Only check on the first level: once we start printing
171      * a tree, print the rest of the subtree.  Otherwise we won't print
172      * subitems whose abbreviation doesn't match the protocol--for example
173      * text items (whose abbreviation is simply "text").
174      */
175     if ((output_only_tables != NULL) && (pdata->level == 0)
176         && (g_hash_table_lookup(output_only_tables, fi->hfinfo->abbrev) == NULL)) {
177         return;
178     }
179
180     /* If it's uninterpreted data, dump it (unless our caller will
181        be printing the entire packet in hex). */
182     if ((fi->hfinfo->id == proto_data) && (pdata->print_hex_for_data)) {
183         /*
184          * Find the data for this field.
185          */
186         pd = get_field_data(pdata->src_list, fi);
187         if (pd) {
188             if (!print_line(pdata->stream, 0, "")) {
189                 pdata->success = FALSE;
190                 return;
191             }
192             if (!print_hex_data_buffer(pdata->stream, pd,
193                                        fi->length, pdata->encoding)) {
194                 pdata->success = FALSE;
195                 return;
196             }
197         }
198     }
199
200     /* If we're printing all levels, or if this node is one with a
201        subtree and its subtree is expanded, recurse into the subtree,
202        if it exists. */
203     g_assert((fi->tree_type >= -1) && (fi->tree_type < num_tree_types));
204     if ((pdata->print_dissections == print_dissections_expanded) ||
205         ((pdata->print_dissections == print_dissections_as_displayed) &&
206          (fi->tree_type >= 0) && tree_expanded(fi->tree_type))) {
207         if (node->first_child != NULL) {
208             pdata->level++;
209             proto_tree_children_foreach(node,
210                                         proto_tree_print_node, pdata);
211             pdata->level--;
212             if (!pdata->success)
213                 return;
214         }
215     }
216 }
217
218 #define PDML2HTML_XSL "pdml2html.xsl"
219 void
220 write_pdml_preamble(FILE *fh, const gchar *filename)
221 {
222     time_t t = time(NULL);
223     char *ts = asctime(localtime(&t));
224
225     ts[strlen(ts)-1] = 0; /* overwrite \n */
226
227     fputs("<?xml version=\"1.0\"?>\n", fh);
228     fputs("<?xml-stylesheet type=\"text/xsl\" href=\"" PDML2HTML_XSL "\"?>\n", fh);
229     fprintf(fh, "<!-- You can find " PDML2HTML_XSL " in %s or at http://anonsvn.wireshark.org/trunk/wireshark/" PDML2HTML_XSL ". -->\n", get_datafile_dir());
230     fputs("<pdml version=\"" PDML_VERSION "\" ", fh);
231     fprintf(fh, "creator=\"%s/%s\" time=\"%s\" capture_file=\"%s\">\n", PACKAGE, VERSION, ts, filename ? filename : "");
232 }
233
234 void
235 proto_tree_write_pdml(epan_dissect_t *edt, FILE *fh)
236 {
237     write_pdml_data data;
238
239     /* Create the output */
240     data.level    = 0;
241     data.fh       = fh;
242     data.src_list = edt->pi.data_src;
243     data.edt      = edt;
244
245     fprintf(fh, "<packet>\n");
246
247     /* Print a "geninfo" protocol as required by PDML */
248     print_pdml_geninfo(edt->tree, fh);
249
250     proto_tree_children_foreach(edt->tree, proto_tree_write_node_pdml,
251                                 &data);
252
253     fprintf(fh, "</packet>\n\n");
254 }
255
256 /* Write out a tree's data, and any child nodes, as PDML */
257 static void
258 proto_tree_write_node_pdml(proto_node *node, gpointer data)
259 {
260     field_info      *fi    = PNODE_FINFO(node);
261     write_pdml_data *pdata = (write_pdml_data*) data;
262     const gchar     *label_ptr;
263     gchar            label_str[ITEM_LABEL_LENGTH];
264     char            *dfilter_string;
265     int              i;
266     gboolean         wrap_in_fake_protocol;
267
268     /* dissection with an invisible proto tree? */
269     g_assert(fi);
270
271     /* Will wrap up top-level field items inside a fake protocol wrapper to
272        preserve the PDML schema */
273     wrap_in_fake_protocol =
274         (((fi->hfinfo->type != FT_PROTOCOL) ||
275           (fi->hfinfo->id == proto_data)) &&
276          (pdata->level == 0));
277
278     /* Indent to the correct level */
279     for (i = -1; i < pdata->level; i++) {
280         fputs("  ", pdata->fh);
281     }
282
283     if (wrap_in_fake_protocol) {
284         /* Open fake protocol wrapper */
285         fputs("<proto name=\"fake-field-wrapper\">\n", pdata->fh);
286
287         /* Indent to increased level before writing out field */
288         pdata->level++;
289         for (i = -1; i < pdata->level; i++) {
290             fputs("  ", pdata->fh);
291         }
292     }
293
294     /* Text label. It's printed as a field with no name. */
295     if (fi->hfinfo->id == hf_text_only) {
296         /* Get the text */
297         if (fi->rep) {
298             label_ptr = fi->rep->representation;
299         }
300         else {
301             label_ptr = "";
302         }
303
304         /* Show empty name since it is a required field */
305         fputs("<field name=\"", pdata->fh);
306         fputs("\" show=\"", pdata->fh);
307         print_escaped_xml(pdata->fh, label_ptr);
308
309         fprintf(pdata->fh, "\" size=\"%d", fi->length);
310         if (node->parent && node->parent->finfo && (fi->start < node->parent->finfo->start)) {
311             fprintf(pdata->fh, "\" pos=\"%d", node->parent->finfo->start + fi->start);
312         } else {
313             fprintf(pdata->fh, "\" pos=\"%d", fi->start);
314         }
315
316         if (fi->length > 0) {
317             fputs("\" value=\"", pdata->fh);
318             write_pdml_field_hex_value(pdata, fi);
319         }
320
321         if (node->first_child != NULL) {
322             fputs("\">\n", pdata->fh);
323         }
324         else {
325             fputs("\"/>\n", pdata->fh);
326         }
327     }
328
329     /* Uninterpreted data, i.e., the "Data" protocol, is
330      * printed as a field instead of a protocol. */
331     else if (fi->hfinfo->id == proto_data) {
332
333         /* Write out field with data */
334         fputs("<field name=\"data\" value=\"", pdata->fh);
335         write_pdml_field_hex_value(pdata, fi);
336         fputs("\">\n", pdata->fh);
337     }
338     /* Normal protocols and fields */
339     else {
340         if ((fi->hfinfo->type == FT_PROTOCOL) && (fi->hfinfo->id != proto_expert)) {
341             fputs("<proto name=\"", pdata->fh);
342         }
343         else {
344             fputs("<field name=\"", pdata->fh);
345         }
346         print_escaped_xml(pdata->fh, fi->hfinfo->abbrev);
347
348 #if 0
349         /* PDML spec, see:
350          * http://www.nbee.org/doku.php?id=netpdl:pdml_specification
351          *
352          * the show fields contains things in 'human readable' format
353          * showname: contains only the name of the field
354          * show: contains only the data of the field
355          * showdtl: contains additional details of the field data
356          * showmap: contains mappings of the field data (e.g. the hostname to an IP address)
357          *
358          * XXX - the showname shouldn't contain the field data itself
359          * (like it's contained in the fi->rep->representation).
360          * Unfortunately, we don't have the field data representation for
361          * all fields, so this isn't currently possible */
362         fputs("\" showname=\"", pdata->fh);
363         print_escaped_xml(pdata->fh, fi->hfinfo->name);
364 #endif
365
366         if (fi->rep) {
367             fputs("\" showname=\"", pdata->fh);
368             print_escaped_xml(pdata->fh, fi->rep->representation);
369         }
370         else {
371             label_ptr = label_str;
372             proto_item_fill_label(fi, label_str);
373             fputs("\" showname=\"", pdata->fh);
374             print_escaped_xml(pdata->fh, label_ptr);
375         }
376
377         if (PROTO_ITEM_IS_HIDDEN(node))
378             fprintf(pdata->fh, "\" hide=\"yes");
379
380         fprintf(pdata->fh, "\" size=\"%d", fi->length);
381         if (node->parent && node->parent->finfo && (fi->start < node->parent->finfo->start)) {
382             fprintf(pdata->fh, "\" pos=\"%d", node->parent->finfo->start + fi->start);
383         } else {
384             fprintf(pdata->fh, "\" pos=\"%d", fi->start);
385         }
386 /*      fprintf(pdata->fh, "\" id=\"%d", fi->hfinfo->id);*/
387
388         /* show, value, and unmaskedvalue attributes */
389         switch (fi->hfinfo->type)
390         {
391         case FT_PROTOCOL:
392             break;
393         case FT_NONE:
394             fputs("\" show=\"\" value=\"",  pdata->fh);
395             break;
396         default:
397             dfilter_string = fvalue_to_string_repr(&fi->value, FTREPR_DISPLAY, NULL);
398             if (dfilter_string != NULL) {
399
400                 fputs("\" show=\"", pdata->fh);
401                 print_escaped_xml(pdata->fh, dfilter_string);
402             }
403             g_free(dfilter_string);
404
405             /*
406              * XXX - should we omit "value" for any fields?
407              * What should we do for fields whose length is 0?
408              * They might come from a pseudo-header or from
409              * the capture header (e.g., time stamps), or
410              * they might be generated fields.
411              */
412             if (fi->length > 0) {
413                 fputs("\" value=\"", pdata->fh);
414
415                 if (fi->hfinfo->bitmask!=0) {
416                     switch (fi->value.ftype->ftype) {
417                         case FT_INT8:
418                         case FT_INT16:
419                         case FT_INT24:
420                         case FT_INT32:
421                             fprintf(pdata->fh, "%X", (guint) fvalue_get_sinteger(&fi->value));
422                             break;
423                         case FT_UINT8:
424                         case FT_UINT16:
425                         case FT_UINT24:
426                         case FT_UINT32:
427                         case FT_BOOLEAN:
428                             fprintf(pdata->fh, "%X", fvalue_get_uinteger(&fi->value));
429                             break;
430                         case FT_INT64:
431                         case FT_UINT64:
432                             fprintf(pdata->fh, "%" G_GINT64_MODIFIER "X",
433                                     fvalue_get_integer64(&fi->value));
434                             break;
435                         default:
436                             g_assert_not_reached();
437                     }
438                     fputs("\" unmaskedvalue=\"", pdata->fh);
439                     write_pdml_field_hex_value(pdata, fi);
440                 }
441                 else {
442                     write_pdml_field_hex_value(pdata, fi);
443                 }
444             }
445         }
446
447         if (node->first_child != NULL) {
448             fputs("\">\n", pdata->fh);
449         }
450         else if (fi->hfinfo->id == proto_data) {
451             fputs("\">\n", pdata->fh);
452         }
453         else {
454             fputs("\"/>\n", pdata->fh);
455         }
456     }
457
458     /* We always print all levels for PDML. Recurse here. */
459     if (node->first_child != NULL) {
460         pdata->level++;
461         proto_tree_children_foreach(node,
462                                     proto_tree_write_node_pdml, pdata);
463         pdata->level--;
464     }
465
466     /* Take back the extra level we added for fake wrapper protocol */
467     if (wrap_in_fake_protocol) {
468         pdata->level--;
469     }
470
471     if (node->first_child != NULL) {
472         /* Indent to correct level */
473         for (i = -1; i < pdata->level; i++) {
474             fputs("  ", pdata->fh);
475         }
476         /* Close off current element */
477         /* Data and expert "protocols" use simple tags */
478         if ((fi->hfinfo->id != proto_data) && (fi->hfinfo->id != proto_expert)) {
479             if (fi->hfinfo->type == FT_PROTOCOL) {
480                 fputs("</proto>\n", pdata->fh);
481             }
482             else {
483                 fputs("</field>\n", pdata->fh);
484             }
485         } else {
486             fputs("</field>\n", pdata->fh);
487         }
488     }
489
490     /* Close off fake wrapper protocol */
491     if (wrap_in_fake_protocol) {
492         fputs("</proto>\n", pdata->fh);
493     }
494 }
495
496 /* Print info for a 'geninfo' pseudo-protocol. This is required by
497  * the PDML spec. The information is contained in Wireshark's 'frame' protocol,
498  * but we produce a 'geninfo' protocol in the PDML to conform to spec.
499  * The 'frame' protocol follows the 'geninfo' protocol in the PDML. */
500 static void
501 print_pdml_geninfo(proto_tree *tree, FILE *fh)
502 {
503     guint32     num, len, caplen;
504     nstime_t   *timestamp;
505     GPtrArray  *finfo_array;
506     field_info *frame_finfo;
507     gchar      *tmp;
508
509     /* Get frame protocol's finfo. */
510     finfo_array = proto_find_finfo(tree, proto_frame);
511     if (g_ptr_array_len(finfo_array) < 1) {
512         return;
513     }
514     frame_finfo = (field_info *)finfo_array->pdata[0];
515     g_ptr_array_free(finfo_array, TRUE);
516
517     /* frame.number --> geninfo.num */
518     finfo_array = proto_find_finfo(tree, hf_frame_number);
519     if (g_ptr_array_len(finfo_array) < 1) {
520         return;
521     }
522     num = fvalue_get_uinteger(&((field_info*)finfo_array->pdata[0])->value);
523     g_ptr_array_free(finfo_array, TRUE);
524
525     /* frame.frame_len --> geninfo.len */
526     finfo_array = proto_find_finfo(tree, hf_frame_len);
527     if (g_ptr_array_len(finfo_array) < 1) {
528         return;
529     }
530     len = fvalue_get_uinteger(&((field_info*)finfo_array->pdata[0])->value);
531     g_ptr_array_free(finfo_array, TRUE);
532
533     /* frame.cap_len --> geninfo.caplen */
534     finfo_array = proto_find_finfo(tree, hf_frame_capture_len);
535     if (g_ptr_array_len(finfo_array) < 1) {
536         return;
537     }
538     caplen = fvalue_get_uinteger(&((field_info*)finfo_array->pdata[0])->value);
539     g_ptr_array_free(finfo_array, TRUE);
540
541     /* frame.time --> geninfo.timestamp */
542     finfo_array = proto_find_finfo(tree, hf_frame_arrival_time);
543     if (g_ptr_array_len(finfo_array) < 1) {
544         return;
545     }
546     timestamp = (nstime_t *)fvalue_get(&((field_info*)finfo_array->pdata[0])->value);
547     g_ptr_array_free(finfo_array, TRUE);
548
549     /* Print geninfo start */
550     fprintf(fh,
551             "  <proto name=\"geninfo\" pos=\"0\" showname=\"General information\" size=\"%u\">\n",
552             frame_finfo->length);
553
554     /* Print geninfo.num */
555     fprintf(fh,
556             "    <field name=\"num\" pos=\"0\" show=\"%u\" showname=\"Number\" value=\"%x\" size=\"%u\"/>\n",
557             num, num, frame_finfo->length);
558
559     /* Print geninfo.len */
560     fprintf(fh,
561             "    <field name=\"len\" pos=\"0\" show=\"%u\" showname=\"Frame Length\" value=\"%x\" size=\"%u\"/>\n",
562             len, len, frame_finfo->length);
563
564     /* Print geninfo.caplen */
565     fprintf(fh,
566             "    <field name=\"caplen\" pos=\"0\" show=\"%u\" showname=\"Captured Length\" value=\"%x\" size=\"%u\"/>\n",
567             caplen, caplen, frame_finfo->length);
568
569     tmp = abs_time_to_str(NULL, timestamp, ABSOLUTE_TIME_LOCAL, TRUE);
570
571     /* Print geninfo.timestamp */
572     fprintf(fh,
573             "    <field name=\"timestamp\" pos=\"0\" show=\"%s\" showname=\"Captured Time\" value=\"%d.%09d\" size=\"%u\"/>\n",
574             tmp, (int) timestamp->secs, timestamp->nsecs, frame_finfo->length);
575
576     wmem_free(NULL, tmp);
577
578     /* Print geninfo end */
579     fprintf(fh,
580             "  </proto>\n");
581 }
582
583 void
584 write_pdml_finale(FILE *fh)
585 {
586     fputs("</pdml>\n", fh);
587 }
588
589 void
590 write_psml_preamble(FILE *fh)
591 {
592     fputs("<?xml version=\"1.0\"?>\n", fh);
593     fputs("<psml version=\"" PSML_VERSION "\" ", fh);
594     fprintf(fh, "creator=\"%s/%s\">\n", PACKAGE, VERSION);
595     write_headers = TRUE;
596 }
597
598 void
599 proto_tree_write_psml(epan_dissect_t *edt, FILE *fh)
600 {
601     gint i;
602
603     /* if this is the first packet, we have to create the PSML structure output */
604     if (write_headers) {
605         fprintf(fh, "<structure>\n");
606
607         for (i = 0; i < edt->pi.cinfo->num_cols; i++) {
608             fprintf(fh, "<section>");
609             print_escaped_xml(fh, edt->pi.cinfo->col_title[i]);
610             fprintf(fh, "</section>\n");
611         }
612
613         fprintf(fh, "</structure>\n\n");
614
615         write_headers = FALSE;
616     }
617
618     fprintf(fh, "<packet>\n");
619
620     for (i = 0; i < edt->pi.cinfo->num_cols; i++) {
621         fprintf(fh, "<section>");
622         print_escaped_xml(fh, edt->pi.cinfo->col_data[i]);
623         fprintf(fh, "</section>\n");
624     }
625
626     fprintf(fh, "</packet>\n\n");
627 }
628
629 void
630 write_psml_finale(FILE *fh)
631 {
632     fputs("</psml>\n", fh);
633 }
634
635 void
636 write_csv_preamble(FILE *fh _U_)
637 {
638     write_headers = TRUE;
639 }
640
641 static gchar *csv_massage_str(const gchar *source, const gchar *exceptions)
642 {
643     gchar *csv_str;
644     gchar *tmp_str;
645
646     /* In general, our output for any field can contain Unicode characters,
647        so g_strescape (which escapes any non-ASCII) is the wrong thing to do.
648        Unfortunately glib doesn't appear to provide g_unicode_strescape()... */
649     csv_str = g_strescape(source, exceptions);
650     tmp_str = csv_str;
651     /* Locate the UTF-8 right arrow character and replace it by an ASCII equivalent */
652     while ( (tmp_str = strstr(tmp_str, "\xe2\x86\x92")) != NULL ) {
653         tmp_str[0] = ' ';
654         tmp_str[1] = '>';
655         tmp_str[2] = ' ';
656     }
657     tmp_str = csv_str;
658     while ( (tmp_str = strstr(tmp_str, "\\\"")) != NULL )
659         *tmp_str = '\"';
660     return csv_str;
661 }
662
663 static void csv_write_str(const char *str, char sep, FILE *fh)
664 {
665     gchar *csv_str;
666
667     /* Do not escape the UTF-8 righ arrow character */
668     csv_str = csv_massage_str(str, "\xe2\x86\x92");
669     fprintf(fh, "\"%s\"%c", csv_str, sep);
670     g_free(csv_str);
671 }
672
673 void
674 proto_tree_write_csv(epan_dissect_t *edt, FILE *fh)
675 {
676     gint i;
677
678     /* if this is the first packet, we have to write the CSV header */
679     if (write_headers) {
680         for (i = 0; i < edt->pi.cinfo->num_cols - 1; i++)
681             csv_write_str(edt->pi.cinfo->col_title[i], ',', fh);
682         csv_write_str(edt->pi.cinfo->col_title[i], '\n', fh);
683         write_headers = FALSE;
684     }
685
686     for (i = 0; i < edt->pi.cinfo->num_cols - 1; i++)
687         csv_write_str(edt->pi.cinfo->col_data[i], ',', fh);
688     csv_write_str(edt->pi.cinfo->col_data[i], '\n', fh);
689 }
690
691 void
692 write_csv_finale(FILE *fh _U_)
693 {
694
695 }
696
697 void
698 write_carrays_preamble(FILE *fh _U_)
699 {
700
701 }
702
703 void
704 proto_tree_write_carrays(guint32 num, FILE *fh, epan_dissect_t *edt)
705 {
706     guint32       i = 0, src_num = 0;
707     GSList       *src_le;
708     tvbuff_t     *tvb;
709     const char   *name;
710     const guchar *cp;
711     guint         length;
712     char          ascii[9];
713     struct data_source *src;
714
715     for (src_le = edt->pi.data_src; src_le != NULL; src_le = src_le->next) {
716         memset(ascii, 0, sizeof(ascii));
717         src = (struct data_source *)src_le->data;
718         tvb = get_data_source_tvb(src);
719         length = tvb_length(tvb);
720         if (length == 0)
721             continue;
722
723         cp = tvb_get_ptr(tvb, 0, length);
724
725         name = get_data_source_name(src);
726         if (name)
727             fprintf(fh, "/* %s */\n", name);
728         if (src_num) {
729             fprintf(fh, "static const unsigned char pkt%u_%u[%u] = {\n",
730                     num, src_num, length);
731         } else {
732             fprintf(fh, "static const unsigned char pkt%u[%u] = {\n",
733                     num, length);
734         }
735         src_num++;
736
737         for (i = 0; i < length; i++) {
738             fprintf(fh, "0x%02x", *(cp + i));
739             ascii[i % 8] = g_ascii_isprint(*(cp + i)) ? *(cp + i) : '.';
740
741             if (i == (length - 1)) {
742                 guint rem;
743                 rem = length % 8;
744                 if (rem) {
745                     guint j;
746                     for ( j = 0; j < 8 - rem; j++ )
747                         fprintf(fh, "      ");
748                 }
749                 fprintf(fh, "  /* %s */\n};\n\n", ascii);
750                 break;
751             }
752
753             if (!((i + 1) % 8)) {
754                 fprintf(fh, ", /* %s */\n", ascii);
755                 memset(ascii, 0, sizeof(ascii));
756             }
757             else {
758                 fprintf(fh, ", ");
759             }
760         }
761     }
762 }
763
764 void
765 write_carrays_finale(FILE *fh _U_)
766 {
767
768 }
769
770 /*
771  * Find the data source for a specified field, and return a pointer
772  * to the data in it. Returns NULL if the data is out of bounds.
773  */
774 /* XXX: What am I missing ?
775  *      Why bother searching for fi->ds_tvb for the matching tvb
776  *       in the data_source list ?
777  *      IOW: Why not just use fi->ds_tvb for the arg to tvb_get_ptr() ?
778  */
779
780 static const guint8 *
781 get_field_data(GSList *src_list, field_info *fi)
782 {
783     GSList   *src_le;
784     tvbuff_t *src_tvb;
785     gint      length, tvbuff_length;
786     struct data_source *src;
787
788     for (src_le = src_list; src_le != NULL; src_le = src_le->next) {
789         src = (struct data_source *)src_le->data;
790         src_tvb = get_data_source_tvb(src);
791         if (fi->ds_tvb == src_tvb) {
792             /*
793              * Found it.
794              *
795              * XXX - a field can have a length that runs past
796              * the end of the tvbuff.  Ideally, that should
797              * be fixed when adding an item to the protocol
798              * tree, but checking the length when doing
799              * that could be expensive.  Until we fix that,
800              * we'll do the check here.
801              */
802             tvbuff_length = tvb_length_remaining(src_tvb,
803                                                  fi->start);
804             if (tvbuff_length < 0) {
805                 return NULL;
806             }
807             length = fi->length;
808             if (length > tvbuff_length)
809                 length = tvbuff_length;
810             return tvb_get_ptr(src_tvb, fi->start, length);
811         }
812     }
813     g_assert_not_reached();
814     return NULL;  /* not found */
815 }
816
817 /* Print a string, escaping out certain characters that need to
818  * escaped out for XML. */
819 static void
820 print_escaped_xml(FILE *fh, const char *unescaped_string)
821 {
822     const char *p;
823     char        temp_str[8];
824
825     for (p = unescaped_string; *p != '\0'; p++) {
826         switch (*p) {
827         case '&':
828             fputs("&amp;", fh);
829             break;
830         case '<':
831             fputs("&lt;", fh);
832             break;
833         case '>':
834             fputs("&gt;", fh);
835             break;
836         case '"':
837             fputs("&quot;", fh);
838             break;
839         case '\'':
840             fputs("&#x27;", fh);
841             break;
842         default:
843             if (g_ascii_isprint(*p))
844                 fputc(*p, fh);
845             else {
846                 g_snprintf(temp_str, sizeof(temp_str), "\\x%x", (guint8)*p);
847                 fputs(temp_str, fh);
848             }
849         }
850     }
851 }
852
853 static void
854 write_pdml_field_hex_value(write_pdml_data *pdata, field_info *fi)
855 {
856     int           i;
857     const guint8 *pd;
858
859     if (!fi->ds_tvb)
860         return;
861
862     if (fi->length > tvb_length_remaining(fi->ds_tvb, fi->start)) {
863         fprintf(pdata->fh, "field length invalid!");
864         return;
865     }
866
867     /* Find the data for this field. */
868     pd = get_field_data(pdata->src_list, fi);
869
870     if (pd) {
871         /* Print a simple hex dump */
872         for (i = 0 ; i < fi->length; i++) {
873             fprintf(pdata->fh, "%02x", pd[i]);
874         }
875     }
876 }
877
878 gboolean
879 print_hex_data(print_stream_t *stream, epan_dissect_t *edt)
880 {
881     gboolean      multiple_sources;
882     GSList       *src_le;
883     tvbuff_t     *tvb;
884     const char   *name;
885     char         *line;
886     const guchar *cp;
887     guint         length;
888     struct data_source *src;
889
890     /*
891      * Set "multiple_sources" iff this frame has more than one
892      * data source; if it does, we need to print the name of
893      * the data source before printing the data from the
894      * data source.
895      */
896     multiple_sources = (edt->pi.data_src->next != NULL);
897
898     for (src_le = edt->pi.data_src; src_le != NULL;
899          src_le = src_le->next) {
900         src = (struct data_source *)src_le->data;
901         tvb = get_data_source_tvb(src);
902         if (multiple_sources) {
903             name = get_data_source_name(src);
904             line = g_strdup_printf("%s:", name);
905             print_line(stream, 0, line);
906             g_free(line);
907         }
908         length = tvb_length(tvb);
909         if (length == 0)
910             return TRUE;
911         cp = tvb_get_ptr(tvb, 0, length);
912         if (!print_hex_data_buffer(stream, cp, length,
913                                    (packet_char_enc)edt->pi.fd->flags.encoding))
914             return FALSE;
915     }
916     return TRUE;
917 }
918
919 /*
920  * This routine is based on a routine created by Dan Lasley
921  * <DLASLEY@PROMUS.com>.
922  *
923  * It was modified for Wireshark by Gilbert Ramirez and others.
924  */
925
926 #define MAX_OFFSET_LEN   8       /* max length of hex offset of bytes */
927 #define BYTES_PER_LINE  16      /* max byte values printed on a line */
928 #define HEX_DUMP_LEN    (BYTES_PER_LINE*3)
929                                 /* max number of characters hex dump takes -
930                                    2 digits plus trailing blank */
931 #define DATA_DUMP_LEN   (HEX_DUMP_LEN + 2 + BYTES_PER_LINE)
932                                 /* number of characters those bytes take;
933                                    3 characters per byte of hex dump,
934                                    2 blanks separating hex from ASCII,
935                                    1 character per byte of ASCII dump */
936 #define MAX_LINE_LEN    (MAX_OFFSET_LEN + 2 + DATA_DUMP_LEN)
937                                 /* number of characters per line;
938                                    offset, 2 blanks separating offset
939                                    from data dump, data dump */
940
941 static gboolean
942 print_hex_data_buffer(print_stream_t *stream, const guchar *cp,
943                       guint length, packet_char_enc encoding)
944 {
945     register unsigned int ad, i, j, k, l;
946     guchar                c;
947     gchar                 line[MAX_LINE_LEN + 1];
948     unsigned int          use_digits;
949
950     static gchar binhex[16] = {
951         '0', '1', '2', '3', '4', '5', '6', '7',
952         '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
953
954     /*
955      * How many of the leading digits of the offset will we supply?
956      * We always supply at least 4 digits, but if the maximum offset
957      * won't fit in 4 digits, we use as many digits as will be needed.
958      */
959     if (((length - 1) & 0xF0000000) != 0)
960         use_digits = 8; /* need all 8 digits */
961     else if (((length - 1) & 0x0F000000) != 0)
962         use_digits = 7; /* need 7 digits */
963     else if (((length - 1) & 0x00F00000) != 0)
964         use_digits = 6; /* need 6 digits */
965     else if (((length - 1) & 0x000F0000) != 0)
966         use_digits = 5; /* need 5 digits */
967     else
968         use_digits = 4; /* we'll supply 4 digits */
969
970     ad = 0;
971     i = 0;
972     j = 0;
973     k = 0;
974     while (i < length) {
975         if ((i & 15) == 0) {
976             /*
977              * Start of a new line.
978              */
979             j = 0;
980             l = use_digits;
981             do {
982                 l--;
983                 c = (ad >> (l*4)) & 0xF;
984                 line[j++] = binhex[c];
985             } while (l != 0);
986             line[j++] = ' ';
987             line[j++] = ' ';
988             memset(line+j, ' ', DATA_DUMP_LEN);
989
990             /*
991              * Offset in line of ASCII dump.
992              */
993             k = j + HEX_DUMP_LEN + 2;
994         }
995         c = *cp++;
996         line[j++] = binhex[c>>4];
997         line[j++] = binhex[c&0xf];
998         j++;
999         if (encoding == PACKET_CHAR_ENC_CHAR_EBCDIC) {
1000             c = EBCDIC_to_ASCII1(c);
1001         }
1002         line[k++] = ((c >= ' ') && (c < 0x7f)) ? c : '.';
1003         i++;
1004         if (((i & 15) == 0) || (i == length)) {
1005             /*
1006              * We'll be starting a new line, or
1007              * we're finished printing this buffer;
1008              * dump out the line we've constructed,
1009              * and advance the offset.
1010              */
1011             line[k] = '\0';
1012             if (!print_line(stream, 0, line))
1013                 return FALSE;
1014             ad += 16;
1015         }
1016     }
1017     return TRUE;
1018 }
1019
1020 gsize output_fields_num_fields(output_fields_t* fields)
1021 {
1022     g_assert(fields);
1023
1024     if (NULL == fields->fields) {
1025         return 0;
1026     } else {
1027         return fields->fields->len;
1028     }
1029 }
1030
1031 void output_fields_free(output_fields_t* fields)
1032 {
1033     g_assert(fields);
1034
1035     if (NULL != fields->fields) {
1036         gsize i;
1037
1038         if (NULL != fields->field_indicies) {
1039             /* Keys are stored in fields->fields, values are
1040              * integers.
1041              */
1042             g_hash_table_destroy(fields->field_indicies);
1043         }
1044
1045         if (NULL != fields->field_values) {
1046             g_free(fields->field_values);
1047         }
1048
1049         for(i = 0; i < fields->fields->len; ++i) {
1050             gchar* field = (gchar *)g_ptr_array_index(fields->fields,i);
1051             g_free(field);
1052         }
1053         g_ptr_array_free(fields->fields, TRUE);
1054     }
1055
1056     g_free(fields);
1057 }
1058
1059 #define COLUMN_FIELD_FILTER  "_ws.col."
1060
1061 void output_fields_add(output_fields_t *fields, const gchar *field)
1062 {
1063     gchar *field_copy;
1064
1065     g_assert(fields);
1066     g_assert(field);
1067
1068
1069     if (NULL == fields->fields) {
1070         fields->fields = g_ptr_array_new();
1071     }
1072
1073     field_copy = g_strdup(field);
1074
1075     g_ptr_array_add(fields->fields, field_copy);
1076
1077     /* See if we have a column as a field entry */
1078     if (!strncmp(field, COLUMN_FIELD_FILTER, strlen(COLUMN_FIELD_FILTER)))
1079         fields->includes_col_fields = TRUE;
1080
1081 }
1082
1083 static void
1084 output_field_check(void *data, void *user_data)
1085 {
1086     gchar *field = (gchar *)data;
1087     gboolean *all_valid = (gboolean *)user_data;
1088
1089     if (!strncmp(field, COLUMN_FIELD_FILTER, strlen(COLUMN_FIELD_FILTER)))
1090         return;
1091
1092     if (!proto_registrar_get_byname(field)) {
1093         g_warning("'%s' isn't a valid field!", field);
1094         *all_valid = FALSE;
1095     }
1096
1097 }
1098
1099 gboolean
1100 output_fields_valid(output_fields_t *fields)
1101 {
1102     gboolean all_valid = TRUE;
1103
1104     if (fields->fields == NULL) {
1105         return TRUE;
1106     }
1107
1108     g_ptr_array_foreach(fields->fields, output_field_check, &all_valid);
1109
1110     return all_valid;
1111 }
1112
1113 gboolean output_fields_set_option(output_fields_t *info, gchar *option)
1114 {
1115     const gchar *option_name;
1116     const gchar *option_value;
1117
1118     g_assert(info);
1119     g_assert(option);
1120
1121     if ('\0' == *option) {
1122         return FALSE; /* Is this guarded against by option parsing? */
1123     }
1124     option_name = strtok(option, "=");
1125     if (!option_name) {
1126         return FALSE;
1127     }
1128     option_value = option + strlen(option_name) + 1;
1129     if (0 == strcmp(option_name, "header")) {
1130         switch (NULL == option_value ? '\0' : *option_value) {
1131         case 'n':
1132             info->print_header = FALSE;
1133             break;
1134         case 'y':
1135             info->print_header = TRUE;
1136             break;
1137         default:
1138             return FALSE;
1139         }
1140         return TRUE;
1141     }
1142
1143     if (0 == strcmp(option_name, "separator")) {
1144         switch (NULL == option_value ? '\0' : *option_value) {
1145         case '\0':
1146             return FALSE;
1147         case '/':
1148             switch (*++option_value) {
1149             case 't':
1150                 info->separator = '\t';
1151                 break;
1152             case 's':
1153                 info->separator = ' ';
1154                 break;
1155             default:
1156                 info->separator = '\\';
1157             }
1158             break;
1159         default:
1160             info->separator = *option_value;
1161             break;
1162         }
1163         return TRUE;
1164     }
1165
1166     if (0 == strcmp(option_name, "occurrence")) {
1167         switch (NULL == option_value ? '\0' : *option_value) {
1168         case 'f':
1169         case 'l':
1170         case 'a':
1171             info->occurrence = *option_value;
1172             break;
1173         default:
1174             return FALSE;
1175         }
1176         return TRUE;
1177     }
1178
1179     if (0 == strcmp(option_name, "aggregator")) {
1180         switch (NULL == option_value ? '\0' : *option_value) {
1181         case '\0':
1182             return FALSE;
1183         case '/':
1184             switch (*++option_value) {
1185             case 's':
1186                 info->aggregator = ' ';
1187                 break;
1188             default:
1189                 info->aggregator = '\\';
1190             }
1191             break;
1192         default:
1193             info->aggregator = *option_value;
1194             break;
1195         }
1196         return TRUE;
1197     }
1198
1199     if (0 == strcmp(option_name, "quote")) {
1200         switch (NULL == option_value ? '\0' : *option_value) {
1201         default: /* Fall through */
1202         case '\0':
1203             info->quote = '\0';
1204             return FALSE;
1205         case 'd':
1206             info->quote = '"';
1207             break;
1208         case 's':
1209             info->quote = '\'';
1210             break;
1211         case 'n':
1212             info->quote = '\0';
1213             break;
1214         }
1215         return TRUE;
1216     }
1217
1218     return FALSE;
1219 }
1220
1221 void output_fields_list_options(FILE *fh)
1222 {
1223     fprintf(fh, "TShark: The available options for field output \"E\" are:\n");
1224     fputs("header=y|n    Print field abbreviations as first line of output (def: N: no)\n", fh);
1225     fputs("separator=/t|/s|<character>   Set the separator to use;\n     \"/t\" = tab, \"/s\" = space (def: /t: tab)\n", fh);
1226     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);
1227     fputs("aggregator=,|/s|<character>   Set the aggregator to use;\n     \",\" = comma, \"/s\" = space (def: ,: comma)\n", fh);
1228     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);
1229 }
1230
1231 gboolean output_fields_has_cols(output_fields_t* fields)
1232 {
1233     g_assert(fields);
1234     return fields->includes_col_fields;
1235 }
1236
1237 void write_fields_preamble(output_fields_t* fields, FILE *fh)
1238 {
1239     gsize i;
1240
1241     g_assert(fields);
1242     g_assert(fh);
1243     g_assert(fields->fields);
1244
1245     if (!fields->print_header) {
1246         return;
1247     }
1248
1249     for(i = 0; i < fields->fields->len; ++i) {
1250         const gchar* field = (const gchar *)g_ptr_array_index(fields->fields,i);
1251         if (i != 0 ) {
1252             fputc(fields->separator, fh);
1253         }
1254         fputs(field, fh);
1255     }
1256     fputc('\n', fh);
1257 }
1258
1259 static void format_field_values(output_fields_t* fields, gpointer field_index, const gchar* value)
1260 {
1261     guint      indx;
1262     GPtrArray* fv_p;
1263
1264     if ((NULL == value) || ('\0' == *value))
1265         return;
1266
1267     /* Unwrap change made to disambiguiate zero / null */
1268     indx = GPOINTER_TO_UINT(field_index) - 1;
1269
1270     if (fields->field_values[indx] == NULL) {
1271         fields->field_values[indx] = g_ptr_array_new();
1272     }
1273
1274     /* Essentially: fieldvalues[indx] is a 'GPtrArray *' with each array entry */
1275     /*  pointing to a string which is (part of) the final output string.       */
1276
1277     fv_p = fields->field_values[indx];
1278
1279     switch (fields->occurrence) {
1280     case 'f':
1281         /* print the value of only the first occurrence of the field */
1282         if (g_ptr_array_len(fv_p) != 0)
1283             return;
1284         break;
1285     case 'l':
1286         /* print the value of only the last occurrence of the field */
1287         g_ptr_array_set_size(fv_p, 0);
1288         break;
1289     case 'a':
1290         /* print the value of all accurrences of the field */
1291         /* If not the first, add the 'aggregator' */
1292         if (g_ptr_array_len(fv_p) > 0) {
1293             g_ptr_array_add(fv_p, (gpointer)g_strdup_printf("%c", fields->aggregator));
1294         }
1295         break;
1296     default:
1297         g_assert_not_reached();
1298         break;
1299     }
1300
1301     g_ptr_array_add(fv_p, (gpointer)value);
1302 }
1303
1304 static void proto_tree_get_node_field_values(proto_node *node, gpointer data)
1305 {
1306     write_field_data_t *call_data;
1307     field_info *fi;
1308     gpointer    field_index;
1309
1310     call_data = (write_field_data_t *)data;
1311     fi = PNODE_FINFO(node);
1312
1313     /* dissection with an invisible proto tree? */
1314     g_assert(fi);
1315
1316     field_index = g_hash_table_lookup(call_data->fields->field_indicies, fi->hfinfo->abbrev);
1317     if (NULL != field_index) {
1318         format_field_values(call_data->fields, field_index,
1319                             get_node_field_value(fi, call_data->edt) /* g_ alloc'd string */
1320             );
1321     }
1322
1323     /* Recurse here. */
1324     if (node->first_child != NULL) {
1325         proto_tree_children_foreach(node, proto_tree_get_node_field_values,
1326                                     call_data);
1327     }
1328 }
1329
1330 void proto_tree_write_fields(output_fields_t *fields, epan_dissect_t *edt, column_info *cinfo, FILE *fh)
1331 {
1332     gsize     i;
1333     gint      col;
1334     gchar    *col_name;
1335     gpointer  field_index;
1336
1337     write_field_data_t data;
1338
1339     g_assert(fields);
1340     g_assert(fields->fields);
1341     g_assert(edt);
1342     g_assert(fh);
1343
1344     data.fields = fields;
1345     data.edt = edt;
1346
1347     if (NULL == fields->field_indicies) {
1348         /* Prepare a lookup table from string abbreviation for field to its index. */
1349         fields->field_indicies = g_hash_table_new(g_str_hash, g_str_equal);
1350
1351         i = 0;
1352         while (i < fields->fields->len) {
1353             gchar *field = (gchar *)g_ptr_array_index(fields->fields, i);
1354             /* Store field indicies +1 so that zero is not a valid value,
1355              * and can be distinguished from NULL as a pointer.
1356              */
1357             ++i;
1358             g_hash_table_insert(fields->field_indicies, field, GUINT_TO_POINTER(i));
1359         }
1360     }
1361
1362     /* Array buffer to store values for this packet              */
1363     /*  Allocate an array for the 'GPtrarray *' the first time   */
1364     /*   ths function is invoked for a file;                     */
1365     /*  Any and all 'GPtrArray *' are freed (after use) each     */
1366     /*   time (each packet) this function is invoked for a flle. */
1367     /* XXX: ToDo: use packet-scope'd memory & (if/when implemented) wmem ptr_array */
1368     if (NULL == fields->field_values)
1369         fields->field_values = g_new0(GPtrArray*, fields->fields->len);  /* free'd in output_fields_free() */
1370
1371     proto_tree_children_foreach(edt->tree, proto_tree_get_node_field_values,
1372                                 &data);
1373
1374     if (fields->includes_col_fields) {
1375         for (col = 0; col < cinfo->num_cols; col++) {
1376             /* Prepend COLUMN_FIELD_FILTER as the field name */
1377             col_name = ep_strdup_printf("%s%s", COLUMN_FIELD_FILTER, cinfo->col_title[col]);
1378             field_index = g_hash_table_lookup(fields->field_indicies, col_name);
1379
1380             if (NULL != field_index) {
1381                 format_field_values(fields, field_index, g_strdup(cinfo->col_data[col]));
1382             }
1383         }
1384     }
1385
1386     for(i = 0; i < fields->fields->len; ++i) {
1387         if (0 != i) {
1388             fputc(fields->separator, fh);
1389         }
1390         if (NULL != fields->field_values[i]) {
1391             GPtrArray *fv_p;
1392             gchar * str;
1393             gsize j;
1394             fv_p = fields->field_values[i];
1395             if (fields->quote != '\0') {
1396                 fputc(fields->quote, fh);
1397             }
1398
1399             /* Output the array of (partial) field values */
1400             for (j = 0; j < g_ptr_array_len(fv_p); j++ ) {
1401                 str = (gchar *)g_ptr_array_index(fv_p, j);
1402                 fputs(str, fh);
1403                 g_free(str);
1404             }
1405             if (fields->quote != '\0') {
1406                 fputc(fields->quote, fh);
1407             }
1408             g_ptr_array_free(fv_p, TRUE);  /* get ready for the next packet */
1409             fields->field_values[i] = NULL;
1410         }
1411     }
1412 }
1413
1414 void write_fields_finale(output_fields_t* fields _U_ , FILE *fh _U_)
1415 {
1416     /* Nothing to do */
1417 }
1418
1419 /* Returns an g_malloced string */
1420 gchar* get_node_field_value(field_info* fi, epan_dissect_t* edt)
1421 {
1422     if (fi->hfinfo->id == hf_text_only) {
1423         /* Text label.
1424          * Get the text */
1425         if (fi->rep) {
1426             return g_strdup(fi->rep->representation);
1427         }
1428         else {
1429             return get_field_hex_value(edt->pi.data_src, fi);
1430         }
1431     }
1432     else if (fi->hfinfo->id == proto_data) {
1433         /* Uninterpreted data, i.e., the "Data" protocol, is
1434          * printed as a field instead of a protocol. */
1435         return get_field_hex_value(edt->pi.data_src, fi);
1436     }
1437     else {
1438         /* Normal protocols and fields */
1439         gchar      *dfilter_string;
1440
1441         switch (fi->hfinfo->type)
1442         {
1443         case FT_PROTOCOL:
1444             /* Print out the full details for the protocol. */
1445             if (fi->rep) {
1446                 return g_strdup(fi->rep->representation);
1447             } else {
1448                 /* Just print out the protocol abbreviation */
1449                 return g_strdup(fi->hfinfo->abbrev);
1450             }
1451         case FT_NONE:
1452             /* Return "1" so that the presence of a field of type
1453              * FT_NONE can be checked when using -T fields */
1454             return g_strdup("1");
1455         default:
1456             dfilter_string = fvalue_to_string_repr(&fi->value, FTREPR_DISPLAY, NULL);
1457             if (dfilter_string != NULL) {
1458                 return dfilter_string;
1459             } else {
1460                 return get_field_hex_value(edt->pi.data_src, fi);
1461             }
1462         }
1463     }
1464 }
1465
1466 static gchar*
1467 get_field_hex_value(GSList *src_list, field_info *fi)
1468 {
1469     const guint8 *pd;
1470
1471     if (!fi->ds_tvb)
1472         return NULL;
1473
1474     if (fi->length > tvb_length_remaining(fi->ds_tvb, fi->start)) {
1475         return g_strdup("field length invalid!");
1476     }
1477
1478     /* Find the data for this field. */
1479     pd = get_field_data(src_list, fi);
1480
1481     if (pd) {
1482         int        i;
1483         gchar     *buffer;
1484         gchar     *p;
1485         int        len;
1486         const int  chars_per_byte = 2;
1487
1488         len    = chars_per_byte * fi->length;
1489         buffer = (gchar *)g_malloc(sizeof(gchar)*(len + 1));
1490         buffer[len] = '\0'; /* Ensure NULL termination in bad cases */
1491         p = buffer;
1492         /* Print a simple hex dump */
1493         for (i = 0 ; i < fi->length; i++) {
1494             g_snprintf(p, chars_per_byte+1, "%02x", pd[i]);
1495             p += chars_per_byte;
1496         }
1497         return buffer;
1498     } else {
1499         return NULL;
1500     }
1501 }
1502
1503 output_fields_t* output_fields_new(void)
1504 {
1505     output_fields_t* fields     = g_new(output_fields_t, 1);
1506     fields->print_header        = FALSE;
1507     fields->separator           = '\t';
1508     fields->occurrence          = 'a';
1509     fields->aggregator          = ',';
1510     fields->fields              = NULL; /*Do lazy initialisation */
1511     fields->field_indicies      = NULL;
1512     fields->field_values        = NULL;
1513     fields->quote               ='\0';
1514     fields->includes_col_fields = FALSE;
1515     return fields;
1516 }
1517
1518 /*
1519  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
1520  *
1521  * Local variables:
1522  * c-basic-offset: 4
1523  * tab-width: 8
1524  * indent-tabs-mode: nil
1525  * End:
1526  *
1527  * vi: set shiftwidth=4 tabstop=8 expandtab:
1528  * :indentSize=4:tabSize=8:noTabs=true:
1529  */