# HG changeset patch # User Sadrul Habib Chowdhury # Date 1206998637 0 # Node ID 981a0bfc3d9d4274cd036c322ba8cead82a6cfce # Parent b30f54a720313d29acbea9bc3a9138c8bf25d997 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. diff -r b30f54a72031 -r 981a0bfc3d9d libpurple/protocols/msnp9/msn.c --- 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); } diff -r b30f54a72031 -r 981a0bfc3d9d libpurple/protocols/msnp9/object.c --- 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) { diff -r b30f54a72031 -r 981a0bfc3d9d libpurple/protocols/msnp9/object.h --- 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. diff -r b30f54a72031 -r 981a0bfc3d9d libpurple/protocols/msnp9/slp.c --- 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")) { diff -r b30f54a72031 -r 981a0bfc3d9d libpurple/protocols/msnp9/user.c --- 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