コード例 #1
0
/**
 * 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;
}
コード例 #2
0
/**
 * asb_plugin_merge:
 */
void
asb_plugin_merge (AsbPlugin *plugin, GList **list)
{
	AsApp *app;
	AsApp *found;
	GList *l;
	GList *list_new = NULL;
	_cleanup_hashtable_unref_ GHashTable *hash;

	/* 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_full (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)) {
			asb_plugin_add_app (&list_new, l->data);
			continue;
		}
		app = AS_APP (l->data);
		if (as_app_get_id_kind (app) != AS_ID_KIND_ADDON) {
			asb_plugin_add_app (&list_new, l->data);
			continue;
		}
		found = g_hash_table_lookup (hash, as_app_get_id_full (app));
		if (found == NULL) {
			asb_plugin_add_app (&list_new, l->data);
			continue;
		}
		if (g_strcmp0 (as_app_get_pkgname_default (app),
			       as_app_get_pkgname_default (found)) == 0) {
			g_debug ("absorbing addon %s shipped in main package %s",
				 as_app_get_id_full (app),
				 as_app_get_pkgname_default (app));
			as_app_subsume_full (found, app, AS_APP_SUBSUME_FLAG_PARTIAL);
			continue;
		}
		asb_plugin_add_app (&list_new, app);
	}

	/* success */
	g_list_free_full (*list, (GDestroyNotify) g_object_unref);
	*list = list_new;
}
コード例 #3
0
ファイル: asb-context.c プロジェクト: superm1/appstream-glib
/**
 * 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;
}
コード例 #4
0
/**
 * asb_plugin_merge_prepare_deps:
 */
static void
asb_plugin_merge_prepare_deps (GList *list)
{
    AsApp *app;
    AsbPackage *pkg;
    GList *l;

    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;
        if (!ASB_IS_APP (app))
            continue;
        if (as_app_get_vetos(app)->len > 0)
            continue;
        pkg = asb_app_get_package (ASB_APP (app));
        asb_plugin_absorb_parent_for_pkgname (list, app, asb_package_get_name (pkg));
    }
}
コード例 #5
0
/**
 * asb_plugin_merge_prepare_deps:
 */
static void
asb_plugin_merge_prepare_deps (GList *list)
{
	AsApp *app;
	AsbPackage *pkg;
	GList *l;
	gchar **deps;
	guint i;

	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;
		pkg = asb_app_get_package (ASB_APP (app));
		deps = asb_package_get_deps (pkg);
		for (i = 0; deps[i] != NULL; i++)
			asb_plugin_absorb_parent_for_pkgname (list, app, deps[i]);
	}
}
コード例 #6
0
ファイル: asb-context.c プロジェクト: superm1/appstream-glib
/**
 * 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;
}
コード例 #7
0
/**
 * asb_plugin_absorb_parent_for_pkgname:
 */
static void
asb_plugin_absorb_parent_for_pkgname (GList *list, AsApp *parent, const gchar *pkgname)
{
	AsApp *app;
	GList *l;

	for (l = list; l != NULL; l = l->next) {
		app = AS_APP (l->data);
		if (as_app_get_id_kind (app) != AS_ID_KIND_ADDON)
			continue;
		if (g_strcmp0 (as_app_get_pkgname_default (app), pkgname) != 0)
			continue;
		g_debug ("Adding X-Merge-With-Parent on %s as %s depends on %s",
			 as_app_get_id_full (app),
			 as_app_get_pkgname_default (parent),
			 as_app_get_pkgname_default (app));
		as_app_add_metadata (app,
				     "X-Merge-With-Parent",
				     as_app_get_id_full (parent), -1);
	}
}
コード例 #8
0
/**
 * cra_plugin_process_app:
 */
gboolean
cra_plugin_process_app (CraPlugin *plugin,
			CraPackage *pkg,
			CraApp *app,
			const gchar *tmpdir,
			GError **error)
{
	const gchar *tmp;
	AsRelease *release;
	gchar **deps;
	gchar **filelist;
	GPtrArray *releases;
	guint i;
	guint secs;
	guint days;

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

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

	/* use the URL to guess the project group */
	tmp = cra_package_get_url (pkg);
	if (as_app_get_project_group (AS_APP (app)) == NULL && tmp != NULL) {
		tmp = cra_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 = cra_package_get_filelist (pkg);
	for (i = 0; filelist[i] != NULL; i++) {
		if (g_str_has_prefix (filelist[i],
				      "/usr/share/help/")) {
			as_app_add_metadata (AS_APP (app),
					     "X-Kudo-InstallsUserDocs", "", -1);
			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_metadata (AS_APP (app),
					     "X-Kudo-SearchProvider", "", -1);
			break;
		}
	}

	/* look for a modern toolkit */
	deps = cra_package_get_deps (pkg);
	for (i = 0; deps != NULL && deps[i] != NULL; i++) {
		if (g_strcmp0 (deps[i], "libgtk-3.so.0") == 0) {
			as_app_add_metadata (AS_APP (app),
					     "X-Kudo-GTK3", "", -1);
			break;
		}
		if (g_strcmp0 (deps[i], "libQt5Core.so.5") == 0) {
			as_app_add_metadata (AS_APP (app),
					     "X-Kudo-QT5", "", -1);
			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) {
			cra_app_add_veto (app, "Uses obsolete GTK1 toolkit");
			break;
		}
		if (g_strcmp0 (deps[i], "libqt-mt.so.3") == 0) {
			cra_app_add_veto (app, "Uses obsolete QT3 toolkit");
			break;
		}
		if (g_strcmp0 (deps[i], "liblcms.so.1") == 0) {
			cra_app_add_veto (app, "Uses obsolete LCMS library");
			break;
		}
		if (g_strcmp0 (deps[i], "libelektra.so.4") == 0) {
			cra_app_add_veto (app, "Uses obsolete Elektra library");
			break;
		}
		if (g_strcmp0 (deps[i], "libXt.so.6") == 0) {
			cra_app_add_requires_appdata (app, "Uses obsolete X11 toolkit");
			break;
		}
		if (g_strcmp0 (deps[i], "wine-core") == 0) {
			cra_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));
	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 (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);

		/* this is just too old for us to care about */
		if (days > 365 * 10) {
			cra_app_add_veto (app, "Dead upstream for %i years",
					  secs / (60 * 60 * 24 * 365));
		}

		/* we need AppData if the app needs saving */
		else if (days > 365 * 5) {
			cra_app_add_requires_appdata (app,
				"Dead upstream for > %i years", 5);
		}
	}

	/* do any extra screenshots exist */
	tmp = cra_package_get_config (pkg, "ScreenshotsExtra");
	if (tmp != NULL) {
		_cleanup_free_ gchar *dirname = NULL;
		dirname = g_build_filename (tmp, as_app_get_id (AS_APP (app)), NULL);
		if (g_file_test (dirname, G_FILE_TEST_EXISTS)) {
			if (!cra_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"))
		cra_app_add_requires_appdata (app, "ConsoleOnly");

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

	return TRUE;
}
コード例 #9
0
/**
 * 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;
	GPtrArray *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);
	if (g_strcmp0 (tmp, "wallpapoz.desktop") == 0)
		as_app_add_category (AS_APP (app), "System", -1);
	if (g_strcmp0 (tmp, "superkaramba.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 (asb_plugin_match_glob ("/usr/share/help/*", filelist[i])) {
			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 (asb_plugin_match_glob ("/usr/share/gnome-shell/search-providers/*",
					   filelist[i])) {
			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 (asb_plugin_match_glob ("/usr/share/icons/HighContrast/*",
					   filelist[i])) {
			as_app_add_kudo_kind (AS_APP (app),
					      AS_KUDO_KIND_HIGH_CONTRAST);
			break;
		}
		if (asb_plugin_match_glob ("/usr/share/icons/hicolor/symbolic/apps/*.svg",
					   filelist[i])) {
			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; i < deps->len; i++) {
		tmp = g_ptr_array_index (deps, i);
		if (g_strcmp0 (tmp, "libgtk-3.so.0") == 0 ||
		    g_strcmp0 (tmp, "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; i < deps->len; i++) {
		tmp = g_ptr_array_index (deps, i);
		if (g_strcmp0 (tmp, "libgtk-1.2.so.0") == 0) {
			as_app_add_veto (AS_APP (app), "Uses obsolete GTK1 toolkit");
			break;
		}
		if (g_strcmp0 (tmp, "libglib-1.2.so.0") == 0) {
			as_app_add_veto (AS_APP (app), "Uses obsolete GLib library");
			break;
		}
		if (g_strcmp0 (tmp, "libqt-mt.so.3") == 0) {
			as_app_add_veto (AS_APP (app), "Uses obsolete QT3 toolkit");
			break;
		}
		if (g_strcmp0 (tmp, "liblcms.so.1") == 0) {
			as_app_add_veto (AS_APP (app), "Uses obsolete LCMS library");
			break;
		}
		if (g_strcmp0 (tmp, "libelektra.so.4") == 0) {
			as_app_add_veto (AS_APP (app), "Uses obsolete Elektra library");
			break;
		}
		if (g_strcmp0 (tmp, "libXt.so.6") == 0) {
			asb_app_add_requires_appdata (app, "Uses obsolete X11 toolkit");
			break;
		}
		if (g_strcmp0 (tmp, "Xvfb") == 0) {
			asb_app_add_requires_appdata (app, "Uses obsolete Xvfb");
			break;
		}
		if (g_strcmp0 (tmp, "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);
		}
	}

	/* 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;
}
コード例 #10
0
/**
 * _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;
}
コード例 #11
0
/**
 * as_app_validate:
 * @app: a #AsApp instance.
 * @flags: the #AsAppValidateFlags to use, e.g. %AS_APP_VALIDATE_FLAG_NONE
 * @error: A #GError or %NULL.
 *
 * Validates data in the instance for style and consitency.
 *
 * Returns: (transfer container) (element-type AsProblem): A list of problems, or %NULL
 *
 * Since: 0.1.4
 **/
GPtrArray *
as_app_validate (AsApp *app, AsAppValidateFlags flags, GError **error)
{
	AsAppProblems problems;
	AsAppValidateHelper helper;
	GError *error_local = NULL;
	GHashTable *urls;
	GList *l;
	GPtrArray *probs = NULL;
	const gchar *description;
	const gchar *id_full;
	const gchar *key;
	const gchar *license;
	const gchar *name;
	const gchar *summary;
	const gchar *tmp;
	const gchar *update_contact;
	gboolean deprectated_failure = FALSE;
	gboolean require_contactdetails = TRUE;
	gboolean require_copyright = FALSE;
	gboolean require_project_license = FALSE;
	gboolean require_translations = FALSE;
	gboolean require_url = TRUE;
	gboolean ret;
	guint length_name_max = 30;
	guint length_name_min = 3;
	guint length_summary_max = 100;
	guint length_summary_min = 8;
	guint number_para_max = 4;
	guint number_para_min = 2;
	guint str_len;
	_cleanup_list_free_ GList *keys = NULL;

	/* relax the requirements a bit */
	if ((flags & AS_APP_VALIDATE_FLAG_RELAX) > 0) {
		length_name_max = 100;
		length_summary_max = 200;
		require_contactdetails = FALSE;
		require_url = FALSE;
		number_para_max = 10;
		number_para_min = 1;
	}

	/* make the requirements more strict */
	if ((flags & AS_APP_VALIDATE_FLAG_STRICT) > 0) {
		deprectated_failure = TRUE;
		require_copyright = TRUE;
		require_translations = TRUE;
		require_project_license = TRUE;
	}

	/* set up networking */
	helper.probs = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
	helper.screenshot_urls = g_ptr_array_new_with_free_func (g_free);
	helper.flags = flags;
	helper.previous_para_was_short = FALSE;
	helper.para_chars_before_list = 0;
	helper.number_paragraphs = 0;
	ret = as_app_validate_setup_networking (&helper, error);
	if (!ret)
		goto out;

	/* success, enough */
	probs = helper.probs;

	/* id */
	ret = FALSE;
	id_full = as_app_get_id_full (app);
	switch (as_app_get_id_kind (app)) {
	case AS_ID_KIND_DESKTOP:
		if (g_str_has_suffix (id_full, ".desktop"))
			ret = TRUE;
		break;
	case AS_ID_KIND_FONT:
		if (g_str_has_suffix (id_full, ".ttf"))
			ret = TRUE;
		else if (g_str_has_suffix (id_full, ".otf"))
			ret = TRUE;
		break;
	case AS_ID_KIND_INPUT_METHOD:
		if (g_str_has_suffix (id_full, ".xml"))
			ret = TRUE;
		else if (g_str_has_suffix (id_full, ".db"))
			ret = TRUE;
		break;
	case AS_ID_KIND_CODEC:
		if (g_str_has_prefix (id_full, "gstreamer"))
			ret = TRUE;
		break;
	case AS_ID_KIND_UNKNOWN:
		ai_app_validate_add (probs,
				     AS_PROBLEM_KIND_ATTRIBUTE_INVALID,
				     "<id> has invalid type attribute");

		break;
	case AS_ID_KIND_ADDON:
		/* anything goes */
		ret = TRUE;
	default:
		break;
	}
	if (!ret) {
		ai_app_validate_add (probs,
				     AS_PROBLEM_KIND_MARKUP_INVALID,
				     "<id> does not have correct extension for kind");
	}

	/* metadata_license */
	license = as_app_get_metadata_license (app);
	if (license != NULL) {
		if (g_strcmp0 (license, "CC0-1.0") != 0 &&
		    g_strcmp0 (license, "CC-BY-3.0") != 0 &&
		    g_strcmp0 (license, "CC-BY-SA-3.0") != 0 &&
		    g_strcmp0 (license, "GFDL-1.3") != 0) {
			ai_app_validate_add (probs,
					     AS_PROBLEM_KIND_TAG_INVALID,
					     "<metadata_license> is not valid");
		}
	}
	if (license == NULL) {
		switch (as_app_get_source_kind (app)) {
		case AS_APP_SOURCE_KIND_APPDATA:
		case AS_APP_SOURCE_KIND_METAINFO:
			ai_app_validate_add (probs,
					     AS_PROBLEM_KIND_TAG_MISSING,
					     "<metadata_license> is not present");
			break;
		default:
			break;
		}
	}

	/* project_license */
	license = as_app_get_project_license (app);
	if (license != NULL) {
		ret = as_app_validate_license (license, &error_local);
		if (!ret) {
			g_prefix_error (&error_local,
					"<project_license> is not valid: ");
			ai_app_validate_add (probs,
					     AS_PROBLEM_KIND_TAG_INVALID,
					     error_local->message);
			g_clear_error (&error_local);
		}
	}
	if (require_project_license && license == NULL) {
		switch (as_app_get_source_kind (app)) {
		case AS_APP_SOURCE_KIND_APPDATA:
		case AS_APP_SOURCE_KIND_METAINFO:
			ai_app_validate_add (probs,
					     AS_PROBLEM_KIND_TAG_MISSING,
					     "<project_license> is not present");
			break;
		default:
			break;
		}
	}

	/* updatecontact */
	update_contact = as_app_get_update_contact (app);
	if (g_strcmp0 (update_contact,
		       "someone_who_cares@upstream_project.org") == 0) {
		ai_app_validate_add (probs,
				     AS_PROBLEM_KIND_TAG_INVALID,
				     "<update_contact> is still set to a dummy value");
	}
	if (update_contact != NULL && strlen (update_contact) < 6) {
		ai_app_validate_add (probs,
				     AS_PROBLEM_KIND_STYLE_INCORRECT,
				     "<update_contact> is too short");
	}
	if (require_contactdetails && update_contact == NULL) {
		switch (as_app_get_source_kind (app)) {
		case AS_APP_SOURCE_KIND_APPDATA:
		case AS_APP_SOURCE_KIND_METAINFO:
			ai_app_validate_add (probs,
					     AS_PROBLEM_KIND_TAG_MISSING,
					     "<updatecontact> is not present");
			break;
		default:
			break;
		}
	}

	/* only found for files */
	problems = as_app_get_problems (app);
	if (as_app_get_source_kind (app) == AS_APP_SOURCE_KIND_APPDATA ||
	    as_app_get_source_kind (app) == AS_APP_SOURCE_KIND_METAINFO) {
		if ((problems & AS_APP_PROBLEM_NO_XML_HEADER) > 0) {
			ai_app_validate_add (probs,
					     AS_PROBLEM_KIND_MARKUP_INVALID,
					     "<?xml> header not found");
		}
		if (require_copyright &&
		    (problems & AS_APP_PROBLEM_NO_COPYRIGHT_INFO) > 0) {
			ai_app_validate_add (probs,
					     AS_PROBLEM_KIND_VALUE_MISSING,
					     "<!-- Copyright [year] [name] --> is not present");
		}
	}

	/* check for things that have to exist */
	if (as_app_get_id_full (app) == NULL) {
		ai_app_validate_add (probs,
				     AS_PROBLEM_KIND_TAG_MISSING,
				     "<id> is not present");
	}

	/* url */
	urls = as_app_get_urls (app);
	keys = g_hash_table_get_keys (urls);
	for (l = keys; l != NULL; l = l->next) {
		key = l->data;
		if (g_strcmp0 (key, "unknown") == 0) {
			ai_app_validate_add (probs,
					     AS_PROBLEM_KIND_TAG_INVALID,
					     "<url> type invalid");
		}
		tmp = g_hash_table_lookup (urls, key);
		if (!g_str_has_prefix (tmp, "http://") &&
		    !g_str_has_prefix (tmp, "https://")) {
			ai_app_validate_add (probs,
					     AS_PROBLEM_KIND_TAG_INVALID,
					     "<url> does not start with 'http://'");
		}
	}

	/* screenshots */
	as_app_validate_screenshots (app, &helper);

	/* releases */
	ret = as_app_validate_releases (app, &helper, error);
	if (!ret)
		goto out;

	/* name */
	name = as_app_get_name (app, "C");
	if (name != NULL) {
		str_len = strlen (name);
		if (str_len < length_name_min) {
			ai_app_validate_add (probs,
					     AS_PROBLEM_KIND_STYLE_INCORRECT,
					     "<name> is too short");
		}
		if (str_len > length_name_max) {
			ai_app_validate_add (probs,
					     AS_PROBLEM_KIND_STYLE_INCORRECT,
					     "<name> is too long");
		}
		if (ai_app_validate_fullstop_ending (name)) {
			ai_app_validate_add (probs,
					     AS_PROBLEM_KIND_STYLE_INCORRECT,
					     "<name> cannot end in '.'");
		}
		if (as_app_validate_has_hyperlink (name)) {
			ai_app_validate_add (probs,
					     AS_PROBLEM_KIND_STYLE_INCORRECT,
					     "<name> cannot contain a hyperlink");
		}
	}

	/* comment */
	summary = as_app_get_comment (app, "C");
	if (summary != NULL) {
		str_len = strlen (summary);
		if (str_len < length_summary_min) {
			ai_app_validate_add (probs,
					     AS_PROBLEM_KIND_STYLE_INCORRECT,
					     "<summary> is too short");
		}
		if (str_len > length_summary_max) {
			ai_app_validate_add (probs,
					     AS_PROBLEM_KIND_STYLE_INCORRECT,
					     "<summary> is too long");
		}
		if (ai_app_validate_fullstop_ending (summary)) {
			ai_app_validate_add (probs,
					     AS_PROBLEM_KIND_STYLE_INCORRECT,
					     "<summary> cannot end in '.'");
		}
		if (as_app_validate_has_hyperlink (summary)) {
			ai_app_validate_add (probs,
					     AS_PROBLEM_KIND_STYLE_INCORRECT,
					     "<summary> cannot contain a hyperlink");
		}
	}
	if (summary != NULL && name != NULL &&
	    strlen (summary) < strlen (name)) {
		ai_app_validate_add (probs,
				     AS_PROBLEM_KIND_STYLE_INCORRECT,
				     "<summary> is shorter than <name>");
	}
	description = as_app_get_description (app, "C");
	if (description != NULL) {
		ret = as_app_validate_description (description,
						   &helper,
						   number_para_min,
						   number_para_max,
						   &error_local);
		if (!ret) {
			ai_app_validate_add (probs,
					     AS_PROBLEM_KIND_MARKUP_INVALID,
					     error_local->message);
			g_error_free (error_local);
		}
	}
	if (require_translations) {
		if (name != NULL &&
		    as_app_get_name_size (app) == 1 &&
		    (problems & AS_APP_PROBLEM_INTLTOOL_NAME) == 0) {
			ai_app_validate_add (probs,
					     AS_PROBLEM_KIND_TRANSLATIONS_REQUIRED,
					     "<name> has no translations");
		}
		if (summary != NULL &&
		    as_app_get_comment_size (app) == 1 &&
		    (problems & AS_APP_PROBLEM_INTLTOOL_SUMMARY) == 0) {
			ai_app_validate_add (probs,
					     AS_PROBLEM_KIND_TRANSLATIONS_REQUIRED,
					     "<summary> has no translations");
		}
		if (description != NULL &&
		    as_app_get_description_size (app) == 1 &&
		    (problems & AS_APP_PROBLEM_INTLTOOL_DESCRIPTION) == 0) {
			ai_app_validate_add (probs,
					     AS_PROBLEM_KIND_TRANSLATIONS_REQUIRED,
					     "<description> has no translations");
		}
	}

	/* using deprecated names */
	if (deprectated_failure && (problems & AS_APP_PROBLEM_DEPRECATED_LICENCE) > 0) {
		ai_app_validate_add (probs,
				     AS_PROBLEM_KIND_ATTRIBUTE_INVALID,
				     "<licence> is deprecated, use "
				     "<metadata_license> instead");
	}
	if ((problems & AS_APP_PROBLEM_MULTIPLE_ENTRIES) > 0) {
		ai_app_validate_add (probs,
				     AS_PROBLEM_KIND_MARKUP_INVALID,
				     "<application> used more than once");
	}

	/* require homepage */
	if (require_url && as_app_get_url_item (app, AS_URL_KIND_HOMEPAGE) == NULL) {
		switch (as_app_get_source_kind (app)) {
		case AS_APP_SOURCE_KIND_APPDATA:
		case AS_APP_SOURCE_KIND_METAINFO:
			ai_app_validate_add (probs,
					     AS_PROBLEM_KIND_TAG_MISSING,
					     "<url> is not present");
			break;
		default:
			break;
		}
	}
out:
	g_ptr_array_unref (helper.screenshot_urls);
	if (helper.session != NULL)
		g_object_unref (helper.session);
	return probs;
}