/**
 * asb_plugin_merge:
 */
void
asb_plugin_merge (AsbPlugin *plugin, GList *list)
{
    AsApp *app;
    AsApp *found;
    GList *l;
    const gchar *tmp;
    _cleanup_hashtable_unref_ GHashTable *hash = NULL;

    /* add X-Merge-With-Parent on any metainfo files that are in a package
     * required by a desktop package */
    asb_plugin_merge_prepare_deps (list);

    /* add all packages to the hash */
    hash = g_hash_table_new_full (g_str_hash, g_str_equal,
                                  g_free, (GDestroyNotify) g_object_unref);
    for (l = list; l != NULL; l = l->next) {
        app = AS_APP (l->data);
        g_hash_table_insert (hash,
                             g_strdup (as_app_get_id (app)),
                             g_object_ref (app));
    }

    /* absorb some apps into their parent */
    for (l = list; l != NULL; l = l->next) {
        app = AS_APP (l->data);

        /* no absorb metadata */
        tmp = as_app_get_metadata_item (app, "X-Merge-With-Parent");
        if (tmp == NULL)
            continue;

        /* find the parent app */
        found = g_hash_table_lookup (hash, tmp);
        if (found == NULL) {
            as_app_add_veto (app, "No referenced '%s'", tmp);
            continue;
        }

        /* partially absorb */
        as_app_add_veto (app, "partially absorbing %s into %s",
                         as_app_get_id (app), as_app_get_id (found));
        as_app_subsume_full (found, app, AS_APP_SUBSUME_FLAG_PARTIAL);
    }
}
Exemple #2
0
/**
 * asb_context_detect_missing_data:
 **/
static gboolean
asb_context_detect_missing_data (AsbContext *ctx, GError **error)
{
	AsApp *app;
	AsbContextPrivate *priv = GET_PRIVATE (ctx);
	GList *l;

	/* look for the thing that an addon extends */
	for (l = priv->apps; l != NULL; l = l->next) {
		app = AS_APP (l->data);
		if (as_app_get_name (AS_APP (app), "C") == NULL)
			as_app_add_veto (AS_APP (app), "No <name> in AppData");
		if (as_app_get_comment (AS_APP (app), "C") == NULL)
			as_app_add_veto (AS_APP (app), "No <summary> in AppData");
		if (as_app_get_id_kind (AS_APP (app)) != AS_ID_KIND_ADDON) {
			if (as_app_get_icon_default (AS_APP (app)) == NULL)
				as_app_add_veto (AS_APP (app), "Has no Icon");
		}
	}
	return TRUE;
}
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;
}
Exemple #4
0
/**
 * asb_context_detect_missing_parents:
 **/
static gboolean
asb_context_detect_missing_parents (AsbContext *ctx, GError **error)
{
	AsApp *app;
	AsApp *found;
	AsbContextPrivate *priv = GET_PRIVATE (ctx);
	GList *l;
	const gchar *tmp;
	g_autoptr(GHashTable) hash = NULL;

	/* add all desktop apps to the hash */
	hash = g_hash_table_new (g_str_hash, g_str_equal);
	for (l = priv->apps; l != NULL; l = l->next) {
		app = AS_APP (l->data);
		if (!ASB_IS_APP (app))
			continue;
		if (as_app_get_pkgname_default (app) == NULL)
			continue;
		if (as_app_get_id_kind (app) != AS_ID_KIND_DESKTOP)
			continue;
		g_hash_table_insert (hash,
				     (gpointer) as_app_get_id (app),
				     app);
	}

	/* look for the thing that an addon extends */
	for (l = priv->apps; l != NULL; l = l->next) {
		app = AS_APP (l->data);
		if (!ASB_IS_APP (app))
			continue;
		if (as_app_get_pkgname_default (app) == NULL)
			continue;
		if (as_app_get_id_kind (app) != AS_ID_KIND_ADDON)
			continue;
		if (as_app_get_extends(app)->len == 0)
			continue;
		tmp = g_ptr_array_index (as_app_get_extends(app), 0);
		found = g_hash_table_lookup (hash, tmp);
		if (found != NULL)
			continue;
		found = as_store_get_app_by_id (priv->store_old, tmp);
		if (found != NULL)
			continue;

		/* do not add the addon */
		as_app_add_veto (app, "%s has no parent of '%s'",
				 as_app_get_id (app), tmp);
		g_print ("WARNING: %s has no parent of '%s'\n",
			 as_app_get_id (app), tmp);
	}
	return TRUE;
}
/**
 * asb_plugin_merge:
 */
void
asb_plugin_merge (AsbPlugin *plugin, GList *list)
{
	AsApp *app;
	AsApp *found;
	GList *l;
	_cleanup_hashtable_unref_ GHashTable *hash = NULL;

	/* make a hash table of ID->AsApp */
	hash = g_hash_table_new_full (g_str_hash, g_str_equal,
				      g_free, (GDestroyNotify) g_object_unref);
	for (l = list; l != NULL; l = l->next) {
		app = AS_APP (l->data);
		if (as_app_get_id_kind (app) != AS_ID_KIND_DESKTOP)
			continue;
		g_hash_table_insert (hash,
				     g_strdup (as_app_get_id (app)),
				     g_object_ref (app));
	}

	/* add addons where the pkgname is different from the
	 * main package */
	for (l = list; l != NULL; l = l->next) {
		if (!ASB_IS_APP (l->data))
			continue;
		app = AS_APP (l->data);
		if (as_app_get_id_kind (app) != AS_ID_KIND_ADDON)
			continue;
		found = g_hash_table_lookup (hash, as_app_get_id (app));
		if (found == NULL)
			continue;
		if (g_strcmp0 (as_app_get_pkgname_default (app),
			       as_app_get_pkgname_default (found)) != 0)
			continue;
		as_app_add_veto (app,
				 "absorbing addon %s shipped in "
				 "main package %s",
				 as_app_get_id (app),
				 as_app_get_pkgname_default (app));
		as_app_subsume_full (found, app, AS_APP_SUBSUME_FLAG_PARTIAL);
	}
}
/**
 * as_app_parse_desktop_file:
 **/
gboolean
as_app_parse_desktop_file (AsApp *app,
			   const gchar *desktop_file,
			   AsAppParseFlags flags,
			   GError **error)
{
	GKeyFileFlags kf_flags = G_KEY_FILE_KEEP_TRANSLATIONS;
	gchar *tmp;
	guint i;
	g_autoptr(GError) error_local = NULL;
	g_autofree gchar *app_id = NULL;
	g_autoptr(GKeyFile) kf = NULL;
	g_auto(GStrv) keys = NULL;

	/* load file */
	kf = g_key_file_new ();
	if (flags & AS_APP_PARSE_FLAG_KEEP_COMMENTS)
		kf_flags |= G_KEY_FILE_KEEP_COMMENTS;
	if (!g_key_file_load_from_file (kf, desktop_file, kf_flags, &error_local)) {
		g_set_error (error,
			     AS_APP_ERROR,
			     AS_APP_ERROR_INVALID_TYPE,
			     "Failed to parse %s: %s",
			     desktop_file, error_local->message);
		return FALSE;
	}

	/* create app */
	app_id = g_path_get_basename (desktop_file);
	as_app_set_id_kind (app, AS_ID_KIND_DESKTOP);

	/* is blacklisted */
	if (as_utils_is_blacklisted_id (app_id))
		as_app_add_veto (app, "%s is not an application", app_id);

	/* Ubuntu helpfully put the package name in the desktop file name */
	tmp = g_strstr_len (app_id, -1, ":");
	if (tmp != NULL)
		as_app_set_id (app, tmp + 1);
	else
		as_app_set_id (app, app_id);

	/* look at all the keys */
	keys = g_key_file_get_keys (kf, G_KEY_FILE_DESKTOP_GROUP, NULL, error);
	if (keys == NULL)
		return FALSE;
	for (i = 0; keys[i] != NULL; i++) {
		if (!as_app_parse_file_key (app, kf, keys[i], flags, error))
			return FALSE;
		if ((flags & AS_APP_PARSE_FLAG_USE_HEURISTICS) > 0) {
			if (!as_app_infer_file_key (app, kf, keys[i], error))
				return FALSE;
		}
	}

	/* perform any fallbacks */
	if ((flags & AS_APP_PARSE_FLAG_USE_FALLBACKS) > 0 &&
	    as_app_get_comment_size (app) == 0) {
		for (i = 0; keys[i] != NULL; i++) {
			if (!as_app_parse_file_key_fallback_comment (app,
								     kf,
								     keys[i],
								     error))
				return FALSE;
		}
	}

	/* all applications require icons */
	if (as_app_get_icons(app)->len == 0)
		as_app_add_veto (app, "%s has no icon", app_id);

	return TRUE;
}
/**
 * as_app_parse_file_key:
 **/
static gboolean
as_app_parse_file_key (AsApp *app,
		       GKeyFile *kf,
		       const gchar *key,
		       AsAppParseFlags flags,
		       GError **error)
{
	gchar *dot = NULL;
	guint i;
	guint j;
	g_autofree gchar *locale = NULL;
	g_autofree gchar *tmp = NULL;
	g_auto(GStrv) list = NULL;

	/* NoDisplay */
	if (g_strcmp0 (key, G_KEY_FILE_DESKTOP_KEY_NO_DISPLAY) == 0) {
		tmp = g_key_file_get_string (kf,
					     G_KEY_FILE_DESKTOP_GROUP,
					     key,
					     NULL);
		if (tmp != NULL && strcasecmp (tmp, "True") == 0)
			as_app_add_veto (app, "NoDisplay=true");

	/* Type */
	} else if (g_strcmp0 (key, G_KEY_FILE_DESKTOP_KEY_TYPE) == 0) {
		tmp = g_key_file_get_string (kf,
					     G_KEY_FILE_DESKTOP_GROUP,
					     key,
					     NULL);
		if (g_strcmp0 (tmp, G_KEY_FILE_DESKTOP_TYPE_APPLICATION) != 0) {
			g_set_error_literal (error,
					     AS_APP_ERROR,
					     AS_APP_ERROR_INVALID_TYPE,
					     "not an application");
			return FALSE;
		}

	/* Icon */
	} else if (g_strcmp0 (key, G_KEY_FILE_DESKTOP_KEY_ICON) == 0) {
		tmp = g_key_file_get_string (kf,
					     G_KEY_FILE_DESKTOP_GROUP,
					     key,
					     NULL);
		if (tmp != NULL && tmp[0] != '\0') {
			g_autoptr(AsIcon) icon = NULL;
			icon = as_icon_new ();
			as_icon_set_name (icon, tmp);
			dot = g_strstr_len (tmp, -1, ".");
			if (dot != NULL)
				*dot = '\0';
			if (as_utils_is_stock_icon_name (tmp)) {
				as_icon_set_name (icon, tmp);
				as_icon_set_kind (icon, AS_ICON_KIND_STOCK);
			} else if ((flags & AS_APP_PARSE_FLAG_USE_FALLBACKS) > 0 &&
				   _as_utils_is_stock_icon_name_fallback (tmp)) {
				as_icon_set_name (icon, tmp);
				as_icon_set_kind (icon, AS_ICON_KIND_STOCK);
			} else {
				as_icon_set_kind (icon, AS_ICON_KIND_LOCAL);
			}
			as_app_add_icon (app, icon);
		}

	/* Categories */
	} else if (g_strcmp0 (key, G_KEY_FILE_DESKTOP_KEY_CATEGORIES) == 0) {
		list = g_key_file_get_string_list (kf,
						   G_KEY_FILE_DESKTOP_GROUP,
						   key,
						   NULL, NULL);
		for (i = 0; list[i] != NULL; i++) {

			/* not a standard category */
			if (g_str_has_prefix (list[i], "X-"))
				continue;

			/* check the category is valid */
			if (!as_utils_is_category_id (list[i]))
				continue;

			/* ignore some useless keys */
			if (g_strcmp0 (list[i], "GTK") == 0)
				continue;
			if (g_strcmp0 (list[i], "Qt") == 0)
				continue;
			if (g_strcmp0 (list[i], "KDE") == 0)
				continue;
			if (g_strcmp0 (list[i], "GNOME") == 0)
				continue;
			as_app_add_category (app, list[i]);
		}

	} else if (g_strcmp0 (key, "Keywords") == 0) {
		list = g_key_file_get_string_list (kf,
						   G_KEY_FILE_DESKTOP_GROUP,
						   key,
						   NULL, NULL);
		for (i = 0; list[i] != NULL; i++) {
			g_auto(GStrv) kw_split = NULL;
			kw_split = g_strsplit (list[i], ",", -1);
			for (j = 0; kw_split[j] != NULL; j++) {
				if (kw_split[j][0] == '\0')
					continue;
				as_app_add_keyword (app, "C", kw_split[j]);
			}
		}

	} else if (g_str_has_prefix (key, "Keywords")) {
		locale = as_app_desktop_key_get_locale (key);
		list = g_key_file_get_locale_string_list (kf,
							  G_KEY_FILE_DESKTOP_GROUP,
							  key,
							  locale,
							  NULL, NULL);
		for (i = 0; list[i] != NULL; i++) {
			g_auto(GStrv) kw_split = NULL;
			kw_split = g_strsplit (list[i], ",", -1);
			for (j = 0; kw_split[j] != NULL; j++) {
				if (kw_split[j][0] == '\0')
					continue;
				as_app_add_keyword (app, locale, kw_split[j]);
			}
		}

	} else if (g_strcmp0 (key, "MimeType") == 0) {
		list = g_key_file_get_string_list (kf,
						   G_KEY_FILE_DESKTOP_GROUP,
						   key,
						   NULL, NULL);
		for (i = 0; list[i] != NULL; i++)
			as_app_add_mimetype (app, list[i]);

	} else if (g_strcmp0 (key, "X-AppInstall-Package") == 0) {
		tmp = g_key_file_get_string (kf,
					     G_KEY_FILE_DESKTOP_GROUP,
					     key,
					     NULL);
		if (tmp != NULL && tmp[0] != '\0')
			as_app_add_pkgname (app, tmp);

	/* OnlyShowIn */
	} else if (g_strcmp0 (key, G_KEY_FILE_DESKTOP_KEY_ONLY_SHOW_IN) == 0) {
		/* if an app has only one entry, it's that desktop */
		list = g_key_file_get_string_list (kf,
						   G_KEY_FILE_DESKTOP_GROUP,
						   key,
						   NULL, NULL);
		if (g_strv_length (list) == 1)
			as_app_set_project_group (app, list[0]);

	/* Name */
	} else if (g_strcmp0 (key, G_KEY_FILE_DESKTOP_KEY_NAME) == 0 ||
	           g_strcmp0 (key, "_Name") == 0) {
		tmp = g_key_file_get_string (kf,
					     G_KEY_FILE_DESKTOP_GROUP,
					     key,
					     NULL);
		if (tmp != NULL && tmp[0] != '\0')
			as_app_set_name (app, "C", tmp);

	/* Name[] */
	} else if (g_str_has_prefix (key, G_KEY_FILE_DESKTOP_KEY_NAME)) {
		locale = as_app_desktop_key_get_locale (key);
		tmp = g_key_file_get_locale_string (kf,
						    G_KEY_FILE_DESKTOP_GROUP,
						    G_KEY_FILE_DESKTOP_KEY_NAME,
						    locale,
						    NULL);
		if (tmp != NULL && tmp[0] != '\0')
			as_app_set_name (app, locale, tmp);

	/* Comment */
	} else if (g_strcmp0 (key, G_KEY_FILE_DESKTOP_KEY_COMMENT) == 0 ||
	           g_strcmp0 (key, "_Comment") == 0) {
		tmp = g_key_file_get_string (kf,
					     G_KEY_FILE_DESKTOP_GROUP,
					     key,
					     NULL);
		if (tmp != NULL && tmp[0] != '\0')
			as_app_set_comment (app, "C", tmp);

	/* Comment[] */
	} else if (g_str_has_prefix (key, G_KEY_FILE_DESKTOP_KEY_COMMENT)) {
		locale = as_app_desktop_key_get_locale (key);
		tmp = g_key_file_get_locale_string (kf,
						    G_KEY_FILE_DESKTOP_GROUP,
						    G_KEY_FILE_DESKTOP_KEY_COMMENT,
						    locale,
						    NULL);
		if (tmp != NULL && tmp[0] != '\0')
			as_app_set_comment (app, locale, tmp);

	/* non-standard */
	} else if (g_strcmp0 (key, "X-Ubuntu-Software-Center-Name") == 0) {
		tmp = g_key_file_get_string (kf,
					     G_KEY_FILE_DESKTOP_GROUP,
					     key,
					     NULL);
		if (tmp != NULL && tmp[0] != '\0')
			as_app_set_name (app, "C", tmp);
	} else if (g_str_has_prefix (key, "X-Ubuntu-Software-Center-Name")) {
		locale = as_app_desktop_key_get_locale (key);
		tmp = g_key_file_get_locale_string (kf,
						    G_KEY_FILE_DESKTOP_GROUP,
						    "X-Ubuntu-Software-Center-Name",
						    locale,
						    NULL);
		if (tmp != NULL && tmp[0] != '\0')
			as_app_set_name (app, locale, tmp);
	}

	return TRUE;
}
/**
 * asb_plugin_loader_merge:
 * @plugin_loader: A #AsbPluginLoader
 * @apps: (element-type AsbApp): a list of applications that need merging
 *
 * Merge the list of applications using the plugins.
 *
 * Since: 0.2.5
 **/
void
asb_plugin_loader_merge (AsbPluginLoader *plugin_loader, GList *apps)
{
	AsbApp *app;
	AsbApp *found;
	AsbPluginLoaderPrivate *priv = GET_PRIVATE (plugin_loader);
	AsbPluginMergeFunc plugin_func = NULL;
	AsbPlugin *plugin;
	GList *l;
	const gchar *key;
	const gchar *tmp;
	gboolean ret;
	guint i;
	g_autoptr(GHashTable) hash = NULL;

	/* run each plugin */
	for (i = 0; i < priv->plugins->len; i++) {
		plugin = g_ptr_array_index (priv->plugins, i);
		ret = g_module_symbol (plugin->module,
				       "asb_plugin_merge",
				       (gpointer *) &plugin_func);
		if (!ret)
			continue;
		plugin_func (plugin, apps);
	}

	/* FIXME: move to font plugin */
	for (l = apps; l != NULL; l = l->next) {
		if (!ASB_IS_APP (l->data))
			continue;
		app = ASB_APP (l->data);
		as_app_remove_metadata (AS_APP (app), "FontFamily");
		as_app_remove_metadata (AS_APP (app), "FontFullName");
		as_app_remove_metadata (AS_APP (app), "FontIconText");
		as_app_remove_metadata (AS_APP (app), "FontParent");
		as_app_remove_metadata (AS_APP (app), "FontSampleText");
		as_app_remove_metadata (AS_APP (app), "FontSubFamily");
		as_app_remove_metadata (AS_APP (app), "FontClassifier");
	}

	/* deduplicate */
	hash = g_hash_table_new (g_str_hash, g_str_equal);
	for (l = apps; l != NULL; l = l->next) {
		if (!ASB_IS_APP (l->data))
			continue;
		app = ASB_APP (l->data);
		if (as_app_get_vetos(AS_APP(app))->len > 0)
			continue;
		key = as_app_get_id (AS_APP (app));
		found = g_hash_table_lookup (hash, key);
		if (found == NULL) {
			g_hash_table_insert (hash,
					     (gpointer) key,
					     (gpointer) app);
			continue;
		}
		if (as_app_get_kind (AS_APP (app)) == AS_APP_KIND_FIRMWARE) {
			as_app_subsume_full (AS_APP (found), AS_APP (app),
					     AS_APP_SUBSUME_FLAG_MERGE);
		}
		tmp = asb_package_get_nevr (asb_app_get_package (found));
		as_app_add_veto (AS_APP (app), "duplicate of %s", tmp);
		asb_package_log (asb_app_get_package (app),
				 ASB_PACKAGE_LOG_LEVEL_WARNING,
				 "duplicate %s not included as added from %s",
				 key, tmp);
	}
}
/**
 * asb_plugin_process_app:
 */
gboolean
asb_plugin_process_app (AsbPlugin *plugin,
			AsbPackage *pkg,
			AsbApp *app,
			const gchar *tmpdir,
			GError **error)
{
	const gchar *tmp;
	AsRelease *release;
	gchar **deps;
	gchar **filelist;
	GPtrArray *releases;
	guint i;
	gint64 secs;
	guint days;

	/* add extra categories */
	tmp = as_app_get_id (AS_APP (app));
	if (g_strcmp0 (tmp, "0install.desktop") == 0)
		as_app_add_category (AS_APP (app), "System", -1);
	if (g_strcmp0 (tmp, "alacarte.desktop") == 0)
		as_app_add_category (AS_APP (app), "System", -1);
	if (g_strcmp0 (tmp, "deja-dup.desktop") == 0)
		as_app_add_category (AS_APP (app), "Utility", -1);
	if (g_strcmp0 (tmp, "gddccontrol.desktop") == 0)
		as_app_add_category (AS_APP (app), "System", -1);
	if (g_strcmp0 (tmp, "nautilus.desktop") == 0)
		as_app_add_category (AS_APP (app), "System", -1);
	if (g_strcmp0 (tmp, "pessulus.desktop") == 0)
		as_app_add_category (AS_APP (app), "System", -1);
	if (g_strcmp0 (tmp, "pmdefaults.desktop") == 0)
		as_app_add_category (AS_APP (app), "System", -1);
	if (g_strcmp0 (tmp, "fwfstab.desktop") == 0)
		as_app_add_category (AS_APP (app), "System", -1);
	if (g_strcmp0 (tmp, "bmpanel2cfg.desktop") == 0)
		as_app_add_category (AS_APP (app), "System", -1);

	/* add extra project groups */
	if (g_strcmp0 (tmp, "nemo.desktop") == 0)
		as_app_set_project_group (AS_APP (app), "Cinnamon", -1);
	if (g_strcmp0 (tmp, "xfdashboard.desktop") == 0)
		as_app_set_project_group (AS_APP (app), "XFCE", -1);

	/* use the URL to guess the project group */
	tmp = asb_package_get_url (pkg);
	if (as_app_get_project_group (AS_APP (app)) == NULL && tmp != NULL) {
		tmp = asb_glob_value_search (plugin->priv->project_groups, tmp);
		if (tmp != NULL)
			as_app_set_project_group (AS_APP (app), tmp, -1);
	}

	/* use summary to guess the project group */
	tmp = as_app_get_comment (AS_APP (app), NULL);
	if (tmp != NULL && g_strstr_len (tmp, -1, "for KDE") != NULL)
		as_app_set_project_group (AS_APP (app), "KDE", -1);

	/* look for any installed docs */
	filelist = asb_package_get_filelist (pkg);
	for (i = 0; filelist[i] != NULL; i++) {
		if (g_str_has_prefix (filelist[i],
				      "/usr/share/help/")) {
			as_app_add_kudo_kind (AS_APP (app),
					      AS_KUDO_KIND_USER_DOCS);
			break;
		}
	}

	/* look for a shell search provider */
	for (i = 0; filelist[i] != NULL; i++) {
		if (g_str_has_prefix (filelist[i],
				      "/usr/share/gnome-shell/search-providers/")) {
			as_app_add_kudo_kind (AS_APP (app),
					      AS_KUDO_KIND_SEARCH_PROVIDER);
			break;
		}
	}

	/* look for a high contrast icon */
	for (i = 0; filelist[i] != NULL; i++) {
		if (g_str_has_prefix (filelist[i],
				      "/usr/share/icons/HighContrast/")) {
			as_app_add_kudo_kind (AS_APP (app),
					      AS_KUDO_KIND_HIGH_CONTRAST);
			break;
		}
	}

	/* look for a modern toolkit */
	deps = asb_package_get_deps (pkg);
	for (i = 0; deps != NULL && deps[i] != NULL; i++) {
		if (g_strcmp0 (deps[i], "libgtk-3.so.0") == 0 ||
		    g_strcmp0 (deps[i], "libQt5Core.so.5") == 0) {
			as_app_add_kudo_kind (AS_APP (app),
					      AS_KUDO_KIND_MODERN_TOOLKIT);
			break;
		}
	}

	/* look for ancient toolkits */
	for (i = 0; deps != NULL && deps[i] != NULL; i++) {
		if (g_strcmp0 (deps[i], "libgtk-1.2.so.0") == 0) {
			as_app_add_veto (AS_APP (app), "Uses obsolete GTK1 toolkit");
			break;
		}
		if (g_strcmp0 (deps[i], "libglib-1.2.so.0") == 0) {
			as_app_add_veto (AS_APP (app), "Uses obsolete GLib library");
			break;
		}
		if (g_strcmp0 (deps[i], "libqt-mt.so.3") == 0) {
			as_app_add_veto (AS_APP (app), "Uses obsolete QT3 toolkit");
			break;
		}
		if (g_strcmp0 (deps[i], "liblcms.so.1") == 0) {
			as_app_add_veto (AS_APP (app), "Uses obsolete LCMS library");
			break;
		}
		if (g_strcmp0 (deps[i], "libelektra.so.4") == 0) {
			as_app_add_veto (AS_APP (app), "Uses obsolete Elektra library");
			break;
		}
		if (g_strcmp0 (deps[i], "libXt.so.6") == 0) {
			asb_app_add_requires_appdata (app, "Uses obsolete X11 toolkit");
			break;
		}
		if (g_strcmp0 (deps[i], "wine-core") == 0) {
			asb_app_add_requires_appdata (app, "Uses wine");
			break;
		}
	}

	/* has the application been updated in the last year */
	releases = as_app_get_releases (AS_APP (app));
	if (asb_context_get_api_version (plugin->ctx) < 0.8) {
		for (i = 0; i < releases->len; i++) {
			release = g_ptr_array_index (releases, i);
			secs = (g_get_real_time () / G_USEC_PER_SEC) -
				as_release_get_timestamp (release);
			days = secs / (60 * 60 * 24);
			if (secs > 0 && days < 365) {
				as_app_add_metadata (AS_APP (app),
						     "X-Kudo-RecentRelease", "", -1);
				break;
			}
		}
	}

	/* has there been no upstream version recently */
	if (releases->len > 0 &&
	    as_app_get_id_kind (AS_APP (app)) == AS_ID_KIND_DESKTOP) {
		release = g_ptr_array_index (releases, 0);
		secs = (g_get_real_time () / G_USEC_PER_SEC) -
			as_release_get_timestamp (release);
		days = secs / (60 * 60 * 24);
		/* we need AppData if the app needs saving */
		if (secs > 0 && days > 365 * 5) {
			asb_app_add_requires_appdata (app,
				"Dead upstream for > %i years", 5);
		}
	}

	/* do any extra screenshots exist */
	tmp = asb_package_get_config (pkg, "ScreenshotsExtra");
	if (tmp != NULL) {
		_cleanup_free_ gchar *dirname = NULL;
		dirname = g_build_filename (tmp, as_app_get_id_filename (AS_APP (app)), NULL);
		if (g_file_test (dirname, G_FILE_TEST_EXISTS)) {
			if (!asb_plugin_hardcoded_add_screenshots (app, dirname, error))
				return FALSE;
		}
	}

	/* a ConsoleOnly category means we require AppData */
	if (as_app_has_category (AS_APP(app), "ConsoleOnly"))
		asb_app_add_requires_appdata (app, "ConsoleOnly");

	/* no categories means we require AppData */
	if (as_app_get_id_kind (AS_APP (app)) == AS_ID_KIND_DESKTOP &&
	    as_app_get_categories(AS_APP(app))->len == 0)
		asb_app_add_requires_appdata (app, "no Categories");

	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;
}
/**
 * _as_app_composite:
 */
static gboolean
_as_app_composite (AsApp *app, AsApp *donor, GError **error)
{
	AsApp *tmp;
	gint rc;
	_cleanup_free_ gchar *id = NULL;

	/* check this makes sense */
	if (as_app_get_id_kind (app) != as_app_get_id_kind (donor)) {
		g_set_error (error,
			     AS_APP_ERROR,
			     AS_APP_ERROR_INVALID_TYPE,
			     "Cannot composite %s:%s of different id kind",
			     as_app_get_id (app),
			     as_app_get_id (donor));
		return FALSE;
	}

	/* the ID, name with the shortest length wins */
	rc = strlen (as_app_get_id (app)) - strlen (as_app_get_id (donor));
	if (rc == 0) {
		rc = strlen (as_app_get_name (app, "C")) -
		     strlen (as_app_get_name (donor, "C"));
	}
	if (rc > 0) {
		tmp = app;
		app = donor;
		donor = tmp;
	}

	/* set the new composite string */
	id = as_utils_get_string_overlap (as_app_get_id (app), as_app_get_id (donor));
	if (id == NULL || !_as_app_is_id_valid (id)) {
		g_set_error (error,
			     AS_APP_ERROR,
			     AS_APP_ERROR_INVALID_TYPE,
			     "Cannot composite %s:%s as no ID overlap",
			     as_app_get_id (app),
			     as_app_get_id (donor));
		return FALSE;
	}


	/* log */
	if (ASB_IS_APP (app) && g_strcmp0 (as_app_get_id (app), id) != 0) {
		asb_package_log (asb_app_get_package (ASB_APP (app)),
				 ASB_PACKAGE_LOG_LEVEL_INFO,
				 "Renamed %s into %s so it could be "
				 "composited with %s",
				 as_app_get_id (app), id,
				 as_app_get_id (donor));
	}
	if (ASB_IS_APP (donor)) {
		asb_package_log (asb_app_get_package (ASB_APP (donor)),
				 ASB_PACKAGE_LOG_LEVEL_INFO,
				 "Composited %s into %s",
				 as_app_get_id (donor), id);
	}

	/* set the new ID (on both apps?) */
	as_app_set_id (app, id, -1);

	/* add some easily merged properties */
	as_app_subsume_full (app, donor, AS_APP_SUBSUME_FLAG_PARTIAL);
	as_app_add_veto (donor, "absorbed into %s", as_app_get_id (app));
	return TRUE;
}
Exemple #12
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;
}
Exemple #13
0
static gboolean
as_app_parse_file_key (AsApp *app,
		       GKeyFile *kf,
		       const gchar *key,
		       AsAppParseFlags flags,
		       GError **error)
{
	guint i;
	guint j;
	g_autofree gchar *locale = NULL;
	g_autofree gchar *tmp = NULL;
	g_auto(GStrv) list = NULL;

	/* NoDisplay */
	if (g_strcmp0 (key, G_KEY_FILE_DESKTOP_KEY_NO_DISPLAY) == 0) {
		tmp = g_key_file_get_string (kf,
					     G_KEY_FILE_DESKTOP_GROUP,
					     key,
					     NULL);
		if (tmp != NULL && strcasecmp (tmp, "True") == 0)
			as_app_add_veto (app, "NoDisplay=true");

	/* Type */
	} else if (g_strcmp0 (key, G_KEY_FILE_DESKTOP_KEY_TYPE) == 0) {
		tmp = g_key_file_get_string (kf,
					     G_KEY_FILE_DESKTOP_GROUP,
					     key,
					     NULL);
		if (g_strcmp0 (tmp, G_KEY_FILE_DESKTOP_TYPE_APPLICATION) != 0) {
			g_set_error_literal (error,
					     AS_APP_ERROR,
					     AS_APP_ERROR_INVALID_TYPE,
					     "not an application");
			return FALSE;
		}

	/* Icon */
	} else if (g_strcmp0 (key, G_KEY_FILE_DESKTOP_KEY_ICON) == 0) {
		tmp = g_key_file_get_string (kf,
					     G_KEY_FILE_DESKTOP_GROUP,
					     key,
					     NULL);
		if (tmp != NULL && tmp[0] != '\0') {
			g_autoptr(AsIcon) icon = NULL;
			icon = as_app_desktop_create_icon (app, tmp, flags);
			as_app_add_icon (app, icon);
		}

	/* Categories */
	} else if (g_strcmp0 (key, G_KEY_FILE_DESKTOP_KEY_CATEGORIES) == 0) {
		list = g_key_file_get_string_list (kf,
						   G_KEY_FILE_DESKTOP_GROUP,
						   key,
						   NULL, NULL);
		for (i = 0; list[i] != NULL; i++) {
			const gchar *category_blacklist[] = {
				"X-GNOME-Settings-Panel",
				"X-Unity-Settings-Panel",
				NULL };

			/* we have to veto these */
			for (j = 0; category_blacklist[j] != NULL; j++) {
				if (g_strcmp0 (list[i], category_blacklist[j]) == 0) {
					as_app_add_veto (app, "Has category %s",
							 category_blacklist[j]);
				}
			}

			/* check the category is valid */
			if (!as_utils_is_category_id (list[i]))
				continue;

			/* ignore some useless keys */
			if (g_strcmp0 (list[i], "GTK") == 0)
				continue;
			if (g_strcmp0 (list[i], "Qt") == 0)
				continue;
			if (g_strcmp0 (list[i], "KDE") == 0)
				continue;
			if (g_strcmp0 (list[i], "GNOME") == 0)
				continue;
			as_app_add_category (app, list[i]);
		}

	} else if (g_strcmp0 (key, "Keywords") == 0) {
		list = g_key_file_get_string_list (kf,
						   G_KEY_FILE_DESKTOP_GROUP,
						   key,
						   NULL, NULL);
		for (i = 0; list[i] != NULL; i++) {
			g_auto(GStrv) kw_split = NULL;
			kw_split = g_strsplit (list[i], ",", -1);
			for (j = 0; kw_split[j] != NULL; j++) {
				if (kw_split[j][0] == '\0')
					continue;
				as_app_add_keyword (app, "C", kw_split[j]);
			}
		}

	} else if (g_str_has_prefix (key, "Keywords")) {
		locale = as_app_desktop_key_get_locale (key);
		if (flags & AS_APP_PARSE_FLAG_ONLY_NATIVE_LANGS &&
		    !g_strv_contains (g_get_language_names (), locale))
			return TRUE;
		list = g_key_file_get_locale_string_list (kf,
							  G_KEY_FILE_DESKTOP_GROUP,
							  key,
							  locale,
							  NULL, NULL);
		for (i = 0; list[i] != NULL; i++) {
			g_auto(GStrv) kw_split = NULL;
			kw_split = g_strsplit (list[i], ",", -1);
			for (j = 0; kw_split[j] != NULL; j++) {
				if (kw_split[j][0] == '\0')
					continue;
				as_app_add_keyword (app, locale, kw_split[j]);
			}
		}

	} else if (g_strcmp0 (key, "MimeType") == 0) {
		list = g_key_file_get_string_list (kf,
						   G_KEY_FILE_DESKTOP_GROUP,
						   key,
						   NULL, NULL);
		for (i = 0; list[i] != NULL; i++)
			as_app_add_mimetype (app, list[i]);

	} else if (g_strcmp0 (key, "X-AppInstall-Package") == 0) {
		tmp = g_key_file_get_string (kf,
					     G_KEY_FILE_DESKTOP_GROUP,
					     key,
					     NULL);
		if (tmp != NULL && tmp[0] != '\0')
			as_app_add_pkgname (app, tmp);

	/* OnlyShowIn */
	} else if (g_strcmp0 (key, G_KEY_FILE_DESKTOP_KEY_ONLY_SHOW_IN) == 0) {
		/* if an app has only one entry, it's that desktop */
		list = g_key_file_get_string_list (kf,
						   G_KEY_FILE_DESKTOP_GROUP,
						   key,
						   NULL, NULL);
		if (g_strv_length (list) == 1)
			as_app_set_project_group (app, list[0]);

	/* Name */
	} else if (g_strcmp0 (key, G_KEY_FILE_DESKTOP_KEY_NAME) == 0 ||
	           g_strcmp0 (key, "_Name") == 0) {
		tmp = g_key_file_get_string (kf,
					     G_KEY_FILE_DESKTOP_GROUP,
					     key,
					     NULL);
		if (tmp != NULL && tmp[0] != '\0')
			as_app_set_name (app, "C", tmp);

	/* Name[] */
	} else if (g_str_has_prefix (key, G_KEY_FILE_DESKTOP_KEY_NAME)) {
		locale = as_app_desktop_key_get_locale (key);
		if (flags & AS_APP_PARSE_FLAG_ONLY_NATIVE_LANGS &&
		    !g_strv_contains (g_get_language_names (), locale))
			return TRUE;
		tmp = g_key_file_get_locale_string (kf,
						    G_KEY_FILE_DESKTOP_GROUP,
						    G_KEY_FILE_DESKTOP_KEY_NAME,
						    locale,
						    NULL);
		if (tmp != NULL && tmp[0] != '\0')
			as_app_set_name (app, locale, tmp);

	/* Comment */
	} else if (g_strcmp0 (key, G_KEY_FILE_DESKTOP_KEY_COMMENT) == 0 ||
	           g_strcmp0 (key, "_Comment") == 0) {
		tmp = g_key_file_get_string (kf,
					     G_KEY_FILE_DESKTOP_GROUP,
					     key,
					     NULL);
		if (tmp != NULL && tmp[0] != '\0')
			as_app_set_comment (app, "C", tmp);

	/* Comment[] */
	} else if (g_str_has_prefix (key, G_KEY_FILE_DESKTOP_KEY_COMMENT)) {
		locale = as_app_desktop_key_get_locale (key);
		if (flags & AS_APP_PARSE_FLAG_ONLY_NATIVE_LANGS &&
		    !g_strv_contains (g_get_language_names (), locale))
			return TRUE;
		tmp = g_key_file_get_locale_string (kf,
						    G_KEY_FILE_DESKTOP_GROUP,
						    G_KEY_FILE_DESKTOP_KEY_COMMENT,
						    locale,
						    NULL);
		if (tmp != NULL && tmp[0] != '\0')
			as_app_set_comment (app, locale, tmp);

	/* non-standard */
	} else if (g_strcmp0 (key, "X-Ubuntu-Software-Center-Name") == 0) {
		tmp = g_key_file_get_string (kf,
					     G_KEY_FILE_DESKTOP_GROUP,
					     key,
					     NULL);
		if (tmp != NULL && tmp[0] != '\0')
			as_app_set_name (app, "C", tmp);
	} else if (g_str_has_prefix (key, "X-Ubuntu-Software-Center-Name")) {
		locale = as_app_desktop_key_get_locale (key);
		if (flags & AS_APP_PARSE_FLAG_ONLY_NATIVE_LANGS &&
		    !g_strv_contains (g_get_language_names (), locale))
			return TRUE;
		tmp = g_key_file_get_locale_string (kf,
						    G_KEY_FILE_DESKTOP_GROUP,
						    "X-Ubuntu-Software-Center-Name",
						    locale,
						    NULL);
		if (tmp != NULL && tmp[0] != '\0')
			as_app_set_name (app, locale, tmp);

	/* for Ubuntu */
	} else if (g_strcmp0 (key, "X-AppStream-Ignore") == 0) {
		gboolean ret;
		ret = g_key_file_get_boolean (kf,
					      G_KEY_FILE_DESKTOP_GROUP,
					      key,
					      NULL);
		if (ret)
			as_app_add_veto (app, "X-AppStream-Ignore");
	}

	/* add any external attribute as metadata to the application */
	if (flags & AS_APP_PARSE_FLAG_ADD_ALL_METADATA)
		as_app_parse_file_metadata (app, kf, key);

	return TRUE;
}