summaryrefslogtreecommitdiff
path: root/src/vcard-manager.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/vcard-manager.c')
-rw-r--r--src/vcard-manager.c249
1 files changed, 142 insertions, 107 deletions
diff --git a/src/vcard-manager.c b/src/vcard-manager.c
index 872e865e9..67466be01 100644
--- a/src/vcard-manager.c
+++ b/src/vcard-manager.c
@@ -26,6 +26,7 @@
#include <telepathy-glib/dbus.h>
#include <telepathy-glib/heap.h>
+#include <wocky/wocky.h>
#define DEBUG_FLAG GABBLE_DEBUG_VCARD
@@ -154,7 +155,7 @@ struct _GabbleVCardManagerPrivate
/* Patched vCard that we sent to the server to update, but haven't
* got confirmation yet. We don't want to store it in cache (visible
* to others) before we're sure the server accepts it. */
- LmMessageNode *patched_vcard;
+ WockyNode *patched_vcard;
};
struct _GabbleVCardManagerRequest
@@ -208,7 +209,7 @@ struct _GabbleVCardCacheEntry
guint suspended_timer_id;
/* VCard node for this entry (owned reference), or NULL if there's no node */
- LmMessageNode *vcard_node;
+ WockyNode *vcard_node;
/* If @vcard_node is not NULL, the time the message will expire */
time_t expires;
@@ -235,7 +236,7 @@ gabble_vcard_manager_cache_quark (void)
static void cache_entry_free (void *data);
static gint cache_entry_compare (gconstpointer a, gconstpointer b);
static void manager_patch_vcard (
- GabbleVCardManager *self, LmMessageNode *vcard_node);
+ GabbleVCardManager *self, WockyNode *vcard_node);
static void request_send (GabbleVCardManagerRequest *request,
guint timeout);
@@ -350,6 +351,42 @@ gabble_vcard_manager_set_property (GObject *object,
}
}
+static gboolean
+copy_attribute (const gchar *key,
+ const gchar *value,
+ const gchar *prefix,
+ const gchar *ns,
+ gpointer user_data)
+{
+ WockyNode *copy = (WockyNode *) user_data;
+
+ wocky_node_set_attribute_ns (copy, key, value, ns);
+ return TRUE;
+}
+
+static WockyNode *
+copy_node (WockyNode *node)
+{
+ WockyNode *copy;
+ GSList *l;
+
+ copy = wocky_node_new (node->name, wocky_node_get_ns (node));
+ wocky_node_set_content (copy, node->content);
+ wocky_node_set_language (copy, wocky_node_get_language (node));
+
+ wocky_node_each_attribute (node, copy_attribute, copy);
+
+ for (l = node->children; l != NULL; l = g_slist_next (l))
+ {
+ WockyNode *child = l->data;
+
+ copy->children = g_slist_prepend (copy->children, copy_node (child));
+ }
+ copy->children = g_slist_reverse (copy->children);
+
+ return copy;
+}
+
static void delete_request (GabbleVCardManagerRequest *request);
static void cancel_request (GabbleVCardManagerRequest *request);
static void cancel_all_edit_requests (GabbleVCardManager *manager);
@@ -382,7 +419,7 @@ cache_entry_free (gpointer data)
gabble_request_pipeline_item_cancel (entry->pipeline_item);
}
- tp_clear_pointer (&entry->vcard_node, lm_message_node_unref);
+ tp_clear_pointer (&entry->vcard_node, wocky_node_free);
tp_handle_unref (contact_repo, entry->handle);
@@ -503,13 +540,13 @@ gabble_vcard_manager_invalidate_cache (GabbleVCardManager *manager,
tp_heap_remove (priv->timed_cache, entry);
- tp_clear_pointer (&entry->vcard_node, lm_message_node_unref);
+ tp_clear_pointer (&entry->vcard_node, wocky_node_free);
cache_entry_attempt_to_free (entry);
}
static void complete_one_request (GabbleVCardManagerRequest *request,
- LmMessageNode *vcard_node, GError *error);
+ WockyNode *vcard_node, GError *error);
static void
cache_entry_complete_requests (GabbleVCardCacheEntry *entry, GError *error)
@@ -530,7 +567,7 @@ cache_entry_complete_requests (GabbleVCardCacheEntry *entry, GError *error)
static void
complete_one_request (GabbleVCardManagerRequest *request,
- LmMessageNode *vcard_node,
+ WockyNode *vcard_node,
GError *error)
{
if (request->callback)
@@ -609,26 +646,26 @@ gabble_vcard_manager_finalize (GObject *object)
}
gchar *
-vcard_get_avatar_sha1 (LmMessageNode *vcard)
+vcard_get_avatar_sha1 (WockyNode *vcard)
{
gchar *sha1;
const gchar *binval_value;
GString *avatar;
- LmMessageNode *node;
- LmMessageNode *binval;
+ WockyNode *node;
+ WockyNode *binval;
- node = lm_message_node_get_child (vcard, "PHOTO");
+ node = wocky_node_get_child (vcard, "PHOTO");
if (!node)
return g_strdup ("");
DEBUG ("Our vCard has a PHOTO %p", node);
- binval = lm_message_node_get_child (node, "BINVAL");
+ binval = wocky_node_get_child (node, "BINVAL");
if (!binval)
return g_strdup ("");
- binval_value = lm_message_node_get_value (binval);
+ binval_value = binval->content;
if (!binval_value)
return g_strdup ("");
@@ -655,7 +692,7 @@ static void
initial_request_cb (GabbleVCardManager *self,
GabbleVCardManagerRequest *request,
TpHandle handle,
- LmMessageNode *vcard,
+ WockyNode *vcard,
GError *error,
gpointer user_data)
{
@@ -810,17 +847,17 @@ cancel_request (GabbleVCardManagerRequest *request)
}
static gchar *
-extract_nickname (LmMessageNode *vcard_node)
+extract_nickname (WockyNode *vcard_node)
{
- LmMessageNode *node;
+ WockyNode *node;
const gchar *nick;
- node = lm_message_node_get_child (vcard_node, "NICKNAME");
+ node = wocky_node_get_child (vcard_node, "NICKNAME");
if (node == NULL)
return NULL;
- nick = lm_message_node_get_value (node);
+ nick = node->content;
return g_strdup (nick);
}
@@ -829,7 +866,7 @@ static void
observe_vcard (GabbleConnection *conn,
GabbleVCardManager *manager,
TpHandle handle,
- LmMessageNode *vcard_node)
+ WockyNode *vcard_node)
{
TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
(TpBaseConnection *) conn, TP_HANDLE_TYPE_CONTACT);
@@ -841,11 +878,11 @@ observe_vcard (GabbleConnection *conn,
if (alias == NULL)
{
- LmMessageNode *fn_node = lm_message_node_get_child (vcard_node, "FN");
+ WockyNode *fn_node = wocky_node_get_child (vcard_node, "FN");
if (fn_node != NULL)
{
- const gchar *fn = lm_message_node_get_value (fn_node);
+ const gchar *fn = fn_node->content;
if (!tp_str_empty (fn))
{
@@ -893,7 +930,7 @@ observe_vcard (GabbleConnection *conn,
*/
static void
replace_reply_cb (GabbleConnection *conn,
- LmMessage *reply_msg,
+ WockyStanza *reply_msg,
gpointer user_data,
GError *error)
{
@@ -901,7 +938,7 @@ replace_reply_cb (GabbleConnection *conn,
GabbleVCardManagerPrivate *priv = self->priv;
TpBaseConnection *base = (TpBaseConnection *) conn;
GList *li;
- LmMessageNode *node = NULL;
+ WockyNode *node = NULL;
/* If we sent a SET request, it's dead now. */
priv->edit_pipeline_item = NULL;
@@ -911,7 +948,7 @@ replace_reply_cb (GabbleConnection *conn,
if (error)
{
/* We won't need our patched vcard after all */
- tp_clear_pointer (&priv->patched_vcard, lm_message_node_unref);
+ tp_clear_pointer (&priv->patched_vcard, wocky_node_free);
}
else
{
@@ -921,7 +958,7 @@ replace_reply_cb (GabbleConnection *conn,
g_assert (priv->patched_vcard != NULL);
/* Finally we may put the new vcard in the cache. */
- tp_clear_pointer (&entry->vcard_node, lm_message_node_unref);
+ tp_clear_pointer (&entry->vcard_node, wocky_node_free);
entry->vcard_node = priv->patched_vcard;
priv->patched_vcard = NULL;
@@ -974,21 +1011,19 @@ replace_reply_cb (GabbleConnection *conn,
* (NICKNAME, PHOTO and in future FN are the problematic ones). */
static gboolean
gabble_vcard_manager_replace_is_significant (GabbleVCardManagerEditInfo *info,
- LmMessageNode *old_vcard)
+ WockyNode *old_vcard)
{
gboolean seen = FALSE;
- NodeIter i;
+ WockyNodeIter i;
+ WockyNode *node;
- for (i = node_iter (old_vcard); i != NULL; i = node_iter_next (i))
+ /* Find the first node matching the one we want to edit */
+ wocky_node_iter_init (&i, old_vcard, info->element_name, NULL);
+ while (wocky_node_iter_next (&i, &node))
{
- LmMessageNode *node = node_iter_data (i);
const gchar *value;
const gchar *new_value;
- /* skip over nodes that aren't the one we want to edit */
- if (tp_strdiff (info->element_name, node->name))
- continue;
-
/* if there are >= 2 copies of this field, we're going to reduce that
* to 1 */
if (seen)
@@ -996,7 +1031,7 @@ gabble_vcard_manager_replace_is_significant (GabbleVCardManagerEditInfo *info,
/* consider NULL and "" to be different representations for the
* same thing */
- value = lm_message_node_get_value (node);
+ value = node->content;
new_value = info->element_value;
if (value == NULL)
@@ -1024,11 +1059,11 @@ gabble_vcard_manager_replace_is_significant (GabbleVCardManagerEditInfo *info,
child_iter = child_iter->next)
{
GabbleVCardChild *child = child_iter->data;
- LmMessageNode *child_node = lm_message_node_get_child (node,
+ WockyNode *child_node = wocky_node_get_child (node,
child->key);
if (child_node == NULL ||
- tp_strdiff (lm_message_node_get_value (child_node),
+ tp_strdiff (child_node->content,
child->value))
{
return TRUE;
@@ -1048,17 +1083,17 @@ gabble_vcard_manager_replace_is_significant (GabbleVCardManagerEditInfo *info,
return !seen;
}
-static LmMessageNode *vcard_copy (LmMessageNode *parent, LmMessageNode *src,
+static WockyNode *vcard_copy (WockyNode *parent, WockyNode *src,
const gchar *exclude, gboolean *exclude_mattered);
-static LmMessage *
+static WockyStanza *
gabble_vcard_manager_edit_info_apply (GabbleVCardManagerEditInfo *info,
- LmMessageNode *old_vcard,
+ WockyNode *old_vcard,
GabbleVCardManager *vcard_manager)
{
- LmMessage *msg;
- LmMessageNode *vcard_node;
- LmMessageNode *node;
+ WockyStanza *msg;
+ WockyNode *vcard_node;
+ WockyNode *node;
GList *iter;
gboolean maybe_changed = FALSE;
GabbleConnection *conn = vcard_manager->priv->connection;
@@ -1087,7 +1122,7 @@ gabble_vcard_manager_edit_info_apply (GabbleVCardManagerEditInfo *info,
* */
gchar *alias;
- node = lm_message_node_get_child (old_vcard, info->element_name);
+ node = wocky_node_get_child (old_vcard, info->element_name);
/* If the user has set this field explicitly via SetContactInfo(),
* that takes precedence */
@@ -1132,28 +1167,28 @@ gabble_vcard_manager_edit_info_apply (GabbleVCardManagerEditInfo *info,
return NULL;
}
- msg = lm_message_new_with_sub_type (NULL, LM_MESSAGE_TYPE_IQ,
- LM_MESSAGE_SUB_TYPE_SET);
+ msg = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET,
+ NULL, NULL, NULL);
if (info->edit_type == GABBLE_VCARD_EDIT_CLEAR)
{
/* start from a clean slate... */
- vcard_node = lm_message_node_add_child (
+ vcard_node = wocky_node_add_child_with_content (
wocky_stanza_get_top_node (msg), "vCard", "");
- lm_message_node_set_attribute (vcard_node, "xmlns", "vcard-temp");
+ vcard_node->ns = g_quark_from_string ("vcard-temp");
/* ... but as a special case, the photo gets copied in from the old
* vCard, because SetContactInfo doesn't touch photos */
- node = lm_message_node_get_child (old_vcard, "PHOTO");
+ node = wocky_node_get_child (old_vcard, "PHOTO");
if (node != NULL)
vcard_copy (vcard_node, node, NULL, NULL);
- /* Yes, we can do this: "LmMessageNode" is really a WockyNode */
+ /* Yes, we can do this: "WockyNode" is really a WockyNode */
if (wocky_node_equal (old_vcard, vcard_node))
{
/* nothing actually happened, forget it */
- lm_message_unref (msg);
+ g_object_unref (msg);
return NULL;
}
@@ -1179,21 +1214,21 @@ gabble_vcard_manager_edit_info_apply (GabbleVCardManagerEditInfo *info,
{
maybe_changed = TRUE;
- node = lm_message_node_add_child (vcard_node,
+ node = wocky_node_add_child_with_content (vcard_node,
info->element_name, info->element_value);
for (iter = info->children; iter != NULL; iter = iter->next)
{
GabbleVCardChild *child = iter->data;
- lm_message_node_add_child (node, child->key, child->value);
+ wocky_node_add_child_with_content (node, child->key, child->value);
}
}
if ((!maybe_changed) || wocky_node_equal (old_vcard, vcard_node))
{
/* nothing actually happened, forget it */
- lm_message_unref (msg);
+ g_object_unref (msg);
return NULL;
}
@@ -1204,24 +1239,25 @@ gabble_vcard_manager_edit_info_apply (GabbleVCardManagerEditInfo *info,
*
* Note that this function doesn't copy any attributes other than
* xmlns, because LM provides no way to iterate over attributes. Thanks, LM. */
-static LmMessageNode *
-vcard_copy (LmMessageNode *parent,
- LmMessageNode *src,
+static WockyNode *
+vcard_copy (WockyNode *parent,
+ WockyNode *src,
const gchar *exclude,
gboolean *exclude_mattered)
{
- LmMessageNode *new = lm_message_node_add_child (parent, src->name,
- lm_message_node_get_value (src));
+ WockyNode *new = wocky_node_add_child_with_content (parent, src->name,
+ src->content);
const gchar *xmlns;
- NodeIter i;
+ WockyNodeIter i;
+ WockyNode *child;
- xmlns = lm_message_node_get_attribute (src, "xmlns");
+ xmlns = wocky_node_get_ns (src);
if (xmlns != NULL)
- lm_message_node_set_attribute (new, "xmlns", xmlns);
+ new->ns = g_quark_from_string (xmlns);
- for (i = node_iter (src); i; i = node_iter_next (i))
+ wocky_node_iter_init (&i, src, NULL, NULL);
+ while (wocky_node_iter_next (&i, &child))
{
- LmMessageNode *child = node_iter_data (i);
if (tp_strdiff (child->name, exclude))
{
@@ -1239,10 +1275,10 @@ vcard_copy (LmMessageNode *parent,
static void
manager_patch_vcard (GabbleVCardManager *self,
- LmMessageNode *vcard_node)
+ WockyNode *vcard_node)
{
GabbleVCardManagerPrivate *priv = self->priv;
- LmMessage *msg = NULL;
+ WockyStanza *msg = NULL;
GList *li;
/* Bail out if we don't have outstanding edits to make, or if we already
@@ -1254,19 +1290,19 @@ manager_patch_vcard (GabbleVCardManager *self,
/* Apply any unsent edits to the patched vCard */
for (li = priv->edits; li != NULL; li = li->next)
{
- LmMessage *new_msg = gabble_vcard_manager_edit_info_apply (
+ WockyStanza *new_msg = gabble_vcard_manager_edit_info_apply (
li->data, vcard_node, self);
/* edit_info_apply returns NULL if nothing happened */
if (new_msg == NULL)
continue;
- tp_clear_pointer (&msg, lm_message_unref);
+ tp_clear_pointer (&msg, g_object_unref);
msg = new_msg;
/* gabble_vcard_manager_edit_info_apply always returns an IQ message
* with one vCard child */
- vcard_node = lm_message_node_get_child (
+ vcard_node = wocky_node_get_child (
wocky_stanza_get_top_node (msg), "vCard");
g_assert (vcard_node != NULL);
}
@@ -1282,13 +1318,13 @@ manager_patch_vcard (GabbleVCardManager *self,
/* We'll save the patched vcard, and if the server says
* we're ok, put it into the cache. But we want to leave the
* original vcard in the cache until that happens. */
- priv->patched_vcard = lm_message_node_ref (vcard_node);
+ priv->patched_vcard = copy_node (vcard_node);
priv->edit_pipeline_item = gabble_request_pipeline_enqueue (
priv->connection->req_pipeline, msg, default_request_timeout,
replace_reply_cb, self);
- lm_message_unref (msg);
+ g_object_unref (msg);
out:
/* We've applied those, forget about them */
@@ -1321,14 +1357,14 @@ suspended_request_timeout_cb (gpointer data)
static gboolean
is_item_not_found (const GError *error)
{
- return (error->domain == GABBLE_XMPP_ERROR &&
- error->code == XMPP_ERROR_ITEM_NOT_FOUND);
+ return (error->domain == WOCKY_XMPP_ERROR &&
+ error->code == WOCKY_XMPP_ERROR_ITEM_NOT_FOUND);
}
/* Called when a GET request in the pipeline has either succeeded or failed. */
static void
pipeline_reply_cb (GabbleConnection *conn,
- LmMessage *reply_msg,
+ WockyStanza *reply_msg,
gpointer user_data,
GError *error)
{
@@ -1339,7 +1375,7 @@ pipeline_reply_cb (GabbleConnection *conn,
TpBaseConnection *base = (TpBaseConnection *) conn;
TpHandleRepoIface *contact_repo =
tp_base_connection_get_handles (base, TP_HANDLE_TYPE_CONTACT);
- LmMessageNode *vcard_node = NULL;
+ WockyNode *vcard_node = NULL;
DEBUG("called for entry %p", entry);
@@ -1358,33 +1394,32 @@ pipeline_reply_cb (GabbleConnection *conn,
{
/* First, handle the error "wait": suspend the request and replay it
* later */
- LmMessageNode *error_node = NULL;
- GabbleXmppError xmpp_error = XMPP_ERROR_UNDEFINED_CONDITION;
- GabbleXmppErrorType error_type = XMPP_ERROR_UNDEFINED_CONDITION;
+ WockyXmppErrorType error_type = WOCKY_XMPP_ERROR_TYPE_CANCEL;
+ GError *stanza_error = NULL;
- /* FIXME: add a helper in error.c to extract the type, error, and message
- * from an XMPP stanza.
- */
- if (reply_msg != NULL)
- error_node = lm_message_node_get_child (
- wocky_stanza_get_top_node (reply_msg), "error");
-
- if (error_node != NULL)
- xmpp_error = gabble_xmpp_error_from_node (error_node, &error_type);
-
- if (error_type == XMPP_ERROR_TYPE_WAIT)
+ if (reply_msg != NULL &&
+ wocky_stanza_extract_errors (reply_msg, &error_type, &stanza_error,
+ NULL, NULL))
{
- DEBUG ("Retrieving %u's vCard returned a temporary <%s/> error; "
- "trying againg in %u seconds", entry->handle,
- gabble_xmpp_error_string (xmpp_error), request_wait_delay);
+ if (error_type == WOCKY_XMPP_ERROR_TYPE_WAIT)
+ {
+ DEBUG ("%s", g_quark_to_string (stanza_error->domain));
+ DEBUG ("Retrieving %u's vCard returned a temporary <%s/> error; "
+ "trying againg in %u seconds", entry->handle,
+ wocky_xmpp_stanza_error_to_string (stanza_error),
+ request_wait_delay);
+
+ g_source_remove (request->timer_id);
+ request->timer_id = 0;
- g_source_remove (request->timer_id);
- request->timer_id = 0;
+ entry->suspended_timer_id = g_timeout_add_seconds (
+ request_wait_delay, suspended_request_timeout_cb, request);
- entry->suspended_timer_id = g_timeout_add_seconds (
- request_wait_delay, suspended_request_timeout_cb, request);
+ g_error_free (stanza_error);
+ return;
+ }
- return;
+ g_error_free (stanza_error);
}
/* If request for our own vCard failed, and we do have
@@ -1408,7 +1443,7 @@ pipeline_reply_cb (GabbleConnection *conn,
g_assert (reply_msg != NULL);
- vcard_node = lm_message_node_get_child (
+ vcard_node = wocky_node_get_child (
wocky_stanza_get_top_node (reply_msg), "vCard");
if (NULL == vcard_node)
@@ -1417,14 +1452,14 @@ pipeline_reply_cb (GabbleConnection *conn,
DEBUG ("successful lookup response contained no <vCard> node, "
"creating an empty one");
- vcard_node = lm_message_node_add_child (
+ vcard_node = wocky_node_add_child_with_content (
wocky_stanza_get_top_node (reply_msg), "vCard",
NULL);
- lm_message_node_set_attribute (vcard_node, "xmlns", NS_VCARD_TEMP);
+ vcard_node->ns = g_quark_from_string (NS_VCARD_TEMP);
}
/* Put the message in the cache */
- entry->vcard_node = lm_message_node_ref (vcard_node);
+ entry->vcard_node = copy_node (vcard_node);
entry->expires = time (NULL) + VCARD_CACHE_ENTRY_TTL;
tp_heap_add (priv->timed_cache, entry);
@@ -1483,7 +1518,7 @@ request_send (GabbleVCardManagerRequest *request, guint timeout)
else
{
const char *jid;
- LmMessage *msg;
+ WockyStanza *msg;
request->timer_id =
g_timeout_add_seconds (request->timeout, timeout_request, request);
@@ -1499,17 +1534,17 @@ request_send (GabbleVCardManagerRequest *request, guint timeout)
DEBUG ("Cache entry %p is not mine, @to = %s", entry, jid);
}
- msg = lm_message_build_with_sub_type (jid,
- LM_MESSAGE_TYPE_IQ, LM_MESSAGE_SUB_TYPE_GET,
- '(', "vCard", "",
- '@', "xmlns", NS_VCARD_TEMP,
+ msg = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET,
+ NULL, jid,
+ '(', "vCard",
+ ':', NS_VCARD_TEMP,
')',
NULL);
entry->pipeline_item = gabble_request_pipeline_enqueue (
conn->req_pipeline, msg, timeout, pipeline_reply_cb, request);
- lm_message_unref (msg);
+ g_object_unref (msg);
DEBUG ("adding request to cache entry %p and queueing the <iq>", entry);
}
@@ -1695,7 +1730,7 @@ gabble_vcard_manager_cancel_request (GabbleVCardManager *self,
gboolean
gabble_vcard_manager_get_cached (GabbleVCardManager *self,
TpHandle handle,
- LmMessageNode **node)
+ WockyNode **node)
{
GabbleVCardManagerPrivate *priv = self->priv;
GabbleVCardCacheEntry *entry = g_hash_table_lookup (priv->cache,