degesch: encoding fixes

Shouldn't be totally broken anymore.
This commit is contained in:
Přemysl Eric Janouch 2015-04-25 14:53:29 +02:00
parent c38dfced51
commit 4393e48145
1 changed files with 69 additions and 56 deletions

125
degesch.c
View File

@ -1453,13 +1453,47 @@ initiate_quit (struct app_context *ctx)
try_finish_quit (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, static bool irc_send (struct app_context *ctx,
const char *format, ...) ATTRIBUTE_PRINTF (2, 3); const char *format, ...) ATTRIBUTE_PRINTF (2, 3);
static bool static bool
irc_send (struct app_context *ctx, const char *format, ...) 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_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) if (g_debug_mode)
{ {
@ -1467,25 +1501,14 @@ irc_send (struct app_context *ctx, const char *format, ...)
if (ctx->readline_prompt_shown) if (ctx->readline_prompt_shown)
app_readline_hide (&state); app_readline_hide (&state);
fputs ("[IRC] <== \"", stderr); char *term = irc_to_term (ctx, str.str);
va_start (ap, format); fprintf (stderr, "[IRC] <== \"%s\"\n", term);
vfprintf (stderr, format, ap); free (term);
va_end (ap);
fputs ("\"\n", stderr);
if (ctx->readline_prompt_shown) if (ctx->readline_prompt_shown)
app_readline_restore (&state, ctx->readline_prompt); 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"); str_append (&str, "\r\n");
va_end (ap);
bool result = true; bool result = true;
if (ctx->ssl) 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 will need a proper mode parser; to be shared with kike
// TODO: we alse definitely need to parse server capability messages // 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 static void
irc_handle_join (struct app_context *ctx, const struct irc_message *msg) 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) if (buffer)
{ {
buffer_send (ctx, buffer, BUFFER_LINE_JOIN, 0, buffer_send (ctx, buffer, BUFFER_LINE_JOIN, 0,
.who = xstrdup (msg->prefix), .who = irc_to_utf8 (ctx, msg->prefix),
.object = xstrdup (channel_name)); .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) if (buffer)
{ {
buffer_send (ctx, buffer, BUFFER_LINE_KICK, 0, buffer_send (ctx, buffer, BUFFER_LINE_KICK, 0,
.who = xstrdup (msg->prefix), .who = irc_to_utf8 (ctx, msg->prefix),
.object = xstrdup (target), .object = irc_to_utf8 (ctx, target),
.reason = xstrdup (message)); .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); str_map_set (&ctx->irc_buffer_map, user->nickname, NULL);
buffer_send (ctx, pm_buffer, BUFFER_LINE_NICK, 0, buffer_send (ctx, pm_buffer, BUFFER_LINE_NICK, 0,
.who = xstrdup (msg->prefix), .who = irc_to_utf8 (ctx, msg->prefix),
.object = xstrdup (new_nickname)); .object = irc_to_utf8 (ctx, new_nickname));
// TODO: use a full weechat-style buffer name here // TODO: use a full weechat-style buffer name here
buffer_rename (ctx, pm_buffer, new_nickname); buffer_rename (ctx, pm_buffer, new_nickname);
} }
@ -2064,7 +2078,7 @@ irc_handle_nick (struct app_context *ctx, const struct irc_message *msg)
continue; continue;
buffer_send (ctx, buffer, BUFFER_LINE_NICK, 0, buffer_send (ctx, buffer, BUFFER_LINE_NICK, 0,
.object = xstrdup (new_nickname)); .object = irc_to_utf8 (ctx, new_nickname));
} }
} }
else 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); str_map_find (&ctx->irc_buffer_map, iter->channel->name);
hard_assert (buffer != NULL); hard_assert (buffer != NULL);
buffer_send (ctx, buffer, BUFFER_LINE_NICK, 0, buffer_send (ctx, buffer, BUFFER_LINE_NICK, 0,
.who = xstrdup (msg->prefix), .who = irc_to_utf8 (ctx, msg->prefix),
.object = xstrdup (new_nickname)); .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) if (buffer)
{ {
buffer_send (ctx, buffer, BUFFER_LINE_PART, 0, buffer_send (ctx, buffer, BUFFER_LINE_PART, 0,
.who = xstrdup (msg->prefix), .who = irc_to_utf8 (ctx, msg->prefix),
.object = xstrdup (channel_name), .object = irc_to_utf8 (ctx, channel_name),
.reason = xstrdup (message)); .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: handle CTCP messages
// TODO: highlights // TODO: highlights
buffer_send (ctx, buffer, BUFFER_LINE_PRIVMSG, 0, buffer_send (ctx, buffer, BUFFER_LINE_PRIVMSG, 0,
.who = xstrdup (msg->prefix), .who = irc_to_utf8 (ctx, msg->prefix),
.text = xstrdup (message)); .text = irc_to_utf8 (ctx, message));
} }
} }
@ -2206,8 +2220,8 @@ irc_handle_quit (struct app_context *ctx, const struct irc_message *msg)
if (buffer) if (buffer)
{ {
buffer_send (ctx, buffer, BUFFER_LINE_QUIT, 0, buffer_send (ctx, buffer, BUFFER_LINE_QUIT, 0,
.who = xstrdup (msg->prefix), .who = irc_to_utf8 (ctx, msg->prefix),
.reason = xstrdup (message)); .reason = irc_to_utf8 (ctx, message));
// TODO: set some kind of a flag in the buffer and when the user // 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. // 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); buffer = str_map_find (&ctx->irc_buffer_map, iter->channel->name);
if (buffer) if (buffer)
buffer_send (ctx, buffer, BUFFER_LINE_QUIT, 0, buffer_send (ctx, buffer, BUFFER_LINE_QUIT, 0,
.who = xstrdup (msg->prefix), .who = irc_to_utf8 (ctx, msg->prefix),
.reason = xstrdup (message)); .reason = irc_to_utf8 (ctx, message));
// This destroys "iter" which doesn't matter to us // This destroys "iter" which doesn't matter to us
irc_remove_user_from_channel (user, iter->channel); 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) if (buffer)
{ {
buffer_send (ctx, buffer, BUFFER_LINE_TOPIC, 0, buffer_send (ctx, buffer, BUFFER_LINE_TOPIC, 0,
.who = xstrdup (msg->prefix), .who = irc_to_utf8 (ctx, msg->prefix),
.text = xstrdup (topic)); .text = irc_to_utf8 (ctx, topic));
} }
} }
@ -2338,10 +2352,9 @@ irc_process_numeric (struct app_context *ctx,
// and send it to the server buffer // and send it to the server buffer
char *reconstructed = join_str_vector (&copy, ' '); char *reconstructed = join_str_vector (&copy, ' ');
str_vector_free (&copy); str_vector_free (&copy);
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); free (reconstructed);
buffer_send_status (ctx, ctx->server_buffer, "%s", utf8);
free (utf8);
switch (numeric) switch (numeric)
{ {
@ -2380,9 +2393,9 @@ irc_process_message (const struct irc_message *msg,
if (ctx->readline_prompt_shown) if (ctx->readline_prompt_shown)
app_readline_hide (&state); app_readline_hide (&state);
char *utf8 = irc_to_utf8 (ctx, raw); char *term = irc_to_term (ctx, raw);
fprintf (stderr, "[IRC] ==> \"%s\"\n", utf8); fprintf (stderr, "[IRC] ==> \"%s\"\n", term);
free (utf8); free (term);
if (ctx->readline_prompt_shown) if (ctx->readline_prompt_shown)
app_readline_restore (&state, ctx->readline_prompt); app_readline_restore (&state, ctx->readline_prompt);
@ -2577,10 +2590,10 @@ log_outcoming_privmsg (struct app_context *ctx,
{ {
if (buffer) if (buffer)
buffer_send (ctx, buffer, BUFFER_LINE_PRIVMSG, 0, buffer_send (ctx, buffer, BUFFER_LINE_PRIVMSG, 0,
.who = xstrdup (ctx->irc_user->nickname), .who = irc_to_utf8 (ctx, ctx->irc_user->nickname),
.text = xstrdup (line)); .text = irc_to_utf8 (ctx, line));
else else
// TODO: fix logging // TODO: fix logging and encoding
buffer_send (ctx, ctx->server_buffer, BUFFER_LINE_STATUS, 0, buffer_send (ctx, ctx->server_buffer, BUFFER_LINE_STATUS, 0,
.text = xstrdup_printf ("MSG(%s): %s", a->target, line)); .text = xstrdup_printf ("MSG(%s): %s", a->target, line));
} }
@ -2595,10 +2608,10 @@ log_outcoming_notice (struct app_context *ctx,
{ {
if (buffer) if (buffer)
buffer_send (ctx, buffer, BUFFER_LINE_NOTICE, 0, buffer_send (ctx, buffer, BUFFER_LINE_NOTICE, 0,
.who = xstrdup (ctx->irc_user->nickname), .who = irc_to_utf8 (ctx, ctx->irc_user->nickname),
.text = xstrdup (line)); .text = irc_to_utf8 (ctx, line));
else else
// TODO: fix logging // TODO: fix logging and encoding
buffer_send (ctx, ctx->server_buffer, BUFFER_LINE_STATUS, 0, buffer_send (ctx, ctx->server_buffer, BUFFER_LINE_STATUS, 0,
.text = xstrdup_printf ("Notice -> %s: %s", a->target, line)); .text = xstrdup_printf ("Notice -> %s: %s", a->target, line));
} }