diff options
Diffstat (limited to 'src/vcard-manager.c')
-rw-r--r-- | src/vcard-manager.c | 249 |
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, |