changeset 9806:41b97d72e647

[gaim-migrate @ 10674] Clean up oscar incoming IM parsing/charset converting. committer: Tailor Script <tailor@pidgin.im>
author Mark Doliner <mark@kingant.net>
date Sat, 21 Aug 2004 21:53:57 +0000
parents ccf5a52730b9
children 0c170246a9ec
files src/protocols/oscar/aim.h src/protocols/oscar/im.c src/protocols/oscar/oscar.c
diffstat 3 files changed, 91 insertions(+), 69 deletions(-) [+]
line wrap: on
line diff
--- a/src/protocols/oscar/aim.h	Sat Aug 21 20:35:23 2004 +0000
+++ b/src/protocols/oscar/aim.h	Sat Aug 21 21:53:57 2004 +0000
@@ -681,19 +681,23 @@
 	fu16_t instance;
 };
 
-#define AIM_IMFLAGS_AWAY		0x0001 /* mark as an autoreply */
-#define AIM_IMFLAGS_ACK			0x0002 /* request a receipt notice */
-#define AIM_IMFLAGS_UNICODE		0x0004
-#define AIM_IMFLAGS_ISO_8859_1		0x0008
-#define AIM_IMFLAGS_BUDDYREQ		0x0010 /* buddy icon requested */
-#define AIM_IMFLAGS_HASICON		0x0020 /* already has icon */
+#define AIM_IMFLAGS_AWAY				0x0001 /* mark as an autoreply */
+#define AIM_IMFLAGS_ACK					0x0002 /* request a receipt notice */
+#define AIM_IMFLAGS_UNICODE				0x0004
+#define AIM_IMFLAGS_ISO_8859_1			0x0008
+#define AIM_IMFLAGS_BUDDYREQ			0x0010 /* buddy icon requested */
+#define AIM_IMFLAGS_HASICON				0x0020 /* already has icon */
 #define AIM_IMFLAGS_SUBENC_MACINTOSH	0x0040 /* damn that Steve Jobs! */
-#define AIM_IMFLAGS_CUSTOMFEATURES 	0x0080 /* features field present */
-#define AIM_IMFLAGS_EXTDATA		0x0100
-#define AIM_IMFLAGS_X			0x0200
-#define AIM_IMFLAGS_MULTIPART		0x0400 /* ->mpmsg section valid */
-#define AIM_IMFLAGS_OFFLINE		0x0800 /* send to offline user */
-#define AIM_IMFLAGS_TYPINGNOT		0x1000 /* typing notification */
+#define AIM_IMFLAGS_CUSTOMFEATURES 		0x0080 /* features field present */
+#define AIM_IMFLAGS_EXTDATA				0x0100
+#define AIM_IMFLAGS_X					0x0200
+#define AIM_IMFLAGS_MULTIPART			0x0400 /* ->mpmsg section valid */
+#define AIM_IMFLAGS_OFFLINE				0x0800 /* send to offline user */
+#define AIM_IMFLAGS_TYPINGNOT			0x1000 /* typing notification */
+
+#define AIM_IMCHARSET_ASCII		0x0000
+#define AIM_IMCHARSET_UNICODE	0x0002 /* UCS-2BE */
+#define AIM_IMCHARSET_CUSTOM	0x0003
 
 /*
  * Multipart message structures.
--- a/src/protocols/oscar/im.c	Sat Aug 21 20:35:23 2004 +0000
+++ b/src/protocols/oscar/im.c	Sat Aug 21 21:53:57 2004 +0000
@@ -1316,10 +1316,11 @@
  */
 static int incomingim_ch1_parsemsgs(aim_session_t *sess, fu8_t *data, int len, struct aim_incomingim_ch1_args *args)
 {
+	/* Should this be ASCII -> UNICODE -> Custom */
 	static const fu16_t charsetpri[] = {
-		0x0000, /* ASCII first */
-		0x0003, /* then ISO-8859-1 */
-		0x0002, /* UNICODE as last resort */
+		AIM_IMCHARSET_ASCII, /* ASCII first */
+		AIM_IMCHARSET_CUSTOM, /* then ISO-8859-1 */
+		AIM_IMCHARSET_UNICODE, /* UNICODE as last resort */
 	};
 	static const int charsetpricount = 3;
 	int i;
@@ -1388,11 +1389,11 @@
 			args->charsubset = sec->charsubset;
 
 			/* Set up the simple flags */
-			if (args->charset == 0x0000)
+			if (args->charset == AIM_IMCHARSET_ASCII)
 				; /* ASCII */
-			else if (args->charset == 0x0002)
+			else if (args->charset == AIM_IMCHARSET_UNICODE)
 				args->icbmflags |= AIM_IMFLAGS_UNICODE;
-			else if (args->charset == 0x0003)
+			else if (args->charset == AIM_IMCHARSET_CUSTOM)
 				args->icbmflags |= AIM_IMFLAGS_ISO_8859_1;
 			else if (args->charset == 0xffff)
 				; /* no encoding (yeep!) */
--- a/src/protocols/oscar/oscar.c	Sat Aug 21 20:35:23 2004 +0000
+++ b/src/protocols/oscar/oscar.c	Sat Aug 21 21:53:57 2004 +0000
@@ -3025,16 +3025,67 @@
 	return 0;
 }
 
+static gchar *
+gaim_plugin_oscar_parse_im_part(fu16_t charset, fu16_t charsubset, fu8_t *data, fu16_t datalen)
+{
+	gchar *ret;
+	gsize convlen;
+	GError *err = NULL;
+
+	gaim_debug_misc("oscar", "Parsing IM part, charset=0x%04hx, charsubset=0x%04hx, datalen=%hd\n", charset, charsubset, datalen);
+
+	if ((datalen == 0) || (data == NULL))
+		return NULL;
+
+	switch (charset) {
+		case AIM_IMCHARSET_UNICODE: /* UCS-2BE */
+			ret = g_convert(data, datalen, "UTF-8", "UCS-2BE", NULL, &convlen, &err);
+			if (err != NULL) {
+				gaim_debug_warn("oscar",
+						   "UCS-2BE conversation failed: %s\n", err->message);
+				g_error_free(err);
+				ret = g_strdup(_("(There was an error receiving this message)"));
+			}
+		break;
+
+		case AIM_IMCHARSET_CUSTOM: /* Use the value specified for this account */
+			ret = g_convert(data, datalen, "UTF-8", "ISO-8859-1", NULL, &convlen, &err);
+			if (err != NULL) {
+				gaim_debug_warn("oscar",
+						   "UCS-2BE conversation failed: %s\n", err->message);
+				g_error_free(err);
+				ret = g_strdup(_("(There was an error receiving this message)"));
+			}
+		break;
+
+		case AIM_IMCHARSET_ASCII:
+		default: /* Unknown, hope for valid UTF-8... */
+			if (g_utf8_validate(data, datalen, NULL)) {
+				ret = g_strndup(data, datalen);
+			} else {
+				gaim_debug_warn("oscar",
+						   "Received invalid UTF-8.\n");
+				ret = g_strdup(_("(There was an error receiving this message)"));
+			}
+			break;
+	}
+
+	return ret;
+}
+
 static int incomingim_chan1(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_t *userinfo, struct aim_incomingim_ch1_args *args) {
 	GaimConnection *gc = sess->aux_data;
 	OscarData *od = gc->proto_data;
 	GaimAccount *account = gaim_connection_get_account(gc);
-	gchar *tmp;
 	GaimConvImFlags flags = 0;
-	gsize convlen;
-	GError *err = NULL;
 	struct buddyinfo *bi;
 	const char *iconfile;
+	GString *message;
+	gchar *tmp;
+	aim_mpmsg_section_t *curpart;
+
+	gaim_debug_misc("oscar", "Recived IM from %s with %d parts\n",
+					userinfo->sn, args->mpmsg.numparts);
 
 	bi = g_hash_table_lookup(od->buddyinfo, gaim_normalize(account, userinfo->sn));
 	if (!bi) {
@@ -3088,53 +3139,19 @@
 					   "Can't stat buddy icon file!\n");
 	}
 
-	gaim_debug_misc("oscar",
-			   "Received message from %s with charset %hu %hu\n",
-			   userinfo->sn, args->charset, args->charsubset);
-
-	if (args->icbmflags & AIM_IMFLAGS_UNICODE) {
-		/* This message is marked as UNICODE, so we have to
-		 * convert it to utf-8 before handing it to the gaim core.
-		 * This conversion should *never* fail, if it does it
-		 * means that either the incoming ICBM is corrupted or
-		 * there is something we don't understand about it.
-		 * For the record, AIM Unicode is big-endian UCS-2 */
-
-		gaim_debug_info("oscar", "Received UNICODE IM\n");
-
-		if (!args->msg || !args->msglen)
-			return 1;
-
-		tmp = g_convert(args->msg, args->msglen, "UTF-8", "UCS-2BE", NULL, &convlen, &err);
-		if (err) {
-			gaim_debug_info("oscar",
-					   "Unicode IM conversion: %s\n", err->message);
-			tmp = g_strdup(_("(There was an error receiving this message)"));
-			g_error_free(err);
+	message = g_string_new("");
+	curpart = args->mpmsg.parts;
+	while (curpart != NULL) {
+		tmp = gaim_plugin_oscar_parse_im_part(curpart->charset, curpart->charsubset,
+											curpart->data, curpart->datalen);
+		if (tmp != NULL) {
+			g_string_append(message, tmp);
+			g_free(tmp);
 		}
-	} else {
-		/* This will get executed for both AIM_IMFLAGS_ISO_8859_1 and
-		 * unflagged messages, which are ASCII.  That's OK because
-		 * ASCII is a strict subset of ISO-8859-1; this should
-		 * help with compatibility with old, broken versions of
-		 * gaim (everything before 0.60) and other broken clients
-		 * that will happily send ISO-8859-1 without marking it as
-		 * such */
-		if (args->icbmflags & AIM_IMFLAGS_ISO_8859_1)
-			gaim_debug_info("oscar",
-					   "Received ISO-8859-1 IM\n");
-
-		if (!args->msg || !args->msglen)
-			return 1;
-
-		tmp = g_convert(args->msg, args->msglen, "UTF-8", "ISO-8859-1", NULL, &convlen, &err);
-		if (err) {
-			gaim_debug_info("oscar",
-					   "ISO-8859-1 IM conversion: %s\n", err->message);
-			tmp = g_strdup(_("(There was an error receiving this message)"));
-			g_error_free(err);
-		}
-	}
+
+		curpart = curpart->next;
+	}
+	tmp = g_string_free(message, FALSE);
 
 	/*
 	 * If the message is being received by an ICQ user then escape any HTML,
@@ -5281,7 +5298,7 @@
 		args.flags |= oscar_encoding_check(tmpmsg);
 		if (args.flags & AIM_IMFLAGS_UNICODE) {
 			gaim_debug_info("oscar", "Sending Unicode IM\n");
-			args.charset = 0x0002;
+			args.charset = AIM_IMCHARSET_UNICODE;
 			args.charsubset = 0x0000;
 			args.msg = g_convert(tmpmsg, len, "UCS-2BE", "UTF-8", NULL, &len, &err);
 			if (err) {
@@ -5296,7 +5313,7 @@
 		} else if (args.flags & AIM_IMFLAGS_ISO_8859_1) {
 			gaim_debug_info("oscar",
 					   "Sending ISO-8859-1 IM\n");
-			args.charset = 0x0003;
+			args.charset = AIM_IMCHARSET_CUSTOM;
 			args.charsubset = 0x0000;
 			args.msg = g_convert(tmpmsg, len, "ISO-8859-1", "UTF-8", NULL, &len, &err);
 			if (err) {