summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--extensions/Connection_Interface_Addressing.xml245
-rw-r--r--extensions/Makefile.am1
-rw-r--r--extensions/all.xml6
-rw-r--r--src/Makefile.am4
-rw-r--r--src/addressing-util.c412
-rw-r--r--src/addressing-util.h70
-rw-r--r--src/conn-addressing.c166
-rw-r--r--src/conn-addressing.h34
-rw-r--r--src/connection.c5
-rw-r--r--src/protocol.c77
-rw-r--r--tests/twisted/addressing.py70
-rw-r--r--tests/twisted/constants.py1
-rw-r--r--tests/twisted/servicetest.py1
13 files changed, 1028 insertions, 64 deletions
diff --git a/extensions/Connection_Interface_Addressing.xml b/extensions/Connection_Interface_Addressing.xml
new file mode 100644
index 000000000..db8155f23
--- /dev/null
+++ b/extensions/Connection_Interface_Addressing.xml
@@ -0,0 +1,245 @@
+<?xml version="1.0" ?>
+<node name="/Connection_Interface_Addressing" xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0">
+ <tp:copyright> Copyright (C) 2010 Collabora Limited </tp:copyright>
+ <tp:license xmlns="http://www.w3.org/1999/xhtml">
+ <p>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.</p>
+
+ <p>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.</p>
+
+ <p>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 Street, Fifth Floor, Boston, MA 02110-1301, USA.</p>
+ </tp:license>
+ <interface name="org.freedesktop.Telepathy.Connection.Interface.Addressing.DRAFT"
+ tp:causes-havoc="experimental">
+ <tp:requires interface="org.freedesktop.Telepathy.Connection"/>
+ <tp:requires interface="org.freedesktop.Telepathy.Connection.Interface.Contacts"/>
+ <tp:added version="0.19.12">(as draft)</tp:added>
+ <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
+ <p>This interface deals with the multiple address types that can
+ refer to the same contact, such as vCard fields and URIs.</p>
+
+ <p>It can be used to retrieve contacts with a specific addresses
+ through <tp:member-ref>GetContactsByVCardField</tp:member-ref> and
+ <tp:member-ref>GetContactsByURI</tp:member-ref>, as well as
+ defining the various addressing methods for a given contact
+ through this interface's contact attributes.</p>
+ </tp:docstring>
+
+ <method name="GetContactsByVCardField"
+ tp:name-for-bindings="Get_Contacts_By_VCard_Field">
+ <arg direction="in" name="Field" type="s">
+ <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
+ <p>The vCard field of the addresses we are requesting. The
+ field name SHOULD be in lower case. Supported
+ fields can be found in
+ <tp:dbus-ref namespace="org.freedesktop.Telepathy.Protocol.Interface.Addressing">AddressableVCardFields</tp:dbus-ref>.</p>
+
+ <p>The <code>url</code> vCard field MUST NOT appear here; see
+ <tp:member-ref>GetContactsByURI</tp:member-ref> instead.</p>
+
+ <tp:rationale>
+ <p>In practice, protocols have a limited set of URI
+ schemes that make sense to resolve as a contact.</p>
+ </tp:rationale>
+
+ </tp:docstring>
+ </arg>
+ <arg direction="in" name="Addresses" type="as">
+ <tp:docstring>
+ The addresses to get contact handles for. The address types
+ should match the given vCard field.
+ </tp:docstring>
+ </arg>
+ <arg direction="in" name="Interfaces" type="as"
+ tp:type="DBus_Interface[]">
+ <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
+ <p>A list of strings indicating which D-Bus interfaces the calling
+ process is interested in. All supported attributes from these
+ interfaces, whose values can be obtained without additional network
+ activity, will be in the reply.</p>
+
+ <p>Attributes from this interface and from
+ <tp:dbus-ref>org.freedesktop.Telepathy.Connection</tp:dbus-ref>
+ are always returned, and need not be requested
+ explicitly.</p>
+
+ <p>The behavior of this parameter is similar to the same
+ parameter in
+ <tp:dbus-ref namespace="org.freedesktop.Telepathy.Connection.Interface">Contacts.GetContactAttributes</tp:dbus-ref>.</p>
+ </tp:docstring>
+ </arg>
+
+ <arg direction="out" type="a{su}" name="Requested"
+ tp:type="Addressing_Normalization_Map">
+ <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
+ <p>A mapping from requested vCard addresses to the corresponding
+ contact handles.</p>
+
+ <p>Requested addresses that are not valid or understood for this protocol
+ MUST be omitted from the mapping.</p>
+ </tp:docstring>
+ </arg>
+
+ <arg direction="out" type="a{ua{sv}}" name="Attributes"
+ tp:type="Contact_Attributes_Map">
+ <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
+ <p>A dictionary mapping the contact handles to contact attributes.
+ If any of the requested addresses are in fact invalid, they are
+ simply omitted from this mapping. If contact attributes are not
+ immediately known, the behaviour is defined by the interface;
+ the attribute should either be omitted from the result or
+ replaced with a default value.</p>
+
+ <p>Requested addresses that are not valid or understood for this protocol
+ MUST be omitted from the mapping.</p>
+
+ <p>Each contact's attributes will always include at least the
+ identifier that would be obtained by inspecting the handle
+ (<code>org.freedesktop.Telepathy.Connection/contact-id</code>).
+ </p>
+ </tp:docstring>
+ </arg>
+
+ <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
+ <p>Request contacts and retrieve their attributes using a given field
+ in their vCards.</p>
+
+ <p>The connection manager should record that these handles are in
+ use by the client who invokes this method, and must not
+ deallocate the handles until the client disconnects from the
+ bus or calls the
+ <tp:dbus-ref namespace="org.freedesktop.Telepathy">Connection.ReleaseHandles</tp:dbus-ref>
+ method.</p>
+ </tp:docstring>
+
+ <tp:possible-errors>
+ <tp:error name="org.freedesktop.Telepathy.Error.Disconnected"/>
+ </tp:possible-errors>
+ </method>
+
+ <method name="GetContactsByURI"
+ tp:name-for-bindings="Get_Contacts_By_URI">
+ <arg direction="in" name="URIs" type="as">
+ <tp:docstring>
+ The URI addresses to get contact handles for. Supported
+ schemes can be found in
+ <tp:dbus-ref namespace="org.freedesktop.Telepathy.Protocol.Interface.Addressing">AddressableURISchemes</tp:dbus-ref>.
+ </tp:docstring>
+ </arg>
+ <arg direction="in" name="Interfaces" type="as"
+ tp:type="DBus_Interface[]">
+ <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
+ <p>A list of strings indicating which D-Bus interfaces the calling
+ process is interested in. All supported attributes from these
+ interfaces, whose values can be obtained without additional network
+ activity, will be in the reply.</p>
+
+ <p>Attributes from this interface and from
+ <tp:dbus-ref>org.freedesktop.Telepathy.Connection</tp:dbus-ref>
+ are always returned, and need not be requested
+ explicitly.</p>
+
+ <p>The behavior of this parameter is similar to the same
+ parameter in
+ <tp:dbus-ref namespace="org.freedesktop.Telepathy.Connection.Interface">Contacts.GetContactAttributes</tp:dbus-ref>.</p>
+ </tp:docstring>
+ </arg>
+
+ <arg direction="out" type="a{su}" name="Requested"
+ tp:type="Addressing_Normalization_Map">
+ <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
+ <p>A mapping of requested URIs to the corresponding contact handles.</p>
+
+ <p>Requested URIs that are not valid or understood for this protocol
+ MUST be omitted from the mapping.</p>
+ </tp:docstring>
+ </arg>
+
+ <arg direction="out" type="a{ua{sv}}" name="Attributes"
+ tp:type="Contact_Attributes_Map">
+ <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
+ <p>A dictionary mapping the contact handles to contact attributes.
+ If any of the requested addresses are in fact invalid, they are
+ simply omitted from this mapping. If contact attributes are not
+ immediately known, the behaviour is defined by the interface;
+ the attribute should either be omitted from the result or
+ replaced with a default value.</p>
+
+ <p>Requested URIs that are not valid or understood for this protocol
+ MUST be omitted from the mapping.</p>
+
+ <p>Each contact's attributes will always include at least the
+ identifier that would be obtained by inspecting the handle
+ (<code>org.freedesktop.Telepathy.Connection/contact-id</code>).
+ </p>
+ </tp:docstring>
+ </arg>
+
+ <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
+ <p>Request contacts and retrieve their attributes using URI addresses.</p>
+
+ <p>The connection manager should record that these handles are in
+ use by the client who invokes this method, and must not
+ deallocate the handles until the client disconnects from the
+ bus or calls the
+ <tp:dbus-ref namespace="org.freedesktop.Telepathy">Connection.ReleaseHandles</tp:dbus-ref>
+ method.</p>
+ </tp:docstring>
+
+ <tp:possible-errors>
+ <tp:error name="org.freedesktop.Telepathy.Error.Disconnected"/>
+ </tp:possible-errors>
+ </method>
+
+ <tp:mapping name="VCard_Field_Address_Map" array-name="">
+ <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
+ <p>A mapping of vCard fields and addresses that repreent
+ the given contact.</p>
+ </tp:docstring>
+ <tp:member type="s" name="VCard_Field"/>
+ <tp:member type="s" name="Address"/>
+ </tp:mapping>
+
+ <tp:contact-attribute name="addresses" type="a{ss}"
+ tp:type="VCard_Field_Address_Map">
+ <tp:docstring>
+ The various vCard addresses that identify this contact.
+ </tp:docstring>
+ </tp:contact-attribute>
+
+ <tp:contact-attribute name="uris" type="as">
+ <tp:docstring>
+ The various URI addresses that identify this contact.
+ </tp:docstring>
+ </tp:contact-attribute>
+
+ <tp:mapping name="Addressing_Normalization_Map">
+ <tp:docstring>
+ A map from URIs/vCard addresses to the corresponding handle.
+ </tp:docstring>
+ <tp:added version="0.25.UNRELEASED"/>
+
+ <tp:member type="s" name="Requested_String">
+ <tp:docstring>
+ The URI or vCard address that has been requested by
+ <tp:member-ref>GetContactsByVCardField</tp:member-ref> or
+ <tp:member-ref>GetContactsByURI</tp:member-ref>.
+ </tp:docstring>
+ </tp:member>
+ <tp:member type="u" name="Handle" tp:type="Contact_Handle">
+ <tp:docstring>
+ A nonzero handle.
+ </tp:docstring>
+ </tp:member>
+ </tp:mapping>
+
+ </interface>
+</node>
+<!-- vim:set sw=2 sts=2 et ft=xml: -->
diff --git a/extensions/Makefile.am b/extensions/Makefile.am
index 47b51b350..8e50ffbce 100644
--- a/extensions/Makefile.am
+++ b/extensions/Makefile.am
@@ -4,6 +4,7 @@ EXTRA_DIST = \
all.xml \
Channel_Type_FileTransfer_Future.xml \
Connection_Future.xml \
+ Connection_Interface_Addressing.xml \
Connection_Interface_Gabble_Decloak.xml \
Gabble_Plugin_Console.xml \
Gabble_Plugin_Gateways.xml \
diff --git a/extensions/all.xml b/extensions/all.xml
index 90f52a89b..99997d6db 100644
--- a/extensions/all.xml
+++ b/extensions/all.xml
@@ -33,6 +33,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA</p>
from="Telepathy specification"/>
</tp:generic-types>
+<xi:include href="Connection_Interface_Addressing.xml"/>
+
<xi:include href="OLPC_Buddy_Info.xml"/>
<xi:include href="OLPC_Activity_Properties.xml"/>
@@ -81,6 +83,10 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA</p>
<tp:external-type name="String_Variant_Map" type="a{sv}"
from="Telepathy specification"/>
+ <!-- use types from Connection_Interface_Contacts -->
+ <tp:external-type name="Contact_Attributes_Map" type="a{ua{sv}}"
+ from="Telepathy specification"/>
+
<!-- use types from Connection_Interface_Requests -->
<tp:external-type name="Channel_Class" type="a{sv}"
from="Telepathy specification"/>
diff --git a/src/Makefile.am b/src/Makefile.am
index 36477041e..c24f2a867 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -13,6 +13,8 @@ libexec_PROGRAMS=telepathy-gabble
noinst_PROGRAMS = write-mgr-file
libgabble_convenience_la_SOURCES = \
+ addressing-util.h \
+ addressing-util.c \
auth-manager.h \
auth-manager.c \
base64.h \
@@ -51,6 +53,8 @@ libgabble_convenience_la_SOURCES = \
caps-hash.c \
$(top_srcdir)/gabble/caps-channel-manager.h \
caps-channel-manager.c \
+ conn-addressing.h \
+ conn-addressing.c \
conn-aliasing.h \
conn-aliasing.c \
conn-avatars.h \
diff --git a/src/addressing-util.c b/src/addressing-util.c
new file mode 100644
index 000000000..7ad84d9c0
--- /dev/null
+++ b/src/addressing-util.c
@@ -0,0 +1,412 @@
+/*
+ * addressing-util.c - Source for Gabble addressing utility functions
+ * Copyright (C) 2010 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 "config.h"
+#include "addressing-util.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <wocky/wocky-utils.h>
+
+#include "connection.h"
+#include "util.h"
+
+static const gchar *addressable_vcard_fields[] = {"x-jabber", NULL};
+static const gchar *addressable_uri_schemes[] = {"xmpp", NULL};
+
+
+const gchar * const *
+gabble_get_addressable_uri_schemes ()
+{
+ return addressable_uri_schemes;
+}
+
+const gchar * const *
+gabble_get_addressable_vcard_fields ()
+{
+ return addressable_vcard_fields;
+}
+
+gchar *
+gabble_normalize_contact_uri (const gchar *uri,
+ GError **error)
+{
+ gchar *scheme = NULL;
+ gchar *normalized_jid = NULL;
+ gchar *normalized_uri = NULL;
+
+ g_return_val_if_fail (uri != NULL, NULL);
+
+ normalized_jid = gabble_uri_to_jid (uri, error);
+ if (normalized_jid == NULL)
+ {
+ goto OUT;
+ }
+
+ scheme = g_uri_parse_scheme (uri);
+
+ normalized_uri = gabble_jid_to_uri (scheme, normalized_jid, error);
+
+OUT:
+ g_free (scheme);
+ g_free (normalized_jid);
+
+ return normalized_uri;
+}
+
+gchar *
+gabble_uri_to_jid (const gchar *uri,
+ GError **error)
+{
+ gchar *scheme;
+ gchar *normalized_jid = NULL;
+
+ g_return_val_if_fail (uri != NULL, NULL);
+
+ scheme = g_uri_parse_scheme (uri);
+
+ if (scheme == NULL)
+ {
+ g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ "'%s' is not a valid URI", uri);
+ goto OUT;
+ }
+ else if (g_ascii_strcasecmp (scheme, "xmpp") == 0)
+ {
+ gchar *node = NULL;
+ gchar *domain = NULL;
+ gchar *resource = NULL;
+
+ if (!gabble_parse_xmpp_uri (uri, &node, &domain, &resource, error))
+ goto OUT;
+
+ normalized_jid = gabble_encode_jid (node, domain, resource);
+
+ g_free (node);
+ g_free (domain);
+ g_free (resource);
+ }
+ else
+ {
+ g_set_error (error, TP_ERRORS, TP_ERROR_NOT_IMPLEMENTED,
+ "'%s' URI scheme is not supported by this protocol",
+ scheme);
+ goto OUT;
+ }
+
+OUT:
+ g_free (scheme);
+
+ return normalized_jid;
+}
+
+gchar *
+gabble_jid_to_uri (const gchar *scheme,
+ const gchar *jid,
+ GError **error)
+{
+ gchar *normalized_uri = NULL;
+ gchar *node = NULL;
+ gchar *domain = NULL;
+ gchar *resource = NULL;
+ gchar *escaped_node = NULL;
+ gchar *escaped_domain = NULL;
+ gchar *escaped_resource = NULL;
+ gchar *escaped_jid = NULL;
+ gchar *normalized_scheme = NULL;
+
+ g_return_val_if_fail (scheme != NULL, NULL);
+
+ if (!wocky_decode_jid (jid, &node, &domain, &resource))
+ {
+ g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ "'%s' is not a valid JID", jid);
+ return NULL;
+ }
+
+ /* convert from "foo?" to "foo%3F" */
+ if (node)
+ escaped_node = g_uri_escape_string (node, NULL, TRUE);
+
+ g_assert (domain != NULL);
+ escaped_domain = g_uri_escape_string (domain, NULL, TRUE);
+
+ if (resource)
+ escaped_resource = g_uri_escape_string (resource, NULL, TRUE);
+
+ escaped_jid = gabble_encode_jid (escaped_node, escaped_domain, escaped_resource);
+
+ normalized_scheme = g_ascii_strdown (scheme, -1);
+
+ normalized_uri = g_strdup_printf ("%s:%s", normalized_scheme, escaped_jid);
+
+ g_free (node);
+ g_free (domain);
+ g_free (resource);
+ g_free (escaped_node);
+ g_free (escaped_domain);
+ g_free (escaped_resource);
+ g_free (escaped_jid);
+ g_free (normalized_scheme);
+
+ return normalized_uri;
+}
+
+TpHandle
+gabble_ensure_handle_from_uri (TpHandleRepoIface *repo,
+ const gchar *uri,
+ GError **error)
+{
+ TpHandle handle;
+
+ gchar *jid = gabble_uri_to_jid (uri, error);
+
+ if (jid == NULL)
+ return 0;
+
+ handle = tp_handle_ensure (repo, jid, NULL, error);
+
+ g_free (jid);
+
+ return handle;
+}
+
+gchar *
+gabble_parse_vcard_address (const gchar *vcard_field,
+ const gchar *vcard_address,
+ GError **error)
+{
+ gchar *normalized_address = NULL;
+
+ g_return_val_if_fail (vcard_field != NULL, NULL);
+ g_return_val_if_fail (vcard_address != NULL, NULL);
+
+ if (g_ascii_strcasecmp (vcard_field, "x-jabber") == 0)
+ {
+ GError *gabble_error = NULL;
+
+ normalized_address = gabble_normalize_contact (NULL,
+ vcard_address, GUINT_TO_POINTER (GABBLE_JID_GLOBAL),
+ &gabble_error);
+
+ if (gabble_error != NULL)
+ {
+ g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ "'%s' is an invalid address: %s", vcard_address,
+ gabble_error->message);
+ g_error_free (gabble_error);
+ }
+ }
+ else
+ {
+ g_set_error (error, TP_ERRORS, TP_ERROR_NOT_IMPLEMENTED,
+ "'%s' vCard field is not supported by this protocol", vcard_field);
+ }
+
+ return normalized_address;
+}
+
+TpHandle
+gabble_ensure_handle_from_vcard_address (TpHandleRepoIface *repo,
+ const gchar *vcard_field,
+ const gchar *vcard_address,
+ GError **error)
+{
+ TpHandle handle;
+
+ gchar *normalized_address = gabble_parse_vcard_address (vcard_field, vcard_address, error);
+
+ if (normalized_address == NULL)
+ return 0;
+
+ handle = tp_handle_ensure (repo, vcard_address, NULL, error);
+
+ g_free (normalized_address);
+
+ return handle;
+}
+
+gchar **
+gabble_uris_for_handle (TpHandleRepoIface *contact_repo,
+ TpHandle contact)
+{
+ GPtrArray *uris = g_ptr_array_new ();
+
+ for (const gchar * const *scheme = addressable_uri_schemes; *scheme != NULL; scheme++)
+ {
+ gchar *uri = gabble_uri_for_handle (contact_repo, *scheme, contact);
+
+ if (uri != NULL)
+ {
+ g_ptr_array_add (uris, uri);
+ }
+ }
+
+ g_ptr_array_add (uris, NULL);
+ return (gchar **) g_ptr_array_free (uris, FALSE);
+}
+
+GHashTable *
+gabble_vcard_addresses_for_handle (TpHandleRepoIface *contact_repo,
+ TpHandle contact)
+{
+ GHashTable *addresses = g_hash_table_new_full (g_str_hash, g_str_equal,
+ NULL, (GDestroyNotify) g_free);
+
+ for (const gchar * const *field = addressable_vcard_fields; *field != NULL; field++)
+ {
+ gchar *vcard_address = gabble_vcard_address_for_handle (contact_repo, *field, contact);
+
+ if (vcard_address != NULL)
+ {
+ g_hash_table_insert (addresses, (gpointer) *field, vcard_address);
+ }
+ }
+
+ return addresses;
+}
+
+gchar *
+gabble_vcard_address_for_handle (TpHandleRepoIface *contact_repo,
+ const gchar *vcard_field,
+ TpHandle contact)
+{
+ const gchar *identifier = tp_handle_inspect (contact_repo, contact);
+ return gabble_parse_vcard_address (vcard_field, identifier, NULL);
+}
+
+gchar *
+gabble_uri_for_handle (TpHandleRepoIface *contact_repo,
+ const gchar *scheme,
+ TpHandle contact)
+{
+ const gchar *identifier = tp_handle_inspect (contact_repo, contact);
+ return gabble_jid_to_uri (scheme, identifier, NULL);
+}
+
+gboolean
+gabble_parse_xmpp_uri (const gchar *uri,
+ gchar **node,
+ gchar **domain,
+ gchar **resource,
+ GError **error)
+{
+ gboolean ret = FALSE;
+ gchar *scheme;
+ const gchar *jid;
+ gchar *tmp_node = NULL;
+ gchar *tmp_domain = NULL;
+ gchar *tmp_resource = NULL;
+ gchar *unescaped_node = NULL;
+ gchar *unescaped_domain = NULL;
+ gchar *unescaped_resource = NULL;
+ gchar *unescaped_jid = NULL;
+ gchar *normalized_jid = NULL;
+ GError *gabble_error = NULL;
+
+ g_return_val_if_fail (uri != NULL, FALSE);
+ g_return_val_if_fail (domain != NULL, FALSE);
+
+ scheme = g_uri_parse_scheme (uri);
+
+ if (scheme == NULL)
+ {
+ g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ "'%s' is not a valid URI", uri);
+ goto OUT;
+ }
+
+ jid = uri + strlen (scheme) + 1; /* Strip the scheme */
+
+ if (!wocky_decode_jid (jid, &tmp_node, &tmp_domain, &tmp_resource))
+ {
+ g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ "'%s' is not a valid XMPP URI", uri);
+ goto OUT;
+ }
+
+ /* convert from "foo%3F" to "foo?" */
+ if (tmp_node)
+ {
+ unescaped_node = g_uri_unescape_string (tmp_node, NULL);
+ if (unescaped_node == NULL)
+ {
+ g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ "'%s' is not a valid XMPP URI", uri);
+ goto OUT;
+ }
+ }
+
+ g_assert (tmp_domain);
+ unescaped_domain = g_uri_unescape_string (tmp_domain, NULL);
+ if (unescaped_domain == NULL)
+ {
+ g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ "'%s' is not a valid XMPP URI", uri);
+ goto OUT;
+ }
+
+ if (tmp_resource)
+ {
+ unescaped_resource = g_uri_unescape_string (tmp_resource, NULL);
+ if (unescaped_resource == NULL)
+ {
+ g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ "'%s' is not a valid XMPP URI", uri);
+ goto OUT;
+ }
+ }
+
+ unescaped_jid = gabble_encode_jid (unescaped_node, unescaped_domain, unescaped_resource);
+
+ normalized_jid = gabble_normalize_contact (NULL, unescaped_jid,
+ GUINT_TO_POINTER (GABBLE_JID_GLOBAL), &gabble_error);
+
+ if (gabble_error != NULL)
+ {
+ g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ "'%s' is not a valid XMPP URI: %s", uri,
+ gabble_error->message);
+ g_error_free (gabble_error);
+ goto OUT;
+ }
+
+ if (!wocky_decode_jid (normalized_jid, node, domain, resource))
+ {
+ g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ "'%s' is not a valid XMPP URI", uri);
+ goto OUT;
+ }
+
+ ret = TRUE;
+
+OUT:
+ g_free (scheme);
+ g_free (tmp_node);
+ g_free (tmp_domain);
+ g_free (tmp_resource);
+ g_free (unescaped_node);
+ g_free (unescaped_domain);
+ g_free (unescaped_resource);
+ g_free (unescaped_jid);
+ g_free (normalized_jid);
+ return ret;
+}
diff --git a/src/addressing-util.h b/src/addressing-util.h
new file mode 100644
index 000000000..d4354a3fa
--- /dev/null
+++ b/src/addressing-util.h
@@ -0,0 +1,70 @@
+/*
+ * addressing-util.c - Headers for Gabble addressing utility functions
+ * Copyright (C) 2010 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
+ */
+
+#ifndef __GABBLE_UTIL_ADDRESSING_H__
+#define __GABBLE_UTIL_ADDRESSING_H__
+
+#include <telepathy-glib/handle-repo-dynamic.h>
+
+const gchar * const * gabble_get_addressable_uri_schemes (void);
+
+const gchar * const * gabble_get_addressable_vcard_fields (void);
+
+gchar * gabble_normalize_contact_uri (const gchar *uri,
+ GError **error);
+gchar * gabble_uri_to_jid (const gchar *uri,
+ GError **error);
+gchar * gabble_jid_to_uri (const gchar *scheme,
+ const gchar *jid,
+ GError **error);
+
+TpHandle gabble_ensure_handle_from_uri (TpHandleRepoIface *repo,
+ const gchar *uri,
+ GError **error);
+
+gchar * gabble_parse_vcard_address (const gchar *vcard_field,
+ const gchar *vcard_address,
+ GError **error);
+
+TpHandle gabble_ensure_handle_from_vcard_address (TpHandleRepoIface *repo,
+ const gchar *vcard_field,
+ const gchar *vcard_address,
+ GError **error);
+
+gchar **gabble_uris_for_handle (TpHandleRepoIface *contact_repo,
+ TpHandle contact);
+
+GHashTable *gabble_vcard_addresses_for_handle (TpHandleRepoIface *contact_repo,
+ TpHandle contact);
+
+gchar *gabble_uri_for_handle (TpHandleRepoIface *contact_repo,
+ const gchar *uri_scheme,
+ TpHandle contact);
+
+gchar *gabble_vcard_address_for_handle (TpHandleRepoIface *contact_repo,
+ const gchar *vcard_field,
+ TpHandle contact);
+
+gboolean gabble_parse_xmpp_uri (const gchar *uri,
+ gchar **node,
+ gchar **domain,
+ gchar **resource,
+ GError **error);
+
+#endif /* __GABBLE_UTIL_ADDRESSING_H__ */
diff --git a/src/conn-addressing.c b/src/conn-addressing.c
new file mode 100644
index 000000000..465699494
--- /dev/null
+++ b/src/conn-addressing.c
@@ -0,0 +1,166 @@
+/*
+ * conn-addressing.h - Header for Gabble connection code handling addressing.
+ * Copyright (C) 2010 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 "conn-addressing.h"
+
+#include <dbus/dbus-glib-lowlevel.h>
+
+#include "extensions/extensions.h"
+
+#include "addressing-util.h"
+#include "namespaces.h"
+#include "util.h"
+
+static const char *assumed_interfaces[] = {
+ TP_IFACE_CONNECTION,
+ GABBLE_IFACE_CONNECTION_INTERFACE_ADDRESSING,
+ NULL
+ };
+
+
+static void
+_fill_contact_attributes (TpHandleRepoIface *contact_repo,
+ TpHandle contact,
+ GHashTable *attributes_hash)
+{
+ gchar **uris = gabble_uris_for_handle (contact_repo, contact);
+ GHashTable *addresses = gabble_vcard_addresses_for_handle (contact_repo, contact);
+
+ tp_contacts_mixin_set_contact_attribute (attributes_hash,
+ contact, GABBLE_IFACE_CONNECTION_INTERFACE_ADDRESSING"/uris",
+ tp_g_value_slice_new_take_boxed (G_TYPE_STRV, uris));
+
+ tp_contacts_mixin_set_contact_attribute (attributes_hash,
+ contact, GABBLE_IFACE_CONNECTION_INTERFACE_ADDRESSING"/addresses",
+ tp_g_value_slice_new_take_boxed (TP_HASH_TYPE_STRING_STRING_MAP, addresses));
+}
+
+static void
+conn_addressing_fill_contact_attributes (GObject *obj,
+ const GArray *contacts,
+ GHashTable *attributes_hash)
+{
+ guint i;
+ TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
+ (TpBaseConnection *) obj, TP_HANDLE_TYPE_CONTACT);
+
+ for (i = 0; i < contacts->len; i++)
+ {
+ TpHandle contact = g_array_index (contacts, TpHandle, i);
+ _fill_contact_attributes (contact_repo, contact, attributes_hash);
+ }
+}
+
+static void
+conn_addressing_get_contacts_by_uri (GabbleSvcConnectionInterfaceAddressing *iface,
+ const gchar **uris,
+ const gchar **interfaces,
+ DBusGMethodInvocation *context)
+{
+ const gchar **uri;
+ TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
+ (TpBaseConnection *) iface, TP_HANDLE_TYPE_CONTACT);
+ GHashTable *attributes;
+ GHashTable *requested = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+ GArray *handles = g_array_sized_new (TRUE, TRUE, sizeof (TpHandle),
+ g_strv_length ((gchar **) uris));
+ gchar *sender = dbus_g_method_get_sender (context);
+
+ for (uri = uris; *uri != NULL; uri++)
+ {
+ TpHandle h = gabble_ensure_handle_from_uri (contact_repo, *uri, NULL);
+
+ if (h == 0)
+ continue;
+
+ g_hash_table_insert (requested, g_strdup (*uri), GUINT_TO_POINTER (h));
+ g_array_append_val (handles, h);
+ }
+
+ attributes = tp_contacts_mixin_get_contact_attributes (G_OBJECT (iface), handles,
+ interfaces, assumed_interfaces, sender);
+
+ gabble_svc_connection_interface_addressing_return_from_get_contacts_by_uri (
+ context, requested, attributes);
+
+ tp_handles_unref (contact_repo, handles);
+ g_hash_table_unref (requested);
+ g_hash_table_unref (attributes);
+ g_free (sender);
+}
+
+static void
+conn_addressing_get_contacts_by_vcard_field (GabbleSvcConnectionInterfaceAddressing *iface,
+ const gchar *field,
+ const gchar **addresses,
+ const gchar **interfaces,
+ DBusGMethodInvocation *context)
+{
+ const gchar **address;
+ TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
+ (TpBaseConnection *) iface, TP_HANDLE_TYPE_CONTACT);
+ GHashTable *attributes;
+ GHashTable *requested = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+ GArray *handles = g_array_sized_new (TRUE, TRUE, sizeof (TpHandle),
+ g_strv_length ((gchar **) addresses));
+ gchar *sender = dbus_g_method_get_sender (context);
+
+ for (address = addresses; *address != NULL; address++)
+ {
+ TpHandle h = gabble_ensure_handle_from_vcard_address (contact_repo, field,
+ *address, NULL);
+
+ if (h == 0)
+ continue;
+
+ g_hash_table_insert (requested, g_strdup (*address), GUINT_TO_POINTER (h));
+ g_array_append_val (handles, h);
+ }
+
+ attributes = tp_contacts_mixin_get_contact_attributes (G_OBJECT (iface), handles,
+ interfaces, assumed_interfaces, sender);
+
+ gabble_svc_connection_interface_addressing_return_from_get_contacts_by_vcard_field (
+ context, requested, attributes);
+
+ tp_handles_unref (contact_repo, handles);
+ g_hash_table_unref (requested);
+ g_hash_table_unref (attributes);
+ g_free (sender);
+}
+
+void
+conn_addressing_init (GabbleConnection *self) {
+ tp_contacts_mixin_add_contact_attributes_iface (G_OBJECT (self),
+ GABBLE_IFACE_CONNECTION_INTERFACE_ADDRESSING,
+ conn_addressing_fill_contact_attributes);
+}
+
+void
+conn_addressing_iface_init (gpointer g_iface,
+ gpointer iface_data)
+{
+#define IMPLEMENT(x) \
+ gabble_svc_connection_interface_addressing_implement_##x (\
+ g_iface, conn_addressing_##x)
+
+ IMPLEMENT (get_contacts_by_uri);
+ IMPLEMENT (get_contacts_by_vcard_field);
+#undef IMPLEMENT
+}
diff --git a/src/conn-addressing.h b/src/conn-addressing.h
new file mode 100644
index 000000000..2dbe08756
--- /dev/null
+++ b/src/conn-addressing.h
@@ -0,0 +1,34 @@
+/*
+ * conn-addressing.h - Header for Gabble connection code handling addressing.
+ * Copyright (C) 2010 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
+ */
+
+#ifndef GABBLE_CONN_ADDRESSING_H
+#define GABBLE_CONN_ADDRESSING_H
+
+#include <glib.h>
+
+#include "connection.h"
+
+G_BEGIN_DECLS
+
+void conn_addressing_iface_init (gpointer g_iface, gpointer iface_data);
+void conn_addressing_init (GabbleConnection *self);
+
+G_END_DECLS
+
+#endif /* GABBLE_CONN_ADDRESSING_H */
diff --git a/src/connection.c b/src/connection.c
index c3a28f7da..25c185ebf 100644
--- a/src/connection.c
+++ b/src/connection.c
@@ -86,6 +86,7 @@
#include "util.h"
#include "vcard-manager.h"
#include "conn-util.h"
+#include "conn-addressing.h"
static guint disco_reply_timeout = 5;
@@ -140,6 +141,8 @@ G_DEFINE_TYPE_WITH_CODE(GabbleConnection,
conn_client_types_iface_init);
G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_POWER_SAVING,
conn_power_saving_iface_init);
+ G_IMPLEMENT_INTERFACE (GABBLE_TYPE_SVC_CONNECTION_INTERFACE_ADDRESSING,
+ conn_addressing_iface_init);
)
/* properties */
@@ -420,6 +423,7 @@ gabble_connection_constructor (GType type,
conn_sidecars_init (self);
conn_mail_notif_init (self);
conn_client_types_init (self);
+ conn_addressing_init (self);
tp_contacts_mixin_add_contact_attributes_iface (G_OBJECT (self),
TP_IFACE_CONNECTION_INTERFACE_CAPABILITIES,
@@ -838,6 +842,7 @@ static const gchar *implemented_interfaces[] = {
GABBLE_IFACE_CONNECTION_INTERFACE_GABBLE_DECLOAK,
GABBLE_IFACE_CONNECTION_FUTURE,
TP_IFACE_CONNECTION_INTERFACE_CLIENT_TYPES,
+ GABBLE_IFACE_CONNECTION_INTERFACE_ADDRESSING,
NULL
};
static const gchar **interfaces_always_present = implemented_interfaces + 3;
diff --git a/src/protocol.c b/src/protocol.c
index ea10746c6..5576c7cfe 100644
--- a/src/protocol.c
+++ b/src/protocol.c
@@ -34,6 +34,7 @@
#include "roomlist-manager.h"
#include "search-manager.h"
#include "util.h"
+#include "addressing-util.h"
#define PROTOCOL_NAME "jabber"
#define ICON_NAME "im-" PROTOCOL_NAME
@@ -44,7 +45,8 @@ static void addressing_iface_init (TpProtocolAddressingInterface *iface);
G_DEFINE_TYPE_WITH_CODE (GabbleJabberProtocol, gabble_jabber_protocol,
TP_TYPE_BASE_PROTOCOL,
- G_IMPLEMENT_INTERFACE (TP_TYPE_PROTOCOL_ADDRESSING, addressing_iface_init))
+ G_IMPLEMENT_INTERFACE (TP_TYPE_PROTOCOL_ADDRESSING, addressing_iface_init);
+ )
static TpCMParamSpec jabber_params[] = {
{ "account", DBUS_TYPE_STRING_AS_STRING, G_TYPE_STRING,
@@ -378,17 +380,13 @@ dup_authentication_types (TpBaseProtocol *self)
static GStrv
dup_supported_uri_schemes (TpBaseProtocol *self)
{
- const gchar * const addressing_uri_schemes[] = {"xmpp", NULL};
-
- return g_strdupv ((GStrv) addressing_uri_schemes);
+ return g_strdupv ((gchar **) gabble_get_addressable_uri_schemes ());
}
static GStrv
dup_supported_vcard_fields (TpBaseProtocol *self)
{
- const gchar * const addressing_vcard_fields[] = {"x-jabber", NULL};
-
- return g_strdupv ((GStrv) addressing_vcard_fields);
+ return g_strdupv ((gchar **) gabble_get_addressable_vcard_fields ());
}
static gchar *
@@ -397,28 +395,16 @@ addressing_normalize_vcard_address (TpBaseProtocol *self,
const gchar *vcard_address,
GError **error)
{
- gchar *normalized_address = NULL;
+ gchar *normalized_address = gabble_parse_vcard_address (vcard_field, vcard_address, error);
- if (g_ascii_strcasecmp (vcard_field, "x-jabber") == 0)
+ if (normalized_address == NULL)
{
- GError *gabble_error = NULL;
- normalized_address = gabble_normalize_contact (NULL,
- vcard_address, GUINT_TO_POINTER (GABBLE_JID_GLOBAL),
- &gabble_error);
-
- if (gabble_error != NULL)
+ /* InvalidHandle makes no sense in Protocol */
+ if (error != NULL && g_error_matches (*error, TP_ERROR, TP_ERROR_INVALID_HANDLE))
{
- g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
- "'%s' is an invalid address: %s", vcard_address,
- gabble_error->message);
- g_error_free (gabble_error);
+ (*error)->code = TP_ERROR_INVALID_ARGUMENT;
}
}
- else
- {
- g_set_error (error, TP_ERRORS, TP_ERROR_NOT_IMPLEMENTED,
- "'x-jabber' is the only vCard field supported by this protocol");
- }
return normalized_address;
}
@@ -428,47 +414,20 @@ addressing_normalize_contact_uri (TpBaseProtocol *self,
const gchar *uri,
GError **error)
{
- gchar *scheme = g_uri_parse_scheme (uri);
- gchar *normalized_uri = NULL;
+ gchar *normalized_address = NULL;
- if (scheme == NULL)
- {
- g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
- "'%s' is not a valid URI", uri);
- }
- else if (g_ascii_strcasecmp (scheme, "xmpp") == 0)
- {
- GError *gabble_error = NULL;
- const gchar *address = uri + strlen (scheme) + 1; /* Strip the scheme */
- gchar *normalized_address = gabble_normalize_contact (NULL,
- address, GUINT_TO_POINTER (GABBLE_JID_GLOBAL), &gabble_error);
+ normalized_address = gabble_normalize_contact_uri (uri, error);
- if (gabble_error != NULL)
- {
- g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
- "'%s' is an invalid address: %s", address,
- gabble_error->message);
- g_error_free (gabble_error);
- }
- else
+ if (normalized_address == NULL)
+ {
+ /* InvalidHandle makes no sense in Protocol */
+ if (error != NULL && g_error_matches (*error, TP_ERROR, TP_ERROR_INVALID_HANDLE))
{
- gchar *normalized_scheme = g_ascii_strdown (scheme, -1);
- normalized_uri = g_strdup_printf ("%s:%s", normalized_scheme,
- normalized_address);
-
- g_free (normalized_scheme);
- g_free (normalized_address);
+ (*error)->code = TP_ERROR_INVALID_ARGUMENT;
}
}
- else
- {
- g_set_error (error, TP_ERRORS, TP_ERROR_NOT_IMPLEMENTED,
- "'xmpp' is the only URI scheme supported by this protocol");
- }
- g_free (scheme);
-
- return normalized_uri;
+ return normalized_address;
}
static void
diff --git a/tests/twisted/addressing.py b/tests/twisted/addressing.py
index f8291f9e7..d09462a24 100644
--- a/tests/twisted/addressing.py
+++ b/tests/twisted/addressing.py
@@ -3,12 +3,14 @@ Test Gabble's different addressing interfaces.
"""
import dbus
-from servicetest import unwrap, tp_path_prefix, assertEquals, ProxyWrapper
+from servicetest import unwrap, tp_path_prefix, assertEquals, ProxyWrapper, \
+ assertContains, assertSameSets, assertDoesNotContain
from gabbletest import exec_test, call_async
import constants as cs
+import ns
import time
-def test(q, bus, conn, stream):
+def test_protocol(q, bus, conn, stream):
proto = ProxyWrapper(
bus.get_object(cs.CM + '.gabble',
tp_path_prefix + '/ConnectionManager/gabble/jabber'),
@@ -44,9 +46,14 @@ def test(q, bus, conn, stream):
# NormalizeContactURI
normalized_uri = proto.Addressing.NormalizeContactURI(
- "xmpp:EITAN@example.COM/resource")
+ "xmpp:EITAN?@example.COM/resource")
- assertEquals("xmpp:eitan@example.com", normalized_uri)
+ assertEquals("xmpp:eitan%3F@example.com", normalized_uri)
+
+ normalized_uri = proto.Addressing.NormalizeContactURI(
+ "xmpp:EITAN?@example.COM/resourc?e")
+
+ assertEquals("xmpp:eitan%3F@example.com", normalized_uri)
call_async(q, proto.Addressing, "NormalizeContactURI",
"Something that is far from a URI")
@@ -66,5 +73,58 @@ def test(q, bus, conn, stream):
q.expect('dbus-error', method="NormalizeContactURI",
name=cs.INVALID_ARGUMENT)
+def test_connection(q, bus, conn, stream):
+ event = q.expect('stream-iq', query_ns=ns.ROSTER)
+ event.stanza['type'] = 'result'
+
+ normalized_buddies = ['amy@foo.com', 'bob@foo.com', 'che@foo.com']
+ buddies = ['AMY@foo.com', 'bob@FOO.com', 'che@foo.com/resource']
+
+ for buddy in normalized_buddies:
+ item = event.query.addElement('item')
+ item['jid'] = buddy
+ item['subscription'] = 'both'
+
+ stream.send(event.stanza)
+
+ requested, attributes = conn.Addressing.GetContactsByVCardField(
+ "X-JABBER", buddies[:2] + ['bad!jid'] + buddies[2:], [])
+
+ addresses = []
+
+ assertEquals(3, len(attributes))
+ assertEquals(3, len(requested))
+
+ for attr in attributes.values():
+ assertContains(cs.CONN_IFACE_ADDRESSING + '/addresses', attr.keys())
+ assertContains('x-jabber', attr[cs.CONN_IFACE_ADDRESSING + '/addresses'].keys())
+ addresses.append(attr[cs.CONN_IFACE_ADDRESSING + '/addresses']['x-jabber'])
+
+ assertSameSets(normalized_buddies, addresses)
+ assertSameSets(buddies, requested.keys());
+
+ normalized_buddies = ['amy%3F@foo.com', 'bob@foo.com', 'che@foo.com']
+ buddies = ['AMY?@foo.com', 'bob@FOO.com', 'che@foo.com/resource']
+
+ normalized_schemes = ["xmpp", "xmpp", "http"]
+ schemes = ["xmpp", "XMPP", "http"]
+ valid_schemes = ["xmpp", "XMPP"]
+
+ request_uris = [a + ":" + b for a, b in zip(schemes, buddies)]
+ valid_request_uris = [a + ":" + b for a, b in zip(valid_schemes, buddies)]
+ normalized_request_uris = [a + ":" + b for a, b in zip(normalized_schemes, normalized_buddies)]
+
+ requested, attributes = conn.Addressing.GetContactsByURI(request_uris, [])
+
+ assertEquals(2, len(attributes))
+ assertEquals(2, len(requested))
+
+ for attr in attributes.values():
+ assertContains(attr[cs.CONN_IFACE_ADDRESSING + '/uris'][0], normalized_request_uris)
+ assertContains(cs.CONN_IFACE_ADDRESSING + '/uris', attr.keys())
+
+ assertSameSets(valid_request_uris, requested.keys())
+
if __name__ == '__main__':
- exec_test(test)
+ exec_test(test_protocol)
+ exec_test(test_connection)
diff --git a/tests/twisted/constants.py b/tests/twisted/constants.py
index b580cd932..e869a4a97 100644
--- a/tests/twisted/constants.py
+++ b/tests/twisted/constants.py
@@ -139,6 +139,7 @@ CONN_IFACE_CONTACT_GROUPS = CONN + '.Interface.ContactGroups'
CONN_IFACE_CLIENT_TYPES = CONN + '.Interface.ClientTypes'
CONN_IFACE_POWER_SAVING = CONN + '.Interface.PowerSaving'
CONN_IFACE_CONTACT_BLOCKING = CONN + '.Interface.ContactBlocking'
+CONN_IFACE_ADDRESSING = CONN + '.Interface.Addressing.DRAFT'
ATTR_CONTACT_CAPABILITIES = CONN_IFACE_CONTACT_CAPS + '/capabilities'
diff --git a/tests/twisted/servicetest.py b/tests/twisted/servicetest.py
index 0531ba638..0fee466e6 100644
--- a/tests/twisted/servicetest.py
+++ b/tests/twisted/servicetest.py
@@ -465,6 +465,7 @@ def wrap_connection(conn):
('ContactList', cs.CONN_IFACE_CONTACT_LIST),
('ContactGroups', cs.CONN_IFACE_CONTACT_GROUPS),
('PowerSaving', cs.CONN_IFACE_POWER_SAVING),
+ ('Addressing', cs.CONN_IFACE_ADDRESSING),
]))
def wrap_channel(chan, type_, extra=None):