diff options
author | Guy Harris <guy@alum.mit.edu> | 2014-11-21 19:22:54 -0800 |
---|---|---|
committer | Guy Harris <guy@alum.mit.edu> | 2014-11-22 03:24:17 +0000 |
commit | 7d7fc47a2a2ce31a3726e422b1c35c9a213add61 (patch) | |
tree | 698fb85ed3cc7b271cdb8d94f55efcfd1baad1f6 /epan/print_stream.c | |
parent | 08475ff67309409bb7f828a85f6ed43c0aefb615 (diff) |
Split the low-level print stream code into a separate file.
Put the low-level print stream code from epan/print.c into
epan/print_stream.c, leaving the higher-level stuff in print.c
Change-Id: Iae961f168ec655a29f434257b1af0937fca9f025
Reviewed-on: https://code.wireshark.org/review/5436
Reviewed-by: Guy Harris <guy@alum.mit.edu>
Diffstat (limited to 'epan/print_stream.c')
-rw-r--r-- | epan/print_stream.c | 367 |
1 files changed, 367 insertions, 0 deletions
diff --git a/epan/print_stream.c b/epan/print_stream.c new file mode 100644 index 0000000000..5f93072c98 --- /dev/null +++ b/epan/print_stream.c @@ -0,0 +1,367 @@ +/* print.c + * Routines for printing packet analysis trees. + * + * Gilbert Ramirez <gram@alumni.rice.edu> + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" + +#include <stdio.h> + +#include <glib.h> + +#include <epan/print_stream.h> + +#include <epan/ps.h> + +#include <wsutil/file_util.h> + +static FILE * +open_print_dest(gboolean to_file, const char *dest) +{ + FILE *fh; + + /* Open the file or command for output */ + if (to_file) + fh = ws_fopen(dest, "w"); + else + fh = popen(dest, "w"); + + return fh; +} + +static gboolean +close_print_dest(gboolean to_file, FILE *fh) +{ + /* Close the file or command */ + if (to_file) + return (fclose(fh) == 0); + else + return (pclose(fh) == 0); +} + +/* Some formats need stuff at the beginning of the output */ +gboolean +print_preamble(print_stream_t *self, gchar *filename, const char *version_string) +{ + return self->ops->print_preamble ? (self->ops->print_preamble)(self, filename, version_string) : TRUE; +} + +gboolean +print_line(print_stream_t *self, int indent, const char *line) +{ + return (self->ops->print_line)(self, indent, line); +} + +/* Insert bookmark */ +gboolean +print_bookmark(print_stream_t *self, const gchar *name, const gchar *title) +{ + return self->ops->print_bookmark ? (self->ops->print_bookmark)(self, name, title) : TRUE; +} + +gboolean +new_page(print_stream_t *self) +{ + return self->ops->new_page ? (self->ops->new_page)(self) : TRUE; +} + +/* Some formats need stuff at the end of the output */ +gboolean +print_finale(print_stream_t *self) +{ + return self->ops->print_finale ? (self->ops->print_finale)(self) : TRUE; +} + +gboolean +destroy_print_stream(print_stream_t *self) +{ + return self->ops->destroy ? (self->ops->destroy)(self) : TRUE; +} + +typedef struct { + gboolean to_file; + FILE *fh; +} output_text; + +#define MAX_INDENT 160 + +static gboolean +print_line_text(print_stream_t *self, int indent, const char *line) +{ + static char spaces[MAX_INDENT]; + size_t ret; + + output_text *output = (output_text *)self->data; + unsigned int num_spaces; + + /* should be space, if NUL -> initialize */ + if (!spaces[0]) { + int i; + + for (i = 0; i < MAX_INDENT; i++) + spaces[i] = ' '; + } + + /* Prepare the tabs for printing, depending on tree level */ + num_spaces = indent * 4; + if (num_spaces > MAX_INDENT) + num_spaces = MAX_INDENT; + + ret = fwrite(spaces, 1, num_spaces, output->fh); + if (ret == num_spaces) { + fputs(line, output->fh); + putc('\n', output->fh); + } + return !ferror(output->fh); +} + +static gboolean +new_page_text(print_stream_t *self) +{ + output_text *output = (output_text *)self->data; + + fputs("\f", output->fh); + return !ferror(output->fh); +} + +static gboolean +destroy_text(print_stream_t *self) +{ + output_text *output = (output_text *)self->data; + gboolean ret; + + ret = close_print_dest(output->to_file, output->fh); + g_free(output); + g_free(self); + return ret; +} + +static const print_stream_ops_t print_text_ops = { + NULL, /* preamble */ + print_line_text, + NULL, /* bookmark */ + new_page_text, + NULL, /* finale */ + destroy_text +}; + +static print_stream_t * +print_stream_text_alloc(gboolean to_file, FILE *fh) +{ + print_stream_t *stream; + output_text *output; + + output = (output_text *)g_malloc(sizeof *output); + output->to_file = to_file; + output->fh = fh; + stream = (print_stream_t *)g_malloc(sizeof (print_stream_t)); + stream->ops = &print_text_ops; + stream->data = output; + + return stream; +} + +print_stream_t * +print_stream_text_new(gboolean to_file, const char *dest) +{ + FILE *fh; + + fh = open_print_dest(to_file, dest); + if (fh == NULL) + return NULL; + + 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 { + gboolean to_file; + FILE *fh; +} output_ps; + +#define MAX_PS_LINE_LENGTH 256 + +static +void ps_clean_string(char *out, const char *in, int outbuf_size) +{ + 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) { + case '(': + case ')': + case '\\': + out[wr] = '\\'; + out[++wr] = c; + break; + + default: + out[wr] = c; + break; + } + + if (c == 0) { + break; + } + } +} + +static gboolean +print_preamble_ps(print_stream_t *self, gchar *filename, const char *version_string) +{ + output_ps *output = (output_ps *)self->data; + char psbuffer[MAX_PS_LINE_LENGTH]; /* static sized buffer! */ + + print_ps_preamble(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 %s) def\n", psbuffer, version_string); + fputs("\n", output->fh); + return !ferror(output->fh); +} + +static gboolean +print_line_ps(print_stream_t *self, int indent, const char *line) +{ + output_ps *output = (output_ps *)self->data; + char psbuffer[MAX_PS_LINE_LENGTH]; /* static sized buffer! */ + + ps_clean_string(psbuffer, line, MAX_PS_LINE_LENGTH); + fprintf(output->fh, "%d (%s) putline\n", indent, psbuffer); + return !ferror(output->fh); +} + +static gboolean +print_bookmark_ps(print_stream_t *self, const gchar *name, const gchar *title) +{ + output_ps *output = (output_ps *)self->data; + char psbuffer[MAX_PS_LINE_LENGTH]; /* static sized buffer! */ + + /* + * See the Adobe "pdfmark reference": + * + * http://partners.adobe.com/asn/acrobat/docs/pdfmark.pdf + * + * The pdfmark stuff tells code that turns PostScript into PDF + * things that it should do. + * + * The /OUT stuff creates a bookmark that goes to the + * destination with "name" as the name and "title" as the title. + * + * The "/DEST" creates the destination. + */ + ps_clean_string(psbuffer, title, MAX_PS_LINE_LENGTH); + fprintf(output->fh, "[/Dest /%s /Title (%s) /OUT pdfmark\n", name, + psbuffer); + fputs("[/View [/XYZ -4 currentpoint matrix currentmatrix matrix defaultmatrix\n", + output->fh); + fputs("matrix invertmatrix matrix concatmatrix transform exch pop 20 add null]\n", + output->fh); + fprintf(output->fh, "/Dest /%s /DEST pdfmark\n", name); + return !ferror(output->fh); +} + +static gboolean +new_page_ps(print_stream_t *self) +{ + output_ps *output = (output_ps *)self->data; + + fputs("formfeed\n", output->fh); + return !ferror(output->fh); +} + +static gboolean +print_finale_ps(print_stream_t *self) +{ + output_ps *output = (output_ps *)self->data; + + print_ps_finale(output->fh); + return !ferror(output->fh); +} + +static gboolean +destroy_ps(print_stream_t *self) +{ + output_ps *output = (output_ps *)self->data; + gboolean ret; + + ret = close_print_dest(output->to_file, output->fh); + g_free(output); + g_free(self); + return ret; +} + +static const print_stream_ops_t print_ps_ops = { + print_preamble_ps, + print_line_ps, + print_bookmark_ps, + new_page_ps, + print_finale_ps, + destroy_ps +}; + +static print_stream_t * +print_stream_ps_alloc(gboolean to_file, FILE *fh) +{ + print_stream_t *stream; + output_ps *output; + + output = (output_ps *)g_malloc(sizeof *output); + output->to_file = to_file; + output->fh = fh; + stream = (print_stream_t *)g_malloc(sizeof (print_stream_t)); + stream->ops = &print_ps_ops; + stream->data = output; + + return stream; +} + +print_stream_t * +print_stream_ps_new(gboolean to_file, const char *dest) +{ + FILE *fh; + + fh = open_print_dest(to_file, dest); + if (fh == NULL) + return NULL; + + 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); +} |