/** * asb_plugin_process_filename: */ static gboolean asb_plugin_process_filename (AsbPlugin *plugin, AsbPackage *pkg, const gchar *filename, GList **apps, GError **error) { _cleanup_object_unref_ AsbApp *app = NULL; app = asb_app_new (pkg, NULL); if (!as_app_parse_file (AS_APP (app), filename, AS_APP_PARSE_FLAG_APPEND_DATA, error)) return FALSE; if (as_app_get_id_kind (AS_APP (app)) != AS_ID_KIND_ADDON && as_app_get_id_kind (AS_APP (app)) != AS_ID_KIND_FONT) { g_set_error (error, ASB_PLUGIN_ERROR, ASB_PLUGIN_ERROR_FAILED, "%s is not an addon or font", as_app_get_id (AS_APP (app))); return FALSE; } asb_app_set_requires_appdata (app, FALSE); asb_app_set_hidpi_enabled (app, asb_context_get_flag (plugin->ctx, ASB_CONTEXT_FLAG_HIDPI_ICONS)); asb_plugin_add_app (apps, AS_APP (app)); return TRUE; }
static AsApp * load_appdata (const gchar *prefix, const gchar *app_name, GError **error) { g_autofree gchar *appdata_basename = NULL; g_autofree gchar *appdata_path = NULL; g_autoptr(AsApp) app = NULL; g_autoptr(GPtrArray) problems = NULL; AsProblemKind problem_kind; AsProblem *problem; guint i; appdata_basename = g_strconcat (app_name, ".appdata.xml", NULL); appdata_path = g_build_filename (prefix, "share", "appdata", appdata_basename, NULL); g_debug ("Looking for %s", appdata_path); app = as_app_new (); if (!as_app_parse_file (app, appdata_path, AS_APP_PARSE_FLAG_USE_HEURISTICS, error)) return NULL; if (as_app_get_kind (app) == AS_APP_KIND_UNKNOWN) { g_set_error (error, AS_APP_ERROR, AS_APP_ERROR_FAILED, "%s has no recognised type", as_app_get_id (AS_APP (app))); return NULL; } problems = as_app_validate (app, AS_APP_VALIDATE_FLAG_NO_NETWORK | AS_APP_VALIDATE_FLAG_RELAX, error); if (problems == NULL) return NULL; for (i = 0; i < problems->len; i++) { problem = g_ptr_array_index (problems, i); problem_kind = as_problem_get_kind (problem); as_compose_app_log (app, "AppData problem: %s : %s", as_problem_kind_to_string (problem_kind), as_problem_get_message (problem)); } if (problems->len > 0) { g_set_error (error, AS_APP_ERROR, AS_APP_ERROR_FAILED, "AppData file %s was not valid", appdata_path); return NULL; } return g_steal_pointer (&app); }
static AsApp * load_desktop (const gchar *prefix, const gchar *icons_dir, guint min_icon_size, const gchar *app_name, const gchar *appdata_id, GError **error) { AsIcon *icon; g_autofree gchar *desktop_basename = NULL; g_autofree gchar *desktop_path = NULL; g_autoptr(AsApp) app = NULL; if (appdata_id != NULL) desktop_basename = g_strdup (appdata_id); else desktop_basename = g_strconcat (app_name, ".desktop", NULL); desktop_path = g_build_filename (prefix, "share/applications", desktop_basename, NULL); app = as_app_new (); if (!as_app_parse_file (app, desktop_path, AS_APP_PARSE_FLAG_USE_HEURISTICS | AS_APP_PARSE_FLAG_ALLOW_VETO, error)) return NULL; if (as_app_get_kind (app) == AS_APP_KIND_UNKNOWN) { g_set_error (error, AS_APP_ERROR, AS_APP_ERROR_FAILED, "%s has no recognised type", as_app_get_id (AS_APP (app))); return NULL; } icon = as_app_get_icon_default (AS_APP (app)); if (icon != NULL) { g_autofree gchar *key = NULL; key = g_strdup (as_icon_get_name (icon)); if (as_icon_get_kind (icon) == AS_ICON_KIND_STOCK) { as_compose_app_log (app, "using stock icon %s", key); } else { g_autoptr(GError) error_local = NULL; gboolean ret; g_ptr_array_set_size (as_app_get_icons (AS_APP (app)), 0); ret = add_icons (app, icons_dir, min_icon_size, prefix, key, error); if (!ret) return NULL; } } return g_steal_pointer (&app); }
static gboolean asb_plugin_desktop_refine (AsbPlugin *plugin, AsbPackage *pkg, const gchar *filename, AsbApp *app, const gchar *tmpdir, GError **error) { AsIcon *icon; AsAppParseFlags parse_flags = AS_APP_PARSE_FLAG_USE_HEURISTICS | AS_APP_PARSE_FLAG_ALLOW_VETO; gboolean ret; g_autoptr(AsApp) desktop_app = NULL; g_autoptr(GdkPixbuf) pixbuf = NULL; /* use GenericName fallback */ if (asb_context_get_flag (plugin->ctx, ASB_CONTEXT_FLAG_USE_FALLBACKS)) parse_flags |= AS_APP_PARSE_FLAG_USE_FALLBACKS; /* create app */ desktop_app = as_app_new (); if (!as_app_parse_file (desktop_app, filename, parse_flags, error)) return FALSE; /* copy all metadata */ as_app_subsume_full (AS_APP (app), desktop_app, AS_APP_SUBSUME_FLAG_NO_OVERWRITE); /* is the icon a stock-icon-name? */ icon = as_app_get_icon_default (AS_APP (app)); if (icon != NULL) { g_autofree gchar *key = NULL; key = g_strdup (as_icon_get_name (icon)); if (as_icon_get_kind (icon) == AS_ICON_KIND_STOCK) { asb_package_log (pkg, ASB_PACKAGE_LOG_LEVEL_DEBUG, "using stock icon %s", key); } else { g_autoptr(GError) error_local = NULL; g_ptr_array_set_size (as_app_get_icons (AS_APP (app)), 0); ret = asb_plugin_desktop_add_icons (plugin, app, tmpdir, key, &error_local); if (!ret) { as_app_add_veto (AS_APP (app), "%s", error_local->message); } } } return TRUE; }
/** * appdata_validate_and_show_results: **/ static gint appdata_validate_and_show_results (const gchar *filename_original, const gchar *filename, const gchar *output_format, AsAppValidateFlags flags) { AsApp *app; GError *error = NULL; GPtrArray *problems = NULL; const gchar *tmp; gboolean ret; gint retval = EXIT_CODE_SUCCESS; /* scan file for problems */ app = as_app_new (); as_app_set_source_kind (app, AS_APP_SOURCE_KIND_APPDATA); ret = as_app_parse_file (app, filename, AS_APP_PARSE_FLAG_NONE, &error); if (!ret) { retval = EXIT_CODE_FAILURE; g_print ("Failed: %s\n", error->message); g_error_free (error); goto out; } problems = as_app_validate (app, flags, &error); if (problems == NULL) { retval = EXIT_CODE_FAILURE; g_print ("Failed: %s\n", error->message); g_error_free (error); goto out; } if (problems->len > 0) retval = EXIT_CODE_WARNINGS; /* print problems */ tmp = filename_original != NULL ? filename_original : filename; if (g_strcmp0 (output_format, "html") == 0) { appdata_validate_format_html (tmp, problems); } else if (g_strcmp0 (output_format, "xml") == 0) { appdata_validate_format_xml (tmp, problems); } else { appdata_validate_format_text (tmp, problems); } out: g_object_unref (app); if (problems) g_ptr_array_unref (problems); return retval; }
/** * cra_plugin_process_filename: */ static gboolean cra_plugin_process_filename (CraPlugin *plugin, CraPackage *pkg, const gchar *filename, GList **apps, const gchar *tmpdir, GError **error) { const gchar *key; gboolean ret; _cleanup_free_ gchar *app_id = NULL; _cleanup_free_ gchar *full_filename = NULL; _cleanup_free_ gchar *icon_filename = NULL; _cleanup_object_unref_ CraApp *app = NULL; _cleanup_object_unref_ GdkPixbuf *pixbuf = NULL; /* create app */ app_id = g_path_get_basename (filename); app = cra_app_new (pkg, app_id); full_filename = g_build_filename (tmpdir, filename, NULL); ret = as_app_parse_file (AS_APP (app), full_filename, AS_APP_PARSE_FLAG_USE_HEURISTICS, error); if (!ret) return FALSE; /* NoDisplay requires AppData */ if (as_app_get_metadata_item (AS_APP (app), "NoDisplay") != NULL) cra_app_add_requires_appdata (app, "NoDisplay=true"); /* Settings or DesktopSettings requires AppData */ if (as_app_has_category (AS_APP (app), "Settings")) cra_app_add_requires_appdata (app, "Category=Settings"); if (as_app_has_category (AS_APP (app), "DesktopSettings")) cra_app_add_requires_appdata (app, "Category=DesktopSettings"); /* is the icon a stock-icon-name? */ key = as_app_get_icon (AS_APP (app)); if (key != NULL) { if (as_app_get_icon_kind (AS_APP (app)) == AS_ICON_KIND_STOCK) { cra_package_log (pkg, CRA_PACKAGE_LOG_LEVEL_DEBUG, "using stock icon %s", key); } else { /* is icon XPM or GIF */ if (g_str_has_suffix (key, ".xpm")) cra_app_add_veto (app, "Uses XPM icon: %s", key); else if (g_str_has_suffix (key, ".gif")) cra_app_add_veto (app, "Uses GIF icon: %s", key); else if (g_str_has_suffix (key, ".ico")) cra_app_add_veto (app, "Uses ICO icon: %s", key); /* find icon */ pixbuf = cra_app_find_icon (tmpdir, key, error); if (pixbuf == NULL) return FALSE; /* save in target directory */ icon_filename = g_strdup_printf ("%s.png", as_app_get_id (AS_APP (app))); as_app_set_icon (AS_APP (app), icon_filename, -1); as_app_set_icon_kind (AS_APP (app), AS_ICON_KIND_CACHED); cra_app_set_pixbuf (app, pixbuf); } } /* add */ cra_plugin_add_app (apps, app); return TRUE; }
/** * asb_plugin_process_filename: */ static gboolean asb_plugin_process_filename (AsbPlugin *plugin, AsbPackage *pkg, const gchar *filename, GList **apps, const gchar *tmpdir, GError **error) { AsIcon *icon; AsAppParseFlags parse_flags = AS_APP_PARSE_FLAG_USE_HEURISTICS; gboolean ret; _cleanup_free_ gchar *app_id = NULL; _cleanup_free_ gchar *full_filename = NULL; _cleanup_object_unref_ AsbApp *app = NULL; _cleanup_object_unref_ GdkPixbuf *pixbuf = NULL; /* use GenericName fallback */ if (asb_context_get_flag (plugin->ctx, ASB_CONTEXT_FLAG_USE_FALLBACKS)) parse_flags |= AS_APP_PARSE_FLAG_USE_FALLBACKS; /* create app */ app_id = g_path_get_basename (filename); app = asb_app_new (pkg, app_id); asb_app_set_hidpi_enabled (app, asb_context_get_flag (plugin->ctx, ASB_CONTEXT_FLAG_HIDPI_ICONS)); full_filename = g_build_filename (tmpdir, filename, NULL); if (!as_app_parse_file (AS_APP (app), full_filename, parse_flags, error)) return FALSE; /* NoDisplay apps are never included */ if (as_app_get_metadata_item (AS_APP (app), "NoDisplay") != NULL) asb_app_add_requires_appdata (app, "NoDisplay=true"); /* Settings or DesktopSettings requires AppData */ if (!asb_context_get_flag (plugin->ctx, ASB_CONTEXT_FLAG_IGNORE_SETTINGS)) { if (as_app_has_category (AS_APP (app), "Settings")) asb_app_add_requires_appdata (app, "Category=Settings"); if (as_app_has_category (AS_APP (app), "DesktopSettings")) asb_app_add_requires_appdata (app, "Category=DesktopSettings"); } /* is the icon a stock-icon-name? */ icon = as_app_get_icon_default (AS_APP (app)); if (icon != NULL) { _cleanup_free_ gchar *key = NULL; key = g_strdup (as_icon_get_name (icon)); if (as_icon_get_kind (icon) == AS_ICON_KIND_STOCK) { asb_package_log (pkg, ASB_PACKAGE_LOG_LEVEL_DEBUG, "using stock icon %s", key); } else { _cleanup_error_free_ GError *error_local = NULL; g_ptr_array_set_size (as_app_get_icons (AS_APP (app)), 0); ret = asb_plugin_desktop_add_icons (plugin, app, tmpdir, key, &error_local); if (!ret) { as_app_add_veto (AS_APP (app), "%s", error_local->message); } } } /* add */ asb_plugin_add_app (apps, AS_APP (app)); return TRUE; }
static gboolean asb_plugin_process_filename (AsbPlugin *plugin, AsbPackage *pkg, const gchar *filename, GList **apps, GError **error) { AsProblemKind problem_kind; AsProblem *problem; GPtrArray *icons; const gchar *tmp; guint i; g_autoptr(AsbApp) app = NULL; g_autoptr(GPtrArray) problems = NULL; app = asb_app_new (NULL, NULL); if (!as_app_parse_file (AS_APP (app), filename, AS_APP_PARSE_FLAG_USE_HEURISTICS, error)) return FALSE; if (as_app_get_kind (AS_APP (app)) == AS_APP_KIND_UNKNOWN) { g_set_error (error, ASB_PLUGIN_ERROR, ASB_PLUGIN_ERROR_FAILED, "%s has no recognised type", as_app_get_id (AS_APP (app))); return FALSE; } /* validate */ problems = as_app_validate (AS_APP (app), AS_APP_VALIDATE_FLAG_NO_NETWORK | AS_APP_VALIDATE_FLAG_RELAX, error); if (problems == NULL) return FALSE; asb_app_set_package (app, pkg); for (i = 0; i < problems->len; i++) { problem = g_ptr_array_index (problems, i); problem_kind = as_problem_get_kind (problem); asb_package_log (asb_app_get_package (app), ASB_PACKAGE_LOG_LEVEL_WARNING, "AppData problem: %s : %s", as_problem_kind_to_string (problem_kind), as_problem_get_message (problem)); } /* nuke things that do not belong */ icons = as_app_get_icons (AS_APP (app)); if (icons->len > 0) g_ptr_array_set_size (icons, 0); /* fix up the project license */ tmp = as_app_get_project_license (AS_APP (app)); if (tmp != NULL && !as_utils_is_spdx_license (tmp)) { g_autofree gchar *license_spdx = NULL; license_spdx = as_utils_license_to_spdx (tmp); if (as_utils_is_spdx_license (license_spdx)) { asb_package_log (asb_app_get_package (app), ASB_PACKAGE_LOG_LEVEL_WARNING, "project license fixup: %s -> %s", tmp, license_spdx); as_app_set_project_license (AS_APP (app), license_spdx); } else { asb_package_log (asb_app_get_package (app), ASB_PACKAGE_LOG_LEVEL_WARNING, "project license is invalid: %s", tmp); as_app_set_project_license (AS_APP (app), NULL); } } /* check license */ tmp = as_app_get_metadata_license (AS_APP (app)); if (tmp == NULL) { g_set_error (error, ASB_PLUGIN_ERROR, ASB_PLUGIN_ERROR_FAILED, "AppData %s has no licence", filename); return FALSE; } if (!as_utils_is_spdx_license (tmp)) { g_set_error (error, ASB_PLUGIN_ERROR, ASB_PLUGIN_ERROR_FAILED, "AppData %s license '%s' invalid", filename, tmp); return FALSE; } /* log updateinfo */ tmp = as_app_get_update_contact (AS_APP (app)); if (tmp != NULL) { asb_package_log (asb_app_get_package (app), ASB_PACKAGE_LOG_LEVEL_INFO, "Upstream contact <%s>", tmp); } /* add icon for firmware */ if (as_app_get_kind (AS_APP (app)) == AS_APP_KIND_FIRMWARE) { g_autoptr(AsIcon) icon = NULL; icon = as_icon_new (); as_icon_set_kind (icon, AS_ICON_KIND_STOCK); as_icon_set_name (icon, "application-x-executable"); as_app_add_icon (AS_APP (app), icon); } /* fix up input methods */ if (as_app_get_kind (AS_APP (app)) == AS_APP_KIND_INPUT_METHOD) { g_autoptr(AsIcon) icon = NULL; icon = as_icon_new (); as_icon_set_kind (icon, AS_ICON_KIND_STOCK); as_icon_set_name (icon, "system-run-symbolic"); as_app_add_icon (AS_APP (app), icon); as_app_add_category (AS_APP (app), "Addons"); as_app_add_category (AS_APP (app), "InputSources"); } /* fix up codecs */ if (as_app_get_kind (AS_APP (app)) == AS_APP_KIND_CODEC) { g_autoptr(AsIcon) icon = NULL; icon = as_icon_new (); as_icon_set_kind (icon, AS_ICON_KIND_STOCK); as_icon_set_name (icon, "application-x-executable"); as_app_add_icon (AS_APP (app), icon); as_app_add_category (AS_APP (app), "Addons"); as_app_add_category (AS_APP (app), "Codecs"); } /* success */ asb_app_set_hidpi_enabled (app, asb_context_get_flag (plugin->ctx, ASB_CONTEXT_FLAG_HIDPI_ICONS)); asb_plugin_add_app (apps, AS_APP (app)); return TRUE; }
static gboolean as_store_cab_from_bytes_with_origin (AsStore *store, GBytes *bytes, const gchar *basename, GCancellable *cancellable, GError **error) { g_autoptr(GCabCabinet) gcab = NULL; g_autoptr(GError) error_local = NULL; g_autofree gchar *tmp_path = NULL; g_autoptr(GFile) tmp_file = NULL; g_autoptr(GInputStream) input_stream = NULL; g_autoptr(GPtrArray) filelist = NULL; guint i; /* open the file */ gcab = gcab_cabinet_new (); input_stream = g_memory_input_stream_new_from_bytes (bytes); if (!gcab_cabinet_load (gcab, input_stream, NULL, &error_local)) { g_set_error (error, AS_STORE_ERROR, AS_STORE_ERROR_FAILED, "cannot load .cab file: %s", error_local->message); return FALSE; } /* decompress to /tmp */ tmp_path = g_dir_make_tmp ("appstream-glib-XXXXXX", &error_local); if (tmp_path == NULL) { g_set_error (error, AS_STORE_ERROR, AS_STORE_ERROR_FAILED, "failed to create temp dir: %s", error_local->message); return FALSE; } /* extract the entire cab file */ filelist = g_ptr_array_new_with_free_func (g_free); tmp_file = g_file_new_for_path (tmp_path); if (!gcab_cabinet_extract_simple (gcab, tmp_file, as_store_cab_cb, filelist, NULL, &error_local)) { g_set_error (error, AS_STORE_ERROR, AS_STORE_ERROR_FAILED, "failed to extract .cab file: %s", error_local->message); return FALSE; } /* loop through each file looking for components */ for (i = 0; i < filelist->len; i++) { AsRelease *rel; AsChecksum *csum_tmp; const gchar *fn; g_autofree gchar *tmp_fn = NULL; g_autoptr(AsApp) app = NULL; /* debug */ fn = g_ptr_array_index (filelist, i); g_debug ("found file %u\t%s", i, fn); /* if inf or metainfo, add */ if (as_format_guess_kind (fn) != AS_FORMAT_KIND_METAINFO) continue; tmp_fn = g_build_filename (tmp_path, fn, NULL); app = as_app_new (); if (!as_app_parse_file (app, tmp_fn, AS_APP_PARSE_FLAG_NONE, &error_local)) { g_set_error (error, AS_STORE_ERROR, AS_STORE_ERROR_FAILED, "%s could not be loaded: %s", tmp_fn, error_local->message); return FALSE; } /* only process the latest release */ rel = as_app_get_release_default (app); if (rel == NULL) { g_set_error_literal (error, AS_STORE_ERROR, AS_STORE_ERROR_FAILED, "no releases in metainfo file"); return FALSE; } /* ensure we always have a container checksum */ csum_tmp = as_release_get_checksum_by_target (rel, AS_CHECKSUM_TARGET_CONTAINER); if (csum_tmp == NULL) { g_autoptr(AsChecksum) csum = NULL; csum = as_checksum_new (); as_checksum_set_target (csum, AS_CHECKSUM_TARGET_CONTAINER); if (basename != NULL) as_checksum_set_filename (csum, basename); as_release_add_checksum (rel, csum); } /* set the container checksum */ if (!as_store_cab_verify_checksum_cab (rel, bytes, error)) return FALSE; /* this is the size of the cab file itself */ if (as_release_get_size (rel, AS_SIZE_KIND_DOWNLOAD) == 0) as_release_set_size (rel, AS_SIZE_KIND_DOWNLOAD, g_bytes_get_size (bytes)); /* ensure we always have a content checksum */ csum_tmp = as_release_get_checksum_by_target (rel, AS_CHECKSUM_TARGET_CONTENT); if (csum_tmp == NULL) { g_autoptr(AsChecksum) csum = NULL; csum = as_checksum_new (); as_checksum_set_target (csum, AS_CHECKSUM_TARGET_CONTENT); /* if this isn't true, a firmware needs to set in * the metainfo.xml file something like: * <checksum target="content" filename="FLASH.ROM"/> */ as_checksum_set_filename (csum, "firmware.bin"); as_release_add_checksum (rel, csum); csum_tmp = csum; } if (!as_store_cab_verify_checksum_fw (csum_tmp, tmp_path, error)) return FALSE; /* set blobs */ if (!as_store_cab_set_release_blobs (rel, tmp_path, error)) return FALSE; /* add any component to the store */ as_store_add_app (store, app); } /* delete temp files */ for (i = 0; i < filelist->len; i++) { const gchar *fn; g_autofree gchar *tmp_fn = NULL; fn = g_ptr_array_index (filelist, i); tmp_fn = g_build_filename (tmp_path, fn, NULL); g_unlink (tmp_fn); } g_rmdir (tmp_path); /* success */ return TRUE; }