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