# HG changeset patch # User Paul Aurich # Date 1242107374 0 # Node ID 92565c8e1e3a32ab2ac5fdd6781586a88b9d4c57 # Parent 329f5a43b68a5799b347c3e32d5152dc67ee642b Add jabber signals for IQ, Message, and Presence stanzas. Lightly tested (it doesn't crash [Prove me wrong!]) and as you'll note, I refer to documentation that doesn't yet exist. diff -r 329f5a43b68a -r 92565c8e1e3a ChangeLog.API --- a/ChangeLog.API Mon May 11 22:05:00 2009 +0000 +++ b/ChangeLog.API Tue May 12 05:49:34 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 diff -r 329f5a43b68a -r 92565c8e1e3a libpurple/protocols/jabber/iq.c --- a/libpurple/protocols/jabber/iq.c Mon May 11 22:05:00 2009 +0000 +++ b/libpurple/protocols/jabber/iq.c Tue May 12 05:49:34 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; } diff -r 329f5a43b68a -r 92565c8e1e3a libpurple/protocols/jabber/iq.h --- a/libpurple/protocols/jabber/iq.h Mon May 11 22:05:00 2009 +0000 +++ b/libpurple/protocols/jabber/iq.h Tue May 12 05:49:34 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_ */ diff -r 329f5a43b68a -r 92565c8e1e3a libpurple/protocols/jabber/jabber.c --- a/libpurple/protocols/jabber/jabber.c Mon May 11 22:05:00 2009 +0000 +++ b/libpurple/protocols/jabber/jabber.c Tue May 12 05:49:34 2009 +0000 @@ -3380,6 +3380,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, @@ -3389,6 +3390,8 @@ void jabber_uninit_plugin(void) { + purple_plugin_ipc_unregister_all(jabber_plugin); + jabber_features_destroy(); jabber_identities_destroy(); } diff -r 329f5a43b68a -r 92565c8e1e3a libpurple/protocols/jabber/jabber.h --- a/libpurple/protocols/jabber/jabber.h Mon May 11 22:05:00 2009 +0000 +++ b/libpurple/protocols/jabber/jabber.h Tue May 12 05:49:34 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, diff -r 329f5a43b68a -r 92565c8e1e3a libpurple/protocols/jabber/libxmpp.c --- a/libpurple/protocols/jabber/libxmpp.c Mon May 11 22:05:00 2009 +0000 +++ b/libpurple/protocols/jabber/libxmpp.c Tue May 12 05:49:34 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; } diff -r 329f5a43b68a -r 92565c8e1e3a libpurple/protocols/jabber/message.c --- a/libpurple/protocols/jabber/message.c Mon May 11 22:05:00 2009 +0000 +++ b/libpurple/protocols/jabber/message.c Tue May 12 05:49:34 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); diff -r 329f5a43b68a -r 92565c8e1e3a libpurple/protocols/jabber/presence.c --- a/libpurple/protocols/jabber/presence.c Mon May 11 22:05:00 2009 +0000 +++ b/libpurple/protocols/jabber/presence.c Tue May 12 05:49:34 2009 +0000 @@ -446,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; @@ -469,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;