changeset 27292:a6d84d9de605

Add support for receiving handwritten (Ink) messages from MSN buddies. Based on patch from notak and galt, but using imgstore instead of a custom smiley (like AIM DirectIM), and with better error checking. References #393.
author Elliott Sales de Andrade <qulogic@pidgin.im>
date Mon, 06 Jul 2009 04:37:06 +0000
parents 3a0552df3379
children 14131ba5a07c
files ChangeLog libpurple/protocols/msn/msg.c libpurple/protocols/msn/msg.h libpurple/protocols/msn/msn.h libpurple/protocols/msn/slpcall.c libpurple/protocols/msn/switchboard.c libpurple/protocols/msn/switchboard.h
diffstat 7 files changed, 113 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Sun Jul 05 05:41:00 2009 +0000
+++ b/ChangeLog	Mon Jul 06 04:37:06 2009 +0000
@@ -24,6 +24,7 @@
 	  PURPLE_GNUTLS_DEBUG environment variable, which is an integer between
 	  0 and 9 (higher is more verbose). Higher values may reveal sensitive
 	  information.
+	* Add support for receiving handwritten (ink) messages on MSN.
 
 	Gadu-Gadu:
 	* Accounts can specify a server to which to connect.
--- a/libpurple/protocols/msn/msg.c	Sun Jul 05 05:41:00 2009 +0000
+++ b/libpurple/protocols/msn/msg.c	Mon Jul 06 04:37:06 2009 +0000
@@ -1048,3 +1048,14 @@
 	g_hash_table_destroy(body);
 }
 
+/* Only called from chats. Handwritten messages for IMs come as a SLP message */
+void
+msn_handwritten_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
+{
+	const char *body;
+	size_t body_len;
+
+	body = msn_message_get_bin_data(msg, &body_len);
+	msn_switchboard_show_ink(cmdproc->data, msg->remote_user, body);
+}
+
--- a/libpurple/protocols/msn/msg.h	Sun Jul 05 05:41:00 2009 +0000
+++ b/libpurple/protocols/msn/msg.h	Mon Jul 06 04:37:06 2009 +0000
@@ -345,4 +345,6 @@
 
 void msn_datacast_msg(MsnCmdProc *cmdproc, MsnMessage *msg);
 
+void msn_handwritten_msg(MsnCmdProc *cmdproc, MsnMessage *msg);
+
 #endif /* _MSN_MSG_H_ */
--- a/libpurple/protocols/msn/msn.h	Sun Jul 05 05:41:00 2009 +0000
+++ b/libpurple/protocols/msn/msn.h	Mon Jul 06 04:37:06 2009 +0000
@@ -138,7 +138,7 @@
 } MsnClientVerId;
 
 #define MSN_CLIENT_ID_VERSION      MSN_CLIENT_VER_7_0
-#define MSN_CLIENT_ID_CAPABILITIES MSN_CLIENT_CAP_PACKET
+#define MSN_CLIENT_ID_CAPABILITIES (MSN_CLIENT_CAP_PACKET|MSN_CLIENT_CAP_INK_GIF)
 
 #define MSN_CLIENT_ID \
 	((MSN_CLIENT_ID_VERSION    << 24) | \
--- a/libpurple/protocols/msn/slpcall.c	Sun Jul 05 05:41:00 2009 +0000
+++ b/libpurple/protocols/msn/slpcall.c	Mon Jul 06 04:37:06 2009 +0000
@@ -210,8 +210,51 @@
 	{
 		char *body_str;
 
-		body_str = g_strndup((const char *)body, body_len);
-		slpcall = msn_slp_sip_recv(slplink, body_str);
+		if (slpmsg->session_id == 64)
+		{
+			/* This is for handwritten messages (Ink) */
+			GError *error;
+			glong items_read, items_written;
+
+			body_str = g_utf16_to_utf8((gunichar2 *)body, body_len / 2,
+			                           &items_read, &items_written, &error);
+			body_len -= items_read * 2 + 2;
+			body += items_read * 2 + 2;
+			if (body_str == NULL
+			 || body_len <= 0
+			 || strstr(body_str, "image/gif") == NULL)
+			{
+				if (error != NULL)
+					purple_debug_error("msn",
+					                   "Unable to convert Ink header from UTF-16 to UTF-8: %s\n",
+					                   error->message);
+				else
+					purple_debug_error("msn",
+					                   "Received Ink in unknown format\n");
+				g_free(body_str);
+				return NULL;
+			}
+			g_free(body_str);
+
+			body_str = g_utf16_to_utf8((gunichar2 *)body, body_len / 2,
+			                           &items_read, &items_written, &error);
+			if (!body_str)
+			{
+				purple_debug_error("msn",
+				                   "Unable to convert Ink body from UTF-16 to UTF-8: %s\n",
+				                   error->message);
+				return NULL;
+			}
+
+			msn_switchboard_show_ink(slpmsg->slplink->swboard,
+			                         slplink->remote_user,
+			                         body_str);
+		}
+		else
+		{
+			body_str = g_strndup((const char *)body, body_len);
+			slpcall = msn_slp_sip_recv(slplink, body_str);
+		}
 		g_free(body_str);
 	}
 	else if (slpmsg->flags == 0x20 ||
--- a/libpurple/protocols/msn/switchboard.c	Sun Jul 05 05:41:00 2009 +0000
+++ b/libpurple/protocols/msn/switchboard.c	Mon Jul 06 04:37:06 2009 +0000
@@ -905,6 +905,47 @@
 #endif
 }
 
+void
+msn_switchboard_show_ink(MsnSwitchBoard *swboard, const char *passport,
+                         const char *data)
+{
+	PurpleConnection *gc;
+	guchar *image_data;
+	size_t image_len;
+	int imgid;
+	char *image_msg;
+
+	if (!purple_str_has_prefix(data, "base64:"))
+	{
+		purple_debug_error("msn", "Ignoring Ink not in Base64 format.\n");
+		return;
+	}
+
+	gc = purple_account_get_connection(swboard->session->account);
+
+	data += sizeof("base64:") - 1;
+	image_data = purple_base64_decode(data, &image_len);
+	if (!image_data || !image_len) 
+	{
+		purple_debug_error("msn", "Unable to decode Ink from Base64 format.\n");
+		return;
+	}
+
+	imgid = purple_imgstore_add_with_id(image_data, image_len, NULL);
+	image_msg = g_strdup_printf("<IMG ID=%d/>", imgid);
+
+	if (swboard->current_users > 1 ||
+		((swboard->conv != NULL) &&
+		 purple_conversation_get_type(swboard->conv) == PURPLE_CONV_TYPE_CHAT))
+		serv_got_chat_in(gc, swboard->chat_id, passport, 0, image_msg,
+						 time(NULL));
+	else
+		serv_got_im(gc, passport, image_msg, 0, time(NULL));
+
+	purple_imgstore_unref_by_id(imgid);
+	g_free(image_msg);
+}
+
 /**************************************************************************
  * Connect stuff
  **************************************************************************/
@@ -1239,6 +1280,8 @@
 						   msn_datacast_msg);
 	msn_table_add_msg_type(cbs_table, "text/x-msmsgsinvite",
 						   msn_invite_msg);
+	msn_table_add_msg_type(cbs_table, "image/gif",
+						   msn_handwritten_msg);
 }
 
 void
--- a/libpurple/protocols/msn/switchboard.h	Sun Jul 05 05:41:00 2009 +0000
+++ b/libpurple/protocols/msn/switchboard.h	Mon Jul 06 04:37:06 2009 +0000
@@ -280,4 +280,14 @@
  */
 void msn_invite_msg(MsnCmdProc *cmdproc, MsnMessage *msg);
 
+/**
+ * Shows an ink message from this switchboard.
+ *
+ * @param swboard  The switchboard.
+ * @param passport The user that sent the ink.
+ * @param data     The ink data.
+ */
+void msn_switchboard_show_ink(MsnSwitchBoard *swboard, const char *passport,
+                              const char *data);
+
 #endif /* _MSN_SWITCHBOARD_H_ */