Update to 3.35.4
This commit is contained in:
parent
179d9e9667
commit
ee29f854a6
1
.gitignore
vendored
1
.gitignore
vendored
@ -155,3 +155,4 @@ gnome-desktop-2.90.4.tar.bz2
|
||||
/gnome-desktop-3.34.0.tar.xz
|
||||
/gnome-desktop-3.34.1.tar.xz
|
||||
/gnome-desktop-3.35.2.tar.xz
|
||||
/gnome-desktop-3.35.4.tar.xz
|
||||
|
@ -1,25 +0,0 @@
|
||||
From 5331b019c572de39be6242a58bd613e81de49df6 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Berg <bberg@redhat.com>
|
||||
Date: Sat, 30 Nov 2019 19:12:00 +0100
|
||||
Subject: [PATCH 1/2] build: Remove stray # from config.h.meson
|
||||
|
||||
---
|
||||
config.h.meson | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/config.h.meson b/config.h.meson
|
||||
index 2c72485a..3818c9e6 100644
|
||||
--- a/config.h.meson
|
||||
+++ b/config.h.meson
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
/* we have the timerfd_create(2) system call */
|
||||
#mesondefine HAVE_TIMERFD
|
||||
-#
|
||||
+
|
||||
/* Define to 1 if you have the `openat' function. */
|
||||
#mesondefine HAVE_OPENAT
|
||||
|
||||
--
|
||||
2.23.0
|
||||
|
@ -1,424 +0,0 @@
|
||||
From 791200e749f069087d040fd6248be636de539e44 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Berg <bberg@redhat.com>
|
||||
Date: Sat, 30 Nov 2019 16:49:10 +0100
|
||||
Subject: [PATCH 2/2] systemd: Add utility function to start a transient
|
||||
systemd scope
|
||||
|
||||
In a systemd world, it is often a good idea to move launched
|
||||
applications outside of the own unit into one of their own. This helper
|
||||
allows to do so in a safe and consistent way.
|
||||
---
|
||||
config.h.meson | 3 +
|
||||
libgnome-desktop/gnome-systemd.c | 270 +++++++++++++++++++++++++++++++
|
||||
libgnome-desktop/gnome-systemd.h | 41 +++++
|
||||
libgnome-desktop/meson.build | 3 +
|
||||
meson.build | 3 +
|
||||
meson_options.txt | 4 +
|
||||
6 files changed, 324 insertions(+)
|
||||
create mode 100644 libgnome-desktop/gnome-systemd.c
|
||||
create mode 100644 libgnome-desktop/gnome-systemd.h
|
||||
|
||||
diff --git a/config.h.meson b/config.h.meson
|
||||
index 3818c9e6..7a8d8d96 100644
|
||||
--- a/config.h.meson
|
||||
+++ b/config.h.meson
|
||||
@@ -16,6 +16,9 @@
|
||||
/* Define to 1 if you have the `openat' function. */
|
||||
#mesondefine HAVE_OPENAT
|
||||
|
||||
+/* define if libsystemd is available */
|
||||
+#mesondefine HAVE_SYSTEMD
|
||||
+
|
||||
/* define if udev is available */
|
||||
#mesondefine HAVE_UDEV
|
||||
|
||||
diff --git a/libgnome-desktop/gnome-systemd.c b/libgnome-desktop/gnome-systemd.c
|
||||
new file mode 100644
|
||||
index 00000000..4c875583
|
||||
--- /dev/null
|
||||
+++ b/libgnome-desktop/gnome-systemd.c
|
||||
@@ -0,0 +1,270 @@
|
||||
+/* gnome-systemd.c
|
||||
+ *
|
||||
+ * Copyright 2019 Benjamin Berg <bberg@redhat.com>
|
||||
+ *
|
||||
+ * This file is free software; you can redistribute it and/or modify it
|
||||
+ * under the terms of the GNU Lesser General Public License as
|
||||
+ * published by the Free Software Foundation; either version 3 of the
|
||||
+ * License, or (at your option) any later version.
|
||||
+ *
|
||||
+ * This file 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
|
||||
+ * Lesser General Public License for more details.
|
||||
+ *
|
||||
+ * You should have received a copy of the GNU Lesser General Public
|
||||
+ * License along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
+ *
|
||||
+ * SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
+ */
|
||||
+
|
||||
+#include "config.h"
|
||||
+
|
||||
+#define GNOME_DESKTOP_USE_UNSTABLE_API
|
||||
+#include "gnome-systemd.h"
|
||||
+
|
||||
+#ifdef HAVE_SYSTEMD
|
||||
+#include <errno.h>
|
||||
+#include <systemd/sd-login.h>
|
||||
+#endif
|
||||
+
|
||||
+#ifdef HAVE_SYSTEMD
|
||||
+typedef struct {
|
||||
+ char *name;
|
||||
+ char *description;
|
||||
+ gint32 pid;
|
||||
+} StartSystemdScopeData;
|
||||
+
|
||||
+static void
|
||||
+start_systemd_scope_data_free (StartSystemdScopeData *data)
|
||||
+{
|
||||
+ g_clear_pointer (&data->name, g_free);
|
||||
+ g_clear_pointer (&data->description, g_free);
|
||||
+ g_free (data);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+on_start_transient_unit_cb (GObject *source,
|
||||
+ GAsyncResult *res,
|
||||
+ gpointer user_data)
|
||||
+{
|
||||
+ g_autoptr (GTask) task = G_TASK (user_data);
|
||||
+ g_autoptr (GVariant) reply = NULL;
|
||||
+ GError *error = NULL;
|
||||
+ StartSystemdScopeData *task_data = g_task_get_task_data (task);
|
||||
+
|
||||
+ reply = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source),
|
||||
+ res, &error);
|
||||
+ if (error && !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||
+ {
|
||||
+ g_warning ("Could not create transient scope for PID %d: %s",
|
||||
+ task_data->pid, error->message);
|
||||
+ g_task_return_error (task, error);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ g_debug ("Created transient scope for PID %d", task_data->pid);
|
||||
+
|
||||
+ g_task_return_boolean (task, TRUE);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+start_systemd_scope (GDBusConnection *connection, GTask *task)
|
||||
+{
|
||||
+ GVariantBuilder builder;
|
||||
+ g_autofree char *unit_name = NULL;
|
||||
+ StartSystemdScopeData *task_data = g_task_get_task_data (task);
|
||||
+
|
||||
+ g_assert (task_data != NULL);
|
||||
+
|
||||
+ /* This needs to be unique, hopefully the pid will be enough. */
|
||||
+ unit_name = g_strdup_printf ("gnome-launched-%s-%d.scope", task_data->name, task_data->pid);
|
||||
+
|
||||
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("(ssa(sv)a(sa(sv)))"));
|
||||
+ g_variant_builder_add (&builder, "s", unit_name);
|
||||
+ g_variant_builder_add (&builder, "s", "fail");
|
||||
+
|
||||
+ /* Note that gnome-session ships a drop-in to control further defaults. */
|
||||
+ g_variant_builder_open (&builder, G_VARIANT_TYPE ("a(sv)"));
|
||||
+ if (task_data->description)
|
||||
+ g_variant_builder_add (&builder,
|
||||
+ "(sv)",
|
||||
+ "Description",
|
||||
+ g_variant_new_string (task_data->description));
|
||||
+ g_variant_builder_add (&builder,
|
||||
+ "(sv)",
|
||||
+ "PIDs",
|
||||
+ g_variant_new_fixed_array (G_VARIANT_TYPE_UINT32, &task_data->pid, 1, 4));
|
||||
+ g_variant_builder_close (&builder);
|
||||
+
|
||||
+ g_variant_builder_open (&builder, G_VARIANT_TYPE ("a(sa(sv))"));
|
||||
+ g_variant_builder_close (&builder);
|
||||
+
|
||||
+ g_dbus_connection_call (connection,
|
||||
+ "org.freedesktop.systemd1",
|
||||
+ "/org/freedesktop/systemd1",
|
||||
+ "org.freedesktop.systemd1.Manager",
|
||||
+ "StartTransientUnit",
|
||||
+ g_variant_builder_end (&builder),
|
||||
+ G_VARIANT_TYPE ("(o)"),
|
||||
+ G_DBUS_CALL_FLAGS_NO_AUTO_START,
|
||||
+ 1000,
|
||||
+ g_task_get_cancellable (task),
|
||||
+ on_start_transient_unit_cb,
|
||||
+ task);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+on_bus_gotten_cb (GObject *source,
|
||||
+ GAsyncResult *res,
|
||||
+ gpointer user_data)
|
||||
+{
|
||||
+ g_autoptr(GTask) task = G_TASK (user_data);
|
||||
+ g_autoptr(GDBusConnection) connection = NULL;
|
||||
+ GError *error = NULL;
|
||||
+
|
||||
+ connection = g_bus_get_finish (res, &error);
|
||||
+ if (error)
|
||||
+ {
|
||||
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||
+ g_warning ("Could not get session bus: %s", error->message);
|
||||
+
|
||||
+ g_task_return_error (task, error);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ start_systemd_scope (connection, g_steal_pointer (&task));
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
+/**
|
||||
+ * gnome_start_systemd_scope:
|
||||
+ * @name: Name for the application
|
||||
+ * @pid: The PID of the application
|
||||
+ * @description: (nullable): A description to use for the unit, or %NULL
|
||||
+ * @connection: (nullable): An #GDBusConnection to the session bus, or %NULL
|
||||
+ * @cancellable: (nullable): #GCancellable to use
|
||||
+ * @callback: (nullable): Callback to call when the operation is done
|
||||
+ * @user_data: Data to be passed to @callback
|
||||
+ *
|
||||
+ * If the current process is running inside a user systemd instance, then move
|
||||
+ * the launched PID into a transient scope. The given @name will be used to
|
||||
+ * create a unit name. It should be the application ID for desktop files or
|
||||
+ * the executable in all other cases.
|
||||
+ *
|
||||
+ * It is advisable to use this function every time where the started application
|
||||
+ * can be considered reasonably independent of the launching application. Placing
|
||||
+ * it in a scope creates proper separation between the programs rather than being
|
||||
+ * considered a single entity by systemd.
|
||||
+ *
|
||||
+ * It is always safe to call this function. Note that a successful return code
|
||||
+ * does not imply that a unit has been created. It solely means that no error
|
||||
+ * condition was hit sending the request.
|
||||
+ *
|
||||
+ * If @connection is %NULL then g_dbus_get() will be called internally.
|
||||
+ *
|
||||
+ * Note that most callers will not need to handle errors. As such, it is normal
|
||||
+ * to pass a %NULL @callback.
|
||||
+ *
|
||||
+ * Stability: unstable
|
||||
+ */
|
||||
+void
|
||||
+gnome_start_systemd_scope (const char *name,
|
||||
+ gint32 pid,
|
||||
+ const char *description,
|
||||
+ GDBusConnection *connection,
|
||||
+ GCancellable *cancellable,
|
||||
+ GAsyncReadyCallback callback,
|
||||
+ gpointer user_data)
|
||||
+{
|
||||
+ g_autoptr(GTask) task = NULL;
|
||||
+
|
||||
+#ifdef HAVE_SYSTEMD
|
||||
+ g_autofree char *own_unit = NULL;
|
||||
+ const char *valid_chars =
|
||||
+ "-._1234567890"
|
||||
+ "abcdefghijklmnopqrstuvwxyz"
|
||||
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
+ StartSystemdScopeData *task_data;
|
||||
+ gint res;
|
||||
+
|
||||
+ task = g_task_new (NULL, cancellable, callback, user_data);
|
||||
+ task_data = g_new0 (StartSystemdScopeData, 1);
|
||||
+
|
||||
+ task_data->pid = pid;
|
||||
+
|
||||
+ /* Create a nice and (mangled) name to embed into the unit */
|
||||
+ if (name == NULL)
|
||||
+ name = "anonymous";
|
||||
+
|
||||
+ if (name[0] == '/')
|
||||
+ name++;
|
||||
+
|
||||
+ task_data->name = g_str_to_ascii (name, "C");
|
||||
+ g_strdelimit (task_data->name, "/", '-');
|
||||
+ g_strcanon (task_data->name, valid_chars, '_');
|
||||
+
|
||||
+ task_data->description = g_strdup (description);
|
||||
+ if (task_data->description == NULL)
|
||||
+ {
|
||||
+ const char *app_name = g_get_application_name();
|
||||
+
|
||||
+ if (app_name)
|
||||
+ task_data->description = g_strdup_printf ("Application launched by %s",
|
||||
+ app_name);
|
||||
+ }
|
||||
+
|
||||
+ g_task_set_task_data (task, task_data, (GDestroyNotify) start_systemd_scope_data_free);
|
||||
+
|
||||
+ /* We cannot do anything if this process is not managed by the
|
||||
+ * systemd user instance. */
|
||||
+ res = sd_pid_get_user_unit (getpid (), &own_unit);
|
||||
+ if (res == -ENODATA)
|
||||
+ {
|
||||
+ g_debug ("Not systemd managed, will not move PID %d into transient scope\n", pid);
|
||||
+ g_task_return_boolean (task, TRUE);
|
||||
+
|
||||
+ return;
|
||||
+ }
|
||||
+ if (res < 0)
|
||||
+ {
|
||||
+ g_warning ("Error fetching user unit for own pid: %d\n", -res);
|
||||
+ g_task_return_new_error (task,
|
||||
+ G_IO_ERROR,
|
||||
+ g_io_error_from_errno (-res),
|
||||
+ "Error fetching user unit for own pid: %d", -res);
|
||||
+
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (connection == NULL)
|
||||
+ g_bus_get (G_BUS_TYPE_SESSION, cancellable, on_bus_gotten_cb, g_steal_pointer (&task));
|
||||
+ else
|
||||
+ start_systemd_scope (connection, g_steal_pointer (&task));
|
||||
+#else
|
||||
+ g_debug ("Not creating transient scope for PID %d. Systemd support not compiled in.", pid);
|
||||
+
|
||||
+ task = g_task_new (NULL, cancellable, callback, user_data);
|
||||
+ g_task_return_boolean (task, TRUE);
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * gnome_start_systemd_scope_finish:
|
||||
+ * @res: A #GAsyncResult
|
||||
+ * @error: Return location for errors, or %NULL to ignore
|
||||
+ *
|
||||
+ * Finish an asynchronous operation to create a transient scope that was
|
||||
+ * started with gnome_start_systemd_scope().
|
||||
+ *
|
||||
+ * Note that a successful return code does not imply that a unit has been
|
||||
+ * created. It solely means that no error condition was hit sending the request.
|
||||
+ *
|
||||
+ * Returns: %FALSE on error, %TRUE otherwise
|
||||
+ */
|
||||
+gboolean
|
||||
+gnome_start_systemd_scope_finish (GAsyncResult *res,
|
||||
+ GError **error)
|
||||
+{
|
||||
+ return g_task_propagate_boolean (G_TASK (res), error);
|
||||
+}
|
||||
diff --git a/libgnome-desktop/gnome-systemd.h b/libgnome-desktop/gnome-systemd.h
|
||||
new file mode 100644
|
||||
index 00000000..5d403b4f
|
||||
--- /dev/null
|
||||
+++ b/libgnome-desktop/gnome-systemd.h
|
||||
@@ -0,0 +1,41 @@
|
||||
+/* gnome-systemd.h
|
||||
+ *
|
||||
+ * Copyright 2019 Benjamin Berg <bberg@redhat.com>
|
||||
+ *
|
||||
+ * This file is free software; you can redistribute it and/or modify it
|
||||
+ * under the terms of the GNU Lesser General Public License as
|
||||
+ * published by the Free Software Foundation; either version 3 of the
|
||||
+ * License, or (at your option) any later version.
|
||||
+ *
|
||||
+ * This file 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
|
||||
+ * Lesser General Public License for more details.
|
||||
+ *
|
||||
+ * You should have received a copy of the GNU Lesser General Public
|
||||
+ * License along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
+ *
|
||||
+ * SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
+ */
|
||||
+
|
||||
+#ifndef _GNOME_SYSTEMD_H
|
||||
+#define _GNOME_SYSTEMD_H
|
||||
+
|
||||
+#ifndef GNOME_DESKTOP_USE_UNSTABLE_API
|
||||
+#error GnomeDesktopSystemd is unstable API. You must define GNOME_DESKTOP_USE_UNSTABLE_API before including gnome-systemd.h
|
||||
+#endif
|
||||
+
|
||||
+#include <gio/gio.h>
|
||||
+
|
||||
+void gnome_start_systemd_scope (const char *name,
|
||||
+ gint32 pid,
|
||||
+ const char *description,
|
||||
+ GDBusConnection *connection,
|
||||
+ GCancellable *cancellable,
|
||||
+ GAsyncReadyCallback callback,
|
||||
+ gpointer user_data);
|
||||
+
|
||||
+gboolean gnome_start_systemd_scope_finish (GAsyncResult *res,
|
||||
+ GError **error);
|
||||
+
|
||||
+#endif /* _GNOME_SYSTEMD_H */
|
||||
diff --git a/libgnome-desktop/meson.build b/libgnome-desktop/meson.build
|
||||
index 8503215f..01d10b7e 100644
|
||||
--- a/libgnome-desktop/meson.build
|
||||
+++ b/libgnome-desktop/meson.build
|
||||
@@ -17,6 +17,7 @@ introspection_sources = [
|
||||
'gnome-rr.c',
|
||||
'gnome-rr-config.c',
|
||||
'gnome-rr-output-info.c',
|
||||
+ 'gnome-systemd.c',
|
||||
'gnome-pnp-ids.c',
|
||||
'gnome-wall-clock.c',
|
||||
'gnome-xkb-info.c',
|
||||
@@ -57,6 +58,7 @@ libgnome_desktop_headers = [
|
||||
'gnome-desktop-thumbnail.h',
|
||||
'gnome-rr.h',
|
||||
'gnome-rr-config.h',
|
||||
+ 'gnome-systemd.h',
|
||||
'gnome-pnp-ids.h',
|
||||
'gnome-wall-clock.h',
|
||||
'gnome-xkb-info.h',
|
||||
@@ -75,6 +77,7 @@ gnome_desktop_deps = [
|
||||
glib_dep,
|
||||
gio_dep,
|
||||
gio_unix_dep,
|
||||
+ libsystemd_dep,
|
||||
schemas_dep,
|
||||
xkb_config_dep,
|
||||
iso_codes_dep,
|
||||
diff --git a/meson.build b/meson.build
|
||||
index 6876c2c3..360d6600 100644
|
||||
--- a/meson.build
|
||||
+++ b/meson.build
|
||||
@@ -50,6 +50,8 @@ xkb_config_dep = dependency('xkeyboard-config')
|
||||
iso_codes_dep = dependency('iso-codes')
|
||||
x_dep = dependency('x11')
|
||||
|
||||
+libsystemd_dep = dependency('libsystemd', required: get_option('systemd'))
|
||||
+
|
||||
udev_dep = dependency('libudev', required: get_option('udev'))
|
||||
|
||||
# Check for bubblewrap compatible platform
|
||||
@@ -85,6 +87,7 @@ conf.set('ENABLE_SECCOMP', seccomp_dep.found())
|
||||
conf.set('HAVE_BWRAP', seccomp_dep.found())
|
||||
conf.set('_GNU_SOURCE', seccomp_dep.found())
|
||||
|
||||
+conf.set('HAVE_SYSTEMD', libsystemd_dep.found())
|
||||
conf.set('HAVE_UDEV', udev_dep.found())
|
||||
|
||||
conf.set('HAVE_TIMERFD', cc.has_function('timerfd_create'))
|
||||
diff --git a/meson_options.txt b/meson_options.txt
|
||||
index e3402a11..c0fea3f8 100644
|
||||
--- a/meson_options.txt
|
||||
+++ b/meson_options.txt
|
||||
@@ -21,6 +21,10 @@ option('udev',
|
||||
type: 'feature', description: 'Udev support'
|
||||
)
|
||||
|
||||
+option('systemd',
|
||||
+ type: 'feature', description: 'Systemd integration support'
|
||||
+)
|
||||
+
|
||||
option('gtk_doc',
|
||||
type: 'boolean', value: false, description: 'Build API reference'
|
||||
)
|
||||
--
|
||||
2.23.0
|
||||
|
@ -5,17 +5,14 @@
|
||||
%global po_package gnome-desktop-3.0
|
||||
|
||||
Name: gnome-desktop3
|
||||
Version: 3.35.2
|
||||
Release: 2%{?dist}
|
||||
Version: 3.35.4
|
||||
Release: 1%{?dist}
|
||||
Summary: Library with common API for various GNOME modules
|
||||
|
||||
License: GPLv2+ and LGPLv2+
|
||||
URL: http://www.gnome.org
|
||||
Source0: http://download.gnome.org/sources/gnome-desktop/3.35/gnome-desktop-%{version}.tar.xz
|
||||
|
||||
Patch0001: 0001-build-Remove-stray-from-config.h.meson.patch
|
||||
Patch0002: 0002-systemd-Add-utility-function-to-start-a-transient-sy.patch
|
||||
|
||||
BuildRequires: gcc
|
||||
BuildRequires: gettext
|
||||
BuildRequires: gtk-doc
|
||||
@ -88,7 +85,7 @@ the functionality of the installed %{name} package.
|
||||
%{_datadir}/gnome/gnome-version.xml
|
||||
%{_libexecdir}/gnome-rr-debug
|
||||
# LGPL
|
||||
%{_libdir}/libgnome-desktop-3.so.18{,.*}
|
||||
%{_libdir}/libgnome-desktop-3.so.19{,.*}
|
||||
%{_libdir}/girepository-1.0/GnomeDesktop-3.0.typelib
|
||||
|
||||
%files devel
|
||||
@ -105,6 +102,9 @@ the functionality of the installed %{name} package.
|
||||
%{_datadir}/installed-tests
|
||||
|
||||
%changelog
|
||||
* Thu Jan 16 2020 Kalev Lember <klember@redhat.com> - 3.35.4-1
|
||||
- Update to 3.35.4
|
||||
|
||||
* Thu Dec 05 2019 Benjamin Berg <bberg@redhat.com> - 3.35.2-2
|
||||
- Add upstream patch adding new API that is already in stable
|
||||
https://gitlab.gnome.org/GNOME/gnome-desktop/merge_requests/58
|
||||
|
2
sources
2
sources
@ -1 +1 @@
|
||||
SHA512 (gnome-desktop-3.35.2.tar.xz) = 005ab549710cc74895c7fa11588c04f1bb25fa78cdf31565aa0e3c8bee30bb04f6dcdfa092f5f8ab2bf386e527bfa75fb38962d46ef0e46349e9acd618637812
|
||||
SHA512 (gnome-desktop-3.35.4.tar.xz) = b909f094f9c29aab6d814d5a2972c68833250feb2703c8de7bcd1025c683d94bf68c3183514cd04c97a8747a46ca6c7da3ba729f50f27941879f341d7d7b1d77
|
||||
|
Loading…
Reference in New Issue
Block a user