X-Git-Url: http://git.samba.org/samba.git/?p=obnox%2Fwireshark%2Fwip.git;a=blobdiff_plain;f=print.c;h=aedcb2f88e1d1ed4d44b6f7f4abc46a9c43894cc;hp=d9178a842d6a3f5c88ace5079a62edcbba73515d;hb=0d73ad9c881b0c790a217b68a1fe63fb3c3b797d;hpb=a89df87cad96d23a76fd10b039a8d5af6aa845ad diff --git a/print.c b/print.c index d9178a842d..aedcb2f88e 100644 --- a/print.c +++ b/print.c @@ -56,7 +56,7 @@ typedef struct { GSList *src_list; print_dissections_e print_dissections; gboolean print_hex_for_data; - char_enc encoding; + packet_char_enc encoding; epan_dissect_t *edt; } print_data; @@ -75,20 +75,23 @@ typedef struct { struct _output_fields { gboolean print_header; gchar separator; + gchar occurrence; + gchar aggregator; GPtrArray* fields; GHashTable* field_indicies; - const gchar** field_values; + emem_strbuf_t** field_values; gchar quote; }; +static gboolean write_headers = FALSE; + static const gchar* get_field_hex_value(GSList* src_list, field_info *fi); -const gchar* get_node_field_value(field_info* fi, epan_dissect_t* edt); static void proto_tree_print_node(proto_node *node, gpointer data); static void proto_tree_write_node_pdml(proto_node *node, gpointer data); static const guint8 *get_field_data(GSList *src_list, field_info *fi); static void write_pdml_field_hex_value(write_pdml_data *pdata, field_info *fi); static gboolean print_hex_data_buffer(print_stream_t *stream, const guchar *cp, - guint length, char_enc encoding); + guint length, packet_char_enc encoding); static void ps_clean_string(unsigned char *out, const unsigned char *in, int outbuf_size); static void print_escaped_xml(FILE *fh, const char *unescaped_string); @@ -151,12 +154,14 @@ proto_tree_print(print_args_t *print_args, epan_dissect_t *edt, static void proto_tree_print_node(proto_node *node, gpointer data) { - field_info *fi = PITEM_FINFO(node); + field_info *fi = PNODE_FINFO(node); print_data *pdata = (print_data*) data; const guint8 *pd; gchar label_str[ITEM_LABEL_LENGTH]; gchar *label_ptr; + g_assert(fi && "dissection with an invisible proto tree?"); + /* Don't print invisible entries. */ if (PROTO_ITEM_IS_HIDDEN(node)) return; @@ -255,17 +260,20 @@ proto_tree_write_pdml(epan_dissect_t *edt, FILE *fh) static void proto_tree_write_node_pdml(proto_node *node, gpointer data) { - field_info *fi = PITEM_FINFO(node); + field_info *fi = PNODE_FINFO(node); write_pdml_data *pdata = (write_pdml_data*) data; const gchar *label_ptr; gchar label_str[ITEM_LABEL_LENGTH]; char *dfilter_string; size_t chop_len; int i; + gboolean wrap_in_fake_protocol; + + g_assert(fi && "dissection with an invisible proto tree?"); /* Will wrap up top-level field items inside a fake protocol wrapper to preserve the PDML schema */ - gboolean wrap_in_fake_protocol = + wrap_in_fake_protocol = (((fi->hfinfo->type != FT_PROTOCOL) || (fi->hfinfo->id == proto_data)) && (pdata->level == 0)); @@ -336,7 +344,7 @@ proto_tree_write_node_pdml(proto_node *node, gpointer data) #if 0 /* PDML spec, see: - * http://analyzer.polito.it/30alpha/docs/dissectors/PDMLSpec.htm + * http://www.nbee.org/doku.php?id=netpdl:pdml_specification * * the show fields contains things in 'human readable' format * showname: contains only the name of the field @@ -484,8 +492,8 @@ print_pdml_geninfo(proto_tree *tree, FILE *fh) if (g_ptr_array_len(finfo_array) < 1) { return; } - frame_finfo = finfo_array->pdata[0]; - g_ptr_array_free(finfo_array, FALSE); + frame_finfo = (field_info *)finfo_array->pdata[0]; + g_ptr_array_free(finfo_array, TRUE); /* frame.number --> geninfo.num */ finfo_array = proto_find_finfo(tree, hf_frame_number); @@ -493,7 +501,7 @@ print_pdml_geninfo(proto_tree *tree, FILE *fh) return; } num = fvalue_get_uinteger(&((field_info*)finfo_array->pdata[0])->value); - g_ptr_array_free(finfo_array, FALSE); + g_ptr_array_free(finfo_array, TRUE); /* frame.frame_len --> geninfo.len */ finfo_array = proto_find_finfo(tree, hf_frame_len); @@ -501,7 +509,7 @@ print_pdml_geninfo(proto_tree *tree, FILE *fh) return; } len = fvalue_get_uinteger(&((field_info*)finfo_array->pdata[0])->value); - g_ptr_array_free(finfo_array, FALSE); + g_ptr_array_free(finfo_array, TRUE); /* frame.cap_len --> geninfo.caplen */ finfo_array = proto_find_finfo(tree, hf_frame_capture_len); @@ -509,15 +517,15 @@ print_pdml_geninfo(proto_tree *tree, FILE *fh) return; } caplen = fvalue_get_uinteger(&((field_info*)finfo_array->pdata[0])->value); - g_ptr_array_free(finfo_array, FALSE); + g_ptr_array_free(finfo_array, TRUE); /* frame.time --> geninfo.timestamp */ finfo_array = proto_find_finfo(tree, hf_frame_arrival_time); if (g_ptr_array_len(finfo_array) < 1) { return; } - timestamp = fvalue_get(&((field_info*)finfo_array->pdata[0])->value); - g_ptr_array_free(finfo_array, FALSE); + timestamp = (nstime_t *)fvalue_get(&((field_info*)finfo_array->pdata[0])->value); + g_ptr_array_free(finfo_array, TRUE); /* Print geninfo start */ fprintf(fh, @@ -542,7 +550,7 @@ print_pdml_geninfo(proto_tree *tree, FILE *fh) /* Print geninfo.timestamp */ fprintf(fh, " \n", - abs_time_to_str(timestamp), (int) timestamp->secs, timestamp->nsecs, frame_finfo->length); + abs_time_to_str(timestamp, ABSOLUTE_TIME_LOCAL, TRUE), (int) timestamp->secs, timestamp->nsecs, frame_finfo->length); /* Print geninfo end */ fprintf(fh, @@ -561,6 +569,7 @@ write_psml_preamble(FILE *fh) fputs("\n", fh); fputs("\n", PACKAGE, VERSION); + write_headers = TRUE; } void @@ -569,7 +578,7 @@ proto_tree_write_psml(epan_dissect_t *edt, FILE *fh) gint i; /* if this is the first packet, we have to create the PSML structure output */ - if(edt->pi.fd->num == 1) { + if(write_headers) { fprintf(fh, "\n"); for(i=0; i < edt->pi.cinfo->num_cols; i++) { @@ -579,6 +588,8 @@ proto_tree_write_psml(epan_dissect_t *edt, FILE *fh) } fprintf(fh, "\n\n"); + + write_headers = FALSE; } fprintf(fh, "\n"); @@ -601,26 +612,46 @@ write_psml_finale(FILE *fh) void write_csv_preamble(FILE *fh _U_) { + write_headers = TRUE; +} +static gchar *csv_massage_str(const gchar *source, const gchar *exceptions) +{ + gchar *csv_str; + gchar *tmp_str; + + csv_str = g_strescape(source, exceptions); + tmp_str = csv_str; + while ( (tmp_str = strstr(tmp_str, "\\\"")) != NULL ) + *tmp_str = '\"'; + return csv_str; } -void -proto_tree_write_csv(epan_dissect_t *edt, FILE *fh) +static void csv_write_str(const char *str, char sep, FILE *fh) { - gint i; + gchar *csv_str; - /* if this is the first packet, we have to write the CSV header */ - if(edt->pi.fd->num == 1) { - for(i=0; i < edt->pi.cinfo->num_cols - 1; i++) - fprintf(fh, "\"%s\",", edt->pi.cinfo->col_title[i]); + csv_str = csv_massage_str(str, NULL); + fprintf(fh, "\"%s\"%c", csv_str, sep); + g_free(csv_str); +} - fprintf(fh, "\"%s\"\n", edt->pi.cinfo->col_title[i]); - } +void +proto_tree_write_csv(epan_dissect_t *edt, FILE *fh) +{ + gint i; + /* if this is the first packet, we have to write the CSV header */ + if(write_headers) { for(i=0; i < edt->pi.cinfo->num_cols - 1; i++) - fprintf(fh, "\"%s\",", edt->pi.cinfo->col_data[i]); + csv_write_str(edt->pi.cinfo->col_title[i], ',', fh); + csv_write_str(edt->pi.cinfo->col_title[i], '\n', fh); + write_headers = FALSE; + } - fprintf(fh, "\"%s\"\n", edt->pi.cinfo->col_data[i]); + for(i=0; i < edt->pi.cinfo->num_cols - 1; i++) + csv_write_str(edt->pi.cinfo->col_data[i], ',', fh); + csv_write_str(edt->pi.cinfo->col_data[i], '\n', fh); } void @@ -681,7 +712,7 @@ get_field_data(GSList *src_list, field_info *fi) gint length, tvbuff_length; for (src_le = src_list; src_le != NULL; src_le = src_le->next) { - src = src_le->data; + src = (data_source *)src_le->data; src_tvb = src->tvb; if (fi->ds_tvb == src_tvb) { /* @@ -715,6 +746,7 @@ static void print_escaped_xml(FILE *fh, const char *unescaped_string) { const char *p; + char temp_str[8]; for (p = unescaped_string; *p != '\0'; p++) { switch (*p) { @@ -734,7 +766,12 @@ print_escaped_xml(FILE *fh, const char *unescaped_string) fputs("'", fh); break; default: - fputc(*p, fh); + if (g_ascii_isprint(*p)) + fputc(*p, fh); + else { + g_snprintf(temp_str, sizeof(temp_str), "\\x%x", (guint8)*p); + fputs(temp_str, fh); + } } } } @@ -786,7 +823,7 @@ print_hex_data(print_stream_t *stream, epan_dissect_t *edt) for (src_le = edt->pi.data_src; src_le != NULL; src_le = src_le->next) { - src = src_le->data; + src = (data_source *)src_le->data; tvb = src->tvb; if (multiple_sources) { name = get_data_source_name(src); @@ -830,7 +867,7 @@ print_hex_data(print_stream_t *stream, epan_dissect_t *edt) static gboolean print_hex_data_buffer(print_stream_t *stream, const guchar *cp, - guint length, char_enc encoding) + guint length, packet_char_enc encoding) { register unsigned int ad, i, j, k, l; guchar c; @@ -869,7 +906,6 @@ print_hex_data_buffer(print_stream_t *stream, const guchar *cp, * Start of a new line. */ j = 0; - k = 0; l = use_digits; do { l--; @@ -889,7 +925,7 @@ print_hex_data_buffer(print_stream_t *stream, const guchar *cp, line[j++] = binhex[c>>4]; line[j++] = binhex[c&0xf]; j++; - if (encoding == CHAR_EBCDIC) { + if (encoding == PACKET_CHAR_ENC_CHAR_EBCDIC) { c = EBCDIC_to_ASCII1(c); } line[k++] = c >= ' ' && c < 0x7f ? c : '.'; @@ -917,6 +953,11 @@ void ps_clean_string(unsigned char *out, const unsigned char *in, int rd, wr; char c; + if (in == NULL) { + out[0] = '\0'; + return; + } + for (rd = 0, wr = 0 ; wr < outbuf_size; rd++, wr++ ) { c = in[rd]; switch (c) { @@ -992,7 +1033,7 @@ print_preamble_text(print_stream_t *self _U_, gchar *filename _U_) static gboolean print_line_text(print_stream_t *self, int indent, const char *line) { - output_text *output = self->data; + output_text *output = (output_text *)self->data; char space[MAX_INDENT+1]; int i; int num_spaces; @@ -1025,7 +1066,7 @@ print_bookmark_text(print_stream_t *self _U_, const gchar *name _U_, static gboolean new_page_text(print_stream_t *self) { - output_text *output = self->data; + output_text *output = (output_text *)self->data; fputs("\f", output->fh); return !ferror(output->fh); @@ -1041,7 +1082,7 @@ print_finale_text(print_stream_t *self _U_) static gboolean destroy_text(print_stream_t *self) { - output_text *output = self->data; + output_text *output = (output_text *)self->data; gboolean ret; ret = close_print_dest(output->to_file, output->fh); @@ -1059,21 +1100,16 @@ static const print_stream_ops_t print_text_ops = { destroy_text }; -print_stream_t * -print_stream_text_new(int to_file, const char *dest) +static print_stream_t * +print_stream_text_alloc(int to_file, FILE *fh) { - FILE *fh; print_stream_t *stream; output_text *output; - fh = open_print_dest(to_file, dest); - if (fh == NULL) - return NULL; - - output = g_malloc(sizeof *output); + output = (output_text *)g_malloc(sizeof *output); output->to_file = to_file; output->fh = fh; - stream = g_malloc(sizeof (print_stream_t)); + stream = (print_stream_t *)g_malloc(sizeof (print_stream_t)); stream->ops = &print_text_ops; stream->data = output; @@ -1081,19 +1117,21 @@ print_stream_text_new(int to_file, const char *dest) } print_stream_t * -print_stream_text_stdio_new(FILE *fh) +print_stream_text_new(int to_file, const char *dest) { - print_stream_t *stream; - output_text *output; + FILE *fh; - output = g_malloc(sizeof *output); - output->to_file = TRUE; - output->fh = fh; - stream = g_malloc(sizeof (print_stream_t)); - stream->ops = &print_text_ops; - stream->data = output; + fh = open_print_dest(to_file, dest); + if (fh == NULL) + return NULL; - return stream; + return print_stream_text_alloc(to_file, fh); +} + +print_stream_t * +print_stream_text_stdio_new(FILE *fh) +{ + return print_stream_text_alloc(TRUE, fh); } typedef struct { @@ -1104,14 +1142,11 @@ typedef struct { static gboolean print_preamble_ps(print_stream_t *self, gchar *filename) { - output_ps *output = self->data; + output_ps *output = (output_ps *)self->data; unsigned char psbuffer[MAX_PS_LINE_LENGTH]; /* static sized buffer! */ print_ps_preamble(output->fh); - fputs("%% Set the font to 8 point\n", output->fh); - fputs("/Courier findfont 8 scalefont setfont\n", output->fh); - fputs("\n", output->fh); fputs("%% the page title\n", output->fh); ps_clean_string(psbuffer, filename, MAX_PS_LINE_LENGTH); fprintf(output->fh, "/ws_pagetitle (%s - Wireshark " VERSION "%s) def\n", psbuffer, wireshark_svnversion); @@ -1122,7 +1157,7 @@ print_preamble_ps(print_stream_t *self, gchar *filename) static gboolean print_line_ps(print_stream_t *self, int indent, const char *line) { - output_ps *output = self->data; + output_ps *output = (output_ps *)self->data; unsigned char psbuffer[MAX_PS_LINE_LENGTH]; /* static sized buffer! */ ps_clean_string(psbuffer, line, MAX_PS_LINE_LENGTH); @@ -1133,7 +1168,7 @@ print_line_ps(print_stream_t *self, int indent, const char *line) static gboolean print_bookmark_ps(print_stream_t *self, const gchar *name, const gchar *title) { - output_ps *output = self->data; + output_ps *output = (output_ps *)self->data; unsigned char psbuffer[MAX_PS_LINE_LENGTH]; /* static sized buffer! */ /* @@ -1163,7 +1198,7 @@ print_bookmark_ps(print_stream_t *self, const gchar *name, const gchar *title) static gboolean new_page_ps(print_stream_t *self) { - output_ps *output = self->data; + output_ps *output = (output_ps *)self->data; fputs("formfeed\n", output->fh); return !ferror(output->fh); @@ -1172,7 +1207,7 @@ new_page_ps(print_stream_t *self) static gboolean print_finale_ps(print_stream_t *self) { - output_ps *output = self->data; + output_ps *output = (output_ps *)self->data; print_ps_finale(output->fh); return !ferror(output->fh); @@ -1181,7 +1216,7 @@ print_finale_ps(print_stream_t *self) static gboolean destroy_ps(print_stream_t *self) { - output_ps *output = self->data; + output_ps *output = (output_ps *)self->data; gboolean ret; ret = close_print_dest(output->to_file, output->fh); @@ -1199,21 +1234,16 @@ static const print_stream_ops_t print_ps_ops = { destroy_ps }; -print_stream_t * -print_stream_ps_new(int to_file, const char *dest) +static print_stream_t * +print_stream_ps_alloc(int to_file, FILE *fh) { - FILE *fh; print_stream_t *stream; output_ps *output; - fh = open_print_dest(to_file, dest); - if (fh == NULL) - return NULL; - - output = g_malloc(sizeof *output); + output = (output_ps *)g_malloc(sizeof *output); output->to_file = to_file; output->fh = fh; - stream = g_malloc(sizeof (print_stream_t)); + stream = (print_stream_t *)g_malloc(sizeof (print_stream_t)); stream->ops = &print_ps_ops; stream->data = output; @@ -1221,19 +1251,21 @@ print_stream_ps_new(int to_file, const char *dest) } print_stream_t * -print_stream_ps_stdio_new(FILE *fh) +print_stream_ps_new(int to_file, const char *dest) { - print_stream_t *stream; - output_ps *output; + FILE *fh; - output = g_malloc(sizeof *output); - output->to_file = TRUE; - output->fh = fh; - stream = g_malloc(sizeof (print_stream_t)); - stream->ops = &print_ps_ops; - stream->data = output; + fh = open_print_dest(to_file, dest); + if (fh == NULL) + return NULL; - return stream; + return print_stream_ps_alloc(to_file, fh); +} + +print_stream_t * +print_stream_ps_stdio_new(FILE *fh) +{ + return print_stream_ps_alloc(TRUE, fh); } output_fields_t* output_fields_new() @@ -1241,6 +1273,8 @@ output_fields_t* output_fields_new() output_fields_t* fields = g_new(output_fields_t, 1); fields->print_header = FALSE; fields->separator = '\t'; + fields->occurrence = 'a'; + fields->aggregator = ','; fields->fields = NULL; /*Do lazy initialisation */ fields->field_indicies = NULL; fields->field_values = NULL; @@ -1272,7 +1306,7 @@ void output_fields_free(output_fields_t* fields) if(NULL != fields->fields) { gsize i; for(i = 0; i < fields->fields->len; ++i) { - gchar* field = g_ptr_array_index(fields->fields,i); + gchar* field = (gchar *)g_ptr_array_index(fields->fields,i); g_free(field); } g_ptr_array_free(fields->fields, TRUE); @@ -1348,6 +1382,39 @@ gboolean output_fields_set_option(output_fields_t* info, gchar* option) return TRUE; } + if(0 == strcmp(option_name, "occurrence")) { + switch(NULL == option_value ? '\0' : *option_value) { + case 'f': + case 'l': + case 'a': + info->occurrence = *option_value; + break; + default: + return FALSE; + } + return TRUE; + } + + if(0 == strcmp(option_name,"aggregator")) { + switch(NULL == option_value ? '\0' : *option_value) { + case '\0': + return FALSE; + case '/': + switch(*++option_value) { + case 's': + info->aggregator = ' '; + break; + default: + info->aggregator = '\\'; + } + break; + default: + info->aggregator = *option_value; + break; + } + return TRUE; + } + if(0 == strcmp(option_name, "quote")) { switch(NULL == option_value ? '\0' : *option_value) { default: /* Fall through */ @@ -1373,9 +1440,11 @@ gboolean output_fields_set_option(output_fields_t* info, gchar* option) void output_fields_list_options(FILE *fh) { fprintf(fh, "TShark: The available options for field output \"E\" are:\n"); - fputs("header=y|n Print field abbreviations as first line of output (def: N: no)\n", fh); - fputs("separator=/t|/s| Set the separator to use; \"/t\" = tab,\n \"/s\" = space (def: /t: tab)\n", fh); - fputs("quote=d|s|n Print either d: double-quotes, s: single quotes or n: no quotes around field values (def: n: none)\n", fh); + fputs("header=y|n Print field abbreviations as first line of output (def: N: no)\n", fh); + fputs("separator=/t|/s| Set the separator to use;\n \"/t\" = tab, \"/s\" = space (def: /t: tab)\n", fh); + 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); + fputs("aggregator=,|/s| Set the aggregator to use;\n \",\" = comma, \"/s\" = space (def: ,: comma)\n", fh); + 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); } @@ -1391,7 +1460,7 @@ void write_fields_preamble(output_fields_t* fields, FILE *fh) } for(i = 0; i < fields->fields->len; ++i) { - const gchar* field = g_ptr_array_index(fields->fields,i); + const gchar* field = (const gchar *)g_ptr_array_index(fields->fields,i); if(i != 0 ) { fputc(fields->separator, fh); } @@ -1406,8 +1475,10 @@ static void proto_tree_get_node_field_values(proto_node *node, gpointer data) field_info *fi; gpointer field_index; - call_data = data; - fi = PITEM_FINFO(node); + call_data = (write_field_data_t *)data; + fi = PNODE_FINFO(node); + + g_assert(fi && "dissection with an invisible proto tree?"); field_index = g_hash_table_lookup(call_data->fields->field_indicies, fi->hfinfo->abbrev); if(NULL != field_index) { @@ -1419,7 +1490,16 @@ static void proto_tree_get_node_field_values(proto_node *node, gpointer data) guint actual_index; actual_index = GPOINTER_TO_UINT(field_index); /* Unwrap change made to disambiguiate zero / null */ - call_data->fields->field_values[actual_index - 1] = value; + if ( call_data->fields->field_values[actual_index - 1] == NULL ) { + call_data->fields->field_values[actual_index - 1] = ep_strbuf_new(value); + } else if ( call_data->fields->occurrence == 'l' ) { + /* print only the value of the last occurrence of the field */ + ep_strbuf_printf(call_data->fields->field_values[actual_index - 1],"%s",value); + } else if ( call_data->fields->occurrence == 'a' ) { + /* print the value of all accurrences of the field */ + ep_strbuf_append_printf(call_data->fields->field_values[actual_index - 1], + "%c%s",call_data->fields->aggregator,value); + } } } @@ -1449,7 +1529,7 @@ void proto_tree_write_fields(output_fields_t* fields, epan_dissect_t *edt, FILE i = 0; while( i < fields->fields->len) { - gchar* field = g_ptr_array_index(fields->fields, i); + gchar* field = (gchar *)g_ptr_array_index(fields->fields, i); /* Store field indicies +1 so that zero is not a valid value, * and can be distinguished from NULL as a pointer. */ @@ -1459,7 +1539,7 @@ void proto_tree_write_fields(output_fields_t* fields, epan_dissect_t *edt, FILE } /* Buffer to store values for this packet */ - fields->field_values = ep_alloc_array0(const gchar*, fields->fields->len); + fields->field_values = ep_alloc_array0(emem_strbuf_t*, fields->fields->len); proto_tree_children_foreach(edt->tree, proto_tree_get_node_field_values, &data); @@ -1472,7 +1552,7 @@ void proto_tree_write_fields(output_fields_t* fields, epan_dissect_t *edt, FILE if(fields->quote != '\0') { fputc(fields->quote, fh); } - fputs(fields->field_values[i], fh); + fputs(fields->field_values[i]->str, fh); if(fields->quote != '\0') { fputc(fields->quote, fh); }