changeset 30819:ca90b6c27eb8

Refactored oscar_encoding_to_utf8(). 1. Removed elb's hack from #1645. It doesn't appear to be necessary anymore, since the recent official clients (6.5, 7.1) aren't that stupid now. 2. Simplified logic in incomingim_chan2(). 3. Removed all NULL return check for oscar_encoding_to_utf8(), because it will always return non-NULL value.
author ivan.komarov@soc.pidgin.im
date Wed, 28 Jul 2010 16:30:04 +0000
parents 9d386bf63eab
children 420907755a2f
files libpurple/protocols/oscar/encoding.c libpurple/protocols/oscar/encoding.h libpurple/protocols/oscar/oscar.c libpurple/protocols/oscar/userinfo.c
diffstat 4 files changed, 59 insertions(+), 132 deletions(-) [+]
line wrap: on
line diff
--- a/libpurple/protocols/oscar/encoding.c	Tue Jul 27 21:17:01 2010 +0000
+++ b/libpurple/protocols/oscar/encoding.c	Wed Jul 28 16:30:04 2010 +0000
@@ -33,70 +33,51 @@
 	return AIM_CHARSET_ASCII;
 }
 
-gchar *
-oscar_encoding_extract(const char *encoding)
+static gchar *
+encoding_extract(const char *encoding)
 {
-	gchar *ret = NULL;
 	char *begin, *end;
 
 	g_return_val_if_fail(encoding != NULL, NULL);
 
-	/* Make sure encoding begins with charset= */
-	if (strncmp(encoding, "text/aolrtf; charset=", 21) &&
-		strncmp(encoding, "text/x-aolrtf; charset=", 23) &&
-		strncmp(encoding, "text/plain; charset=", 20))
-	{
-		return NULL;
+	if (!g_str_has_prefix(encoding, "text/aolrtf; charset=") &&
+		!g_str_has_prefix(encoding, "text/x-aolrtf; charset=") &&
+		!g_str_has_prefix(encoding, "text/plain; charset=")) {
+		return g_strdup(encoding);
 	}
 
 	begin = strchr(encoding, '"');
 	end = strrchr(encoding, '"');
 
-	if ((begin == NULL) || (end == NULL) || (begin >= end))
-		return NULL;
+	if ((begin == NULL) || (end == NULL) || (begin >= end)) {
+		return g_strdup(encoding);
+	}
 
-	ret = g_strndup(begin+1, (end-1) - begin);
-
-	return ret;
+	return g_strndup(begin+1, (end-1) - begin);
 }
 
 gchar *
-oscar_encoding_to_utf8(PurpleAccount *account, const char *encoding, const char *text, int textlen)
+oscar_encoding_to_utf8(const char *encoding, const char *text, int textlen)
 {
 	gchar *utf8 = NULL;
-
-	if ((encoding == NULL) || encoding[0] == '\0') {
+	const gchar *glib_encoding = NULL;
+	gchar *extracted_encoding = encoding_extract(encoding);
+	
+	if (extracted_encoding == NULL || *extracted_encoding == '\0') {
 		purple_debug_info("oscar", "Empty encoding, assuming UTF-8\n");
-	} else if (!g_ascii_strcasecmp(encoding, "iso-8859-1")) {
-		utf8 = g_convert(text, textlen, "UTF-8", "iso-8859-1", NULL, NULL, NULL);
-	} else if (!g_ascii_strcasecmp(encoding, "ISO-8859-1-Windows-3.1-Latin-1") ||
-	           !g_ascii_strcasecmp(encoding, "us-ascii"))
-	{
-		utf8 = g_convert(text, textlen, "UTF-8", "Windows-1252", NULL, NULL, NULL);
-	} else if (!g_ascii_strcasecmp(encoding, "unicode-2-0")) {
-		/* 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 UTF-16 (not from UTF-8
-		 * to UTF-16!) 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, "UTF-16BE", &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", "UTF-16BE", 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);
-		utf8 = g_convert(text, textlen, "UTF-8", encoding, NULL, NULL, NULL);
+	} else if (!g_ascii_strcasecmp(extracted_encoding, "iso-8859-1")) {
+		glib_encoding = "iso-8859-1";
+	} else if (!g_ascii_strcasecmp(extracted_encoding, "ISO-8859-1-Windows-3.1-Latin-1") || !g_ascii_strcasecmp(extracted_encoding, "us-ascii")) {
+		glib_encoding = "Windows-1252";
+	} else if (!g_ascii_strcasecmp(extracted_encoding, "unicode-2-0")) {
+		glib_encoding = "UTF-16BE";
+	} else if (g_ascii_strcasecmp(extracted_encoding, "utf-8")) {
+		purple_debug_warning("oscar", "Unrecognized character encoding \"%s\", attempting to convert to UTF-8 anyway\n", extracted_encoding);
+		glib_encoding = extracted_encoding;
+	}
+
+	if (glib_encoding != NULL) {
+		utf8 = g_convert(text, textlen, "UTF-8", glib_encoding, NULL, NULL, NULL);
 	}
 
 	/*
@@ -106,13 +87,13 @@
 	 * just copy it.
 	 */
 	if (utf8 == NULL) {
-		if (textlen != 0 && *text != '\0'
-				&& !g_utf8_validate(text, textlen, NULL))
+		if (textlen != 0 && *text != '\0' && !g_utf8_validate(text, textlen, NULL))
 			utf8 = g_strdup(_("(There was an error receiving this message.  The buddy you are speaking with is probably using a different encoding than expected.  If you know what encoding he is using, you can specify it in the advanced account options for your AIM/ICQ account.)"));
 		else
 			utf8 = g_strndup(text, textlen);
 	}
 
+	g_free(extracted_encoding);
 	return utf8;
 }
 
--- a/libpurple/protocols/oscar/encoding.h	Tue Jul 27 21:17:01 2010 +0000
+++ b/libpurple/protocols/oscar/encoding.h	Wed Jul 28 16:30:04 2010 +0000
@@ -29,14 +29,7 @@
  */
 guint16 oscar_charset_check(const char *utf8);
 
-/**
- * Take a string of the form charset="bleh" where bleh is
- * one of us-ascii, utf-8, iso-8859-1, or unicode-2-0, and
- * return a newly allocated string containing bleh.
- */
-gchar * oscar_encoding_extract(const char *encoding);
-
-gchar * oscar_encoding_to_utf8(PurpleAccount *account, const char *encoding, const char *text, int textlen);
+gchar * oscar_encoding_to_utf8(const char *encoding, const char *text, int textlen);
 gchar * oscar_utf8_try_convert(PurpleAccount *account, OscarData *od, const gchar *msg);
 
 /**
--- a/libpurple/protocols/oscar/oscar.c	Tue Jul 27 21:17:01 2010 +0000
+++ b/libpurple/protocols/oscar/oscar.c	Wed Jul 28 16:30:04 2010 +0000
@@ -1413,18 +1413,18 @@
 		purple_prpl_got_user_status_deactive(account, info->bn, OSCAR_STATUS_ID_MOBILE);
 	}
 
-	if (info->status != NULL && info->status[0] != '\0')
+	if (info->status != NULL && info->status[0] != '\0') {
 		/* Grab the available message */
-		message = oscar_encoding_to_utf8(account, info->status_encoding,
-										 info->status, info->status_len);
+		message = oscar_encoding_to_utf8(info->status_encoding, info->status, info->status_len);
+	}
 
 	tmp2 = tmp = (message ? purple_markup_escape_text(message, -1) : NULL);
 
 	if (strcmp(status_id, OSCAR_STATUS_ID_AVAILABLE) == 0) {
-		if (info->itmsurl_encoding && info->itmsurl && info->itmsurl_len)
+		if (info->itmsurl_encoding && info->itmsurl && info->itmsurl_len) {
 			/* Grab the iTunes Music Store URL */
-			itmsurl = oscar_encoding_to_utf8(account, info->itmsurl_encoding,
-											 info->itmsurl, info->itmsurl_len);
+			itmsurl = oscar_encoding_to_utf8(info->itmsurl_encoding, info->itmsurl, info->itmsurl_len);
+		}
 
 		if (tmp2 == NULL && itmsurl != NULL)
 			/*
@@ -1705,35 +1705,20 @@
 			G_GUINT64_FORMAT ", user %s, status %hu\n",
 			args->type, userinfo->bn, args->status);
 
-	if (args->msg != NULL)
-	{
-		if (args->encoding != NULL)
-		{
-			char *encoding = NULL;
-			encoding = oscar_encoding_extract(args->encoding);
-			message = oscar_encoding_to_utf8(account, encoding, args->msg,
-			                                 args->msglen);
-			g_free(encoding);
-		} else {
-			if (g_utf8_validate(args->msg, args->msglen, NULL))
-				message = g_strdup(args->msg);
-		}
+	if (args->msg != NULL) {
+		message = oscar_encoding_to_utf8(args->encoding, args->msg, args->msglen);
 	}
 
 	if (args->type & OSCAR_CAPABILITY_CHAT)
 	{
-		char *encoding, *utf8name, *tmp;
+		char *utf8name, *tmp;
 		GHashTable *components;
 
 		if (!args->info.chat.roominfo.name || !args->info.chat.roominfo.exchange) {
 			g_free(message);
 			return 1;
 		}
-		encoding = args->encoding ? oscar_encoding_extract(args->encoding) : NULL;
-		utf8name = oscar_encoding_to_utf8(account, encoding,
-				args->info.chat.roominfo.name,
-				args->info.chat.roominfo.namelen);
-		g_free(encoding);
+		utf8name = oscar_encoding_to_utf8(args->encoding, args->info.chat.roominfo.name, args->info.chat.roominfo.namelen);
 
 		tmp = extract_name(utf8name);
 		if (tmp != NULL)
@@ -1754,8 +1739,7 @@
 				     components);
 	}
 
-	else if ((args->type & OSCAR_CAPABILITY_SENDFILE) ||
-			 (args->type & OSCAR_CAPABILITY_DIRECTIM))
+	else if ((args->type & OSCAR_CAPABILITY_SENDFILE) || (args->type & OSCAR_CAPABILITY_DIRECTIM))
 	{
 		if (args->status == AIM_RENDEZVOUS_PROPOSE)
 		{
@@ -1808,24 +1792,11 @@
 		purple_debug_info("oscar", "Got an ICQ Server Relay message of "
 				"type %d\n", args->info.rtfmsg.msgtype);
 
-		if (args->info.rtfmsg.msgtype == 1)
-		{
-			if (args->info.rtfmsg.msg != NULL)
-			{
-				char *rtfmsg = NULL;
-				if (args->encoding != NULL) {
-					char *encoding = oscar_encoding_extract(args->encoding);
-					rtfmsg = oscar_encoding_to_utf8(account, encoding,
-							args->info.rtfmsg.msg, strlen(args->info.rtfmsg.msg));
-					g_free(encoding);
-				} else {
-					if (g_utf8_validate(args->info.rtfmsg.msg, strlen(args->info.rtfmsg.msg), NULL))
-						rtfmsg = g_strdup(args->info.rtfmsg.msg);
-				}
-				if (rtfmsg) {
-					serv_got_im(gc, userinfo->bn, rtfmsg, flags, time(NULL));
-					g_free(rtfmsg);
-				}
+		if (args->info.rtfmsg.msgtype == 1) {
+			if (args->info.rtfmsg.msg != NULL) {
+				char *rtfmsg = oscar_encoding_to_utf8(args->encoding, args->info.rtfmsg.msg, strlen(args->info.rtfmsg.msg));
+				serv_got_im(gc, userinfo->bn, rtfmsg, flags, time(NULL));
+				g_free(rtfmsg);
 			}
 		} else if (args->info.rtfmsg.msgtype == 26) {
 			purple_debug_info("oscar", "Sending X-Status Reply\n");
@@ -2582,7 +2553,6 @@
 
 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;
@@ -2601,10 +2571,7 @@
 	charset = va_arg(ap, char *);
 	va_end(ap);
 
-	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.]"));
+	utf8 = oscar_encoding_to_utf8(charset, msg, len);
 	serv_got_chat_in(gc, ccon->id, info->bn, 0, utf8, time(NULL));
 	g_free(utf8);
 
--- a/libpurple/protocols/oscar/userinfo.c	Tue Jul 27 21:17:01 2010 +0000
+++ b/libpurple/protocols/oscar/userinfo.c	Wed Jul 28 16:30:04 2010 +0000
@@ -191,30 +191,21 @@
 	   the "message" attribute of the status contains only the plaintext
 	   message. */
 	if (userinfo) {
-		if ((userinfo->flags & AIM_FLAG_AWAY)
-				&& userinfo->away_len > 0
-				&& userinfo->away != NULL
-				&& userinfo->away_encoding != NULL)
-		{
+		if ((userinfo->flags & AIM_FLAG_AWAY) && userinfo->away_len > 0 && userinfo->away != NULL && userinfo->away_encoding != NULL) {
 			/* Away message */
-			tmp = oscar_encoding_extract(userinfo->away_encoding);
-			message = oscar_encoding_to_utf8(account,
-					tmp, userinfo->away, userinfo->away_len);
-			g_free(tmp);
+			message = oscar_encoding_to_utf8(userinfo->away_encoding, userinfo->away, userinfo->away_len);
 		} else {
 			/*
 			 * Available message or non-HTML away message (because that's
 			 * all we have right now.
 			 */
 			if ((userinfo->status != NULL) && userinfo->status[0] != '\0') {
-				message = oscar_encoding_to_utf8(account,
-						userinfo->status_encoding, userinfo->status,
-						userinfo->status_len);
+				message = oscar_encoding_to_utf8(userinfo->status_encoding, userinfo->status, userinfo->status_len);
 			}
 #if defined (_WIN32) || defined (__APPLE__)
-			if (userinfo->itmsurl && (userinfo->itmsurl[0] != '\0'))
-				itmsurl = oscar_encoding_to_utf8(account, userinfo->itmsurl_encoding,
-												 userinfo->itmsurl, userinfo->itmsurl_len);
+			if (userinfo->itmsurl && (userinfo->itmsurl[0] != '\0')) {
+				itmsurl = oscar_encoding_to_utf8(userinfo->itmsurl_encoding, userinfo->itmsurl, userinfo->itmsurl_len);
+			}
 #endif
 		}
 	} else {
@@ -552,17 +543,12 @@
 
 	/* 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(account, tmp, userinfo->info,
-		                                   userinfo->info_len);
+		info_utf8 = oscar_encoding_to_utf8(userinfo->info_encoding, userinfo->info, userinfo->info_len);
+		tmp = oscar_util_format_string(info_utf8, purple_account_get_username(account));
+		purple_notify_user_info_add_section_break(user_info);
+		oscar_user_info_add_pair(user_info, _("Profile"), tmp);
 		g_free(tmp);
-		if (info_utf8 != NULL) {
-			tmp = oscar_util_format_string(info_utf8, purple_account_get_username(account));
-			purple_notify_user_info_add_section_break(user_info);
-			oscar_user_info_add_pair(user_info, _("Profile"), tmp);
-			g_free(tmp);
-			g_free(info_utf8);
-		}
+		g_free(info_utf8);
 	}
 
 	purple_notify_user_info_add_section_break(user_info);