Mercurial > pidgin
changeset 26983:2dfb639b4f26
propagate from branch 'im.pidgin.pidgin' (head 191873f724e4551edc337f1e018980f32c41391b)
to branch 'im.pidgin.cpw.malu.client_type' (head 622ef46be3dcff9f70c21918cbeed71f7508b85c)
author | Marcus Lundblad <ml@update.uu.se> |
---|---|
date | Wed, 13 May 2009 20:37:46 +0000 |
parents | eeee4309d3d8 (diff) 007dff3cb9e4 (current diff) |
children | d2424873c666 |
files | libpurple/protocols/jabber/buddy.c libpurple/protocols/jabber/buddy.h libpurple/protocols/jabber/jabber.c |
diffstat | 35 files changed, 431 insertions(+), 153 deletions(-) [+] |
line wrap: on
line diff
--- a/COPYRIGHT Thu May 07 21:20:16 2009 +0000 +++ b/COPYRIGHT Wed May 13 20:37:46 2009 +0000 @@ -424,6 +424,7 @@ Lex Spoon Chris Stafford Kevin Stange +Joshua Stein Jakub Steiner Richard Stellingwerff Charlie Stockman
--- a/ChangeLog Thu May 07 21:20:16 2009 +0000 +++ b/ChangeLog Wed May 13 20:37:46 2009 +0000 @@ -38,6 +38,9 @@ contains formatting. * Show when the user was last logged in when doing "Get Info" on an offline buddy, provided the server supports it. + * Support custom smileys in MUCs (only when all participants supports the + "Bits of Binary" extension, and a maximum of 10 participants are in the + chat (to avoid getting too many fetch requests). Yahoo: * P2P file transfers. (Sulabh Mahajan) @@ -65,6 +68,8 @@ * The nicks of the persons who leave the chatroom are italicized in the chat's conversation history. The nicks are un-italicized when they rejoin. + * Always set unseen-count and unseen-state on conversations. + (Joshua Stein) Finch: * The hardware cursor is updated correctly. This will be useful
--- a/ChangeLog.API Thu May 07 21:20:16 2009 +0000 +++ b/ChangeLog.API Wed May 13 20:37:46 2009 +0000 @@ -15,6 +15,7 @@ * account-destroying * blist-node-added and blist-node-removed signals (see blist-signals.dox) + * Jabber plugin signals (see jabber-signals.dox) * purple_buddy_destroy * purple_buddy_get_protocol_data * purple_buddy_set_protocol_data
--- a/Makefile.mingw Thu May 07 21:20:16 2009 +0000 +++ b/Makefile.mingw Wed May 13 20:37:46 2009 +0000 @@ -96,15 +96,15 @@ -not \( -false $(EXTERNAL_DLLS_FIND_EXP) \) -exec $(STRIP) --strip-unneeded {} ';' installer: create_release_install_dir - $(MAKENSIS) /V3 /DPIDGIN_VERSION="$(PIDGIN_VERSION)" /DPIDGIN_PRODUCT_VERSION="$(PIDGIN_PRODUCT_VERSION)" /DWITH_GTK /DPIDGIN_INSTALL_DIR="$(STRIPPED_RELEASE_DIR)" /DGTK_INSTALL_VERSION="$(GTK_INSTALL_VERSION)" pidgin/win32/nsis/pidgin-installer.nsi + $(MAKENSIS) $(MAKENSISOPT)V3 $(MAKENSISOPT)DPIDGIN_VERSION="$(PIDGIN_VERSION)" $(MAKENSISOPT)DPIDGIN_PRODUCT_VERSION="$(PIDGIN_PRODUCT_VERSION)" $(MAKENSISOPT)DWITH_GTK $(MAKENSISOPT)DPIDGIN_INSTALL_DIR="$(STRIPPED_RELEASE_DIR)" $(MAKENSISOPT)DGTK_INSTALL_VERSION="$(GTK_INSTALL_VERSION)" pidgin/win32/nsis/pidgin-installer.nsi mv pidgin/win32/nsis/pidgin-$(PIDGIN_VERSION).exe ./ installer_nogtk: create_release_install_dir - $(MAKENSIS) /V3 /DPIDGIN_VERSION="$(PIDGIN_VERSION)" /DPIDGIN_PRODUCT_VERSION="$(PIDGIN_PRODUCT_VERSION)" /DPIDGIN_INSTALL_DIR="$(STRIPPED_RELEASE_DIR)" /DGTK_INSTALL_VERSION="$(GTK_INSTALL_VERSION)" pidgin/win32/nsis/pidgin-installer.nsi + $(MAKENSIS) $(MAKENSISOPT)V3 $(MAKENSISOPT)DPIDGIN_VERSION="$(PIDGIN_VERSION)" $(MAKENSISOPT)DPIDGIN_PRODUCT_VERSION="$(PIDGIN_PRODUCT_VERSION)" $(MAKENSISOPT)DPIDGIN_INSTALL_DIR="$(STRIPPED_RELEASE_DIR)" $(MAKENSISOPT)DGTK_INSTALL_VERSION="$(GTK_INSTALL_VERSION)" pidgin/win32/nsis/pidgin-installer.nsi mv pidgin/win32/nsis/pidgin-$(PIDGIN_VERSION)-no-gtk.exe ./ installer_debug: install - $(MAKENSIS) /V3 /DPIDGIN_VERSION="$(PIDGIN_VERSION)" /DPIDGIN_PRODUCT_VERSION="$(PIDGIN_PRODUCT_VERSION)" /DPIDGIN_INSTALL_DIR="$(PIDGIN_INSTALL_DIR)" /DDEBUG /DGTK_INSTALL_VERSION="$(GTK_INSTALL_VERSION)" pidgin/win32/nsis/pidgin-installer.nsi + $(MAKENSIS) $(MAKENSISOPT)V3 $(MAKENSISOPT)DPIDGIN_VERSION="$(PIDGIN_VERSION)" $(MAKENSISOPT)DPIDGIN_PRODUCT_VERSION="$(PIDGIN_PRODUCT_VERSION)" $(MAKENSISOPT)DPIDGIN_INSTALL_DIR="$(PIDGIN_INSTALL_DIR)" $(MAKENSISOPT)DDEBUG $(MAKENSISOPT)DGTK_INSTALL_VERSION="$(GTK_INSTALL_VERSION)" pidgin/win32/nsis/pidgin-installer.nsi mv pidgin/win32/nsis/pidgin-$(PIDGIN_VERSION)-debug.exe ./ installer_zip: create_release_install_dir
--- a/libpurple/dbus-analyze-functions.py Thu May 07 21:20:16 2009 +0000 +++ b/libpurple/dbus-analyze-functions.py Wed May 13 20:37:46 2009 +0000 @@ -31,6 +31,15 @@ "purple_account_unregister", "purple_connection_new_unregister", + # These functions are excluded because they involve setting arbitrary + # data via pointers for protocols and UIs. This just won't work. + "purple_blist_get_ui_data", + "purple_blist_set_ui_data", + "purple_blist_node_get_ui_data", + "purple_blist_node_set_ui_data", + "purple_buddy_get_protocol_data", + "purple_buddy_set_protocol_data", + # This is excluded because this script treats PurpleLogReadFlags* # as pointer to a struct, instead of a pointer to an enum. This # causes a compilation error. Someone should fix this script.
--- a/libpurple/protocols/jabber/buddy.c Thu May 07 21:20:16 2009 +0000 +++ b/libpurple/protocols/jabber/buddy.c Wed May 13 20:37:46 2009 +0000 @@ -74,7 +74,7 @@ if (js->buddies == NULL) return NULL; - if(!(realname = jabber_normalize(js->gc->account, name))) + if(!(realname = jabber_get_bare_jid(name))) return NULL; jb = g_hash_table_lookup(js->buddies, realname); @@ -1741,7 +1741,7 @@ g_free(full_jid); } - if (!jb->resources) { + if (!jb->resources && strchr(jid, '/') == NULL) { /* user is offline, send a jabber:iq:last to find out last time online */ iq = jabber_iq_new_query(js, JABBER_IQ_GET, "jabber:iq:last"); xmlnode_set_attrib(iq->node, "to", jid);
--- a/libpurple/protocols/jabber/buddy.h Thu May 07 21:20:16 2009 +0000 +++ b/libpurple/protocols/jabber/buddy.h Wed May 13 20:37:46 2009 +0000 @@ -86,6 +86,7 @@ GList *exts; } caps; GList *commands; + gboolean commands_fetched; } JabberBuddyResource; void jabber_buddy_free(JabberBuddy *jb);
--- a/libpurple/protocols/jabber/caps.c Thu May 07 21:20:16 2009 +0000 +++ b/libpurple/protocols/jabber/caps.c Wed May 13 20:37:46 2009 +0000 @@ -35,13 +35,7 @@ GList *values; } JabberDataFormField; -typedef struct _JabberCapsKey { - char *node; - char *ver; - char *hash; -} JabberCapsKey; - -static GHashTable *capstable = NULL; /* JabberCapsKey -> JabberCapsClientInfo */ +static GHashTable *capstable = NULL; /* JabberCapsTuple -> JabberCapsClientInfo */ static GHashTable *nodetable = NULL; /* char *node -> JabberCapsNodeExts */ static guint save_timer = 0; @@ -86,7 +80,7 @@ } static guint jabber_caps_hash(gconstpointer data) { - const JabberCapsKey *key = data; + const JabberCapsTuple *key = data; guint nodehash = g_str_hash(key->node); guint verhash = g_str_hash(key->ver); /* @@ -99,22 +93,14 @@ } static gboolean jabber_caps_compare(gconstpointer v1, gconstpointer v2) { - const JabberCapsKey *name1 = v1; - const JabberCapsKey *name2 = v2; + const JabberCapsTuple *name1 = v1; + const JabberCapsTuple *name2 = v2; return g_str_equal(name1->node, name2->node) && g_str_equal(name1->ver, name2->ver) && purple_strequal(name1->hash, name2->hash); } -void jabber_caps_destroy_key(gpointer data) { - JabberCapsKey *key = data; - g_free(key->node); - g_free(key->ver); - g_free(key->hash); - g_free(key); -} - static void jabber_caps_client_info_destroy(JabberCapsClientInfo *info) { @@ -140,6 +126,10 @@ jabber_caps_node_exts_unref(info->exts); + g_free((char *)info->tuple.node); + g_free((char *)info->tuple.ver); + g_free((char *)info->tuple.hash); + g_free(info); } @@ -176,16 +166,16 @@ } static void jabber_caps_store_client(gpointer key, gpointer value, gpointer user_data) { - JabberCapsKey *clientinfo = key; - JabberCapsClientInfo *props = value; + const JabberCapsTuple *tuple = key; + const JabberCapsClientInfo *props = value; xmlnode *root = user_data; xmlnode *client = xmlnode_new_child(root, "client"); GList *iter; - xmlnode_set_attrib(client, "node", clientinfo->node); - xmlnode_set_attrib(client, "ver", clientinfo->ver); - if (clientinfo->hash) - xmlnode_set_attrib(client, "hash", clientinfo->hash); + xmlnode_set_attrib(client, "node", tuple->node); + xmlnode_set_attrib(client, "ver", tuple->ver); + if (tuple->hash) + xmlnode_set_attrib(client, "hash", tuple->hash); for(iter = props->identities; iter; iter = g_list_next(iter)) { JabberIdentity *id = iter->data; xmlnode *identity = xmlnode_new_child(client, "identity"); @@ -255,8 +245,8 @@ if(client->type != XMLNODE_TYPE_TAG) continue; if(!strcmp(client->name, "client")) { - JabberCapsKey *key = g_new0(JabberCapsKey, 1); JabberCapsClientInfo *value = g_new0(JabberCapsClientInfo, 1); + JabberCapsTuple *key = (JabberCapsTuple*)&value->tuple; xmlnode *child; JabberCapsNodeExts *exts = NULL; key->node = g_strdup(xmlnode_get_attrib(client,"node")); @@ -340,7 +330,7 @@ void jabber_caps_init(void) { nodetable = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify)jabber_caps_node_exts_unref); - capstable = g_hash_table_new_full(jabber_caps_hash, jabber_caps_compare, jabber_caps_destroy_key, (GDestroyNotify)jabber_caps_client_info_destroy); + capstable = g_hash_table_new_full(jabber_caps_hash, jabber_caps_compare, NULL, (GDestroyNotify)jabber_caps_client_info_destroy); jabber_caps_load(); } @@ -356,6 +346,28 @@ capstable = nodetable = NULL; } +gboolean jabber_caps_exts_known(const JabberCapsClientInfo *info, + char **exts) +{ + int i; + g_return_val_if_fail(info != NULL, FALSE); + + if (!exts) + return TRUE; + + for (i = 0; exts[i]; ++i) { + /* Hack since we advertise the ext along with v1.5 caps but don't + * store any exts */ + if (g_str_equal(exts[i], "voice-v1") && !info->exts) + continue; + if (!info->exts || + !g_hash_table_lookup(info->exts->exts, exts[i])) + return FALSE; + } + + return TRUE; +} + typedef struct _jabber_caps_cbplususerdata { guint ref; @@ -429,7 +441,7 @@ "http://jabber.org/protocol/disco#info"); jabber_caps_cbplususerdata *userdata = data; JabberCapsClientInfo *info = NULL, *value; - JabberCapsKey key; + JabberCapsTuple key; if (!query || type == JABBER_IQ_ERROR) { /* Any outstanding exts will be dealt with via ref-counting */ @@ -481,7 +493,7 @@ jabber_caps_client_info_destroy(info); info = value; } else { - JabberCapsKey *n_key = g_new(JabberCapsKey, 1); + JabberCapsTuple *n_key = (JabberCapsTuple *)&info->tuple; n_key->node = userdata->node; n_key->ver = userdata->ver; n_key->hash = userdata->hash; @@ -549,16 +561,19 @@ } void jabber_caps_get_info(JabberStream *js, const char *who, const char *node, - const char *ver, const char *hash, const char *ext, + const char *ver, const char *hash, char **exts, jabber_caps_get_info_cb cb, gpointer user_data) { JabberCapsClientInfo *info; - JabberCapsKey key; + JabberCapsTuple key; jabber_caps_cbplususerdata *userdata; - if (ext && *ext && hash) + if (exts && hash) { purple_debug_info("jabber", "Ignoring exts in new-style caps from %s\n", who); + g_strfreev(exts); + exts = NULL; + } /* Using this in a read-only fashion, so the cast is OK */ key.node = (char *)node; @@ -607,9 +622,8 @@ } /* Are there any exts that we don't recognize? */ - if (ext && *ext && !hash) { + if (exts) { JabberCapsNodeExts *node_exts; - gchar **splat = g_strsplit(ext, " ", 0); int i; if (info) { @@ -621,23 +635,23 @@ /* We'll put it in later once we have the client info */ node_exts = userdata->node_exts = jabber_caps_find_exts_by_node(node); - for (i = 0; splat[i]; ++i) { - userdata->exts = g_list_prepend(userdata->exts, splat[i]); + for (i = 0; exts[i]; ++i) { + userdata->exts = g_list_prepend(userdata->exts, exts[i]); /* Look it up if we don't already know what it means */ - if (!g_hash_table_lookup(node_exts->exts, splat[i])) { + if (!g_hash_table_lookup(node_exts->exts, exts[i])) { JabberIq *iq; xmlnode *query; char *nodeext; ext_iq_data *cbdata = g_new(ext_iq_data, 1); - cbdata->name = splat[i]; + cbdata->name = exts[i]; cbdata->data = cbplususerdata_ref(userdata); iq = jabber_iq_new_query(js, JABBER_IQ_GET, "http://jabber.org/protocol/disco#info"); query = xmlnode_get_child_with_namespace(iq->node, "query", "http://jabber.org/protocol/disco#info"); - nodeext = g_strdup_printf("%s#%s", node, splat[i]); + nodeext = g_strdup_printf("%s#%s", node, exts[i]); xmlnode_set_attrib(query, "node", nodeext); g_free(nodeext); xmlnode_set_attrib(iq->node, "to", who); @@ -647,11 +661,11 @@ ++userdata->extOutstanding; } - splat[i] = NULL; + exts[i] = NULL; } /* All the strings are now part of the GList, so don't need * g_strfreev. */ - g_free(splat); + g_free(exts); } if (userdata->info && userdata->extOutstanding == 0) {
--- a/libpurple/protocols/jabber/caps.h Thu May 07 21:20:16 2009 +0000 +++ b/libpurple/protocols/jabber/caps.h Wed May 13 20:37:46 2009 +0000 @@ -30,11 +30,19 @@ typedef struct _JabberCapsNodeExts JabberCapsNodeExts; +typedef struct _JabberCapsTuple { + const char *node; + const char *ver; + const char *hash; +} JabberCapsTuple; + struct _JabberCapsClientInfo { GList *identities; /* JabberIdentity */ GList *features; /* char * */ GList *forms; /* xmlnode * */ JabberCapsNodeExts *exts; + + const JabberCapsTuple tuple; }; /* @@ -60,7 +68,10 @@ void jabber_caps_init(void); void jabber_caps_uninit(void); -void jabber_caps_destroy_key(gpointer value); +/** + * Check whether all of the exts in a char* array are known to the given info. + */ +gboolean jabber_caps_exts_known(const JabberCapsClientInfo *info, char **exts); /** * Main entity capabilites function to get the capabilities of a contact. @@ -68,10 +79,13 @@ * The callback will be called synchronously if we already have the * capabilities for the specified (node,ver,hash) (and, if exts are specified, * if we know what each means) + * + * @param exts A g_strsplit'd (NULL-terminated) array of strings. This + * function is responsible for freeing it. */ void jabber_caps_get_info(JabberStream *js, const char *who, const char *node, const char *ver, const char *hash, - const char *ext, jabber_caps_get_info_cb cb, + char **exts, jabber_caps_get_info_cb cb, gpointer user_data); /**
--- a/libpurple/protocols/jabber/chat.c Thu May 07 21:20:16 2009 +0000 +++ b/libpurple/protocols/jabber/chat.c Wed May 13 20:37:46 2009 +0000 @@ -1162,5 +1162,59 @@ g_free(room_jid); } +typedef struct { + const gchar *cap; + gboolean *all_support; + JabberBuddy *jb; +} JabberChatCapsData; +static void +jabber_chat_all_participants_have_capability_foreach(gpointer key, + gpointer value, + gpointer user_data) +{ + const gchar *cap = ((JabberChatCapsData *) user_data)->cap; + gboolean *all_support = ((JabberChatCapsData *) user_data)->all_support; + JabberBuddy *jb = ((JabberChatCapsData *) user_data)->jb; + JabberChatMember *member = (JabberChatMember *) value; + const gchar *resource = member->handle; + JabberBuddyResource *jbr = jabber_buddy_find_resource(jb, resource); + if (jbr) { + *all_support &= jabber_resource_has_capability(jbr, cap); + } else { + *all_support = FALSE; + } +} + +gboolean +jabber_chat_all_participants_have_capability(const JabberChat *chat, + const gchar *cap) +{ + gchar *chat_jid = NULL; + JabberBuddy *jb = NULL; + gboolean all_support = TRUE; + JabberChatCapsData data; + + chat_jid = g_strdup_printf("%s@%s", chat->room, chat->server); + jb = jabber_buddy_find(chat->js, chat_jid, FALSE); + + if (jb) { + data.cap = cap; + data.all_support = &all_support; + data.jb = jb; + + g_hash_table_foreach(chat->members, + jabber_chat_all_participants_have_capability_foreach, &data); + } else { + all_support = FALSE; + } + g_free(chat_jid); + return all_support; +} + +guint +jabber_chat_get_num_participants(const JabberChat *chat) +{ + return g_hash_table_size(chat->members); +}
--- a/libpurple/protocols/jabber/chat.h Thu May 07 21:20:16 2009 +0000 +++ b/libpurple/protocols/jabber/chat.h Wed May 13 20:37:46 2009 +0000 @@ -95,5 +95,8 @@ char *jabber_roomlist_room_serialize(PurpleRoomlistRoom *room); +gboolean jabber_chat_all_participants_have_capability(const JabberChat *chat, + const gchar *cap); +guint jabber_chat_get_num_participants(const JabberChat *chat); #endif /* PURPLE_JABBER_CHAT_H_ */
--- a/libpurple/protocols/jabber/disco.h Thu May 07 21:20:16 2009 +0000 +++ b/libpurple/protocols/jabber/disco.h Wed May 13 20:37:46 2009 +0000 @@ -1,5 +1,5 @@ /** - * @file iq.h JabberID handlers + * @file disco.h service discovery handlers * * purple *
--- a/libpurple/protocols/jabber/google.c Thu May 07 21:20:16 2009 +0000 +++ b/libpurple/protocols/jabber/google.c Wed May 13 20:37:46 2009 +0000 @@ -638,7 +638,6 @@ const char *to, *url; const char *in_str; char *to_name; - char *default_tos[1]; int i, count = 1, returned_count; @@ -658,14 +657,20 @@ /* If Gmail doesn't tell us who the mail is to, let's use our JID */ to = xmlnode_get_attrib(packet, "to"); - default_tos[0] = jabber_get_bare_jid(to); message = xmlnode_get_child(child, "mail-thread-info"); if (count == 0 || !message) { - if (count > 0) - purple_notify_emails(js->gc, count, FALSE, NULL, NULL, (const char**) default_tos, NULL, NULL, NULL); - g_free(default_tos[0]); + if (count > 0) { + char *bare_jid = jabber_get_bare_jid(to); + const char *default_tos[2] = { bare_jid }; + + purple_notify_emails(js->gc, count, FALSE, NULL, NULL, default_tos, NULL, NULL, NULL); + g_free(bare_jid); + } else { + purple_notify_emails(js->gc, count, FALSE, NULL, NULL, NULL, NULL, NULL, NULL); + } + return; } @@ -673,10 +678,10 @@ * accordingly */ for (returned_count = 0; message; returned_count++, message=xmlnode_get_next_twin(message)); - froms = g_new0(const char* , returned_count); - tos = g_new0(const char* , returned_count); - subjects = g_new0(char* , returned_count); - urls = g_new0(const char* , returned_count); + froms = g_new0(const char* , returned_count + 1); + tos = g_new0(const char* , returned_count + 1); + subjects = g_new0(char* , returned_count + 1); + urls = g_new0(const char* , returned_count + 1); to = xmlnode_get_attrib(packet, "to"); to_name = jabber_get_bare_jid(to); @@ -726,16 +731,12 @@ if (i>0) purple_notify_emails(js->gc, count, count == i, (const char**) subjects, froms, tos, urls, NULL, NULL); - else - purple_notify_emails(js->gc, count, FALSE, NULL, NULL, (const char**) default_tos, NULL, NULL, NULL); - g_free(to_name); g_free(tos); - g_free(default_tos[0]); g_free(froms); - for (; i > 0; i--) - g_free(subjects[i - 1]); + for (i = 0; i < returned_count; i++) + g_free(subjects[i]); g_free(subjects); g_free(urls); @@ -763,7 +764,8 @@ /* Acknowledge the notification */ iq = jabber_iq_new(js, JABBER_IQ_RESULT); - xmlnode_set_attrib(iq->node, "to", from); + if (from) + xmlnode_set_attrib(iq->node, "to", from); xmlnode_set_attrib(iq->node, "id", id); jabber_iq_send(iq);
--- a/libpurple/protocols/jabber/iq.c Thu May 07 21:20:16 2009 +0000 +++ b/libpurple/protocols/jabber/iq.c Wed May 13 20:37:46 2009 +0000 @@ -42,7 +42,7 @@ #endif GHashTable *iq_handlers = NULL; - +GHashTable *signal_iq_handlers = NULL; JabberIq *jabber_iq_new(JabberStream *js, JabberIqType type) { @@ -289,6 +289,16 @@ const char *xmlns; const char *iq_type, *id, *from; JabberIqType type = JABBER_IQ_NONE; + gboolean signal_return; + + from = xmlnode_get_attrib(packet, "from"); + id = xmlnode_get_attrib(packet, "id"); + iq_type = xmlnode_get_attrib(packet, "type"); + + signal_return = GPOINTER_TO_INT(purple_signal_emit_return_1(jabber_plugin, + "jabber-receiving-iq", js->gc, iq_type, id, from, packet)); + if (signal_return) + return; /* * child will be either the first tag child or NULL if there is no child. @@ -301,10 +311,6 @@ break; } - iq_type = xmlnode_get_attrib(packet, "type"); - from = xmlnode_get_attrib(packet, "from"); - id = xmlnode_get_attrib(packet, "id"); - if (iq_type) { if (!strcmp(iq_type, "get")) type = JABBER_IQ_GET; @@ -361,12 +367,23 @@ } } - /* Apparently not, so lets see if we have a pre-defined handler */ + /* + * Apparently not, so let's see if we have a pre-defined handler + * or if an outside plugin is interested. + */ if(child && (xmlns = xmlnode_get_namespace(child))) { char *key = g_strdup_printf("%s %s", child->name, xmlns); JabberIqHandler *jih = g_hash_table_lookup(iq_handlers, key); + int signal_ref = GPOINTER_TO_INT(g_hash_table_lookup(signal_iq_handlers, key)); g_free(key); + if (signal_ref > 0) { + signal_return = GPOINTER_TO_INT(purple_signal_emit_return_1(jabber_plugin, "jabber-watched-iq", + js->gc, iq_type, id, from, child)); + if (signal_return) + return; + } + if(jih) { jih(js, from, type, id, child); return; @@ -408,9 +425,48 @@ g_hash_table_replace(iq_handlers, key, handlerfunc); } +void jabber_iq_signal_register(const gchar *node, const gchar *xmlns) +{ + gchar *key; + int ref; + + g_return_if_fail(node != NULL && *node != '\0'); + g_return_if_fail(xmlns != NULL && *xmlns != '\0'); + + key = g_strdup_printf("%s %s", node, xmlns); + ref = GPOINTER_TO_INT(g_hash_table_lookup(signal_iq_handlers, key)); + if (ref == 0) { + g_hash_table_insert(signal_iq_handlers, key, GINT_TO_POINTER(1)); + } else { + g_hash_table_insert(signal_iq_handlers, key, GINT_TO_POINTER(ref + 1)); + g_free(key); + } +} + +void jabber_iq_signal_unregister(const gchar *node, const gchar *xmlns) +{ + gchar *key; + int ref; + + g_return_if_fail(node != NULL && *node != '\0'); + g_return_if_fail(xmlns != NULL && *xmlns != '\0'); + + key = g_strdup_printf("%s %s", node, xmlns); + ref = GPOINTER_TO_INT(g_hash_table_lookup(signal_iq_handlers, key)); + + if (ref == 1) { + g_hash_table_remove(signal_iq_handlers, key); + } else if (ref > 1) { + g_hash_table_insert(signal_iq_handlers, key, GINT_TO_POINTER(ref - 1)); + } + + g_free(key); +} + void jabber_iq_init(void) { iq_handlers = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); + signal_iq_handlers = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); jabber_iq_register_handler("jingle", JINGLE, jingle_parse); jabber_iq_register_handler("mailbox", "google:mail:notify", @@ -446,5 +502,6 @@ void jabber_iq_uninit(void) { g_hash_table_destroy(iq_handlers); - iq_handlers = NULL; + g_hash_table_destroy(signal_iq_handlers); + iq_handlers = signal_iq_handlers = NULL; }
--- a/libpurple/protocols/jabber/iq.h Thu May 07 21:20:16 2009 +0000 +++ b/libpurple/protocols/jabber/iq.h Wed May 13 20:37:46 2009 +0000 @@ -31,6 +31,7 @@ } JabberIqType; #include "jabber.h" +#include "connection.h" typedef struct _JabberIq JabberIq; @@ -106,4 +107,8 @@ void jabber_iq_register_handler(const char *node, const char *xmlns, JabberIqHandler *func); +/* Connected to namespace-handler registration signals */ +void jabber_iq_signal_register(const gchar *node, const gchar *xmlns); +void jabber_iq_signal_unregister(const gchar *node, const gchar *xmlns); + #endif /* PURPLE_JABBER_IQ_H_ */
--- a/libpurple/protocols/jabber/jabber.c Thu May 07 21:20:16 2009 +0000 +++ b/libpurple/protocols/jabber/jabber.c Wed May 13 20:37:46 2009 +0000 @@ -3397,7 +3397,7 @@ jabber_add_feature(XEP_0224_NAMESPACE, jabber_buzz_isenabled); /* Bits Of Binary */ - jabber_add_feature(XEP_0231_NAMESPACE, jabber_custom_smileys_isenabled); + jabber_add_feature(XEP_0231_NAMESPACE, 0); /* Jingle features! */ jabber_add_feature(JINGLE, 0); @@ -3418,6 +3418,7 @@ purple_value_new(PURPLE_TYPE_SUBTYPE, PURPLE_SUBTYPE_ACCOUNT), purple_value_new(PURPLE_TYPE_STRING), purple_value_new(PURPLE_TYPE_STRING)); + purple_plugin_ipc_register(plugin, "add_feature", PURPLE_CALLBACK(jabber_ipc_add_feature), purple_marshal_VOID__POINTER, NULL, 1, @@ -3427,6 +3428,8 @@ void jabber_uninit_plugin(void) { + purple_plugin_ipc_unregister_all(jabber_plugin); + jabber_features_destroy(); jabber_identities_destroy(); }
--- a/libpurple/protocols/jabber/jabber.h Thu May 07 21:20:16 2009 +0000 +++ b/libpurple/protocols/jabber/jabber.h Wed May 13 20:37:46 2009 +0000 @@ -75,6 +75,8 @@ /* Index into attention_types list */ #define JABBER_BUZZ 0 +PurplePlugin *jabber_plugin; + typedef enum { JABBER_STREAM_OFFLINE, JABBER_STREAM_CONNECTING,
--- a/libpurple/protocols/jabber/libxmpp.c Thu May 07 21:20:16 2009 +0000 +++ b/libpurple/protocols/jabber/libxmpp.c Wed May 13 20:37:46 2009 +0000 @@ -46,6 +46,8 @@ #include "data.h" #include "ibb.h" +PurplePlugin *jabber_plugin = NULL; + static PurplePluginProtocolInfo prpl_info = { OPT_PROTO_CHAT_TOPIC | OPT_PROTO_UNIQUE_CHATNAME | OPT_PROTO_MAIL_CHECK | @@ -125,6 +127,8 @@ static gboolean load_plugin(PurplePlugin *plugin) { + jabber_plugin = plugin; + purple_signal_register(plugin, "jabber-receiving-xmlnode", purple_marshal_VOID__POINTER_POINTER, NULL, 2, purple_value_new(PURPLE_TYPE_SUBTYPE, PURPLE_SUBTYPE_CONNECTION), @@ -140,16 +144,65 @@ purple_value_new(PURPLE_TYPE_SUBTYPE, PURPLE_SUBTYPE_CONNECTION), purple_value_new_outgoing(PURPLE_TYPE_STRING)); + purple_signal_register(plugin, "jabber-receiving-message", + purple_marshal_BOOLEAN__POINTER_POINTER_POINTER, + purple_value_new(PURPLE_TYPE_BOOLEAN), 6, + purple_value_new(PURPLE_TYPE_SUBTYPE, PURPLE_SUBTYPE_CONNECTION), + purple_value_new(PURPLE_TYPE_STRING), /* type */ + purple_value_new(PURPLE_TYPE_STRING), /* id */ + purple_value_new(PURPLE_TYPE_STRING), /* from */ + purple_value_new(PURPLE_TYPE_STRING), /* to */ + purple_value_new(PURPLE_TYPE_SUBTYPE, PURPLE_SUBTYPE_XMLNODE)); + + purple_signal_register(plugin, "jabber-receiving-iq", + purple_marshal_BOOLEAN__POINTER_POINTER_POINTER_POINTER_POINTER, + purple_value_new(PURPLE_TYPE_BOOLEAN), 5, + purple_value_new(PURPLE_TYPE_SUBTYPE, PURPLE_SUBTYPE_CONNECTION), + purple_value_new(PURPLE_TYPE_STRING), /* type */ + purple_value_new(PURPLE_TYPE_STRING), /* id */ + purple_value_new(PURPLE_TYPE_STRING), /* from */ + purple_value_new(PURPLE_TYPE_SUBTYPE, PURPLE_SUBTYPE_XMLNODE)); + + purple_signal_register(plugin, "jabber-watched-iq", + purple_marshal_BOOLEAN__POINTER_POINTER_POINTER_POINTER_POINTER, + purple_value_new(PURPLE_TYPE_BOOLEAN), 5, + purple_value_new(PURPLE_TYPE_SUBTYPE, PURPLE_SUBTYPE_CONNECTION), + purple_value_new(PURPLE_TYPE_STRING), /* type */ + purple_value_new(PURPLE_TYPE_STRING), /* id */ + purple_value_new(PURPLE_TYPE_STRING), /* from */ + purple_value_new(PURPLE_TYPE_SUBTYPE, PURPLE_SUBTYPE_XMLNODE)); /* child */ + + purple_signal_register(plugin, "jabber-register-namespace-watcher", + purple_marshal_VOID__POINTER_POINTER_POINTER, + NULL, 2, + purple_value_new(PURPLE_TYPE_STRING), /* node */ + purple_value_new(PURPLE_TYPE_STRING)); /* namespace */ + + purple_signal_register(plugin, "jabber-unregister-namespace-watcher", + purple_marshal_VOID__POINTER_POINTER_POINTER, + NULL, 2, + purple_value_new(PURPLE_TYPE_STRING), /* node */ + purple_value_new(PURPLE_TYPE_STRING)); /* namespace */ + + purple_signal_connect(plugin, "jabber-register-namespace-watcher", + plugin, PURPLE_CALLBACK(jabber_iq_signal_register), NULL); + purple_signal_connect(plugin, "jabber-unregister-namespace-watcher", + plugin, PURPLE_CALLBACK(jabber_iq_signal_unregister), NULL); + + purple_signal_register(plugin, "jabber-receiving-presence", + purple_marshal_BOOLEAN__POINTER_POINTER_POINTER_POINTER, + purple_value_new(PURPLE_TYPE_BOOLEAN), 4, + purple_value_new(PURPLE_TYPE_SUBTYPE, PURPLE_SUBTYPE_CONNECTION), + purple_value_new(PURPLE_TYPE_STRING), /* type */ + purple_value_new(PURPLE_TYPE_STRING), /* from */ + purple_value_new(PURPLE_TYPE_SUBTYPE, PURPLE_SUBTYPE_XMLNODE)); + return TRUE; } static gboolean unload_plugin(PurplePlugin *plugin) { - purple_signal_unregister(plugin, "jabber-receiving-xmlnode"); - - purple_signal_unregister(plugin, "jabber-sending-xmlnode"); - - purple_signal_unregister(plugin, "jabber-sending-text"); + purple_signals_unregister_by_instance(plugin); /* reverse order of init_plugin */ jabber_bosh_uninit(); @@ -166,6 +219,8 @@ /* Stay on target...stay on target... Almost there... */ jabber_uninit_plugin(); + jabber_plugin = NULL; + return TRUE; }
--- a/libpurple/protocols/jabber/message.c Thu May 07 21:20:16 2009 +0000 +++ b/libpurple/protocols/jabber/message.c Wed May 13 20:37:46 2009 +0000 @@ -532,16 +532,25 @@ void jabber_message_parse(JabberStream *js, xmlnode *packet) { JabberMessage *jm; - const char *type; + const char *id, *from, *to, *type; xmlnode *child; + gboolean signal_return; + + from = xmlnode_get_attrib(packet, "from"); + id = xmlnode_get_attrib(packet, "id"); + to = xmlnode_get_attrib(packet, "to"); + type = xmlnode_get_attrib(packet, "type"); + + signal_return = GPOINTER_TO_INT(purple_signal_emit_return_1(jabber_plugin, + "jabber-receiving-message", js->gc, type, id, from, to, packet)); + if (signal_return) + return; jm = g_new0(JabberMessage, 1); jm->js = js; jm->sent = time(NULL); jm->delayed = FALSE; - type = xmlnode_get_attrib(packet, "type"); - if(type) { if(!strcmp(type, "normal")) jm->type = JABBER_MESSAGE_NORMAL; @@ -559,9 +568,9 @@ jm->type = JABBER_MESSAGE_NORMAL; } - jm->from = g_strdup(xmlnode_get_attrib(packet, "from")); - jm->to = g_strdup(xmlnode_get_attrib(packet, "to")); - jm->id = g_strdup(xmlnode_get_attrib(packet, "id")); + jm->from = g_strdup(from); + jm->to = g_strdup(to); + jm->id = g_strdup(id); for(child = packet->child; child; child = child->next) { const char *xmlns = xmlnode_get_namespace(child); @@ -912,11 +921,12 @@ static gboolean jabber_conv_support_custom_smileys(const PurpleConnection *gc, - const PurpleConversation *conv, + PurpleConversation *conv, const gchar *who) { JabberStream *js = (JabberStream *) gc->proto_data; JabberBuddy *jb; + JabberChat *chat; if (!js) { purple_debug_error("jabber", @@ -925,7 +935,6 @@ } switch (purple_conversation_get_type(conv)) { - /* for the time being, we will not support custom smileys in MUCs */ case PURPLE_CONV_TYPE_IM: jb = jabber_buddy_find(js, who, FALSE); if (jb) { @@ -934,6 +943,18 @@ return FALSE; } break; + case PURPLE_CONV_TYPE_CHAT: + chat = jabber_chat_find_by_conv(conv); + if (chat) { + /* do not attempt to send custom smileys in a MUC with more than + 10 people, to avoid getting too many BoB requests */ + return jabber_chat_get_num_participants(chat) <= 10 && + jabber_chat_all_participants_have_capability(chat, + XEP_0231_NAMESPACE); + } else { + return FALSE; + } + break; default: return FALSE; break; @@ -1194,6 +1215,7 @@ JabberMessage *jm; JabberStream *js; char *xhtml; + char *tmp; if(!msg || !gc) return 0; @@ -1211,6 +1233,11 @@ jm->id = jabber_get_next_id(jm->js); purple_markup_html_to_xhtml(msg, &xhtml, &jm->body); + tmp = jabber_message_smileyfy_xhtml(jm, xhtml); + if (tmp) { + g_free(xhtml); + xhtml = tmp; + } if (chat->xhtml && !jabber_xhtml_plain_equal(xhtml, jm->body)) jm->xhtml = g_strdup_printf("<html xmlns='http://jabber.org/protocol/xhtml-im'><body xmlns='http://www.w3.org/1999/xhtml'>%s</body></html>", xhtml);
--- a/libpurple/protocols/jabber/oob.h Thu May 07 21:20:16 2009 +0000 +++ b/libpurple/protocols/jabber/oob.h Wed May 13 20:37:46 2009 +0000 @@ -1,5 +1,5 @@ /** - * @file jutil.h utility functions + * @file oob.h out-of-band transfer functions * * purple *
--- a/libpurple/protocols/jabber/ping.h Thu May 07 21:20:16 2009 +0000 +++ b/libpurple/protocols/jabber/ping.h Wed May 13 20:37:46 2009 +0000 @@ -1,5 +1,5 @@ /** - * @file ping.h utility functions + * @file ping.h ping functions * * purple *
--- a/libpurple/protocols/jabber/presence.c Thu May 07 21:20:16 2009 +0000 +++ b/libpurple/protocols/jabber/presence.c Wed May 13 20:37:46 2009 +0000 @@ -429,13 +429,15 @@ jbr->caps.info = info; jbr->caps.exts = exts; - if (jabber_resource_has_capability(jbr, "http://jabber.org/protocol/commands")) { + if (!jbr->commands_fetched && jabber_resource_has_capability(jbr, "http://jabber.org/protocol/commands")) { JabberIq *iq = jabber_iq_new_query(userdata->js, JABBER_IQ_GET, "http://jabber.org/protocol/disco#items"); xmlnode *query = xmlnode_get_child_with_namespace(iq->node, "query", "http://jabber.org/protocol/disco#items"); xmlnode_set_attrib(iq->node, "to", userdata->from); xmlnode_set_attrib(query, "node", "http://jabber.org/protocol/commands"); jabber_iq_set_callback(iq, jabber_adhoc_disco_result_cb, NULL); jabber_iq_send(iq); + + jbr->commands_fetched = TRUE; } g_free(userdata->from); @@ -444,8 +446,8 @@ void jabber_presence_parse(JabberStream *js, xmlnode *packet) { - const char *from = xmlnode_get_attrib(packet, "from"); - const char *type = xmlnode_get_attrib(packet, "type"); + const char *from; + const char *type; const char *real_jid = NULL; const char *affiliation = NULL; const char *role = NULL; @@ -467,10 +469,19 @@ xmlnode *caps = NULL; int idle = 0; gchar *nickname = NULL; + gboolean signal_return; + + from = xmlnode_get_attrib(packet, "from"); + type = xmlnode_get_attrib(packet, "type"); if(!(jb = jabber_buddy_find(js, from, TRUE))) return; + signal_return = GPOINTER_TO_INT(purple_signal_emit_return_1(jabber_plugin, + "jabber-receiving-presence", js->gc, type, from, packet)); + if (signal_return) + return; + if(!(jid = jabber_id_new(from))) return; @@ -854,13 +865,26 @@ /* v1.3 uses: node, ver, and optionally ext. * v1.5 uses: node, ver, and hash. */ if (node && *node && ver && *ver) { - JabberPresenceCapabilities *userdata = g_new0(JabberPresenceCapabilities, 1); - userdata->js = js; - userdata->jb = jb; - userdata->from = g_strdup(from); - jabber_caps_get_info(js, from, node, ver, hash, ext, - (jabber_caps_get_info_cb)jabber_presence_set_capabilities, - userdata); + gchar **exts = ext && *ext ? g_strsplit(ext, " ", -1) : NULL; + jbr = jabber_buddy_find_resource(jb, jid->resource); + + /* Look it up if we don't already have all this information */ + if (!jbr || !jbr->caps.info || + !g_str_equal(node, jbr->caps.info->tuple.node) || + !g_str_equal(ver, jbr->caps.info->tuple.ver) || + !purple_strequal(hash, jbr->caps.info->tuple.hash) || + !jabber_caps_exts_known(jbr->caps.info, (gchar **)exts)) { + JabberPresenceCapabilities *userdata = g_new0(JabberPresenceCapabilities, 1); + userdata->js = js; + userdata->jb = jb; + userdata->from = g_strdup(from); + jabber_caps_get_info(js, from, node, ver, hash, exts, + (jabber_caps_get_info_cb)jabber_presence_set_capabilities, + userdata); + } else { + if (exts) + g_strfreev(exts); + } } }
--- a/libpurple/protocols/jabber/si.h Thu May 07 21:20:16 2009 +0000 +++ b/libpurple/protocols/jabber/si.h Wed May 13 20:37:46 2009 +0000 @@ -1,5 +1,5 @@ /** - * @file jutil.h utility functions + * @file si.h SI transfer functions * * purple *
--- a/libpurple/protocols/msn/notification.c Thu May 07 21:20:16 2009 +0000 +++ b/libpurple/protocols/msn/notification.c Wed May 13 20:37:46 2009 +0000 @@ -1891,14 +1891,11 @@ if (count > 0) { - const char *passport; - const char *url; - - passport = msn_user_get_passport(session->user); - url = session->passport_info.mail_url; + const char *passports[2] = { msn_user_get_passport(session->user) }; + const char *urls[2] = { session->passport_info.mail_url }; purple_notify_emails(gc, count, FALSE, NULL, NULL, - &passport, &url, NULL, NULL); + passports, urls, NULL, NULL); } } @@ -1960,14 +1957,11 @@ if (count > 0) { - const char *passport; - const char *url; - - passport = msn_user_get_passport(session->user); - url = session->passport_info.mail_url; + const char *passports[2] = { msn_user_get_passport(session->user) }; + const char *urls[2] = { session->passport_info.mail_url }; purple_notify_emails(gc, count, FALSE, NULL, NULL, - &passport, &url, NULL, NULL); + passports, urls, NULL, NULL); } }
--- a/libpurple/protocols/msn/oim.c Thu May 07 21:20:16 2009 +0000 +++ b/libpurple/protocols/msn/oim.c Wed May 13 20:37:46 2009 +0000 @@ -764,14 +764,14 @@ if (iu_node != NULL && purple_account_get_check_mail(session->account)) { char *unread = xmlnode_get_data(iu_node); - const char *passport = msn_user_get_passport(session->user); - const char *url = session->passport_info.mail_url; + const char *passports[2] = { msn_user_get_passport(session->user) }; + const char *urls[2] = { session->passport_info.mail_url }; int count = atoi(unread); /* XXX/khc: pretty sure this is wrong */ if (count > 0) purple_notify_emails(session->account->gc, count, FALSE, NULL, - NULL, &passport, &url, NULL, NULL); + NULL, passports, urls, NULL, NULL); g_free(unread); }
--- a/libpurple/protocols/msn/slplink.c Thu May 07 21:20:16 2009 +0000 +++ b/libpurple/protocols/msn/slplink.c Wed May 13 20:37:46 2009 +0000 @@ -683,9 +683,9 @@ size = st.st_size; if(!file_name) { - base = g_path_get_basename(file_path); - u8 = purple_utf8_try_convert(base); - g_free(base); + gchar *basename = g_path_get_basename(file_path); + u8 = purple_utf8_try_convert(basename); + g_free(basename); file_name = u8; }
--- a/libpurple/protocols/msnp9/notification.c Thu May 07 21:20:16 2009 +0000 +++ b/libpurple/protocols/msnp9/notification.c Wed May 13 20:37:46 2009 +0000 @@ -1280,14 +1280,11 @@ if (count > 0) { - const char *passport; - const char *url; + const char *passports[2] = { msn_user_get_passport(session->user) }; + const char *urls[2] = { session->passport_info.file }; - passport = msn_user_get_passport(session->user); - url = session->passport_info.file; - - purple_notify_emails(gc, atoi(unread), FALSE, NULL, NULL, - &passport, &url, NULL, NULL); + purple_notify_emails(gc, count, FALSE, NULL, NULL, + passports, urls, NULL, NULL); } }
--- a/libpurple/protocols/myspace/myspace.c Thu May 07 21:20:16 2009 +0000 +++ b/libpurple/protocols/myspace/myspace.c Wed May 13 20:37:46 2009 +0000 @@ -847,8 +847,6 @@ MsimMessage *body; guint old_inbox_status; guint i, n; - const gchar *froms[5], *tos[5], *urls[5], *subjects[5]; - /* Information for each new inbox message type. */ static struct { @@ -863,16 +861,22 @@ { "FriendRequest", MSIM_INBOX_FRIEND_REQUEST, "http://messaging.myspace.com/index.cfm?fuseaction=mail.friendRequests", NULL }, { "PictureComment", MSIM_INBOX_PICTURE_COMMENT, "http://home.myspace.com/index.cfm?fuseaction=user", NULL } }; + const gchar *froms[G_N_ELEMENTS(message_types) + 1] = { "" }, + *tos[G_N_ELEMENTS(message_types) + 1] = { "" }, + *urls[G_N_ELEMENTS(message_types) + 1] = { "" }, + *subjects[G_N_ELEMENTS(message_types) + 1] = { "" }; + + g_return_if_fail(reply != NULL); /* Can't write _()'d strings in array initializers. Workaround. */ + /* khc: then use N_() in the array initializer and use _() when they are + used */ message_types[0].text = _("New mail messages"); message_types[1].text = _("New blog comments"); message_types[2].text = _("New profile comments"); message_types[3].text = _("New friend requests!"); message_types[4].text = _("New picture comments"); - g_return_if_fail(reply != NULL); - body = msim_msg_get_dictionary(reply, "body"); if (body == NULL) @@ -882,7 +886,7 @@ n = 0; - for (i = 0; i < sizeof(message_types) / sizeof(message_types[0]); ++i) { + for (i = 0; i < G_N_ELEMENTS(message_types); ++i) { const gchar *key; guint bit;
--- a/libpurple/protocols/oscar/oscar.c Thu May 07 21:20:16 2009 +0000 +++ b/libpurple/protocols/oscar/oscar.c Wed May 13 20:37:46 2009 +0000 @@ -930,7 +930,7 @@ PurpleGroup *g = NULL; struct buddyinfo *bi = NULL; char *tmp; - const char *bname, *gname = NULL; + const char *bname = NULL, *gname = NULL; od = purple_connection_get_protocol_data(gc); account = purple_connection_get_account(gc); @@ -938,14 +938,14 @@ if ((user_info == NULL) || ((b == NULL) && (userinfo == NULL))) return; - bname = purple_buddy_get_name(b); if (userinfo == NULL) - userinfo = aim_locate_finduserinfo(od, bname); + userinfo = aim_locate_finduserinfo(od, purple_buddy_get_name(b)); if (b == NULL) b = purple_find_buddy(account, userinfo->bn); if (b != NULL) { + bname = purple_buddy_get_name(b); g = purple_buddy_get_group(b); gname = purple_group_get_name(g); presence = purple_buddy_get_presence(b); @@ -3571,8 +3571,10 @@ purple_account_get_username(account), emailinfo->domain ? "@" : "", emailinfo->domain ? emailinfo->domain : ""); + const char *tos[2] = { to }; + const char *urls[2] = { emailinfo->url }; purple_notify_emails(gc, emailinfo->nummsgs, FALSE, NULL, NULL, - (const char **)&to, (const char **)&emailinfo->url, NULL, NULL); + tos, urls, NULL, NULL); g_free(to); }
--- a/libpurple/protocols/qq/qq_crypt.c Thu May 07 21:20:16 2009 +0000 +++ b/libpurple/protocols/qq/qq_crypt.c Wed May 13 20:37:46 2009 +0000 @@ -163,9 +163,11 @@ c32_prev[0] = crypted32[0]; c32_prev[1] = crypted32[1]; /* set next 64 bits want to crypt*/ - crypted_ptr += 8; - memcpy(crypted32, crypted_ptr, sizeof(crypted32)); - plain32[0] = crypted32[0] ^ c32_prev[0]; plain32[1] = crypted32[1] ^ c32_prev[1]; + if (count64 > 0) { + crypted_ptr += 8; + memcpy(crypted32, crypted_ptr, sizeof(crypted32)); + plain32[0] = crypted32[0] ^ c32_prev[0]; plain32[1] = crypted32[1] ^ c32_prev[1]; + } } }
--- a/libpurple/protocols/yahoo/yahoo.c Thu May 07 21:20:16 2009 +0000 +++ b/libpurple/protocols/yahoo/yahoo.c Wed May 13 20:37:46 2009 +0000 @@ -1520,10 +1520,10 @@ g_free(dec_subj); g_free(from); } else if (count > 0) { - const char *to = purple_account_get_username(account); - const char *url = yahoo_mail_url; - - purple_notify_emails(gc, count, FALSE, NULL, NULL, &to, &url, + const char *tos[2] = { purple_account_get_username(account) }; + const char *urls[2] = { yahoo_mail_url }; + + purple_notify_emails(gc, count, FALSE, NULL, NULL, tos, urls, NULL, NULL); } } @@ -4753,8 +4753,10 @@ status = purple_presence_get_active_status(purple_account_get_presence(purple_connection_get_account(gc))); tmp = purple_status_get_attr_string(status, "message"); if (tmp != NULL) { - msg = yahoo_string_encode(gc, tmp, NULL); + gboolean utf8 = TRUE; + msg = yahoo_string_encode(gc, tmp, &utf8); msg2 = purple_markup_strip_html(msg); + yahoo_packet_hash_str(pkt, 97, utf8 ? "1" : 0); yahoo_packet_hash_str(pkt, 19, msg2); } else { /* get_yahoo_status_from_purple_status() returns YAHOO_STATUS_CUSTOM for
--- a/libpurple/win32/global.mak Thu May 07 21:20:16 2009 +0000 +++ b/libpurple/win32/global.mak Wed May 13 20:37:46 2009 +0000 @@ -103,6 +103,7 @@ endif GMSGFMT ?= $(GTK_BIN)/msgfmt MAKENSIS ?= makensis.exe +MAKENSISOPT ?= / PERL ?= /cygdrive/c/perl/bin/perl WINDRES ?= windres STRIP ?= strip
--- a/pidgin/gtkconv.c Thu May 07 21:20:16 2009 +0000 +++ b/pidgin/gtkconv.c Wed May 13 20:37:46 2009 +0000 @@ -8324,6 +8324,9 @@ gtkconv->unseen_state = state; } + purple_conversation_set_data(gtkconv->active_conv, "unseen-count", GINT_TO_POINTER(gtkconv->unseen_count)); + purple_conversation_set_data(gtkconv->active_conv, "unseen-state", GINT_TO_POINTER(gtkconv->unseen_state)); + purple_conversation_update(gtkconv->active_conv, PURPLE_CONV_UPDATE_UNSEEN); }
--- a/pidgin/win32/pidgin_dll_rc.rc.in Thu May 07 21:20:16 2009 +0000 +++ b/pidgin/win32/pidgin_dll_rc.rc.in Wed May 13 20:37:46 2009 +0000 @@ -2,8 +2,6 @@ #include "version.h" #include "resource.h" -#define PIXMAPDIR "pixmaps/tray/16/" - VS_VERSION_INFO VERSIONINFO FILEVERSION PURPLE_MAJOR_VERSION,PURPLE_MINOR_VERSION,PURPLE_MICRO_VERSION,0 PRODUCTVERSION PURPLE_MAJOR_VERSION,PURPLE_MINOR_VERSION,PURPLE_MICRO_VERSION,0 @@ -33,11 +31,11 @@ END END -PIDGIN_TRAY_AVAILABLE_4BIT ICON PIXMAPDIR "available_4bit.ico" -PIDGIN_TRAY_AWAY_4BIT ICON PIXMAPDIR "away_4bit.ico" -PIDGIN_TRAY_BUSY_4BIT ICON PIXMAPDIR "busy_4bit.ico" -PIDGIN_TRAY_XA_4BIT ICON PIXMAPDIR "extended-away_4bit.ico" -PIDGIN_TRAY_OFFLINE_4BIT ICON PIXMAPDIR "offline_4bit.ico" -PIDGIN_TRAY_CONNECTING_4BIT ICON PIXMAPDIR "connecting_4bit.ico" -PIDGIN_TRAY_PENDING_4BIT ICON PIXMAPDIR "message_4bit.ico" -PIDGIN_TRAY_INVISIBLE_4BIT ICON PIXMAPDIR "invisible_4bit.ico" +PIDGIN_TRAY_AVAILABLE_4BIT ICON "pixmaps/tray/16/available_4bit.ico" +PIDGIN_TRAY_AWAY_4BIT ICON "pixmaps/tray/16/away_4bit.ico" +PIDGIN_TRAY_BUSY_4BIT ICON "pixmaps/tray/16/busy_4bit.ico" +PIDGIN_TRAY_XA_4BIT ICON "pixmaps/tray/16/extended-away_4bit.ico" +PIDGIN_TRAY_OFFLINE_4BIT ICON "pixmaps/tray/16/offline_4bit.ico" +PIDGIN_TRAY_CONNECTING_4BIT ICON "pixmaps/tray/16/connecting_4bit.ico" +PIDGIN_TRAY_PENDING_4BIT ICON "pixmaps/tray/16/message_4bit.ico" +PIDGIN_TRAY_INVISIBLE_4BIT ICON "pixmaps/tray/16/invisible_4bit.ico"
--- a/pidgin/win32/pidgin_exe_rc.rc.in Thu May 07 21:20:16 2009 +0000 +++ b/pidgin/win32/pidgin_exe_rc.rc.in Wed May 13 20:37:46 2009 +0000 @@ -2,8 +2,6 @@ #include "resource.h" #include "version.h" -#define PIXMAPDIR "pixmaps/" - VS_VERSION_INFO VERSIONINFO FILEVERSION PURPLE_MAJOR_VERSION,PURPLE_MINOR_VERSION,PURPLE_MICRO_VERSION,0 PRODUCTVERSION PURPLE_MAJOR_VERSION,PURPLE_MINOR_VERSION,PURPLE_MICRO_VERSION,0 @@ -33,4 +31,4 @@ END END -PIDGIN_ICON ICON PIXMAPDIR "pidgin.ico" +PIDGIN_ICON ICON "pixmaps/pidgin.ico"