[gnome-software/1722-flatpak-handle-more-well-known-filesystem-permissions] lib: Add GsAppPermissions object



commit 7212f10a7448e23da0490e8c949893bc92643baf
Author: Milan Crha <mcrha redhat com>
Date:   Thu Jun 16 18:04:18 2022 +0200

    lib: Add GsAppPermissions object
    
    This will serve as an extensible object to store app permissions,
    instead of a bare enum with limited size.

 lib/gnome-software.h     |   1 +
 lib/gs-app-permissions.c | 298 +++++++++++++++++++++++++++++++++++++++++++++++
 lib/gs-app-permissions.h |  66 +++++++++++
 lib/gs-app.h             |  29 +----
 lib/meson.build          |   2 +
 5 files changed, 369 insertions(+), 27 deletions(-)
---
diff --git a/lib/gnome-software.h b/lib/gnome-software.h
index a78b767c9..1594bfc14 100644
--- a/lib/gnome-software.h
+++ b/lib/gnome-software.h
@@ -15,6 +15,7 @@
 #include <gs-app.h>
 #include <gs-app-list.h>
 #include <gs-app-collation.h>
+#include <gs-app-permissions.h>
 #include <gs-app-query.h>
 #include <gs-category.h>
 #include <gs-category-manager.h>
diff --git a/lib/gs-app-permissions.c b/lib/gs-app-permissions.c
new file mode 100644
index 000000000..21329570a
--- /dev/null
+++ b/lib/gs-app-permissions.c
@@ -0,0 +1,298 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ * vi:set noexpandtab tabstop=8 shiftwidth=8:
+ *
+ * Copyright (C) 2022 Red Hat <www.redhat.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+/**
+ * SECTION:gs-app-permissions
+ * @short_description: A representation of an app permissions
+ *
+ * #GsAppPermissions is an object to represent an app permissions.
+ *
+ * While some common permissions are handled with the #GsAppPermissionsFlags,
+ * the object allows to define custom permissions on the filesystem.
+ *
+ * Since: 43
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include "gs-app-permissions.h"
+
+#define DOES_NOT_CONTAIN ((guint) ~0)
+
+struct _GsAppPermissions
+{
+       GObject parent;
+
+       GsAppPermissionsFlags flags;
+       GPtrArray *filesystem_read; /* (owner) (nullable) (element-type utf-8) */
+       GPtrArray *filesystem_full; /* (owner) (nullable) (element-type utf-8) */
+};
+
+G_DEFINE_TYPE (GsAppPermissions, gs_app_permissions, G_TYPE_OBJECT)
+
+static void
+gs_app_permissions_finalize (GObject *object)
+{
+       GsAppPermissions *self = GS_APP_PERMISSIONS (object);
+
+       g_clear_pointer (&self->filesystem_read, g_ptr_array_unref);
+       g_clear_pointer (&self->filesystem_full, g_ptr_array_unref);
+
+       G_OBJECT_CLASS (gs_app_permissions_parent_class)->finalize (object);
+}
+
+static void
+gs_app_permissions_class_init (GsAppPermissionsClass *klass)
+{
+       GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+       object_class->finalize = gs_app_permissions_finalize;
+}
+
+static void
+gs_app_permissions_init (GsAppPermissions *self)
+{
+}
+
+/**
+ * gs_app_permissions_new:
+ *
+ * Create a new #GsAppPermissions containing the app permissions.
+ *
+ * Returns: (transfer full): a new #GsAppPermissions
+ * Since: 43
+ */
+GsAppPermissions *
+gs_app_permissions_new (void)
+{
+       return g_object_new (GS_TYPE_APP_PERMISSIONS, NULL);
+}
+
+/**
+ * gs_app_permissions_set_flags:
+ * @self: a #GsAppPermissions
+ * @flags: a #GsAppPermissionsFlags to set
+ *
+ * Set the permission flags, overwriting any previously set flags.
+ * Compare to gs_app_permissions_add_flag() and
+ * gs_app_permissions_remove_flag().
+ *
+ * Since: 43
+ */
+void
+gs_app_permissions_set_flags (GsAppPermissions *self,
+                             GsAppPermissionsFlags flags)
+{
+       g_return_if_fail (GS_IS_APP_PERMISSIONS (self));
+
+       self->flags = flags;
+}
+
+/**
+ * gs_app_permissions_get_flags:
+ * @self: a #GsAppPermissions
+ *
+ * Get the permission flags.
+ *
+ * Returns: the permission flags
+ * Since: 43
+ */
+GsAppPermissionsFlags
+gs_app_permissions_get_flags (GsAppPermissions *self)
+{
+       g_return_val_if_fail (GS_IS_APP_PERMISSIONS (self), GS_APP_PERMISSIONS_FLAGS_UNKNOWN);
+
+       return self->flags;
+}
+
+/**
+ * gs_app_permissions_add_flag:
+ * @self: a #GsAppPermissions
+ * @flags: a #GsAppPermissionsFlags to add
+ *
+ * Add the @flags into the already set flags. The @flags cannot contain
+ * #GS_APP_PERMISSIONS_FLAGS_NONE, neither cannot be #GS_APP_PERMISSIONS_FLAGS_UNKNOWN.
+ * To set these two use gs_app_permissions_set_flags() instead.
+ *
+ * In case the current flags contain #GS_APP_PERMISSIONS_FLAGS_NONE, it's
+ * automatically unset.
+ *
+ * Since: 43
+ */
+void
+gs_app_permissions_add_flag (GsAppPermissions *self,
+                            GsAppPermissionsFlags flags)
+{
+       g_return_if_fail (GS_IS_APP_PERMISSIONS (self));
+       g_return_if_fail (flags != GS_APP_PERMISSIONS_FLAGS_UNKNOWN);
+       g_return_if_fail ((flags & GS_APP_PERMISSIONS_FLAGS_NONE) == 0);
+
+       self->flags = (self->flags & (~GS_APP_PERMISSIONS_FLAGS_NONE)) | flags;
+}
+
+/**
+ * gs_app_permissions_remove_flag:
+ * @self: a #GsAppPermissions
+ * @flags: a #GsAppPermissionsFlags to remove
+ *
+ * Remove the @flags from the already set flags. The @flags cannot contain
+ * #GS_APP_PERMISSIONS_FLAGS_NONE, neither cannot be #GS_APP_PERMISSIONS_FLAGS_UNKNOWN.
+ * To set these two use gs_app_permissions_set_flags() instead.
+ *
+ * In case the result of the removal would lead to no flag set the #GS_APP_PERMISSIONS_FLAGS_NONE
+ * is set automatically.
+ *
+ * Since: 43
+ */
+void
+gs_app_permissions_remove_flag (GsAppPermissions *self,
+                               GsAppPermissionsFlags flags)
+{
+       g_return_if_fail (GS_IS_APP_PERMISSIONS (self));
+       g_return_if_fail (flags != GS_APP_PERMISSIONS_FLAGS_UNKNOWN);
+       g_return_if_fail ((flags & GS_APP_PERMISSIONS_FLAGS_NONE) == 0);
+
+       self->flags = (self->flags & (~flags));
+
+       if (!self->flags)
+               self->flags = GS_APP_PERMISSIONS_FLAGS_NONE;
+}
+
+static guint
+app_permissions_get_array_index (GPtrArray *array,
+                                const gchar *filename)
+{
+       g_return_val_if_fail (filename != NULL, DOES_NOT_CONTAIN);
+
+       if (array == NULL)
+               return DOES_NOT_CONTAIN;
+
+       for (guint i = 0; i < array->len; i++) {
+               const gchar *item = g_ptr_array_index (array, i);
+               if (g_strcmp0 (item, filename) == 0)
+                       return 0;
+       }
+
+       return DOES_NOT_CONTAIN;
+}
+
+/**
+ * gs_app_permissions_add_filesystem_read:
+ * @self: a #GsAppPermissions
+ * @filename: a filename to access
+ *
+ * Add @filename as a file to access for read. The @filename
+ * can be either a path or a localized pretty name of it, like "Documents".
+ * The addition is ignored in case the same @filename is part of
+ * the read or full access file names.
+ *
+ * Since: 43
+ */
+void
+gs_app_permissions_add_filesystem_read (GsAppPermissions *self,
+                                       const gchar *filename)
+{
+       g_return_if_fail (GS_IS_APP_PERMISSIONS (self));
+       g_return_if_fail (filename != NULL);
+
+       /* Already known */
+       if (app_permissions_get_array_index (self->filesystem_read, filename) != DOES_NOT_CONTAIN ||
+           app_permissions_get_array_index (self->filesystem_full, filename) != DOES_NOT_CONTAIN)
+               return;
+
+       if (self->filesystem_read == NULL)
+               self->filesystem_read = g_ptr_array_new_with_free_func (g_free);
+
+       g_ptr_array_add (self->filesystem_read, g_strdup (filename));
+}
+
+/**
+ * gs_app_permissions_get_filesystem_read:
+ * @self: a #GsAppPermissions
+ *
+ * Get the list of filesystem file names requested for read access using
+ * gs_app_permissions_add_filesystem_read().
+ * The array is owned by the @self and should not be modified by any way.
+ * It can be %NULL, when no file access was set.
+ *
+ * Returns: (nullable) (transfer none) (element-type utf-8): an array of
+ *    file names requesting read access or %NULL, when none was set.
+ *
+ * Since: 43
+ */
+const GPtrArray *
+gs_app_permissions_get_filesystem_read (GsAppPermissions *self)
+{
+       g_return_val_if_fail (GS_IS_APP_PERMISSIONS (self), NULL);
+
+       return self->filesystem_read;
+}
+
+/**
+ * gs_app_permissions_add_filesystem_full:
+ * @self: a #GsAppPermissions
+ * @filename: a filename to access
+ *
+ * Add @filename as a file to access for read and write. The @filename
+ * can be either a path or a localized pretty name of it, like "Documents".
+ * The addition is ignored in case the same @filename is include in the list
+ * already. The @filename is removed from the read list, if it's part of it.
+ *
+ * Since: 43
+ */
+void
+gs_app_permissions_add_filesystem_full (GsAppPermissions *self,
+                                       const gchar *filename)
+{
+       guint read_index;
+
+       g_return_if_fail (GS_IS_APP_PERMISSIONS (self));
+       g_return_if_fail (filename != NULL);
+
+       /* Already known */
+       if (app_permissions_get_array_index (self->filesystem_full, filename) != DOES_NOT_CONTAIN)
+               return;
+
+       if (self->filesystem_full == NULL)
+               self->filesystem_full = g_ptr_array_new_with_free_func (g_free);
+
+       g_ptr_array_add (self->filesystem_full, g_strdup (filename));
+
+       /* Remove from the read list and free the read list if becomes empty */
+       read_index = app_permissions_get_array_index (self->filesystem_read, filename);
+       if (read_index != DOES_NOT_CONTAIN) {
+               g_ptr_array_remove_index (self->filesystem_read, read_index);
+               if (self->filesystem_read->len == 0)
+                       g_clear_pointer (&self->filesystem_read, g_ptr_array_unref);
+       }
+}
+
+/**
+ * gs_app_permissions_get_filesystem_full:
+ * @self: a #GsAppPermissions
+ *
+ * Get the list of filesystem file names requested for read and write access using
+ * gs_app_permissions_add_filesystem_full().
+ * The array is owned by the @self and should not be modified by any way.
+ * It can be %NULL, when no file access was set.
+ *
+ * Returns: (nullable) (transfer none) (element-type utf-8): an array of
+ *    file names requesting read and write access or %NULL, when none was set.
+ *
+ * Since: 43
+ */
+const GPtrArray *
+gs_app_permissions_get_filesystem_full (GsAppPermissions *self)
+{
+       g_return_val_if_fail (GS_IS_APP_PERMISSIONS (self), NULL);
+
+       return self->filesystem_full;
+}
diff --git a/lib/gs-app-permissions.h b/lib/gs-app-permissions.h
new file mode 100644
index 000000000..3e95897f2
--- /dev/null
+++ b/lib/gs-app-permissions.h
@@ -0,0 +1,66 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ * vi:set noexpandtab tabstop=8 shiftwidth=8:
+ *
+ * Copyright (C) 2022 Red Hat <www.redhat.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#pragma once
+
+#include <glib.h>
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+typedef enum {
+       GS_APP_PERMISSIONS_FLAGS_UNKNOWN                = 0,
+       GS_APP_PERMISSIONS_FLAGS_NONE                   = 1 << 0,
+       GS_APP_PERMISSIONS_FLAGS_NETWORK                = 1 << 1,
+       GS_APP_PERMISSIONS_FLAGS_SYSTEM_BUS             = 1 << 2,
+       GS_APP_PERMISSIONS_FLAGS_SESSION_BUS            = 1 << 3,
+       GS_APP_PERMISSIONS_FLAGS_DEVICES                = 1 << 4,
+       GS_APP_PERMISSIONS_FLAGS_HOME_FULL              = 1 << 5,
+       GS_APP_PERMISSIONS_FLAGS_HOME_READ              = 1 << 6,
+       GS_APP_PERMISSIONS_FLAGS_FILESYSTEM_FULL        = 1 << 7,
+       GS_APP_PERMISSIONS_FLAGS_FILESYSTEM_READ        = 1 << 8,
+       GS_APP_PERMISSIONS_FLAGS_DOWNLOADS_FULL         = 1 << 9,
+       GS_APP_PERMISSIONS_FLAGS_DOWNLOADS_READ         = 1 << 10,
+       GS_APP_PERMISSIONS_FLAGS_SETTINGS               = 1 << 11,
+       GS_APP_PERMISSIONS_FLAGS_X11                    = 1 << 12,
+       GS_APP_PERMISSIONS_FLAGS_ESCAPE_SANDBOX         = 1 << 13,
+       GS_APP_PERMISSIONS_FLAGS_FILESYSTEM_OTHER       = 1 << 14,
+       GS_APP_PERMISSIONS_FLAGS_LAST  /*< skip >*/
+} GsAppPermissionsFlags;
+
+#define LIMITED_PERMISSIONS (GS_APP_PERMISSIONS_FLAGS_SETTINGS | \
+                       GS_APP_PERMISSIONS_FLAGS_NETWORK | \
+                       GS_APP_PERMISSIONS_FLAGS_DOWNLOADS_READ | \
+                       GS_APP_PERMISSIONS_FLAGS_DOWNLOADS_FULL)
+#define MEDIUM_PERMISSIONS (LIMITED_PERMISSIONS | \
+                       GS_APP_PERMISSIONS_FLAGS_X11)
+
+#define GS_TYPE_APP_PERMISSIONS (gs_app_permissions_get_type ())
+
+G_DECLARE_FINAL_TYPE (GsAppPermissions, gs_app_permissions, GS, APP_PERMISSIONS, GObject)
+
+GsAppPermissions       *gs_app_permissions_new         (void);
+void                    gs_app_permissions_set_flags   (GsAppPermissions       *self,
+                                                        GsAppPermissionsFlags   flags);
+GsAppPermissionsFlags   gs_app_permissions_get_flags   (GsAppPermissions       *self);
+void                    gs_app_permissions_add_flag    (GsAppPermissions       *self,
+                                                        GsAppPermissionsFlags   flags);
+void                    gs_app_permissions_remove_flag (GsAppPermissions       *self,
+                                                        GsAppPermissionsFlags   flags);
+void                    gs_app_permissions_add_filesystem_read
+                                                       (GsAppPermissions       *self,
+                                                        const gchar            *filename);
+const GPtrArray                *gs_app_permissions_get_filesystem_read
+                                                       (GsAppPermissions       *self);
+void                    gs_app_permissions_add_filesystem_full
+                                                       (GsAppPermissions       *self,
+                                                        const gchar            *filename);
+const GPtrArray                *gs_app_permissions_get_filesystem_full
+                                                       (GsAppPermissions       *self);
+
+G_END_DECLS
diff --git a/lib/gs-app.h b/lib/gs-app.h
index 7eec0f227..f93903366 100644
--- a/lib/gs-app.h
+++ b/lib/gs-app.h
@@ -15,6 +15,8 @@
 #include <libsoup/soup.h>
 #include <appstream.h>
 
+#include <gs-app-permissions.h>
+
 G_BEGIN_DECLS
 
 /* Dependency loop means we can’t include the header. */
@@ -208,33 +210,6 @@ typedef enum {
        GS_APP_QUALITY_LAST  /*< skip >*/
 } GsAppQuality;
 
-typedef enum {
-       GS_APP_PERMISSIONS_FLAGS_UNKNOWN                = 0,
-       GS_APP_PERMISSIONS_FLAGS_NONE                   = 1 << 0,
-       GS_APP_PERMISSIONS_FLAGS_NETWORK                = 1 << 1,
-       GS_APP_PERMISSIONS_FLAGS_SYSTEM_BUS             = 1 << 2,
-       GS_APP_PERMISSIONS_FLAGS_SESSION_BUS            = 1 << 3,
-       GS_APP_PERMISSIONS_FLAGS_DEVICES                = 1 << 4,
-       GS_APP_PERMISSIONS_FLAGS_HOME_FULL              = 1 << 5,
-       GS_APP_PERMISSIONS_FLAGS_HOME_READ              = 1 << 6,
-       GS_APP_PERMISSIONS_FLAGS_FILESYSTEM_FULL        = 1 << 7,
-       GS_APP_PERMISSIONS_FLAGS_FILESYSTEM_READ        = 1 << 8,
-       GS_APP_PERMISSIONS_FLAGS_DOWNLOADS_FULL         = 1 << 9,
-       GS_APP_PERMISSIONS_FLAGS_DOWNLOADS_READ         = 1 << 10,
-       GS_APP_PERMISSIONS_FLAGS_SETTINGS               = 1 << 11,
-       GS_APP_PERMISSIONS_FLAGS_X11                    = 1 << 12,
-       GS_APP_PERMISSIONS_FLAGS_ESCAPE_SANDBOX         = 1 << 13,
-       GS_APP_PERMISSIONS_FLAGS_FILESYSTEM_OTHER       = 1 << 14,
-       GS_APP_PERMISSIONS_FLAGS_LAST  /*< skip >*/
-} GsAppPermissionsFlags;
-
-#define LIMITED_PERMISSIONS (GS_APP_PERMISSIONS_FLAGS_SETTINGS | \
-                       GS_APP_PERMISSIONS_FLAGS_NETWORK | \
-                       GS_APP_PERMISSIONS_FLAGS_DOWNLOADS_READ | \
-                       GS_APP_PERMISSIONS_FLAGS_DOWNLOADS_FULL)
-#define MEDIUM_PERMISSIONS (LIMITED_PERMISSIONS | \
-                       GS_APP_PERMISSIONS_FLAGS_X11)
-
 /**
  * GS_APP_PROGRESS_UNKNOWN:
  *
diff --git a/lib/meson.build b/lib/meson.build
index 69746c062..1d011255d 100644
--- a/lib/meson.build
+++ b/lib/meson.build
@@ -6,6 +6,7 @@ libgnomesoftware_public_headers = [
   'gs-app.h',
   'gs-app-collation.h',
   'gs-app-list.h',
+  'gs-app-permissions.h',
   'gs-app-query.h',
   'gs-appstream.h',
   'gs-category.h',
@@ -84,6 +85,7 @@ libgnomesoftware = library(
   sources : [
     'gs-app.c',
     'gs-app-list.c',
+    'gs-app-permissions.c',
     'gs-app-query.c',
     'gs-appstream.c',
     'gs-category.c',


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]