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