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; }
/** * asb_context_add_app_ignore: **/ void asb_context_add_app_ignore (AsbContext *ctx, AsbPackage *pkg) { AsApp *app_tmp; AsbContextPrivate *priv = GET_PRIVATE (ctx); g_autofree gchar *name_arch = NULL; g_autoptr(AsApp) app = NULL; g_autoptr(GPtrArray) apps = NULL; /* only do this when we are using a cache-id */ if ((priv->flags & ASB_CONTEXT_FLAG_ADD_CACHE_ID) == 0) return; /* check not already added a dummy application for this package */ apps = as_store_get_apps_by_metadata (priv->store_ignore, "X-CacheID", asb_package_get_basename (pkg)); if (apps->len > 0) { g_debug ("already found CacheID of %s", asb_package_get_basename (pkg)); return; } /* package name already exists, but with a different CacheID */ name_arch = g_strdup_printf ("%s.%s", asb_package_get_name (pkg), asb_package_get_arch (pkg)); app_tmp = as_store_get_app_by_id (priv->store_ignore, name_arch); if (app_tmp != NULL) { as_app_add_metadata (AS_APP (app_tmp), "X-CacheID", asb_package_get_basename (pkg)); return; } /* never encountered before, so add */ app = as_app_new (); as_app_set_id (app, name_arch); as_app_add_pkgname (app, asb_package_get_name (pkg)); as_app_add_metadata (app, "X-CacheID", asb_package_get_basename (pkg)); as_store_add_app (priv->store_ignore, app); }
static void gs_editor_button_new_os_upgrade_clicked_cb (GtkApplication *application, GsEditor *self) { g_autoptr(AsApp) item = as_app_new (); const gchar *css = "border: 1px solid #808080;\nbackground: #fffeee;\ncolor: #000;"; /* add new app */ as_app_set_kind (item, AS_APP_KIND_OS_UPGRADE); as_app_set_state (item, AS_APP_STATE_AVAILABLE); as_app_set_id (item, "org.gnome.release"); as_app_set_name (item, NULL, "GNOME"); as_app_set_comment (item, NULL, "A major upgrade, with new features and added polish."); as_app_add_metadata (item, "GnomeSoftware::UpgradeBanner-css", css); as_store_add_app (self->store, item); g_set_object (&self->selected_item, item); self->pending_changes = TRUE; gs_editor_refresh_choice (self); gs_editor_refresh_details (self); gs_editor_set_page (self, "details"); }
static void gs_editor_button_new_feature_clicked_cb (GtkApplication *application, GsEditor *self) { g_autofree gchar *id = NULL; g_autoptr(AsApp) item = as_app_new (); const gchar *css = "border: 1px solid #808080;\nbackground: #eee;\ncolor: #000;"; /* add new app */ as_app_set_kind (item, AS_APP_KIND_DESKTOP); id = g_strdup_printf ("example-%04x.desktop", (guint) g_random_int_range (0x0000, 0xffff)); as_app_set_id (item, id); as_app_add_metadata (item, "GnomeSoftware::FeatureTile-css", css); as_app_add_kudo (item, "GnomeSoftware::popular"); as_app_add_category (item, "Featured"); as_store_add_app (self->store, item); g_set_object (&self->selected_item, item); self->pending_changes = TRUE; gs_editor_refresh_choice (self); gs_editor_refresh_details (self); gs_editor_set_page (self, "details"); }
/** * fu_util_verify_update: **/ static gboolean fu_util_verify_update (FuUtilPrivate *priv, gchar **values, GError **error) { guint i; _cleanup_object_unref_ AsStore *store = NULL; _cleanup_object_unref_ GFile *xml_file = NULL; if (g_strv_length (values) < 2) { g_set_error_literal (error, FWUPD_ERROR, FWUPD_ERROR_INTERNAL, "Invalid arguments: expected 'filename.xml' 'filename.rom'"); return FALSE; } store = as_store_new (); /* open existing file */ xml_file = g_file_new_for_path (values[0]); if (g_file_query_exists (xml_file, NULL)) { if (!as_store_from_file (store, xml_file, NULL, NULL, error)) return FALSE; } /* add new values */ as_store_set_api_version (store, 0.9); for (i = 1; values[i] != NULL; i++) { _cleanup_free_ gchar *guid = NULL; _cleanup_free_ gchar *id = NULL; _cleanup_object_unref_ AsApp *app = NULL; _cleanup_object_unref_ AsRelease *rel = NULL; _cleanup_object_unref_ FuRom *rom = NULL; _cleanup_object_unref_ GFile *file = NULL; _cleanup_error_free_ GError *error_local = NULL; file = g_file_new_for_path (values[i]); rom = fu_rom_new (); g_print ("Processing %s...\n", values[i]); if (!fu_rom_load_file (rom, file, FU_ROM_LOAD_FLAG_BLANK_PPID, NULL, &error_local)) { g_print ("%s\n", error_local->message); continue; } /* add app to store */ app = as_app_new (); id = g_strdup_printf ("0x%04x:0x%04x", fu_rom_get_vendor (rom), fu_rom_get_model (rom)); guid = fu_guid_generate_from_string (id); as_app_set_id (app, guid, -1); as_app_set_id_kind (app, AS_ID_KIND_FIRMWARE); as_app_set_source_kind (app, AS_APP_SOURCE_KIND_INF); rel = as_release_new (); as_release_set_version (rel, fu_rom_get_version (rom), -1); as_release_set_checksum (rel, G_CHECKSUM_SHA1, fu_rom_get_checksum (rom), -1); as_app_add_release (app, rel); as_store_add_app (store, app); } if (!as_store_to_file (store, xml_file, AS_NODE_TO_XML_FLAG_ADD_HEADER | AS_NODE_TO_XML_FLAG_FORMAT_INDENT | AS_NODE_TO_XML_FLAG_FORMAT_MULTILINE, NULL, error)) return FALSE; return TRUE; }
static gboolean gs_plugin_steam_update_store_app (GsPlugin *plugin, AsStore *store, GHashTable *app, GError **error) { const gchar *name; GVariant *tmp; guint32 gameid; gchar *app_id; g_autofree gchar *cache_basename = NULL; g_autofree gchar *cache_fn = NULL; g_autofree gchar *gameid_str = NULL; g_autofree gchar *html = NULL; g_autofree gchar *uri = NULL; g_autoptr(AsApp) item = NULL; /* this is the key */ tmp = g_hash_table_lookup (app, "gameid"); if (tmp == NULL) return TRUE; gameid = g_variant_get_uint32 (tmp); /* valve use the name as the application ID, not the gameid */ tmp = g_hash_table_lookup (app, "name"); if (tmp == NULL) return TRUE; name = g_variant_get_string (tmp, NULL); app_id = g_strdup_printf ("%s.desktop", name); /* already exists */ if (as_store_get_app_by_id (store, app_id) != NULL) { g_debug ("already exists %" G_GUINT32_FORMAT ", skipping", gameid); return TRUE; } /* create application with the gameid as the key */ g_debug ("parsing steam %" G_GUINT32_FORMAT, gameid); item = as_app_new (); as_app_set_kind (item, AS_APP_KIND_DESKTOP); as_app_set_project_license (item, "Steam"); as_app_set_id (item, app_id); as_app_set_name (item, NULL, name); as_app_add_category (item, "Game"); as_app_add_kudo_kind (item, AS_KUDO_KIND_MODERN_TOOLKIT); as_app_set_comment (item, NULL, "Available on Steam"); /* this is for the GNOME Software plugin */ gameid_str = g_strdup_printf ("%" G_GUINT32_FORMAT, gameid); as_app_add_metadata (item, "X-Steam-GameID", gameid_str); as_app_add_metadata (item, "GnomeSoftware::Plugin", "steam"); /* ban certains apps based on the name */ if (g_strstr_len (name, -1, "Dedicated Server") != NULL) as_app_add_veto (item, "Dedicated Server"); /* oslist */ tmp = g_hash_table_lookup (app, "oslist"); if (tmp == NULL) { as_app_add_veto (item, "No operating systems listed"); } else if (g_strstr_len (g_variant_get_string (tmp, NULL), -1, "linux") == NULL) { as_app_add_veto (item, "No Linux support"); } /* url: homepage */ tmp = g_hash_table_lookup (app, "homepage"); if (tmp != NULL) as_app_add_url (item, AS_URL_KIND_HOMEPAGE, g_variant_get_string (tmp, NULL)); /* developer name */ tmp = g_hash_table_lookup (app, "developer"); if (tmp != NULL) as_app_set_developer_name (item, NULL, g_variant_get_string (tmp, NULL)); /* type */ tmp = g_hash_table_lookup (app, "type"); if (tmp != NULL) { const gchar *kind = g_variant_get_string (tmp, NULL); if (g_strcmp0 (kind, "DLC") == 0 || g_strcmp0 (kind, "Config") == 0 || g_strcmp0 (kind, "Tool") == 0) as_app_add_veto (item, "type is %s", kind); } /* don't bother saving apps with failures */ if (as_app_get_vetos(item)->len > 0) return TRUE; /* icons */ tmp = g_hash_table_lookup (app, "clienticns"); if (tmp != NULL) { g_autoptr(GError) error_local = NULL; g_autofree gchar *ic_uri = NULL; ic_uri = g_strdup_printf ("https://steamcdn-a.akamaihd.net/steamcommunity/public/images/apps/%" G_GUINT32_FORMAT "/%s.icns", gameid, g_variant_get_string (tmp, NULL)); if (!gs_plugin_steam_download_icon (plugin, item, ic_uri, &error_local)) { g_warning ("Failed to parse clienticns: %s", error_local->message); } } /* try clienticon */ if (as_app_get_icons(item)->len == 0) { tmp = g_hash_table_lookup (app, "clienticon"); if (tmp != NULL) { g_autoptr(GError) error_local = NULL; g_autofree gchar *ic_uri = NULL; ic_uri = g_strdup_printf ("http://cdn.akamai.steamstatic.com/steamcommunity/public/images/apps/%" G_GUINT32_FORMAT "/%s.ico", gameid, g_variant_get_string (tmp, NULL)); if (!gs_plugin_steam_download_icon (plugin, item, ic_uri, &error_local)) { g_warning ("Failed to parse clienticon: %s", error_local->message); } } } /* fall back to a resized logo */ if (as_app_get_icons(item)->len == 0) { tmp = g_hash_table_lookup (app, "logo"); if (tmp != NULL) { AsIcon *icon = NULL; g_autofree gchar *ic_uri = NULL; ic_uri = g_strdup_printf ("http://cdn.akamai.steamstatic.com/steamcommunity/public/images/apps/%" G_GUINT32_FORMAT "/%s.jpg", gameid, g_variant_get_string (tmp, NULL)); icon = as_icon_new (); as_icon_set_kind (icon, AS_ICON_KIND_REMOTE); as_icon_set_url (icon, ic_uri); as_app_add_icon (item, icon); } } /* size */ tmp = g_hash_table_lookup (app, "maxsize"); if (tmp != NULL) { /* string when over 16Gb... :/ */ if (g_strcmp0 (g_variant_get_type_string (tmp), "u") == 0) { g_autofree gchar *val = NULL; val = g_strdup_printf ("%" G_GUINT32_FORMAT, g_variant_get_uint32 (tmp)); as_app_add_metadata (item, "X-Steam-Size", val); } else { as_app_add_metadata (item, "X-Steam-Size", g_variant_get_string (tmp, NULL)); } } /* download page from the store */ cache_basename = g_strdup_printf ("%s.html", gameid_str); cache_fn = gs_utils_get_cache_filename ("steam", cache_basename, GS_UTILS_CACHE_FLAG_WRITEABLE, error); if (cache_fn == NULL) return FALSE; if (!g_file_test (cache_fn, G_FILE_TEST_EXISTS)) { g_autoptr(GsApp) app_dl = gs_app_new (gs_plugin_get_name (plugin)); uri = g_strdup_printf ("http://store.steampowered.com/app/%s/", gameid_str); if (!gs_plugin_download_file (plugin, app_dl, uri, cache_fn, NULL, /* GCancellable */ error)) return FALSE; } /* get screenshots and descriptions */ if (!g_file_get_contents (cache_fn, &html, NULL, error)) { gs_utils_error_convert_gio (error); return FALSE; } if (!gs_plugin_steam_update_screenshots (item, html, error)) return FALSE; if (!gs_plugin_steam_update_description (item, html, error)) return FALSE; /* add */ as_store_add_app (store, item); 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; }