Honor protocols.display_hidden_proto_items preferences when outputting fields in...
[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 <epan/packet.h>
31 #include <epan/epan.h>
32 #include <epan/epan_dissect.h>
33 #include <epan/to_str.h>
34 #include <epan/expert.h>
35 #include <epan/packet-range.h>
36 #include <epan/prefs.h>
37 #include <epan/print.h>
38 #include <epan/charsets.h>
39 #include <wsutil/filesystem.h>
40 #include <ws_version_info.h>
41 #include <wsutil/utf8_entities.h>
42 #include <ftypes/ftypes-int.h>
43
44 #define PDML_VERSION "0"
45 #define PSML_VERSION "0"
46
47 typedef struct {
48     int                  level;
49     print_stream_t      *stream;
50     gboolean             success;
51     GSList              *src_list;
52     print_dissections_e  print_dissections;
53     gboolean             print_hex_for_data;
54     packet_char_enc      encoding;
55     GHashTable          *output_only_tables; /* output only these protocols */
56 } print_data;
57
58 typedef struct {
59     int             level;
60     FILE           *fh;
61     GSList         *src_list;
62     gchar         **filter;
63 } write_pdml_data;
64
65 typedef struct {
66     int             level;
67     FILE           *fh;
68     GSList         *src_list;
69     gchar         **filter;
70     gboolean        print_hex;
71 } write_json_data;
72
73 typedef struct {
74     output_fields_t *fields;
75     epan_dissect_t  *edt;
76 } write_field_data_t;
77
78 struct _output_fields {
79     gboolean      print_bom;
80     gboolean      print_header;
81     gchar         separator;
82     gchar         occurrence;
83     gchar         aggregator;
84     GPtrArray    *fields;
85     GHashTable   *field_indicies;
86     GPtrArray   **field_values;
87     gchar         quote;
88     gboolean      includes_col_fields;
89 };
90
91 static gchar *get_field_hex_value(GSList *src_list, field_info *fi);
92 static void proto_tree_print_node(proto_node *node, gpointer data);
93 static void proto_tree_write_node_pdml(proto_node *node, gpointer data);
94 static void proto_tree_write_node_json(proto_node *node, gpointer data);
95 static void proto_tree_write_node_ek(proto_node *node, gpointer data);
96 static const guint8 *get_field_data(GSList *src_list, field_info *fi);
97 static void pdml_write_field_hex_value(write_pdml_data *pdata, field_info *fi);
98 static void json_write_field_hex_value(write_json_data *pdata, field_info *fi);
99 static gboolean print_hex_data_buffer(print_stream_t *stream, const guchar *cp,
100                                       guint length, packet_char_enc encoding);
101 static void write_specified_fields(fields_format format,
102                                    output_fields_t *fields,
103                                    epan_dissect_t *edt, column_info *cinfo,
104                                    FILE *fh);
105 static void print_escaped_xml(FILE *fh, const char *unescaped_string);
106 static void print_escaped_json(FILE *fh, const char *unescaped_string);
107 static void print_escaped_ek(FILE *fh, const char *unescaped_string);
108
109 static void print_pdml_geninfo(epan_dissect_t *edt, FILE *fh);
110
111 static void proto_tree_get_node_field_values(proto_node *node, gpointer data);
112
113 static gboolean json_is_first;
114
115 /* Cache the protocols and field handles that the print functionality needs
116    This helps break explicit dependency on the dissectors. */
117 static int proto_data = -1;
118 static int proto_frame = -1;
119 static int hf_frame_arrival_time = -1;
120 static int hf_frame_number = -1;
121 static int hf_frame_len = -1;
122 static int hf_frame_capture_len = -1;
123
124 void print_cache_field_handles(void)
125 {
126     proto_data = proto_get_id_by_short_name("Data");
127     proto_frame = proto_get_id_by_short_name("Frame");
128     hf_frame_arrival_time = proto_registrar_get_id_byname("frame.time");
129     hf_frame_number = proto_registrar_get_id_byname("frame.number");
130     hf_frame_len = proto_registrar_get_id_byname("frame.len");
131     hf_frame_capture_len = proto_registrar_get_id_byname("frame.cap_len");
132 }
133
134 gboolean
135 proto_tree_print(print_args_t *print_args, epan_dissect_t *edt,
136                  GHashTable *output_only_tables, print_stream_t *stream)
137 {
138     print_data data;
139
140     /* Create the output */
141     data.level              = 0;
142     data.stream             = stream;
143     data.success            = TRUE;
144     data.src_list           = edt->pi.data_src;
145     data.encoding           = (packet_char_enc)edt->pi.fd->flags.encoding;
146     data.print_dissections  = print_args->print_dissections;
147     /* If we're printing the entire packet in hex, don't
148        print uninterpreted data fields in hex as well. */
149     data.print_hex_for_data = !print_args->print_hex;
150     data.output_only_tables = output_only_tables;
151
152     proto_tree_children_foreach(edt->tree, proto_tree_print_node, &data);
153     return data.success;
154 }
155
156 /* Print a tree's data, and any child nodes. */
157 static void
158 proto_tree_print_node(proto_node *node, gpointer data)
159 {
160     field_info   *fi    = PNODE_FINFO(node);
161     print_data   *pdata = (print_data*) data;
162     const guint8 *pd;
163     gchar         label_str[ITEM_LABEL_LENGTH];
164     gchar        *label_ptr;
165
166     /* dissection with an invisible proto tree? */
167     g_assert(fi);
168
169     /* Don't print invisible entries. */
170     if (PROTO_ITEM_IS_HIDDEN(node) && (prefs.display_hidden_proto_items == FALSE))
171         return;
172
173     /* Give up if we've already gotten an error. */
174     if (!pdata->success)
175         return;
176
177     /* was a free format label produced? */
178     if (fi->rep) {
179         label_ptr = fi->rep->representation;
180     }
181     else { /* no, make a generic label */
182         label_ptr = label_str;
183         proto_item_fill_label(fi, label_str);
184     }
185
186     if (PROTO_ITEM_IS_GENERATED(node))
187         label_ptr = g_strconcat("[", label_ptr, "]", NULL);
188
189     pdata->success = print_line(pdata->stream, pdata->level, label_ptr);
190
191     if (PROTO_ITEM_IS_GENERATED(node))
192         g_free(label_ptr);
193
194     if (!pdata->success)
195         return;
196
197     /*
198      * If -O is specified, only display the protocols which are in the
199      * lookup table.  Only check on the first level: once we start printing
200      * a tree, print the rest of the subtree.  Otherwise we won't print
201      * subitems whose abbreviation doesn't match the protocol--for example
202      * text items (whose abbreviation is simply "text").
203      */
204     if ((pdata->output_only_tables != NULL) && (pdata->level == 0)
205         && (g_hash_table_lookup(pdata->output_only_tables, fi->hfinfo->abbrev) == NULL)) {
206         return;
207     }
208
209     /* If it's uninterpreted data, dump it (unless our caller will
210        be printing the entire packet in hex). */
211     if ((fi->hfinfo->id == proto_data) && (pdata->print_hex_for_data)) {
212         /*
213          * Find the data for this field.
214          */
215         pd = get_field_data(pdata->src_list, fi);
216         if (pd) {
217             if (!print_line(pdata->stream, 0, "")) {
218                 pdata->success = FALSE;
219                 return;
220             }
221             if (!print_hex_data_buffer(pdata->stream, pd,
222                                        fi->length, pdata->encoding)) {
223                 pdata->success = FALSE;
224                 return;
225             }
226         }
227     }
228
229     /* If we're printing all levels, or if this node is one with a
230        subtree and its subtree is expanded, recurse into the subtree,
231        if it exists. */
232     g_assert((fi->tree_type >= -1) && (fi->tree_type < num_tree_types));
233     if ((pdata->print_dissections == print_dissections_expanded) ||
234         ((pdata->print_dissections == print_dissections_as_displayed) &&
235          (fi->tree_type >= 0) && tree_expanded(fi->tree_type))) {
236         if (node->first_child != NULL) {
237             pdata->level++;
238             proto_tree_children_foreach(node,
239                                         proto_tree_print_node, pdata);
240             pdata->level--;
241             if (!pdata->success)
242                 return;
243         }
244     }
245 }
246
247 #define PDML2HTML_XSL "pdml2html.xsl"
248 void
249 write_pdml_preamble(FILE *fh, const gchar *filename)
250 {
251     time_t t = time(NULL);
252     struct tm * timeinfo;
253     char *fmt_ts;
254     const char *ts;
255
256     /* Create the output */
257     timeinfo = localtime(&t);
258     if (timeinfo != NULL) {
259         fmt_ts = asctime(timeinfo);
260         fmt_ts[strlen(fmt_ts)-1] = 0; /* overwrite \n */
261         ts = fmt_ts;
262     } else
263         ts = "Not representable";
264
265     fprintf(fh, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
266     fprintf(fh, "<?xml-stylesheet type=\"text/xsl\" href=\"" PDML2HTML_XSL "\"?>\n");
267     fprintf(fh, "<!-- You can find " PDML2HTML_XSL " in %s or at https://code.wireshark.org/review/gitweb?p=wireshark.git;a=blob_plain;f=" PDML2HTML_XSL ". -->\n", get_datafile_dir());
268     fprintf(fh, "<pdml version=\"" PDML_VERSION "\" creator=\"%s/%s\" time=\"%s\" capture_file=\"", PACKAGE, VERSION, ts);
269     if (filename) {
270         /* \todo filename should be converted to UTF-8. */
271         print_escaped_xml(fh, filename);
272     }
273     fprintf(fh, "\">\n");
274 }
275
276 void
277 write_json_preamble(FILE *fh)
278 {
279     fputs("[\n", fh);
280     json_is_first = TRUE;
281 }
282
283 /* Check if the str match the protocolfilter. json_filter is space
284    delimited string and str need to exact-match to one of the value. */
285 static gboolean check_protocolfilter(gchar **protocolfilter, const char *str)
286 {
287     gboolean res = FALSE;
288     gchar **ptr;
289
290     if (str == NULL || protocolfilter == NULL) {
291         return FALSE;
292     }
293
294     for (ptr = protocolfilter; *ptr; ptr++) {
295         if (strcmp(*ptr, str) == 0) {
296             res = TRUE;
297             break;
298         }
299     }
300
301     return res;
302 }
303
304 void
305 write_pdml_proto_tree(output_fields_t* fields, gchar **protocolfilter, epan_dissect_t *edt, FILE *fh)
306 {
307     write_pdml_data data;
308
309     g_assert(edt);
310     g_assert(fh);
311
312     /* Create the output */
313     fprintf(fh, "<packet>\n");
314
315     /* Print a "geninfo" protocol as required by PDML */
316     print_pdml_geninfo(edt, fh);
317
318     if (fields == NULL || fields->fields == NULL) {
319         /* Write out all fields */
320         data.level    = 0;
321         data.fh       = fh;
322         data.src_list = edt->pi.data_src;
323         data.filter   = protocolfilter;
324
325         proto_tree_children_foreach(edt->tree, proto_tree_write_node_pdml,
326                                     &data);
327     } else {
328         /* Write out specified fields */
329         write_specified_fields(FORMAT_XML, fields, edt, NULL, fh);
330     }
331
332     fprintf(fh, "</packet>\n\n");
333 }
334
335 void
336 write_json_proto_tree(output_fields_t* fields, print_args_t *print_args, gchar **protocolfilter, epan_dissect_t *edt, FILE *fh)
337 {
338     write_json_data data;
339     char ts[30];
340     time_t t = time(NULL);
341     struct tm * timeinfo;
342
343     g_assert(edt);
344     g_assert(fh);
345
346     /* Create the output */
347     timeinfo = localtime(&t);
348     if (timeinfo != NULL)
349         strftime(ts, sizeof ts, "%Y-%m-%d", timeinfo);
350     else
351         g_strlcpy(ts, "XXXX-XX-XX", sizeof ts); /* XXX - better way of saying "Not representable"? */
352
353     if (!json_is_first)
354         fputs("  ,\n", fh);
355     else
356         json_is_first = FALSE;
357
358     fputs("  {\n", fh);
359     fprintf(fh, "    \"_index\": \"packets-%s\",\n", ts);
360     fputs("    \"_type\": \"pcap_file\",\n", fh);
361     fputs("    \"_score\": null,\n", fh);
362     fputs("    \"_source\": {\n", fh);
363     fputs("      \"layers\": {\n", fh);
364
365     if (fields == NULL || fields->fields == NULL) {
366         /* Write out all fields */
367         data.level    = 1;
368         data.fh       = fh;
369         data.src_list = edt->pi.data_src;
370         data.filter   = protocolfilter;
371         data.print_hex = print_args->print_hex;
372
373         proto_tree_children_foreach(edt->tree, proto_tree_write_node_json,
374                                     &data);
375     } else {
376         /* Write out specified fields */
377         write_specified_fields(FORMAT_JSON, fields, edt, NULL, fh);
378     }
379
380     fputs("      }\n", fh);
381     fputs("    }\n", fh);
382     fputs("  }\n", fh);
383
384 }
385
386 void
387 write_ek_proto_tree(output_fields_t* fields, print_args_t *print_args, gchar **protocolfilter, epan_dissect_t *edt, FILE *fh)
388 {
389     write_json_data data;
390     char ts[30];
391     time_t t = time(NULL);
392     struct tm  *timeinfo;
393
394     g_assert(edt);
395     g_assert(fh);
396
397     /* Create the output */
398     timeinfo = localtime(&t);
399     if (timeinfo != NULL)
400         strftime(ts, sizeof ts, "%Y-%m-%d", timeinfo);
401     else
402         g_strlcpy(ts, "XXXX-XX-XX", sizeof ts); /* XXX - better way of saying "Not representable"? */
403
404     fprintf(fh, "{\"index\" : {\"_index\": \"packets-%s\", \"_type\": \"pcap_file\", \"_score\": null}}\n", ts);
405     /* Timestamp added for time indexing in Elasticsearch */
406     fprintf(fh, "{\"timestamp\" : \"%" G_GUINT64_FORMAT "%03d\", \"layers\" : {", (guint64)edt->pi.abs_ts.secs, edt->pi.abs_ts.nsecs/1000000);
407
408     if (fields == NULL || fields->fields == NULL) {
409         /* Write out all fields */
410         data.level    = 0;
411         data.fh       = fh;
412         data.src_list = edt->pi.data_src;
413         data.filter   = protocolfilter;
414         data.print_hex = print_args->print_hex;
415
416         proto_tree_children_foreach(edt->tree, proto_tree_write_node_ek,
417                                     &data);
418     } else {
419         /* Write out specified fields */
420         write_specified_fields(FORMAT_EK, fields, edt, NULL, fh);
421     }
422
423     fputs("}}\n", fh);
424 }
425
426 void
427 write_fields_proto_tree(output_fields_t* fields, epan_dissect_t *edt, column_info *cinfo, FILE *fh)
428 {
429     g_assert(edt);
430     g_assert(fh);
431
432     /* Create the output */
433     write_specified_fields(FORMAT_CSV, fields, edt, cinfo, fh);
434 }
435
436 /* Write out a tree's data, and any child nodes, as PDML */
437 static void
438 proto_tree_write_node_pdml(proto_node *node, gpointer data)
439 {
440     field_info      *fi    = PNODE_FINFO(node);
441     write_pdml_data *pdata = (write_pdml_data*) data;
442     const gchar     *label_ptr;
443     gchar            label_str[ITEM_LABEL_LENGTH];
444     char            *dfilter_string;
445     int              i;
446     gboolean         wrap_in_fake_protocol;
447
448     /* dissection with an invisible proto tree? */
449     g_assert(fi);
450
451     /* Will wrap up top-level field items inside a fake protocol wrapper to
452        preserve the PDML schema */
453     wrap_in_fake_protocol =
454         (((fi->hfinfo->type != FT_PROTOCOL) ||
455           (fi->hfinfo->id == proto_data)) &&
456          (pdata->level == 0));
457
458     /* Indent to the correct level */
459     for (i = -1; i < pdata->level; i++) {
460         fputs("  ", pdata->fh);
461     }
462
463     if (wrap_in_fake_protocol) {
464         /* Open fake protocol wrapper */
465         fputs("<proto name=\"fake-field-wrapper\">\n", pdata->fh);
466
467         /* Indent to increased level before writing out field */
468         pdata->level++;
469         for (i = -1; i < pdata->level; i++) {
470             fputs("  ", pdata->fh);
471         }
472     }
473
474     /* Text label. It's printed as a field with no name. */
475     if (fi->hfinfo->id == hf_text_only) {
476         /* Get the text */
477         if (fi->rep) {
478             label_ptr = fi->rep->representation;
479         }
480         else {
481             label_ptr = "";
482         }
483
484         /* Show empty name since it is a required field */
485         fputs("<field name=\"", pdata->fh);
486         fputs("\" show=\"", pdata->fh);
487         print_escaped_xml(pdata->fh, label_ptr);
488
489         fprintf(pdata->fh, "\" size=\"%d", fi->length);
490         if (node->parent && node->parent->finfo && (fi->start < node->parent->finfo->start)) {
491             fprintf(pdata->fh, "\" pos=\"%d", node->parent->finfo->start + fi->start);
492         } else {
493             fprintf(pdata->fh, "\" pos=\"%d", fi->start);
494         }
495
496         if (fi->length > 0) {
497             fputs("\" value=\"", pdata->fh);
498             pdml_write_field_hex_value(pdata, fi);
499         }
500
501         if (node->first_child != NULL) {
502             fputs("\">\n", pdata->fh);
503         }
504         else {
505             fputs("\"/>\n", pdata->fh);
506         }
507     }
508
509     /* Uninterpreted data, i.e., the "Data" protocol, is
510      * printed as a field instead of a protocol. */
511     else if (fi->hfinfo->id == proto_data) {
512         /* Write out field with data */
513         fputs("<field name=\"data\" value=\"", pdata->fh);
514         pdml_write_field_hex_value(pdata, fi);
515         fputs("\">\n", pdata->fh);
516     }
517     /* Normal protocols and fields */
518     else {
519         if ((fi->hfinfo->type == FT_PROTOCOL) && (fi->hfinfo->id != proto_expert)) {
520             fputs("<proto name=\"", pdata->fh);
521         }
522         else {
523             fputs("<field name=\"", pdata->fh);
524         }
525         print_escaped_xml(pdata->fh, fi->hfinfo->abbrev);
526
527 #if 0
528         /* PDML spec, see:
529          * http://www.nbee.org/doku.php?id=netpdl:pdml_specification
530          *
531          * the show fields contains things in 'human readable' format
532          * showname: contains only the name of the field
533          * show: contains only the data of the field
534          * showdtl: contains additional details of the field data
535          * showmap: contains mappings of the field data (e.g. the hostname to an IP address)
536          *
537          * XXX - the showname shouldn't contain the field data itself
538          * (like it's contained in the fi->rep->representation).
539          * Unfortunately, we don't have the field data representation for
540          * all fields, so this isn't currently possible */
541         fputs("\" showname=\"", pdata->fh);
542         print_escaped_xml(pdata->fh, fi->hfinfo->name);
543 #endif
544
545         if (fi->rep) {
546             fputs("\" showname=\"", pdata->fh);
547             print_escaped_xml(pdata->fh, fi->rep->representation);
548         }
549         else {
550             label_ptr = label_str;
551             proto_item_fill_label(fi, label_str);
552             fputs("\" showname=\"", pdata->fh);
553             print_escaped_xml(pdata->fh, label_ptr);
554         }
555
556         if (PROTO_ITEM_IS_HIDDEN(node) && (prefs.display_hidden_proto_items == FALSE))
557             fprintf(pdata->fh, "\" hide=\"yes");
558
559         fprintf(pdata->fh, "\" size=\"%d", fi->length);
560         if (node->parent && node->parent->finfo && (fi->start < node->parent->finfo->start)) {
561             fprintf(pdata->fh, "\" pos=\"%d", node->parent->finfo->start + fi->start);
562         } else {
563             fprintf(pdata->fh, "\" pos=\"%d", fi->start);
564         }
565 /*      fprintf(pdata->fh, "\" id=\"%d", fi->hfinfo->id);*/
566
567         /* show, value, and unmaskedvalue attributes */
568         switch (fi->hfinfo->type)
569         {
570         case FT_PROTOCOL:
571             break;
572         case FT_NONE:
573             fputs("\" show=\"\" value=\"",  pdata->fh);
574             break;
575         default:
576             dfilter_string = fvalue_to_string_repr(NULL, &fi->value, FTREPR_DISPLAY, fi->hfinfo->display);
577             if (dfilter_string != NULL) {
578
579                 fputs("\" show=\"", pdata->fh);
580                 print_escaped_xml(pdata->fh, dfilter_string);
581             }
582             wmem_free(NULL, dfilter_string);
583
584             /*
585              * XXX - should we omit "value" for any fields?
586              * What should we do for fields whose length is 0?
587              * They might come from a pseudo-header or from
588              * the capture header (e.g., time stamps), or
589              * they might be generated fields.
590              */
591             if (fi->length > 0) {
592                 fputs("\" value=\"", pdata->fh);
593
594                 if (fi->hfinfo->bitmask!=0) {
595                     switch (fi->value.ftype->ftype) {
596                         case FT_INT8:
597                         case FT_INT16:
598                         case FT_INT24:
599                         case FT_INT32:
600                             fprintf(pdata->fh, "%X", (guint) fvalue_get_sinteger(&fi->value));
601                             break;
602                         case FT_UINT8:
603                         case FT_UINT16:
604                         case FT_UINT24:
605                         case FT_UINT32:
606                             fprintf(pdata->fh, "%X", fvalue_get_uinteger(&fi->value));
607                             break;
608                         case FT_INT40:
609                         case FT_INT48:
610                         case FT_INT56:
611                         case FT_INT64:
612                             fprintf(pdata->fh, "%" G_GINT64_MODIFIER "X", fvalue_get_sinteger64(&fi->value));
613                             break;
614                         case FT_UINT40:
615                         case FT_UINT48:
616                         case FT_UINT56:
617                         case FT_UINT64:
618                         case FT_BOOLEAN:
619                             fprintf(pdata->fh, "%" G_GINT64_MODIFIER "X", fvalue_get_uinteger64(&fi->value));
620                             break;
621                         default:
622                             g_assert_not_reached();
623                     }
624                     fputs("\" unmaskedvalue=\"", pdata->fh);
625                     pdml_write_field_hex_value(pdata, fi);
626                 }
627                 else {
628                     pdml_write_field_hex_value(pdata, fi);
629                 }
630             }
631         }
632
633         if (node->first_child != NULL) {
634             fputs("\">\n", pdata->fh);
635         }
636         else if (fi->hfinfo->id == proto_data) {
637             fputs("\">\n", pdata->fh);
638         }
639         else {
640             fputs("\"/>\n", pdata->fh);
641         }
642     }
643
644     /* We print some levels for PDML. Recurse here. */
645     if (node->first_child != NULL) {
646         if (pdata->filter == NULL || check_protocolfilter(pdata->filter, fi->hfinfo->abbrev)) {
647             pdata->level++;
648             proto_tree_children_foreach(node,
649                                         proto_tree_write_node_pdml, pdata);
650             pdata->level--;
651         } else {
652             /* Indent to the correct level */
653             for (i = -2; i < pdata->level; i++) {
654                 fputs("  ", pdata->fh);
655             }
656             /* print dummy field */
657             fputs("<field name=\"filtered\" value=\"", pdata->fh);
658             print_escaped_xml(pdata->fh, fi->hfinfo->abbrev);
659             fputs("\" />\n", pdata->fh);
660         }
661     }
662
663     /* Take back the extra level we added for fake wrapper protocol */
664     if (wrap_in_fake_protocol) {
665         pdata->level--;
666     }
667
668     if (node->first_child != NULL) {
669         /* Indent to correct level */
670         for (i = -1; i < pdata->level; i++) {
671             fputs("  ", pdata->fh);
672         }
673         /* Close off current element */
674         /* Data and expert "protocols" use simple tags */
675         if ((fi->hfinfo->id != proto_data) && (fi->hfinfo->id != proto_expert)) {
676             if (fi->hfinfo->type == FT_PROTOCOL) {
677                 fputs("</proto>\n", pdata->fh);
678             }
679             else {
680                 fputs("</field>\n", pdata->fh);
681             }
682         } else {
683             fputs("</field>\n", pdata->fh);
684         }
685     }
686
687     /* Close off fake wrapper protocol */
688     if (wrap_in_fake_protocol) {
689         fputs("</proto>\n", pdata->fh);
690     }
691 }
692
693
694 /* Write out a tree's data, and any child nodes, as JSON */
695 static void
696 proto_tree_write_node_json(proto_node *node, gpointer data)
697 {
698     field_info      *fi    = PNODE_FINFO(node);
699     write_json_data *pdata = (write_json_data*) data;
700     const gchar     *label_ptr;
701     gchar            label_str[ITEM_LABEL_LENGTH];
702     char            *dfilter_string;
703     int              i;
704
705     /* dissection with an invisible proto tree? */
706     g_assert(fi);
707
708     /* Indent to the correct level */
709     for (i = -3; i < pdata->level; i++) {
710         fputs("  ", pdata->fh);
711     }
712
713     /* Text label. It's printed as a field with no name. */
714     if (fi->hfinfo->id == hf_text_only) {
715         /* Get the text */
716         if (fi->rep) {
717             label_ptr = fi->rep->representation;
718         }
719         else {
720             label_ptr = "";
721         }
722
723         /* Show empty name since it is a required field */
724         fputs("\"", pdata->fh);
725         print_escaped_json(pdata->fh, label_ptr);
726
727         if (node->first_child != NULL) {
728             fputs("\": {\n", pdata->fh);
729         }
730         else {
731             if (node->next == NULL) {
732               fputs("\": \"\"\n",  pdata->fh);
733             } else {
734               fputs("\": \"\",\n",  pdata->fh);
735             }
736         }
737     }
738
739     /* Normal protocols and fields */
740     else {
741         /*
742          * Hex dump -x
743          */
744         if (pdata->print_hex && fi->length > 0) {
745             fputs("\"", pdata->fh);
746             print_escaped_json(pdata->fh, fi->hfinfo->abbrev);
747             fputs("_raw", pdata->fh);
748             fputs("\": \"", pdata->fh);
749
750             if (fi->hfinfo->bitmask!=0) {
751                 switch (fi->value.ftype->ftype) {
752                     case FT_INT8:
753                     case FT_INT16:
754                     case FT_INT24:
755                     case FT_INT32:
756                         fprintf(pdata->fh, "%X", (guint) fvalue_get_sinteger(&fi->value));
757                         break;
758                     case FT_UINT8:
759                     case FT_UINT16:
760                     case FT_UINT24:
761                     case FT_UINT32:
762                         fprintf(pdata->fh, "%X", fvalue_get_uinteger(&fi->value));
763                         break;
764                     case FT_INT40:
765                     case FT_INT48:
766                     case FT_INT56:
767                     case FT_INT64:
768                         fprintf(pdata->fh, "%" G_GINT64_MODIFIER "X", fvalue_get_sinteger64(&fi->value));
769                         break;
770                     case FT_UINT40:
771                     case FT_UINT48:
772                     case FT_UINT56:
773                     case FT_UINT64:
774                     case FT_BOOLEAN:
775                         fprintf(pdata->fh, "%" G_GINT64_MODIFIER "X", fvalue_get_uinteger64(&fi->value));
776                         break;
777                     default:
778                         g_assert_not_reached();
779                 }
780                 fputs("\",\n", pdata->fh);
781             }
782             else {
783                 json_write_field_hex_value(pdata, fi);
784                 fputs("\",\n", pdata->fh);
785             }
786
787             /* Indent to the correct level */
788             for (i = -3; i < pdata->level; i++) {
789                 fputs("  ", pdata->fh);
790             }
791         }
792
793
794         fputs("\"", pdata->fh);
795
796         print_escaped_json(pdata->fh, fi->hfinfo->abbrev);
797
798         /* show, value, and unmaskedvalue attributes */
799         switch (fi->hfinfo->type)
800         {
801         case FT_PROTOCOL:
802             if (node->first_child != NULL) {
803                 fputs("\": {\n", pdata->fh);
804             } else {
805                 fputs("\": \"", pdata->fh);
806                 if (fi->rep) {
807                     print_escaped_json(pdata->fh, fi->rep->representation);
808                 }
809                 else {
810                     label_ptr = label_str;
811                     proto_item_fill_label(fi, label_str);
812                     print_escaped_json(pdata->fh, label_ptr);
813                 }
814                 if (node->next == NULL) {
815                     fputs("\"\n",  pdata->fh);
816                 } else {
817                     fputs("\",\n",  pdata->fh);
818                 }
819             }
820             break;
821         case FT_NONE:
822             if (node->first_child != NULL) {
823                 fputs("\": {\n", pdata->fh);
824             } else {
825                 if (node->next == NULL) {
826                   fputs("\": \"\"\n",  pdata->fh);
827                 } else {
828                   fputs("\": \"\",\n",  pdata->fh);
829                 }
830             }
831             break;
832         default:
833             dfilter_string = fvalue_to_string_repr(NULL, &fi->value, FTREPR_DISPLAY, fi->hfinfo->display);
834             if (dfilter_string != NULL) {
835                 fputs("\": \"", pdata->fh);
836                 print_escaped_json(pdata->fh, dfilter_string);
837                 if (node->first_child != NULL) {
838                     fputs("\",\n", pdata->fh);
839                     /* Indent to the correct level */
840                     for (i = -3; i < pdata->level; i++) {
841                         fputs("  ", pdata->fh);
842                     }
843                     fputs("\"", pdata->fh);
844                     print_escaped_json(pdata->fh, fi->hfinfo->abbrev);
845                     fputs("_tree\": {\n", pdata->fh);
846                 }
847             }
848             wmem_free(NULL, dfilter_string);
849
850             if (node->first_child == NULL) {
851                 if (node->next == NULL) {
852                     fputs("\"\n", pdata->fh);
853                 } else {
854                     fputs("\",\n", pdata->fh);
855                 }
856             }
857         }
858
859     }
860
861     /* We print some levels for JSON. Recurse here. */
862     if (node->first_child != NULL) {
863         if (pdata->filter == NULL || check_protocolfilter(pdata->filter, fi->hfinfo->abbrev)) {
864             pdata->level++;
865             proto_tree_children_foreach(node, proto_tree_write_node_json, pdata);
866             pdata->level--;
867         } else {
868             /* Indent to the correct level */
869             for (i = -4; i < pdata->level; i++) {
870                 fputs("  ", pdata->fh);
871             }
872             /* print dummy field */
873             fputs("\"filtered\": \"", pdata->fh);
874             print_escaped_json(pdata->fh, fi->hfinfo->abbrev);
875             fputs("\"\n", pdata->fh);
876         }
877     }
878
879     if (node->first_child != NULL) {
880         /* Indent to correct level */
881         for (i = -3; i < pdata->level; i++) {
882             fputs("  ", pdata->fh);
883         }
884         /* Close off current element */
885         if (node->next == NULL) {
886             fputs("}\n", pdata->fh);
887         } else {
888             fputs("},\n", pdata->fh);
889         }
890     }
891 }
892
893 /* Write out a tree's data, and any child nodes, as JSON for EK */
894 static void
895 proto_tree_write_node_ek(proto_node *node, gpointer data)
896 {
897     field_info      *fi    = PNODE_FINFO(node);
898     field_info      *fi_parent    = PNODE_FINFO(node->parent);
899     write_json_data *pdata = (write_json_data*) data;
900     const gchar     *label_ptr;
901     gchar            label_str[ITEM_LABEL_LENGTH];
902     char            *dfilter_string;
903     int              i;
904     gchar           *abbrev_escaped = NULL;
905
906     /* dissection with an invisible proto tree? */
907     g_assert(fi);
908
909     /* Text label. It's printed as a field with no name. */
910     if (fi->hfinfo->id == hf_text_only) {
911         /* Get the text */
912         if (fi->rep) {
913             label_ptr = fi->rep->representation;
914         }
915         else {
916             label_ptr = "";
917         }
918
919         /* Show empty name since it is a required field */
920         fputs("\"", pdata->fh);
921         if (fi_parent != NULL) {
922             print_escaped_ek(pdata->fh, fi_parent->hfinfo->abbrev);
923             fputs("_", pdata->fh);
924         }
925         print_escaped_ek(pdata->fh, fi->hfinfo->abbrev);
926
927         if (node->first_child != NULL) {
928             fputs("\": \"", pdata->fh);
929             print_escaped_json(pdata->fh, label_ptr);
930             fputs("\",", pdata->fh);
931
932         }
933         else {
934             if (node->next == NULL) {
935                 fputs("\": \"",  pdata->fh);
936                 print_escaped_json(pdata->fh, label_ptr);
937                 fputs("\"", pdata->fh);
938             } else {
939                 fputs("\": \"",  pdata->fh);
940                 print_escaped_json(pdata->fh, label_ptr);
941                 fputs("\",", pdata->fh);
942             }
943         }
944     }
945
946     /* Normal protocols and fields */
947     else {
948         /*
949          * Hex dump -x
950          */
951         if (pdata->print_hex && fi->length > 0) {
952             fputs("\"", pdata->fh);
953             if (fi_parent != NULL) {
954                 print_escaped_ek(pdata->fh, fi_parent->hfinfo->abbrev);
955                 fputs("_", pdata->fh);
956             }
957             print_escaped_ek(pdata->fh, fi->hfinfo->abbrev);
958             fputs("_raw", pdata->fh);
959             fputs("\": \"", pdata->fh);
960
961             if (fi->hfinfo->bitmask!=0) {
962                 switch (fi->value.ftype->ftype) {
963                     case FT_INT8:
964                     case FT_INT16:
965                     case FT_INT24:
966                     case FT_INT32:
967                         fprintf(pdata->fh, "%X", (guint) fvalue_get_sinteger(&fi->value));
968                         break;
969                     case FT_UINT8:
970                     case FT_UINT16:
971                     case FT_UINT24:
972                     case FT_UINT32:
973                         fprintf(pdata->fh, "%X", fvalue_get_uinteger(&fi->value));
974                         break;
975                     case FT_INT40:
976                     case FT_INT48:
977                     case FT_INT56:
978                     case FT_INT64:
979                         fprintf(pdata->fh, "%" G_GINT64_MODIFIER "X", fvalue_get_sinteger64(&fi->value));
980                         break;
981                     case FT_UINT40:
982                     case FT_UINT48:
983                     case FT_UINT56:
984                     case FT_UINT64:
985                     case FT_BOOLEAN:
986                         fprintf(pdata->fh, "%" G_GINT64_MODIFIER "X", fvalue_get_uinteger64(&fi->value));
987                         break;
988                     default:
989                         g_assert_not_reached();
990                 }
991                 fputs("\",", pdata->fh);
992             }
993             else {
994                 json_write_field_hex_value(pdata, fi);
995                 fputs("\",", pdata->fh);
996             }
997         }
998
999
1000
1001         fputs("\"", pdata->fh);
1002
1003         if (fi_parent != NULL) {
1004             print_escaped_ek(pdata->fh, fi_parent->hfinfo->abbrev);
1005             fputs("_", pdata->fh);
1006         }
1007         print_escaped_ek(pdata->fh, fi->hfinfo->abbrev);
1008
1009         /* show, value, and unmaskedvalue attributes */
1010         switch (fi->hfinfo->type)
1011         {
1012         case FT_PROTOCOL:
1013             if (node->first_child != NULL) {
1014                 fputs("\": {", pdata->fh);
1015             } else {
1016                 fputs("\": \"", pdata->fh);
1017                 if (fi->rep) {
1018                     print_escaped_json(pdata->fh, fi->rep->representation);
1019                 }
1020                 else {
1021                     label_ptr = label_str;
1022                     proto_item_fill_label(fi, label_str);
1023                     print_escaped_json(pdata->fh, label_ptr);
1024                 }
1025                 if (node->next == NULL) {
1026                     fputs("\"",  pdata->fh);
1027                 } else {
1028                     fputs("\",",  pdata->fh);
1029                 }
1030             }
1031             break;
1032         case FT_NONE:
1033             if (node->first_child != NULL) {
1034                 fputs("\": \"\",",  pdata->fh);
1035             } else {
1036                 if (node->next == NULL) {
1037                     fputs("\": \"\"",  pdata->fh);
1038                 } else {
1039                     fputs("\": \"\",",  pdata->fh);
1040                 }
1041             }
1042             break;
1043         default:
1044             dfilter_string = fvalue_to_string_repr(NULL, &fi->value, FTREPR_DISPLAY, fi->hfinfo->display);
1045             if (dfilter_string != NULL) {
1046                 fputs("\": \"", pdata->fh);
1047                 print_escaped_json(pdata->fh, dfilter_string);
1048             }
1049             wmem_free(NULL, dfilter_string);
1050
1051             if (node->next == NULL && node->first_child == NULL) {
1052                 fputs("\"", pdata->fh);
1053             } else {
1054                 fputs("\",", pdata->fh);
1055             }
1056         }
1057
1058     }
1059
1060     /* We print some levels for JSON. Recurse here. */
1061     if (node->first_child != NULL) {
1062
1063         if (pdata->filter != NULL) {
1064
1065             /* to to thread the '.' and '_' equally. The '.' is replace by print_escaped_ek for '_' */
1066             if (fi->hfinfo->abbrev != NULL) {
1067                 if (strlen(fi->hfinfo->abbrev) > 0) {
1068                     abbrev_escaped = g_strdup(fi->hfinfo->abbrev);
1069
1070                     i = 0;
1071                     while(abbrev_escaped[i]!='\0') {
1072                         if(abbrev_escaped[i]=='.') {
1073                             abbrev_escaped[i]='_';
1074                         }
1075                         i++;
1076                     }
1077                 }
1078             }
1079
1080             if(check_protocolfilter(pdata->filter, fi->hfinfo->abbrev) || check_protocolfilter(pdata->filter, abbrev_escaped)) {
1081                 pdata->level++;
1082                 proto_tree_children_foreach(node, proto_tree_write_node_ek, pdata);
1083                 pdata->level--;
1084             } else {
1085                 /* print dummy field */
1086                 fputs("\"filtered\": \"", pdata->fh);
1087                 print_escaped_ek(pdata->fh, fi->hfinfo->abbrev);
1088                 fputs("\"", pdata->fh);
1089             }
1090
1091             /* release abbrev_escaped string */
1092             if (abbrev_escaped != NULL) {
1093                 g_free(abbrev_escaped);
1094             }
1095
1096         } else {
1097             pdata->level++;
1098             proto_tree_children_foreach(node,
1099                                         proto_tree_write_node_ek, pdata);
1100             pdata->level--;
1101         }
1102     }
1103
1104     if (node->first_child != NULL) {
1105         if (fi->hfinfo->type == FT_PROTOCOL) {
1106             /* Close off current element */
1107             if (node->next == NULL) {
1108                 fputs("}", pdata->fh);
1109             } else {
1110                 fputs("},", pdata->fh);
1111             }
1112         } else {
1113             if (node->next != NULL) {
1114                 fputs(",", pdata->fh);
1115             }
1116         }
1117     }
1118 }
1119
1120 /* Print info for a 'geninfo' pseudo-protocol. This is required by
1121  * the PDML spec. The information is contained in Wireshark's 'frame' protocol,
1122  * but we produce a 'geninfo' protocol in the PDML to conform to spec.
1123  * The 'frame' protocol follows the 'geninfo' protocol in the PDML. */
1124 static void
1125 print_pdml_geninfo(epan_dissect_t *edt, FILE *fh)
1126 {
1127     guint32     num, len, caplen;
1128     GPtrArray  *finfo_array;
1129     field_info *frame_finfo;
1130     gchar      *tmp;
1131
1132     /* Get frame protocol's finfo. */
1133     finfo_array = proto_find_first_finfo(edt->tree, proto_frame);
1134     if (g_ptr_array_len(finfo_array) < 1) {
1135         return;
1136     }
1137     frame_finfo = (field_info *)finfo_array->pdata[0];
1138     g_ptr_array_free(finfo_array, TRUE);
1139
1140     /* frame.number, packet_info.num */
1141     num = edt->pi.num;
1142
1143     /* frame.frame_len, packet_info.frame_data->pkt_len */
1144     len = edt->pi.fd->pkt_len;
1145
1146     /* frame.cap_len --> packet_info.frame_data->cap_len */
1147     caplen = edt->pi.fd->cap_len;
1148
1149     /* Print geninfo start */
1150     fprintf(fh,
1151             "  <proto name=\"geninfo\" pos=\"0\" showname=\"General information\" size=\"%d\">\n",
1152             frame_finfo->length);
1153
1154     /* Print geninfo.num */
1155     fprintf(fh,
1156             "    <field name=\"num\" pos=\"0\" show=\"%u\" showname=\"Number\" value=\"%x\" size=\"%d\"/>\n",
1157             num, num, frame_finfo->length);
1158
1159     /* Print geninfo.len */
1160     fprintf(fh,
1161             "    <field name=\"len\" pos=\"0\" show=\"%u\" showname=\"Frame Length\" value=\"%x\" size=\"%d\"/>\n",
1162             len, len, frame_finfo->length);
1163
1164     /* Print geninfo.caplen */
1165     fprintf(fh,
1166             "    <field name=\"caplen\" pos=\"0\" show=\"%u\" showname=\"Captured Length\" value=\"%x\" size=\"%d\"/>\n",
1167             caplen, caplen, frame_finfo->length);
1168
1169     tmp = abs_time_to_str(NULL, &edt->pi.abs_ts, ABSOLUTE_TIME_LOCAL, TRUE);
1170
1171     /* Print geninfo.timestamp */
1172     fprintf(fh,
1173             "    <field name=\"timestamp\" pos=\"0\" show=\"%s\" showname=\"Captured Time\" value=\"%d.%09d\" size=\"%d\"/>\n",
1174             tmp, (int)edt->pi.abs_ts.secs, edt->pi.abs_ts.nsecs, frame_finfo->length);
1175
1176     wmem_free(NULL, tmp);
1177
1178     /* Print geninfo end */
1179     fprintf(fh,
1180             "  </proto>\n");
1181 }
1182
1183 void
1184 write_pdml_finale(FILE *fh)
1185 {
1186     fputs("</pdml>\n", fh);
1187 }
1188
1189 void
1190 write_json_finale(FILE *fh)
1191 {
1192     fputs("]\n", fh);
1193 }
1194
1195 void
1196 write_psml_preamble(column_info *cinfo, FILE *fh)
1197 {
1198     gint i;
1199
1200     fprintf(fh, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
1201     fprintf(fh, "<psml version=\"" PSML_VERSION "\" creator=\"%s/%s\">\n", PACKAGE, VERSION);
1202     fprintf(fh, "<structure>\n");
1203
1204     for (i = 0; i < cinfo->num_cols; i++) {
1205         fprintf(fh, "<section>");
1206         print_escaped_xml(fh, cinfo->columns[i].col_title);
1207         fprintf(fh, "</section>\n");
1208     }
1209
1210     fprintf(fh, "</structure>\n\n");
1211 }
1212
1213 void
1214 write_psml_columns(epan_dissect_t *edt, FILE *fh)
1215 {
1216     gint i;
1217
1218     fprintf(fh, "<packet>\n");
1219
1220     for (i = 0; i < edt->pi.cinfo->num_cols; i++) {
1221         fprintf(fh, "<section>");
1222         print_escaped_xml(fh, edt->pi.cinfo->columns[i].col_data);
1223         fprintf(fh, "</section>\n");
1224     }
1225
1226     fprintf(fh, "</packet>\n\n");
1227 }
1228
1229 void
1230 write_psml_finale(FILE *fh)
1231 {
1232     fputs("</psml>\n", fh);
1233 }
1234
1235 static gchar *csv_massage_str(const gchar *source, const gchar *exceptions)
1236 {
1237     gchar *csv_str;
1238     gchar *tmp_str;
1239
1240     /* In general, our output for any field can contain Unicode characters,
1241        so g_strescape (which escapes any non-ASCII) is the wrong thing to do.
1242        Unfortunately glib doesn't appear to provide g_unicode_strescape()... */
1243     csv_str = g_strescape(source, exceptions);
1244     tmp_str = csv_str;
1245     /* Locate the UTF-8 right arrow character and replace it by an ASCII equivalent */
1246     while ( (tmp_str = strstr(tmp_str, UTF8_RIGHTWARDS_ARROW)) != NULL ) {
1247         tmp_str[0] = ' ';
1248         tmp_str[1] = '>';
1249         tmp_str[2] = ' ';
1250     }
1251     tmp_str = csv_str;
1252     while ( (tmp_str = strstr(tmp_str, "\\\"")) != NULL )
1253         *tmp_str = '\"';
1254     return csv_str;
1255 }
1256
1257 static void csv_write_str(const char *str, char sep, FILE *fh)
1258 {
1259     gchar *csv_str;
1260
1261     /* Do not escape the UTF-8 right arrow character */
1262     csv_str = csv_massage_str(str, UTF8_RIGHTWARDS_ARROW);
1263     fprintf(fh, "\"%s\"%c", csv_str, sep);
1264     g_free(csv_str);
1265 }
1266
1267 void
1268 write_csv_column_titles(column_info *cinfo, FILE *fh)
1269 {
1270     gint i;
1271
1272     for (i = 0; i < cinfo->num_cols - 1; i++)
1273         csv_write_str(cinfo->columns[i].col_title, ',', fh);
1274     csv_write_str(cinfo->columns[i].col_title, '\n', fh);
1275 }
1276
1277 void
1278 write_csv_columns(epan_dissect_t *edt, FILE *fh)
1279 {
1280     gint i;
1281
1282     for (i = 0; i < edt->pi.cinfo->num_cols - 1; i++)
1283         csv_write_str(edt->pi.cinfo->columns[i].col_data, ',', fh);
1284     csv_write_str(edt->pi.cinfo->columns[i].col_data, '\n', fh);
1285 }
1286
1287 void
1288 write_carrays_hex_data(guint32 num, FILE *fh, epan_dissect_t *edt)
1289 {
1290     guint32       i = 0, src_num = 0;
1291     GSList       *src_le;
1292     tvbuff_t     *tvb;
1293     char         *name;
1294     const guchar *cp;
1295     guint         length;
1296     char          ascii[9];
1297     struct data_source *src;
1298
1299     for (src_le = edt->pi.data_src; src_le != NULL; src_le = src_le->next) {
1300         memset(ascii, 0, sizeof(ascii));
1301         src = (struct data_source *)src_le->data;
1302         tvb = get_data_source_tvb(src);
1303         length = tvb_captured_length(tvb);
1304         if (length == 0)
1305             continue;
1306
1307         cp = tvb_get_ptr(tvb, 0, length);
1308
1309         name = get_data_source_name(src);
1310         if (name) {
1311             fprintf(fh, "/* %s */\n", name);
1312             wmem_free(NULL, name);
1313         }
1314         if (src_num) {
1315             fprintf(fh, "static const unsigned char pkt%u_%u[%u] = {\n",
1316                     num, src_num, length);
1317         } else {
1318             fprintf(fh, "static const unsigned char pkt%u[%u] = {\n",
1319                     num, length);
1320         }
1321         src_num++;
1322
1323         for (i = 0; i < length; i++) {
1324             fprintf(fh, "0x%02x", *(cp + i));
1325             ascii[i % 8] = g_ascii_isprint(*(cp + i)) ? *(cp + i) : '.';
1326
1327             if (i == (length - 1)) {
1328                 guint rem;
1329                 rem = length % 8;
1330                 if (rem) {
1331                     guint j;
1332                     for ( j = 0; j < 8 - rem; j++ )
1333                         fprintf(fh, "      ");
1334                 }
1335                 fprintf(fh, "  /* %s */\n};\n\n", ascii);
1336                 break;
1337             }
1338
1339             if (!((i + 1) % 8)) {
1340                 fprintf(fh, ", /* %s */\n", ascii);
1341                 memset(ascii, 0, sizeof(ascii));
1342             }
1343             else {
1344                 fprintf(fh, ", ");
1345             }
1346         }
1347     }
1348 }
1349
1350 /*
1351  * Find the data source for a specified field, and return a pointer
1352  * to the data in it. Returns NULL if the data is out of bounds.
1353  */
1354 /* XXX: What am I missing ?
1355  *      Why bother searching for fi->ds_tvb for the matching tvb
1356  *       in the data_source list ?
1357  *      IOW: Why not just use fi->ds_tvb for the arg to tvb_get_ptr() ?
1358  */
1359
1360 static const guint8 *
1361 get_field_data(GSList *src_list, field_info *fi)
1362 {
1363     GSList   *src_le;
1364     tvbuff_t *src_tvb;
1365     gint      length, tvbuff_length;
1366     struct data_source *src;
1367
1368     for (src_le = src_list; src_le != NULL; src_le = src_le->next) {
1369         src = (struct data_source *)src_le->data;
1370         src_tvb = get_data_source_tvb(src);
1371         if (fi->ds_tvb == src_tvb) {
1372             /*
1373              * Found it.
1374              *
1375              * XXX - a field can have a length that runs past
1376              * the end of the tvbuff.  Ideally, that should
1377              * be fixed when adding an item to the protocol
1378              * tree, but checking the length when doing
1379              * that could be expensive.  Until we fix that,
1380              * we'll do the check here.
1381              */
1382             tvbuff_length = tvb_captured_length_remaining(src_tvb,
1383                                                  fi->start);
1384             if (tvbuff_length < 0) {
1385                 return NULL;
1386             }
1387             length = fi->length;
1388             if (length > tvbuff_length)
1389                 length = tvbuff_length;
1390             return tvb_get_ptr(src_tvb, fi->start, length);
1391         }
1392     }
1393     g_assert_not_reached();
1394     return NULL;  /* not found */
1395 }
1396
1397 /* Print a string, escaping out certain characters that need to
1398  * escaped out for XML. */
1399 static void
1400 print_escaped_xml(FILE *fh, const char *unescaped_string)
1401 {
1402     const char *p;
1403     char        temp_str[8];
1404
1405     if (fh == NULL || unescaped_string == NULL) {
1406         return;
1407     }
1408
1409     for (p = unescaped_string; *p != '\0'; p++) {
1410         switch (*p) {
1411         case '&':
1412             fputs("&amp;", fh);
1413             break;
1414         case '<':
1415             fputs("&lt;", fh);
1416             break;
1417         case '>':
1418             fputs("&gt;", fh);
1419             break;
1420         case '"':
1421             fputs("&quot;", fh);
1422             break;
1423         case '\'':
1424             fputs("&#x27;", fh);
1425             break;
1426         default:
1427             if (g_ascii_isprint(*p))
1428                 fputc(*p, fh);
1429             else {
1430                 g_snprintf(temp_str, sizeof(temp_str), "\\x%x", (guint8)*p);
1431                 fputs(temp_str, fh);
1432             }
1433         }
1434     }
1435 }
1436
1437 static void
1438 print_escaped_bare(FILE *fh, const char *unescaped_string, gboolean change_dot)
1439 {
1440     const char *p;
1441     char        temp_str[8];
1442
1443     if (fh == NULL || unescaped_string == NULL) {
1444         return;
1445     }
1446
1447     for (p = unescaped_string; *p != '\0'; p++) {
1448         switch (*p) {
1449         case '"':
1450             fputs("\\\"", fh);
1451             break;
1452         case '\\':
1453             fputs("\\\\", fh);
1454             break;
1455         case '/':
1456             fputs("\\/", fh);
1457             break;
1458         case '\b':
1459             fputs("\\b", fh);
1460             break;
1461         case '\f':
1462             fputs("\\f", fh);
1463             break;
1464         case '\n':
1465             fputs("\\n", fh);
1466             break;
1467         case '\r':
1468             fputs("\\r", fh);
1469             break;
1470         case '\t':
1471             fputs("\\t", fh);
1472             break;
1473         case '.':
1474             if (change_dot)
1475                 fputs("_", fh);
1476             else
1477                 fputs(".", fh);
1478             break;
1479         default:
1480             if (g_ascii_isprint(*p))
1481                 fputc(*p, fh);
1482             else {
1483                 g_snprintf(temp_str, sizeof(temp_str), "\\u00%02x", (guint8)*p);
1484                 fputs(temp_str, fh);
1485             }
1486         }
1487     }
1488 }
1489
1490 /* Print a string, escaping out certain characters that need to
1491  * escaped out for JSON. */
1492 static void
1493 print_escaped_json(FILE *fh, const char *unescaped_string)
1494 {
1495     print_escaped_bare(fh, unescaped_string, FALSE);
1496 }
1497
1498 /* Print a string, escaping out certain characters that need to
1499  * escaped out for Elasticsearch title. */
1500 static void
1501 print_escaped_ek(FILE *fh, const char *unescaped_string)
1502 {
1503     print_escaped_bare(fh, unescaped_string, TRUE);
1504 }
1505
1506 static void
1507 pdml_write_field_hex_value(write_pdml_data *pdata, field_info *fi)
1508 {
1509     int           i;
1510     const guint8 *pd;
1511
1512     if (!fi->ds_tvb)
1513         return;
1514
1515     if (fi->length > tvb_captured_length_remaining(fi->ds_tvb, fi->start)) {
1516         fprintf(pdata->fh, "field length invalid!");
1517         return;
1518     }
1519
1520     /* Find the data for this field. */
1521     pd = get_field_data(pdata->src_list, fi);
1522
1523     if (pd) {
1524         /* Print a simple hex dump */
1525         for (i = 0 ; i < fi->length; i++) {
1526             fprintf(pdata->fh, "%02x", pd[i]);
1527         }
1528     }
1529 }
1530
1531 static void
1532 json_write_field_hex_value(write_json_data *pdata, field_info *fi)
1533 {
1534     int           i;
1535     const guint8 *pd;
1536
1537     if (!fi->ds_tvb)
1538         return;
1539
1540     if (fi->length > tvb_captured_length_remaining(fi->ds_tvb, fi->start)) {
1541         fprintf(pdata->fh, "field length invalid!");
1542         return;
1543     }
1544
1545     /* Find the data for this field. */
1546     pd = get_field_data(pdata->src_list, fi);
1547
1548     if (pd) {
1549         /* Print a simple hex dump */
1550         for (i = 0 ; i < fi->length; i++) {
1551             fprintf(pdata->fh, "%02x", pd[i]);
1552         }
1553     }
1554 }
1555
1556 gboolean
1557 print_hex_data(print_stream_t *stream, epan_dissect_t *edt)
1558 {
1559     gboolean      multiple_sources;
1560     GSList       *src_le;
1561     tvbuff_t     *tvb;
1562     char         *line, *name;
1563     const guchar *cp;
1564     guint         length;
1565     struct data_source *src;
1566
1567     /*
1568      * Set "multiple_sources" iff this frame has more than one
1569      * data source; if it does, we need to print the name of
1570      * the data source before printing the data from the
1571      * data source.
1572      */
1573     multiple_sources = (edt->pi.data_src->next != NULL);
1574
1575     for (src_le = edt->pi.data_src; src_le != NULL;
1576          src_le = src_le->next) {
1577         src = (struct data_source *)src_le->data;
1578         tvb = get_data_source_tvb(src);
1579         if (multiple_sources) {
1580             name = get_data_source_name(src);
1581             line = g_strdup_printf("%s:", name);
1582             wmem_free(NULL, name);
1583             print_line(stream, 0, line);
1584             g_free(line);
1585         }
1586         length = tvb_captured_length(tvb);
1587         if (length == 0)
1588             return TRUE;
1589         cp = tvb_get_ptr(tvb, 0, length);
1590         if (!print_hex_data_buffer(stream, cp, length,
1591                                    (packet_char_enc)edt->pi.fd->flags.encoding))
1592             return FALSE;
1593     }
1594     return TRUE;
1595 }
1596
1597 /*
1598  * This routine is based on a routine created by Dan Lasley
1599  * <DLASLEY@PROMUS.com>.
1600  *
1601  * It was modified for Wireshark by Gilbert Ramirez and others.
1602  */
1603
1604 #define MAX_OFFSET_LEN   8       /* max length of hex offset of bytes */
1605 #define BYTES_PER_LINE  16      /* max byte values printed on a line */
1606 #define HEX_DUMP_LEN    (BYTES_PER_LINE*3)
1607                                 /* max number of characters hex dump takes -
1608                                    2 digits plus trailing blank */
1609 #define DATA_DUMP_LEN   (HEX_DUMP_LEN + 2 + BYTES_PER_LINE)
1610                                 /* number of characters those bytes take;
1611                                    3 characters per byte of hex dump,
1612                                    2 blanks separating hex from ASCII,
1613                                    1 character per byte of ASCII dump */
1614 #define MAX_LINE_LEN    (MAX_OFFSET_LEN + 2 + DATA_DUMP_LEN)
1615                                 /* number of characters per line;
1616                                    offset, 2 blanks separating offset
1617                                    from data dump, data dump */
1618
1619 static gboolean
1620 print_hex_data_buffer(print_stream_t *stream, const guchar *cp,
1621                       guint length, packet_char_enc encoding)
1622 {
1623     register unsigned int ad, i, j, k, l;
1624     guchar                c;
1625     gchar                 line[MAX_LINE_LEN + 1];
1626     unsigned int          use_digits;
1627
1628     static gchar binhex[16] = {
1629         '0', '1', '2', '3', '4', '5', '6', '7',
1630         '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
1631
1632     /*
1633      * How many of the leading digits of the offset will we supply?
1634      * We always supply at least 4 digits, but if the maximum offset
1635      * won't fit in 4 digits, we use as many digits as will be needed.
1636      */
1637     if (((length - 1) & 0xF0000000) != 0)
1638         use_digits = 8; /* need all 8 digits */
1639     else if (((length - 1) & 0x0F000000) != 0)
1640         use_digits = 7; /* need 7 digits */
1641     else if (((length - 1) & 0x00F00000) != 0)
1642         use_digits = 6; /* need 6 digits */
1643     else if (((length - 1) & 0x000F0000) != 0)
1644         use_digits = 5; /* need 5 digits */
1645     else
1646         use_digits = 4; /* we'll supply 4 digits */
1647
1648     ad = 0;
1649     i = 0;
1650     j = 0;
1651     k = 0;
1652     while (i < length) {
1653         if ((i & 15) == 0) {
1654             /*
1655              * Start of a new line.
1656              */
1657             j = 0;
1658             l = use_digits;
1659             do {
1660                 l--;
1661                 c = (ad >> (l*4)) & 0xF;
1662                 line[j++] = binhex[c];
1663             } while (l != 0);
1664             line[j++] = ' ';
1665             line[j++] = ' ';
1666             memset(line+j, ' ', DATA_DUMP_LEN);
1667
1668             /*
1669              * Offset in line of ASCII dump.
1670              */
1671             k = j + HEX_DUMP_LEN + 2;
1672         }
1673         c = *cp++;
1674         line[j++] = binhex[c>>4];
1675         line[j++] = binhex[c&0xf];
1676         j++;
1677         if (encoding == PACKET_CHAR_ENC_CHAR_EBCDIC) {
1678             c = EBCDIC_to_ASCII1(c);
1679         }
1680         line[k++] = ((c >= ' ') && (c < 0x7f)) ? c : '.';
1681         i++;
1682         if (((i & 15) == 0) || (i == length)) {
1683             /*
1684              * We'll be starting a new line, or
1685              * we're finished printing this buffer;
1686              * dump out the line we've constructed,
1687              * and advance the offset.
1688              */
1689             line[k] = '\0';
1690             if (!print_line(stream, 0, line))
1691                 return FALSE;
1692             ad += 16;
1693         }
1694     }
1695     return TRUE;
1696 }
1697
1698 gsize output_fields_num_fields(output_fields_t* fields)
1699 {
1700     g_assert(fields);
1701
1702     if (NULL == fields->fields) {
1703         return 0;
1704     } else {
1705         return fields->fields->len;
1706     }
1707 }
1708
1709 void output_fields_free(output_fields_t* fields)
1710 {
1711     g_assert(fields);
1712
1713     if (NULL != fields->fields) {
1714         gsize i;
1715
1716         if (NULL != fields->field_indicies) {
1717             /* Keys are stored in fields->fields, values are
1718              * integers.
1719              */
1720             g_hash_table_destroy(fields->field_indicies);
1721         }
1722
1723         if (NULL != fields->field_values) {
1724             g_free(fields->field_values);
1725         }
1726
1727         for(i = 0; i < fields->fields->len; ++i) {
1728             gchar* field = (gchar *)g_ptr_array_index(fields->fields,i);
1729             g_free(field);
1730         }
1731         g_ptr_array_free(fields->fields, TRUE);
1732     }
1733
1734     g_free(fields);
1735 }
1736
1737 #define COLUMN_FIELD_FILTER  "_ws.col."
1738
1739 void output_fields_add(output_fields_t *fields, const gchar *field)
1740 {
1741     gchar *field_copy;
1742
1743     g_assert(fields);
1744     g_assert(field);
1745
1746
1747     if (NULL == fields->fields) {
1748         fields->fields = g_ptr_array_new();
1749     }
1750
1751     field_copy = g_strdup(field);
1752
1753     g_ptr_array_add(fields->fields, field_copy);
1754
1755     /* See if we have a column as a field entry */
1756     if (!strncmp(field, COLUMN_FIELD_FILTER, strlen(COLUMN_FIELD_FILTER)))
1757         fields->includes_col_fields = TRUE;
1758
1759 }
1760
1761 static void
1762 output_field_check(void *data, void *user_data)
1763 {
1764     gchar *field = (gchar *)data;
1765     GSList **invalid_fields = (GSList **)user_data;
1766
1767     if (!strncmp(field, COLUMN_FIELD_FILTER, strlen(COLUMN_FIELD_FILTER)))
1768         return;
1769
1770     if (!proto_registrar_get_byname(field)) {
1771         *invalid_fields = g_slist_prepend(*invalid_fields, field);
1772     }
1773
1774 }
1775
1776 GSList *
1777 output_fields_valid(output_fields_t *fields)
1778 {
1779     GSList *invalid_fields = NULL;
1780     if (fields->fields == NULL) {
1781         return NULL;
1782     }
1783
1784     g_ptr_array_foreach(fields->fields, output_field_check, &invalid_fields);
1785
1786     return invalid_fields;
1787 }
1788
1789 gboolean output_fields_set_option(output_fields_t *info, gchar *option)
1790 {
1791     const gchar *option_name;
1792     const gchar *option_value;
1793
1794     g_assert(info);
1795     g_assert(option);
1796
1797     if ('\0' == *option) {
1798         return FALSE; /* this happens if we're called from tshark -E '' */
1799     }
1800     option_name = strtok(option, "=");
1801     if (!option_name) {
1802         return FALSE;
1803     }
1804     option_value = option + strlen(option_name) + 1;
1805     if (*option_value == '\0') {
1806         return FALSE;
1807     }
1808
1809     if (0 == strcmp(option_name, "header")) {
1810         switch (*option_value) {
1811         case 'n':
1812             info->print_header = FALSE;
1813             break;
1814         case 'y':
1815             info->print_header = TRUE;
1816             break;
1817         default:
1818             return FALSE;
1819         }
1820         return TRUE;
1821     }
1822     else if (0 == strcmp(option_name, "separator")) {
1823         switch (*option_value) {
1824         case '/':
1825             switch (*++option_value) {
1826             case 't':
1827                 info->separator = '\t';
1828                 break;
1829             case 's':
1830                 info->separator = ' ';
1831                 break;
1832             default:
1833                 info->separator = '\\';
1834             }
1835             break;
1836         default:
1837             info->separator = *option_value;
1838             break;
1839         }
1840         return TRUE;
1841     }
1842     else if (0 == strcmp(option_name, "occurrence")) {
1843         switch (*option_value) {
1844         case 'f':
1845         case 'l':
1846         case 'a':
1847             info->occurrence = *option_value;
1848             break;
1849         default:
1850             return FALSE;
1851         }
1852         return TRUE;
1853     }
1854     else if (0 == strcmp(option_name, "aggregator")) {
1855         switch (*option_value) {
1856         case '/':
1857             switch (*++option_value) {
1858             case 's':
1859                 info->aggregator = ' ';
1860                 break;
1861             default:
1862                 info->aggregator = '\\';
1863             }
1864             break;
1865         default:
1866             info->aggregator = *option_value;
1867             break;
1868         }
1869         return TRUE;
1870     }
1871     else if (0 == strcmp(option_name, "quote")) {
1872         switch (*option_value) {
1873         case 'd':
1874             info->quote = '"';
1875             break;
1876         case 's':
1877             info->quote = '\'';
1878             break;
1879         case 'n':
1880             info->quote = '\0';
1881             break;
1882         default:
1883             info->quote = '\0';
1884             return FALSE;
1885         }
1886         return TRUE;
1887     }
1888     else if (0 == strcmp(option_name, "bom")) {
1889         switch (*option_value) {
1890         case 'n':
1891             info->print_bom = FALSE;
1892             break;
1893         case 'y':
1894             info->print_bom = TRUE;
1895             break;
1896         default:
1897             return FALSE;
1898         }
1899         return TRUE;
1900     }
1901
1902     return FALSE;
1903 }
1904
1905 void output_fields_list_options(FILE *fh)
1906 {
1907     fprintf(fh, "TShark: The available options for field output \"E\" are:\n");
1908     fputs("bom=y|n    Prepend output with the UTF-8 BOM (def: N: no)\n", fh);
1909     fputs("header=y|n    Print field abbreviations as first line of output (def: N: no)\n", fh);
1910     fputs("separator=/t|/s|<character>   Set the separator to use;\n     \"/t\" = tab, \"/s\" = space (def: /t: tab)\n", fh);
1911     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);
1912     fputs("aggregator=,|/s|<character>   Set the aggregator to use;\n     \",\" = comma, \"/s\" = space (def: ,: comma)\n", fh);
1913     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);
1914 }
1915
1916 gboolean output_fields_has_cols(output_fields_t* fields)
1917 {
1918     g_assert(fields);
1919     return fields->includes_col_fields;
1920 }
1921
1922 void write_fields_preamble(output_fields_t* fields, FILE *fh)
1923 {
1924     gsize i;
1925
1926     g_assert(fields);
1927     g_assert(fh);
1928     g_assert(fields->fields);
1929
1930     if (fields->print_bom) {
1931         fputs(UTF8_BOM, fh);
1932     }
1933
1934
1935     if (!fields->print_header) {
1936         return;
1937     }
1938
1939     for(i = 0; i < fields->fields->len; ++i) {
1940         const gchar* field = (const gchar *)g_ptr_array_index(fields->fields,i);
1941         if (i != 0 ) {
1942             fputc(fields->separator, fh);
1943         }
1944         fputs(field, fh);
1945     }
1946     fputc('\n', fh);
1947 }
1948
1949 static void format_field_values(output_fields_t* fields, gpointer field_index, const gchar* value)
1950 {
1951     guint      indx;
1952     GPtrArray* fv_p;
1953
1954     if (NULL == value)
1955         return;
1956
1957     /* Unwrap change made to disambiguiate zero / null */
1958     indx = GPOINTER_TO_UINT(field_index) - 1;
1959
1960     if (fields->field_values[indx] == NULL) {
1961         fields->field_values[indx] = g_ptr_array_new();
1962     }
1963
1964     /* Essentially: fieldvalues[indx] is a 'GPtrArray *' with each array entry */
1965     /*  pointing to a string which is (part of) the final output string.       */
1966
1967     fv_p = fields->field_values[indx];
1968
1969     switch (fields->occurrence) {
1970     case 'f':
1971         /* print the value of only the first occurrence of the field */
1972         if (g_ptr_array_len(fv_p) != 0)
1973             return;
1974         break;
1975     case 'l':
1976         /* print the value of only the last occurrence of the field */
1977         g_ptr_array_set_size(fv_p, 0);
1978         break;
1979     case 'a':
1980         /* print the value of all accurrences of the field */
1981         /* If not the first, add the 'aggregator' */
1982         if (g_ptr_array_len(fv_p) > 0) {
1983             g_ptr_array_add(fv_p, (gpointer)g_strdup_printf("%c", fields->aggregator));
1984         }
1985         break;
1986     default:
1987         g_assert_not_reached();
1988         break;
1989     }
1990
1991     g_ptr_array_add(fv_p, (gpointer)value);
1992 }
1993
1994 static void proto_tree_get_node_field_values(proto_node *node, gpointer data)
1995 {
1996     write_field_data_t *call_data;
1997     field_info *fi;
1998     gpointer    field_index;
1999
2000     call_data = (write_field_data_t *)data;
2001     fi = PNODE_FINFO(node);
2002
2003     /* dissection with an invisible proto tree? */
2004     g_assert(fi);
2005
2006     field_index = g_hash_table_lookup(call_data->fields->field_indicies, fi->hfinfo->abbrev);
2007     if (NULL != field_index) {
2008         format_field_values(call_data->fields, field_index,
2009                             get_node_field_value(fi, call_data->edt) /* g_ alloc'd string */
2010             );
2011     }
2012
2013     /* Recurse here. */
2014     if (node->first_child != NULL) {
2015         proto_tree_children_foreach(node, proto_tree_get_node_field_values,
2016                                     call_data);
2017     }
2018 }
2019
2020 static void write_specified_fields(fields_format format, output_fields_t *fields, epan_dissect_t *edt, column_info *cinfo, FILE *fh)
2021 {
2022     gsize     i;
2023     gboolean first = TRUE;
2024     gint      col;
2025     gchar    *col_name;
2026     gpointer  field_index;
2027
2028     write_field_data_t data;
2029
2030     g_assert(fields);
2031     g_assert(fields->fields);
2032     g_assert(edt);
2033     g_assert(fh);
2034
2035     data.fields = fields;
2036     data.edt = edt;
2037
2038     if (NULL == fields->field_indicies) {
2039         /* Prepare a lookup table from string abbreviation for field to its index. */
2040         fields->field_indicies = g_hash_table_new(g_str_hash, g_str_equal);
2041
2042         i = 0;
2043         while (i < fields->fields->len) {
2044             gchar *field = (gchar *)g_ptr_array_index(fields->fields, i);
2045             /* Store field indicies +1 so that zero is not a valid value,
2046              * and can be distinguished from NULL as a pointer.
2047              */
2048             ++i;
2049             g_hash_table_insert(fields->field_indicies, field, GUINT_TO_POINTER(i));
2050         }
2051     }
2052
2053     /* Array buffer to store values for this packet              */
2054     /*  Allocate an array for the 'GPtrarray *' the first time   */
2055     /*   ths function is invoked for a file;                     */
2056     /*  Any and all 'GPtrArray *' are freed (after use) each     */
2057     /*   time (each packet) this function is invoked for a flle. */
2058     /* XXX: ToDo: use packet-scope'd memory & (if/when implemented) wmem ptr_array */
2059     if (NULL == fields->field_values)
2060         fields->field_values = g_new0(GPtrArray*, fields->fields->len);  /* free'd in output_fields_free() */
2061
2062     proto_tree_children_foreach(edt->tree, proto_tree_get_node_field_values,
2063                                 &data);
2064
2065     switch (format) {
2066     case FORMAT_CSV:
2067         if (fields->includes_col_fields) {
2068             for (col = 0; col < cinfo->num_cols; col++) {
2069                 /* Prepend COLUMN_FIELD_FILTER as the field name */
2070                 col_name = g_strdup_printf("%s%s", COLUMN_FIELD_FILTER, cinfo->columns[col].col_title);
2071                 field_index = g_hash_table_lookup(fields->field_indicies, col_name);
2072                 g_free(col_name);
2073
2074                 if (NULL != field_index) {
2075                     format_field_values(fields, field_index, g_strdup(cinfo->columns[col].col_data));
2076                 }
2077             }
2078         }
2079
2080         for(i = 0; i < fields->fields->len; ++i) {
2081             if (0 != i) {
2082                 fputc(fields->separator, fh);
2083             }
2084             if (NULL != fields->field_values[i]) {
2085                 GPtrArray *fv_p;
2086                 gchar * str;
2087                 gsize j;
2088                 fv_p = fields->field_values[i];
2089                 if (fields->quote != '\0') {
2090                     fputc(fields->quote, fh);
2091                 }
2092
2093                 /* Output the array of (partial) field values */
2094                 for (j = 0; j < g_ptr_array_len(fv_p); j++ ) {
2095                     str = (gchar *)g_ptr_array_index(fv_p, j);
2096                     fputs(str, fh);
2097                     g_free(str);
2098                 }
2099                 if (fields->quote != '\0') {
2100                     fputc(fields->quote, fh);
2101                 }
2102                 g_ptr_array_free(fv_p, TRUE);  /* get ready for the next packet */
2103                 fields->field_values[i] = NULL;
2104             }
2105         }
2106         break;
2107     case FORMAT_XML:
2108         for(i = 0; i < fields->fields->len; ++i) {
2109             gchar *field = (gchar *)g_ptr_array_index(fields->fields, i);
2110
2111             if (NULL != fields->field_values[i]) {
2112                 GPtrArray *fv_p;
2113                 gchar * str;
2114                 gsize j;
2115                 fv_p = fields->field_values[i];
2116
2117                 /* Output the array of (partial) field values */
2118                 for (j = 0; j < (g_ptr_array_len(fv_p)); j+=2 ) {
2119                     str = (gchar *)g_ptr_array_index(fv_p, j);
2120
2121                     fprintf(fh, "  <field name=\"%s\" value=", field);
2122                     fputs("\"", fh);
2123                     print_escaped_xml(fh, str);
2124                     fputs("\"/>\n", fh);
2125                     g_free(str);
2126                 }
2127                 g_ptr_array_free(fv_p, TRUE);  /* get ready for the next packet */
2128                 fields->field_values[i] = NULL;
2129             }
2130         }
2131         break;
2132     case FORMAT_JSON:
2133         for(i = 0; i < fields->fields->len; ++i) {
2134             gchar *field = (gchar *)g_ptr_array_index(fields->fields, i);
2135
2136             if (NULL != fields->field_values[i]) {
2137                 GPtrArray *fv_p;
2138                 gchar * str;
2139                 gsize j;
2140                 fv_p = fields->field_values[i];
2141
2142                 /* Output the array of (partial) field values */
2143                 for (j = 0; j < (g_ptr_array_len(fv_p)); j += 2) {
2144                     str = (gchar *)g_ptr_array_index(fv_p, j);
2145
2146                     if (j == 0) {
2147                         if (!first) {
2148                             fputs(",\n", fh);
2149                         }
2150                         fprintf(fh, "        \"%s\": [", field);
2151                     }
2152                     fputs("\"", fh);
2153                     print_escaped_json(fh, str);
2154                     fputs("\"", fh);
2155                     g_free(str);
2156
2157                     if (j + 2 < (g_ptr_array_len(fv_p))) {
2158                         fputs(",", fh);
2159                     }
2160                     else {
2161                         fputs("]", fh);
2162
2163                         }
2164                     }
2165
2166                 first = FALSE;
2167                 g_ptr_array_free(fv_p, TRUE);  /* get ready for the next packet */
2168                 fields->field_values[i] = NULL;
2169             }
2170         }
2171         fputc('\n',fh);
2172         break;
2173     case FORMAT_EK:
2174         for(i = 0; i < fields->fields->len; ++i) {
2175             gchar *field = (gchar *)g_ptr_array_index(fields->fields, i);
2176
2177             if (NULL != fields->field_values[i]) {
2178                 GPtrArray *fv_p;
2179                 gchar * str;
2180                 gsize j;
2181                 fv_p = fields->field_values[i];
2182
2183                 /* Output the array of (partial) field values */
2184                 for (j = 0; j < (g_ptr_array_len(fv_p)); j += 2) {
2185                     str = (gchar *)g_ptr_array_index(fv_p, j);
2186
2187                     if (j == 0) {
2188                         if (!first) {
2189                             fputs(",", fh);
2190                         }
2191                         fputs("\"", fh);
2192                         print_escaped_ek(fh, field);
2193                         fputs("\": [", fh);
2194                     }
2195                     fputs("\"", fh);
2196                     print_escaped_json(fh, str);
2197                     fputs("\"", fh);
2198                     g_free(str);
2199
2200                     if (j + 2 < (g_ptr_array_len(fv_p))) {
2201                         fputs(",", fh);
2202                     }
2203                     else {
2204                         fputs("]", fh);
2205
2206                         }
2207                     }
2208
2209                 first = FALSE;
2210                 g_ptr_array_free(fv_p, TRUE);  /* get ready for the next packet */
2211                 fields->field_values[i] = NULL;
2212             }
2213         }
2214         break;
2215
2216     default:
2217         fprintf(stderr, "Unknown fields format %d\n", format);
2218         g_assert_not_reached();
2219         break;
2220     }
2221 }
2222
2223 void write_fields_finale(output_fields_t* fields _U_ , FILE *fh _U_)
2224 {
2225     /* Nothing to do */
2226 }
2227
2228 /* Returns an g_malloced string */
2229 gchar* get_node_field_value(field_info* fi, epan_dissect_t* edt)
2230 {
2231     if (fi->hfinfo->id == hf_text_only) {
2232         /* Text label.
2233          * Get the text */
2234         if (fi->rep) {
2235             return g_strdup(fi->rep->representation);
2236         }
2237         else {
2238             return get_field_hex_value(edt->pi.data_src, fi);
2239         }
2240     }
2241     else if (fi->hfinfo->id == proto_data) {
2242         /* Uninterpreted data, i.e., the "Data" protocol, is
2243          * printed as a field instead of a protocol. */
2244         return get_field_hex_value(edt->pi.data_src, fi);
2245     }
2246     else {
2247         /* Normal protocols and fields */
2248         gchar      *dfilter_string;
2249
2250         switch (fi->hfinfo->type)
2251         {
2252         case FT_PROTOCOL:
2253             /* Print out the full details for the protocol. */
2254             if (fi->rep) {
2255                 return g_strdup(fi->rep->representation);
2256             } else {
2257                 /* Just print out the protocol abbreviation */
2258                 return g_strdup(fi->hfinfo->abbrev);
2259             }
2260         case FT_NONE:
2261             /* Return "1" so that the presence of a field of type
2262              * FT_NONE can be checked when using -T fields */
2263             return g_strdup("1");
2264         default:
2265             dfilter_string = fvalue_to_string_repr(NULL, &fi->value, FTREPR_DISPLAY, fi->hfinfo->display);
2266             if (dfilter_string != NULL) {
2267                 gchar* ret = g_strdup(dfilter_string);
2268                 wmem_free(NULL, dfilter_string);
2269                 return ret;
2270             } else {
2271                 return get_field_hex_value(edt->pi.data_src, fi);
2272             }
2273         }
2274     }
2275 }
2276
2277 static gchar*
2278 get_field_hex_value(GSList *src_list, field_info *fi)
2279 {
2280     const guint8 *pd;
2281
2282     if (!fi->ds_tvb)
2283         return NULL;
2284
2285     if (fi->length > tvb_captured_length_remaining(fi->ds_tvb, fi->start)) {
2286         return g_strdup("field length invalid!");
2287     }
2288
2289     /* Find the data for this field. */
2290     pd = get_field_data(src_list, fi);
2291
2292     if (pd) {
2293         int        i;
2294         gchar     *buffer;
2295         gchar     *p;
2296         int        len;
2297         const int  chars_per_byte = 2;
2298
2299         len    = chars_per_byte * fi->length;
2300         buffer = (gchar *)g_malloc(sizeof(gchar)*(len + 1));
2301         buffer[len] = '\0'; /* Ensure NULL termination in bad cases */
2302         p = buffer;
2303         /* Print a simple hex dump */
2304         for (i = 0 ; i < fi->length; i++) {
2305             g_snprintf(p, chars_per_byte+1, "%02x", pd[i]);
2306             p += chars_per_byte;
2307         }
2308         return buffer;
2309     } else {
2310         return NULL;
2311     }
2312 }
2313
2314 output_fields_t* output_fields_new(void)
2315 {
2316     output_fields_t* fields     = g_new(output_fields_t, 1);
2317     fields->print_bom           = FALSE;
2318     fields->print_header        = FALSE;
2319     fields->separator           = '\t';
2320     fields->occurrence          = 'a';
2321     fields->aggregator          = ',';
2322     fields->fields              = NULL; /*Do lazy initialisation */
2323     fields->field_indicies      = NULL;
2324     fields->field_values        = NULL;
2325     fields->quote               ='\0';
2326     fields->includes_col_fields = FALSE;
2327     return fields;
2328 }
2329
2330 /*
2331  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
2332  *
2333  * Local variables:
2334  * c-basic-offset: 4
2335  * tab-width: 8
2336  * indent-tabs-mode: nil
2337  * End:
2338  *
2339  * vi: set shiftwidth=4 tabstop=8 expandtab:
2340  * :indentSize=4:tabSize=8:noTabs=true:
2341  */