Commit e236db25 authored by Daniel Sabo's avatar Daniel Sabo

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.
parent d39c4f98
......@@ -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 ();
......
......@@ -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
......
......@@ -45,6 +45,7 @@ struct _GeglConfig
gint threads;
gboolean use_opencl;
gint queue_size;
gchar *application_license;
};
struct _GeglConfigClass
......
......@@ -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 */
......
......@@ -171,6 +171,17 @@ gegl_swap_dir (void)
return swap_dir;
}
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,
......@@ -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;
}
......
......@@ -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,
......
......@@ -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
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment