Esempio n. 1
0
static gboolean
gs_plugin_fedora_distro_upgrades_refresh (GsPlugin *plugin,
					  guint cache_age,
					  GCancellable *cancellable,
					  GError **error)
{
	GsPluginData *priv = gs_plugin_get_data (plugin);
	/* check cache age */
	if (cache_age > 0) {
		guint tmp;
		g_autoptr(GFile) file = g_file_new_for_path (priv->cachefn);
		tmp = gs_utils_get_file_age (file);
		if (tmp < cache_age) {
			g_debug ("%s is only %u seconds old",
				 priv->cachefn, tmp);
			return TRUE;
		}
	}

	/* download new file */
	if (!gs_plugin_download_file (plugin, NULL,
				      FEDORA_PKGDB_COLLECTIONS_API_URI,
				      priv->cachefn,
				      cancellable,
				      error)) {
		gs_utils_error_add_unique_id (error, priv->cached_origin);
		return FALSE;
	}

	/* success */
	return TRUE;
}
Esempio n. 2
0
static gboolean
gs_plugin_fwupd_install (GsPlugin *plugin,
			 GsApp *app,
			 GCancellable *cancellable,
			 GError **error)
{
	GsPluginData *priv = gs_plugin_get_data (plugin);
	const gchar *device_id;
	FwupdInstallFlags install_flags = 0;
	GFile *local_file;
	g_autofree gchar *filename = NULL;

	/* not set */
	local_file = gs_app_get_local_file (app);
	if (local_file == NULL) {
		g_set_error (error,
			     GS_PLUGIN_ERROR,
			     GS_PLUGIN_ERROR_FAILED,
			     "not enough data for fwupd %s",
			     filename);
		return FALSE;
	}

	/* file does not yet exist */
	filename = g_file_get_path (local_file);
	if (!g_file_query_exists (local_file, cancellable)) {
		const gchar *uri = gs_fwupd_app_get_update_uri (app);
		gs_app_set_state (app, AS_APP_STATE_INSTALLING);
		if (!gs_plugin_download_file (plugin, app, uri, filename,
					      cancellable, error))
			return FALSE;
	}

	/* limit to single device? */
	device_id = gs_fwupd_app_get_device_id (app);
	if (device_id == NULL)
		device_id = FWUPD_DEVICE_ID_ANY;

	/* set the last object */
	g_set_object (&priv->app_current, app);

	/* only offline supported */
	if (gs_app_get_metadata_item (app, "fwupd::OnlyOffline") != NULL)
		install_flags |= FWUPD_INSTALL_FLAG_OFFLINE;

	gs_app_set_state (app, AS_APP_STATE_INSTALLING);
	if (!fwupd_client_install (priv->client, device_id,
				   filename, install_flags,
				   cancellable, error)) {
		gs_plugin_fwupd_error_convert (error);
		gs_app_set_state_recover (app);
		return FALSE;
	}

	/* delete the file from the cache */
	gs_app_set_state (app, AS_APP_STATE_INSTALLED);
	return g_file_delete (local_file, cancellable, error);
}
Esempio n. 3
0
static gboolean
gs_plugin_odrs_refresh_ratings (GsPlugin *plugin,
				guint cache_age,
				GCancellable *cancellable,
				GError **error)
{
	GsPluginData *priv = gs_plugin_get_data (plugin);
	g_autofree gchar *fn = NULL;
	g_autofree gchar *uri = NULL;
	g_autoptr(GsApp) app_dl = gs_app_new (gs_plugin_get_name (plugin));

	/* check cache age */
	fn = gs_utils_get_cache_filename ("ratings",
					  "odrs.json",
					  GS_UTILS_CACHE_FLAG_WRITEABLE,
					  error);
	if (fn == NULL)
		return FALSE;
	if (cache_age > 0) {
		guint tmp;
		g_autoptr(GFile) file = NULL;
		file = g_file_new_for_path (fn);
		tmp = gs_utils_get_file_age (file);
		if (tmp < cache_age) {
			g_debug ("%s is only %u seconds old, so ignoring refresh",
				 fn, tmp);
			return gs_plugin_odrs_load_ratings (plugin, fn, error);
		}
	}

	/* download the complete file */
	uri = g_strdup_printf ("%s/ratings", priv->review_server);
	if (!gs_plugin_download_file (plugin, app_dl, uri, fn, cancellable, error)) {
		gs_utils_error_add_unique_id (error, priv->cached_origin);
		return FALSE;
	}
	return gs_plugin_odrs_load_ratings (plugin, fn, error);
}
Esempio n. 4
0
gboolean
gs_plugin_download_app (GsPlugin *plugin,
			GsApp *app,
			GCancellable *cancellable,
			GError **error)
{
	GFile *local_file;
	g_autofree gchar *filename = NULL;

	/* only process this app if was created by this plugin */
	if (g_strcmp0 (gs_app_get_management_plugin (app),
		       gs_plugin_get_name (plugin)) != 0)
		return TRUE;

	/* not set */
	local_file = gs_app_get_local_file (app);
	if (local_file == NULL) {
		g_set_error (error,
			     GS_PLUGIN_ERROR,
			     GS_PLUGIN_ERROR_FAILED,
			     "not enough data for fwupd %s",
			     filename);
		return FALSE;
	}

	/* file does not yet exist */
	filename = g_file_get_path (local_file);
	if (!g_file_query_exists (local_file, cancellable)) {
		const gchar *uri = gs_fwupd_app_get_update_uri (app);
		if (!gs_plugin_download_file (plugin, app, uri, filename,
					      cancellable, error))
			return FALSE;
	}
	gs_app_set_size_download (app, 0);
	return TRUE;
}
Esempio n. 5
0
static gboolean
gs_plugin_fwupd_refresh_remote (GsPlugin *plugin,
				FwupdRemote *remote,
				guint cache_age,
				GCancellable *cancellable,
				GError **error)
{
	GsPluginData *priv = gs_plugin_get_data (plugin);
	GChecksumType checksum_kind;
	const gchar *url_sig = NULL;
	const gchar *url = NULL;
	g_autoptr(GError) error_local = NULL;
	g_autofree gchar *basename = NULL;
	g_autofree gchar *basename_sig = NULL;
	g_autofree gchar *cache_id = NULL;
	g_autofree gchar *checksum = NULL;
	g_autofree gchar *filename = NULL;
	g_autofree gchar *filename_sig = NULL;
	g_autoptr(GBytes) data = NULL;
	g_autoptr(GsApp) app_dl = gs_app_new (gs_plugin_get_name (plugin));

	/* sanity check */
	if (fwupd_remote_get_filename_cache_sig (remote) == NULL) {
		g_set_error (error,
			     GS_PLUGIN_ERROR,
			     GS_PLUGIN_ERROR_FAILED,
			     "remote %s has no cache signature",
			     fwupd_remote_get_id (remote));
		return FALSE;
	}

	/* check cache age */
	if (cache_age > 0) {
		guint64 age = fwupd_remote_get_age (remote);
		guint tmp = age < G_MAXUINT ? (guint) age : G_MAXUINT;
		if (tmp < cache_age) {
			g_debug ("%s is only %u seconds old, so ignoring refresh",
				 filename_sig, tmp);
			return TRUE;
		}
	}

	/* download the signature first, it's smaller */
	cache_id = g_strdup_printf ("fwupd/remotes.d/%s", fwupd_remote_get_id (remote));
	basename_sig = g_path_get_basename (fwupd_remote_get_filename_cache_sig (remote));
	filename_sig = gs_utils_get_cache_filename (cache_id, basename_sig,
						    GS_UTILS_CACHE_FLAG_WRITEABLE,
						    error);

	/* download the signature first, it's smaller */
	url_sig = fwupd_remote_get_metadata_uri_sig (remote);
	gs_app_set_summary_missing (app_dl,
				    /* TRANSLATORS: status text when downloading */
				    _("Downloading firmware update signature…"));
	data = gs_plugin_download_data (plugin, app_dl, url_sig, cancellable, error);
	if (data == NULL) {
		gs_utils_error_add_origin_id (error, priv->cached_origin);
		return FALSE;
	}

	/* is the signature hash the same as we had before? */
	checksum_kind = fwupd_checksum_guess_kind (fwupd_remote_get_checksum (remote));
	checksum = g_compute_checksum_for_data (checksum_kind,
						(const guchar *) g_bytes_get_data (data, NULL),
						g_bytes_get_size (data));
	if (g_strcmp0 (checksum, fwupd_remote_get_checksum (remote)) == 0) {
		g_debug ("signature of %s is unchanged", url_sig);
		return TRUE;
	}

	/* save to a file */
	g_debug ("saving new remote signature to %s:", filename_sig);
	if (!g_file_set_contents (filename_sig,
				  g_bytes_get_data (data, NULL),
				  (guint) g_bytes_get_size (data),
				  &error_local)) {
		g_set_error (error,
			     GS_PLUGIN_ERROR,
			     GS_PLUGIN_ERROR_WRITE_FAILED,
			     "Failed to save firmware signature: %s",
			     error_local->message);
		return FALSE;
	}

	/* download the payload and save to file */
	basename = g_path_get_basename (fwupd_remote_get_filename_cache (remote));
	filename = gs_utils_get_cache_filename (cache_id, basename,
						GS_UTILS_CACHE_FLAG_WRITEABLE,
						error);
	if (filename == NULL)
		return FALSE;
	g_debug ("saving new firmware metadata to %s:", filename);
	gs_app_set_summary_missing (app_dl,
				    /* TRANSLATORS: status text when downloading */
				    _("Downloading firmware update metadata…"));
	url = fwupd_remote_get_metadata_uri (remote);
	if (!gs_plugin_download_file (plugin, app_dl, url, filename,
				      cancellable, error)) {
		gs_utils_error_add_origin_id (error, priv->cached_origin);
		return FALSE;
	}

	/* phew, lets send all this to fwupd */
	if (!fwupd_client_update_metadata (priv->client,
					   fwupd_remote_get_id (remote),
					   filename,
					   filename_sig,
					   cancellable,
					   error)) {
		gs_plugin_fwupd_error_convert (error);
		return FALSE;
	}
	return TRUE;
}
Esempio n. 6
0
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;
}
Esempio n. 7
0
static gboolean
gs_plugin_steam_download_icon (GsPlugin *plugin,
			       AsApp *app,
			       const gchar *uri,
			       GError **error)
{
	gsize data_len;
	g_autofree gchar *cache_basename = NULL;
	g_autofree gchar *cache_fn = NULL;
	g_autofree gchar *cache_png = NULL;
	g_autofree gchar *data = NULL;
	g_autoptr(AsIcon) icon = NULL;
	g_autoptr(GdkPixbuf) pb = NULL;

	/* download icons from the cdn */
	cache_basename = g_path_get_basename (uri);
	cache_fn = gs_utils_get_cache_filename ("steam",
						cache_basename,
						GS_UTILS_CACHE_FLAG_NONE,
						error);
	if (cache_fn == NULL)
		return FALSE;
	if (g_file_test (cache_fn, G_FILE_TEST_EXISTS)) {
		if (!g_file_get_contents (cache_fn, &data, &data_len, error)) {
			gs_utils_error_convert_gio (error);
			return FALSE;
		}
	} else {
		if (!gs_mkdir_parent (cache_fn, error))
			return FALSE;
		if (!gs_plugin_download_file (plugin,
					      NULL, /* GsApp */
					      uri,
					      cache_fn,
					      NULL, /* GCancellable */
					      error))
			return FALSE;
	}

	/* load the icon as large as possible */
	pb = gdk_pixbuf_new_from_file (cache_fn, error);
	if (pb == NULL) {
		gs_utils_error_convert_gdk_pixbuf (error);
		return FALSE;
	}

	/* too small? */
	if (gdk_pixbuf_get_width (pb) < 48 ||
	    gdk_pixbuf_get_height (pb) < 48) {
		g_set_error (error,
			     GS_PLUGIN_ERROR,
			     GS_PLUGIN_ERROR_INVALID_FORMAT,
			     "icon is too small %ix%i",
			     gdk_pixbuf_get_width (pb),
			     gdk_pixbuf_get_height (pb));
		return FALSE;
	}

	/* save to cache */
	memcpy (cache_basename + 40, ".png\0", 5);
	cache_png = gs_utils_get_cache_filename ("steam",
						 cache_basename,
						 GS_UTILS_CACHE_FLAG_WRITEABLE,
						 error);
	if (cache_png == NULL)
		return FALSE;
	if (!gdk_pixbuf_save (pb, cache_png, "png", error, NULL)) {
		gs_utils_error_convert_gdk_pixbuf (error);
		return FALSE;
	}

	/* add an icon */
	icon = as_icon_new ();
	as_icon_set_kind (icon, AS_ICON_KIND_LOCAL);
	as_icon_set_filename (icon, cache_png);
	as_app_add_icon (app, icon);
	return TRUE;
}