diff --git a/libeos-parental-controls/app-filter.c b/libeos-parental-controls/app-filter.c index ce3c927..d462d8f 100644 --- a/libeos-parental-controls/app-filter.c +++ b/libeos-parental-controls/app-filter.c @@ -196,6 +196,51 @@ epc_app_filter_is_flatpak_ref_allowed (EpcAppFilter *filter, } } +static gint +strcmp_cb (gconstpointer a, + gconstpointer b) +{ + const gchar *str_a = *((const gchar * const *) a); + const gchar *str_b = *((const gchar * const *) b); + + return g_strcmp0 (str_a, str_b); +} + +/** + * epc_app_filter_get_oars_sections: + * @filter: an #EpcAppFilter + * + * List the OARS sections present in this app filter. The sections are returned + * in lexicographic order. A section will be listed even if its stored value is + * %EPC_APP_FILTER_OARS_VALUE_UNKNOWN. The returned list may be empty. + * + * Returns: (transfer container) (array zero-terminated=1): %NULL-terminated + * array of OARS sections + * Since: 0.1.0 + */ +const gchar ** +epc_app_filter_get_oars_sections (EpcAppFilter *filter) +{ + g_autoptr(GPtrArray) sections = g_ptr_array_new_with_free_func (NULL); + GVariantIter iter; + const gchar *oars_section; + + g_return_val_if_fail (filter != NULL, NULL); + g_return_val_if_fail (filter->ref_count >= 1, NULL); + + g_variant_iter_init (&iter, filter->oars_ratings); + + while (g_variant_iter_loop (&iter, "{&s&s}", &oars_section, NULL)) + g_ptr_array_add (sections, (gpointer) oars_section); + + /* Sort alphabetically for easier comparisons later. */ + g_ptr_array_sort (sections, strcmp_cb); + + g_ptr_array_add (sections, NULL); /* NULL terminator */ + + return (const gchar **) g_ptr_array_free (g_steal_pointer (§ions), FALSE); +} + /** * epc_app_filter_get_oars_value: * @filter: an #EpcAppFilter diff --git a/libeos-parental-controls/app-filter.h b/libeos-parental-controls/app-filter.h index e643950..ab19c5b 100644 --- a/libeos-parental-controls/app-filter.h +++ b/libeos-parental-controls/app-filter.h @@ -103,8 +103,9 @@ gboolean epc_app_filter_is_path_allowed (EpcAppFilter *filter, gboolean epc_app_filter_is_flatpak_ref_allowed (EpcAppFilter *filter, const gchar *flatpak_ref); -EpcAppFilterOarsValue epc_app_filter_get_oars_value (EpcAppFilter *filter, - const gchar *oars_section); +const gchar **epc_app_filter_get_oars_sections (EpcAppFilter *filter); +EpcAppFilterOarsValue epc_app_filter_get_oars_value (EpcAppFilter *filter, + const gchar *oars_section); EpcAppFilter *epc_get_app_filter (GDBusConnection *connection, uid_t user_id, diff --git a/libeos-parental-controls/tests/app-filter.c b/libeos-parental-controls/tests/app-filter.c index c0062c3..6e2eadc 100644 --- a/libeos-parental-controls/tests/app-filter.c +++ b/libeos-parental-controls/tests/app-filter.c @@ -29,6 +29,21 @@ #include +/* Check two arrays contain exactly the same items in the same order. */ +static void +assert_strv_equal (const gchar * const *strv_a, + const gchar * const *strv_b) +{ + gsize i; + + for (i = 0; strv_a[i] != NULL && strv_b[i] != NULL; i++) + g_assert_cmpstr (strv_a[i], ==, strv_b[i]); + + g_assert_null (strv_a[i]); + g_assert_null (strv_b[i]); +} + + /* A placeholder smoketest which checks that the error quark works. */ static void test_app_filter_error_quark (void) @@ -98,6 +113,7 @@ test_app_filter_builder_non_empty (BuilderFixture *fixture, gconstpointer test_data) { g_autoptr(EpcAppFilter) filter = NULL; + g_autofree const gchar **sections = NULL; epc_app_filter_builder_blacklist_path (fixture->builder, "/bin/true"); epc_app_filter_builder_blacklist_path (fixture->builder, "/usr/bin/gnome-software"); @@ -127,6 +143,10 @@ test_app_filter_builder_non_empty (BuilderFixture *fixture, EPC_APP_FILTER_OARS_VALUE_MODERATE); g_assert_cmpint (epc_app_filter_get_oars_value (filter, "something-else"), ==, EPC_APP_FILTER_OARS_VALUE_UNKNOWN); + + sections = epc_app_filter_get_oars_sections (filter); + const gchar * const expected_sections[] = { "drugs-alcohol", "language-humor", NULL }; + assert_strv_equal ((const gchar * const *) sections, expected_sections); } /* Test building an empty #EpcAppFilter using an #EpcAppFilterBuilder. */ @@ -135,6 +155,7 @@ test_app_filter_builder_empty (BuilderFixture *fixture, gconstpointer test_data) { g_autoptr(EpcAppFilter) filter = NULL; + g_autofree const gchar **sections = NULL; filter = epc_app_filter_builder_end (fixture->builder); @@ -153,6 +174,10 @@ test_app_filter_builder_empty (BuilderFixture *fixture, EPC_APP_FILTER_OARS_VALUE_UNKNOWN); g_assert_cmpint (epc_app_filter_get_oars_value (filter, "something-else"), ==, EPC_APP_FILTER_OARS_VALUE_UNKNOWN); + + sections = epc_app_filter_get_oars_sections (filter); + const gchar * const expected_sections[] = { NULL }; + assert_strv_equal ((const gchar * const *) sections, expected_sections); } /* Check that copying a cleared #EpcAppFilterBuilder works, and the copy can