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