# HG changeset patch # User Marcus Lundblad # Date 1220651709 0 # Node ID 305fac6af8f99be18116695f186f157d105a0fa4 # Parent 8997acd7d143b62457061b5b2b22451a7469289d Updated to use latest spec. in XEP-0231 New namespace. Cache data globally in a running instance based on CID. Set the PNG compression level param when saving a custom smiley from GTKIMHTML. diff -r 8997acd7d143 -r 305fac6af8f9 libpurple/protocols/jabber/chat.c --- a/libpurple/protocols/jabber/chat.c Thu Sep 04 22:18:58 2008 +0000 +++ b/libpurple/protocols/jabber/chat.c Fri Sep 05 21:55:09 2008 +0000 @@ -685,9 +685,7 @@ xmlnode_insert_data(status, msg, -1); } jabber_send(chat->js, presence); - - jabber_data_delete_associated_with_conv(chat->conv); - + xmlnode_free(presence); g_free(room_jid); } diff -r 8997acd7d143 -r 305fac6af8f9 libpurple/protocols/jabber/data.c --- a/libpurple/protocols/jabber/data.c Thu Sep 04 22:18:58 2008 +0000 +++ b/libpurple/protocols/jabber/data.c Fri Sep 05 21:55:09 2008 +0000 @@ -25,43 +25,23 @@ #include "conversation.h" #include "iq.h" -/* hash table to store locally supplied data objects, by conversation and - alt text (smiley shortcut) */ -static GHashTable *local_datas_by_alt = NULL; - -/* hash table to store locally supplied data objects, by content id */ -static GHashTable *local_datas_by_cid = NULL; - -/* remote supplied data objects by content id */ -static GHashTable *remote_datas_by_cid = NULL; - - -void -jabber_data_init(void) -{ - /* setup hash tables for storing data instances here */ - purple_debug_info("jabber", "Setting up data handling\n"); - - local_datas_by_alt = g_hash_table_new(NULL, NULL); - local_datas_by_cid = g_hash_table_new(NULL, NULL); - remote_datas_by_cid = g_hash_table_new(NULL, NULL); -} +static GHashTable *local_data_by_alt = NULL; +static GHashTable *local_data_by_cid = NULL; +static GHashTable *remote_data_by_cid = NULL; JabberData * jabber_data_create_from_data(gconstpointer rawdata, gsize size, const char *type, - const char *alt) + JabberStream *js) { JabberData *data = g_new0(JabberData, 1); gchar *checksum = purple_util_get_image_checksum(rawdata, size); gchar cid[256]; - /* is there some better way to generate a content ID? */ - g_snprintf(cid, sizeof(cid), "%s@%s", checksum, g_get_host_name()); + g_snprintf(cid, sizeof(cid), "sha1+%s@bob.xmpp.org", checksum); g_free(checksum); data->cid = g_strdup(cid); data->type = g_strdup(type); - data->alt = g_strdup(alt); data->size = size; data->data = g_memdup(rawdata, size); @@ -91,8 +71,7 @@ data->cid = g_strdup(xmlnode_get_attrib(tag, "cid")); data->type = g_strdup(xmlnode_get_attrib(tag, "type")); - data->alt = g_strdup(xmlnode_get_attrib(tag, "alt")); - + raw_data = xmlnode_get_data(tag); data->data = purple_base64_decode(raw_data, &size); data->size = size; @@ -107,7 +86,6 @@ jabber_data_delete(JabberData *data) { g_free(data->cid); - g_free(data->alt); g_free(data->type); g_free(data->data); g_free(data); @@ -119,11 +97,6 @@ return data->cid; } -const char * -jabber_data_get_alt(const JabberData *data) -{ - return data->alt; -} const char * jabber_data_get_type(const JabberData *data) @@ -150,7 +123,6 @@ char *base64data = purple_base64_encode(data->data, data->size); xmlnode_set_namespace(tag, XEP_0231_NAMESPACE); - xmlnode_set_attrib(tag, "alt", data->alt); xmlnode_set_attrib(tag, "cid", data->cid); xmlnode_set_attrib(tag, "type", data->type); @@ -162,12 +134,12 @@ } xmlnode * -jabber_data_get_xhtml_im(const JabberData *data) +jabber_data_get_xhtml_im(const JabberData *data, const gchar *alt) { xmlnode *img = xmlnode_new("img"); char src[128]; - xmlnode_set_attrib(img, "alt", data->alt); + xmlnode_set_attrib(img, "alt", alt); g_snprintf(src, sizeof(src), "cid:%s", data->cid); xmlnode_set_attrib(img, "src", src); @@ -186,107 +158,36 @@ } const JabberData * -jabber_data_find_local_by_alt(const PurpleConversation *conv, const char *alt) +jabber_data_find_local_by_alt(const gchar *alt) { - GHashTable *local_datas = g_hash_table_lookup(local_datas_by_alt, conv); - - if (local_datas) { - return g_hash_table_lookup(local_datas, alt); - } else { - return NULL; - } -} - - -const JabberData * -jabber_data_find_local_by_cid(const PurpleConversation *conv, const char *cid) -{ - GHashTable *local_datas = g_hash_table_lookup(local_datas_by_cid, conv); - - if (local_datas) { - return g_hash_table_lookup(local_datas, cid); - } else { - return NULL; - } + return g_hash_table_lookup(local_data_by_alt, alt); } const JabberData * -jabber_data_find_remote_by_cid(const PurpleConversation *conv, const char *cid) +jabber_data_find_local_by_cid(const gchar *cid) { - GHashTable *remote_datas = g_hash_table_lookup(remote_datas_by_cid, conv); + return g_hash_table_lookup(local_data_by_cid, cid); +} - if (remote_datas) { - return g_hash_table_lookup(remote_datas, cid); - } else { - return NULL; - } +const JabberData * +jabber_data_find_remote_by_cid(const gchar *cid) +{ + return g_hash_table_lookup(remote_data_by_cid, cid); } void -jabber_data_associate_local_with_conv(JabberData *data, PurpleConversation *conv) +jabber_data_associate_local(JabberData *data, const gchar *alt) { - GHashTable *datas_by_alt = g_hash_table_lookup(local_datas_by_alt, conv); - GHashTable *datas_by_cid = g_hash_table_lookup(local_datas_by_cid, conv); - - if (!datas_by_alt) { - datas_by_alt = g_hash_table_new(g_str_hash, g_str_equal); - g_hash_table_insert(local_datas_by_alt, conv, datas_by_alt); - } - - if (!datas_by_cid) { - datas_by_cid = g_hash_table_new(g_str_hash, g_str_equal); - g_hash_table_insert(local_datas_by_cid, conv, datas_by_cid); - } - - g_hash_table_insert(datas_by_alt, g_strdup(jabber_data_get_alt(data)), data); - g_hash_table_insert(datas_by_cid, g_strdup(jabber_data_get_cid(data)), data); + g_hash_table_insert(local_data_by_alt, g_strdup(alt), data); + g_hash_table_insert(local_data_by_cid, g_strdup(jabber_data_get_cid(data)), + data); } void -jabber_data_associate_remote_with_conv(JabberData *data, PurpleConversation *conv) -{ - GHashTable *datas_by_cid = g_hash_table_lookup(remote_datas_by_cid, conv); - - if (!datas_by_cid) { - datas_by_cid = g_hash_table_new(g_str_hash, g_str_equal); - g_hash_table_insert(remote_datas_by_cid, conv, datas_by_cid); - } - - g_hash_table_insert(datas_by_cid, g_strdup(jabber_data_get_cid(data)), data); -} - -static void -jabber_data_delete_from_hash_table(gpointer key, gpointer value, - gpointer user_data) +jabber_data_associate_remote(JabberData *data) { - JabberData *data = (JabberData *) value; - jabber_data_delete(data); - g_free(key); -} - -void -jabber_data_delete_associated_with_conv(PurpleConversation *conv) -{ - GHashTable *local_datas = g_hash_table_lookup(local_datas_by_cid, conv); - GHashTable *remote_datas = g_hash_table_lookup(remote_datas_by_cid, conv); - GHashTable *local_datas_alt = g_hash_table_lookup(local_datas_by_alt, conv); - - if (local_datas) { - g_hash_table_foreach(local_datas, jabber_data_delete_from_hash_table, - NULL); - g_hash_table_destroy(local_datas); - g_hash_table_remove(local_datas_by_cid, conv); - } - if (remote_datas) { - g_hash_table_foreach(remote_datas, jabber_data_delete_from_hash_table, - NULL); - g_hash_table_destroy(remote_datas); - g_hash_table_remove(remote_datas_by_cid, conv); - } - if (local_datas_alt) { - g_hash_table_destroy(local_datas_alt); - g_hash_table_remove(local_datas_by_alt, conv); - } + g_hash_table_insert(remote_data_by_cid, g_strdup(jabber_data_get_cid(data)), + data); } void @@ -294,15 +195,11 @@ { JabberIq *result = NULL; const char *who = xmlnode_get_attrib(packet, "from"); - const PurpleConnection *gc = js->gc; - const PurpleAccount *account = purple_connection_get_account(gc); - const PurpleConversation *conv = - purple_find_conversation_with_account(PURPLE_CONV_TYPE_ANY, who, account); xmlnode *data_node = xmlnode_get_child(packet, "data"); const JabberData *data = - jabber_data_find_local_by_cid(conv, xmlnode_get_attrib(data_node, "cid")); + jabber_data_find_local_by_cid(xmlnode_get_attrib(data_node, "cid")); - if (!conv || !data) { + if (!data) { xmlnode *item_not_found = xmlnode_new("item-not-found"); result = jabber_iq_new(js, JABBER_IQ_ERROR); @@ -318,3 +215,24 @@ } jabber_iq_send(result); } + +void +jabber_data_init(void) +{ + purple_debug_info("jabber", "creating hash tables for data objects\n"); + local_data_by_alt = g_hash_table_new_full(g_str_hash, g_str_equal, + g_free, NULL); + local_data_by_cid = g_hash_table_new_full(g_str_hash, g_str_equal, + g_free, jabber_data_delete); + remote_data_by_cid = g_hash_table_new_full(g_str_hash, g_str_equal, + g_free, jabber_data_delete); +} + +void +jabber_data_uninit(void) +{ + purple_debug_info("jabber", "destroying hash tables for data objects\n"); + g_hash_table_destroy(local_data_by_alt); + g_hash_table_destroy(local_data_by_cid); + g_hash_table_destroy(remote_data_by_cid); +} diff -r 8997acd7d143 -r 305fac6af8f9 libpurple/protocols/jabber/data.h --- a/libpurple/protocols/jabber/data.h Thu Sep 04 22:18:58 2008 +0000 +++ b/libpurple/protocols/jabber/data.h Fri Sep 05 21:55:09 2008 +0000 @@ -21,24 +21,20 @@ #include "conversation.h" #include "jabber.h" -#define XEP_0231_NAMESPACE "urn:xmpp:tmp:data-element" -#define XEP_0231_IB_IMAGE_NAMESPACE "urn:xmpp:tmp:data-element:inband-image" +#define XEP_0231_NAMESPACE "urn:xmpp:bob" #include typedef struct { char *cid; - char *alt; char *type; gsize size; gpointer data; } JabberData; -void jabber_data_init(void); - /* creates a JabberData instance from raw data */ JabberData *jabber_data_create_from_data(gconstpointer data, gsize size, - const char *type, const char *alt); + const char *type, JabberStream *js); /* create a JabberData instance from an XML "data" element (as defined by XEP 0231 */ @@ -47,7 +43,6 @@ void jabber_data_delete(JabberData *data); const char *jabber_data_get_cid(const JabberData *data); -const char *jabber_data_get_alt(const JabberData *data); const char *jabber_data_get_type(const JabberData *data); gsize jabber_data_get_size(const JabberData *data); @@ -57,27 +52,39 @@ xmlnode *jabber_data_get_xml_definition(const JabberData *data); /* returns an XHTML-IM "img" tag given a data instance */ -xmlnode *jabber_data_get_xhtml_im(const JabberData *data); +xmlnode *jabber_data_get_xhtml_im(const JabberData *data, const gchar *alt); /* returns a data request element (to be included in an iq stanza) for requesting data */ xmlnode *jabber_data_get_xml_request(const gchar *cid); /* lookup functions */ -const JabberData *jabber_data_find_local_by_alt(const PurpleConversation *conv, +const JabberData *jabber_data_find_local_by_alt(const gchar *alt); +const JabberData *jabber_data_find_local_by_cid(const gchar *cid); +const JabberData *jabber_data_find_remote_by_cid(const gchar *cid); +/* +const JabberData *jabber_data_find_local_by_alt(PurpleConversation *conv, const char *alt); -const JabberData *jabber_data_find_local_by_cid(const PurpleConversation *conv, +const JabberData *jabber_data_find_local_by_cid(PurpleConversation *conv, const char *cid); -const JabberData *jabber_data_find_remote_by_cid(const PurpleConversation *conv, +const JabberData *jabber_data_find_remote_by_cid(PurpleConversation *conv, const char *cid); - -/* associate data objects with a conversation */ -void jabber_data_associate_local_with_conv(JabberData *data, PurpleConversation *conv); +*/ + +/* store data objects */ +void jabber_data_associate_local(JabberData *data, const gchar *alt); +void jabber_data_associate_remote(JabberData *data); +/* +void jabber_data_associate_local_with_conv(JabberData *data, PurpleConversation *conv, + const gchar *alt); void jabber_data_associate_remote_with_conv(JabberData *data, PurpleConversation *conv); void jabber_data_delete_associated_with_conv(PurpleConversation *conv); +*/ /* handles iq requests */ void jabber_data_parse(JabberStream *js, xmlnode *packet); +void jabber_data_init(void); +void jabber_data_uninit(void); #endif /* JABBER_DATA_H */ diff -r 8997acd7d143 -r 305fac6af8f9 libpurple/protocols/jabber/iq.c --- a/libpurple/protocols/jabber/iq.c Thu Sep 04 22:18:58 2008 +0000 +++ b/libpurple/protocols/jabber/iq.c Fri Sep 05 21:55:09 2008 +0000 @@ -356,8 +356,7 @@ return; } - if (xmlnode_get_child_with_namespace(packet, "data", - "urn:xmpp:tmp:data-element")) { + if (xmlnode_get_child_with_namespace(packet, "data", XEP_0231_NAMESPACE)) { jabber_data_parse(js, packet); return; } diff -r 8997acd7d143 -r 305fac6af8f9 libpurple/protocols/jabber/jabber.c --- a/libpurple/protocols/jabber/jabber.c Thu Sep 04 22:18:58 2008 +0000 +++ b/libpurple/protocols/jabber/jabber.c Fri Sep 05 21:55:09 2008 +0000 @@ -1902,11 +1902,7 @@ JabberID *jid; JabberBuddy *jb; JabberBuddyResource *jbr; - PurpleAccount *account = purple_connection_get_account(gc); - PurpleConversation *conv = - purple_find_conversation_with_account(PURPLE_CONV_TYPE_ANY, - who, account); - + if(!(jid = jabber_id_new(who))) return; @@ -1920,8 +1916,6 @@ jabber_message_conv_closed(js, who); } - jabber_data_delete_associated_with_conv(conv); - jabber_id_free(jid); } diff -r 8997acd7d143 -r 305fac6af8f9 libpurple/protocols/jabber/libxmpp.c --- a/libpurple/protocols/jabber/libxmpp.c Thu Sep 04 22:18:58 2008 +0000 +++ b/libpurple/protocols/jabber/libxmpp.c Fri Sep 05 21:55:09 2008 +0000 @@ -138,7 +138,8 @@ purple_value_new(PURPLE_TYPE_SUBTYPE, PURPLE_SUBTYPE_CONNECTION), purple_value_new_outgoing(PURPLE_TYPE_STRING)); - + jabber_data_uninit(); + return TRUE; } @@ -277,14 +278,14 @@ jabber_tune_init(); jabber_caps_init(); + jabber_data_init(); - + jabber_add_feature("avatarmeta", AVATARNAMESPACEMETA, jabber_pep_namespace_only_when_pep_enabled_cb); jabber_add_feature("avatardata", AVATARNAMESPACEDATA, jabber_pep_namespace_only_when_pep_enabled_cb); jabber_add_feature("buzz", "http://www.xmpp.org/extensions/xep-0224.html#ns", jabber_buzz_isenabled); - /* this string will need to be updated when XEP-0231 turns "draft" */ - jabber_add_feature("smileys", XEP_0231_IB_IMAGE_NAMESPACE, + jabber_add_feature("bob", XEP_0231_NAMESPACE, jabber_custom_smileys_isenabled); jabber_pep_register_handler("avatar", AVATARNAMESPACEMETA, jabber_buddy_avatar_update_metadata); diff -r 8997acd7d143 -r 305fac6af8f9 libpurple/protocols/jabber/message.c --- a/libpurple/protocols/jabber/message.c Thu Sep 04 22:18:58 2008 +0000 +++ b/libpurple/protocols/jabber/message.c Fri Sep 05 21:55:09 2008 +0000 @@ -24,7 +24,6 @@ #include "notify.h" #include "server.h" #include "util.h" - #include "buddy.h" #include "chat.h" #include "data.h" @@ -323,66 +322,67 @@ gchar *alt; } JabberSmileyRef; -static GList * -_jabber_message_get_refs_from_xmlnode(const xmlnode *message) + +static void +jabber_message_get_refs_from_xmlnode_internal(const xmlnode *message, + GHashTable *table) { xmlnode *child; - GList *refs = NULL; - + for (child = xmlnode_get_child(message, "img") ; child ; child = xmlnode_get_next_twin(child)) { const gchar *src = xmlnode_get_attrib(child, "src"); - const gssize len = strlen(src); - - if (len > 4 && g_str_has_prefix(src, "cid:")) { - JabberSmileyRef *ref = g_new0(JabberSmileyRef, 1); - ref->cid = g_strdup(&(src[4])); - ref->alt = g_strdup(xmlnode_get_attrib(child, "alt")); - refs = g_list_append(refs, ref); + + if (g_str_has_prefix(src, "cid:")) { + const gchar *cid = src + 4; + + /* if we haven't "fetched" this yet... */ + if (!g_hash_table_lookup(table, cid)) { + /* take a copy of the cid and let the SmileyRef own it... */ + gchar *temp_cid = g_strdup(cid); + JabberSmileyRef *ref = g_new0(JabberSmileyRef, 1); + const gchar *alt = xmlnode_get_attrib(child, "alt"); + ref->cid = temp_cid; + /* if there is no "alt" string, use the cid... */ + if (alt && alt[0] != '\0') { + ref->alt = g_strdup(xmlnode_get_attrib(child, "alt")); + } else { + ref->alt = g_strdup(cid); + } + g_hash_table_insert(table, temp_cid, ref); + } } } - + for (child = message->child ; child ; child = child->next) { - refs = g_list_concat(refs, - _jabber_message_get_refs_from_xmlnode(child)); + jabber_message_get_refs_from_xmlnode_internal(child, table); } +} - return refs; +static gboolean +jabber_message_get_refs_steal(gpointer key, gpointer value, gpointer user_data) +{ + GList **refs = (GList **) user_data; + JabberSmileyRef *ref = (JabberSmileyRef *) value; + + *refs = g_list_append(*refs, ref); + + return TRUE; } static GList * jabber_message_get_refs_from_xmlnode(const xmlnode *message) { - GList *refs = _jabber_message_get_refs_from_xmlnode(message); + GList *refs = NULL; GHashTable *unique_refs = g_hash_table_new(g_str_hash, g_str_equal); - GList *result = NULL; - GList *iterator = NULL; - - for (iterator = refs ; iterator ; iterator = g_list_next(iterator)) { - JabberSmileyRef *ref = (JabberSmileyRef *) iterator->data; - if (!g_hash_table_lookup(unique_refs, ref->cid)) { - JabberSmileyRef *new_ref = g_new0(JabberSmileyRef, 1); - new_ref->cid = g_strdup(ref->cid); - new_ref->alt = g_strdup(ref->alt); - g_hash_table_insert(unique_refs, ref->cid, ref); - result = g_list_append(result, new_ref); - } - } - - for (iterator = refs ; iterator ; iterator = g_list_next(iterator)) { - JabberSmileyRef *ref = (JabberSmileyRef *) iterator->data; - g_free(ref->cid); - g_free(ref->alt); - g_free(ref); - } - + + jabber_message_get_refs_from_xmlnode_internal(message, unique_refs); + (void) g_hash_table_foreach_steal(unique_refs, + jabber_message_get_refs_steal, (gpointer) &refs); g_hash_table_destroy(unique_refs); - - return result; + return refs; } - - static gchar * jabber_message_xml_to_string_strip_img_smileys(xmlnode *xhtml) { @@ -404,6 +404,9 @@ if (g_str_has_prefix(&(markup[pos2]), "/>")) { pos2 += 2; break; + } else if (g_str_has_prefix(&(markup[pos2]), "")) { + pos2 += 5; + break; } } @@ -417,10 +420,16 @@ if (g_str_has_prefix(src, "cid:")) { const gchar *alt = xmlnode_get_attrib(img, "alt"); - gchar *escaped = g_markup_escape_text(alt, -1); - out = g_string_append(out, escaped); + gchar *escaped = NULL; + /* if the "alt" attribute is empty, put the cid as smiley string */ + if (alt && alt[0] != '\0') { + escaped = g_markup_escape_text(alt, -1); + out = g_string_append(out, escaped); + g_free(escaped); + } else { + out = g_string_append(out, src + 4); + } pos += pos2 - pos; - g_free(escaped); } else { out = g_string_append_c(out, markup[pos]); pos++; @@ -438,27 +447,36 @@ } static void -jabber_message_add_remote_smileys_to_conv(PurpleConversation *conv, - const xmlnode *message) +jabber_message_add_remote_smileys(const xmlnode *message) { xmlnode *data_tag; - for (data_tag = xmlnode_get_child(message, "data") ; data_tag ; + for (data_tag = xmlnode_get_child_with_namespace(message, "data", XEP_0231_NAMESPACE) ; + data_tag ; data_tag = xmlnode_get_next_twin(data_tag)) { const gchar *cid = xmlnode_get_attrib(data_tag, "cid"); - const JabberData *data = jabber_data_find_remote_by_cid(conv, cid); + const JabberData *data = jabber_data_find_remote_by_cid(cid); - if (!data) { + if (!data && cid != NULL) { /* we haven't cached this already, let's add it */ JabberData *new_data = jabber_data_create_from_xml(data_tag); - jabber_data_associate_remote_with_conv(new_data, conv); + jabber_data_associate_remote(new_data); } } } +/* used in the function below to supply a conversation and shortcut for a + smiley */ +typedef struct { + PurpleConversation *conv; + const gchar *alt; +} JabberDataRef; + static void jabber_message_get_data_cb(JabberStream *js, xmlnode *packet, gpointer data) { - PurpleConversation *conv = (PurpleConversation *) data; + JabberDataRef *ref = (JabberDataRef *) data; + PurpleConversation *conv = ref->conv; + const gchar *alt = ref->alt; xmlnode *data_element = xmlnode_get_child(packet, "data"); xmlnode *item_not_found = xmlnode_get_child(packet, "item-not-found"); @@ -467,11 +485,11 @@ JabberData *data = jabber_data_create_from_xml(data_element); if (data) { - jabber_data_associate_remote_with_conv(data, conv); - purple_conv_custom_smiley_write(conv, jabber_data_get_alt(data), + jabber_data_associate_remote(data); + purple_conv_custom_smiley_write(conv, alt, jabber_data_get_data(data), jabber_data_get_size(data)); - purple_conv_custom_smiley_close(conv, jabber_data_get_alt(data)); + purple_conv_custom_smiley_close(conv, alt); } } else if (item_not_found) { @@ -480,17 +498,23 @@ } else { purple_debug_error("jabber", "Unknown response to data request\n"); } + + g_free(ref); } static void jabber_message_send_data_request(JabberStream *js, PurpleConversation *conv, - const gchar *cid, const gchar *who) + const gchar *cid, const gchar *who, + const gchar *alt) { JabberIq *request = jabber_iq_new(js, JABBER_IQ_GET); + JabberDataRef *ref = g_new0(JabberDataRef, 1); xmlnode *data_request = jabber_data_get_xml_request(cid); xmlnode_set_attrib(request->node, "to", who); - jabber_iq_set_callback(request, jabber_message_get_data_cb, conv); + ref->conv = conv; + ref->alt = alt; + jabber_iq_set_callback(request, jabber_message_get_data_cb, ref); xmlnode_insert_child(request->node, data_request); jabber_iq_send(request); @@ -565,7 +589,9 @@ /* find a list of smileys ("cid" and "alt" text pairs) occuring in the message */ smiley_refs = jabber_message_get_refs_from_xmlnode(child); - + purple_debug_info("jabber", "found %d smileys\n", + g_list_length(smiley_refs)); + if (jm->type == JABBER_MESSAGE_GROUPCHAT) { JabberID *jid = jabber_id_new(jm->from); JabberChat *chat = NULL; @@ -582,17 +608,8 @@ who, account); } - /* if the conversation doesn't exist yet we need to create it - now */ - if (!conv) { - /* if a message of this type is initiating a conversation, - that must be an IM */ - conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, - account, who); - } - /* process any newly provided smileys */ - jabber_message_add_remote_smileys_to_conv(conv, packet); + jabber_message_add_remote_smileys(packet); } /* reformat xhtml so that img tags with a "cid:" src gets @@ -617,7 +634,7 @@ if (purple_conv_custom_smiley_add(conv, alt, "cid", cid, TRUE)) { const JabberData *data = - jabber_data_find_remote_by_cid(conv, cid); + jabber_data_find_remote_by_cid(cid); /* if data is already known, we add write it immediatly */ if (data) { purple_conv_custom_smiley_write(conv, alt, @@ -626,7 +643,8 @@ purple_conv_custom_smiley_close(conv, alt); } else { /* we need to request the smiley (data) */ - jabber_message_send_data_request(js, conv, cid, who); + jabber_message_send_data_request(js, conv, cid, who, + alt); } } } @@ -814,8 +832,7 @@ } static gchar * -jabber_message_get_smileyfied_xhtml(const PurpleConversation *conv, - const gchar *xhtml, const GList *smileys) +jabber_message_get_smileyfied_xhtml(const gchar *xhtml, const GList *smileys) { /* create XML element for all smileys (img tags) */ GString *result = g_string_new(NULL); @@ -836,8 +853,8 @@ if (g_str_has_prefix(&(xhtml[pos]), escaped)) { /* we found the current smiley at this position */ const JabberData *data = - jabber_data_find_local_by_alt(conv, shortcut); - xmlnode *img = jabber_data_get_xhtml_im(data); + jabber_data_find_local_by_alt(shortcut); + xmlnode *img = jabber_data_get_xhtml_im(data, shortcut); int len; gchar *img_text = xmlnode_to_str(img, &len); @@ -868,18 +885,27 @@ const gchar *who) { JabberStream *js = (JabberStream *) gc->proto_data; - JabberBuddy *jb = jabber_buddy_find(js, who, FALSE); + JabberBuddy *jb; + + if (!js) { + purple_debug_error("jabber", + "jabber_conv_support_custom_smileys: could not find stream\n"); + return FALSE; + } + jb = jabber_buddy_find(js, who, FALSE); if (!jb) { purple_debug_error("jabber", "jabber_conv_support_custom smileys: could not find buddy\n"); return FALSE; } + + switch (purple_conversation_get_type(conv)) { /* for the time being, we will not support custom smileys in MUCs */ case PURPLE_CONV_TYPE_IM: - return jabber_buddy_has_capability(jb, XEP_0231_IB_IMAGE_NAMESPACE); + return jabber_buddy_has_capability(jb, XEP_0231_NAMESPACE); break; default: return FALSE; @@ -976,7 +1002,7 @@ PurpleConversation *conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_ANY, jm->to, account); - + if (jabber_conv_support_custom_smileys(jm->js->gc, conv, jm->to)) { GList *found_smileys = jabber_message_xhtml_find_smileys(jm->xhtml); @@ -990,28 +1016,33 @@ (PurpleSmiley *) iterator->data; const gchar *shortcut = purple_smiley_get_shortcut(smiley); const JabberData *data = - jabber_data_find_local_by_alt(conv, shortcut); - - /* if data has not been sent before, include data */ + jabber_data_find_local_by_alt(shortcut); + + /* the object has not been sent before */ if (!data) { PurpleStoredImage *image = purple_smiley_get_stored_image(smiley); const gchar *ext = purple_imgstore_get_extension(image); - + JabberStream *js = jm->js; + JabberData *new_data = jabber_data_create_from_data(purple_imgstore_get_data(image), - purple_imgstore_get_size(image), - jabber_message_get_mimetype_from_ext(ext), - shortcut); - jabber_data_associate_local_with_conv(new_data, conv); - xmlnode_insert_child(message, - jabber_data_get_xml_definition(new_data)); + purple_imgstore_get_size(image), + jabber_message_get_mimetype_from_ext(ext), js); + purple_debug_info("jabber", + "cache local smiley alt = %s, cid = %s\n", + shortcut, jabber_data_get_cid(new_data)); + jabber_data_associate_local(new_data, shortcut); + /* if the size of the data is small enough, include it */ + if (jabber_data_get_size(new_data) <= 1024) { + xmlnode_insert_child(message, + jabber_data_get_xml_definition(new_data)); + } } } smileyfied_xhtml = - jabber_message_get_smileyfied_xhtml(conv, jm->xhtml, - found_smileys); + jabber_message_get_smileyfied_xhtml(jm->xhtml, found_smileys); child = xmlnode_from_str(smileyfied_xhtml, -1); g_free(smileyfied_xhtml); g_list_free(found_smileys); diff -r 8997acd7d143 -r 305fac6af8f9 pidgin/gtksmiley.c --- a/pidgin/gtksmiley.c Thu Sep 04 22:18:58 2008 +0000 +++ b/pidgin/gtksmiley.c Fri Sep 05 21:55:09 2008 +0000 @@ -273,8 +273,8 @@ gsize size = 0; gchar *filename; - gdk_pixbuf_save_to_bufferv(s->custom_pixbuf, &buffer, &size, - "png", NULL, NULL, NULL); + gdk_pixbuf_save_to_buffer(s->custom_pixbuf, &buffer, &size, + "png", NULL, "compression", "9", NULL, NULL); filename = purple_util_get_image_filename(buffer, size); s->filename = g_build_filename(purple_smileys_get_storing_dir(), filename, NULL); purple_util_write_data_to_file_absolute(s->filename, buffer, size);