summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Aurich <darkrain42@pidgin.im>2009-05-08 02:38:39 +0000
committerPaul Aurich <darkrain42@pidgin.im>2009-05-08 02:38:39 +0000
commitacf718a063526bfd956dc89893e4170462085b1a (patch)
treec42f838fc4d32e9910edfd5a7485f366ba3be486
parentf1ad85f1b22fd588271432a856dc4d924dcb9504 (diff)
downloadpidgin-acf718a063526bfd956dc89893e4170462085b1a.tar.gz
Only call jabber_caps_get_info if we don't have all the information we want.
Has the pleasant side-effect of *not* polling for adhoc commands every time we get presence (this should make MattJ happy).
-rw-r--r--libpurple/protocols/jabber/caps.c45
-rw-r--r--libpurple/protocols/jabber/caps.h10
-rw-r--r--libpurple/protocols/jabber/presence.c27
3 files changed, 62 insertions, 20 deletions
diff --git a/libpurple/protocols/jabber/caps.c b/libpurple/protocols/jabber/caps.c
index aff2535a17..fabe56f8be 100644
--- a/libpurple/protocols/jabber/caps.c
+++ b/libpurple/protocols/jabber/caps.c
@@ -346,6 +346,27 @@ void jabber_caps_uninit(void)
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 but don't have any */
+ 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;
@@ -539,16 +560,19 @@ jabber_caps_ext_iqcb(JabberStream *js, const char *from, JabberIqType type,
}
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;
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;
@@ -597,9 +621,8 @@ void jabber_caps_get_info(JabberStream *js, const char *who, const char *node,
}
/* 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) {
@@ -611,23 +634,23 @@ void jabber_caps_get_info(JabberStream *js, const char *who, const char *node,
/* 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);
@@ -637,11 +660,11 @@ void jabber_caps_get_info(JabberStream *js, const char *who, const char *node,
++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) {
diff --git a/libpurple/protocols/jabber/caps.h b/libpurple/protocols/jabber/caps.h
index a2f0c16f5f..46a31ac625 100644
--- a/libpurple/protocols/jabber/caps.h
+++ b/libpurple/protocols/jabber/caps.h
@@ -68,7 +68,10 @@ typedef void (*jabber_caps_get_info_cb)(JabberCapsClientInfo *info, GList *exts,
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.
@@ -76,10 +79,13 @@ void jabber_caps_destroy_key(gpointer value);
* 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);
/**
diff --git a/libpurple/protocols/jabber/presence.c b/libpurple/protocols/jabber/presence.c
index 3bf43bd48f..f54c24a9cf 100644
--- a/libpurple/protocols/jabber/presence.c
+++ b/libpurple/protocols/jabber/presence.c
@@ -854,13 +854,26 @@ void jabber_presence_parse(JabberStream *js, xmlnode *packet)
/* 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);
+ }
}
}