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