From 4393e48145989906ac05cc622a6fcbac6d414e8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C5=99emysl=20Janouch?= Date: Sat, 25 Apr 2015 14:53:29 +0200 Subject: [PATCH] degesch: encoding fixes Shouldn't be totally broken anymore. --- degesch.c | 125 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 69 insertions(+), 56 deletions(-) diff --git a/degesch.c b/degesch.c index c3aab2d..095e05e 100644 --- a/degesch.c +++ b/degesch.c @@ -1453,13 +1453,47 @@ initiate_quit (struct app_context *ctx) try_finish_quit (ctx); } +// As of 2015, everything should be in UTF-8. And if it's not, we'll decode it +// as ISO Latin 1. This function should not be called on the whole message. +static char * +irc_to_utf8 (struct app_context *ctx, const char *text) +{ + size_t len = strlen (text) + 1; + if (utf8_validate (text, len)) + return xstrdup (text); + return iconv_xstrdup (ctx->latin1_to_utf8, (char *) text, len, NULL); +} + +// This function is used to output debugging IRC traffic to the terminal. +// It's far from ideal, as any non-UTF-8 text degrades the entire line to +// ISO Latin 1. But it should work good enough most of the time. +static char * +irc_to_term (struct app_context *ctx, const char *text) +{ + char *utf8 = irc_to_utf8 (ctx, text); + char *term = iconv_xstrdup (ctx->term_from_utf8, utf8, -1, NULL); + free (utf8); + return term; +} + static bool irc_send (struct app_context *ctx, const char *format, ...) ATTRIBUTE_PRINTF (2, 3); static bool irc_send (struct app_context *ctx, const char *format, ...) { + if (!soft_assert (ctx->irc_fd != -1)) + { + print_debug ("tried sending a message to a dead server connection"); + return false; + } + va_list ap; + va_start (ap, format); + struct str str; + str_init (&str); + str_append_vprintf (&str, format, ap); + va_end (ap); if (g_debug_mode) { @@ -1467,25 +1501,14 @@ irc_send (struct app_context *ctx, const char *format, ...) if (ctx->readline_prompt_shown) app_readline_hide (&state); - fputs ("[IRC] <== \"", stderr); - va_start (ap, format); - vfprintf (stderr, format, ap); - va_end (ap); - fputs ("\"\n", stderr); + char *term = irc_to_term (ctx, str.str); + fprintf (stderr, "[IRC] <== \"%s\"\n", term); + free (term); if (ctx->readline_prompt_shown) app_readline_restore (&state, ctx->readline_prompt); } - - if (!soft_assert (ctx->irc_fd != -1)) - return false; - - va_start (ap, format); - struct str str; - str_init (&str); - str_append_vprintf (&str, format, ap); str_append (&str, "\r\n"); - va_end (ap); bool result = true; if (ctx->ssl) @@ -1902,15 +1925,6 @@ init_readline (void) // TODO: we will need a proper mode parser; to be shared with kike // TODO: we alse definitely need to parse server capability messages -static char * -irc_to_utf8 (struct app_context *ctx, const char *text) -{ - size_t len = strlen (text) + 1; - if (utf8_validate (text, len)) - return xstrdup (text); - return iconv_xstrdup (ctx->latin1_to_utf8, (char *) text, len, NULL); -} - static void irc_handle_join (struct app_context *ctx, const struct irc_message *msg) { @@ -1969,8 +1983,8 @@ irc_handle_join (struct app_context *ctx, const struct irc_message *msg) if (buffer) { buffer_send (ctx, buffer, BUFFER_LINE_JOIN, 0, - .who = xstrdup (msg->prefix), - .object = xstrdup (channel_name)); + .who = irc_to_utf8 (ctx, msg->prefix), + .object = irc_to_utf8 (ctx, channel_name)); } } @@ -2003,9 +2017,9 @@ irc_handle_kick (struct app_context *ctx, const struct irc_message *msg) if (buffer) { buffer_send (ctx, buffer, BUFFER_LINE_KICK, 0, - .who = xstrdup (msg->prefix), - .object = xstrdup (target), - .reason = xstrdup (message)); + .who = irc_to_utf8 (ctx, msg->prefix), + .object = irc_to_utf8 (ctx, target), + .reason = irc_to_utf8 (ctx, message)); } } @@ -2045,8 +2059,8 @@ irc_handle_nick (struct app_context *ctx, const struct irc_message *msg) str_map_set (&ctx->irc_buffer_map, user->nickname, NULL); buffer_send (ctx, pm_buffer, BUFFER_LINE_NICK, 0, - .who = xstrdup (msg->prefix), - .object = xstrdup (new_nickname)); + .who = irc_to_utf8 (ctx, msg->prefix), + .object = irc_to_utf8 (ctx, new_nickname)); // TODO: use a full weechat-style buffer name here buffer_rename (ctx, pm_buffer, new_nickname); } @@ -2064,7 +2078,7 @@ irc_handle_nick (struct app_context *ctx, const struct irc_message *msg) continue; buffer_send (ctx, buffer, BUFFER_LINE_NICK, 0, - .object = xstrdup (new_nickname)); + .object = irc_to_utf8 (ctx, new_nickname)); } } else @@ -2076,8 +2090,8 @@ irc_handle_nick (struct app_context *ctx, const struct irc_message *msg) str_map_find (&ctx->irc_buffer_map, iter->channel->name); hard_assert (buffer != NULL); buffer_send (ctx, buffer, BUFFER_LINE_NICK, 0, - .who = xstrdup (msg->prefix), - .object = xstrdup (new_nickname)); + .who = irc_to_utf8 (ctx, msg->prefix), + .object = irc_to_utf8 (ctx, new_nickname)); } } @@ -2128,9 +2142,9 @@ irc_handle_part (struct app_context *ctx, const struct irc_message *msg) if (buffer) { buffer_send (ctx, buffer, BUFFER_LINE_PART, 0, - .who = xstrdup (msg->prefix), - .object = xstrdup (channel_name), - .reason = xstrdup (message)); + .who = irc_to_utf8 (ctx, msg->prefix), + .object = irc_to_utf8 (ctx, channel_name), + .reason = irc_to_utf8 (ctx, message)); } } @@ -2175,8 +2189,8 @@ irc_handle_privmsg (struct app_context *ctx, const struct irc_message *msg) // TODO: handle CTCP messages // TODO: highlights buffer_send (ctx, buffer, BUFFER_LINE_PRIVMSG, 0, - .who = xstrdup (msg->prefix), - .text = xstrdup (message)); + .who = irc_to_utf8 (ctx, msg->prefix), + .text = irc_to_utf8 (ctx, message)); } } @@ -2206,8 +2220,8 @@ irc_handle_quit (struct app_context *ctx, const struct irc_message *msg) if (buffer) { buffer_send (ctx, buffer, BUFFER_LINE_QUIT, 0, - .who = xstrdup (msg->prefix), - .reason = xstrdup (message)); + .who = irc_to_utf8 (ctx, msg->prefix), + .reason = irc_to_utf8 (ctx, message)); // TODO: set some kind of a flag in the buffer and when the user // reappers on a channel (JOIN), log a "is back online" message. @@ -2221,8 +2235,8 @@ irc_handle_quit (struct app_context *ctx, const struct irc_message *msg) buffer = str_map_find (&ctx->irc_buffer_map, iter->channel->name); if (buffer) buffer_send (ctx, buffer, BUFFER_LINE_QUIT, 0, - .who = xstrdup (msg->prefix), - .reason = xstrdup (message)); + .who = irc_to_utf8 (ctx, msg->prefix), + .reason = irc_to_utf8 (ctx, message)); // This destroys "iter" which doesn't matter to us irc_remove_user_from_channel (user, iter->channel); @@ -2255,8 +2269,8 @@ irc_handle_topic (struct app_context *ctx, const struct irc_message *msg) if (buffer) { buffer_send (ctx, buffer, BUFFER_LINE_TOPIC, 0, - .who = xstrdup (msg->prefix), - .text = xstrdup (topic)); + .who = irc_to_utf8 (ctx, msg->prefix), + .text = irc_to_utf8 (ctx, topic)); } } @@ -2338,10 +2352,9 @@ irc_process_numeric (struct app_context *ctx, // and send it to the server buffer char *reconstructed = join_str_vector (©, ' '); str_vector_free (©); - char *utf8 = irc_to_utf8 (ctx, reconstructed); + buffer_send (ctx, ctx->server_buffer, BUFFER_LINE_STATUS, 0, + .text = irc_to_utf8 (ctx, reconstructed)); free (reconstructed); - buffer_send_status (ctx, ctx->server_buffer, "%s", utf8); - free (utf8); switch (numeric) { @@ -2380,9 +2393,9 @@ irc_process_message (const struct irc_message *msg, if (ctx->readline_prompt_shown) app_readline_hide (&state); - char *utf8 = irc_to_utf8 (ctx, raw); - fprintf (stderr, "[IRC] ==> \"%s\"\n", utf8); - free (utf8); + char *term = irc_to_term (ctx, raw); + fprintf (stderr, "[IRC] ==> \"%s\"\n", term); + free (term); if (ctx->readline_prompt_shown) app_readline_restore (&state, ctx->readline_prompt); @@ -2577,10 +2590,10 @@ log_outcoming_privmsg (struct app_context *ctx, { if (buffer) buffer_send (ctx, buffer, BUFFER_LINE_PRIVMSG, 0, - .who = xstrdup (ctx->irc_user->nickname), - .text = xstrdup (line)); + .who = irc_to_utf8 (ctx, ctx->irc_user->nickname), + .text = irc_to_utf8 (ctx, line)); else - // TODO: fix logging + // TODO: fix logging and encoding buffer_send (ctx, ctx->server_buffer, BUFFER_LINE_STATUS, 0, .text = xstrdup_printf ("MSG(%s): %s", a->target, line)); } @@ -2595,10 +2608,10 @@ log_outcoming_notice (struct app_context *ctx, { if (buffer) buffer_send (ctx, buffer, BUFFER_LINE_NOTICE, 0, - .who = xstrdup (ctx->irc_user->nickname), - .text = xstrdup (line)); + .who = irc_to_utf8 (ctx, ctx->irc_user->nickname), + .text = irc_to_utf8 (ctx, line)); else - // TODO: fix logging + // TODO: fix logging and encoding buffer_send (ctx, ctx->server_buffer, BUFFER_LINE_STATUS, 0, .text = xstrdup_printf ("Notice -> %s: %s", a->target, line)); }