diff -r d0f3a028347a -r 59927b2d3b75 telepathygabble/src/vcard-manager.c --- a/telepathygabble/src/vcard-manager.c Tue Feb 02 01:10:06 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,956 +0,0 @@ -/* - * vcard-manager.c - Source for Gabble vCard lookup helper - * - * Copyright (C) 2006 Collabora Ltd. - * - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - - -#include -#include - -#include "debug.h" -#include "gabble-connection.h" -#include "namespaces.h" -#include "telepathy-helpers.h" -#include "util.h" -#include "vcard-manager.h" - -#include "gabble_enums.h" - -#define DBUS_API_SUBJECT_TO_CHANGE -#define DEBUG_FLAG GABBLE_DEBUG_VCARD -#define DEFAULT_REQUEST_TIMEOUT 20000 - -#ifdef DEBUG_FLAG -//#define DEBUG(format, ...) -#define DEBUGGING 0 -#define NODE_DEBUG(n, s) -#endif /* DEBUG_FLAG */ - - -#ifndef EMULATOR -G_DEFINE_TYPE(GabbleVCardManager, gabble_vcard_manager, G_TYPE_OBJECT); -#endif - -/* signal enum */ -enum -{ - NICKNAME_UPDATE, - LAST_SIGNAL -#ifdef EMULATOR - = LAST_SIGNAL_VCARD_MGR -#endif - -}; - -#ifdef EMULATOR -#include "libgabble_wsd_solution.h" - - GET_STATIC_ARRAY_FROM_TLS(signals,gabble_vcard_mgr,guint) - #define signals (GET_WSD_VAR_NAME(signals,gabble_vcard_mgr, s)()) - - GET_STATIC_VAR_FROM_TLS(quark1,gabble_vcard_mgr,GQuark) - #define quark1 (*GET_WSD_VAR_NAME(quark1,gabble_vcard_mgr, s)()) - - GET_STATIC_VAR_FROM_TLS(quark2,gabble_vcard_mgr,GQuark) - #define quark2 (*GET_WSD_VAR_NAME(quark2,gabble_vcard_mgr, s)()) - - GET_STATIC_VAR_FROM_TLS(gabble_vcard_manager_parent_class,gabble_vcard_mgr,gpointer) - #define gabble_vcard_manager_parent_class (*GET_WSD_VAR_NAME(gabble_vcard_manager_parent_class,gabble_vcard_mgr,s)()) - - GET_STATIC_VAR_FROM_TLS(g_define_type_id,gabble_vcard_mgr,GType) - #define g_define_type_id (*GET_WSD_VAR_NAME(g_define_type_id,gabble_vcard_mgr,s)()) - - GET_STATIC_ARRAY_FROM_TLS(NO_ALIAS,gabble_vcard_mgr,gchar) - #define NO_ALIAS (GET_WSD_VAR_NAME(NO_ALIAS,gabble_vcard_mgr,s)()) - -static void gabble_vcard_manager_init (GabbleVCardManager *self); -static void gabble_vcard_manager_class_init (GabbleVCardManagerClass *klass); -static void gabble_vcard_manager_class_intern_init (gpointer klass) - { - gabble_vcard_manager_parent_class = g_type_class_peek_parent (klass); - gabble_vcard_manager_class_init ((GabbleVCardManagerClass*) klass); - } - EXPORT_C GType gabble_vcard_manager_get_type (void) - { - if ((g_define_type_id == 0)) { static const GTypeInfo g_define_type_info = { sizeof (GabbleVCardManagerClass), (GBaseInitFunc) ((void *)0), (GBaseFinalizeFunc) ((void *)0), (GClassInitFunc) gabble_vcard_manager_class_intern_init, (GClassFinalizeFunc) ((void *)0), ((void *)0), sizeof (GabbleVCardManager), 0, (GInstanceInitFunc) gabble_vcard_manager_init, ((void *)0) }; g_define_type_id = g_type_register_static ( ((GType) ((20) << (2))), g_intern_static_string ("GabbleVCardManager"), &g_define_type_info, (GTypeFlags) 0); { {} ; } } return g_define_type_id; } ; - -#else - - static guint signals[LAST_SIGNAL] = {0}; - - static const gchar *NO_ALIAS = "none"; - -#endif - - -/* Properties */ -enum -{ - PROP_CONNECTION = 1, - LAST_PROPERTY -}; - - - -typedef struct _GabbleVCardManagerPrivate GabbleVCardManagerPrivate; -struct _GabbleVCardManagerPrivate -{ - GabbleConnection *connection; - GList *requests; - gboolean dispose_has_run; -}; - -struct _GabbleVCardManagerRequest -{ - GabbleVCardManager *manager; - guint timer_id; - guint timeout; - - GabbleHandle handle; - gchar **edit_args; - - GabbleVCardManagerCb callback; - gpointer user_data; - GObject *bound_object; -}; - -GQuark -gabble_vcard_manager_error_quark (void) -{ - -#ifndef EMULATOR - static GQuark quark1 = 0; -#endif - - if (!quark1) - quark1 = g_quark_from_static_string ("gabble-vcard-manager-error"); - return quark1; -} - -GQuark -gabble_vcard_manager_cache_quark (void) -{ - -#ifndef EMULATOR - static GQuark quark2 = 0; -#endif - - if (!quark2) - quark2 = g_quark_from_static_string ("gabble-vcard-manager-cache"); - return quark2; -} - -#define GABBLE_VCARD_MANAGER_GET_PRIVATE(o) ((GabbleVCardManagerPrivate*)((o)->priv)); - -static void -gabble_vcard_manager_init (GabbleVCardManager *obj) -{ - GabbleVCardManagerPrivate *priv = - G_TYPE_INSTANCE_GET_PRIVATE (obj, GABBLE_TYPE_VCARD_MANAGER, GabbleVCardManagerPrivate); - obj->priv = priv; - -} - -static void gabble_vcard_manager_set_property (GObject *object, guint property_id, - const GValue *value, GParamSpec *pspec); -static void gabble_vcard_manager_get_property (GObject *object, guint property_id, - GValue *value, GParamSpec *pspec); -static void gabble_vcard_manager_dispose (GObject *object); -static void gabble_vcard_manager_finalize (GObject *object); - -static void -gabble_vcard_manager_class_init (GabbleVCardManagerClass *gabble_vcard_manager_class) -{ - GObjectClass *object_class = G_OBJECT_CLASS (gabble_vcard_manager_class); - GParamSpec *param_spec; - - g_type_class_add_private (gabble_vcard_manager_class, sizeof (GabbleVCardManagerPrivate)); - - object_class->get_property = gabble_vcard_manager_get_property; - object_class->set_property = gabble_vcard_manager_set_property; - - object_class->dispose = gabble_vcard_manager_dispose; - object_class->finalize = gabble_vcard_manager_finalize; - - param_spec = g_param_spec_object ("connection", "GabbleConnection object", - "Gabble connection object that owns this " - "vCard lookup helper object.", - GABBLE_TYPE_CONNECTION, - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_READWRITE | - G_PARAM_STATIC_NICK | - G_PARAM_STATIC_BLURB); - g_object_class_install_property (object_class, PROP_CONNECTION, param_spec); - - /* signal definitions */ - - signals[NICKNAME_UPDATE] = - g_signal_new ("nickname-update", - G_TYPE_FROM_CLASS (gabble_vcard_manager_class), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, - g_cclosure_marshal_VOID__UINT, - G_TYPE_NONE, 1, G_TYPE_UINT); - -} - -static void -gabble_vcard_manager_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec) -{ - GabbleVCardManager *chan = GABBLE_VCARD_MANAGER (object); - GabbleVCardManagerPrivate *priv = GABBLE_VCARD_MANAGER_GET_PRIVATE (chan); - - switch (property_id) { - case PROP_CONNECTION: - g_value_set_object (value, priv->connection); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - break; - } -} - -static void -gabble_vcard_manager_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec) -{ - GabbleVCardManager *chan = GABBLE_VCARD_MANAGER (object); - GabbleVCardManagerPrivate *priv = GABBLE_VCARD_MANAGER_GET_PRIVATE (chan); - - switch (property_id) { - case PROP_CONNECTION: - priv->connection = g_value_get_object (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - break; - } -} - -static void cancel_request (GabbleVCardManagerRequest *request); - -void -gabble_vcard_manager_dispose (GObject *object) -{ - DBusGProxy *bus_proxy; - GabbleVCardManager *self = GABBLE_VCARD_MANAGER (object); - GabbleVCardManagerPrivate *priv = GABBLE_VCARD_MANAGER_GET_PRIVATE (self); - bus_proxy = tp_get_bus_proxy (); - - if (priv->dispose_has_run) - return; - - priv->dispose_has_run = TRUE; - - /* cancel request removes the element from the list after cancelling */ - while (priv->requests) - cancel_request (priv->requests->data); - - if (G_OBJECT_CLASS (gabble_vcard_manager_parent_class)->dispose) - G_OBJECT_CLASS (gabble_vcard_manager_parent_class)->dispose (object); -} - -void -gabble_vcard_manager_finalize (GObject *object) -{ - G_OBJECT_CLASS (gabble_vcard_manager_parent_class)->finalize (object); -} - -static void -status_changed_cb (GObject *object, - guint status, - guint reason, - gpointer user_data) -{ - GabbleVCardManager *self = GABBLE_VCARD_MANAGER (user_data); - GabbleConnection *conn = GABBLE_CONNECTION (object); - - if (status == TP_CONN_STATUS_CONNECTED) - { - gchar *alias; - GabbleConnectionAliasSource alias_src; - - /* if we have a better alias, patch it into our vCard on the server */ - alias_src = _gabble_connection_get_cached_alias (conn, - conn->self_handle, - &alias); - if (alias_src > GABBLE_CONNECTION_ALIAS_FROM_VCARD) - { - /* ignore errors, just kick off the request in the background */ - gabble_vcard_manager_edit (self, 0, NULL, NULL, G_OBJECT (conn), - NULL, "NICKNAME", alias, NULL); - } - else - { - /* find out our own alias, so it's in the cache; again, - * there's nothing useful we can do with errors really - */ - gabble_vcard_manager_request (self, conn->self_handle, - 0, NULL, NULL, NULL, NULL); - } - - g_free(alias); - } -} - -/** - * gabble_vcard_manager_new: - * @conn: The #GabbleConnection to use for vCard lookup - * - * Creates an object to use for Jabber vCard lookup (JEP 0054). - * There should be one of these per connection - */ -GabbleVCardManager * -gabble_vcard_manager_new (GabbleConnection *conn) -{ - GabbleVCardManager *self; - - g_return_val_if_fail (GABBLE_IS_CONNECTION (conn), NULL); - - self = GABBLE_VCARD_MANAGER (g_object_new (GABBLE_TYPE_VCARD_MANAGER, "connection", conn, NULL)); - g_signal_connect (conn, "status-changed", - G_CALLBACK (status_changed_cb), self); - return self; -} - -static void notify_delete_request (gpointer data, GObject *obj); - -static void -delete_request (GabbleVCardManagerRequest *request) -{ - GabbleVCardManager *manager = request->manager; - GabbleVCardManagerPrivate *priv; - - gabble_debug (DEBUG_FLAG, "Discarding request %p", request); - - g_assert (NULL != request); - g_assert (GABBLE_IS_VCARD_MANAGER (manager)); - - priv = GABBLE_VCARD_MANAGER_GET_PRIVATE (manager); - - g_assert (NULL != g_list_find (priv->requests, request)); - - priv->requests = g_list_remove (priv->requests, request); - - if (NULL != request->bound_object) - { - g_object_weak_unref (request->bound_object, notify_delete_request, request); - } - - if (0 != request->timer_id) - { - g_source_remove (request->timer_id); - } - - gabble_handle_unref (priv->connection->handles, TP_HANDLE_TYPE_CONTACT, - request->handle); - g_strfreev (request->edit_args); - - g_free (request); -} - -static gboolean -timeout_request (gpointer data) -{ - GabbleVCardManagerRequest *request = (GabbleVCardManagerRequest*) data; - GError *err; - g_return_val_if_fail (data != NULL, FALSE); - - err = g_error_new (GABBLE_VCARD_MANAGER_ERROR, GABBLE_VCARD_MANAGER_ERROR_TIMEOUT, - "Request timed out"); - gabble_debug (DEBUG_FLAG, "Request %p timed out, notifying callback %p", - request, request->callback); - if (request->callback) - { - (request->callback)(request->manager, request, request->handle, - NULL, err, request->user_data); - } - g_error_free (err); - - request->timer_id = 0; - delete_request (request); - return FALSE; -} - -static void -cancel_request (GabbleVCardManagerRequest *request) -{ - GError *err; - - g_assert (request != NULL); - - err = g_error_new (GABBLE_VCARD_MANAGER_ERROR, GABBLE_VCARD_MANAGER_ERROR_CANCELLED, - "Request cancelled"); - gabble_debug (DEBUG_FLAG, "Request %p cancelled, notifying callback %p", - request, request->callback); - if (request->callback) - { - (request->callback)(request->manager, request, request->handle, - NULL, err, request->user_data); - } - g_error_free (err); - - delete_request (request); -} - -static void -observe_vcard (GabbleConnection *conn, GabbleVCardManager *manager, - GabbleHandle handle, LmMessageNode *vcard_node) -{ - LmMessageNode *nick_node = lm_message_node_get_child (vcard_node, - "NICKNAME"); - - gabble_debug (DEBUG_FLAG, "Observing vCard for %u", handle); - NODE_DEBUG(vcard_node, "their vCard is"); - - if (nick_node) - { - const gchar *nick = lm_message_node_get_value (nick_node); - - gabble_debug (DEBUG_FLAG, "%u has \"%s\"", handle, nick ? nick : "(null)"); - - if (nick && *nick) - { - /* nicknames are comma-separated, let's use the first one */ - gchar **bits = g_strsplit (nick, ",", 2); - - if (bits[0]) - { - gchar *alias = g_strdup (bits[0]); - - gabble_debug (DEBUG_FLAG, "... using \"%s\" as their alias", alias); - - g_signal_emit (G_OBJECT (manager), signals[NICKNAME_UPDATE], - 0, handle); - if (!gabble_handle_set_qdata (conn->handles, - TP_HANDLE_TYPE_CONTACT, - handle, - gabble_vcard_manager_cache_quark(), - alias, g_free)) - { - gabble_debug (DEBUG_FLAG, "failed to cache their alias"); - g_free (alias); - } - - } - - g_strfreev (bits); - } - } - else - { - const gchar *fn = NULL; - /* let's see if they have a FN (formatted name) instead */ - nick_node = lm_message_node_get_child (vcard_node, "FN"); - if (nick_node) - fn = lm_message_node_get_value (nick_node); - gabble_debug (DEBUG_FLAG, "%u has no , but has \"%s\"", handle, - fn ? fn : "(null)"); - if (fn && *fn) - { - gchar *alias = g_strdup (fn); - - gabble_debug (DEBUG_FLAG, "... using \"%s\" as their alias", alias); - - g_signal_emit (G_OBJECT (manager), signals[NICKNAME_UPDATE], - 0, handle); - if (!gabble_handle_set_qdata (conn->handles, - TP_HANDLE_TYPE_CONTACT, - handle, - gabble_vcard_manager_cache_quark(), - alias, g_free)) - { - gabble_debug (DEBUG_FLAG, "failed to cache their alias"); - g_free (alias); - } - } - else - { - /* remember that they don't have an alias */ - if (!gabble_handle_set_qdata (conn->handles, - TP_HANDLE_TYPE_CONTACT, - handle, - gabble_vcard_manager_cache_quark (), - (gchar *) NO_ALIAS, NULL)) - gabble_debug (DEBUG_FLAG, "failed to cache their lack of vcard alias"); - } - - } -} - -static GabbleVCardManagerRequest *request_send (GabbleVCardManagerRequest *, - LmMessageNode *replacement, - const gchar *jid, - GError **); - -static LmHandlerResult -replace_reply_cb (GabbleConnection *conn, LmMessage *sent_msg, - LmMessage *reply_msg, GObject *object, gpointer user_data) -{ - LmMessageNode *vcard_node = NULL; - GError *err = NULL; - GabbleVCardManagerRequest *request = (GabbleVCardManagerRequest*) user_data; - GabbleVCardManager *manager = GABBLE_VCARD_MANAGER (object); - GabbleVCardManagerPrivate *priv = GABBLE_VCARD_MANAGER_GET_PRIVATE (manager); - - g_assert (request); - - gabble_debug (DEBUG_FLAG, "Replace request got a reply: conn@%p, sent_msg@%p, reply_msg@%p, " - "bound object@%p, request@%p", conn, sent_msg, reply_msg, object, - user_data); - - if (!g_list_find (priv->requests, request)) - { - gabble_debug (DEBUG_FLAG, "I don't care about that request any more"); - return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS; - } - - if (lm_message_get_sub_type (reply_msg) == LM_MESSAGE_SUB_TYPE_ERROR) - { - LmMessageNode *error_node; - - error_node = lm_message_node_get_child (reply_msg->node, "error"); - if (error_node) - { - err = gabble_xmpp_error_to_g_error ( - gabble_xmpp_error_from_node (error_node)); - } - - if (err == NULL) - { - err = g_error_new (GABBLE_VCARD_MANAGER_ERROR, - GABBLE_VCARD_MANAGER_ERROR_UNKNOWN, - "an unknown error occurred"); - } - } - else - { - vcard_node = lm_message_node_get_child (sent_msg->node, "vCard"); - } - - gabble_debug (DEBUG_FLAG, "Request %p %s, notifying callback %p", request, - err ? "failed" : "succeeded", request->callback); - if (request->callback) - { - request->callback (request->manager, request, request->handle, - vcard_node, err, request->user_data); - } - delete_request (request); - - if (err) - g_error_free (err); - - return LM_HANDLER_RESULT_REMOVE_MESSAGE; -} - -static LmHandlerResult -request_reply_cb (GabbleConnection *conn, - LmMessage *sent_msg, - LmMessage *reply_msg, - GObject *object, - gpointer user_data) -{ - LmMessageNode *vcard_node = NULL; - GError *err = NULL; - GabbleVCardManagerRequest *request = (GabbleVCardManagerRequest*) user_data; - GabbleVCardManager *manager = GABBLE_VCARD_MANAGER (object); - GabbleVCardManagerPrivate *priv = GABBLE_VCARD_MANAGER_GET_PRIVATE (manager); - - g_assert (request); - - gabble_debug (DEBUG_FLAG, "Fetch request got a reply: conn@%p, sent_msg@%p, reply_msg@%p, " - "bound object@%p, request@%p", conn, sent_msg, reply_msg, object, - user_data); - - if (!g_list_find (priv->requests, request)) - { - gabble_debug (DEBUG_FLAG, "I don't care about that request any more"); - return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS; - } - - - if (lm_message_get_sub_type (reply_msg) == LM_MESSAGE_SUB_TYPE_ERROR) - { - LmMessageNode *error_node; - - error_node = lm_message_node_get_child (reply_msg->node, "error"); - if (error_node) - { - err = gabble_xmpp_error_to_g_error ( - gabble_xmpp_error_from_node (error_node)); - } - - if (err == NULL) - { - err = g_error_new (GABBLE_VCARD_MANAGER_ERROR, - GABBLE_VCARD_MANAGER_ERROR_UNKNOWN, - "an unknown error occurred"); - } - } - else - { - vcard_node = lm_message_node_get_child (reply_msg->node, "vCard"); - - if (NULL == vcard_node) - { - gabble_debug (DEBUG_FLAG, "successful lookup response contained no node, " - "creating an empty one"); - - vcard_node = lm_message_node_add_child (reply_msg->node, "vCard", - NULL); - lm_message_node_set_attribute (vcard_node, "xmlns", NS_VCARD_TEMP); - } - - observe_vcard (conn, manager, request->handle, vcard_node); - } - - if (vcard_node && request->edit_args) - { - gchar **ptr; - for (ptr = request->edit_args; *ptr; ptr++) - { - gchar *key = *ptr; - gchar *value = *(++ptr); - LmMessageNode *node; - - if (!value) - { - /* oops, someone passed in an odd number of args. */ - g_assert_not_reached (); - break; - } - - node = lm_message_node_get_child (vcard_node, key); - if (node) - { - lm_message_node_set_value (node, value); - } - else - { - node = lm_message_node_add_child (vcard_node, key, value); - } - } - - request_send (request, vcard_node, NULL, &err); - - if (err) - { - gabble_debug (DEBUG_FLAG, "Request %p failed, notifying callback %p", - request, request->callback); - if (request->callback) - { - request->callback (request->manager, request, request->handle, - NULL, err, request->user_data); - } - } - else - { - gabble_debug (DEBUG_FLAG, "Request %p fetch succeeded", request); - /* early return to avoid deleting the request */ - return LM_HANDLER_RESULT_REMOVE_MESSAGE; - } - } - else - { - gabble_debug (DEBUG_FLAG, "Request %p %s, notifying callback %p", - request, err ? "failed" : "succeeded", request->callback); - if (request->callback) - { - request->callback (request->manager, request, request->handle, - vcard_node, err, request->user_data); - } - } - - delete_request (request); - - if (err) - g_error_free (err); - - return LM_HANDLER_RESULT_REMOVE_MESSAGE; -} - -/* If @replacement is NULL sends a request, calling request_reply_cb when - * it returns. - * - * Otherwise steals its children and sends an update, calling - * replace_reply_cb when it returns. - * - * Frees the @request on error, returns it on success. */ -static GabbleVCardManagerRequest * -request_send (GabbleVCardManagerRequest *request, - LmMessageNode *replacement, - const gchar *jid, - GError **error) -{ - LmMessage *msg; - LmMessageNode *lm_node; - GabbleVCardManager *self = request->manager; - GabbleVCardManagerPrivate *priv = GABBLE_VCARD_MANAGER_GET_PRIVATE (self); - - gabble_debug (DEBUG_FLAG, "Sending off request %p to %s for %s", request, - replacement ? "replace vCard" : "retrieve vCard", - jid ? jid : "myself"); - msg = lm_message_new_with_sub_type (jid, LM_MESSAGE_TYPE_IQ, - (replacement - ? LM_MESSAGE_SUB_TYPE_SET - : LM_MESSAGE_SUB_TYPE_GET)); - lm_node = lm_message_node_add_child (msg->node, "vCard", NULL); - lm_message_node_set_attribute (lm_node, "xmlns", NS_VCARD_TEMP); - - if (replacement) - lm_message_node_steal_children (lm_node, replacement); - - if (! _gabble_connection_send_with_reply (priv->connection, msg, - (replacement ? replace_reply_cb : request_reply_cb), - G_OBJECT(self), request, error)) - { - delete_request (request); - lm_message_unref (msg); - return NULL; - } - else - { - if (0 == request->timer_id) - { - request->timer_id = - g_timeout_add (request->timeout, timeout_request, request); - } - lm_message_unref (msg); - return request; - } -} - -static void -notify_delete_request (gpointer data, GObject *obj) -{ - GabbleVCardManagerRequest *request = (GabbleVCardManagerRequest *) data; - request->bound_object = NULL; - delete_request (request); -} - -/* Request the vCard for the given handle. When it arrives, call the given - * callback. - * - * The callback may be NULL if you just want the side-effect of this - * operation, which is to update the cached alias. - */ -GabbleVCardManagerRequest * -gabble_vcard_manager_request (GabbleVCardManager *self, - GabbleHandle handle, - guint timeout, - GabbleVCardManagerCb callback, - gpointer user_data, - GObject *object, - GError **error) -{ - GabbleVCardManagerRequest *request; - const gchar *jid; - GabbleVCardManagerPrivate *priv = GABBLE_VCARD_MANAGER_GET_PRIVATE (self); - - if (timeout == 0) - timeout = DEFAULT_REQUEST_TIMEOUT; - - request = g_new0 (GabbleVCardManagerRequest, 1); - gabble_debug (DEBUG_FLAG, "Created request %p to retrieve <%u>'s vCard", - request, handle); - request->timeout = timeout; - request->manager = self; - gabble_handle_ref (priv->connection->handles, TP_HANDLE_TYPE_CONTACT, - handle); - request->handle = handle; - request->callback = callback; - request->user_data = user_data; - request->bound_object = object; - - if (NULL != object) - g_object_weak_ref (object, notify_delete_request, request); - - priv->requests = g_list_prepend (priv->requests, request); - if (handle == priv->connection->self_handle) - { - jid = NULL; - } - else - { - jid = gabble_handle_inspect (priv->connection->handles, - TP_HANDLE_TYPE_CONTACT, handle); - } - - return request_send (request, NULL, jid, error); -} - -GabbleVCardManagerRequest * -gabble_vcard_manager_replace (GabbleVCardManager *self, - LmMessageNode *replacement, - guint timeout, - GabbleVCardManagerCb callback, - gpointer user_data, - GObject *object, - GError **error) -{ - GabbleVCardManagerRequest *request; - GabbleVCardManagerPrivate *priv = GABBLE_VCARD_MANAGER_GET_PRIVATE (self); - - if (timeout == 0) - timeout = DEFAULT_REQUEST_TIMEOUT; - - request = g_new0 (GabbleVCardManagerRequest, 1); - gabble_debug (DEBUG_FLAG, "Created request %p to replace my vCard", - request); - request->timeout = timeout; - request->manager = self; - gabble_handle_ref (priv->connection->handles, TP_HANDLE_TYPE_CONTACT, - priv->connection->self_handle); - request->handle = priv->connection->self_handle; - request->callback = callback; - request->user_data = user_data; - request->bound_object = object; - - if (NULL != object) - g_object_weak_ref (object, notify_delete_request, request); - - priv->requests = g_list_prepend (priv->requests, request); - - return request_send (request, replacement, NULL, error); -} - -GabbleVCardManagerRequest * -gabble_vcard_manager_edit (GabbleVCardManager *self, - guint timeout, - GabbleVCardManagerCb callback, - gpointer user_data, - GObject *object, - GError **error, - ...) -{ - va_list ap; - size_t i, argc; - GabbleVCardManagerRequest *request; - GabbleVCardManagerPrivate *priv = GABBLE_VCARD_MANAGER_GET_PRIVATE (self); - - if (timeout == 0) - timeout = DEFAULT_REQUEST_TIMEOUT; - - request = g_new0 (GabbleVCardManagerRequest, 1); - gabble_debug (DEBUG_FLAG, "Created request %p to edit my vCard", request); - request->timeout = timeout; - request->manager = self; - gabble_handle_ref (priv->connection->handles, TP_HANDLE_TYPE_CONTACT, - priv->connection->self_handle); - request->handle = priv->connection->self_handle; - request->callback = callback; - request->user_data = user_data; - request->bound_object = object; - - if (NULL != object) - g_object_weak_ref (object, notify_delete_request, request); - - priv->requests = g_list_prepend (priv->requests, request); - - argc = 0; - va_start (ap, error); - while (va_arg (ap, const gchar *) != NULL) - { - argc++; - } - va_end (ap); - g_return_val_if_fail (argc % 2 == 0, NULL); - - request->edit_args = g_new (gchar *, argc + 1); - - va_start (ap, error); - for (i = 0; i < argc; i++) - { - request->edit_args[i] = g_strdup (va_arg (ap, const gchar *)); - } - request->edit_args[argc] = NULL; - va_end (ap); - - return request_send (request, NULL, NULL, error); -} - -void -gabble_vcard_manager_cancel_request (GabbleVCardManager *manager, - GabbleVCardManagerRequest *request) -{ - GabbleVCardManagerPrivate *priv; - - g_return_if_fail (GABBLE_IS_VCARD_MANAGER (manager)); - g_return_if_fail (NULL != request); - - priv = GABBLE_VCARD_MANAGER_GET_PRIVATE (manager); - - g_return_if_fail (NULL != g_list_find (priv->requests, request)); - - cancel_request (request); -} - -/** - * Return the cached alias derived from the vCard for the given handle, - * if any. If there is no cached alias, return NULL. - */ -const gchar * -gabble_vcard_manager_get_cached_alias (GabbleVCardManager *manager, - GabbleHandle handle) -{ - GabbleVCardManagerPrivate *priv; - const gchar *s; - - g_return_val_if_fail (GABBLE_IS_VCARD_MANAGER (manager), NULL); - - priv = GABBLE_VCARD_MANAGER_GET_PRIVATE (manager); - - s = gabble_handle_get_qdata (priv->connection->handles, - TP_HANDLE_TYPE_CONTACT, - handle, - gabble_vcard_manager_cache_quark()); - - if (s == NO_ALIAS) - s = NULL; - - gabble_debug (DEBUG_FLAG, "Cached alias for %u is \"%s\"", handle, s ? s : "(null)"); - return s; -} - -/** - * Return TRUE if we've tried looking up an alias for this handle before. - */ -gboolean -gabble_vcard_manager_has_cached_alias (GabbleVCardManager *manager, - GabbleHandle handle) -{ - GabbleVCardManagerPrivate *priv; - gpointer p; - - g_return_val_if_fail (GABBLE_IS_VCARD_MANAGER (manager), FALSE); - - priv = GABBLE_VCARD_MANAGER_GET_PRIVATE (manager); - p = gabble_handle_get_qdata (priv->connection->handles, - TP_HANDLE_TYPE_CONTACT, - handle, - gabble_vcard_manager_cache_quark()); - return p != NULL; -} -