changeset 23123:981a0bfc3d9d

Update patch to add support for sending custom smileys in msnp9. I included some fixes from the msnp14 patch that were not corrected in the patch, and also the fix for setting buddyicons. References #1187.
author Sadrul Habib Chowdhury <imadil@gmail.com>
date Mon, 31 Mar 2008 21:23:57 +0000
parents b30f54a72031
children 2f4b10ee752b
files libpurple/protocols/msnp9/msn.c libpurple/protocols/msnp9/object.c libpurple/protocols/msnp9/object.h libpurple/protocols/msnp9/slp.c libpurple/protocols/msnp9/user.c
diffstat 5 files changed, 226 insertions(+), 64 deletions(-) [+]
line wrap: on
line diff
--- a/libpurple/protocols/msnp9/msn.c	Mon Mar 31 21:04:51 2008 +0000
+++ b/libpurple/protocols/msnp9/msn.c	Mon Mar 31 21:23:57 2008 +0000
@@ -33,6 +33,7 @@
 #include "pluginpref.h"
 #include "prefs.h"
 #include "session.h"
+#include "smiley.h"
 #include "state.h"
 #include "util.h"
 #include "cmds.h"
@@ -83,6 +84,12 @@
 	time_t when;
 } MsnIMData;
 
+typedef struct
+{
+	char *smile;
+	MsnObject *obj;
+} MsnEmoticon;
+
 static const char *
 msn_normalize(const PurpleAccount *account, const char *str)
 {
@@ -116,6 +123,7 @@
 		return FALSE;
 
 	msn_switchboard_send_msg(swboard, msg, TRUE);
+	msn_message_destroy(msg);
 
 	return TRUE;
 }
@@ -796,6 +804,97 @@
 	return FALSE;
 }
 
+static GString*
+msn_msg_emoticon_add(GString *current, MsnEmoticon *emoticon)
+{
+	MsnObject *obj;
+	char *strobj;
+
+	if (emoticon == NULL)
+		return current;
+
+	obj = emoticon->obj;
+
+	if (!obj)
+		return current;
+
+	strobj = msn_object_to_string(obj);
+
+	if (current)
+		g_string_append_printf(current, "\t%s\t%s",
+				emoticon->smile, strobj);
+	else {
+		current = g_string_new("");
+		g_string_printf(current,"%s\t%s",
+					emoticon->smile, strobj);
+	}
+
+	g_free(strobj);
+
+	return current;
+}
+
+static void
+msn_send_emoticons(MsnSwitchBoard *swboard, GString *body)
+{
+	MsnMessage *msg;
+
+	g_return_if_fail(body != NULL);
+
+	msg = msn_message_new(MSN_MSG_SLP);
+	msn_message_set_content_type(msg, "text/x-mms-emoticon");
+	msn_message_set_flag(msg, 'N');
+	msn_message_set_bin_data(msg, body->str, body->len);
+
+	msn_switchboard_send_msg(swboard, msg, TRUE);
+	msn_message_destroy(msg);
+}
+
+static void msn_emoticon_destroy(MsnEmoticon *emoticon)
+{
+	if (emoticon->obj)
+		msn_object_destroy(emoticon->obj);
+	g_free(emoticon->smile);
+	g_free(emoticon);
+}
+
+static GSList* msn_msg_grab_emoticons(const char *msg, const char *username)
+{
+	GSList *list;
+	GList *smileys;
+	PurpleSmiley *smiley;
+	PurpleStoredImage *img;
+	char *ptr;
+	MsnEmoticon *emoticon;
+	int length;
+
+	list = NULL;
+	smileys = purple_smileys_get_all();
+	length = strlen(msg);
+
+	for (; smileys; smileys = g_list_delete_link(smileys, smileys)) {
+		smiley = (PurpleSmiley*)smileys->data;
+
+		ptr = g_strstr_len(msg, length, purple_smiley_get_shortcut(smiley));
+
+		if (!ptr)
+			continue;
+
+		img = purple_smiley_get_stored_image(smiley);
+
+		emoticon = g_new0(MsnEmoticon, 1);
+		emoticon->smile = g_strdup(purple_smiley_get_shortcut(smiley));
+		emoticon->obj = msn_object_new_from_image(img,
+				purple_imgstore_get_filename(img),
+				username, MSN_OBJECT_EMOTICON);
+
+		purple_imgstore_unref(img);
+		list = g_slist_prepend(list, emoticon);
+	}
+
+	return list;
+}
+
 static int
 msn_send_im(PurpleConnection *gc, const char *who, const char *message,
 			PurpleMessageFlags flags)
@@ -805,8 +904,10 @@
 	MsnMessage *msg;
 	char *msgformat;
 	char *msgtext;
+	const char *username;
 
 	account = purple_connection_get_account(gc);
+	username = purple_account_get_username(account);
 
 	if (buddy) {
 		PurplePresence *p = purple_buddy_get_presence(buddy);
@@ -834,13 +935,29 @@
 	g_free(msgformat);
 	g_free(msgtext);
 
-	if (g_ascii_strcasecmp(who, purple_account_get_username(account)))
+	if (g_ascii_strcasecmp(who, username))
 	{
 		MsnSession *session;
 		MsnSwitchBoard *swboard;
+		MsnEmoticon *smile;
+		GSList *smileys;
+		GString *emoticons = NULL;
 
 		session = gc->proto_data;
 		swboard = msn_session_get_swboard(session, who, MSN_SB_FLAG_IM);
+		smileys = msn_msg_grab_emoticons(message, username);
+
+		while (smileys) {
+			smile = (MsnEmoticon*)smileys->data;
+			emoticons = msn_msg_emoticon_add(emoticons,smile);
+			msn_emoticon_destroy(smile);
+			smileys = g_slist_delete_link(smileys, smileys);
+		}
+
+		if (emoticons) {
+			msn_send_emoticons(swboard, emoticons);
+			g_string_free(emoticons, TRUE);
+		}
 
 		msn_switchboard_send_msg(swboard, msg, TRUE);
 	}
--- a/libpurple/protocols/msnp9/object.c	Mon Mar 31 21:04:51 2008 +0000
+++ b/libpurple/protocols/msnp9/object.c	Mon Mar 31 21:23:57 2008 +0000
@@ -23,6 +23,10 @@
  */
 #include "object.h"
 #include "debug.h"
+/* Sha1 stuff */
+#include "cipher.h"
+/* Base64 stuff */
+#include "util.h"
 
 #define GET_STRING_TAG(field, id) \
 	if ((tag = strstr(str, id "=\"")) != NULL) \
@@ -104,6 +108,74 @@
 	return obj;
 }
 
+MsnObject*
+msn_object_new_from_image(PurpleStoredImage *img, const char *location,
+		const char *creator, MsnObjectType type)
+{
+	MsnObject *msnobj;
+
+	PurpleCipherContext *ctx;
+	char *buf;
+	gconstpointer data;
+	size_t size;
+	char *base64;
+	unsigned char digest[20];
+
+	msnobj = NULL;
+
+	if (img == NULL)
+		return msnobj;
+
+	size = purple_imgstore_get_size(img);
+	data = purple_imgstore_get_data(img);
+
+	/* New object */
+	msnobj = msn_object_new();
+	msn_object_set_local(msnobj);
+	msn_object_set_type(msnobj, type);
+	msn_object_set_location(msnobj, location);
+	msn_object_set_creator(msnobj, creator);
+
+	msn_object_set_image(msnobj, img);
+
+	/* Compute the SHA1D field. */
+	memset(digest, 0, sizeof(digest));
+
+	ctx = purple_cipher_context_new_by_name("sha1", NULL);
+	purple_cipher_context_append(ctx, data, size);
+	purple_cipher_context_digest(ctx, sizeof(digest), digest, NULL);
+
+	base64 = purple_base64_encode(digest, sizeof(digest));
+	msn_object_set_sha1d(msnobj, base64);
+	g_free(base64);
+
+	msn_object_set_size(msnobj, size);
+
+	/* Compute the SHA1C field. */
+	buf = g_strdup_printf(
+		"Creator%sSize%dType%dLocation%sFriendly%sSHA1D%s",
+		msn_object_get_creator(msnobj),
+		msn_object_get_size(msnobj),
+		msn_object_get_type(msnobj),
+		msn_object_get_location(msnobj),
+		msn_object_get_friendly(msnobj),
+		msn_object_get_sha1d(msnobj));
+
+	memset(digest, 0, sizeof(digest));
+
+	purple_cipher_context_reset(ctx, NULL);
+	purple_cipher_context_append(ctx, (const guchar *)buf, strlen(buf));
+	purple_cipher_context_digest(ctx, sizeof(digest), digest, NULL);
+	purple_cipher_context_destroy(ctx);
+	g_free(buf);
+
+	base64 = purple_base64_encode(digest, sizeof(digest));
+	msn_object_set_sha1c(msnobj, base64);
+	g_free(base64);
+
+	return msnobj;
+}
+
 void
 msn_object_destroy(MsnObject *obj)
 {
--- a/libpurple/protocols/msnp9/object.h	Mon Mar 31 21:04:51 2008 +0000
+++ b/libpurple/protocols/msnp9/object.h	Mon Mar 31 21:23:57 2008 +0000
@@ -71,6 +71,19 @@
 MsnObject *msn_object_new_from_string(const char *str);
 
 /**
+ * Creates a MsnObject structure from a stored image
+ *
+ * @param img		The image associated to object
+ * @param location	The object location as stored in MsnObject
+ * @param creator	The creator of the object
+ * @param type		The type of the object
+ *
+ * @return A new MsnObject structure
+ */
+MsnObject *msn_object_new_from_image(PurpleStoredImage *img,
+		const char *location, const char *creator, MsnObjectType type);
+
+/**
  * Destroys an MsnObject structure.
  *
  * @param obj The object structure.
--- a/libpurple/protocols/msnp9/slp.c	Mon Mar 31 21:04:51 2008 +0000
+++ b/libpurple/protocols/msnp9/slp.c	Mon Mar 31 21:23:57 2008 +0000
@@ -31,6 +31,8 @@
 #include "user.h"
 #include "switchboard.h"
 
+#include "smiley.h"
+
 /* ms to delay between sending buddy icon requests to the server. */
 #define BUDDY_ICON_DELAY 20000
 
@@ -276,23 +278,32 @@
 		type = msn_object_get_type(obj);
 		g_free(msnobj_data);
 
-		if (!(type == MSN_OBJECT_USERTILE))
+		if ((type != MSN_OBJECT_USERTILE) && (type != MSN_OBJECT_EMOTICON))
 		{
 			purple_debug_error("msn", "Wrong object?\n");
 			msn_object_destroy(obj);
 			g_return_if_reached();
 		}
 
-		img = msn_object_get_image(obj);
+		if (type == MSN_OBJECT_EMOTICON) {
+			char *path;
+			path = g_build_filename(purple_smileys_get_storing_dir(),
+					obj->location, NULL);
+			img = purple_imgstore_new_from_file(path);
+			g_free(path);
+		} else {
+			img = msn_object_get_image(obj);
+			if (img)
+				purple_imgstore_ref(img);
+		}
+		msn_object_destroy(obj);
+
 		if (img == NULL)
 		{
 			purple_debug_error("msn", "Wrong object.\n");
-			msn_object_destroy(obj);
 			g_return_if_reached();
 		}
 
-		msn_object_destroy(obj);
-
 		slpsession = msn_slplink_find_slp_session(slplink,
 												  slpcall->session_id);
 
@@ -317,6 +328,7 @@
 #endif
 		msn_slpmsg_set_image(slpmsg, img);
 		msn_slplink_queue_slpmsg(slplink, slpmsg);
+		purple_imgstore_unref(img);
 	}
 	else if (!strcmp(euf_guid, "5D3E02AB-6190-11D3-BBBB-00C04F795683"))
 	{
--- a/libpurple/protocols/msnp9/user.c	Mon Mar 31 21:04:51 2008 +0000
+++ b/libpurple/protocols/msnp9/user.c	Mon Mar 31 21:23:57 2008 +0000
@@ -153,69 +153,17 @@
 void
 msn_user_set_buddy_icon(MsnUser *user, PurpleStoredImage *img)
 {
-	MsnObject *msnobj = msn_user_get_object(user);
+	MsnObject *msnobj = NULL;
 
 	g_return_if_fail(user != NULL);
 
-	if (img == NULL)
-		msn_user_set_object(user, NULL);
-	else
-	{
-		PurpleCipherContext *ctx;
-		char *buf;
-		gconstpointer data = purple_imgstore_get_data(img);
-		size_t size = purple_imgstore_get_size(img);
-		char *base64;
-		unsigned char digest[20];
-
-		if (msnobj == NULL)
-		{
-			msnobj = msn_object_new();
-			msn_object_set_local(msnobj);
-			msn_object_set_type(msnobj, MSN_OBJECT_USERTILE);
-			msn_object_set_location(msnobj, "TFR2C2.tmp");
-			msn_object_set_creator(msnobj, msn_user_get_passport(user));
-
-			msn_user_set_object(user, msnobj);
-		}
-
-		msn_object_set_image(msnobj, img);
-
-		/* Compute the SHA1D field. */
-		memset(digest, 0, sizeof(digest));
+	msnobj = msn_object_new_from_image(img, "TFR2C2.tmp",
+			user->passport, MSN_OBJECT_USERTILE);
 
-		ctx = purple_cipher_context_new_by_name("sha1", NULL);
-		purple_cipher_context_append(ctx, data, size);
-		purple_cipher_context_digest(ctx, sizeof(digest), digest, NULL);
-
-		base64 = purple_base64_encode(digest, sizeof(digest));
-		msn_object_set_sha1d(msnobj, base64);
-		g_free(base64);
-
-		msn_object_set_size(msnobj, size);
+	if(!msnobj)
+		purple_debug_error("msn", "Unable to open buddy icon from %s!\n", user->passport);
 
-		/* Compute the SHA1C field. */
-		buf = g_strdup_printf(
-			"Creator%sSize%dType%dLocation%sFriendly%sSHA1D%s",
-			msn_object_get_creator(msnobj),
-			msn_object_get_size(msnobj),
-			msn_object_get_type(msnobj),
-			msn_object_get_location(msnobj),
-			msn_object_get_friendly(msnobj),
-			msn_object_get_sha1d(msnobj));
-
-		memset(digest, 0, sizeof(digest));
-
-		purple_cipher_context_reset(ctx, NULL);
-		purple_cipher_context_append(ctx, (const guchar *)buf, strlen(buf));
-		purple_cipher_context_digest(ctx, sizeof(digest), digest, NULL);
-		purple_cipher_context_destroy(ctx);
-		g_free(buf);
-
-		base64 = purple_base64_encode(digest, sizeof(digest));
-		msn_object_set_sha1c(msnobj, base64);
-		g_free(base64);
-	}
+	msn_user_set_object(user, msnobj);
 }
 
 void