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