diff --git a/0001-Make-power-button-action-always-power-off-when-chass.patch b/0001-Make-power-button-action-always-power-off-when-chass.patch deleted file mode 100644 index baac87c95b85ce93988162b2a471866cd2b53967..0000000000000000000000000000000000000000 --- a/0001-Make-power-button-action-always-power-off-when-chass.patch +++ /dev/null @@ -1,45 +0,0 @@ -From a94fd3a1a055c55f96adb1482cb96c7a541af7dd Mon Sep 17 00:00:00 2001 -From: Felipe Borges -Date: Wed, 15 Feb 2023 15:27:59 +0100 -Subject: [PATCH] Make power-button-action always power off when chassis=server - -Servers often don't support hibernation/suspend. ---- - .../org.gnome.settings-daemon.plugins.power.gschema.xml.in | 2 +- - plugins/media-keys/gsd-media-keys-manager.c | 7 ++++--- - 2 files changed, 5 insertions(+), 4 deletions(-) - -diff --git a/data/org.gnome.settings-daemon.plugins.power.gschema.xml.in b/data/org.gnome.settings-daemon.plugins.power.gschema.xml.in -index e1a8787b..ef0ea530 100644 ---- a/data/org.gnome.settings-daemon.plugins.power.gschema.xml.in -+++ b/data/org.gnome.settings-daemon.plugins.power.gschema.xml.in -@@ -39,7 +39,7 @@ - - 'suspend' - Power button action -- The action to take when the system power button is pressed. Virtual machines only honor the 'nothing' action, and will shutdown otherwise. Tablets always suspend, ignoring all the other action options. -+ The action to take when the system power button is pressed. Virtual machines and servers only honor the 'nothing' action, and will shutdown otherwise. Tablets always suspend, ignoring all the other action options. - - - true -diff --git a/plugins/media-keys/gsd-media-keys-manager.c b/plugins/media-keys/gsd-media-keys-manager.c -index 60ff2ced..26d0e438 100644 ---- a/plugins/media-keys/gsd-media-keys-manager.c -+++ b/plugins/media-keys/gsd-media-keys-manager.c -@@ -2042,9 +2042,10 @@ do_config_power_button_action (GsdMediaKeysManager *manager, - return; - - action_type = g_settings_get_enum (priv->power_settings, "power-button-action"); -- /* Always power off VMs, except when power-button-action is "nothing" */ -- if (g_strcmp0 (priv->chassis_type, "vm") == 0) { -- g_warning_once ("Virtual machines only honor the 'nothing' power-button-action, and will shutdown otherwise"); -+ /* Always power off VMs and servers, except when power-button-action is "nothing" */ -+ if (g_strcmp0 (priv->chassis_type, "vm") == 0 || -+ g_strcmp0 (priv->chassis_type, "server")) { -+ g_warning ("Virtual machines only honor the 'nothing' power-button-action, and will shutdown otherwise"); - - if (action_type != GSD_POWER_BUTTON_ACTION_NOTHING) - power_action (manager, "PowerOff", FALSE); --- -2.37.1 - diff --git a/dist b/dist index f0303ad6bc67047392cc47112b4135cc82a0e690..89c1faffc18349bb12eee2371e9dc43bf419b95c 100644 --- a/dist +++ b/dist @@ -1 +1 @@ -an9_2 +an9 diff --git a/gnome-settings-daemon.spec b/gnome-settings-daemon.spec index 6d20cda59bceced900fbbdec22022fd446cdeba0..fb45510dc2422e73fc9848055c622a9e312a5803 100644 --- a/gnome-settings-daemon.spec +++ b/gnome-settings-daemon.spec @@ -11,52 +11,52 @@ %global tarball_version %%(echo %{version} | tr '~' '.') -Name: gnome-settings-daemon -Version: 40.0.1 -Release: 11%{anolis_release}%{?dist} -Summary: The daemon sharing settings from GNOME to GTK+/KDE applications - -License: GPLv2+ -URL: https://download.gnome.org/sources/%{name} -Source0: https://download.gnome.org/sources/%{name}/40/%{name}-%{tarball_version}.tar.xz -Source1: org.gnome.settings-daemon.plugins.power.gschema.override - -BuildRequires: meson >= 0.44.0 -BuildRequires: gcc -BuildRequires: cups-devel -BuildRequires: gettext -BuildRequires: perl-interpreter -BuildRequires: pkgconfig(alsa) -BuildRequires: pkgconfig(colord) >= %{colord_version} -BuildRequires: pkgconfig(fontconfig) -BuildRequires: pkgconfig(gcr-base-3) -BuildRequires: pkgconfig(geoclue-2.0) >= %{geoclue_version} -BuildRequires: pkgconfig(geocode-glib-1.0) >= %{geocode_glib_version} -BuildRequires: pkgconfig(glib-2.0) >= %{glib2_version} -BuildRequires: pkgconfig(gnome-desktop-3.0) >= %{gnome_desktop_version} -BuildRequires: pkgconfig(gsettings-desktop-schemas) >= %{gsettings_desktop_schemas_version} -BuildRequires: pkgconfig(gtk+-3.0) >= %{gtk3_version} -BuildRequires: pkgconfig(gudev-1.0) -BuildRequires: pkgconfig(gweather-3.0) >= %{libgweather_version} -BuildRequires: pkgconfig(json-glib-1.0) -BuildRequires: pkgconfig(lcms2) >= 2.2 -BuildRequires: pkgconfig(libcanberra-gtk3) -BuildRequires: pkgconfig(libgeoclue-2.0) -BuildRequires: pkgconfig(libnm) -BuildRequires: pkgconfig(libnotify) -BuildRequires: pkgconfig(libpulse) -BuildRequires: pkgconfig(libpulse-mainloop-glib) -BuildRequires: pkgconfig(librsvg-2.0) -BuildRequires: pkgconfig(mm-glib) -BuildRequires: pkgconfig(nss) -BuildRequires: pkgconfig(polkit-gobject-1) -BuildRequires: pkgconfig(upower-glib) -BuildRequires: pkgconfig(x11) -BuildRequires: pkgconfig(xi) -BuildRequires: pkgconfig(wayland-client) +Name: gnome-settings-daemon +Version: 40.0.1 +Release: 13%{anolis_release}%{?dist} +Summary: The daemon sharing settings from GNOME to GTK+/KDE applications + +License: GPLv2+ +URL: https://download.gnome.org/sources/%{name} +Source0: https://download.gnome.org/sources/%{name}/40/%{name}-%{tarball_version}.tar.xz +Source1: org.gnome.settings-daemon.plugins.power.gschema.override + +BuildRequires: meson >= 0.44.0 +BuildRequires: gcc +BuildRequires: cups-devel +BuildRequires: gettext +BuildRequires: perl-interpreter +BuildRequires: pkgconfig(alsa) +BuildRequires: pkgconfig(colord) >= %{colord_version} +BuildRequires: pkgconfig(fontconfig) +BuildRequires: pkgconfig(gcr-base-3) +BuildRequires: pkgconfig(geoclue-2.0) >= %{geoclue_version} +BuildRequires: pkgconfig(geocode-glib-1.0) >= %{geocode_glib_version} +BuildRequires: pkgconfig(glib-2.0) >= %{glib2_version} +BuildRequires: pkgconfig(gnome-desktop-3.0) >= %{gnome_desktop_version} +BuildRequires: pkgconfig(gsettings-desktop-schemas) >= %{gsettings_desktop_schemas_version} +BuildRequires: pkgconfig(gtk+-3.0) >= %{gtk3_version} +BuildRequires: pkgconfig(gudev-1.0) +BuildRequires: pkgconfig(gweather-3.0) >= %{libgweather_version} +#BuildRequires: pkgconfig(json-glib-1.0) +BuildRequires: pkgconfig(lcms2) >= 2.2 +BuildRequires: pkgconfig(libcanberra-gtk3) +BuildRequires: pkgconfig(libgeoclue-2.0) +BuildRequires: pkgconfig(libnm) +BuildRequires: pkgconfig(libnotify) +BuildRequires: pkgconfig(libpulse) +BuildRequires: pkgconfig(libpulse-mainloop-glib) +BuildRequires: pkgconfig(librsvg-2.0) +BuildRequires: pkgconfig(mm-glib) +BuildRequires: pkgconfig(nss) +BuildRequires: pkgconfig(polkit-gobject-1) +BuildRequires: pkgconfig(upower-glib) +BuildRequires: pkgconfig(x11) +BuildRequires: pkgconfig(xi) +BuildRequires: pkgconfig(wayland-client) %ifnarch s390 s390x -BuildRequires: pkgconfig(libwacom) >= 0.7 -BuildRequires: pkgconfig(xorg-wacom) +BuildRequires: pkgconfig(libwacom) >= 0.7 +BuildRequires: pkgconfig(xorg-wacom) %endif Requires: colord >= %{colord_version} @@ -71,7 +71,7 @@ Requires: libgweather%{?_isa} >= %{libgweather_version} Requires: glibc Patch00001: 0001-power-Enable-power-saver-profile-when-low-on-battery.patch -Patch00002: subscription-manager-support.patch +#Patch00002: subscription-manager-support.patch Patch00003: im-module-setting-fix.patch Patch00004: print-notifications-clear-in-stop.patch Patch00005: 0001-power-Respect-the-nothing-power-button-action-for-VM.patch @@ -82,8 +82,8 @@ A daemon to share settings from GNOME to other applications. It also handles global keybindings, as well as a number of desktop-wide settings. %package devel -Summary: Development files for %{name} -Requires: %{name}%{?_isa} = %{version}-%{release} +Summary: Development files for %{name} +Requires: %{name}%{?_isa} = %{version}-%{release} %description devel The %{name}-devel package contains libraries and header files for @@ -185,11 +185,11 @@ cp %{SOURCE1} $RPM_BUILD_ROOT%{_datadir}/glib-2.0/schemas %{_libexecdir}/gsd-wwan %{_datadir}/glib-2.0/schemas/org.gnome.settings-daemon.plugins.wwan.gschema.xml -%{_sysconfdir}/xdg/autostart/org.gnome.SettingsDaemon.Subscription.desktop -%{_libexecdir}/gsd-subman -%{_libexecdir}/gsd-subman-helper -%{_datadir}/polkit-1/actions/org.gnome.settings-daemon.plugins.subman.policy -%{_datadir}/polkit-1/rules.d/org.gnome.settings-daemon.plugins.subman.rules +#{_sysconfdir}/xdg/autostart/org.gnome.SettingsDaemon.Subscription.desktop +#{_libexecdir}/gsd-subman +#{_libexecdir}/gsd-subman-helper +#{_datadir}/polkit-1/actions/org.gnome.settings-daemon.plugins.subman.policy +#{_datadir}/polkit-1/rules.d/org.gnome.settings-daemon.plugins.subman.rules %dir %{_libdir}/gnome-settings-daemon-40 %{_libdir}/gnome-settings-daemon-40/libgsd.so @@ -211,10 +211,18 @@ cp %{SOURCE1} $RPM_BUILD_ROOT%{_datadir}/glib-2.0/schemas %doc AUTHORS NEWS %changelog -* Mon Jul 24 2023 Zhao Hang - 40.0.1-11.0.1 +* Tue Dec 12 2023 Zhao Hang - 40.0.1-13.0.1 - Add doc sub package - Modify systemd buildrequirement to version 239 and rebuild with systemd-239 () +* Fri Jun 16 2023 Ray Strode - 40.0.1-13 +- Revert hard dependency on subscription-manager since we're going to put it in gnome-session instead + Related: #2175675 + +* Thu May 04 2023 Ray Strode - 40.0.1-12 +- Add hard dependency on subscription-manager + Resolves: #2175675 + * Tue Mar 28 2023 Felipe Borges - 40.0.1-11 - Revert "power-button-action" always poweroff on Server chassis Resolves: #2182380 @@ -1269,7 +1277,7 @@ cp %{SOURCE1} $RPM_BUILD_ROOT%{_datadir}/glib-2.0/schemas * Fri May 08 2009 Bastien Nocera 2.26.1-4 - Remove useless patch, see: -http://bugzilla.gnome.org/show_bug.cgi?id=580761 for details +http: //bugzilla.gnome.org/show_bug.cgi?id=580761 for details * Wed Apr 29 2009 Bastien Nocera 2.26.1-3 - Don't set touchpads to be left-handed, otherwise the tap diff --git a/subscription-manager-support.patch b/subscription-manager-support.patch deleted file mode 100644 index a098a558390a004ad8f4197b161ed4c843e2a150..0000000000000000000000000000000000000000 --- a/subscription-manager-support.patch +++ /dev/null @@ -1,3612 +0,0 @@ -From f73e1e8187570ddbc2fe40a78176689f12859123 Mon Sep 17 00:00:00 2001 -From: Richard Hughes -Date: Thu, 20 Aug 2020 11:16:09 -0400 -Subject: [PATCH 01/20] subman: Add a new plugin to provide system subscription - registration - ---- - meson.build | 1 + - plugins/meson.build | 1 + - plugins/subman/README.md | 56 + - plugins/subman/gsd-subman-common.c | 36 + - plugins/subman/gsd-subman-common.h | 40 + - plugins/subman/gsd-subman-helper.c | 372 +++++++ - plugins/subman/gsd-subscription-manager.c | 982 ++++++++++++++++++ - plugins/subman/gsd-subscription-manager.h | 63 ++ - plugins/subman/main.c | 8 + - plugins/subman/meson.build | 56 + - ...ome.SettingsDaemon.Subscription.desktop.in | 9 + - ...ettings-daemon.plugins.subman.policy.in.in | 27 + - ...gnome.settings-daemon.plugins.subman.rules | 7 + - 13 files changed, 1658 insertions(+) - create mode 100644 plugins/subman/README.md - create mode 100644 plugins/subman/gsd-subman-common.c - create mode 100644 plugins/subman/gsd-subman-common.h - create mode 100644 plugins/subman/gsd-subman-helper.c - create mode 100644 plugins/subman/gsd-subscription-manager.c - create mode 100644 plugins/subman/gsd-subscription-manager.h - create mode 100644 plugins/subman/main.c - create mode 100644 plugins/subman/meson.build - create mode 100644 plugins/subman/org.gnome.SettingsDaemon.Subscription.desktop.in - create mode 100644 plugins/subman/org.gnome.settings-daemon.plugins.subman.policy.in.in - create mode 100644 plugins/subman/org.gnome.settings-daemon.plugins.subman.rules - -diff --git a/meson.build b/meson.build -index ba2a90ca..3cef1ae1 100644 ---- a/meson.build -+++ b/meson.build -@@ -102,6 +102,7 @@ libcanberra_gtk_dep = dependency('libcanberra-gtk3') - libgeoclue_dep = dependency('libgeoclue-2.0', version: '>= 2.3.1') - libnotify_dep = dependency('libnotify', version: '>= 0.7.3') - libpulse_mainloop_glib_dep = dependency('libpulse-mainloop-glib', version: '>= 2.0') -+jsonglib_dep = dependency('json-glib-1.0', version: '>= 1.1.1') - pango_dep = dependency('pango', version: '>= 1.20.0') - polkit_gobject_dep = dependency('polkit-gobject-1', version: '>= 0.114') - upower_glib_dep = dependency('upower-glib', version: '>= 0.99.8') -diff --git a/plugins/meson.build b/plugins/meson.build -index 16397dc6..920b5cc9 100644 ---- a/plugins/meson.build -+++ b/plugins/meson.build -@@ -1,6 +1,7 @@ - all_plugins = [ - ['a11y-settings', 'A11ySettings', 'GNOME accessibility'], - ['color', 'Color', 'GNOME color management'], -+ ['subman', 'Subscription', 'GNOME subscription management'], - ['datetime', 'Datetime', 'GNOME date & time'], - ['power', 'Power', 'GNOME power management'], - ['housekeeping', 'Housekeeping', 'GNOME maintenance of expirable data'], -diff --git a/plugins/subman/README.md b/plugins/subman/README.md -new file mode 100644 -index 00000000..3e1cc3cd ---- /dev/null -+++ b/plugins/subman/README.md -@@ -0,0 +1,56 @@ -+GNOME Settings Daemon: Subscription Manager Plugin -+================================================== -+ -+Testing: -+ -+To add a test acccount on subscription.rhsm.stage.redhat.com, use Ethel: -+http://account-manager-stage.app.eng.rdu2.redhat.com/#view -+ -+Register with a username and password -+------------------------------------- -+ -+ gdbus call \ -+ --session \ -+ --dest org.gnome.SettingsDaemon.Subscription \ -+ --object-path /org/gnome/SettingsDaemon/Subscription \ -+ --method org.gnome.SettingsDaemon.Subscription.Register "{'kind':<'username'>,'hostname':<'subscription.rhsm.stage.redhat.com'>,'username':<'rhughes_test'>,'password':<'barbaz'>}" -+ -+To register with a certificate -+------------------------------ -+ -+ gdbus call \ -+ --session \ -+ --dest org.gnome.SettingsDaemon.Subscription \ -+ --object-path /org/gnome/SettingsDaemon/Subscription \ -+ --method org.gnome.SettingsDaemon.Subscription.Register "{'kind':<'key'>,'hostname':<'subscription.rhsm.stage.redhat.com'>,'organisation':<'foo'>,'activation-key':<'barbaz'>}" -+ -+To unregister -+------------- -+ -+ gdbus call \ -+ --session \ -+ --dest org.gnome.SettingsDaemon.Subscription \ -+ --object-path /org/gnome/SettingsDaemon/Subscription \ -+ --method org.gnome.SettingsDaemon.Subscription.Unregister -+ -+Debugging -+--------- -+ -+Get the UNIX socket using `Subscription.Register` then call something like: -+ -+ sudo G_MESSAGES_DEBUG=all ./plugins/subman/gsd-subman-helper \ -+ --address="unix:abstract=/var/run/dbus-ulGB1wfnbn,guid=71e6bf329d861ce366df7a1d5d036a5b" \ -+ --kind="register-with-username" \ -+ --username="rhughes_test" \ -+ --password="barbaz" \ -+ --hostname="subscription.rhsm.stage.redhat.com" \ -+ --organisation="" -+ -+You can all see some basic debugging running `rhsmd` in the foreground: -+ -+ sudo /usr/libexec/rhsmd -d -k -+ -+Known Limitations -+================= -+ -+Proxy servers are not supported, nor are custom host ports or prefixes. -diff --git a/plugins/subman/gsd-subman-common.c b/plugins/subman/gsd-subman-common.c -new file mode 100644 -index 00000000..e515131e ---- /dev/null -+++ b/plugins/subman/gsd-subman-common.c -@@ -0,0 +1,36 @@ -+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- -+ * -+ * Copyright (C) 2019 Richard Hughes -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, see . -+ * -+ */ -+ -+#include "config.h" -+ -+#include "gsd-subman-common.h" -+ -+const gchar * -+gsd_subman_subscription_status_to_string (GsdSubmanSubscriptionStatus status) -+{ -+ if (status == GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID) -+ return "valid"; -+ if (status == GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID) -+ return "invalid"; -+ if (status == GSD_SUBMAN_SUBSCRIPTION_STATUS_DISABLED) -+ return "disabled"; -+ if (status == GSD_SUBMAN_SUBSCRIPTION_STATUS_PARTIALLY_VALID) -+ return "partially-valid"; -+ return "unknown"; -+} -diff --git a/plugins/subman/gsd-subman-common.h b/plugins/subman/gsd-subman-common.h -new file mode 100644 -index 00000000..fccf9f6a ---- /dev/null -+++ b/plugins/subman/gsd-subman-common.h -@@ -0,0 +1,40 @@ -+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- -+ * -+ * Copyright (C) 2019 Richard Hughes -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, see . -+ * -+ */ -+ -+#ifndef __GSD_SUBMAN_COMMON_H -+#define __GSD_SUBMAN_COMMON_H -+ -+#include -+ -+G_BEGIN_DECLS -+ -+typedef enum { -+ GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN, -+ GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID, -+ GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID, -+ GSD_SUBMAN_SUBSCRIPTION_STATUS_DISABLED, -+ GSD_SUBMAN_SUBSCRIPTION_STATUS_PARTIALLY_VALID, -+ GSD_SUBMAN_SUBSCRIPTION_STATUS_LAST -+} GsdSubmanSubscriptionStatus; -+ -+const gchar *gsd_subman_subscription_status_to_string (GsdSubmanSubscriptionStatus status); -+ -+G_END_DECLS -+ -+#endif /* __GSD_SUBMAN_COMMON_H */ -diff --git a/plugins/subman/gsd-subman-helper.c b/plugins/subman/gsd-subman-helper.c -new file mode 100644 -index 00000000..69ebec7e ---- /dev/null -+++ b/plugins/subman/gsd-subman-helper.c -@@ -0,0 +1,372 @@ -+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- -+ * -+ * Copyright (C) 2019 Richard Hughes -+ * -+ * Licensed under the GNU General Public License Version 2 -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -+ */ -+ -+#include "config.h" -+ -+#include -+#include -+#include -+ -+#include -+#include -+ -+static void -+_helper_convert_error (const gchar *json_txt, GError **error) -+{ -+ JsonNode *json_root; -+ JsonObject *json_obj; -+ const gchar *message; -+ g_autoptr(JsonParser) json_parser = json_parser_new (); -+ -+ /* this may be plain text or JSON :| */ -+ if (!json_parser_load_from_data (json_parser, json_txt, -1, NULL)) { -+ g_set_error_literal (error, -+ G_IO_ERROR, -+ G_IO_ERROR_NOT_SUPPORTED, -+ json_txt); -+ return; -+ } -+ json_root = json_parser_get_root (json_parser); -+ json_obj = json_node_get_object (json_root); -+ if (!json_object_has_member (json_obj, "message")) { -+ g_set_error (error, -+ G_IO_ERROR, -+ G_IO_ERROR_INVALID_DATA, -+ "no message' in %s", json_txt); -+ return; -+ } -+ message = json_object_get_string_member (json_obj, "message"); -+ if (g_strstr_len (message, -1, "Invalid user credentials") != NULL) { -+ g_set_error_literal (error, -+ G_IO_ERROR, -+ G_IO_ERROR_PERMISSION_DENIED, -+ message); -+ return; -+ } -+ g_set_error_literal (error, -+ G_IO_ERROR, -+ G_IO_ERROR_NOT_SUPPORTED, -+ message); -+} -+ -+static gboolean -+_helper_unregister (GError **error) -+{ -+ g_autoptr(GDBusProxy) proxy = NULL; -+ g_autoptr(GVariantBuilder) proxy_options = NULL; -+ g_autoptr(GVariant) res = NULL; -+ -+ g_debug ("unregistering"); -+ proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, -+ G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | -+ G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, -+ NULL, -+ "com.redhat.RHSM1", -+ "/com/redhat/RHSM1/Unregister", -+ "com.redhat.RHSM1.Unregister", -+ NULL, error); -+ if (proxy == NULL) { -+ g_prefix_error (error, "Failed to get proxy: "); -+ return FALSE; -+ } -+ proxy_options = g_variant_builder_new (G_VARIANT_TYPE_VARDICT); -+ res = g_dbus_proxy_call_sync (proxy, -+ "Unregister", -+ g_variant_new ("(a{sv}s)", -+ proxy_options, -+ ""), /* lang */ -+ G_DBUS_CALL_FLAGS_NONE, -+ -1, NULL, error); -+ return res != NULL; -+} -+ -+static gboolean -+_helper_auto_attach (GError **error) -+{ -+ const gchar *str = NULL; -+ g_autoptr(GDBusProxy) proxy = NULL; -+ g_autoptr(GVariantBuilder) proxy_options = NULL; -+ g_autoptr(GVariant) res = NULL; -+ -+ g_debug ("auto-attaching subscriptions"); -+ proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, -+ G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | -+ G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, -+ NULL, -+ "com.redhat.RHSM1", -+ "/com/redhat/RHSM1/Attach", -+ "com.redhat.RHSM1.Attach", -+ NULL, error); -+ if (proxy == NULL) { -+ g_prefix_error (error, "Failed to get proxy: "); -+ return FALSE; -+ } -+ proxy_options = g_variant_builder_new (G_VARIANT_TYPE_VARDICT); -+ res = g_dbus_proxy_call_sync (proxy, -+ "AutoAttach", -+ g_variant_new ("(sa{sv}s)", -+ "", /* now? */ -+ proxy_options, -+ ""), /* lang */ -+ G_DBUS_CALL_FLAGS_NONE, -+ -1, NULL, error); -+ if (res == NULL) -+ return FALSE; -+ g_variant_get (res, "(&s)", &str); -+ g_debug ("Attach.AutoAttach: %s", str); -+ return TRUE; -+} -+ -+static gboolean -+_helper_save_config (const gchar *key, const gchar *value, GError **error) -+{ -+ g_autoptr(GDBusProxy) proxy = NULL; -+ g_autoptr(GVariant) res = NULL; -+ proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, -+ G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | -+ G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, -+ NULL, -+ "com.redhat.RHSM1", -+ "/com/redhat/RHSM1/Config", -+ "com.redhat.RHSM1.Config", -+ NULL, error); -+ if (proxy == NULL) { -+ g_prefix_error (error, "Failed to get proxy: "); -+ return FALSE; -+ } -+ res = g_dbus_proxy_call_sync (proxy, "Set", -+ g_variant_new ("(svs)", -+ key, -+ g_variant_new_string (value), -+ ""), /* lang */ -+ G_DBUS_CALL_FLAGS_NONE, -+ -1, NULL, error); -+ return res != NULL; -+} -+ -+int -+main (int argc, char *argv[]) -+{ -+ const gchar *userlang = ""; /* as root, so no translations */ -+ g_autofree gchar *activation_key = NULL; -+ g_autofree gchar *address = NULL; -+ g_autofree gchar *hostname = NULL; -+ g_autofree gchar *kind = NULL; -+ g_autofree gchar *organisation = NULL; -+ g_autofree gchar *password = NULL; -+ g_autofree gchar *port = NULL; -+ g_autofree gchar *prefix = NULL; -+ g_autofree gchar *proxy_server = NULL; -+ g_autofree gchar *username = NULL; -+ g_autoptr(GDBusConnection) conn_private = NULL; -+ g_autoptr(GDBusProxy) proxy = NULL; -+ g_autoptr(GError) error = NULL; -+ g_autoptr(GOptionContext) context = g_option_context_new (NULL); -+ g_autoptr(GVariantBuilder) proxy_options = NULL; -+ g_autoptr(GVariantBuilder) subman_conopts = NULL; -+ g_autoptr(GVariantBuilder) subman_options = NULL; -+ -+ const GOptionEntry options[] = { -+ { "kind", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, -+ &kind, "Kind, e.g. 'username' or 'key'", NULL }, -+ { "address", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, -+ &address, "UNIX address", NULL }, -+ { "username", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, -+ &username, "Username", NULL }, -+ { "password", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, -+ &password, "Password", NULL }, -+ { "organisation", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, -+ &organisation, "Organisation", NULL }, -+ { "activation-key", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, -+ &activation_key, "Activation keys", NULL }, -+ { "hostname", '\0', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, -+ &hostname, "Registration server hostname", NULL }, -+ { "prefix", '\0', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, -+ &prefix, "Registration server prefix", NULL }, -+ { "port", '\0', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, -+ &port, "Registration server port", NULL }, -+ { "proxy", '\0', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, -+ &proxy_server, "Proxy settings", NULL }, -+ { NULL} -+ }; -+ -+ /* check calling UID */ -+ if (getuid () != 0 || geteuid () != 0) { -+ g_printerr ("This program can only be used by the root user\n"); -+ return G_IO_ERROR_NOT_SUPPORTED; -+ } -+ g_option_context_add_main_entries (context, options, NULL); -+ if (!g_option_context_parse (context, &argc, &argv, &error)) { -+ g_printerr ("Failed to parse arguments: %s\n", error->message); -+ return G_IO_ERROR_NOT_SUPPORTED; -+ } -+ -+ /* uncommon actions */ -+ if (kind == NULL) { -+ g_printerr ("No --kind specified\n"); -+ return G_IO_ERROR_INVALID_DATA; -+ } -+ if (g_strcmp0 (kind, "unregister") == 0) { -+ if (!_helper_unregister (&error)) { -+ g_printerr ("Failed to Unregister: %s\n", error->message); -+ return G_IO_ERROR_NOT_INITIALIZED; -+ } -+ return EXIT_SUCCESS; -+ } -+ if (g_strcmp0 (kind, "auto-attach") == 0) { -+ if (!_helper_auto_attach (&error)) { -+ g_printerr ("Failed to AutoAttach: %s\n", error->message); -+ return G_IO_ERROR_NOT_INITIALIZED; -+ } -+ return EXIT_SUCCESS; -+ } -+ -+ /* connect to abstract socket for reasons */ -+ if (address == NULL) { -+ g_printerr ("No --address specified\n"); -+ return G_IO_ERROR_INVALID_DATA; -+ } -+ conn_private = g_dbus_connection_new_for_address_sync (address, -+ G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT, -+ NULL, NULL, -+ &error); -+ if (conn_private == NULL) { -+ g_printerr ("Invalid --address specified: %s\n", error->message); -+ return G_IO_ERROR_INVALID_DATA; -+ } -+ proxy = g_dbus_proxy_new_sync (conn_private, -+ G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, -+ NULL, /* GDBusInterfaceInfo */ -+ NULL, /* name */ -+ "/com/redhat/RHSM1/Register", -+ "com.redhat.RHSM1.Register", -+ NULL, &error); -+ if (proxy == NULL) { -+ g_printerr ("Count not contact RHSM: %s\n", error->message); -+ return G_IO_ERROR_NOT_FOUND; -+ } -+ -+ /* enable_content=1 auto attaches the subscription */ -+ subman_options = g_variant_builder_new (G_VARIANT_TYPE("a{ss}")); -+ -+ g_variant_builder_add (subman_options, "{ss}", "enable_content", "1"); -+ -+ /* set registration server */ -+ if (hostname == NULL || hostname[0] == '\0') -+ hostname = g_strdup ("subscription.rhsm.redhat.com"); -+ if (prefix == NULL || prefix[0] == '\0') -+ prefix = g_strdup ("/subscription"); -+ if (port == NULL || port[0] == '\0') -+ port = g_strdup ("443"); -+ subman_conopts = g_variant_builder_new (G_VARIANT_TYPE("a{ss}")); -+ g_variant_builder_add (subman_conopts, "{ss}", "host", hostname); -+ g_variant_builder_add (subman_conopts, "{ss}", "handler", prefix); -+ g_variant_builder_add (subman_conopts, "{ss}", "port", port); -+ -+ /* call into RHSM */ -+ if (g_strcmp0 (kind, "register-with-key") == 0) { -+ g_auto(GStrv) activation_keys = NULL; -+ g_autoptr(GError) error_local = NULL; -+ g_autoptr(GVariant) res = NULL; -+ -+ if (activation_key == NULL) { -+ g_printerr ("Required --activation-key\n"); -+ return G_IO_ERROR_INVALID_DATA; -+ } -+ if (organisation == NULL) { -+ g_printerr ("Required --organisation\n"); -+ return G_IO_ERROR_INVALID_DATA; -+ } -+ -+ g_debug ("registering using activation key"); -+ activation_keys = g_strsplit (activation_key, ",", -1); -+ res = g_dbus_proxy_call_sync (proxy, -+ "RegisterWithActivationKeys", -+ g_variant_new ("(s^asa{ss}a{ss}s)", -+ organisation, -+ activation_keys, -+ subman_options, -+ subman_conopts, -+ userlang), -+ G_DBUS_CALL_FLAGS_NO_AUTO_START, -+ -1, NULL, &error_local); -+ if (res == NULL) { -+ g_dbus_error_strip_remote_error (error_local); -+ _helper_convert_error (error_local->message, &error); -+ g_printerr ("Failed to RegisterWithActivationKeys: %s\n", error->message); -+ return error->code; -+ } -+ } else if (g_strcmp0 (kind, "register-with-username") == 0) { -+ g_autoptr(GError) error_local = NULL; -+ g_autoptr(GVariant) res = NULL; -+ -+ g_debug ("registering using username and password"); -+ if (username == NULL) { -+ g_printerr ("Required --username\n"); -+ return G_IO_ERROR_INVALID_DATA; -+ } -+ if (password == NULL) { -+ g_printerr ("Required --password\n"); -+ return G_IO_ERROR_INVALID_DATA; -+ } -+ if (organisation == NULL) { -+ g_printerr ("Required --organisation\n"); -+ return G_IO_ERROR_INVALID_DATA; -+ } -+ res = g_dbus_proxy_call_sync (proxy, -+ "Register", -+ g_variant_new ("(sssa{ss}a{ss}s)", -+ organisation, -+ username, -+ password, -+ subman_options, -+ subman_conopts, -+ userlang), -+ G_DBUS_CALL_FLAGS_NO_AUTO_START, -+ -1, NULL, &error_local); -+ if (res == NULL) { -+ g_dbus_error_strip_remote_error (error_local); -+ _helper_convert_error (error_local->message, &error); -+ g_printerr ("Failed to Register: %s\n", error->message); -+ return error->code; -+ } -+ } else { -+ g_printerr ("Invalid --kind specified: %s\n", kind); -+ return G_IO_ERROR_INVALID_DATA; -+ } -+ -+ /* set the new hostname */ -+ if (!_helper_save_config ("server.hostname", hostname, &error)) { -+ g_printerr ("Failed to save hostname: %s\n", error->message); -+ return G_IO_ERROR_NOT_INITIALIZED; -+ } -+ if (!_helper_save_config ("server.prefix", prefix, &error)) { -+ g_printerr ("Failed to save prefix: %s\n", error->message); -+ return G_IO_ERROR_NOT_INITIALIZED; -+ } -+ if (!_helper_save_config ("server.port", port, &error)) { -+ g_printerr ("Failed to save port: %s\n", error->message); -+ return G_IO_ERROR_NOT_INITIALIZED; -+ } -+ -+ return EXIT_SUCCESS; -+} -+ -diff --git a/plugins/subman/gsd-subscription-manager.c b/plugins/subman/gsd-subscription-manager.c -new file mode 100644 -index 00000000..08b13fa6 ---- /dev/null -+++ b/plugins/subman/gsd-subscription-manager.c -@@ -0,0 +1,982 @@ -+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- -+ * -+ * Copyright (C) 2019 Richard Hughes -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, see . -+ * -+ */ -+ -+#include "config.h" -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include "gnome-settings-profile.h" -+#include "gsd-subman-common.h" -+#include "gsd-subscription-manager.h" -+ -+#define GSD_DBUS_NAME "org.gnome.SettingsDaemon" -+#define GSD_DBUS_PATH "/org/gnome/SettingsDaemon" -+#define GSD_DBUS_BASE_INTERFACE "org.gnome.SettingsDaemon" -+ -+#define GSD_SUBSCRIPTION_DBUS_NAME GSD_DBUS_NAME ".Subscription" -+#define GSD_SUBSCRIPTION_DBUS_PATH GSD_DBUS_PATH "/Subscription" -+#define GSD_SUBSCRIPTION_DBUS_INTERFACE GSD_DBUS_BASE_INTERFACE ".Subscription" -+ -+static const gchar introspection_xml[] = -+"" -+" " -+" " -+" " -+" " -+" " -+" " -+" " -+""; -+ -+#define GSD_SUBSCRIPTION_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_SUBSCRIPTION_MANAGER, GsdSubscriptionManagerPrivate)) -+ -+typedef enum { -+ _RHSM_INTERFACE_CONFIG, -+ _RHSM_INTERFACE_REGISTER_SERVER, -+ _RHSM_INTERFACE_ATTACH, -+ _RHSM_INTERFACE_ENTITLEMENT, -+ _RHSM_INTERFACE_PRODUCTS, -+ _RHSM_INTERFACE_CONSUMER, -+ _RHSM_INTERFACE_SYSPURPOSE, -+ _RHSM_INTERFACE_LAST -+} _RhsmInterface; -+ -+struct GsdSubscriptionManagerPrivate -+{ -+ /* D-Bus */ -+ guint name_id; -+ GDBusNodeInfo *introspection_data; -+ GDBusConnection *connection; -+ GCancellable *bus_cancellable; -+ -+ GDBusProxy *proxies[_RHSM_INTERFACE_LAST]; -+ const gchar *userlang; /* owned by GLib internally */ -+ GHashTable *config; /* str:str */ -+ gchar *address; -+ -+ GTimer *timer_last_notified; -+ NotifyNotification *notification_expired; -+ NotifyNotification *notification_registered; -+ NotifyNotification *notification_registration_required; -+ GsdSubmanSubscriptionStatus subscription_status; -+ GsdSubmanSubscriptionStatus subscription_status_last; -+}; -+ -+enum { -+ PROP_0, -+}; -+ -+static void gsd_subscription_manager_class_init (GsdSubscriptionManagerClass *klass); -+static void gsd_subscription_manager_init (GsdSubscriptionManager *subscription_manager); -+static void gsd_subscription_manager_finalize (GObject *object); -+ -+G_DEFINE_TYPE (GsdSubscriptionManager, gsd_subscription_manager, G_TYPE_OBJECT) -+ -+static gpointer manager_object = NULL; -+ -+GQuark -+gsd_subscription_manager_error_quark (void) -+{ -+ static GQuark quark = 0; -+ if (!quark) -+ quark = g_quark_from_static_string ("gsd_subscription_manager_error"); -+ return quark; -+} -+ -+static GsdSubmanSubscriptionStatus -+_client_subscription_status_from_text (const gchar *status_txt) -+{ -+ if (g_strcmp0 (status_txt, "Unknown") == 0) -+ return GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN; -+ if (g_strcmp0 (status_txt, "Current") == 0) -+ return GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID; -+ if (g_strcmp0 (status_txt, "Invalid") == 0) -+ return GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID; -+ if (g_strcmp0 (status_txt, "Disabled") == 0) -+ return GSD_SUBMAN_SUBSCRIPTION_STATUS_DISABLED; -+ if (g_strcmp0 (status_txt, "Insufficient") == 0) -+ return GSD_SUBMAN_SUBSCRIPTION_STATUS_PARTIALLY_VALID; -+ g_warning ("Unknown subscription status: %s", status_txt); // 'Current'? -+ return GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN; -+} -+ -+static void -+_emit_property_changed (GsdSubscriptionManager *manager, -+ const gchar *property_name, -+ GVariant *property_value) -+{ -+ GsdSubscriptionManagerPrivate *priv = manager->priv; -+ GVariantBuilder builder; -+ GVariantBuilder invalidated_builder; -+ -+ /* not yet connected */ -+ if (priv->connection == NULL) -+ return; -+ -+ /* build the dict */ -+ g_variant_builder_init (&invalidated_builder, G_VARIANT_TYPE ("as")); -+ g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY); -+ g_variant_builder_add (&builder, -+ "{sv}", -+ property_name, -+ property_value); -+ g_dbus_connection_emit_signal (priv->connection, -+ NULL, -+ GSD_SUBSCRIPTION_DBUS_PATH, -+ "org.freedesktop.DBus.Properties", -+ "PropertiesChanged", -+ g_variant_new ("(sa{sv}as)", -+ GSD_SUBSCRIPTION_DBUS_INTERFACE, -+ &builder, -+ &invalidated_builder), -+ NULL); -+ g_variant_builder_clear (&builder); -+ g_variant_builder_clear (&invalidated_builder); -+} -+ -+static gboolean -+_client_subscription_status_update (GsdSubscriptionManager *manager, GError **error) -+{ -+ GsdSubscriptionManagerPrivate *priv = manager->priv; -+ JsonNode *json_root; -+ JsonObject *json_obj; -+ const gchar *json_txt = NULL; -+ const gchar *status_txt = NULL; -+ g_autoptr(GVariant) val = NULL; -+ g_autoptr(JsonParser) json_parser = json_parser_new (); -+ -+ /* save old value */ -+ priv->subscription_status_last = priv->subscription_status; -+ -+ val = g_dbus_proxy_call_sync (priv->proxies[_RHSM_INTERFACE_ENTITLEMENT], -+ "GetStatus", -+ g_variant_new ("(ss)", -+ "", /* assumed as 'now' */ -+ priv->userlang), -+ G_DBUS_CALL_FLAGS_NONE, -+ -1, NULL, error); -+ if (val == NULL) -+ return FALSE; -+ g_variant_get (val, "(&s)", &json_txt); -+ g_debug ("Entitlement.GetStatus JSON: %s", json_txt); -+ if (!json_parser_load_from_data (json_parser, json_txt, -1, error)) -+ return FALSE; -+ json_root = json_parser_get_root (json_parser); -+ json_obj = json_node_get_object (json_root); -+ if (!json_object_has_member (json_obj, "status")) { -+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, -+ "no Entitlement.GetStatus status in %s", json_txt); -+ return FALSE; -+ } -+ -+ status_txt = json_object_get_string_member (json_obj, "status"); -+ g_debug ("Entitlement.GetStatus: %s", status_txt); -+ priv->subscription_status = _client_subscription_status_from_text (status_txt); -+ -+ /* emit notification for g-c-c */ -+ if (priv->subscription_status != priv->subscription_status_last) { -+ _emit_property_changed (manager, "SubscriptionStatus", -+ g_variant_new_uint32 (priv->subscription_status)); -+ } -+ -+ return TRUE; -+} -+ -+static gboolean -+_client_syspurpose_update (GsdSubscriptionManager *manager, GError **error) -+{ -+ GsdSubscriptionManagerPrivate *priv = manager->priv; -+ JsonNode *json_root; -+ JsonObject *json_obj; -+ const gchar *json_txt = NULL; -+ g_autoptr(GVariant) val = NULL; -+ g_autoptr(JsonParser) json_parser = json_parser_new (); -+ -+ val = g_dbus_proxy_call_sync (priv->proxies[_RHSM_INTERFACE_SYSPURPOSE], -+ "GetSyspurpose", -+ g_variant_new ("(s)", priv->userlang), -+ G_DBUS_CALL_FLAGS_NONE, -+ -1, NULL, error); -+ if (val == NULL) -+ return FALSE; -+ g_variant_get (val, "(&s)", &json_txt); -+ g_debug ("Syspurpose.GetSyspurpose JSON: %s", json_txt); -+ if (!json_parser_load_from_data (json_parser, json_txt, -1, error)) -+ return FALSE; -+ json_root = json_parser_get_root (json_parser); -+ json_obj = json_node_get_object (json_root); -+ if (!json_object_has_member (json_obj, "status")) { -+ g_debug ("Syspurpose.GetSyspurpose: Unknown"); -+ return TRUE; -+ } -+ g_debug ("Syspurpose.GetSyspurpose: '%s", json_object_get_string_member (json_obj, "status")); -+ return TRUE; -+} -+ -+static gboolean -+_client_register_start (GsdSubscriptionManager *manager, GError **error) -+{ -+ GsdSubscriptionManagerPrivate *priv = manager->priv; -+ const gchar *address = NULL; -+ g_autoptr(GDBusProxy) proxy = NULL; -+ g_autoptr(GVariant) val = NULL; -+ -+ /* already started */ -+ if (priv->address != NULL) -+ return TRUE; -+ -+ /* apparently: "we can't send registration credentials over the regular -+ * system or session bus since those aren't really locked down..." */ -+ proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, -+ G_DBUS_PROXY_FLAGS_NONE, -+ NULL, -+ "com.redhat.RHSM1", -+ "/com/redhat/RHSM1/RegisterServer", -+ "com.redhat.RHSM1.RegisterServer", -+ NULL, error); -+ if (proxy == NULL) -+ return FALSE; -+ val = g_dbus_proxy_call_sync (proxy, "Start", -+ g_variant_new ("(s)", priv->userlang), -+ G_DBUS_CALL_FLAGS_NONE, -+ -1, NULL, error); -+ if (val == NULL) -+ return FALSE; -+ g_variant_get (val, "(&s)", &address); -+ g_debug ("RegisterServer.Start: %s", address); -+ priv->address = g_strdup (address); -+ return TRUE; -+} -+ -+static gboolean -+_client_register_stop (GsdSubscriptionManager *manager, GError **error) -+{ -+ GsdSubscriptionManagerPrivate *priv = manager->priv; -+ g_autoptr(GDBusProxy) proxy = NULL; -+ g_autoptr(GVariant) val = NULL; -+ -+ /* already started */ -+ if (priv->address == NULL) -+ return TRUE; -+ -+ /* stop registration server */ -+ proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, -+ G_DBUS_PROXY_FLAGS_NONE, -+ NULL, -+ "com.redhat.RHSM1", -+ "/com/redhat/RHSM1/RegisterServer", -+ "com.redhat.RHSM1.RegisterServer", -+ NULL, error); -+ if (proxy == NULL) -+ return FALSE; -+ val = g_dbus_proxy_call_sync (proxy, "Stop", -+ g_variant_new ("(s)", priv->userlang), -+ G_DBUS_CALL_FLAGS_NONE, -+ -1, NULL, error); -+ if (val == NULL) -+ return FALSE; -+ g_clear_pointer (&priv->address, g_free); -+ return TRUE; -+} -+ -+static gboolean -+_client_subprocess_wait_check (GSubprocess *subprocess, GError **error) -+{ -+ gint rc; -+ if (!g_subprocess_wait (subprocess, NULL, error)) { -+ g_prefix_error (error, "failed to run pkexec: "); -+ return FALSE; -+ } -+ rc = g_subprocess_get_exit_status (subprocess); -+ if (rc != 0) { -+ GInputStream *istream = g_subprocess_get_stderr_pipe (subprocess); -+ gchar buf[1024] = { 0x0 }; -+ gsize sz = 0; -+ g_input_stream_read_all (istream, buf, sizeof(buf) - 1, &sz, NULL, NULL); -+ if (sz == 0) { -+ g_set_error_literal (error, G_IO_ERROR, rc, -+ "Failed to run helper without stderr"); -+ return FALSE; -+ } -+ g_set_error_literal (error, G_IO_ERROR, rc, buf); -+ return FALSE; -+ } -+ return TRUE; -+} -+ -+typedef enum { -+ _NOTIFY_EXPIRED, -+ _NOTIFY_REGISTRATION_REQUIRED, -+ _NOTIFY_REGISTERED -+} _NotifyKind; -+ -+static void -+_show_notification (GsdSubscriptionManager *manager, _NotifyKind notify_kind) -+{ -+ GsdSubscriptionManagerPrivate *priv = manager->priv; -+ switch (notify_kind) { -+ case _NOTIFY_EXPIRED: -+ notify_notification_close (priv->notification_registered, NULL); -+ notify_notification_close (priv->notification_registration_required, NULL); -+ notify_notification_show (priv->notification_expired, NULL); -+ break; -+ case _NOTIFY_REGISTRATION_REQUIRED: -+ notify_notification_close (priv->notification_registered, NULL); -+ notify_notification_close (priv->notification_expired, NULL); -+ notify_notification_show (priv->notification_registration_required, NULL); -+ break; -+ case _NOTIFY_REGISTERED: -+ notify_notification_close (priv->notification_expired, NULL); -+ notify_notification_close (priv->notification_registration_required, NULL); -+ notify_notification_show (priv->notification_registered, NULL); -+ break; -+ default: -+ break; -+ } -+ g_timer_reset (priv->timer_last_notified); -+} -+ -+static void -+_client_maybe__show_notification (GsdSubscriptionManager *manager) -+{ -+ GsdSubscriptionManagerPrivate *priv = manager->priv; -+ -+ /* startup */ -+ if (priv->subscription_status_last == GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN && -+ priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN) { -+ _show_notification (manager, _NOTIFY_REGISTRATION_REQUIRED); -+ return; -+ } -+ -+ /* something changed */ -+ if (priv->subscription_status_last != priv->subscription_status) { -+ g_debug ("transisition from subscription status '%s' to '%s'", -+ gsd_subman_subscription_status_to_string (priv->subscription_status_last), -+ gsd_subman_subscription_status_to_string (priv->subscription_status)); -+ -+ /* needs registration */ -+ if (priv->subscription_status_last == GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID && -+ priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID) { -+ _show_notification (manager, _NOTIFY_REGISTRATION_REQUIRED); -+ return; -+ } -+ -+ /* was unregistered */ -+ if (priv->subscription_status_last == GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID && -+ priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN) { -+ _show_notification (manager, _NOTIFY_REGISTRATION_REQUIRED); -+ return; -+ } -+ -+ /* registered */ -+ if (priv->subscription_status_last == GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN && -+ priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID && -+ g_timer_elapsed (priv->timer_last_notified, NULL) > 60) { -+ _show_notification (manager, _NOTIFY_REGISTERED); -+ return; -+ } -+ } -+ -+ /* nag again */ -+ if (priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN && -+ g_timer_elapsed (priv->timer_last_notified, NULL) > 60 * 60 * 24) { -+ _show_notification (manager, _NOTIFY_REGISTRATION_REQUIRED); -+ return; -+ } -+ if (priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID && -+ g_timer_elapsed (priv->timer_last_notified, NULL) > 60 * 60 * 24) { -+ _show_notification (manager, _NOTIFY_EXPIRED); -+ return; -+ } -+ if (priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_PARTIALLY_VALID && -+ g_timer_elapsed (priv->timer_last_notified, NULL) > 60 * 60 * 24) { -+ _show_notification (manager, _NOTIFY_EXPIRED); -+ return; -+ } -+} -+ -+static gboolean -+_client_register_with_keys (GsdSubscriptionManager *manager, -+ const gchar *hostname, -+ const gchar *organisation, -+ const gchar *activation_key, -+ GError **error) -+{ -+ GsdSubscriptionManagerPrivate *priv = manager->priv; -+ g_autoptr(GSubprocess) subprocess = NULL; -+ -+ /* apparently: "we can't send registration credentials over the regular -+ * system or session bus since those aren't really locked down..." */ -+ if (!_client_register_start (manager, error)) -+ return FALSE; -+ g_debug ("spawning %s", LIBEXECDIR "/gsd-subman-helper"); -+ subprocess = g_subprocess_new (G_SUBPROCESS_FLAGS_STDERR_PIPE, error, -+ "pkexec", LIBEXECDIR "/gsd-subman-helper", -+ "--kind", "register-with-key", -+ "--address", priv->address, -+ "--hostname", hostname, -+ "--organisation", organisation, -+ "--activation-key", activation_key, -+ NULL); -+ if (subprocess == NULL) { -+ g_prefix_error (error, "failed to find pkexec: "); -+ return FALSE; -+ } -+ if (!_client_subprocess_wait_check (subprocess, error)) -+ return FALSE; -+ -+ /* FIXME: also do on error? */ -+ if (!_client_register_stop (manager, error)) -+ return FALSE; -+ if (!_client_subscription_status_update (manager, error)) -+ return FALSE; -+ _client_maybe__show_notification (manager); -+ -+ /* success */ -+ return TRUE; -+} -+ -+static gboolean -+_client_register (GsdSubscriptionManager *manager, -+ const gchar *hostname, -+ const gchar *organisation, -+ const gchar *username, -+ const gchar *password, -+ GError **error) -+{ -+ GsdSubscriptionManagerPrivate *priv = manager->priv; -+ g_autoptr(GSubprocess) subprocess = NULL; -+ -+ /* fallback */ -+ if (organisation == NULL) -+ organisation = ""; -+ -+ /* apparently: "we can't send registration credentials over the regular -+ * system or session bus since those aren't really locked down..." */ -+ if (!_client_register_start (manager, error)) -+ return FALSE; -+ g_debug ("spawning %s", LIBEXECDIR "/gsd-subman-helper"); -+ subprocess = g_subprocess_new (G_SUBPROCESS_FLAGS_STDERR_PIPE, error, -+ "pkexec", LIBEXECDIR "/gsd-subman-helper", -+ "--kind", "register-with-username", -+ "--address", priv->address, -+ "--hostname", hostname, -+ "--organisation", organisation, -+ "--username", username, -+ "--password", password, -+ NULL); -+ if (subprocess == NULL) { -+ g_prefix_error (error, "failed to find pkexec: "); -+ return FALSE; -+ } -+ if (!_client_subprocess_wait_check (subprocess, error)) -+ return FALSE; -+ -+ /* FIXME: also do on error? */ -+ if (!_client_register_stop (manager, error)) -+ return FALSE; -+ if (!_client_subscription_status_update (manager, error)) -+ return FALSE; -+ _client_maybe__show_notification (manager); -+ return TRUE; -+} -+ -+static gboolean -+_client_unregister (GsdSubscriptionManager *manager, GError **error) -+{ -+ g_autoptr(GSubprocess) subprocess = NULL; -+ -+ /* apparently: "we can't send registration credentials over the regular -+ * system or session bus since those aren't really locked down..." */ -+ if (!_client_register_start (manager, error)) -+ return FALSE; -+ g_debug ("spawning %s", LIBEXECDIR "/gsd-subman-helper"); -+ subprocess = g_subprocess_new (G_SUBPROCESS_FLAGS_STDERR_PIPE, error, -+ "pkexec", LIBEXECDIR "/gsd-subman-helper", -+ "--kind", "unregister", -+ NULL); -+ if (subprocess == NULL) { -+ g_prefix_error (error, "failed to find pkexec: "); -+ return FALSE; -+ } -+ if (!_client_subprocess_wait_check (subprocess, error)) -+ return FALSE; -+ if (!_client_subscription_status_update (manager, error)) -+ return FALSE; -+ _client_maybe__show_notification (manager); -+ return TRUE; -+} -+ -+static gboolean -+_client_update_config (GsdSubscriptionManager *manager, GError **error) -+{ -+ GsdSubscriptionManagerPrivate *priv = manager->priv; -+ g_autoptr(GVariant) val = NULL; -+ g_autoptr(GVariant) val_server = NULL; -+ g_autoptr(GVariantDict) dict = NULL; -+ GVariantIter iter; -+ gchar *key; -+ gchar *value; -+ -+ val = g_dbus_proxy_call_sync (priv->proxies[_RHSM_INTERFACE_CONFIG], -+ "GetAll", -+ g_variant_new ("(s)", priv->userlang), -+ G_DBUS_CALL_FLAGS_NONE, -+ -1, NULL, error); -+ if (val == NULL) -+ return FALSE; -+ dict = g_variant_dict_new (g_variant_get_child_value (val, 0)); -+ val_server = g_variant_dict_lookup_value (dict, "server", G_VARIANT_TYPE("a{ss}")); -+ if (val_server != NULL) { -+ g_variant_iter_init (&iter, val_server); -+ while (g_variant_iter_next (&iter, "{ss}", &key, &value)) { -+ g_debug ("%s=%s", key, value); -+ g_hash_table_insert (priv->config, -+ g_steal_pointer (&key), -+ g_steal_pointer (&value)); -+ } -+ } -+ return TRUE; -+} -+ -+static void -+_subman_proxy_signal_cb (GDBusProxy *proxy, -+ const gchar *sender_name, -+ const gchar *signal_name, -+ GVariant *parameters, -+ GsdSubscriptionManager *manager) -+{ -+ g_autoptr(GError) error = NULL; -+ if (!_client_syspurpose_update (manager, &error)) { -+ g_warning ("failed to update syspurpose: %s", error->message); -+ g_clear_error (&error); -+ } -+ if (!_client_subscription_status_update (manager, &error)) { -+ g_warning ("failed to update subscription status: %s", error->message); -+ g_clear_error (&error); -+ } -+ _client_maybe__show_notification (manager); -+} -+ -+static void -+_client_unload (GsdSubscriptionManager *manager) -+{ -+ GsdSubscriptionManagerPrivate *priv = manager->priv; -+ for (guint i = 0; i < _RHSM_INTERFACE_LAST; i++) -+ g_clear_object (&priv->proxies[i]); -+ g_hash_table_unref (priv->config); -+} -+ -+static const gchar * -+_rhsm_interface_to_string (_RhsmInterface kind) -+{ -+ if (kind == _RHSM_INTERFACE_CONFIG) -+ return "Config"; -+ if (kind == _RHSM_INTERFACE_REGISTER_SERVER) -+ return "RegisterServer"; -+ if (kind == _RHSM_INTERFACE_ATTACH) -+ return "Attach"; -+ if (kind == _RHSM_INTERFACE_ENTITLEMENT) -+ return "Entitlement"; -+ if (kind == _RHSM_INTERFACE_PRODUCTS) -+ return "Products"; -+ if (kind == _RHSM_INTERFACE_CONSUMER) -+ return "Consumer"; -+ if (kind == _RHSM_INTERFACE_SYSPURPOSE) -+ return "Syspurpose"; -+ return NULL; -+} -+ -+static gboolean -+_client_load (GsdSubscriptionManager *manager, GError **error) -+{ -+ GsdSubscriptionManagerPrivate *priv = manager->priv; -+ -+ priv->config = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); -+ -+ /* connect to all the interfaces on the *different* objects :| */ -+ for (guint i = 0; i < _RHSM_INTERFACE_LAST; i++) { -+ const gchar *kind = _rhsm_interface_to_string (i); -+ g_autofree gchar *opath = g_strdup_printf ("/com/redhat/RHSM1/%s", kind); -+ g_autofree gchar *iface = g_strdup_printf ("com.redhat.RHSM1.%s", kind); -+ priv->proxies[i] = -+ g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, -+ G_DBUS_PROXY_FLAGS_NONE, -+ NULL, -+ "com.redhat.RHSM1", -+ opath, iface, -+ NULL, -+ error); -+ if (priv->proxies[i] == NULL) -+ return FALSE; -+ /* we want to get notified if the status of the system changes */ -+ g_signal_connect (priv->proxies[i], "g-signal", -+ G_CALLBACK (_subman_proxy_signal_cb), manager); -+ } -+ -+ /* get initial status */ -+ priv->userlang = ""; -+ if (!_client_update_config (manager, error)) -+ return FALSE; -+ if (!_client_subscription_status_update (manager, error)) -+ return FALSE; -+ if (!_client_syspurpose_update (manager, error)) -+ return FALSE; -+ -+ /* success */ -+ return TRUE; -+} -+ -+gboolean -+gsd_subscription_manager_start (GsdSubscriptionManager *manager, GError **error) -+{ -+ gboolean ret; -+ g_debug ("Starting subscription manager"); -+ gnome_settings_profile_start (NULL); -+ ret = _client_load (manager, error); -+ _client_maybe__show_notification (manager); -+ gnome_settings_profile_end (NULL); -+ return ret; -+} -+ -+void -+gsd_subscription_manager_stop (GsdSubscriptionManager *manager) -+{ -+ g_debug ("Stopping subscription manager"); -+ _client_unload (manager); -+} -+ -+static void -+gsd_subscription_manager_class_init (GsdSubscriptionManagerClass *klass) -+{ -+ GObjectClass *object_class = G_OBJECT_CLASS (klass); -+ object_class->finalize = gsd_subscription_manager_finalize; -+ notify_init ("gnome-settings-daemon"); -+ g_type_class_add_private (klass, sizeof (GsdSubscriptionManagerPrivate)); -+} -+ -+static void -+_launch_info_overview (void) -+{ -+ const gchar *argv[] = { "gnome-control-center", "info-overview", NULL }; -+ g_debug ("Running gnome-control-center info-overview"); -+ g_spawn_async (NULL, (gchar **) argv, NULL, G_SPAWN_SEARCH_PATH, -+ NULL, NULL, NULL, NULL); -+} -+ -+static void -+_notify_closed_cb (NotifyNotification *notification, gpointer user_data) -+{ -+ /* FIXME: only launch when clicking on the main body, not the window close */ -+ if (notify_notification_get_closed_reason (notification) == 0x400) -+ _launch_info_overview (); -+} -+ -+static void -+_notify_clicked_cb (NotifyNotification *notification, char *action, gpointer user_data) -+{ -+ _launch_info_overview (); -+} -+ -+static void -+gsd_subscription_manager_init (GsdSubscriptionManager *manager) -+{ -+ GsdSubscriptionManagerPrivate *priv = manager->priv = GSD_SUBSCRIPTION_MANAGER_GET_PRIVATE (manager); -+ -+ priv->timer_last_notified = g_timer_new (); -+ -+ /* expired */ -+ priv->notification_expired = -+ notify_notification_new (_("Subscription Has Expired"), -+ _("Add or renew a subscription to continue receiving software updates."), -+ NULL); -+ notify_notification_set_app_name (priv->notification_expired, _("Subscription")); -+ notify_notification_set_hint_string (priv->notification_expired, "desktop-entry", "subman-panel"); -+ notify_notification_set_hint_string (priv->notification_expired, "x-gnome-privacy-scope", "system"); -+ notify_notification_set_urgency (priv->notification_expired, NOTIFY_URGENCY_CRITICAL); -+ notify_notification_add_action (priv->notification_expired, -+ "info-overview", _("Subscribe System…"), -+ _notify_clicked_cb, -+ manager, NULL); -+ g_signal_connect (priv->notification_expired, "closed", -+ G_CALLBACK (_notify_closed_cb), manager); -+ -+ /* registered */ -+ priv->notification_registered = -+ notify_notification_new (_("Registration Successful"), -+ _("The system has been registered and software updates have been enabled."), -+ NULL); -+ notify_notification_set_app_name (priv->notification_registered, _("Subscription")); -+ notify_notification_set_hint_string (priv->notification_registered, "desktop-entry", "subman-panel"); -+ notify_notification_set_hint_string (priv->notification_registered, "x-gnome-privacy-scope", "system"); -+ notify_notification_set_urgency (priv->notification_registered, NOTIFY_URGENCY_CRITICAL); -+ g_signal_connect (priv->notification_registered, "closed", -+ G_CALLBACK (_notify_closed_cb), manager); -+ -+ /* registration required */ -+ priv->notification_registration_required = -+ notify_notification_new (_("System Not Registered"), -+ _("Please register your system to receive software updates."), -+ NULL); -+ notify_notification_set_app_name (priv->notification_registration_required, _("Subscription")); -+ notify_notification_set_hint_string (priv->notification_registration_required, "desktop-entry", "subman-panel"); -+ notify_notification_set_hint_string (priv->notification_registration_required, "x-gnome-privacy-scope", "system"); -+ notify_notification_set_urgency (priv->notification_registration_required, NOTIFY_URGENCY_CRITICAL); -+ notify_notification_add_action (priv->notification_registration_required, -+ "info-overview", _("Register System…"), -+ _notify_clicked_cb, -+ manager, NULL); -+ g_signal_connect (priv->notification_registration_required, "closed", -+ G_CALLBACK (_notify_closed_cb), manager); -+} -+ -+static void -+gsd_subscription_manager_finalize (GObject *object) -+{ -+ GsdSubscriptionManager *manager; -+ -+ g_return_if_fail (object != NULL); -+ g_return_if_fail (GSD_IS_SUBSCRIPTION_MANAGER (object)); -+ -+ manager = GSD_SUBSCRIPTION_MANAGER (object); -+ -+ gsd_subscription_manager_stop (manager); -+ -+ if (manager->priv->bus_cancellable != NULL) { -+ g_cancellable_cancel (manager->priv->bus_cancellable); -+ g_clear_object (&manager->priv->bus_cancellable); -+ } -+ -+ g_clear_pointer (&manager->priv->introspection_data, g_dbus_node_info_unref); -+ g_clear_object (&manager->priv->connection); -+ g_clear_object (&manager->priv->notification_expired); -+ g_clear_object (&manager->priv->notification_registered); -+ g_timer_destroy (manager->priv->timer_last_notified); -+ -+ if (manager->priv->name_id != 0) { -+ g_bus_unown_name (manager->priv->name_id); -+ manager->priv->name_id = 0; -+ } -+ -+ G_OBJECT_CLASS (gsd_subscription_manager_parent_class)->finalize (object); -+} -+ -+static void -+handle_method_call (GDBusConnection *connection, -+ const gchar *sender, -+ const gchar *object_path, -+ const gchar *interface_name, -+ const gchar *method_name, -+ GVariant *parameters, -+ GDBusMethodInvocation *invocation, -+ gpointer user_data) -+{ -+ GsdSubscriptionManager *manager = GSD_SUBSCRIPTION_MANAGER (user_data); -+ g_autoptr(GError) error = NULL; -+ -+ if (g_strcmp0 (method_name, "Register") == 0) { -+ const gchar *organisation = NULL; -+ const gchar *hostname = NULL; -+ -+ if (FALSE) { -+ g_dbus_method_invocation_return_error_literal (invocation, -+ G_IO_ERROR, G_IO_ERROR_NOT_INITIALIZED, -+ "Cannot register at this time"); -+ -+ return; -+ } -+ -+ g_autoptr(GVariantDict) dict = g_variant_dict_new (g_variant_get_child_value (parameters, 0)); -+ -+ const gchar *kind = NULL; -+ if (!g_variant_dict_lookup (dict, "kind", "&s", &kind)) { -+ g_dbus_method_invocation_return_error_literal (invocation, -+ G_IO_ERROR, G_IO_ERROR_FAILED, -+ "No kind specified"); -+ -+ return; -+ } -+ if (g_strcmp0 (kind, "username") == 0) { -+ const gchar *username = NULL; -+ const gchar *password = NULL; -+ g_variant_dict_lookup (dict, "hostname", "&s", &hostname); -+ g_variant_dict_lookup (dict, "organisation", "&s", &organisation); -+ g_variant_dict_lookup (dict, "username", "&s", &username); -+ g_variant_dict_lookup (dict, "password", "&s", &password); -+ if (!_client_register (manager, -+ hostname, -+ organisation, -+ username, -+ password, -+ &error)) { -+ g_dbus_method_invocation_return_gerror (invocation, error); -+ return; -+ } -+ } else if (g_strcmp0 (kind, "key") == 0) { -+ const gchar *activation_key = NULL; -+ g_variant_dict_lookup (dict, "hostname", "&s", &hostname); -+ g_variant_dict_lookup (dict, "organisation", "&s", &organisation); -+ g_variant_dict_lookup (dict, "activation-key", "&s", &activation_key); -+ if (!_client_register_with_keys (manager, -+ hostname, -+ organisation, -+ activation_key, -+ &error)) { -+ g_dbus_method_invocation_return_gerror (invocation, error); -+ return; -+ } -+ } else { -+ g_dbus_method_invocation_return_error_literal (invocation, -+ G_IO_ERROR, G_IO_ERROR_FAILED, -+ "Invalid kind specified"); -+ -+ return; -+ } -+ g_dbus_method_invocation_return_value (invocation, NULL); -+ } else if (g_strcmp0 (method_name, "Unregister") == 0) { -+ if (!_client_unregister (manager, &error)) { -+ g_dbus_method_invocation_return_gerror (invocation, error); -+ return; -+ } -+ g_dbus_method_invocation_return_value (invocation, NULL); -+ } else { -+ g_assert_not_reached (); -+ } -+} -+ -+static GVariant * -+handle_get_property (GDBusConnection *connection, -+ const gchar *sender, -+ const gchar *object_path, -+ const gchar *interface_name, -+ const gchar *property_name, -+ GError **error, gpointer user_data) -+{ -+ GsdSubscriptionManager *manager = GSD_SUBSCRIPTION_MANAGER (user_data); -+ GsdSubscriptionManagerPrivate *priv = manager->priv; -+ -+ if (g_strcmp0 (interface_name, GSD_SUBSCRIPTION_DBUS_INTERFACE) != 0) { -+ g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, -+ "No such interface: %s", interface_name); -+ return NULL; -+ } -+ -+ if (g_strcmp0 (property_name, "SubscriptionStatus") == 0) -+ return g_variant_new_uint32 (priv->subscription_status); -+ -+ g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, -+ "Failed to get property: %s", property_name); -+ return NULL; -+} -+ -+static gboolean -+handle_set_property (GDBusConnection *connection, -+ const gchar *sender, -+ const gchar *object_path, -+ const gchar *interface_name, -+ const gchar *property_name, -+ GVariant *value, -+ GError **error, gpointer user_data) -+{ -+ if (g_strcmp0 (interface_name, GSD_SUBSCRIPTION_DBUS_INTERFACE) != 0) { -+ g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, -+ "No such interface: %s", interface_name); -+ return FALSE; -+ } -+ g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, -+ "No such property: %s", property_name); -+ return FALSE; -+} -+ -+static const GDBusInterfaceVTable interface_vtable = -+{ -+ handle_method_call, -+ handle_get_property, -+ handle_set_property -+}; -+ -+static void -+name_lost_handler_cb (GDBusConnection *connection, const gchar *name, gpointer user_data) -+{ -+ g_debug ("lost name, so exiting"); -+ gtk_main_quit (); -+} -+ -+static void -+on_bus_gotten (GObject *source_object, GAsyncResult *res, GsdSubscriptionManager *manager) -+{ -+ GsdSubscriptionManagerPrivate *priv = manager->priv; -+ GDBusConnection *connection; -+ g_autoptr(GError) error = NULL; -+ -+ connection = g_bus_get_finish (res, &error); -+ if (connection == NULL) { -+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) -+ g_warning ("Could not get session bus: %s", error->message); -+ return; -+ } -+ -+ priv->connection = connection; -+ g_dbus_connection_register_object (connection, -+ GSD_SUBSCRIPTION_DBUS_PATH, -+ priv->introspection_data->interfaces[0], -+ &interface_vtable, -+ manager, -+ NULL, -+ NULL); -+ priv->name_id = g_bus_own_name_on_connection (connection, -+ GSD_SUBSCRIPTION_DBUS_NAME, -+ G_BUS_NAME_OWNER_FLAGS_NONE, -+ NULL, -+ name_lost_handler_cb, -+ manager, -+ NULL); -+} -+ -+static void -+register_manager_dbus (GsdSubscriptionManager *manager) -+{ -+ GsdSubscriptionManagerPrivate *priv = manager->priv; -+ -+ priv->introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL); -+ g_assert (priv->introspection_data != NULL); -+ priv->bus_cancellable = g_cancellable_new (); -+ -+ g_bus_get (G_BUS_TYPE_SESSION, priv->bus_cancellable, -+ (GAsyncReadyCallback) on_bus_gotten, manager); -+} -+ -+GsdSubscriptionManager * -+gsd_subscription_manager_new (void) -+{ -+ if (manager_object != NULL) { -+ g_object_ref (manager_object); -+ } else { -+ manager_object = g_object_new (GSD_TYPE_SUBSCRIPTION_MANAGER, NULL); -+ g_object_add_weak_pointer (manager_object, -+ (gpointer *) &manager_object); -+ register_manager_dbus (manager_object); -+ } -+ -+ return GSD_SUBSCRIPTION_MANAGER (manager_object); -+} -diff --git a/plugins/subman/gsd-subscription-manager.h b/plugins/subman/gsd-subscription-manager.h -new file mode 100644 -index 00000000..6a524b1b ---- /dev/null -+++ b/plugins/subman/gsd-subscription-manager.h -@@ -0,0 +1,63 @@ -+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- -+ * -+ * Copyright (C) 2019 Richard Hughes -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, see . -+ * -+ */ -+ -+#ifndef __GSD_SUBSCRIPTION_MANAGER_H -+#define __GSD_SUBSCRIPTION_MANAGER_H -+ -+#include -+ -+G_BEGIN_DECLS -+ -+#define GSD_TYPE_SUBSCRIPTION_MANAGER (gsd_subscription_manager_get_type ()) -+#define GSD_SUBSCRIPTION_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_SUBSCRIPTION_MANAGER, GsdSubscriptionManager)) -+#define GSD_SUBSCRIPTION_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_SUBSCRIPTION_MANAGER, GsdSubscriptionManagerClass)) -+#define GSD_IS_SUBSCRIPTION_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_SUBSCRIPTION_MANAGER)) -+#define GSD_IS_SUBSCRIPTION_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_SUBSCRIPTION_MANAGER)) -+#define GSD_SUBSCRIPTION_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_SUBSCRIPTION_MANAGER, GsdSubscriptionManagerClass)) -+#define GSD_SUBSCRIPTION_MANAGER_ERROR (gsd_subscription_manager_error_quark ()) -+ -+typedef struct GsdSubscriptionManagerPrivate GsdSubscriptionManagerPrivate; -+ -+typedef struct -+{ -+ GObject parent; -+ GsdSubscriptionManagerPrivate *priv; -+} GsdSubscriptionManager; -+ -+typedef struct -+{ -+ GObjectClass parent_class; -+} GsdSubscriptionManagerClass; -+ -+enum -+{ -+ GSD_SUBSCRIPTION_MANAGER_ERROR_FAILED -+}; -+ -+GType gsd_subscription_manager_get_type (void); -+GQuark gsd_subscription_manager_error_quark (void); -+ -+GsdSubscriptionManager *gsd_subscription_manager_new (void); -+gboolean gsd_subscription_manager_start (GsdSubscriptionManager *manager, -+ GError **error); -+void gsd_subscription_manager_stop (GsdSubscriptionManager *manager); -+ -+G_END_DECLS -+ -+#endif /* __GSD_SUBSCRIPTION_MANAGER_H */ -diff --git a/plugins/subman/main.c b/plugins/subman/main.c -new file mode 100644 -index 00000000..28ac995b ---- /dev/null -+++ b/plugins/subman/main.c -@@ -0,0 +1,8 @@ -+#define NEW gsd_subscription_manager_new -+#define START gsd_subscription_manager_start -+#define STOP gsd_subscription_manager_stop -+#define MANAGER GsdSubscriptionManager -+#define GDK_BACKEND "x11" -+#include "gsd-subscription-manager.h" -+ -+#include "daemon-skeleton-gtk.h" -diff --git a/plugins/subman/meson.build b/plugins/subman/meson.build -new file mode 100644 -index 00000000..bfd073b6 ---- /dev/null -+++ b/plugins/subman/meson.build -@@ -0,0 +1,56 @@ -+sources = files( -+ 'gsd-subscription-manager.c', -+ 'gsd-subman-common.c', -+ 'main.c' -+) -+ -+deps = plugins_deps + [ -+ libnotify_dep, -+ gtk_dep, -+ jsonglib_dep, -+ m_dep, -+] -+ -+cflags += ['-DBINDIR="@0@"'.format(gsd_bindir)] -+cflags += ['-DLIBEXECDIR="@0@"'.format(gsd_libexecdir)] -+ -+executable( -+ 'gsd-' + plugin_name, -+ sources, -+ include_directories: [top_inc, common_inc], -+ dependencies: deps, -+ c_args: cflags, -+ install: true, -+ install_rpath: gsd_pkglibdir, -+ install_dir: gsd_libexecdir -+) -+ -+# .Register needs to be called from root as subman can't do PolicyKit... -+policy = 'org.gnome.settings-daemon.plugins.subman.policy' -+policy_in = configure_file( -+ input: policy + '.in.in', -+ output: policy + '.in', -+ configuration: plugins_conf -+) -+ -+i18n.merge_file( -+ policy, -+ input: policy_in, -+ output: policy, -+ po_dir: po_dir, -+ install: true, -+ install_dir: join_paths(gsd_datadir, 'polkit-1', 'actions') -+) -+ -+install_data('org.gnome.settings-daemon.plugins.subman.rules', -+ install_dir : join_paths(gsd_datadir, 'polkit-1', 'rules.d')) -+ -+executable( -+ 'gsd-subman-helper', -+ 'gsd-subman-helper.c', -+ include_directories: top_inc, -+ dependencies: [gio_dep, jsonglib_dep], -+ install: true, -+ install_rpath: gsd_pkglibdir, -+ install_dir: gsd_libexecdir -+) -diff --git a/plugins/subman/org.gnome.SettingsDaemon.Subscription.desktop.in b/plugins/subman/org.gnome.SettingsDaemon.Subscription.desktop.in -new file mode 100644 -index 00000000..14fe5915 ---- /dev/null -+++ b/plugins/subman/org.gnome.SettingsDaemon.Subscription.desktop.in -@@ -0,0 +1,9 @@ -+[Desktop Entry] -+Type=Application -+Name=GNOME Settings Daemon's subscription manager plugin -+Exec=@libexecdir@/gsd-subman -+OnlyShowIn=GNOME; -+NoDisplay=true -+X-GNOME-Autostart-Phase=Initialization -+X-GNOME-Autostart-Notify=true -+X-GNOME-AutoRestart=true -diff --git a/plugins/subman/org.gnome.settings-daemon.plugins.subman.policy.in.in b/plugins/subman/org.gnome.settings-daemon.plugins.subman.policy.in.in -new file mode 100644 -index 00000000..59e9fdd4 ---- /dev/null -+++ b/plugins/subman/org.gnome.settings-daemon.plugins.subman.policy.in.in -@@ -0,0 +1,27 @@ -+ -+ -+ -+ -+ -+ -+ GNOME Settings Daemon -+ http://git.gnome.org/browse/gnome-settings-daemon -+ emblem-synchronizing -+ -+ -+ Register the system -+ Authentication is required to register the system -+ -+ no -+ no -+ auth_admin_keep -+ -+ @libexecdir@/gsd-subman-helper -+ -+ -+ -diff --git a/plugins/subman/org.gnome.settings-daemon.plugins.subman.rules b/plugins/subman/org.gnome.settings-daemon.plugins.subman.rules -new file mode 100644 -index 00000000..1ed3a0ea ---- /dev/null -+++ b/plugins/subman/org.gnome.settings-daemon.plugins.subman.rules -@@ -0,0 +1,7 @@ -+polkit.addRule(function(action, subject) { -+ if (action.id == "org.gnome.settings-daemon.plugins.subman.register" && -+ subject.active == true && subject.local == true && -+ subject.isInGroup("wheel")) { -+ return polkit.Result.YES; -+ } -+}); --- -2.37.0 - - -From d85f9992ac4b413d07092363568213991f38d898 Mon Sep 17 00:00:00 2001 -From: Kalev Lember -Date: Thu, 27 Jun 2019 16:12:00 +0200 -Subject: [PATCH 02/20] subman: Add InstalledProducts dbus property for g-c-c - ---- - plugins/subman/gsd-subscription-manager.c | 135 ++++++++++++++++++++++ - 1 file changed, 135 insertions(+) - -diff --git a/plugins/subman/gsd-subscription-manager.c b/plugins/subman/gsd-subscription-manager.c -index 08b13fa6..a8c18a26 100644 ---- a/plugins/subman/gsd-subscription-manager.c -+++ b/plugins/subman/gsd-subscription-manager.c -@@ -1,6 +1,7 @@ - /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- - * - * Copyright (C) 2019 Richard Hughes -+ * Copyright (C) 2019 Kalev Lember - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by -@@ -44,6 +45,7 @@ static const gchar introspection_xml[] = - " " - " " - " " -+" " - " " - " " - ""; -@@ -72,6 +74,7 @@ struct GsdSubscriptionManagerPrivate - GDBusProxy *proxies[_RHSM_INTERFACE_LAST]; - const gchar *userlang; /* owned by GLib internally */ - GHashTable *config; /* str:str */ -+ GPtrArray *installed_products; - gchar *address; - - GTimer *timer_last_notified; -@@ -92,6 +95,32 @@ static void gsd_subscription_manager_finalize (GObject *objec - - G_DEFINE_TYPE (GsdSubscriptionManager, gsd_subscription_manager, G_TYPE_OBJECT) - -+typedef struct -+{ -+ gchar *product_name; -+ gchar *product_id; -+ gchar *version; -+ gchar *arch; -+ gchar *status; -+ gchar *starts; -+ gchar *ends; -+} ProductData; -+ -+static void -+product_data_free (ProductData *product) -+{ -+ g_free (product->product_name); -+ g_free (product->product_id); -+ g_free (product->version); -+ g_free (product->arch); -+ g_free (product->status); -+ g_free (product->starts); -+ g_free (product->ends); -+ g_free (product); -+} -+ -+G_DEFINE_AUTOPTR_CLEANUP_FUNC (ProductData, product_data_free); -+ - static gpointer manager_object = NULL; - - GQuark -@@ -120,6 +149,32 @@ _client_subscription_status_from_text (const gchar *status_txt) - return GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN; - } - -+static GVariant * -+_make_installed_products_variant (GPtrArray *installed_products) -+{ -+ GVariantBuilder builder; -+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("aa{sv}")); -+ -+ for (guint i = 0; i < installed_products->len; i++) { -+ ProductData *product = g_ptr_array_index (installed_products, i); -+ g_auto(GVariantDict) dict; -+ -+ g_variant_dict_init (&dict, NULL); -+ -+ g_variant_dict_insert (&dict, "product-name", "s", product->product_name); -+ g_variant_dict_insert (&dict, "product-id", "s", product->product_id); -+ g_variant_dict_insert (&dict, "version", "s", product->version); -+ g_variant_dict_insert (&dict, "arch", "s", product->arch); -+ g_variant_dict_insert (&dict, "status", "s", product->status); -+ g_variant_dict_insert (&dict, "starts", "s", product->starts); -+ g_variant_dict_insert (&dict, "ends", "s", product->ends); -+ -+ g_variant_builder_add_value (&builder, g_variant_dict_end (&dict)); -+ } -+ -+ return g_variant_builder_end (&builder); -+} -+ - static void - _emit_property_changed (GsdSubscriptionManager *manager, - const gchar *property_name, -@@ -154,6 +209,69 @@ _emit_property_changed (GsdSubscriptionManager *manager, - g_variant_builder_clear (&invalidated_builder); - } - -+static gboolean -+_client_installed_products_update (GsdSubscriptionManager *manager, GError **error) -+{ -+ GsdSubscriptionManagerPrivate *priv = manager->priv; -+ JsonNode *json_root; -+ JsonArray *json_products_array; -+ const gchar *json_txt = NULL; -+ g_autoptr(GVariant) val = NULL; -+ g_autoptr(JsonParser) json_parser = json_parser_new (); -+ -+ val = g_dbus_proxy_call_sync (priv->proxies[_RHSM_INTERFACE_PRODUCTS], -+ "ListInstalledProducts", -+ g_variant_new ("(sa{sv}s)", -+ "" /* filter_string */, -+ NULL /* proxy_options */, -+ priv->userlang), -+ G_DBUS_CALL_FLAGS_NONE, -+ -1, NULL, error); -+ if (val == NULL) -+ return FALSE; -+ g_variant_get (val, "(&s)", &json_txt); -+ g_debug ("Products.ListInstalledProducts JSON: %s", json_txt); -+ if (!json_parser_load_from_data (json_parser, json_txt, -1, error)) -+ return FALSE; -+ json_root = json_parser_get_root (json_parser); -+ json_products_array = json_node_get_array (json_root); -+ if (json_products_array == NULL) { -+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, -+ "no InstalledProducts array in %s", json_txt); -+ return FALSE; -+ } -+ -+ g_ptr_array_set_size (priv->installed_products, 0); -+ -+ for (guint i = 0; i < json_array_get_length (json_products_array); i++) { -+ JsonArray *json_product = json_array_get_array_element (json_products_array, i); -+ g_autoptr(ProductData) product = g_new0 (ProductData, 1); -+ -+ if (json_product == NULL) -+ continue; -+ if (json_array_get_length (json_product) < 8) { -+ g_debug ("Unexpected number of array elements in InstalledProducts JSON"); -+ continue; -+ } -+ -+ product->product_name = g_strdup (json_array_get_string_element (json_product, 0)); -+ product->product_id = g_strdup (json_array_get_string_element (json_product, 1)); -+ product->version = g_strdup (json_array_get_string_element (json_product, 2)); -+ product->arch = g_strdup (json_array_get_string_element (json_product, 3)); -+ product->status = g_strdup (json_array_get_string_element (json_product, 4)); -+ product->starts = g_strdup (json_array_get_string_element (json_product, 6)); -+ product->ends = g_strdup (json_array_get_string_element (json_product, 7)); -+ -+ g_ptr_array_add (priv->installed_products, g_steal_pointer (&product)); -+ } -+ -+ /* emit notification for g-c-c */ -+ _emit_property_changed (manager, "InstalledProducts", -+ _make_installed_products_variant (priv->installed_products)); -+ -+ return TRUE; -+} -+ - static gboolean - _client_subscription_status_update (GsdSubscriptionManager *manager, GError **error) - { -@@ -450,6 +568,8 @@ _client_register_with_keys (GsdSubscriptionManager *manager, - return FALSE; - if (!_client_subscription_status_update (manager, error)) - return FALSE; -+ if (!_client_installed_products_update (manager, error)) -+ return FALSE; - _client_maybe__show_notification (manager); - - /* success */ -@@ -497,6 +617,8 @@ _client_register (GsdSubscriptionManager *manager, - return FALSE; - if (!_client_subscription_status_update (manager, error)) - return FALSE; -+ if (!_client_installed_products_update (manager, error)) -+ return FALSE; - _client_maybe__show_notification (manager); - return TRUE; - } -@@ -523,6 +645,8 @@ _client_unregister (GsdSubscriptionManager *manager, GError **error) - return FALSE; - if (!_client_subscription_status_update (manager, error)) - return FALSE; -+ if (!_client_installed_products_update (manager, error)) -+ return FALSE; - _client_maybe__show_notification (manager); - return TRUE; - } -@@ -575,6 +699,10 @@ _subman_proxy_signal_cb (GDBusProxy *proxy, - g_warning ("failed to update subscription status: %s", error->message); - g_clear_error (&error); - } -+ if (!_client_installed_products_update (manager, &error)) { -+ g_warning ("failed to update installed products: %s", error->message); -+ g_clear_error (&error); -+ } - _client_maybe__show_notification (manager); - } - -@@ -640,6 +768,8 @@ _client_load (GsdSubscriptionManager *manager, GError **error) - return FALSE; - if (!_client_subscription_status_update (manager, error)) - return FALSE; -+ if (!_client_installed_products_update (manager, error)) -+ return FALSE; - if (!_client_syspurpose_update (manager, error)) - return FALSE; - -@@ -703,6 +833,7 @@ gsd_subscription_manager_init (GsdSubscriptionManager *manager) - { - GsdSubscriptionManagerPrivate *priv = manager->priv = GSD_SUBSCRIPTION_MANAGER_GET_PRIVATE (manager); - -+ priv->installed_products = g_ptr_array_new_with_free_func ((GDestroyNotify) product_data_free); - priv->timer_last_notified = g_timer_new (); - - /* expired */ -@@ -767,6 +898,7 @@ gsd_subscription_manager_finalize (GObject *object) - g_clear_object (&manager->priv->bus_cancellable); - } - -+ g_clear_pointer (&manager->priv->installed_products, g_ptr_array_unref); - g_clear_pointer (&manager->priv->introspection_data, g_dbus_node_info_unref); - g_clear_object (&manager->priv->connection); - g_clear_object (&manager->priv->notification_expired); -@@ -884,6 +1016,9 @@ handle_get_property (GDBusConnection *connection, - if (g_strcmp0 (property_name, "SubscriptionStatus") == 0) - return g_variant_new_uint32 (priv->subscription_status); - -+ if (g_strcmp0 (property_name, "InstalledProducts") == 0) -+ return _make_installed_products_variant (priv->installed_products); -+ - g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, - "Failed to get property: %s", property_name); - return NULL; --- -2.37.0 - - -From 65750e137dc591d34c1166de28ce2f73eb17d51e Mon Sep 17 00:00:00 2001 -From: Kalev Lember -Date: Fri, 28 Jun 2019 18:10:36 +0200 -Subject: [PATCH 03/20] subman: Increase RHSM dbus call timeouts - -Increase the dbus timeouts to 5 minutes as the register/unregister calls -seem to routinely take more than a minute. ---- - plugins/subman/gsd-subman-helper.c | 17 ++++++++++++----- - 1 file changed, 12 insertions(+), 5 deletions(-) - -diff --git a/plugins/subman/gsd-subman-helper.c b/plugins/subman/gsd-subman-helper.c -index 69ebec7e..a649ae03 100644 ---- a/plugins/subman/gsd-subman-helper.c -+++ b/plugins/subman/gsd-subman-helper.c -@@ -28,6 +28,8 @@ - #include - #include - -+#define DBUS_TIMEOUT 300000 /* 5 minutes */ -+ - static void - _helper_convert_error (const gchar *json_txt, GError **error) - { -@@ -94,7 +96,8 @@ _helper_unregister (GError **error) - proxy_options, - ""), /* lang */ - G_DBUS_CALL_FLAGS_NONE, -- -1, NULL, error); -+ DBUS_TIMEOUT, -+ NULL, error); - return res != NULL; - } - -@@ -127,7 +130,8 @@ _helper_auto_attach (GError **error) - proxy_options, - ""), /* lang */ - G_DBUS_CALL_FLAGS_NONE, -- -1, NULL, error); -+ DBUS_TIMEOUT, -+ NULL, error); - if (res == NULL) - return FALSE; - g_variant_get (res, "(&s)", &str); -@@ -158,7 +162,8 @@ _helper_save_config (const gchar *key, const gchar *value, GError **error) - g_variant_new_string (value), - ""), /* lang */ - G_DBUS_CALL_FLAGS_NONE, -- -1, NULL, error); -+ DBUS_TIMEOUT, -+ NULL, error); - return res != NULL; - } - -@@ -307,7 +312,8 @@ main (int argc, char *argv[]) - subman_conopts, - userlang), - G_DBUS_CALL_FLAGS_NO_AUTO_START, -- -1, NULL, &error_local); -+ DBUS_TIMEOUT, -+ NULL, &error_local); - if (res == NULL) { - g_dbus_error_strip_remote_error (error_local); - _helper_convert_error (error_local->message, &error); -@@ -341,7 +347,8 @@ main (int argc, char *argv[]) - subman_conopts, - userlang), - G_DBUS_CALL_FLAGS_NO_AUTO_START, -- -1, NULL, &error_local); -+ DBUS_TIMEOUT, -+ NULL, &error_local); - if (res == NULL) { - g_dbus_error_strip_remote_error (error_local); - _helper_convert_error (error_local->message, &error); --- -2.37.0 - - -From cbbaf0ac6b826e38c38eba401e4afc5f71708389 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Thu, 20 Aug 2020 11:20:47 -0400 -Subject: [PATCH 04/20] subman: Drop userlang field - -It's currently always erroneously set to empty string. - -This commit drops it, and just uses "C.UTF-8" everywhere, -which is what we actually want. ---- - plugins/subman/gsd-subscription-manager.c | 14 ++++++-------- - 1 file changed, 6 insertions(+), 8 deletions(-) - -diff --git a/plugins/subman/gsd-subscription-manager.c b/plugins/subman/gsd-subscription-manager.c -index a8c18a26..46f051a5 100644 ---- a/plugins/subman/gsd-subscription-manager.c -+++ b/plugins/subman/gsd-subscription-manager.c -@@ -72,7 +72,6 @@ struct GsdSubscriptionManagerPrivate - GCancellable *bus_cancellable; - - GDBusProxy *proxies[_RHSM_INTERFACE_LAST]; -- const gchar *userlang; /* owned by GLib internally */ - GHashTable *config; /* str:str */ - GPtrArray *installed_products; - gchar *address; -@@ -224,7 +223,7 @@ _client_installed_products_update (GsdSubscriptionManager *manager, GError **err - g_variant_new ("(sa{sv}s)", - "" /* filter_string */, - NULL /* proxy_options */, -- priv->userlang), -+ "C.UTF-8"), - G_DBUS_CALL_FLAGS_NONE, - -1, NULL, error); - if (val == NULL) -@@ -290,7 +289,7 @@ _client_subscription_status_update (GsdSubscriptionManager *manager, GError **er - "GetStatus", - g_variant_new ("(ss)", - "", /* assumed as 'now' */ -- priv->userlang), -+ "C.UTF-8"), - G_DBUS_CALL_FLAGS_NONE, - -1, NULL, error); - if (val == NULL) -@@ -332,7 +331,7 @@ _client_syspurpose_update (GsdSubscriptionManager *manager, GError **error) - - val = g_dbus_proxy_call_sync (priv->proxies[_RHSM_INTERFACE_SYSPURPOSE], - "GetSyspurpose", -- g_variant_new ("(s)", priv->userlang), -+ g_variant_new ("(s)", "C.UTF-8"), - G_DBUS_CALL_FLAGS_NONE, - -1, NULL, error); - if (val == NULL) -@@ -375,7 +374,7 @@ _client_register_start (GsdSubscriptionManager *manager, GError **error) - if (proxy == NULL) - return FALSE; - val = g_dbus_proxy_call_sync (proxy, "Start", -- g_variant_new ("(s)", priv->userlang), -+ g_variant_new ("(s)", "C.UTF-8"), - G_DBUS_CALL_FLAGS_NONE, - -1, NULL, error); - if (val == NULL) -@@ -408,7 +407,7 @@ _client_register_stop (GsdSubscriptionManager *manager, GError **error) - if (proxy == NULL) - return FALSE; - val = g_dbus_proxy_call_sync (proxy, "Stop", -- g_variant_new ("(s)", priv->userlang), -+ g_variant_new ("(s)", "C.UTF-8"), - G_DBUS_CALL_FLAGS_NONE, - -1, NULL, error); - if (val == NULL) -@@ -664,7 +663,7 @@ _client_update_config (GsdSubscriptionManager *manager, GError **error) - - val = g_dbus_proxy_call_sync (priv->proxies[_RHSM_INTERFACE_CONFIG], - "GetAll", -- g_variant_new ("(s)", priv->userlang), -+ g_variant_new ("(s)", "C.UTF-8"), - G_DBUS_CALL_FLAGS_NONE, - -1, NULL, error); - if (val == NULL) -@@ -763,7 +762,6 @@ _client_load (GsdSubscriptionManager *manager, GError **error) - } - - /* get initial status */ -- priv->userlang = ""; - if (!_client_update_config (manager, error)) - return FALSE; - if (!_client_subscription_status_update (manager, error)) --- -2.37.0 - - -From be0e7fdd2e19a1322e0c69081b8a2bf8d62d743a Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Sun, 24 Jan 2021 15:04:17 -0500 -Subject: [PATCH 05/20] subman: Use user locale for registration/subscription - operations - -This makes sure that error messages are in the correct locale. ---- - plugins/subman/gsd-subman-helper.c | 17 +++++++++++------ - 1 file changed, 11 insertions(+), 6 deletions(-) - -diff --git a/plugins/subman/gsd-subman-helper.c b/plugins/subman/gsd-subman-helper.c -index a649ae03..3c892c33 100644 ---- a/plugins/subman/gsd-subman-helper.c -+++ b/plugins/subman/gsd-subman-helper.c -@@ -24,11 +24,13 @@ - #include - #include - #include -+#include - - #include - #include - - #define DBUS_TIMEOUT 300000 /* 5 minutes */ -+static const char *locale; - - static void - _helper_convert_error (const gchar *json_txt, GError **error) -@@ -94,7 +96,7 @@ _helper_unregister (GError **error) - "Unregister", - g_variant_new ("(a{sv}s)", - proxy_options, -- ""), /* lang */ -+ locale), - G_DBUS_CALL_FLAGS_NONE, - DBUS_TIMEOUT, - NULL, error); -@@ -128,7 +130,7 @@ _helper_auto_attach (GError **error) - g_variant_new ("(sa{sv}s)", - "", /* now? */ - proxy_options, -- ""), /* lang */ -+ locale), - G_DBUS_CALL_FLAGS_NONE, - DBUS_TIMEOUT, - NULL, error); -@@ -160,7 +162,7 @@ _helper_save_config (const gchar *key, const gchar *value, GError **error) - g_variant_new ("(svs)", - key, - g_variant_new_string (value), -- ""), /* lang */ -+ locale), - G_DBUS_CALL_FLAGS_NONE, - DBUS_TIMEOUT, - NULL, error); -@@ -170,7 +172,6 @@ _helper_save_config (const gchar *key, const gchar *value, GError **error) - int - main (int argc, char *argv[]) - { -- const gchar *userlang = ""; /* as root, so no translations */ - g_autofree gchar *activation_key = NULL; - g_autofree gchar *address = NULL; - g_autofree gchar *hostname = NULL; -@@ -218,6 +219,10 @@ main (int argc, char *argv[]) - g_printerr ("This program can only be used by the root user\n"); - return G_IO_ERROR_NOT_SUPPORTED; - } -+ -+ setlocale (LC_ALL, ""); -+ locale = setlocale (LC_MESSAGES, NULL); -+ - g_option_context_add_main_entries (context, options, NULL); - if (!g_option_context_parse (context, &argc, &argv, &error)) { - g_printerr ("Failed to parse arguments: %s\n", error->message); -@@ -310,7 +315,7 @@ main (int argc, char *argv[]) - activation_keys, - subman_options, - subman_conopts, -- userlang), -+ locale), - G_DBUS_CALL_FLAGS_NO_AUTO_START, - DBUS_TIMEOUT, - NULL, &error_local); -@@ -345,7 +350,7 @@ main (int argc, char *argv[]) - password, - subman_options, - subman_conopts, -- userlang), -+ locale), - G_DBUS_CALL_FLAGS_NO_AUTO_START, - DBUS_TIMEOUT, - NULL, &error_local); --- -2.37.0 - - -From a45af9d440fc55c1df3e4f12d15129d50d89f792 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Thu, 20 Aug 2020 13:34:19 -0400 -Subject: [PATCH 06/20] subman: Handle subscription-manager giving invalid - status better - -subscription-manager potentially returns status messages that the -subman plugin treats as enum values translated in some unknown -other language. It could be tied to system locale, or due to a -caching bug a previous locale used. - -This commit tries to work around that bug, by instead relying on -the GetUUID() method and valid attribute. If there's no UUID we -know the system is unregistered. If there's a UUID but the valid -attribute is FALSE we know the system is registered, but hasn't -got proper entitlements. ---- - plugins/subman/gsd-subscription-manager.c | 69 ++++++++++++----------- - 1 file changed, 36 insertions(+), 33 deletions(-) - -diff --git a/plugins/subman/gsd-subscription-manager.c b/plugins/subman/gsd-subscription-manager.c -index 46f051a5..e2c16056 100644 ---- a/plugins/subman/gsd-subscription-manager.c -+++ b/plugins/subman/gsd-subscription-manager.c -@@ -131,23 +131,6 @@ gsd_subscription_manager_error_quark (void) - return quark; - } - --static GsdSubmanSubscriptionStatus --_client_subscription_status_from_text (const gchar *status_txt) --{ -- if (g_strcmp0 (status_txt, "Unknown") == 0) -- return GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN; -- if (g_strcmp0 (status_txt, "Current") == 0) -- return GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID; -- if (g_strcmp0 (status_txt, "Invalid") == 0) -- return GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID; -- if (g_strcmp0 (status_txt, "Disabled") == 0) -- return GSD_SUBMAN_SUBSCRIPTION_STATUS_DISABLED; -- if (g_strcmp0 (status_txt, "Insufficient") == 0) -- return GSD_SUBMAN_SUBSCRIPTION_STATUS_PARTIALLY_VALID; -- g_warning ("Unknown subscription status: %s", status_txt); // 'Current'? -- return GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN; --} -- - static GVariant * - _make_installed_products_variant (GPtrArray *installed_products) - { -@@ -275,40 +258,60 @@ static gboolean - _client_subscription_status_update (GsdSubscriptionManager *manager, GError **error) - { - GsdSubscriptionManagerPrivate *priv = manager->priv; -+ g_autoptr(GVariant) uuid = NULL; -+ const gchar *uuid_txt = NULL; - JsonNode *json_root; - JsonObject *json_obj; - const gchar *json_txt = NULL; -- const gchar *status_txt = NULL; -- g_autoptr(GVariant) val = NULL; -+ g_autoptr(GVariant) status = NULL; - g_autoptr(JsonParser) json_parser = json_parser_new (); - - /* save old value */ - priv->subscription_status_last = priv->subscription_status; - -- val = g_dbus_proxy_call_sync (priv->proxies[_RHSM_INTERFACE_ENTITLEMENT], -- "GetStatus", -- g_variant_new ("(ss)", -- "", /* assumed as 'now' */ -- "C.UTF-8"), -- G_DBUS_CALL_FLAGS_NONE, -- -1, NULL, error); -- if (val == NULL) -+ uuid = g_dbus_proxy_call_sync (priv->proxies[_RHSM_INTERFACE_CONSUMER], -+ "GetUuid", -+ g_variant_new ("(s)", -+ "C.UTF-8"), -+ G_DBUS_CALL_FLAGS_NONE, -+ -1, NULL, error); -+ if (uuid == NULL) - return FALSE; -- g_variant_get (val, "(&s)", &json_txt); -+ -+ g_variant_get (uuid, "(&s)", &uuid_txt); -+ -+ status = g_dbus_proxy_call_sync (priv->proxies[_RHSM_INTERFACE_ENTITLEMENT], -+ "GetStatus", -+ g_variant_new ("(ss)", -+ "", /* assumed as 'now' */ -+ "C.UTF-8"), -+ G_DBUS_CALL_FLAGS_NONE, -+ -1, NULL, error); -+ if (status == NULL) -+ return FALSE; -+ g_variant_get (status, "(&s)", &json_txt); - g_debug ("Entitlement.GetStatus JSON: %s", json_txt); - if (!json_parser_load_from_data (json_parser, json_txt, -1, error)) - return FALSE; - json_root = json_parser_get_root (json_parser); - json_obj = json_node_get_object (json_root); -- if (!json_object_has_member (json_obj, "status")) { -+ if (!json_object_has_member (json_obj, "valid")) { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, -- "no Entitlement.GetStatus status in %s", json_txt); -+ "no Entitlement.GetStatus valid in %s", json_txt); - return FALSE; - } - -- status_txt = json_object_get_string_member (json_obj, "status"); -- g_debug ("Entitlement.GetStatus: %s", status_txt); -- priv->subscription_status = _client_subscription_status_from_text (status_txt); -+ gboolean is_valid = json_object_get_boolean_member (json_obj, "valid"); -+ -+ if (uuid_txt[0] != '\0') { -+ if (is_valid) { -+ priv->subscription_status = GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID; -+ } else { -+ priv->subscription_status = GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID; -+ } -+ } else { -+ priv->subscription_status = GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN; -+ } - - /* emit notification for g-c-c */ - if (priv->subscription_status != priv->subscription_status_last) { --- -2.37.0 - - -From 609e78ba17ee5610b35dd40f9763ca91306c3535 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Tue, 25 Aug 2020 10:34:03 -0400 -Subject: [PATCH 07/20] subman: Force re-subscribe if the admin already - subscribed - -It's possible for an admin to to half-enroll the system with RHN, -using the CLI tools. - -Meaning, it's possible for them to register the system with the -service, but not attach to a purchased license for the machine, -the, so called, entitlements. - -The subman module always does both halves of the registration process -in lock step. This means, if an admin tries to register using GNOME -while in a half-registered state, subman will fail because the first -step, the registration step, is already finished. - -This commit addresses that problem by trying to unregister up front -before registering. ---- - plugins/subman/gsd-subman-helper.c | 11 +++++++++-- - 1 file changed, 9 insertions(+), 2 deletions(-) - -diff --git a/plugins/subman/gsd-subman-helper.c b/plugins/subman/gsd-subman-helper.c -index 3c892c33..c248dbc3 100644 ---- a/plugins/subman/gsd-subman-helper.c -+++ b/plugins/subman/gsd-subman-helper.c -@@ -78,7 +78,6 @@ _helper_unregister (GError **error) - g_autoptr(GVariantBuilder) proxy_options = NULL; - g_autoptr(GVariant) res = NULL; - -- g_debug ("unregistering"); - proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, - G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | - G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, -@@ -235,6 +234,7 @@ main (int argc, char *argv[]) - return G_IO_ERROR_INVALID_DATA; - } - if (g_strcmp0 (kind, "unregister") == 0) { -+ g_debug ("unregistering"); - if (!_helper_unregister (&error)) { - g_printerr ("Failed to Unregister: %s\n", error->message); - return G_IO_ERROR_NOT_INITIALIZED; -@@ -306,6 +306,9 @@ main (int argc, char *argv[]) - return G_IO_ERROR_INVALID_DATA; - } - -+ g_debug ("trying to unregister in case machine is already registered"); -+ _helper_unregister (NULL); -+ - g_debug ("registering using activation key"); - activation_keys = g_strsplit (activation_key, ",", -1); - res = g_dbus_proxy_call_sync (proxy, -@@ -329,7 +332,6 @@ main (int argc, char *argv[]) - g_autoptr(GError) error_local = NULL; - g_autoptr(GVariant) res = NULL; - -- g_debug ("registering using username and password"); - if (username == NULL) { - g_printerr ("Required --username\n"); - return G_IO_ERROR_INVALID_DATA; -@@ -342,6 +344,11 @@ main (int argc, char *argv[]) - g_printerr ("Required --organisation\n"); - return G_IO_ERROR_INVALID_DATA; - } -+ -+ g_debug ("trying to unregister in case machine is already registered"); -+ _helper_unregister (NULL); -+ -+ g_debug ("registering using username and password"); - res = g_dbus_proxy_call_sync (proxy, - "Register", - g_variant_new ("(sssa{ss}a{ss}s)", --- -2.37.0 - - -From c189fe1089c1f1975352b1a7fbe41f31ad3adc3b Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Tue, 25 Aug 2020 16:20:42 -0400 -Subject: [PATCH 08/20] subman: Don't send secrets through command line - -The command line is introspectable with "ps", and it even gets logged -to syslog, so it's not suitable for passing secrets. - -Unfortunately, the user's password is currently passed. - -This commit addresses that problem by passing the password through -stdin, instead. ---- - plugins/subman/gsd-subman-helper.c | 32 ++++++++------ - plugins/subman/gsd-subscription-manager.c | 52 ++++++++++++++++++++--- - plugins/subman/meson.build | 2 +- - 3 files changed, 66 insertions(+), 20 deletions(-) - -diff --git a/plugins/subman/gsd-subman-helper.c b/plugins/subman/gsd-subman-helper.c -index c248dbc3..03d2cd64 100644 ---- a/plugins/subman/gsd-subman-helper.c -+++ b/plugins/subman/gsd-subman-helper.c -@@ -21,12 +21,14 @@ - - #include "config.h" - -+ - #include - #include - #include - #include - - #include -+#include - #include - - #define DBUS_TIMEOUT 300000 /* 5 minutes */ -@@ -176,7 +178,6 @@ main (int argc, char *argv[]) - g_autofree gchar *hostname = NULL; - g_autofree gchar *kind = NULL; - g_autofree gchar *organisation = NULL; -- g_autofree gchar *password = NULL; - g_autofree gchar *port = NULL; - g_autofree gchar *prefix = NULL; - g_autofree gchar *proxy_server = NULL; -@@ -188,6 +189,7 @@ main (int argc, char *argv[]) - g_autoptr(GVariantBuilder) proxy_options = NULL; - g_autoptr(GVariantBuilder) subman_conopts = NULL; - g_autoptr(GVariantBuilder) subman_options = NULL; -+ g_autoptr(GInputStream) standard_input_stream = g_unix_input_stream_new (STDIN_FILENO, FALSE); - - const GOptionEntry options[] = { - { "kind", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, -@@ -196,12 +198,8 @@ main (int argc, char *argv[]) - &address, "UNIX address", NULL }, - { "username", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, - &username, "Username", NULL }, -- { "password", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, -- &password, "Password", NULL }, - { "organisation", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, - &organisation, "Organisation", NULL }, -- { "activation-key", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, -- &activation_key, "Activation keys", NULL }, - { "hostname", '\0', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, - &hostname, "Registration server hostname", NULL }, - { "prefix", '\0', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, -@@ -296,16 +294,20 @@ main (int argc, char *argv[]) - g_auto(GStrv) activation_keys = NULL; - g_autoptr(GError) error_local = NULL; - g_autoptr(GVariant) res = NULL; -+ gchar activation_key[PIPE_BUF + 1] = ""; - -- if (activation_key == NULL) { -- g_printerr ("Required --activation-key\n"); -- return G_IO_ERROR_INVALID_DATA; -- } - if (organisation == NULL) { - g_printerr ("Required --organisation\n"); - return G_IO_ERROR_INVALID_DATA; - } - -+ g_input_stream_read (standard_input_stream, activation_key, sizeof (activation_key) - 1, NULL, &error_local); -+ -+ if (error_local != NULL) { -+ g_printerr ("Could not read activation key: %s\n", error_local->message); -+ return G_IO_ERROR_INVALID_DATA; -+ } -+ - g_debug ("trying to unregister in case machine is already registered"); - _helper_unregister (NULL); - -@@ -331,20 +333,24 @@ main (int argc, char *argv[]) - } else if (g_strcmp0 (kind, "register-with-username") == 0) { - g_autoptr(GError) error_local = NULL; - g_autoptr(GVariant) res = NULL; -+ gchar password[PIPE_BUF + 1] = ""; - - if (username == NULL) { - g_printerr ("Required --username\n"); - return G_IO_ERROR_INVALID_DATA; - } -- if (password == NULL) { -- g_printerr ("Required --password\n"); -- return G_IO_ERROR_INVALID_DATA; -- } - if (organisation == NULL) { - g_printerr ("Required --organisation\n"); - return G_IO_ERROR_INVALID_DATA; - } - -+ g_input_stream_read (standard_input_stream, password, sizeof (password) - 1, NULL, &error_local); -+ -+ if (error_local != NULL) { -+ g_printerr ("Could not read password: %s\n", error_local->message); -+ return G_IO_ERROR_INVALID_DATA; -+ } -+ - g_debug ("trying to unregister in case machine is already registered"); - _helper_unregister (NULL); - -diff --git a/plugins/subman/gsd-subscription-manager.c b/plugins/subman/gsd-subscription-manager.c -index e2c16056..0838d490 100644 ---- a/plugins/subman/gsd-subscription-manager.c -+++ b/plugins/subman/gsd-subscription-manager.c -@@ -21,6 +21,7 @@ - #include "config.h" - - #include -+#include - #include - #include - #include -@@ -544,26 +545,45 @@ _client_register_with_keys (GsdSubscriptionManager *manager, - { - GsdSubscriptionManagerPrivate *priv = manager->priv; - g_autoptr(GSubprocess) subprocess = NULL; -+ g_autoptr(GBytes) stdin_buf = g_bytes_new (activation_key, strlen (activation_key) + 1); -+ g_autoptr(GBytes) stderr_buf = NULL; -+ gint rc; - - /* apparently: "we can't send registration credentials over the regular - * system or session bus since those aren't really locked down..." */ - if (!_client_register_start (manager, error)) - return FALSE; - g_debug ("spawning %s", LIBEXECDIR "/gsd-subman-helper"); -- subprocess = g_subprocess_new (G_SUBPROCESS_FLAGS_STDERR_PIPE, error, -+ subprocess = g_subprocess_new (G_SUBPROCESS_FLAGS_STDIN_PIPE | G_SUBPROCESS_FLAGS_STDERR_PIPE, error, - "pkexec", LIBEXECDIR "/gsd-subman-helper", - "--kind", "register-with-key", - "--address", priv->address, - "--hostname", hostname, - "--organisation", organisation, -- "--activation-key", activation_key, - NULL); - if (subprocess == NULL) { - g_prefix_error (error, "failed to find pkexec: "); - return FALSE; - } -- if (!_client_subprocess_wait_check (subprocess, error)) -+ -+ if (!g_subprocess_communicate (subprocess, stdin_buf, NULL, NULL, &stderr_buf, error)) { -+ g_prefix_error (error, "failed to run pkexec: "); - return FALSE; -+ } -+ -+ rc = g_subprocess_get_exit_status (subprocess); -+ if (rc != 0) { -+ if (g_bytes_get_size (stderr_buf) == 0) { -+ g_set_error_literal (error, G_IO_ERROR, rc, -+ "Failed to run helper without stderr"); -+ return FALSE; -+ } -+ -+ g_set_error (error, G_IO_ERROR, rc, -+ "%.*s", -+ g_bytes_get_size (stderr_buf), -+ g_bytes_get_data (stderr_buf, NULL)); -+ } - - /* FIXME: also do on error? */ - if (!_client_register_stop (manager, error)) -@@ -588,6 +608,9 @@ _client_register (GsdSubscriptionManager *manager, - { - GsdSubscriptionManagerPrivate *priv = manager->priv; - g_autoptr(GSubprocess) subprocess = NULL; -+ g_autoptr(GBytes) stdin_buf = g_bytes_new (password, strlen (password) + 1); -+ g_autoptr(GBytes) stderr_buf = NULL; -+ gint rc; - - /* fallback */ - if (organisation == NULL) -@@ -598,21 +621,38 @@ _client_register (GsdSubscriptionManager *manager, - if (!_client_register_start (manager, error)) - return FALSE; - g_debug ("spawning %s", LIBEXECDIR "/gsd-subman-helper"); -- subprocess = g_subprocess_new (G_SUBPROCESS_FLAGS_STDERR_PIPE, error, -+ subprocess = g_subprocess_new (G_SUBPROCESS_FLAGS_STDIN_PIPE | G_SUBPROCESS_FLAGS_STDERR_PIPE, -+ error, - "pkexec", LIBEXECDIR "/gsd-subman-helper", - "--kind", "register-with-username", - "--address", priv->address, - "--hostname", hostname, - "--organisation", organisation, - "--username", username, -- "--password", password, - NULL); - if (subprocess == NULL) { - g_prefix_error (error, "failed to find pkexec: "); - return FALSE; - } -- if (!_client_subprocess_wait_check (subprocess, error)) -+ -+ if (!g_subprocess_communicate (subprocess, stdin_buf, NULL, NULL, &stderr_buf, error)) { -+ g_prefix_error (error, "failed to run pkexec: "); - return FALSE; -+ } -+ -+ rc = g_subprocess_get_exit_status (subprocess); -+ if (rc != 0) { -+ if (g_bytes_get_size (stderr_buf) == 0) { -+ g_set_error_literal (error, G_IO_ERROR, rc, -+ "Failed to run helper without stderr"); -+ return FALSE; -+ } -+ -+ g_set_error (error, G_IO_ERROR, rc, -+ "%.*s", -+ g_bytes_get_size (stderr_buf), -+ g_bytes_get_data (stderr_buf, NULL)); -+ } - - /* FIXME: also do on error? */ - if (!_client_register_stop (manager, error)) -diff --git a/plugins/subman/meson.build b/plugins/subman/meson.build -index bfd073b6..e4b4589d 100644 ---- a/plugins/subman/meson.build -+++ b/plugins/subman/meson.build -@@ -49,7 +49,7 @@ executable( - 'gsd-subman-helper', - 'gsd-subman-helper.c', - include_directories: top_inc, -- dependencies: [gio_dep, jsonglib_dep], -+ dependencies: [gio_dep, gio_unix_dep, jsonglib_dep], - install: true, - install_rpath: gsd_pkglibdir, - install_dir: gsd_libexecdir --- -2.37.0 - - -From 3398c5037f9bdf2f6d3d2161146a6edea6c144f2 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Thu, 21 Jan 2021 09:52:19 -0500 -Subject: [PATCH 09/20] subman: Don't treat failure to attach as fatal - -Many organizations don't require specific subscriptions to get -updates (called "simple content access"). At the moment, -those systems get an error when registering. - -This commit quiets the error. ---- - plugins/subman/gsd-subman-helper.c | 46 ++++++++++++++++++++++++------ - 1 file changed, 37 insertions(+), 9 deletions(-) - -diff --git a/plugins/subman/gsd-subman-helper.c b/plugins/subman/gsd-subman-helper.c -index 03d2cd64..ddfe389f 100644 ---- a/plugins/subman/gsd-subman-helper.c -+++ b/plugins/subman/gsd-subman-helper.c -@@ -52,6 +52,17 @@ _helper_convert_error (const gchar *json_txt, GError **error) - } - json_root = json_parser_get_root (json_parser); - json_obj = json_node_get_object (json_root); -+ if (json_object_has_member (json_obj, "severity")) { -+ const gchar *severity; -+ -+ /* warnings are non-fatal so we ignore them -+ */ -+ severity = json_object_get_string_member (json_obj, "severity"); -+ if (g_strstr_len (severity, -1, "warning") != NULL) { -+ return; -+ } -+ } -+ - if (!json_object_has_member (json_obj, "message")) { - g_set_error (error, - G_IO_ERROR, -@@ -108,6 +119,7 @@ static gboolean - _helper_auto_attach (GError **error) - { - const gchar *str = NULL; -+ g_autoptr(GError) error_local = NULL; - g_autoptr(GDBusProxy) proxy = NULL; - g_autoptr(GVariantBuilder) proxy_options = NULL; - g_autoptr(GVariant) res = NULL; -@@ -120,9 +132,12 @@ _helper_auto_attach (GError **error) - "com.redhat.RHSM1", - "/com/redhat/RHSM1/Attach", - "com.redhat.RHSM1.Attach", -- NULL, error); -+ NULL, &error_local); - if (proxy == NULL) { -- g_prefix_error (error, "Failed to get proxy: "); -+ g_dbus_error_strip_remote_error (error_local); -+ g_propagate_prefixed_error (error, -+ g_steal_pointer (&error_local), -+ "Failed to get proxy: "); - return FALSE; - } - proxy_options = g_variant_builder_new (G_VARIANT_TYPE_VARDICT); -@@ -134,9 +149,18 @@ _helper_auto_attach (GError **error) - locale), - G_DBUS_CALL_FLAGS_NONE, - DBUS_TIMEOUT, -- NULL, error); -- if (res == NULL) -- return FALSE; -+ NULL, &error_local); -+ if (res == NULL) { -+ g_dbus_error_strip_remote_error (error_local); -+ _helper_convert_error (error_local->message, error); -+ -+ if (*error != NULL) { -+ g_prefix_error (error, "Failed to get proxy: "); -+ return FALSE; -+ } -+ -+ return TRUE; -+ } - g_variant_get (res, "(&s)", &str); - g_debug ("Attach.AutoAttach: %s", str); - return TRUE; -@@ -327,8 +351,10 @@ main (int argc, char *argv[]) - if (res == NULL) { - g_dbus_error_strip_remote_error (error_local); - _helper_convert_error (error_local->message, &error); -- g_printerr ("Failed to RegisterWithActivationKeys: %s\n", error->message); -- return error->code; -+ if (error != NULL) { -+ g_printerr ("Failed to RegisterWithActivationKeys: %s\n", error->message); -+ return error->code; -+ } - } - } else if (g_strcmp0 (kind, "register-with-username") == 0) { - g_autoptr(GError) error_local = NULL; -@@ -370,8 +396,10 @@ main (int argc, char *argv[]) - if (res == NULL) { - g_dbus_error_strip_remote_error (error_local); - _helper_convert_error (error_local->message, &error); -- g_printerr ("Failed to Register: %s\n", error->message); -- return error->code; -+ if (error != NULL) { -+ g_printerr ("Failed to Register: %s\n", error->message); -+ return error->code; -+ } - } - } else { - g_printerr ("Invalid --kind specified: %s\n", kind); --- -2.37.0 - - -From ae88d09fd12a971d5f60c5eee5d3b7710e4884be Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Sun, 24 Jan 2021 11:24:36 -0500 -Subject: [PATCH 10/20] subman: Add new no-installed-products state - -It's possible, though unlikley, the system has -no packages installed from Red Hat supported package sets. - -This commit adds a new state to track that situation. ---- - plugins/subman/gsd-subman-common.c | 2 ++ - plugins/subman/gsd-subman-common.h | 1 + - plugins/subman/gsd-subscription-manager.c | 17 +++++++---------- - 3 files changed, 10 insertions(+), 10 deletions(-) - -diff --git a/plugins/subman/gsd-subman-common.c b/plugins/subman/gsd-subman-common.c -index e515131e..eef5175d 100644 ---- a/plugins/subman/gsd-subman-common.c -+++ b/plugins/subman/gsd-subman-common.c -@@ -32,5 +32,7 @@ gsd_subman_subscription_status_to_string (GsdSubmanSubscriptionStatus status) - return "disabled"; - if (status == GSD_SUBMAN_SUBSCRIPTION_STATUS_PARTIALLY_VALID) - return "partially-valid"; -+ if (status == GSD_SUBMAN_SUBSCRIPTION_STATUS_NO_INSTALLED_PRODUCTS) -+ return "no-installed-products"; - return "unknown"; - } -diff --git a/plugins/subman/gsd-subman-common.h b/plugins/subman/gsd-subman-common.h -index fccf9f6a..f8a3d9f4 100644 ---- a/plugins/subman/gsd-subman-common.h -+++ b/plugins/subman/gsd-subman-common.h -@@ -30,6 +30,7 @@ typedef enum { - GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID, - GSD_SUBMAN_SUBSCRIPTION_STATUS_DISABLED, - GSD_SUBMAN_SUBSCRIPTION_STATUS_PARTIALLY_VALID, -+ GSD_SUBMAN_SUBSCRIPTION_STATUS_NO_INSTALLED_PRODUCTS, - GSD_SUBMAN_SUBSCRIPTION_STATUS_LAST - } GsdSubmanSubscriptionStatus; - -diff --git a/plugins/subman/gsd-subscription-manager.c b/plugins/subman/gsd-subscription-manager.c -index 0838d490..46f8d35c 100644 ---- a/plugins/subman/gsd-subscription-manager.c -+++ b/plugins/subman/gsd-subscription-manager.c -@@ -269,6 +269,13 @@ _client_subscription_status_update (GsdSubscriptionManager *manager, GError **er - - /* save old value */ - priv->subscription_status_last = priv->subscription_status; -+ if (!_client_installed_products_update (manager, error)) -+ goto out; -+ -+ if (priv->installed_products->len == 0) { -+ priv->subscription_status = GSD_SUBMAN_SUBSCRIPTION_STATUS_NO_INSTALLED_PRODUCTS; -+ goto out; -+ } - - uuid = g_dbus_proxy_call_sync (priv->proxies[_RHSM_INTERFACE_CONSUMER], - "GetUuid", -@@ -590,8 +597,6 @@ _client_register_with_keys (GsdSubscriptionManager *manager, - return FALSE; - if (!_client_subscription_status_update (manager, error)) - return FALSE; -- if (!_client_installed_products_update (manager, error)) -- return FALSE; - _client_maybe__show_notification (manager); - - /* success */ -@@ -659,8 +664,6 @@ _client_register (GsdSubscriptionManager *manager, - return FALSE; - if (!_client_subscription_status_update (manager, error)) - return FALSE; -- if (!_client_installed_products_update (manager, error)) -- return FALSE; - _client_maybe__show_notification (manager); - return TRUE; - } -@@ -741,10 +744,6 @@ _subman_proxy_signal_cb (GDBusProxy *proxy, - g_warning ("failed to update subscription status: %s", error->message); - g_clear_error (&error); - } -- if (!_client_installed_products_update (manager, &error)) { -- g_warning ("failed to update installed products: %s", error->message); -- g_clear_error (&error); -- } - _client_maybe__show_notification (manager); - } - -@@ -809,8 +808,6 @@ _client_load (GsdSubscriptionManager *manager, GError **error) - return FALSE; - if (!_client_subscription_status_update (manager, error)) - return FALSE; -- if (!_client_installed_products_update (manager, error)) -- return FALSE; - if (!_client_syspurpose_update (manager, error)) - return FALSE; - --- -2.37.0 - - -From 18e5e5862aba2031d1a93671ad8156dcc7709eaf Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Sun, 24 Jan 2021 11:26:40 -0500 -Subject: [PATCH 11/20] subman: Fix some build warnings - ---- - plugins/subman/gsd-subscription-manager.c | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - -diff --git a/plugins/subman/gsd-subscription-manager.c b/plugins/subman/gsd-subscription-manager.c -index 46f8d35c..1f9ca447 100644 ---- a/plugins/subman/gsd-subscription-manager.c -+++ b/plugins/subman/gsd-subscription-manager.c -@@ -588,8 +588,8 @@ _client_register_with_keys (GsdSubscriptionManager *manager, - - g_set_error (error, G_IO_ERROR, rc, - "%.*s", -- g_bytes_get_size (stderr_buf), -- g_bytes_get_data (stderr_buf, NULL)); -+ (int) g_bytes_get_size (stderr_buf), -+ (char *) g_bytes_get_data (stderr_buf, NULL)); - } - - /* FIXME: also do on error? */ -@@ -655,8 +655,8 @@ _client_register (GsdSubscriptionManager *manager, - - g_set_error (error, G_IO_ERROR, rc, - "%.*s", -- g_bytes_get_size (stderr_buf), -- g_bytes_get_data (stderr_buf, NULL)); -+ (int) g_bytes_get_size (stderr_buf), -+ (char *) g_bytes_get_data (stderr_buf, NULL)); - } - - /* FIXME: also do on error? */ --- -2.37.0 - - -From f3f5369b1d68f002b020f803fb59cdcb3205e6dc Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Sun, 24 Jan 2021 11:27:42 -0500 -Subject: [PATCH 12/20] subman: Add DBus API to subscribe for updates on - already registered system - -It's possible an admin may have registered their system without -attaching any subscriptions to it. - -At the moment, gnome-settings-daemon only provides a way to register -and subscribe in one step. - -This commit adds an API to support doing the last half of the process -on its own. ---- - plugins/subman/gsd-subscription-manager.c | 51 +++++++++++++++++++++++ - 1 file changed, 51 insertions(+) - -diff --git a/plugins/subman/gsd-subscription-manager.c b/plugins/subman/gsd-subscription-manager.c -index 1f9ca447..705f8b11 100644 ---- a/plugins/subman/gsd-subscription-manager.c -+++ b/plugins/subman/gsd-subscription-manager.c -@@ -46,6 +46,7 @@ static const gchar introspection_xml[] = - " " - " " - " " -+" " - " " - " " - " " -@@ -696,6 +697,50 @@ _client_unregister (GsdSubscriptionManager *manager, GError **error) - return TRUE; - } - -+static gboolean -+_client_attach (GsdSubscriptionManager *manager, -+ GError **error) -+{ -+ g_autoptr(GSubprocess) subprocess = NULL; -+ g_autoptr(GBytes) stderr_buf = NULL; -+ gint rc; -+ -+ g_debug ("spawning %s", LIBEXECDIR "/gsd-subman-helper"); -+ subprocess = g_subprocess_new (G_SUBPROCESS_FLAGS_STDERR_PIPE, -+ error, -+ "pkexec", LIBEXECDIR "/gsd-subman-helper", -+ "--kind", "auto-attach", -+ NULL); -+ if (subprocess == NULL) { -+ g_prefix_error (error, "failed to find pkexec: "); -+ return FALSE; -+ } -+ -+ if (!g_subprocess_communicate (subprocess, NULL, NULL, NULL, &stderr_buf, error)) { -+ g_prefix_error (error, "failed to run pkexec: "); -+ return FALSE; -+ } -+ -+ rc = g_subprocess_get_exit_status (subprocess); -+ if (rc != 0) { -+ if (g_bytes_get_size (stderr_buf) == 0) { -+ g_set_error_literal (error, G_IO_ERROR, rc, -+ "Failed to run helper without stderr"); -+ return FALSE; -+ } -+ -+ g_set_error (error, G_IO_ERROR, rc, -+ "%.*s", -+ (int) g_bytes_get_size (stderr_buf), -+ (char *) g_bytes_get_data (stderr_buf, NULL)); -+ } -+ -+ if (!_client_subscription_status_update (manager, error)) -+ return FALSE; -+ _client_maybe__show_notification (manager); -+ return TRUE; -+} -+ - static gboolean - _client_update_config (GsdSubscriptionManager *manager, GError **error) - { -@@ -1029,6 +1074,12 @@ handle_method_call (GDBusConnection *connection, - return; - } - g_dbus_method_invocation_return_value (invocation, NULL); -+ } else if (g_strcmp0 (method_name, "Attach") == 0) { -+ if (!_client_attach (manager, &error)) { -+ g_dbus_method_invocation_return_gerror (invocation, error); -+ return; -+ } -+ g_dbus_method_invocation_return_value (invocation, NULL); - } else { - g_assert_not_reached (); - } --- -2.37.0 - - -From d00d1c34921d6301579ee29a51be89ce8250e83d Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Sun, 24 Jan 2021 11:34:03 -0500 -Subject: [PATCH 13/20] subman: Improve subscription status handling - -This commit improves how subscription-manager status is -parsed to give more detailed information about subscription -state. ---- - plugins/subman/gsd-subscription-manager.c | 33 +++++++++++++++++++---- - 1 file changed, 28 insertions(+), 5 deletions(-) - -diff --git a/plugins/subman/gsd-subscription-manager.c b/plugins/subman/gsd-subscription-manager.c -index 705f8b11..6d80bfa9 100644 ---- a/plugins/subman/gsd-subscription-manager.c -+++ b/plugins/subman/gsd-subscription-manager.c -@@ -289,6 +289,11 @@ _client_subscription_status_update (GsdSubscriptionManager *manager, GError **er - - g_variant_get (uuid, "(&s)", &uuid_txt); - -+ if (uuid_txt[0] == '\0') { -+ priv->subscription_status = GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN; -+ goto out; -+ } -+ - status = g_dbus_proxy_call_sync (priv->proxies[_RHSM_INTERFACE_ENTITLEMENT], - "GetStatus", - g_variant_new ("(ss)", -@@ -304,6 +309,13 @@ _client_subscription_status_update (GsdSubscriptionManager *manager, GError **er - return FALSE; - json_root = json_parser_get_root (json_parser); - json_obj = json_node_get_object (json_root); -+ -+ const gchar *status_id = NULL; -+ -+ if (json_object_has_member (json_obj, "status_id")) { -+ status_id = json_object_get_string_member (json_obj, "status_id"); -+ } -+ - if (!json_object_has_member (json_obj, "valid")) { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, - "no Entitlement.GetStatus valid in %s", json_txt); -@@ -312,16 +324,27 @@ _client_subscription_status_update (GsdSubscriptionManager *manager, GError **er - - gboolean is_valid = json_object_get_boolean_member (json_obj, "valid"); - -- if (uuid_txt[0] != '\0') { -- if (is_valid) { -+ if (is_valid) { -+ if (g_strcmp0 (status_id, "disabled") != 0) { - priv->subscription_status = GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID; - } else { -- priv->subscription_status = GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID; -+ priv->subscription_status = GSD_SUBMAN_SUBSCRIPTION_STATUS_DISABLED; -+ } -+ goto out; -+ } -+ -+ for (guint i = 0; i < priv->installed_products->len; i++) { -+ ProductData *product = g_ptr_array_index (priv->installed_products, i); -+ -+ if (g_strcmp0 (product->status, "subscribed") == 0) { -+ priv->subscription_status = GSD_SUBMAN_SUBSCRIPTION_STATUS_PARTIALLY_VALID; -+ goto out; - } -- } else { -- priv->subscription_status = GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN; - } - -+ priv->subscription_status = GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID; -+ -+out: - /* emit notification for g-c-c */ - if (priv->subscription_status != priv->subscription_status_last) { - _emit_property_changed (manager, "SubscriptionStatus", --- -2.37.0 - - -From a3d4e534a1dfa6a6ff68d0bede69e063ffeeb4d7 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Sun, 24 Jan 2021 11:55:19 -0500 -Subject: [PATCH 14/20] subman: Drop "LAST" from status enum - -It's unused, so get rid of it. ---- - plugins/subman/gsd-subman-common.h | 1 - - 1 file changed, 1 deletion(-) - -diff --git a/plugins/subman/gsd-subman-common.h b/plugins/subman/gsd-subman-common.h -index f8a3d9f4..88226564 100644 ---- a/plugins/subman/gsd-subman-common.h -+++ b/plugins/subman/gsd-subman-common.h -@@ -31,7 +31,6 @@ typedef enum { - GSD_SUBMAN_SUBSCRIPTION_STATUS_DISABLED, - GSD_SUBMAN_SUBSCRIPTION_STATUS_PARTIALLY_VALID, - GSD_SUBMAN_SUBSCRIPTION_STATUS_NO_INSTALLED_PRODUCTS, -- GSD_SUBMAN_SUBSCRIPTION_STATUS_LAST - } GsdSubmanSubscriptionStatus; - - const gchar *gsd_subman_subscription_status_to_string (GsdSubmanSubscriptionStatus status); --- -2.37.0 - - -From 78859ea58014ee740de0c484308b6dedf4c59ab3 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Sun, 24 Jan 2021 12:41:20 -0500 -Subject: [PATCH 15/20] subman: Clean up notification behavior - -Notifications were only displayed for some status transitions. - -This commit introduces some booleans based on the old and new -statuses to make the code clearer and to make it easier to hit -all the cases. ---- - plugins/subman/gsd-subman-common.h | 1 + - plugins/subman/gsd-subscription-manager.c | 141 ++++++++++++++++++---- - 2 files changed, 120 insertions(+), 22 deletions(-) - -diff --git a/plugins/subman/gsd-subman-common.h b/plugins/subman/gsd-subman-common.h -index 88226564..9397dbe4 100644 ---- a/plugins/subman/gsd-subman-common.h -+++ b/plugins/subman/gsd-subman-common.h -@@ -25,6 +25,7 @@ - G_BEGIN_DECLS - - typedef enum { -+ GSD_SUBMAN_SUBSCRIPTION_STATUS_NOT_READ = -1, - GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN, - GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID, - GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID, -diff --git a/plugins/subman/gsd-subscription-manager.c b/plugins/subman/gsd-subscription-manager.c -index 6d80bfa9..aaccbbc6 100644 ---- a/plugins/subman/gsd-subscription-manager.c -+++ b/plugins/subman/gsd-subscription-manager.c -@@ -270,6 +270,7 @@ _client_subscription_status_update (GsdSubscriptionManager *manager, GError **er - - /* save old value */ - priv->subscription_status_last = priv->subscription_status; -+ - if (!_client_installed_products_update (manager, error)) - goto out; - -@@ -512,55 +513,149 @@ static void - _client_maybe__show_notification (GsdSubscriptionManager *manager) - { - GsdSubscriptionManagerPrivate *priv = manager->priv; -+ gboolean was_read, was_registered, had_subscriptions, needed_subscriptions; -+ gboolean is_read, is_registered, has_subscriptions, needs_subscriptions; -+ -+ switch (priv->subscription_status_last) { -+ case GSD_SUBMAN_SUBSCRIPTION_STATUS_NOT_READ: -+ was_read = FALSE; -+ was_registered = FALSE; -+ needed_subscriptions = TRUE; -+ had_subscriptions = FALSE; -+ break; -+ case GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN: -+ was_read = TRUE; -+ was_registered = FALSE; -+ needed_subscriptions = TRUE; -+ had_subscriptions = FALSE; -+ break; -+ case GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID: -+ was_read = TRUE; -+ was_registered = TRUE; -+ needed_subscriptions = TRUE; -+ had_subscriptions = TRUE; -+ break; -+ case GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID: -+ was_read = TRUE; -+ was_registered = TRUE; -+ needed_subscriptions = TRUE; -+ had_subscriptions = FALSE; -+ break; -+ case GSD_SUBMAN_SUBSCRIPTION_STATUS_DISABLED: -+ was_read = TRUE; -+ was_registered = TRUE; -+ needed_subscriptions = FALSE; -+ had_subscriptions = FALSE; -+ break; -+ case GSD_SUBMAN_SUBSCRIPTION_STATUS_PARTIALLY_VALID: -+ was_read = TRUE; -+ was_registered = TRUE; -+ needed_subscriptions = TRUE; -+ had_subscriptions = FALSE; -+ case GSD_SUBMAN_SUBSCRIPTION_STATUS_NO_INSTALLED_PRODUCTS: -+ was_read = TRUE; -+ was_registered = FALSE; -+ needed_subscriptions = FALSE; -+ had_subscriptions = FALSE; -+ break; -+ } -+ -+ switch (priv->subscription_status) { -+ case GSD_SUBMAN_SUBSCRIPTION_STATUS_NOT_READ: -+ is_read = FALSE; -+ is_registered = FALSE; -+ needs_subscriptions = TRUE; -+ has_subscriptions = FALSE; -+ break; -+ case GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN: -+ is_read = TRUE; -+ is_registered = FALSE; -+ needs_subscriptions = TRUE; -+ has_subscriptions = FALSE; -+ break; -+ case GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID: -+ is_read = TRUE; -+ is_registered = TRUE; -+ needs_subscriptions = TRUE; -+ has_subscriptions = TRUE; -+ break; -+ case GSD_SUBMAN_SUBSCRIPTION_STATUS_PARTIALLY_VALID: -+ case GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID: -+ is_read = TRUE; -+ is_registered = TRUE; -+ needs_subscriptions = TRUE; -+ has_subscriptions = FALSE; -+ break; -+ case GSD_SUBMAN_SUBSCRIPTION_STATUS_DISABLED: -+ is_read = TRUE; -+ is_registered = TRUE; -+ needs_subscriptions = FALSE; -+ has_subscriptions = FALSE; -+ break; -+ case GSD_SUBMAN_SUBSCRIPTION_STATUS_NO_INSTALLED_PRODUCTS: -+ is_read = TRUE; -+ is_registered = FALSE; -+ needs_subscriptions = FALSE; -+ has_subscriptions = FALSE; -+ break; -+ } - - /* startup */ -- if (priv->subscription_status_last == GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN && -- priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN) { -+ if (!was_read && is_read && priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN) { - _show_notification (manager, _NOTIFY_REGISTRATION_REQUIRED); - return; - } - - /* something changed */ -- if (priv->subscription_status_last != priv->subscription_status) { -+ if (was_read && is_read && priv->subscription_status_last != priv->subscription_status) { - g_debug ("transisition from subscription status '%s' to '%s'", - gsd_subman_subscription_status_to_string (priv->subscription_status_last), - gsd_subman_subscription_status_to_string (priv->subscription_status)); - -- /* needs registration */ -- if (priv->subscription_status_last == GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID && -- priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID) { -- _show_notification (manager, _NOTIFY_REGISTRATION_REQUIRED); -+ /* needs subscription */ -+ if (is_registered && needs_subscriptions && !has_subscriptions) { -+ _show_notification (manager, _NOTIFY_EXPIRED); - return; - } - - /* was unregistered */ -- if (priv->subscription_status_last == GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID && -- priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN) { -+ if (was_registered && !is_registered) { - _show_notification (manager, _NOTIFY_REGISTRATION_REQUIRED); - return; - } - -- /* registered */ -- if (priv->subscription_status_last == GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN && -- priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID && -- g_timer_elapsed (priv->timer_last_notified, NULL) > 60) { -- _show_notification (manager, _NOTIFY_REGISTERED); -- return; -+ /* just registered */ -+ if (!was_registered && is_registered) { -+ if (!needs_subscriptions || has_subscriptions) { -+ _show_notification (manager, _NOTIFY_REGISTERED); -+ return; -+ } -+ } -+ -+ /* subscriptions changed */ -+ if (was_registered && is_registered) { -+ /* subscribed */ -+ if (!had_subscriptions && -+ needs_subscriptions && has_subscriptions) { -+ _show_notification (manager, _NOTIFY_REGISTERED); -+ return; -+ } -+ -+ /* simple content access enabled */ -+ if (needed_subscriptions && !had_subscriptions && !needs_subscriptions) { -+ _show_notification (manager, _NOTIFY_REGISTERED); -+ return; -+ } - } - } - - /* nag again */ -- if (priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN && -+ if (!is_registered && - g_timer_elapsed (priv->timer_last_notified, NULL) > 60 * 60 * 24) { - _show_notification (manager, _NOTIFY_REGISTRATION_REQUIRED); - return; - } -- if (priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID && -- g_timer_elapsed (priv->timer_last_notified, NULL) > 60 * 60 * 24) { -- _show_notification (manager, _NOTIFY_EXPIRED); -- return; -- } -- if (priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_PARTIALLY_VALID && -+ if (is_registered && !has_subscriptions && needs_subscriptions && - g_timer_elapsed (priv->timer_last_notified, NULL) > 60 * 60 * 24) { - _show_notification (manager, _NOTIFY_EXPIRED); - return; -@@ -941,6 +1036,8 @@ gsd_subscription_manager_init (GsdSubscriptionManager *manager) - - priv->installed_products = g_ptr_array_new_with_free_func ((GDestroyNotify) product_data_free); - priv->timer_last_notified = g_timer_new (); -+ priv->subscription_status = GSD_SUBMAN_SUBSCRIPTION_STATUS_NOT_READ; -+ priv->subscription_status_last = GSD_SUBMAN_SUBSCRIPTION_STATUS_NOT_READ; - - /* expired */ - priv->notification_expired = --- -2.37.0 - - -From f9a405172b08607777b47c03dbd1034227690fce Mon Sep 17 00:00:00 2001 -From: Kalev Lember -Date: Fri, 12 Feb 2021 14:51:29 +0100 -Subject: [PATCH 16/20] subman: Update POTFILES.in - ---- - po/POTFILES.in | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/po/POTFILES.in b/po/POTFILES.in -index e721f526..7d5b7e9d 100644 ---- a/po/POTFILES.in -+++ b/po/POTFILES.in -@@ -24,6 +24,8 @@ plugins/print-notifications/gsd-printer.c - plugins/print-notifications/gsd-print-notifications-manager.c - plugins/smartcard/gsd-smartcard-manager.c - plugins/smartcard/gsd-smartcard-service.c -+plugins/subman/gsd-subscription-manager.c -+plugins/subman/org.gnome.settings-daemon.plugins.subman.policy.in.in - plugins/usb-protection/gsd-usb-protection-manager.c - plugins/wacom/gsd-wacom-manager.c - plugins/wacom/org.gnome.settings-daemon.plugins.wacom.policy.in.in --- -2.37.0 - - -From 957d7916a843140898f7a3ca2adeb826cd5e6a99 Mon Sep 17 00:00:00 2001 -From: Kalev Lember -Date: Mon, 6 Sep 2021 21:31:14 +0200 -Subject: [PATCH 17/20] subman: Don't force X11 backend - -All of this should work just fine with Wayland. ---- - plugins/subman/main.c | 1 - - 1 file changed, 1 deletion(-) - -diff --git a/plugins/subman/main.c b/plugins/subman/main.c -index 28ac995b..839c1b79 100644 ---- a/plugins/subman/main.c -+++ b/plugins/subman/main.c -@@ -2,7 +2,6 @@ - #define START gsd_subscription_manager_start - #define STOP gsd_subscription_manager_stop - #define MANAGER GsdSubscriptionManager --#define GDK_BACKEND "x11" - #include "gsd-subscription-manager.h" - - #include "daemon-skeleton-gtk.h" --- -2.37.0 - - -From ea88e09c4e9cb2a6dc67740d556f52761297f5b6 Mon Sep 17 00:00:00 2001 -From: Kalev Lember -Date: Tue, 7 Sep 2021 13:08:12 +0200 -Subject: [PATCH 18/20] subman: Fix desktop file hint for notifications - -We don't have a separate subman-panel. It's all part of -info-overview-panel, as of now at least. ---- - plugins/subman/gsd-subscription-manager.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/plugins/subman/gsd-subscription-manager.c b/plugins/subman/gsd-subscription-manager.c -index aaccbbc6..be978fc3 100644 ---- a/plugins/subman/gsd-subscription-manager.c -+++ b/plugins/subman/gsd-subscription-manager.c -@@ -1045,7 +1045,7 @@ gsd_subscription_manager_init (GsdSubscriptionManager *manager) - _("Add or renew a subscription to continue receiving software updates."), - NULL); - notify_notification_set_app_name (priv->notification_expired, _("Subscription")); -- notify_notification_set_hint_string (priv->notification_expired, "desktop-entry", "subman-panel"); -+ notify_notification_set_hint_string (priv->notification_expired, "desktop-entry", "gnome-info-overview-panel"); - notify_notification_set_hint_string (priv->notification_expired, "x-gnome-privacy-scope", "system"); - notify_notification_set_urgency (priv->notification_expired, NOTIFY_URGENCY_CRITICAL); - notify_notification_add_action (priv->notification_expired, -@@ -1061,7 +1061,7 @@ gsd_subscription_manager_init (GsdSubscriptionManager *manager) - _("The system has been registered and software updates have been enabled."), - NULL); - notify_notification_set_app_name (priv->notification_registered, _("Subscription")); -- notify_notification_set_hint_string (priv->notification_registered, "desktop-entry", "subman-panel"); -+ notify_notification_set_hint_string (priv->notification_registered, "desktop-entry", "gnome-info-overview-panel"); - notify_notification_set_hint_string (priv->notification_registered, "x-gnome-privacy-scope", "system"); - notify_notification_set_urgency (priv->notification_registered, NOTIFY_URGENCY_CRITICAL); - g_signal_connect (priv->notification_registered, "closed", -@@ -1073,7 +1073,7 @@ gsd_subscription_manager_init (GsdSubscriptionManager *manager) - _("Please register your system to receive software updates."), - NULL); - notify_notification_set_app_name (priv->notification_registration_required, _("Subscription")); -- notify_notification_set_hint_string (priv->notification_registration_required, "desktop-entry", "subman-panel"); -+ notify_notification_set_hint_string (priv->notification_registration_required, "desktop-entry", "gnome-info-overview-panel"); - notify_notification_set_hint_string (priv->notification_registration_required, "x-gnome-privacy-scope", "system"); - notify_notification_set_urgency (priv->notification_registration_required, NOTIFY_URGENCY_CRITICAL); - notify_notification_add_action (priv->notification_registration_required, --- -2.37.0 - - -From 3b21bc12315dba099d7377b55109bc5f942960f2 Mon Sep 17 00:00:00 2001 -From: Kalev Lember -Date: Wed, 8 Sep 2021 13:25:07 +0200 -Subject: [PATCH 19/20] subman: Use preferences-system icon for notifications - -Use it as a placeholder until we get a new icon for subscription -management. ---- - plugins/subman/gsd-subscription-manager.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/plugins/subman/gsd-subscription-manager.c b/plugins/subman/gsd-subscription-manager.c -index be978fc3..dbb81098 100644 ---- a/plugins/subman/gsd-subscription-manager.c -+++ b/plugins/subman/gsd-subscription-manager.c -@@ -1043,7 +1043,7 @@ gsd_subscription_manager_init (GsdSubscriptionManager *manager) - priv->notification_expired = - notify_notification_new (_("Subscription Has Expired"), - _("Add or renew a subscription to continue receiving software updates."), -- NULL); -+ "preferences-system"); - notify_notification_set_app_name (priv->notification_expired, _("Subscription")); - notify_notification_set_hint_string (priv->notification_expired, "desktop-entry", "gnome-info-overview-panel"); - notify_notification_set_hint_string (priv->notification_expired, "x-gnome-privacy-scope", "system"); -@@ -1059,7 +1059,7 @@ gsd_subscription_manager_init (GsdSubscriptionManager *manager) - priv->notification_registered = - notify_notification_new (_("Registration Successful"), - _("The system has been registered and software updates have been enabled."), -- NULL); -+ "preferences-system"); - notify_notification_set_app_name (priv->notification_registered, _("Subscription")); - notify_notification_set_hint_string (priv->notification_registered, "desktop-entry", "gnome-info-overview-panel"); - notify_notification_set_hint_string (priv->notification_registered, "x-gnome-privacy-scope", "system"); -@@ -1071,7 +1071,7 @@ gsd_subscription_manager_init (GsdSubscriptionManager *manager) - priv->notification_registration_required = - notify_notification_new (_("System Not Registered"), - _("Please register your system to receive software updates."), -- NULL); -+ "preferences-system"); - notify_notification_set_app_name (priv->notification_registration_required, _("Subscription")); - notify_notification_set_hint_string (priv->notification_registration_required, "desktop-entry", "gnome-info-overview-panel"); - notify_notification_set_hint_string (priv->notification_registration_required, "x-gnome-privacy-scope", "system"); --- -2.37.0 - - -From b7da34ad4cfb05a3d50495da65a7d76abacc965f Mon Sep 17 00:00:00 2001 -From: Felipe Borges -Date: Fri, 15 Jul 2022 15:25:14 +0200 -Subject: [PATCH 20/20] subman: Set "enable_content" option only for Register - -The "enable_content" option doesn't work for -RegisterWithActivationKey. ---- - plugins/subman/gsd-subman-helper.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/plugins/subman/gsd-subman-helper.c b/plugins/subman/gsd-subman-helper.c -index ddfe389f..bc56a8c2 100644 ---- a/plugins/subman/gsd-subman-helper.c -+++ b/plugins/subman/gsd-subman-helper.c -@@ -299,8 +299,6 @@ main (int argc, char *argv[]) - /* enable_content=1 auto attaches the subscription */ - subman_options = g_variant_builder_new (G_VARIANT_TYPE("a{ss}")); - -- g_variant_builder_add (subman_options, "{ss}", "enable_content", "1"); -- - /* set registration server */ - if (hostname == NULL || hostname[0] == '\0') - hostname = g_strdup ("subscription.rhsm.redhat.com"); -@@ -361,6 +359,8 @@ main (int argc, char *argv[]) - g_autoptr(GVariant) res = NULL; - gchar password[PIPE_BUF + 1] = ""; - -+ g_variant_builder_add (subman_options, "{ss}", "enable_content", "1"); -+ - if (username == NULL) { - g_printerr ("Required --username\n"); - return G_IO_ERROR_INVALID_DATA; --- -2.37.0 -