summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonny Lamb <jonny.lamb@collabora.co.uk>2011-09-28 14:17:15 +0100
committerJonny Lamb <jonny.lamb@collabora.co.uk>2011-09-28 16:27:51 +0100
commit498920f1f69cdccbcc3c5f2146a1b1b9b5cd5976 (patch)
treeb92a386673a3f527cf339c96b4987ef7e6e13fc5
parentf670d0082e850835b93405eac32da24d94496975 (diff)
connection: drop invalid or duplicate data forms from channel managers
Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk>
-rw-r--r--src/connection.c128
1 files changed, 118 insertions, 10 deletions
diff --git a/src/connection.c b/src/connection.c
index 43b4efc5..b9aa89b3 100644
--- a/src/connection.c
+++ b/src/connection.c
@@ -3246,6 +3246,105 @@ gabble_connection_advertise_capabilities (TpSvcConnectionInterfaceCapabilities *
g_ptr_array_free (ret, TRUE);
}
+static const gchar *
+get_form_type (WockyDataForm *form)
+{
+ WockyDataFormField *field;
+
+ field = g_hash_table_lookup (form->fields,
+ "FORM_TYPE");
+ g_assert (field != NULL);
+
+ return field->raw_value_contents[0];
+}
+
+static const gchar *
+check_form_is_unique (GabbleConnection *self,
+ const gchar *form_type)
+{
+ GHashTableIter iter;
+ gpointer key, value;
+
+ g_hash_table_iter_init (&iter, self->priv->client_data_forms);
+ while (g_hash_table_iter_next (&iter, &key, &value))
+ {
+ const gchar *manager = key;
+ GPtrArray *data_forms = value;
+ guint i;
+
+ if (data_forms == NULL || data_forms->len == 0)
+ continue;
+
+ for (i = 0; i < data_forms->len; i++)
+ {
+ WockyDataForm *form = g_ptr_array_index (data_forms, i);
+
+ if (!tp_strdiff (get_form_type (form), form_type))
+ return manager;
+ }
+ }
+
+ return NULL;
+}
+
+static gboolean
+check_data_form_in_list (GPtrArray *array,
+ const gchar *form_type)
+{
+ guint i;
+
+ for (i = 0; i < array->len; i++)
+ {
+ WockyDataForm *form = g_ptr_array_index (array, i);
+
+ if (!tp_strdiff (get_form_type (form), form_type))
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean
+check_data_form_is_valid (GabbleConnection *self,
+ WockyDataForm *form,
+ GPtrArray *existing_forms)
+{
+ WockyDataFormField *field;
+ const gchar *form_type, *other_client;
+
+ /* We want rid of forms with no FORM_TYPE quickly. */
+ field = g_hash_table_lookup (form->fields, "FORM_TYPE");
+
+ if (field == NULL || tp_str_empty (field->raw_value_contents[0]))
+ {
+ WARNING ("data form with no FORM_TYPE field; ignoring");
+ return FALSE;
+ }
+
+ form_type = field->raw_value_contents[0];
+
+ /* We don't want the same data form from another
+ * caps channel manager for this client either */
+ if (check_data_form_in_list (existing_forms, form_type))
+ {
+ WARNING ("duplicate data form '%s' from another channel "
+ "manager; ignoring", form_type);
+ return FALSE;
+ }
+
+ /* And lastly we don't want a form we're already
+ * advertising. */
+ other_client = check_form_is_unique (self, form_type);
+ if (other_client != NULL)
+ {
+ WARNING ("Data form '%s' already provided by client "
+ "%s; ignoring", form_type, other_client);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
/**
* gabble_connection_update_capabilities
*
@@ -3315,9 +3414,25 @@ gabble_connection_update_capabilities (
{
if (GABBLE_IS_CAPS_CHANNEL_MANAGER (manager))
{
+ GPtrArray *forms = g_ptr_array_new_with_free_func (
+ (GDestroyNotify) g_object_unref);
+ guint j;
+
+ /* First, represent the client... */
gabble_caps_channel_manager_represent_client (
GABBLE_CAPS_CHANNEL_MANAGER (manager), client_name, filters,
- cap_tokens, cap_set, data_forms);
+ cap_tokens, cap_set, forms);
+
+ /* Now check the forms... */
+ for (j = 0; j < forms->len; j++)
+ {
+ WockyDataForm *form = g_ptr_array_index (forms, j);
+
+ if (check_data_form_is_valid (self, form, data_forms))
+ g_ptr_array_add (data_forms, g_object_ref (form));
+ }
+
+ g_ptr_array_unref (forms);
}
}
@@ -3346,20 +3461,13 @@ gabble_connection_update_capabilities (
{
guint j;
+ /* now print out what forms we have here */
DEBUG ("client %s contributes %u data form%s:", client_name,
data_forms->len,
data_forms->len > 1 ? "s" : "");
for (j = 0; j < data_forms->len; j++)
- {
- WockyDataForm *form = g_ptr_array_index (data_forms, j);
- WockyDataFormField *field;
-
- field = g_hash_table_lookup (form->fields, "FORM_TYPE");
- g_assert (field != NULL);
-
- DEBUG (" - %s", field->raw_value_contents[0]);
- }
+ DEBUG (" - %s", get_form_type (g_ptr_array_index (data_forms, i)));
g_hash_table_insert (self->priv->client_data_forms,
g_strdup (client_name), data_forms);