/** * as_pool_get_components_by_categories: * @pool: An instance of #AsDatabase. * @categories: An array of XDG categories to include. * * Return a list of components which are in one of the categories. * * Returns: (transfer container) (element-type AsComponent): an array of #AsComponent objects which have been found. */ GPtrArray* as_pool_get_components_by_categories (AsPool *pool, gchar **categories) { AsPoolPrivate *priv = GET_PRIVATE (pool); GHashTableIter iter; gpointer value; guint i; GPtrArray *results; results = g_ptr_array_new_with_free_func (g_object_unref); /* sanity check */ for (i = 0; categories[i] != NULL; i++) { if (!as_utils_is_category_name (categories[i])) { g_warning ("'%s' is not a valid XDG category name, search results might be invalid or empty.", categories[i]); } } g_hash_table_iter_init (&iter, priv->cpt_table); while (g_hash_table_iter_next (&iter, NULL, &value)) { AsComponent *cpt = AS_COMPONENT (value); for (i = 0; categories[i] != NULL; i++) { if (as_component_has_category (cpt, categories[i])) g_ptr_array_add (results, g_object_ref (cpt)); } } return results; }
/** * as_data_pool_get_components_by_categories: * @dpool: An instance of #AsDatabase. * @categories: A semicolon-separated list of XDG categories to include. * * Return a list of components which are in one of the categories. * * Returns: (element-type AsComponent) (transfer full): an array of #AsComponent objects which have been found. */ GPtrArray* as_data_pool_get_components_by_categories (AsDataPool *dpool, const gchar *categories) { AsDataPoolPrivate *priv = GET_PRIVATE (dpool); GHashTableIter iter; gpointer value; g_auto(GStrv) cats = NULL; guint i; GPtrArray *results; cats = g_strsplit (categories, ";", -1); results = g_ptr_array_new_with_free_func (g_object_unref); /* sanity check */ for (i = 0; cats[i] != NULL; i++) { if (!as_utils_is_category_name (cats[i])) { g_warning ("'%s' is not a valid XDG category name, search results might be invalid or empty.", cats[i]); } } g_hash_table_iter_init (&iter, priv->cpt_table); while (g_hash_table_iter_next (&iter, NULL, &value)) { gchar **cpt_cats; guint j; AsComponent *cpt = AS_COMPONENT (value); cpt_cats = as_component_get_categories (cpt); if (cpt_cats == NULL) continue; for (i = 0; cats[i] != NULL; i++) { for (j = 0; cpt_cats[j] != NULL; j++) { if (g_strcmp0 (cats[i], cpt_cats[j]) == 0) g_ptr_array_add (results, g_object_ref (cpt)); } } } return results; }
/** * as_validator_analyze_component_metainfo_relation_cb: * * Helper function for GHashTable foreach iteration. */ static void as_validator_analyze_component_metainfo_relation_cb (const gchar *fname, AsComponent *cpt, struct MInfoCheckData *data) { g_autofree gchar *cid_base = NULL; /* if we have no component-id, we can't check anything */ if (as_component_get_id (cpt) == NULL) return; as_validator_set_current_cpt (data->validator, cpt); as_validator_set_current_fname (data->validator, fname); /* check if the fname and the component-id match */ if (g_str_has_suffix (as_component_get_id (cpt), ".desktop")) { cid_base = g_strndup (as_component_get_id (cpt), g_strrstr (as_component_get_id (cpt), ".") - as_component_get_id (cpt)); } else { cid_base = g_strdup (as_component_get_id (cpt)); } if (!as_matches_metainfo (fname, cid_base)) { /* the name-without-type didn't match - check for the full id in the component name */ if (!as_matches_metainfo (fname, as_component_get_id (cpt))) { as_validator_add_issue (data->validator, NULL, AS_ISSUE_IMPORTANCE_WARNING, AS_ISSUE_KIND_WRONG_NAME, "The metainfo filename does not match the component ID."); } } /* check if the referenced .desktop file exists */ if (as_component_get_kind (cpt) == AS_COMPONENT_KIND_DESKTOP_APP) { if (g_hash_table_contains (data->desktop_fnames, as_component_get_desktop_id (cpt))) { g_autofree gchar *desktop_fname_full = NULL; g_autoptr(GKeyFile) dfile = NULL; GError *tmp_error = NULL; desktop_fname_full = g_build_filename (data->apps_dir, as_component_get_desktop_id (cpt), NULL); dfile = g_key_file_new (); g_key_file_load_from_file (dfile, desktop_fname_full, G_KEY_FILE_NONE, &tmp_error); if (tmp_error != NULL) { as_validator_add_issue (data->validator, NULL, AS_ISSUE_IMPORTANCE_WARNING, AS_ISSUE_KIND_READ_ERROR, "Unable to read associated .desktop file: %s", tmp_error->message); g_error_free (tmp_error); tmp_error = NULL; } else { /* we successfully opened the .desktop file, now perform some checks */ /* name */ if (as_str_empty (as_component_get_name (cpt)) && (!g_key_file_has_key (dfile, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_NAME, NULL))) { /* we don't have a summary, and there is also none in the .desktop file - this is bad. */ as_validator_add_issue (data->validator, NULL, AS_ISSUE_IMPORTANCE_ERROR, AS_ISSUE_KIND_VALUE_MISSING, "The component is missing a name (none found in its metainfo or .desktop file)"); } /* summary */ if (as_str_empty (as_component_get_summary (cpt)) && (!g_key_file_has_key (dfile, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_COMMENT, NULL))) { /* we don't have a summary, and there is also none in the .desktop file - this is bad. */ as_validator_add_issue (data->validator, NULL, AS_ISSUE_IMPORTANCE_ERROR, AS_ISSUE_KIND_VALUE_MISSING, "The component is missing a summary (none found in its metainfo or .desktop file)"); } /* categories */ if (g_key_file_has_key (dfile, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_CATEGORIES, NULL)) { g_autofree gchar *cats_str = NULL; g_auto(GStrv) cats = NULL; guint i; cats_str = g_key_file_get_string (dfile, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_CATEGORIES, NULL); cats = g_strsplit (cats_str, ";", -1); for (i = 0; cats[i] != NULL; i++) { if (as_str_empty (cats[i])) continue; if (!as_utils_is_category_name (cats[i])) { as_validator_add_issue (data->validator, NULL, AS_ISSUE_IMPORTANCE_ERROR, AS_ISSUE_KIND_VALUE_WRONG, "The category '%s' defined in the .desktop file does not exist.", cats[i]); } } } } } else { as_validator_add_issue (data->validator, NULL, AS_ISSUE_IMPORTANCE_ERROR, AS_ISSUE_KIND_FILE_MISSING, "Component metadata refers to a non-existing .desktop file."); } } as_validator_clear_current_cpt (data->validator); as_validator_clear_current_fname (data->validator); }