gboolean gs_plugin_refine_app (GsPlugin *plugin, GsApp *app, GsPluginRefineFlags flags, GCancellable *cancellable, GError **error) { GsPluginData *priv = gs_plugin_get_data (plugin); const gchar *origin; /* not required */ if ((flags & GS_PLUGIN_REFINE_FLAGS_REQUIRE_LICENSE) == 0) return TRUE; /* no provenance */ if (!gs_app_has_quirk (app, AS_APP_QUIRK_PROVENANCE)) return TRUE; /* nothing to search */ if (priv->sources == NULL || priv->sources[0] == NULL) return TRUE; /* simple case */ origin = gs_app_get_origin (app); if (origin != NULL && gs_utils_strv_fnmatch (priv->sources, origin)) gs_app_set_license (app, GS_APP_QUALITY_NORMAL, priv->license_id); return TRUE; }
/** * gs_appstream_refine_app: */ gboolean gs_appstream_refine_app (GsPlugin *plugin, GsApp *app, AsApp *item, GError **error) { AsRelease *rel; GHashTable *urls; GPtrArray *pkgnames; GPtrArray *kudos; const gchar *tmp; guint i; /* set the kind to be more precise */ if (gs_app_get_kind (app) == AS_APP_KIND_UNKNOWN || gs_app_get_kind (app) == AS_APP_KIND_GENERIC) { gs_app_set_kind (app, as_app_get_kind (item)); } /* is installed already */ if (gs_app_get_state (app) == AS_APP_STATE_UNKNOWN) { switch (as_app_get_source_kind (item)) { case AS_APP_SOURCE_KIND_APPDATA: case AS_APP_SOURCE_KIND_DESKTOP: gs_app_set_kind (app, AS_APP_KIND_DESKTOP); gs_app_set_state (app, AS_APP_STATE_INSTALLED); break; case AS_APP_SOURCE_KIND_METAINFO: gs_app_set_state (app, AS_APP_STATE_INSTALLED); break; case AS_APP_SOURCE_KIND_APPSTREAM: gs_app_set_state (app, as_app_get_state (item)); break; default: break; } } /* set management plugin automatically */ gs_refine_item_management_plugin (app, item); /* set id */ if (as_app_get_id (item) != NULL && gs_app_get_id (app) == NULL) gs_app_set_id (app, as_app_get_id (item)); /* set name */ tmp = as_app_get_name (item, NULL); if (tmp != NULL) { if (g_str_has_prefix (tmp, "(Nightly) ")) { tmp += 10; if (gs_app_get_metadata_item (app, "X-XdgApp-Tags") == NULL) gs_app_set_metadata (app, "X-XdgApp-Tags", "nightly"); } gs_app_set_name (app, GS_APP_QUALITY_HIGHEST, tmp); } /* set summary */ tmp = as_app_get_comment (item, NULL); if (tmp != NULL) { gs_app_set_summary (app, GS_APP_QUALITY_HIGHEST, tmp); } /* add urls */ urls = as_app_get_urls (item); if (g_hash_table_size (urls) > 0 && gs_app_get_url (app, AS_URL_KIND_HOMEPAGE) == NULL) { GList *l; g_autoptr(GList) keys = NULL; keys = g_hash_table_get_keys (urls); for (l = keys; l != NULL; l = l->next) { gs_app_set_url (app, as_url_kind_from_string (l->data), g_hash_table_lookup (urls, l->data)); } } /* set licence */ if (as_app_get_project_license (item) != NULL && gs_app_get_license (app) == NULL) gs_app_set_license (app, GS_APP_QUALITY_HIGHEST, as_app_get_project_license (item)); /* set keywords */ if (as_app_get_keywords (item, NULL) != NULL && gs_app_get_keywords (app) == NULL) { gs_app_set_keywords (app, as_app_get_keywords (item, NULL)); gs_app_add_kudo (app, GS_APP_KUDO_HAS_KEYWORDS); } /* set origin */ if (as_app_get_origin (item) != NULL && gs_app_get_origin (app) == NULL) { gs_app_set_origin (app, as_app_get_origin (item)); } /* set description */ tmp = as_app_get_description (item, NULL); if (tmp != NULL) { g_autofree gchar *from_xml = NULL; from_xml = as_markup_convert_simple (tmp, error); if (from_xml == NULL) { g_prefix_error (error, "trying to parse '%s': ", tmp); return FALSE; } gs_app_set_description (app, GS_APP_QUALITY_HIGHEST, from_xml); } /* set icon */ if (as_app_get_icon_default (item) != NULL && gs_app_get_pixbuf (app) == NULL) gs_refine_item_pixbuf (plugin, app, item); /* set categories */ if (as_app_get_categories (item) != NULL && gs_app_get_categories (app)->len == 0) gs_app_set_categories (app, as_app_get_categories (item)); /* set project group */ if (as_app_get_project_group (item) != NULL && gs_app_get_project_group (app) == NULL) gs_app_set_project_group (app, as_app_get_project_group (item)); /* this is a core application for the desktop and cannot be removed */ if (_as_app_has_compulsory_for_desktop (item, "GNOME") && gs_app_get_kind (app) == AS_APP_KIND_DESKTOP) gs_app_add_quirk (app, AS_APP_QUIRK_COMPULSORY); /* set id kind */ if (gs_app_get_kind (app) == AS_APP_KIND_UNKNOWN) gs_app_set_kind (app, as_app_get_kind (item)); /* copy all the metadata */ gs_appstream_copy_metadata (app, item); /* set package names */ pkgnames = as_app_get_pkgnames (item); if (pkgnames->len > 0 && gs_app_get_sources(app)->len == 0) gs_app_set_sources (app, pkgnames); /* set addons */ gs_appstream_refine_add_addons (plugin, app, item); /* set screenshots */ gs_appstream_refine_add_screenshots (app, item); /* are the screenshots perfect */ if (gs_appstream_are_screenshots_perfect (item)) gs_app_add_kudo (app, GS_APP_KUDO_PERFECT_SCREENSHOTS); /* was this application released recently */ if (gs_appstream_is_recent_release (item)) gs_app_add_kudo (app, GS_APP_KUDO_RECENT_RELEASE); /* add kudos */ if (as_app_get_language (item, plugin->locale) > 50) gs_app_add_kudo (app, GS_APP_KUDO_MY_LANGUAGE); /* add new-style kudos */ kudos = as_app_get_kudos (item); for (i = 0; i < kudos->len; i++) { tmp = g_ptr_array_index (kudos, i); switch (as_kudo_kind_from_string (tmp)) { case AS_KUDO_KIND_SEARCH_PROVIDER: gs_app_add_kudo (app, GS_APP_KUDO_SEARCH_PROVIDER); break; case AS_KUDO_KIND_USER_DOCS: gs_app_add_kudo (app, GS_APP_KUDO_INSTALLS_USER_DOCS); break; case AS_KUDO_KIND_APP_MENU: gs_app_add_kudo (app, GS_APP_KUDO_USES_APP_MENU); break; case AS_KUDO_KIND_MODERN_TOOLKIT: gs_app_add_kudo (app, GS_APP_KUDO_MODERN_TOOLKIT); break; case AS_KUDO_KIND_NOTIFICATIONS: gs_app_add_kudo (app, GS_APP_KUDO_USES_NOTIFICATIONS); break; case AS_KUDO_KIND_HIGH_CONTRAST: gs_app_add_kudo (app, GS_APP_KUDO_HIGH_CONTRAST); break; case AS_KUDO_KIND_HI_DPI_ICON: gs_app_add_kudo (app, GS_APP_KUDO_HI_DPI_ICON); break; default: g_debug ("no idea how to handle kudo '%s'", tmp); break; } } /* is there any update information */ rel = as_app_get_release_default (item); if (rel != NULL) { tmp = as_release_get_description (rel, NULL); if (tmp != NULL) { g_autofree gchar *desc = NULL; desc = as_markup_convert (tmp, AS_MARKUP_CONVERT_FORMAT_MARKDOWN, error); if (desc == NULL) return FALSE; gs_app_set_update_details (app, desc); } gs_app_set_update_urgency (app, as_release_get_urgency (rel)); gs_app_set_update_version (app, as_release_get_version (rel)); } return TRUE; }
/** * gs_plugin_refine_app: */ gboolean gs_plugin_refine_app (GsPlugin *plugin, GsApp *app, GsPluginRefineFlags flags, GCancellable *cancellable, GError **error) { Header h; const gchar *fn; gint rc; g_auto(rpmdbMatchIterator) mi = NULL; g_auto(rpmts) ts = NULL; /* not required */ if ((flags & GS_PLUGIN_REFINE_FLAGS_REQUIRE_VERSION) == 0 && (flags & GS_PLUGIN_REFINE_FLAGS_REQUIRE_SIZE) == 0 && (flags & GS_PLUGIN_REFINE_FLAGS_REQUIRE_LICENSE) == 0 && (flags & GS_PLUGIN_REFINE_FLAGS_REQUIRE_SETUP_ACTION) == 0) return TRUE; /* no need to run the plugin */ if (gs_app_get_source_default (app) != NULL && gs_app_get_source_id_default (app) != NULL) return TRUE; /* open db readonly */ ts = rpmtsCreate(); rpmtsSetRootDir (ts, NULL); rc = rpmtsOpenDB (ts, O_RDONLY); if (rc != 0) { g_set_error (error, GS_PLUGIN_ERROR, GS_PLUGIN_ERROR_FAILED, "Failed to open rpmdb: %i", rc); return FALSE; } /* look for a specific file */ fn = gs_app_get_metadata_item (app, "appstream::source-file"); if (fn == NULL) return TRUE; if (!g_str_has_prefix (fn, "/usr")) return TRUE; mi = rpmtsInitIterator (ts, RPMDBI_INSTFILENAMES, fn, 0); if (mi == NULL) { g_debug ("rpm: no search results for %s", fn); return TRUE; } /* on rpm-ostree this package cannot be removed 'live' */ gs_app_add_quirk (app, AS_APP_QUIRK_COMPULSORY); /* process any results */ g_debug ("rpm: querying for %s with %s", gs_app_get_id (app), fn); while ((h = rpmdbNextIterator (mi)) != NULL) { guint64 epoch; const gchar *name; const gchar *version; const gchar *arch; const gchar *release; const gchar *license; /* add default source */ name = headerGetString (h, RPMTAG_NAME); if (gs_app_get_source_default (app) == NULL) { g_debug ("rpm: setting source to %s", name); gs_app_add_source (app, name); } /* set size */ if (gs_app_get_size_download (app) == 0) gs_app_set_size_download (app, 0); if (gs_app_get_size_installed (app) == 0) { guint64 tmp; tmp = headerGetNumber (h, RPMTAG_SIZE); gs_app_set_size_installed (app, tmp); } /* set license */ license = headerGetString (h, RPMTAG_LICENSE); if (gs_app_get_license (app) == NULL && license != NULL) { g_autofree gchar *tmp = NULL; tmp = as_utils_license_to_spdx (license); gs_app_set_license (app, GS_APP_QUALITY_NORMAL, tmp); } /* add version */ version = headerGetString (h, RPMTAG_VERSION); if (gs_app_get_version (app) == NULL) { g_debug ("rpm: setting version to %s", version); gs_app_set_version (app, version); } /* add source-id */ if (gs_app_get_source_id_default (app) == NULL) { g_autofree gchar *tmp = NULL; release = headerGetString (h, RPMTAG_RELEASE); arch = headerGetString (h, RPMTAG_ARCH); epoch = headerGetNumber (h, RPMTAG_EPOCH); if (epoch > 0) { tmp = g_strdup_printf ("%s;%" G_GUINT64_FORMAT ":%s-%s;%s;installed", name, epoch, version, release, arch); } else { tmp = g_strdup_printf ("%s;%s-%s;%s;installed", name, version, release, arch); } g_debug ("rpm: setting source-id to %s", tmp); gs_app_add_source_id (app, tmp); } } return TRUE; }
gboolean gs_plugin_refine_app (GsPlugin *plugin, GsApp *app, GsPluginRefineFlags flags, GCancellable *cancellable, GError **error) { GsPluginData *priv = gs_plugin_get_data (plugin); g_autoptr(SnapdClient) client = NULL; const gchar *name; g_autoptr(SnapdSnap) local_snap = NULL; g_autoptr(SnapdSnap) store_snap = NULL; SnapdSnap *snap; const gchar *developer_name; g_autofree gchar *description = NULL; /* not us */ if (g_strcmp0 (gs_app_get_management_plugin (app), "snap") != 0) return TRUE; client = get_client (plugin, error); if (client == NULL) return FALSE; /* get information from local snaps and store */ local_snap = snapd_client_get_snap_sync (client, gs_app_get_metadata_item (app, "snap::name"), cancellable, NULL); if (local_snap == NULL || (flags & GS_PLUGIN_REFINE_FLAGS_REQUIRE_SCREENSHOTS) != 0) store_snap = get_store_snap (plugin, gs_app_get_metadata_item (app, "snap::name"), cancellable, NULL); if (local_snap == NULL && store_snap == NULL) return TRUE; if (local_snap != NULL) gs_app_set_state (app, AS_APP_STATE_INSTALLED); else gs_app_set_state (app, AS_APP_STATE_AVAILABLE); /* use store information for basic metadata over local information */ snap = store_snap != NULL ? store_snap : local_snap; name = snapd_snap_get_title (snap); if (name == NULL || g_strcmp0 (name, "") == 0) name = snapd_snap_get_name (snap); gs_app_set_name (app, GS_APP_QUALITY_NORMAL, name); gs_app_set_summary (app, GS_APP_QUALITY_NORMAL, snapd_snap_get_summary (snap)); description = gs_plugin_snap_get_description_safe (snap); if (description != NULL) gs_app_set_description (app, GS_APP_QUALITY_NORMAL, description); gs_app_set_license (app, GS_APP_QUALITY_NORMAL, snapd_snap_get_license (snap)); developer_name = snapd_snap_get_publisher_display_name (snap); if (developer_name == NULL) developer_name = snapd_snap_get_publisher_username (snap); gs_app_set_developer_name (app, developer_name); if (snapd_snap_get_publisher_validation (snap) == SNAPD_PUBLISHER_VALIDATION_VERIFIED) gs_app_add_quirk (app, GS_APP_QUIRK_DEVELOPER_VERIFIED); snap = local_snap != NULL ? local_snap : store_snap; gs_app_set_version (app, snapd_snap_get_version (snap)); switch (snapd_snap_get_snap_type (snap)) { case SNAPD_SNAP_TYPE_APP: gs_app_set_kind (app, AS_APP_KIND_DESKTOP); break; case SNAPD_SNAP_TYPE_KERNEL: case SNAPD_SNAP_TYPE_GADGET: case SNAPD_SNAP_TYPE_OS: gs_app_set_kind (app, AS_APP_KIND_RUNTIME); break; default: case SNAPD_SNAP_TYPE_UNKNOWN: gs_app_set_kind (app, AS_APP_KIND_UNKNOWN); break; } /* add information specific to installed snaps */ if (local_snap != NULL) { SnapdApp *snap_app; GDateTime *install_date; install_date = snapd_snap_get_install_date (local_snap); gs_app_set_size_installed (app, snapd_snap_get_installed_size (local_snap)); gs_app_set_install_date (app, install_date != NULL ? g_date_time_to_unix (install_date) : GS_APP_INSTALL_DATE_UNKNOWN); snap_app = get_primary_app (local_snap); if (snap_app != NULL) { gs_app_set_metadata (app, "snap::launch-name", snapd_app_get_name (snap_app)); gs_app_set_metadata (app, "snap::launch-desktop", snapd_app_get_desktop_file (snap_app)); } else { gs_app_add_quirk (app, GS_APP_QUIRK_NOT_LAUNCHABLE); } } /* add information specific to store snaps */ if (store_snap != NULL) { gs_app_set_origin (app, priv->store_name); gs_app_set_size_download (app, snapd_snap_get_download_size (store_snap)); if (flags & GS_PLUGIN_REFINE_FLAGS_REQUIRE_SCREENSHOTS && gs_app_get_screenshots (app)->len == 0) refine_screenshots (app, store_snap); } /* load icon if requested */ if (flags & GS_PLUGIN_REFINE_FLAGS_REQUIRE_ICON && gs_app_get_pixbuf (app) == NULL) load_icon (plugin, client, app, gs_app_get_metadata_item (app, "snap::name"), local_snap, store_snap, cancellable); return TRUE; }
gboolean gs_plugin_add_distro_upgrades (GsPlugin *plugin, GsAppList *list, GCancellable *cancellable, GError **error) { GsPluginData *priv = gs_plugin_get_data (plugin); gsize len; guint i; g_autofree gchar *data = NULL; g_autoptr(GPtrArray) distros = NULL; g_autoptr(GSettings) settings = NULL; /* just ensure there is any data, no matter how old */ if (!gs_plugin_fedora_distro_upgrades_refresh (plugin, G_MAXUINT, cancellable, error)) return FALSE; /* get cached file */ if (!g_file_get_contents (priv->cachefn, &data, &len, error)) { gs_utils_error_convert_gio (error); return FALSE; } /* parse data */ settings = g_settings_new ("org.gnome.software"); distros = parse_pkgdb_collections_data (data, (gssize) len, error); if (distros == NULL) return FALSE; g_ptr_array_sort (distros, sort_distros_cb); for (i = 0; i < distros->len; i++) { DistroInfo *distro_info = g_ptr_array_index (distros, i); g_autofree gchar *app_id = NULL; g_autofree gchar *app_version = NULL; g_autofree gchar *background = NULL; g_autofree gchar *cache_key = NULL; g_autofree gchar *url = NULL; g_autofree gchar *css = NULL; g_autoptr(GsApp) app = NULL; g_autoptr(AsIcon) ic = NULL; /* only interested in upgrades to the same distro */ if (g_strcmp0 (distro_info->name, priv->os_name) != 0) continue; /* only interested in newer versions, but not more than N+2 */ if (distro_info->version <= priv->os_version || distro_info->version > priv->os_version + 2) continue; /* only interested in non-devel distros */ if (!g_settings_get_boolean (settings, "show-upgrade-prerelease")) { if (distro_info->status == DISTRO_STATUS_DEVEL) continue; } /* search in the cache */ cache_key = g_strdup_printf ("release-%u", distro_info->version); app = gs_plugin_cache_lookup (plugin, cache_key); if (app != NULL) { gs_app_list_add (list, app); continue; } app_id = g_strdup_printf ("org.fedoraproject.release-%u.upgrade", distro_info->version); app_version = g_strdup_printf ("%u", distro_info->version); /* icon from disk */ ic = as_icon_new (); as_icon_set_kind (ic, AS_ICON_KIND_LOCAL); as_icon_set_filename (ic, "/usr/share/pixmaps/fedora-logo-sprite.png"); /* create */ app = gs_app_new (app_id); gs_app_set_kind (app, AS_APP_KIND_OS_UPGRADE); gs_app_set_state (app, AS_APP_STATE_AVAILABLE); gs_app_set_name (app, GS_APP_QUALITY_LOWEST, distro_info->name); gs_app_set_summary (app, GS_APP_QUALITY_LOWEST, /* TRANSLATORS: this is a title for Fedora distro upgrades */ _("A major upgrade, with new features and added polish.")); gs_app_set_description (app, GS_APP_QUALITY_LOWEST, "Fedora Workstation is a polished, " "easy to use operating system for " "laptop and desktop computers, with a " "complete set of tools for developers " "and makers of all kinds."); gs_app_set_version (app, app_version); gs_app_set_size_installed (app, 1024 * 1024 * 1024); /* estimate */ gs_app_set_size_download (app, 256 * 1024 * 1024); /* estimate */ gs_app_set_license (app, GS_APP_QUALITY_LOWEST, "LicenseRef-free"); gs_app_add_quirk (app, AS_APP_QUIRK_NEEDS_REBOOT); gs_app_add_quirk (app, AS_APP_QUIRK_PROVENANCE); gs_app_add_quirk (app, AS_APP_QUIRK_NOT_REVIEWABLE); gs_app_set_origin_ui (app, distro_info->name); gs_app_add_icon (app, ic); gs_app_set_management_plugin (app, "packagekit"); /* show a Fedora magazine article for the release */ url = g_strdup_printf ("https://fedoramagazine.org/whats-new-fedora-%u-workstation", distro_info->version); gs_app_set_url (app, AS_URL_KIND_HOMEPAGE, url); /* use a fancy background */ background = get_upgrade_css_background (distro_info->version); css = g_strdup_printf ("background: %s;" "background-position: center;" "background-size: cover;", background); gs_app_set_metadata (app, "GnomeSoftware::UpgradeBanner-css", css); gs_app_list_add (list, app); /* save in the cache */ gs_plugin_cache_add (plugin, cache_key, app); } return TRUE; }