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..f88aa33 100644 --- a/telepathy-logger/conf-internal.h +++ b/telepathy-logger/conf-internal.h @@ -49,12 +49,10 @@ GType _tpl_conf_get_type (void); 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_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_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..768ece3 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,54 @@ _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_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_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; +} diff --git a/telepathy-logger/log-manager.c b/telepathy-logger/log-manager.c index 37ff1d4..9fb3f6e 100644 --- a/telepathy-logger/log-manager.c +++ b/telepathy-logger/log-manager.c @@ -308,7 +308,6 @@ tpl_log_manager_dup_singleton (void) return g_object_new (TPL_TYPE_LOG_MANAGER, NULL); } - /* * _tpl_log_manager_add_event: * @manager: the log manager @@ -329,6 +328,9 @@ _tpl_log_manager_add_event (TplLogManager *manager, GList *l; gboolean retval = FALSE; + TplEntity *target; + TpAccount *account; + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); g_return_val_if_fail (TPL_IS_LOG_MANAGER (manager), FALSE); g_return_val_if_fail (TPL_IS_EVENT (event), FALSE); @@ -341,6 +343,18 @@ _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); + if (tpl_log_manager_is_disabled_for_entity (manager, account, target)) + return FALSE; + + /* check whether sender is in the list of contacts to ignore */ + target = tpl_event_get_sender (event); + if (tpl_log_manager_is_disabled_for_entity (manager, account, target)) + return FALSE; + /* send the event to any writable log store */ for (l = priv->writable_stores; l != NULL; l = g_list_next (l)) { @@ -1441,3 +1455,165 @@ _tpl_log_manager_search_hit_copy (TplLogSearchHit *hit) return _tpl_log_manager_search_hit_new (hit->account, hit->target, hit->date); } + +static gchar * +_tpl_log_manager_build_identifier (TpAccount *account, + TplEntity *entity) +{ + gchar *identifier; + const gchar *acc_name = tp_proxy_get_object_path (account); + if (g_str_has_prefix (acc_name, TP_ACCOUNT_OBJECT_PATH_BASE)) + acc_name += strlen (TP_ACCOUNT_OBJECT_PATH_BASE); + + identifier = g_strconcat (acc_name, "/", tpl_entity_get_identifier (entity), NULL); + + return identifier; +} + +static gboolean +_tpl_log_manager_is_disabled_for_entity (TplLogManager *self, + const gchar *identifier) +{ + gint i; + TplLogManagerPriv *priv = self->priv; + const gchar **ignorelist; + + priv = self->priv; + ignorelist = _tpl_conf_get_ignorelist (priv->conf); + + for (i = 0; ignorelist && ignorelist[i]; i++) + { + if (g_strcmp0 (ignorelist[i], identifier) == 0) + { + return TRUE; + } + } + + return FALSE; +} + +/** + * tpl_log_manager_disable_for_entity: + * @self: the log manager + * @entity a TplEntity + * + * Disables logging of events for given entity. By default logging is enabled + * for all entities. + */ +void +tpl_log_manager_disable_for_entity (TplLogManager *self, + TpAccount *account, + TplEntity *entity) +{ + TplLogManagerPriv *priv; + gchar *identifier; + + g_return_if_fail (TPL_IS_LOG_MANAGER (self)); + g_return_if_fail (TP_IS_ACCOUNT (account)); + g_return_if_fail (TPL_IS_ENTITY (entity)); + + priv = self->priv; + identifier = _tpl_log_manager_build_identifier (account, entity); + if (!_tpl_log_manager_is_disabled_for_entity (self, identifier)) + { + const gchar **ignorelist = _tpl_conf_get_ignorelist (priv->conf); + gchar **newlist; + if (ignorelist) + { + gint newlen; + newlist = g_strdupv ((gchar **) ignorelist); + newlen = g_strv_length (newlist) + 1; + newlist = g_realloc (newlist, sizeof (gchar*) * newlen ); + newlist[newlen - 1] = g_strdup (identifier); + } + else + { + newlist = g_malloc0_n (2, sizeof (gchar*)); + newlist[0] = g_strdup (identifier); + } + + _tpl_conf_set_ignorelist (priv->conf, (const gchar **) newlist); + g_strfreev (newlist); + } + + g_free (identifier); +} + +/** + * tpl_log_manager_enable_for_entity: + * @self: the log manager + * @entity: a TplEntity + * + * Re-enables logging of events for entity previously disabled by + * tpl_log_manager_disable_for_entity(). By default logging is enabled for all + * entities. + */ +void +tpl_log_manager_enable_for_entity (TplLogManager *self, + TpAccount *account, + TplEntity *entity) +{ + TplLogManagerPriv *priv; + gchar *identifier; + + g_return_if_fail (TPL_IS_LOG_MANAGER (self)); + g_return_if_fail (TP_IS_ACCOUNT (account)); + g_return_if_fail (TPL_IS_ENTITY (entity)); + + priv = self->priv; + identifier = _tpl_log_manager_build_identifier (account, entity); + if (_tpl_log_manager_is_disabled_for_entity (self, identifier)) + { + gint i, j; + const gchar **ignorelist = _tpl_conf_get_ignorelist (priv->conf); + gchar **newlist; + + if (!ignorelist) + return; + + newlist = g_malloc0_n (g_strv_length ((gchar **) ignorelist) - 1, sizeof (gchar*)); + j = 0; + for (i = 0; ignorelist && ignorelist[i]; i++) + { + if (g_strcmp0 (ignorelist[i], identifier) != 0) + { + newlist[j] = g_strdup (ignorelist[i]); + j++; + } + } + + _tpl_conf_set_ignorelist (priv->conf, (const gchar **) newlist); + g_strfreev (newlist); + } + + g_free (identifier); +} + +/** + * tpl_log_manager_is_disabled_for_entity: + * @self: the log manager + * @entity: a TplEntity + * + * Checks, whether logging is disabled for given entity. By default, logging + * is enabled for all entities. + * + * Returns: %TRUE if logging for the entity has been disabled, %FALSE otherwise. + */ +gboolean +tpl_log_manager_is_disabled_for_entity (TplLogManager *self, + TpAccount *account, + TplEntity *entity) +{ + gboolean is_disabled; + gchar *identifier; + + g_return_val_if_fail (TPL_IS_LOG_MANAGER (self), FALSE); + g_return_val_if_fail (TP_IS_ACCOUNT (account), FALSE); + g_return_val_if_fail (TPL_IS_ENTITY (entity), FALSE); + + identifier = _tpl_log_manager_build_identifier (account, entity); + is_disabled = _tpl_log_manager_is_disabled_for_entity (self, identifier); + g_free (identifier); + + return is_disabled; +} diff --git a/telepathy-logger/log-manager.h b/telepathy-logger/log-manager.h index bd5e610..df8c0bc 100644 --- a/telepathy-logger/log-manager.h +++ b/telepathy-logger/log-manager.h @@ -175,6 +175,18 @@ gboolean tpl_log_manager_search_finish (TplLogManager *self, GList **hits, GError **error); +void tpl_log_manager_disable_for_entity (TplLogManager *self, + TpAccount *account, + TplEntity *entity); + +void tpl_log_manager_enable_for_entity (TplLogManager *self, + TpAccount *account, + TplEntity *entity); + +gboolean tpl_log_manager_is_disabled_for_entity (TplLogManager *self, + TpAccount *account, + TplEntity *entity); + void tpl_log_manager_search_free (GList *hits); G_END_DECLS diff --git a/tests/dbus/test-log-manager.c b/tests/dbus/test-log-manager.c index 3137931..875dd15 100644 --- a/tests/dbus/test-log-manager.c +++ b/tests/dbus/test-log-manager.c @@ -9,6 +9,7 @@ #include "telepathy-logger/debug-internal.h" #include "telepathy-logger/log-manager-internal.h" #include "telepathy-logger/log-store-internal.h" +#include #include @@ -512,6 +513,150 @@ 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; + + 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_log_manager_disable_for_entity (fixture->manager, fixture->account, receiver); + tpl_log_manager_disable_for_entity (fixture->manager, fixture->account, sender); + g_assert (tpl_log_manager_is_disabled_for_entity (fixture->manager, fixture->account, receiver)); + g_assert (tpl_log_manager_is_disabled_for_entity (fixture->manager, fixture->account, sender)); + + _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 */ + tpl_log_manager_enable_for_entity (fixture->manager, fixture->account, sender); + g_assert (!tpl_log_manager_is_disabled_for_entity (fixture->manager, fixture->account, sender)); + g_assert (tpl_log_manager_is_disabled_for_entity (fixture->manager, fixture->account, receiver)); + _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_log_manager_enable_for_entity (fixture->manager, fixture->account, receiver); + g_assert (!tpl_log_manager_is_disabled_for_entity (fixture->manager, fixture->account, sender)); + g_assert (!tpl_log_manager_is_disabled_for_entity (fixture->manager, fixture->account, receiver)); + _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) @@ -564,6 +709,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);