diff --git a/data/org.freedesktop.Telepathy.Logger.gschema.xml.in b/data/org.freedesktop.Telepathy.Logger.gschema.xml.in index ddb4c15..ca39e36 100644 --- a/data/org.freedesktop.Telepathy.Logger.gschema.xml.in +++ b/data/org.freedesktop.Telepathy.Logger.gschema.xml.in @@ -8,5 +8,10 @@ "false" will completely disable all logging. + + [] + <_summary>Ignore list + <_description>Conversations with entities with ID listed here will not be logged. + diff --git a/telepathy-logger/conf-internal.h b/telepathy-logger/conf-internal.h index bf80860..9e0d4c3 100644 --- a/telepathy-logger/conf-internal.h +++ b/telepathy-logger/conf-internal.h @@ -51,10 +51,10 @@ TplConf *_tpl_conf_dup (void); gboolean _tpl_conf_is_globally_enabled (TplConf *self); gboolean _tpl_conf_is_account_ignored (TplConf *self, const gchar *account_path); -// GSList *_tpl_conf_get_accounts_ignorelist (TplConf *self); +const gchar **_tpl_conf_get_accounts_ignorelist (TplConf *self); void _tpl_conf_globally_enable (TplConf *self, gboolean enable); -// void _tpl_conf_set_accounts_ignorelist (TplConf *self, GSList *newlist); +void _tpl_conf_set_accounts_ignorelist (TplConf *self, const gchar **newlist); G_END_DECLS #endif // __TPL_CONF_H__ diff --git a/telepathy-logger/conf.c b/telepathy-logger/conf.c index d9e21fb..45cc4b0 100644 --- a/telepathy-logger/conf.c +++ b/telepathy-logger/conf.c @@ -42,6 +42,7 @@ static TplConf *conf_singleton = NULL; typedef struct { gboolean test_mode; + gchar **ignore_list; GSettings *gsettings; } TplConfPriv; @@ -49,7 +50,8 @@ typedef struct enum /* properties */ { PROP_0, - PROP_GLOBALLY_ENABLED + PROP_GLOBALLY_ENABLED, + PROP_IGNORE_LIST, }; @@ -108,6 +110,9 @@ tpl_conf_finalize (GObject *obj) priv = GET_PRIV (obj); + g_strfreev (priv->ignore_list); + priv->ignore_list = NULL; + if (priv->gsettings != NULL) { g_object_unref (priv->gsettings); @@ -157,6 +162,12 @@ _tpl_conf_class_init (TplConfClass *klass) TRUE, G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE)); + g_object_class_install_property (object_class, PROP_IGNORE_LIST, + g_param_spec_pointer ("ignore-list", + "Ignore List", + "List of TplEntities with which not to log conversations.", + G_PARAM_READWRITE)); + g_type_class_add_private (object_class, sizeof (TplConfPriv)); } @@ -178,6 +189,8 @@ _tpl_conf_init (TplConf *self) g_signal_connect (priv->gsettings, "changed::" KEY_ENABLED, G_CALLBACK (_notify_globally_enable), self); } + + priv->ignore_list = NULL; } @@ -243,3 +256,74 @@ _tpl_conf_globally_enable (TplConf *self, g_settings_set_boolean (GET_PRIV (self)->gsettings, KEY_ENABLED, enable); } + +/** + * _tpl_conf_set_accounts_ignorelist: + * @self: a TplConf instance + * @newlist: a NULL-terminated list of account/entity IDs that should not be logged + */ +void +_tpl_conf_set_accounts_ignorelist (TplConf *self, + const gchar **newlist) +{ + TplConfPriv *priv; + + g_return_if_fail (TPL_IS_CONF (self)); + + priv = GET_PRIV (self); + + if (!priv->test_mode) { + g_settings_set_strv (GET_PRIV (self)->gsettings, "ignorelist", newlist); + } + + g_strfreev (priv->ignore_list); + priv->ignore_list = g_strdupv ((gchar **) newlist); + + g_object_notify (G_OBJECT (self), "ignore-list"); +} + +/** + * _tpl_conf_get_accounts_ignorelist: + * @self: a TplConf instance + * + * Provides list of IDs in "account_id/entity_id" format. Events from or to + * this entities should not be logged. + * + * Return value: (transfer-full) a newly allocated NULL-terminated list of contact IDs. + * The list is owned by the @self and should not be freed. + */ +const gchar** +_tpl_conf_get_accounts_ignorelist (TplConf *self) +{ + TplConfPriv *priv; + + g_return_val_if_fail (TPL_IS_CONF (self), NULL); + + priv = GET_PRIV (self); + + if ((priv->ignore_list == NULL) && (!priv->test_mode)) { + priv->ignore_list = g_settings_get_strv (priv->gsettings, "ignorelist"); + } + + return (const gchar **) priv->ignore_list; +} + +gboolean +_tpl_conf_is_account_ignored (TplConf *self, + const gchar *account_path) +{ + gint i; + const gchar **ignore_list; + + g_return_val_if_fail (TPL_IS_CONF (self), FALSE); + g_return_val_if_fail (account_path && *account_path, FALSE); + + ignore_list = _tpl_conf_get_accounts_ignorelist (self); + for (i = 0; ignore_list && ignore_list[i]; i++) { + if (strcmp (ignore_list[i], account_path) == 0) { + return TRUE; + } + } + + return FALSE; +} \ No newline at end of file diff --git a/telepathy-logger/log-manager.c b/telepathy-logger/log-manager.c index 642e3f9..9eebb13 100644 --- a/telepathy-logger/log-manager.c +++ b/telepathy-logger/log-manager.c @@ -317,6 +317,37 @@ tpl_log_manager_dup_singleton (void) return g_object_new (TPL_TYPE_LOG_MANAGER, NULL); } +static gchar * +get_account_entity_id (TpAccount *account, + TplEntity *entity) +{ + const gchar *name; + gchar *id; + gchar *escaped_account, *escaped_id = NULL; + + name = tp_proxy_get_object_path (account); + if (g_str_has_prefix (name, TP_ACCOUNT_OBJECT_PATH_BASE)) + name += strlen (TP_ACCOUNT_OBJECT_PATH_BASE); + escaped_account = g_strdelimit (g_strdup (name), "/", '_'); + + if (entity != NULL) + { + escaped_id = g_strdelimit ( + g_strdup (tpl_entity_get_identifier (entity)), + "/", '_'); + } + + if (entity != NULL + && tpl_entity_get_entity_type (entity) == TPL_ENTITY_ROOM) + id = g_build_path (G_DIR_SEPARATOR_S, escaped_account, "chatroom", escaped_id, NULL); + else + id = g_build_path (G_DIR_SEPARATOR_S, escaped_account, escaped_id, NULL); + + g_free (escaped_account); + g_free (escaped_id); + + return id; +} /* * _tpl_log_manager_add_event: @@ -340,8 +371,12 @@ _tpl_log_manager_add_event (TplLogManager *manager, GError **error) { TplLogManagerPriv *priv; + TpAccount *account; GList *l; gboolean retval = FALSE; + gchar *id; + + TplEntity *target; g_return_val_if_fail (error == NULL || *error == NULL, FALSE); g_return_val_if_fail (TPL_IS_LOG_MANAGER (manager), FALSE); @@ -355,6 +390,26 @@ _tpl_log_manager_add_event (TplLogManager *manager, return FALSE; } + account = tpl_event_get_account (event); + + /* check whether receiver is in the list of contacts to ignore */ + target = tpl_event_get_receiver (event); + id = get_account_entity_id (account, target); + if (_tpl_conf_is_account_ignored (priv->conf, id)) { + g_free (id); + return FALSE; + } + g_free (id); + + /* check whether sender is in the list of contacts to ignore */ + target = tpl_event_get_sender (event); + id = get_account_entity_id (account, target); + if (_tpl_conf_is_account_ignored (priv->conf, id)) { + g_free (id); + return FALSE; + } + g_free (id); + /* send the event to any writable log store */ for (l = priv->writable_stores; l != NULL; l = g_list_next (l)) { diff --git a/tests/dbus/test-log-manager.c b/tests/dbus/test-log-manager.c index c3a91a6..8edf461 100644 --- a/tests/dbus/test-log-manager.c +++ b/tests/dbus/test-log-manager.c @@ -7,6 +7,7 @@ #include "telepathy-logger/debug-internal.h" #include "telepathy-logger/log-manager-internal.h" #include "telepathy-logger/log-store-internal.h" +#include #include @@ -510,6 +511,146 @@ test_search (TestCaseFixture *fixture, fixture->ret = NULL; } +static gboolean +check_ignored_messages (TestCaseFixture *fixture, + TplTextEvent *event, + gboolean should_exist) +{ + TplEntity *entity; + GList *iter; + GDate *date; + + g_object_get (event, "sender", &entity, NULL); + date = g_date_new_dmy (1, 1, 1970); + tpl_log_manager_get_events_for_date_async ( + fixture->manager, + fixture->account, + entity, + TPL_EVENT_MASK_ANY, + date, + get_events_for_date_cb, + fixture); + g_main_loop_run (fixture->main_loop); + + for (iter = fixture->ret; iter; iter = g_list_next (iter)) { + TplEvent *found_event = iter->data; + gchar *result_token, *ref_token; + gboolean exists; + + g_object_get (G_OBJECT (found_event), "message-token", &result_token, NULL); + g_object_get (G_OBJECT (event), "message-token", &ref_token, NULL); + exists = (g_strcmp0 (result_token, ref_token) == 0); + + if (should_exist != exists) { + g_list_free_full (fixture->ret, g_object_unref); + return FALSE; + } + } + + g_list_free_full (fixture->ret, g_object_unref); + + return TRUE; +} + +static void +test_ignorelist (TestCaseFixture *fixture, + gconstpointer user_data) +{ + TplTextEvent *event1, *event2; + TplEntity *receiver, *sender; + TplConf *conf; + gboolean passed; + const gchar *ignorelist[3] = { + "gabble_jabber_user_40collabora_2eco_2euk/ignoreduser1@collabora.co.uk", + "gabble_jabber_user_40collabora_2eco_2euk/ignoreduser2@collabora.co.uk",NULL }; + + receiver = tpl_entity_new ("ignoreduser1@collabora.co.uk", TPL_ENTITY_CONTACT, "Me", "no-avatar"); + sender = tpl_entity_new ("ignoreduser2@collabora.co.uk", TPL_ENTITY_CONTACT, "Someone Else", "no-avatar"); + + event1 = g_object_new (TPL_TYPE_TEXT_EVENT, + "account", fixture->account, + "channel-path", "org.freedesktop.Telepathy.channel.path", + "receiver", receiver, + "sender", sender, + "timestamp", 1, + "message-token", "1234", + "supersedes-token", "5678", + "edit-timestamp", 0, + "message-type", TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL, + "message", "Test 1", + NULL); + + event2 = g_object_new (TPL_TYPE_TEXT_EVENT, + "account", fixture->account, + "channel-path", "org.freedesktop.Telepathy.channel.path", + "receiver", sender, + "sender", receiver, + "timestamp", 2, + "message-token", "5678", + "supersedes-token", "9012", + "edit-timestamp", 0, + "message-type", TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL, + "message", "Test 2", + NULL); + + conf = _tpl_conf_dup (); + + /* Ignore messages from both */ + _tpl_conf_set_accounts_ignorelist (conf, ignorelist); + _tpl_log_manager_add_event (fixture->manager, TPL_EVENT (event1), NULL); + _tpl_log_manager_add_event (fixture->manager, TPL_EVENT (event2), NULL); + + passed = check_ignored_messages (fixture, event1, FALSE); + if (!passed) { + _tpl_log_manager_clear_entity (fixture->manager, fixture->account, sender); + _tpl_log_manager_clear_entity (fixture->manager, fixture->account, receiver); + g_assert (passed); + } + + passed = check_ignored_messages (fixture, event2, FALSE); + _tpl_log_manager_clear_entity (fixture->manager, fixture->account, sender); + _tpl_log_manager_clear_entity (fixture->manager, fixture->account, receiver); + if (!passed) { + g_assert (passed); + } + + /* Ignore message only from ignoreduser1 */ + ignorelist[1] = NULL; + _tpl_conf_set_accounts_ignorelist (conf, ignorelist); + _tpl_log_manager_add_event (fixture->manager, TPL_EVENT (event1), NULL); + _tpl_log_manager_add_event (fixture->manager, TPL_EVENT (event2), NULL); + + passed = check_ignored_messages (fixture, event1, FALSE); + if (!passed) { + _tpl_log_manager_clear_entity (fixture->manager, fixture->account, sender); + _tpl_log_manager_clear_entity (fixture->manager, fixture->account, receiver); + g_assert (passed); + } + + passed = check_ignored_messages (fixture, event2, TRUE); + _tpl_log_manager_clear_entity (fixture->manager, fixture->account, sender); + _tpl_log_manager_clear_entity (fixture->manager, fixture->account, receiver); + if (!passed) { + g_assert (passed); + } + + /* Don't ignore any message */ + _tpl_conf_set_accounts_ignorelist (conf, NULL); + _tpl_log_manager_add_event (fixture->manager, TPL_EVENT (event1), NULL); + + passed = check_ignored_messages (fixture, event1, TRUE); + _tpl_log_manager_clear_entity (fixture->manager, fixture->account, sender); + _tpl_log_manager_clear_entity (fixture->manager, fixture->account, receiver); + if (!passed) { + g_assert (passed); + } + + g_object_unref (conf); + g_object_unref (event1); + g_object_unref (event2); + g_object_unref (sender); + g_object_unref (receiver); +} int main (int argc, char **argv) @@ -562,6 +703,10 @@ main (int argc, char **argv) TestCaseFixture, params, setup, test_search, teardown); + g_test_add ("/log-manager/ignorelist", + TestCaseFixture, params, + setup, test_ignorelist, teardown); + retval = g_test_run (); g_list_foreach (l, (GFunc) g_hash_table_unref, NULL);