[telepathy-gabble/master] Parse the results of unextended searches.
Will Thompson
will.thompson at collabora.co.uk
Wed Aug 26 09:22:04 PDT 2009
---
src/search-channel.c | 212 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 212 insertions(+), 0 deletions(-)
diff --git a/src/search-channel.c b/src/search-channel.c
index 326dceb..43da256 100644
--- a/src/search-channel.c
+++ b/src/search-channel.c
@@ -315,6 +315,182 @@ request_search_fields (GabbleSearchChannel *chan)
/* Search implementation */
+/**
+ * make_field:
+ * @field_name: name of a vCard field; must be a static string.
+ * @values: strv of values for the field.
+ *
+ * Returns: the Contact_Info_Field (field_name, [], values).
+ */
+static GValueArray *
+make_field (const gchar *field_name,
+ gchar **values)
+{
+ GValueArray *field = g_value_array_new (3);
+ GValue *value;
+ static const gchar **empty = { NULL };
+
+ g_value_array_append (field, NULL);
+ value = g_value_array_get_nth (field, 0);
+ g_value_init (value, G_TYPE_STRING);
+ g_value_set_static_string (value, field_name);
+
+ g_value_array_append (field, NULL);
+ value = g_value_array_get_nth (field, 1);
+ g_value_init (value, G_TYPE_STRV);
+ g_value_set_static_boxed (value, empty);
+
+ g_value_array_append (field, NULL);
+ value = g_value_array_get_nth (field, 2);
+ g_value_init (value, G_TYPE_STRV);
+ g_value_set_boxed (value, values);
+
+ return field;
+}
+
+static gchar *
+ht_lookup_and_remove (GHashTable *info_map,
+ gchar *field_name)
+{
+ gchar *ret = g_hash_table_lookup (info_map, field_name);
+
+ g_hash_table_remove (info_map, field_name);
+
+ return ret;
+}
+
+static void
+emit_search_result (GabbleSearchChannel *chan,
+ TpHandleRepoIface *handles,
+ GHashTable *info_map)
+{
+ GPtrArray *info = g_ptr_array_new ();
+ gchar *jid, *first, *last, *nick, *email;
+ TpHandle h;
+ GError *e = NULL;
+
+ jid = ht_lookup_and_remove (info_map, "jid");
+ last = ht_lookup_and_remove (info_map, "last");
+ first = ht_lookup_and_remove (info_map, "first");
+ nick = ht_lookup_and_remove (info_map, "nick");
+ email = ht_lookup_and_remove (info_map, "email");
+
+ if (jid == NULL)
+ {
+ DEBUG ("no jid; giving up");
+ goto out;
+ }
+
+ h = tp_handle_ensure (handles, jid, NULL, &e);
+
+ if (h == 0)
+ {
+ DEBUG ("invalid jid: %s", e->message);
+ g_error_free (e);
+ goto out;
+ }
+
+ tp_handle_set_add (chan->priv->result_handles, h);
+
+ {
+ gchar *components[] = { jid, NULL };
+ g_ptr_array_add (info, make_field ("x-telepathy-identifier", components));
+ }
+
+ /* Build 'n' field: Family Name, Given Name, Additional Names, Honorific
+ * Prefixes, and Honorific Suffixes.
+ */
+ if (last != NULL || first != NULL)
+ {
+ gchar *components[] = {
+ (last == NULL ? "" : last),
+ (first == NULL ? "" : first),
+ "",
+ "",
+ "",
+ NULL
+ };
+ g_ptr_array_add (info, make_field ("n", components));
+ }
+
+ /* Build 'nickname' field. */
+ if (nick != NULL)
+ {
+ gchar *components[] = { nick, NULL };
+ g_ptr_array_add (info, make_field ("nickname", components));
+ }
+
+ /* Build 'email' field */
+ if (email != NULL)
+ {
+ gchar *components[] = { email, NULL };
+ g_ptr_array_add (info, make_field ("email", components));
+ }
+
+ if (g_hash_table_size (info_map) > 0)
+ DEBUG ("<item> contained fields we don't understand; ignoring them");
+
+ gabble_svc_channel_type_contact_search_emit_search_result_received (chan, h, info);
+
+out:
+ {
+ GValue v = { 0, };
+
+ g_value_init (&v, GABBLE_ARRAY_TYPE_CONTACT_INFO_FIELD_LIST);
+ g_value_take_boxed (&v, info);
+ g_value_unset (&v);
+
+ if (h != 0)
+ tp_handle_unref (handles, h);
+ }
+}
+
+static void
+parse_result_item (GabbleSearchChannel *chan,
+ TpHandleRepoIface *handles,
+ LmMessageNode *item)
+{
+ const gchar *jid = lm_message_node_get_attribute (item, "jid");
+ GHashTable *info;
+ LmMessageNode *n;
+
+ if (jid == NULL)
+ {
+ DEBUG ("<item> didn't have a jid attribute; skipping");
+ return;
+ }
+
+ info = g_hash_table_new (g_str_hash, g_str_equal);
+ g_hash_table_insert (info, "jid", (gchar *) jid);
+
+ for (n = item->children; n != NULL; n = n->next)
+ {
+ gchar *value = (gchar *) lm_message_node_get_value (n);
+
+ g_hash_table_insert (info, n->name, value);
+ }
+
+ emit_search_result (chan, handles, info);
+}
+
+static void
+parse_search_results (GabbleSearchChannel *chan,
+ LmMessageNode *query_node)
+{
+ TpHandleRepoIface *handles = tp_base_connection_get_handles (
+ (TpBaseConnection *) chan->base.conn, TP_HANDLE_TYPE_CONTACT);
+ LmMessageNode *item;
+
+ for (item = query_node->children; item != NULL; item = item->next)
+ {
+ if (!strcmp (item->name, "item"))
+ parse_result_item (chan, handles, item);
+ else
+ DEBUG ("found <%s/> in <query/> rather than <item/>, skipping",
+ item->name);
+ }
+}
+
static LmHandlerResult
search_reply_cb (GabbleConnection *conn,
LmMessage *sent_msg,
@@ -322,8 +498,44 @@ search_reply_cb (GabbleConnection *conn,
GObject *object,
gpointer user_data)
{
+ GabbleSearchChannel *chan = GABBLE_SEARCH_CHANNEL (object);
+ LmMessageNode *query_node;
+ GError *err = NULL;
+
DEBUG ("called");
+ query_node = lm_message_node_get_child_with_namespace (reply_msg->node,
+ "query", NS_SEARCH);
+
+ if (lm_message_get_sub_type (reply_msg) == LM_MESSAGE_SUB_TYPE_ERROR)
+ {
+ err = gabble_message_get_xmpp_error (reply_msg);
+
+ if (err == NULL)
+ err = g_error_new (TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ "%s gave us an error we don't understand", chan->priv->server);
+ }
+ else if (NULL == query_node)
+ {
+ err = g_error_new (TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ "%s is broken: it replied to our <query> with an empty IQ",
+ chan->priv->server);
+ }
+
+ if (err != NULL)
+ {
+ DEBUG ("Searching failed: %s", err->message);
+ g_error_free (err);
+ }
+ else
+ {
+ parse_search_results (chan, query_node);
+ }
+
+ g_object_set (chan,
+ "search-state", GABBLE_CHANNEL_CONTACT_SEARCH_STATE_COMPLETED,
+ NULL);
+
return LM_HANDLER_RESULT_REMOVE_MESSAGE;
}
--
1.5.6.5
More information about the telepathy-commits
mailing list