[gegl] Add support for filtering non-LGPL plugins
- From: Daniel Sabo <daniels src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl] Add support for filtering non-LGPL plugins
- Date: Sat, 22 Feb 2014 23:47:11 +0000 (UTC)
commit e236db255f7854b30b95e052e0dbb4e4424d8f04
Author: Daniel Sabo <DanielSabo gmail com>
Date: Sat Dec 7 19:23:09 2013 -0800
Add support for filtering non-LGPL plugins
Add support for filtering operations with more restrictive
licenses (e.g. GPL) at runtime, by default only operations
with licenses no more restrictive than LGPL are exposed.
bin/gegl.c | 4 +
gegl/gegl-config.c | 20 ++++-
gegl/gegl-config.h | 1 +
gegl/gegl-debug.h | 7 +-
gegl/gegl-init.c | 17 ++++
gegl/operation/gegl-operations.c | 178 +++++++++++++++++++++++++++++++++-----
gegl/operation/gegl-operations.h | 2 +
7 files changed, 205 insertions(+), 24 deletions(-)
---
diff --git a/bin/gegl.c b/bin/gegl.c
index 905658f..26239fd 100644
--- a/bin/gegl.c
+++ b/bin/gegl.c
@@ -86,6 +86,10 @@ main (gint argc,
GError *err = NULL;
gchar *path_root = NULL;
+ g_object_set (gegl_config (),
+ "application-license", "GPL3",
+ NULL);
+
gegl_init (&argc, &argv);
#ifdef HAVE_SPIRO
gegl_path_spiro_init ();
diff --git a/gegl/gegl-config.c b/gegl/gegl-config.c
index eb3e82b..7308b56 100644
--- a/gegl/gegl-config.c
+++ b/gegl/gegl-config.c
@@ -45,7 +45,8 @@ enum
PROP_TILE_HEIGHT,
PROP_THREADS,
PROP_USE_OPENCL,
- PROP_QUEUE_SIZE
+ PROP_QUEUE_SIZE,
+ PROP_APPLICATION_LICENSE
};
static void
@@ -98,6 +99,10 @@ gegl_config_get_property (GObject *gobject,
g_value_set_int (value, config->queue_size);
break;
+ case PROP_APPLICATION_LICENSE:
+ g_value_set_string (value, config->application_license);
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, property_id, pspec);
break;
@@ -172,6 +177,11 @@ gegl_config_set_property (GObject *gobject,
case PROP_QUEUE_SIZE:
config->queue_size = g_value_get_int (value);
break;
+ case PROP_APPLICATION_LICENSE:
+ if (config->application_license)
+ g_free (config->application_license);
+ config->application_license = g_value_dup_string (value);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, property_id, pspec);
break;
@@ -280,6 +290,14 @@ gegl_config_class_init (GeglConfigClass *klass)
2, G_MAXINT, 50 * 1024 *1024,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (gobject_class, PROP_APPLICATION_LICENSE,
+ g_param_spec_string ("application-license",
+ "Application license",
+ "A list of additional licenses to allow for
operations",
+ "",
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
}
static void
diff --git a/gegl/gegl-config.h b/gegl/gegl-config.h
index 0a170f8..3faec93 100644
--- a/gegl/gegl-config.h
+++ b/gegl/gegl-config.h
@@ -45,6 +45,7 @@ struct _GeglConfig
gint threads;
gboolean use_opencl;
gint queue_size;
+ gchar *application_license;
};
struct _GeglConfigClass
diff --git a/gegl/gegl-debug.h b/gegl/gegl-debug.h
index 0d87c7e..324ac72 100644
--- a/gegl/gegl-debug.h
+++ b/gegl/gegl-debug.h
@@ -15,7 +15,8 @@ typedef enum {
GEGL_DEBUG_MISC = 1 << 6,
GEGL_DEBUG_INVALIDATION = 1 << 7,
GEGL_DEBUG_OPENCL = 1 << 8,
- GEGL_DEBUG_BUFFER_ALLOC = 1 << 9
+ GEGL_DEBUG_BUFFER_ALLOC = 1 << 9,
+ GEGL_DEBUG_LICENSE = 1 << 10
} GeglDebugFlag;
/* only compiled in from gegl-init.c but kept here to
@@ -33,6 +34,7 @@ static const GDebugKey gegl_debug_keys[] = {
{ "invalidation", GEGL_DEBUG_INVALIDATION},
{ "opencl", GEGL_DEBUG_OPENCL},
{ "buffer-alloc", GEGL_DEBUG_BUFFER_ALLOC},
+ { "license", GEGL_DEBUG_LICENSE},
{ "all", GEGL_DEBUG_PROCESS|
GEGL_DEBUG_BUFFER_LOAD|
GEGL_DEBUG_BUFFER_SAVE|
@@ -40,7 +42,8 @@ static const GDebugKey gegl_debug_keys[] = {
GEGL_DEBUG_PROCESSOR|
GEGL_DEBUG_CACHE|
GEGL_DEBUG_OPENCL|
- GEGL_DEBUG_BUFFER_ALLOC},
+ GEGL_DEBUG_BUFFER_ALLOC|
+ GEGL_DEBUG_LICENSE},
};
#endif /* __GEGL_INIT_C */
diff --git a/gegl/gegl-init.c b/gegl/gegl-init.c
index aa81ccc..ef6e89b 100644
--- a/gegl/gegl-init.c
+++ b/gegl/gegl-init.c
@@ -172,6 +172,17 @@ gegl_swap_dir (void)
}
static void
+gegl_config_application_license_notify (GObject *gobject,
+ GParamSpec *pspec,
+ gpointer user_data)
+{
+ GeglConfig *cfg = GEGL_CONFIG (gobject);
+
+ gegl_operations_set_licenses_from_string (cfg->application_license);
+}
+
+
+static void
gegl_config_use_opencl_notify (GObject *gobject,
GParamSpec *pspec,
gpointer user_data)
@@ -663,6 +674,12 @@ gegl_post_parse_hook (GOptionContext *context,
NULL);
g_object_set (config, "use-opencl", config->use_opencl, NULL);
+ g_signal_connect (G_OBJECT (config),
+ "notify::application-license",
+ G_CALLBACK (gegl_config_application_license_notify),
+ NULL);
+ gegl_operations_set_licenses_from_string (config->application_license);
+
return TRUE;
}
diff --git a/gegl/operation/gegl-operations.c b/gegl/operation/gegl-operations.c
index 5615483..329e6a4 100644
--- a/gegl/operation/gegl-operations.c
+++ b/gegl/operation/gegl-operations.c
@@ -30,11 +30,13 @@
#include "gegl-operations.h"
#include "gegl-operation-context.h"
+static gchar **accepted_licenses = NULL;
+static GHashTable *known_operation_names = NULL;
+static GHashTable *visible_operation_names = NULL;
+static GSList *operations_list = NULL;
+static guint gtype_hash_serial = 0;
-static GHashTable *gtype_hash = NULL;
-static GSList *operations_list = NULL;
-static guint gtype_hash_serial = 0;
-G_LOCK_DEFINE_STATIC (gtype_hash);
+static GMutex operations_cache_mutex = { 0, };
void
gegl_operation_class_register_name (GeglOperationClass *klass,
@@ -44,9 +46,9 @@ gegl_operation_class_register_name (GeglOperationClass *klass,
GType this_type, check_type;
this_type = G_TYPE_FROM_CLASS (klass);
- G_LOCK (gtype_hash);
+ g_mutex_lock (&operations_cache_mutex);
- check_type = (GType) g_hash_table_lookup (gtype_hash, name);
+ check_type = (GType) g_hash_table_lookup (known_operation_names, name);
if (check_type && check_type != this_type)
{
g_warning ("Adding %s shadows %s for operation %s",
@@ -54,13 +56,10 @@ gegl_operation_class_register_name (GeglOperationClass *klass,
g_type_name (check_type),
name);
}
- g_hash_table_insert (gtype_hash, g_strdup (name), (gpointer) this_type);
- if (!check_type && !is_compat)
- operations_list = g_slist_insert_sorted (operations_list, (gpointer) name,
- (GCompareFunc) strcmp);
+ g_hash_table_insert (known_operation_names, g_strdup (name), (gpointer) this_type);
- G_UNLOCK (gtype_hash);
+ g_mutex_unlock (&operations_cache_mutex);
}
static void
@@ -87,6 +86,126 @@ add_operations (GType parent)
g_free (types);
}
+static gboolean
+gegl_operations_check_license (const gchar *operation_license)
+{
+ gint i;
+
+ if (!accepted_licenses || !accepted_licenses[0])
+ return FALSE;
+
+ if (0 == g_ascii_strcasecmp (operation_license, "GPL1+"))
+ {
+ /* Search for GPL1 */
+ for (i = 0; accepted_licenses[i]; ++i)
+ if (0 == g_ascii_strcasecmp ("GPL1", accepted_licenses[i]))
+ return TRUE;
+ /* Search for GPL2 */
+ for (i = 0; accepted_licenses[i]; ++i)
+ if (0 == g_ascii_strcasecmp ("GPL2", accepted_licenses[i]))
+ return TRUE;
+ /* Search for GPL3 */
+ for (i = 0; accepted_licenses[i]; ++i)
+ if (0 == g_ascii_strcasecmp ("GPL3", accepted_licenses[i]))
+ return TRUE;
+ }
+ else if (0 == g_ascii_strcasecmp (operation_license, "GPL2+"))
+ {
+ /* Search for GPL2 */
+ for (i = 0; accepted_licenses[i]; ++i)
+ if (0 == g_ascii_strcasecmp ("GPL2", accepted_licenses[i]))
+ return TRUE;
+ /* Search for GPL3 */
+ for (i = 0; accepted_licenses[i]; ++i)
+ if (0 == g_ascii_strcasecmp ("GPL3", accepted_licenses[i]))
+ return TRUE;
+ }
+ else if (0 == g_ascii_strcasecmp (operation_license, "GPL3+"))
+ {
+ /* Search for GPL3 */
+ for (i = 0; accepted_licenses[i]; ++i)
+ if (0 == g_ascii_strcasecmp ("GPL3", accepted_licenses[i]))
+ return TRUE;
+ }
+ else
+ {
+ /* Search for exact match */
+ for (i = 0; accepted_licenses[i]; ++i)
+ if (0 == g_ascii_strcasecmp (operation_license, accepted_licenses[i]))
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+gegl_operations_update_visible (void)
+{
+ g_mutex_lock (&operations_cache_mutex);
+
+ GHashTableIter iter;
+ const gchar *iter_key;
+ GType iter_value;
+
+ g_hash_table_remove_all (visible_operation_names);
+ g_slist_free (operations_list);
+
+ operations_list = NULL;
+
+ g_hash_table_iter_init (&iter, known_operation_names);
+
+ while (g_hash_table_iter_next (&iter, (gpointer)&iter_key, (gpointer)&iter_value))
+ {
+ GObjectClass *object_class;
+ GeglOperationClass *operation_class;
+
+ object_class = g_type_class_ref (iter_value);
+ operation_class = GEGL_OPERATION_CLASS (object_class);
+
+ const gchar *operation_license = g_hash_table_lookup (operation_class->keys, "license");
+
+ if (!operation_license || gegl_operations_check_license (operation_license))
+ {
+ if (operation_license)
+ {
+ GEGL_NOTE (GEGL_DEBUG_LICENSE, "Accepted %s for %s", operation_license, iter_key);
+ }
+
+ if (operation_class->name && (0 == strcmp (iter_key, operation_class->name)))
+ {
+ /* Is the primary name of the operation */
+ operations_list = g_slist_insert_sorted (operations_list, (gpointer) iter_key,
+ (GCompareFunc) strcmp);
+ }
+
+ g_hash_table_insert (visible_operation_names, g_strdup (iter_key), (gpointer) iter_value);
+ }
+ else if (operation_license)
+ {
+ GEGL_NOTE (GEGL_DEBUG_LICENSE, "Rejected %s for %s", operation_license, iter_key);
+ }
+
+ g_type_class_unref (object_class);
+ }
+
+ g_mutex_unlock (&operations_cache_mutex);
+}
+
+void
+gegl_operations_set_licenses_from_string (const gchar *license_str)
+{
+ g_mutex_lock (&operations_cache_mutex);
+
+ if (accepted_licenses)
+ g_strfreev (accepted_licenses);
+
+ accepted_licenses = g_strsplit (license_str, ",", 0);
+
+ g_mutex_unlock (&operations_cache_mutex);
+
+ gegl_operations_update_visible ();
+}
+
GType
gegl_operation_gtype_from_name (const gchar *name)
{
@@ -96,10 +215,13 @@ gegl_operation_gtype_from_name (const gchar *name)
if (gtype_hash_serial != latest_serial)
{
add_operations (GEGL_TYPE_OPERATION);
+
gtype_hash_serial = latest_serial;
+
+ gegl_operations_update_visible ();
}
- return (GType) g_hash_table_lookup (gtype_hash, name);
+ return (GType) g_hash_table_lookup (visible_operation_names, name);
}
gboolean
@@ -130,6 +252,8 @@ gchar **gegl_list_operations (guint *n_operations_p)
}
}
+ g_mutex_lock (&operations_cache_mutex);
+
n_operations = g_slist_length (operations_list);
pasp_size += (n_operations + 1) * sizeof (gchar *);
for (iter = operations_list; iter != NULL; iter = g_slist_next (iter))
@@ -149,30 +273,42 @@ gchar **gegl_list_operations (guint *n_operations_p)
pasp[i] = NULL;
if (n_operations_p)
*n_operations_p = n_operations;
+
+ g_mutex_unlock (&operations_cache_mutex);
+
return pasp;
}
void
gegl_operation_gtype_init (void)
{
- G_LOCK (gtype_hash);
+ g_mutex_lock (&operations_cache_mutex);
- if (!gtype_hash)
- gtype_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+ if (!known_operation_names)
+ known_operation_names = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
- G_UNLOCK (gtype_hash);
+ if (!visible_operation_names)
+ visible_operation_names = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+
+ g_mutex_unlock (&operations_cache_mutex);
}
void
gegl_operation_gtype_cleanup (void)
{
- G_LOCK (gtype_hash);
- if (gtype_hash)
+ g_mutex_lock (&operations_cache_mutex);
+ if (known_operation_names)
{
- g_hash_table_destroy (gtype_hash);
- gtype_hash = NULL;
+ g_hash_table_destroy (known_operation_names);
+ known_operation_names = NULL;
+
+ g_hash_table_destroy (visible_operation_names);
+ visible_operation_names = NULL;
+
+ g_slist_free (operations_list);
+ operations_list = NULL;
}
- G_UNLOCK (gtype_hash);
+ g_mutex_unlock (&operations_cache_mutex);
}
gboolean gegl_can_do_inplace_processing (GeglOperation *operation,
diff --git a/gegl/operation/gegl-operations.h b/gegl/operation/gegl-operations.h
index dc9b5c3..2a58877 100644
--- a/gegl/operation/gegl-operations.h
+++ b/gegl/operation/gegl-operations.h
@@ -34,4 +34,6 @@ void gegl_operation_class_register_name (GeglOperationClass *klass,
const gchar *name,
const gboolean is_compat);
+void gegl_operations_set_licenses_from_string (const gchar *license_str);
+
#endif
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]