From ae4a912af04456a6fc4022150485be541f65d96c Mon Sep 17 00:00:00 2001 From: Gerald Combs Date: Fri, 6 May 2016 10:25:02 -0700 Subject: TShark: Convert TTY output. If we detect that we're writing to a TTY and that it doesn't support UTF-8, convert our output to the current code page on UNIX/Linux or to UTF-16LE on Windows. This helps to ensure that we don't fill users' screens with mojibake, along with scrubbing invalid output. Add a note about our output behavior to the TShark man page. Add a note about the glyphs we should and shouldn't be using to utf8_entities.h. Bug: 12393 Change-Id: I52b6dd240173b80ffb6d35b5950a46a565c97ce8 Reviewed-on: https://code.wireshark.org/review/15277 Reviewed-by: Gerald Combs Petri-Dish: Gerald Combs Tested-by: Petri Dish Buildbot Reviewed-by: Graham Bloice Reviewed-by: Anders Broman --- epan/print_stream.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) (limited to 'epan/print_stream.c') diff --git a/epan/print_stream.c b/epan/print_stream.c index f53965c75b..740773af2e 100644 --- a/epan/print_stream.c +++ b/epan/print_stream.c @@ -26,6 +26,12 @@ #include +#ifdef _WIN32 +#include +#else +#include +#endif + #include #include @@ -104,6 +110,13 @@ typedef struct { #define MAX_INDENT 160 +#ifdef _WIN32 +static char *to_codeset = "UTF-16LE"; +#else +static char *tty_codeset = NULL; +static char *to_codeset = NULL; +#endif + static gboolean print_line_text(print_stream_t *self, int indent, const char *line) { @@ -128,7 +141,41 @@ print_line_text(print_stream_t *self, int indent, const char *line) ret = fwrite(spaces, 1, num_spaces, output->fh); if (ret == num_spaces) { - fputs(line, output->fh); + gchar *tty_out = NULL; + +#ifndef _WIN32 + /* Is there a more reliable way to do this? */ + if (!tty_codeset) { + gchar *upper_codeset; + + tty_codeset = g_get_codeset(); + upper_codeset = g_ascii_strup(tty_codeset, -1); + if (!strstr(upper_codeset, "UTF-8") && !strstr(upper_codeset, "UTF8")) { + to_codeset = tty_codeset; + } + g_free(upper_codeset); + } +#endif + + if (ws_isatty(ws_fileno(output->fh)) && to_codeset) { + /* XXX Allocating a fresh buffer every line probably isn't the + * most efficient way to do this. However, this has the side + * effect of scrubbing invalid output. + */ + tty_out = g_convert_with_fallback(line, -1, to_codeset, "UTF-8", "?", NULL, NULL, NULL); + } + + if (tty_out) { +#ifdef _WIN32 + DWORD out_len = (DWORD) wcslen((wchar_t *) tty_out); + WriteConsoleW((HANDLE)_get_osfhandle(_fileno(output->fh)), tty_out, out_len, &out_len, NULL); +#else + fputs(tty_out, output->fh); +#endif + g_free(tty_out); + } else { + fputs(line, output->fh); + } putc('\n', output->fh); } return !ferror(output->fh); -- cgit v1.2.3