Mercurial > pidgin
changeset 17632:36ebcb33e2eb
This fixes a bustination of the official ICQ client in at least some
locales. For away (and possibly other) messages, apparently the
official ICQ (5.1?) client of some locales converts messages which are
stored in UTF-8 from a locale-native character set to UCS-2BE; this
results in something which, when decoded "correctly", is gibberish.
Instead, we first try decoding from UCS-2BE to the locale-specific
character set, and if that validates as UTF-8, we display it, instead.
Since UTF-8 is relatively picky, hopefully this won't break too many
sane clients.
author | Ethan Blanton <elb@pidgin.im> |
---|---|
date | Thu, 14 Jun 2007 18:20:53 +0000 |
parents | 91e92cb0d875 |
children | 81d42bfe31fa |
files | libpurple/protocols/oscar/oscar.c libpurple/protocols/oscar/oscar.h |
diffstat | 2 files changed, 39 insertions(+), 14 deletions(-) [+] |
line wrap: on
line diff
--- a/libpurple/protocols/oscar/oscar.c Thu Jun 14 16:17:07 2007 +0000 +++ b/libpurple/protocols/oscar/oscar.c Thu Jun 14 18:20:53 2007 +0000 @@ -298,7 +298,7 @@ } gchar * -oscar_encoding_to_utf8(const char *encoding, const char *text, int textlen) +oscar_encoding_to_utf8(PurpleAccount *account, const char *encoding, const char *text, int textlen) { gchar *utf8 = NULL; @@ -311,7 +311,25 @@ { utf8 = g_convert(text, textlen, "UTF-8", "Windows-1252", NULL, NULL, NULL); } else if (!g_ascii_strcasecmp(encoding, "unicode-2-0")) { - utf8 = g_convert(text, textlen, "UTF-8", "UCS-2BE", NULL, NULL, NULL); + /* Some official ICQ clients are apparently total crack, + * and have been known to save a UTF-8 string converted + * from the locale character set to UCS-2 (not from UTF-8 + * to UCS-2!) in the away message. This hack should find + * and do something (un)reasonable with that, and not + * mess up too much else. */ + const gchar *charset = purple_account_get_string(account, "encoding", NULL); + if (charset) { + gsize len; + utf8 = g_convert(text, textlen, charset, "UCS-2BE", &len, NULL, NULL); + if (!utf8 || len != textlen || !g_utf8_validate(utf8, -1, NULL)) { + g_free(utf8); + utf8 = NULL; + } else { + purple_debug_info("oscar", "Used broken ICQ fallback encoding\n"); + } + } + if (!utf8) + utf8 = g_convert(text, textlen, "UTF-8", "UCS-2BE", NULL, NULL, NULL); } else if (g_ascii_strcasecmp(encoding, "utf-8")) { purple_debug_warning("oscar", "Unrecognized character encoding \"%s\", " "attempting to convert to UTF-8 anyway\n", encoding); @@ -1774,7 +1792,7 @@ { have_status_message = TRUE; if (info->status[0] != '\0') - message = oscar_encoding_to_utf8(info->status_encoding, + message = oscar_encoding_to_utf8(account, info->status_encoding, info->status, info->status_len); } @@ -1790,7 +1808,7 @@ if ((status_id == OSCAR_STATUS_ID_AVAILABLE) && (info->itmsurl != NULL)) { char *itmsurl; - itmsurl = oscar_encoding_to_utf8(info->itmsurl_encoding, + itmsurl = oscar_encoding_to_utf8(account, info->itmsurl_encoding, info->itmsurl, info->itmsurl_len); purple_prpl_got_user_status(account, info->sn, status_id, "message", message, "itmsurl", itmsurl, NULL); @@ -2047,7 +2065,8 @@ { char *encoding = NULL; encoding = oscar_encoding_extract(args->encoding); - message = oscar_encoding_to_utf8(encoding, args->msg, args->msglen); + message = oscar_encoding_to_utf8(account, encoding, args->msg, + args->msglen); g_free(encoding); } else { if (g_utf8_validate(args->msg, args->msglen, NULL)) @@ -2065,7 +2084,7 @@ return 1; } encoding = args->encoding ? oscar_encoding_extract(args->encoding) : NULL; - utf8name = oscar_encoding_to_utf8(encoding, + utf8name = oscar_encoding_to_utf8(account, encoding, args->info.chat.roominfo.name, args->info.chat.roominfo.namelen); g_free(encoding); @@ -2875,12 +2894,12 @@ if ((userinfo->status != NULL) && !(userinfo->flags & AIM_FLAG_AWAY)) { if (userinfo->status[0] != '\0') - tmp = oscar_encoding_to_utf8(userinfo->status_encoding, + tmp = oscar_encoding_to_utf8(account, userinfo->status_encoding, userinfo->status, userinfo->status_len); #if defined (_WIN32) || defined (__APPLE__) if (userinfo->itmsurl && (userinfo->itmsurl[0] != '\0')) { gchar *itmsurl, *tmp2; - itmsurl = oscar_encoding_to_utf8(userinfo->itmsurl_encoding, + itmsurl = oscar_encoding_to_utf8(account, userinfo->itmsurl_encoding, userinfo->itmsurl, userinfo->itmsurl_len); tmp2 = g_strdup_printf("<a href=\"%s\">%s</a>", itmsurl, tmp); @@ -2896,7 +2915,8 @@ /* Away message */ if ((userinfo->flags & AIM_FLAG_AWAY) && (userinfo->away_len > 0) && (userinfo->away != NULL) && (userinfo->away_encoding != NULL)) { tmp = oscar_encoding_extract(userinfo->away_encoding); - away_utf8 = oscar_encoding_to_utf8(tmp, userinfo->away, userinfo->away_len); + away_utf8 = oscar_encoding_to_utf8(account, tmp, userinfo->away, + userinfo->away_len); g_free(tmp); if (away_utf8 != NULL) { tmp = purple_str_sub_away_formatters(away_utf8, purple_account_get_username(account)); @@ -2910,7 +2930,8 @@ /* Info */ if ((userinfo->info_len > 0) && (userinfo->info != NULL) && (userinfo->info_encoding != NULL)) { tmp = oscar_encoding_extract(userinfo->info_encoding); - info_utf8 = oscar_encoding_to_utf8(tmp, userinfo->info, userinfo->info_len); + info_utf8 = oscar_encoding_to_utf8(account, tmp, userinfo->info, + userinfo->info_len); g_free(tmp); if (info_utf8 != NULL) { tmp = purple_str_sub_away_formatters(info_utf8, purple_account_get_username(account)); @@ -2930,6 +2951,7 @@ static int purple_got_infoblock(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { PurpleConnection *gc = od->gc; + PurpleAccount *account = purple_connection_get_account(gc); PurpleBuddy *b; PurplePresence *presence; PurpleStatus *status; @@ -2942,7 +2964,7 @@ userinfo = va_arg(ap, aim_userinfo_t *); va_end(ap); - b = purple_find_buddy(purple_connection_get_account(gc), userinfo->sn); + b = purple_find_buddy(account, userinfo->sn); if (b == NULL) return 1; @@ -2962,7 +2984,9 @@ if ((userinfo->flags & AIM_FLAG_AWAY) && (userinfo->away_len > 0) && (userinfo->away != NULL) && (userinfo->away_encoding != NULL)) { gchar *charset = oscar_encoding_extract(userinfo->away_encoding); - message = oscar_encoding_to_utf8(charset, userinfo->away, userinfo->away_len); + message = oscar_encoding_to_utf8(account, charset, + userinfo->away, + userinfo->away_len); g_free(charset); purple_status_set_attr_string(status, "message", message); g_free(message); @@ -3158,6 +3182,7 @@ static int purple_conv_chat_incoming_msg(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { PurpleConnection *gc = od->gc; + PurpleAccount *account = purple_connection_get_account(gc); struct chat_connection *ccon = find_oscar_chat_by_conn(gc, conn); gchar *utf8; va_list ap; @@ -3176,7 +3201,7 @@ charset = va_arg(ap, char *); va_end(ap); - utf8 = oscar_encoding_to_utf8(charset, msg, len); + utf8 = oscar_encoding_to_utf8(account, charset, msg, len); if (utf8 == NULL) /* The conversion failed! */ utf8 = g_strdup(_("[Unable to display a message from this user because it contained invalid characters.]"));
--- a/libpurple/protocols/oscar/oscar.h Thu Jun 14 16:17:07 2007 +0000 +++ b/libpurple/protocols/oscar/oscar.h Thu Jun 14 18:20:53 2007 +0000 @@ -934,7 +934,7 @@ /* 0x0014 */ int aim_im_sendmtn(OscarData *od, guint16 type1, const char *sn, guint16 type2); void aim_icbm_makecookie(guchar* cookie); gchar *oscar_encoding_extract(const char *encoding); -gchar *oscar_encoding_to_utf8(const char *encoding, const char *text, int textlen); +gchar *oscar_encoding_to_utf8(PurpleAccount *account, const char *encoding, const char *text, int textlen); gchar *purple_plugin_oscar_decode_im_part(PurpleAccount *account, const char *sourcesn, guint16 charset, guint16 charsubset, const gchar *data, gsize datalen);