app: in plug-ins, fix invalid parameter names instead of rejecting procedure

Instead of rejecting plug-in procedures with invalid parameter- or
return-value names (see issues #4392 and 4641), simply fix the
invalid name and allow the procedure to register.  Apparently,
there are plug-ins out there that use invalid parameter names (in
particular, liquid-rescale), so let's keep them working in 2.10.

Show appropriate warning/error for invalid parameter names when not
in PDB compat mode.
This commit is contained in:
Ell
2020-03-15 17:08:38 +02:00
parent e4d3d88ac6
commit 1af8ad8905
4 changed files with 169 additions and 84 deletions

View File

@ -33,143 +33,154 @@
#include "gimp-pdb-compat.h"
/* local function prototypes */
static gchar * gimp_pdb_compat_fix_param_name (const gchar *name);
/* public functions */
GParamSpec *
gimp_pdb_compat_param_spec (Gimp *gimp,
GimpPDBArgType arg_type,
const gchar *name,
const gchar *desc)
const gchar *desc,
gboolean *name_valid)
{
GParamSpec *pspec = NULL;
gchar *real_name;
g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL);
g_return_val_if_fail (name != NULL, NULL);
real_name = gimp_pdb_compat_fix_param_name (name);
if (name_valid) *name_valid = ! strcmp (name, real_name);
switch (arg_type)
{
case GIMP_PDB_INT32:
pspec = gimp_param_spec_int32 (name, name, desc,
pspec = gimp_param_spec_int32 (real_name, real_name, desc,
G_MININT32, G_MAXINT32, 0,
G_PARAM_READWRITE);
break;
case GIMP_PDB_INT16:
pspec = gimp_param_spec_int16 (name, name, desc,
pspec = gimp_param_spec_int16 (real_name, real_name, desc,
G_MININT16, G_MAXINT16, 0,
G_PARAM_READWRITE);
break;
case GIMP_PDB_INT8:
pspec = gimp_param_spec_int8 (name, name, desc,
pspec = gimp_param_spec_int8 (real_name, real_name, desc,
0, G_MAXUINT8, 0,
G_PARAM_READWRITE);
break;
case GIMP_PDB_FLOAT:
pspec = g_param_spec_double (name, name, desc,
pspec = g_param_spec_double (real_name, real_name, desc,
-G_MAXDOUBLE, G_MAXDOUBLE, 0.0,
G_PARAM_READWRITE);
break;
case GIMP_PDB_STRING:
pspec = gimp_param_spec_string (name, name, desc,
pspec = gimp_param_spec_string (real_name, real_name, desc,
TRUE, TRUE, FALSE,
NULL,
G_PARAM_READWRITE);
break;
case GIMP_PDB_INT32ARRAY:
pspec = gimp_param_spec_int32_array (name, name, desc,
pspec = gimp_param_spec_int32_array (real_name, real_name, desc,
G_PARAM_READWRITE);
break;
case GIMP_PDB_INT16ARRAY:
pspec = gimp_param_spec_int16_array (name, name, desc,
pspec = gimp_param_spec_int16_array (real_name, real_name, desc,
G_PARAM_READWRITE);
break;
case GIMP_PDB_INT8ARRAY:
pspec = gimp_param_spec_int8_array (name, name, desc,
pspec = gimp_param_spec_int8_array (real_name, real_name, desc,
G_PARAM_READWRITE);
break;
case GIMP_PDB_FLOATARRAY:
pspec = gimp_param_spec_float_array (name, name, desc,
pspec = gimp_param_spec_float_array (real_name, real_name, desc,
G_PARAM_READWRITE);
break;
case GIMP_PDB_STRINGARRAY:
pspec = gimp_param_spec_string_array (name, name, desc,
pspec = gimp_param_spec_string_array (real_name, real_name, desc,
G_PARAM_READWRITE);
break;
case GIMP_PDB_COLOR:
pspec = gimp_param_spec_rgb (name, name, desc,
pspec = gimp_param_spec_rgb (real_name, real_name, desc,
TRUE, NULL,
G_PARAM_READWRITE);
break;
case GIMP_PDB_ITEM:
pspec = gimp_param_spec_item_id (name, name, desc,
pspec = gimp_param_spec_item_id (real_name, real_name, desc,
gimp, TRUE,
G_PARAM_READWRITE);
break;
case GIMP_PDB_DISPLAY:
pspec = gimp_param_spec_display_id (name, name, desc,
pspec = gimp_param_spec_display_id (real_name, real_name, desc,
gimp, TRUE,
G_PARAM_READWRITE);
break;
case GIMP_PDB_IMAGE:
pspec = gimp_param_spec_image_id (name, name, desc,
pspec = gimp_param_spec_image_id (real_name, real_name, desc,
gimp, TRUE,
G_PARAM_READWRITE);
break;
case GIMP_PDB_LAYER:
pspec = gimp_param_spec_layer_id (name, name, desc,
pspec = gimp_param_spec_layer_id (real_name, real_name, desc,
gimp, TRUE,
G_PARAM_READWRITE);
break;
case GIMP_PDB_CHANNEL:
pspec = gimp_param_spec_channel_id (name, name, desc,
pspec = gimp_param_spec_channel_id (real_name, real_name, desc,
gimp, TRUE,
G_PARAM_READWRITE);
break;
case GIMP_PDB_DRAWABLE:
pspec = gimp_param_spec_drawable_id (name, name, desc,
pspec = gimp_param_spec_drawable_id (real_name, real_name, desc,
gimp, TRUE,
G_PARAM_READWRITE);
break;
case GIMP_PDB_SELECTION:
pspec = gimp_param_spec_selection_id (name, name, desc,
pspec = gimp_param_spec_selection_id (real_name, real_name, desc,
gimp, TRUE,
G_PARAM_READWRITE);
break;
case GIMP_PDB_COLORARRAY:
pspec = gimp_param_spec_color_array (name, name, desc,
pspec = gimp_param_spec_color_array (real_name, real_name, desc,
G_PARAM_READWRITE);
break;
case GIMP_PDB_VECTORS:
pspec = gimp_param_spec_vectors_id (name, name, desc,
pspec = gimp_param_spec_vectors_id (real_name, real_name, desc,
gimp, TRUE,
G_PARAM_READWRITE);
break;
case GIMP_PDB_PARASITE:
pspec = gimp_param_spec_parasite (name, name, desc,
pspec = gimp_param_spec_parasite (real_name, real_name, desc,
G_PARAM_READWRITE);
break;
case GIMP_PDB_STATUS:
pspec = g_param_spec_enum (name, name, desc,
pspec = g_param_spec_enum (real_name, real_name, desc,
GIMP_TYPE_PDB_STATUS_TYPE,
GIMP_PDB_EXECUTION_ERROR,
G_PARAM_READWRITE);
@ -180,8 +191,14 @@ gimp_pdb_compat_param_spec (Gimp *gimp,
}
if (! pspec)
g_warning ("%s: returning NULL for %s (%s)",
G_STRFUNC, name, gimp_pdb_compat_arg_type_to_string (arg_type));
{
g_warning ("%s: returning NULL for %s (%s)",
G_STRFUNC,
real_name,
gimp_pdb_compat_arg_type_to_string (arg_type));
}
g_free (real_name);
return pspec;
}
@ -501,3 +518,45 @@ gimp_pdb_compat_procs_register (GimpPDB *pdb,
compat_procs[i].new_name);
}
}
/* private functions */
/* Since GLib 2.63.3, invalid param-spec names are rejected upon creation.
* This impacts procedure parameters and return-values, which are stored as
* param-specs internally. Since this requirement wasn't previously enforced,
* keep supporting arbitrary parameter names in gimp-2.
*
* See issues #4392 and #4641.
*/
static gchar *
gimp_pdb_compat_fix_param_name (const gchar *name)
{
GString *new_name;
new_name = g_string_new (NULL);
/* First character must be a letter. */
if ((name[0] < 'A' || name[0] > 'Z') &&
(name[0] < 'a' || name[0] > 'z'))
{
g_string_append (new_name, "param-");
}
for (; *name; name++)
{
gchar c = *name;
if ((c < 'A' || c > 'Z') &&
(c < 'a' || c > 'z') &&
(c < '0' || c > '9') &&
c != '-' && c != '_')
{
c = '-';
}
g_string_append_c (new_name, c);
}
return g_string_free (new_name, FALSE);
}

View File

@ -22,7 +22,8 @@
GParamSpec * gimp_pdb_compat_param_spec (Gimp *gimp,
GimpPDBArgType arg_type,
const gchar *name,
const gchar *desc);
const gchar *desc,
gboolean *name_valid);
GType gimp_pdb_compat_arg_type_to_gtype (GimpPDBArgType type);
GimpPDBArgType gimp_pdb_compat_arg_type_from_gtype (GType type);

View File

@ -76,7 +76,6 @@ static void gimp_plug_in_handle_proc_uninstall (GimpPlugIn *plug_in,
static void gimp_plug_in_handle_extension_ack (GimpPlugIn *plug_in);
static void gimp_plug_in_handle_has_init (GimpPlugIn *plug_in);
static gboolean gimp_plug_in_is_valid_property_name (const gchar *name);
/* public functions */
@ -863,49 +862,105 @@ gimp_plug_in_handle_proc_install (GimpPlugIn *plug_in,
for (i = 0; i < proc_install->nparams; i++)
{
GParamSpec *pspec;
gboolean name_valid;
if (! gimp_plug_in_is_valid_property_name (proc_install->params[i].name))
{
gimp_message (plug_in->manager->gimp, NULL, GIMP_MESSAGE_ERROR,
"Plug-in \"%s\"\n(%s)\n"
"attempted to install procedure \"%s\" with "
"invalid parameter name \"%s\".",
gimp_object_get_name (plug_in),
gimp_file_get_utf8_name (plug_in->file),
canonical, proc_install->params[i].name);
g_object_unref (procedure);
return;
}
pspec = gimp_pdb_compat_param_spec (plug_in->manager->gimp,
proc_install->params[i].type,
proc_install->params[i].name,
proc_install->params[i].description);
proc_install->params[i].description,
&name_valid);
gimp_procedure_add_argument (procedure, pspec);
if (pspec && ! name_valid)
{
switch (plug_in->manager->gimp->pdb_compat_mode)
{
case GIMP_PDB_COMPAT_ON:
break;
case GIMP_PDB_COMPAT_WARN:
gimp_message (plug_in->manager->gimp, NULL, GIMP_MESSAGE_WARNING,
"Plug-in \"%s\"\n(%s)\n"
"attempted to install procedure \"%s\" "
"with invalid parameter name \"%s\".\n"
"This is deprecated.\n"
"The parameter name was changed to \"%s\".",
gimp_object_get_name (plug_in),
gimp_file_get_utf8_name (plug_in->file),
gimp_object_get_name (proc),
proc_install->params[i].name,
pspec->name);
break;
case GIMP_PDB_COMPAT_OFF:
gimp_message (plug_in->manager->gimp, NULL, GIMP_MESSAGE_ERROR,
"Plug-in \"%s\"\n(%s)\n"
"attempted to install procedure \"%s\" "
"with invalid parameter name \"%s\".\n"
"This is not allowed.",
gimp_object_get_name (plug_in),
gimp_file_get_utf8_name (plug_in->file),
gimp_object_get_name (proc),
proc_install->params[i].name);
g_object_unref (proc);
return;
}
}
}
for (i = 0; i < proc_install->nreturn_vals; i++)
{
GParamSpec *pspec;
gboolean name_valid;
if (! gimp_plug_in_is_valid_property_name (proc_install->return_vals[i].name))
{
gimp_message (plug_in->manager->gimp, NULL, GIMP_MESSAGE_ERROR,
"Plug-in \"%s\"\n(%s)\n"
"attempted to install procedure \"%s\" with "
"invalid return value name \"%s\".",
gimp_object_get_name (plug_in),
gimp_file_get_utf8_name (plug_in->file),
canonical, proc_install->return_vals[i].name);
g_object_unref (procedure);
return;
}
pspec = gimp_pdb_compat_param_spec (plug_in->manager->gimp,
proc_install->return_vals[i].type,
proc_install->return_vals[i].name,
proc_install->return_vals[i].description);
proc_install->return_vals[i].description,
&name_valid);
gimp_procedure_add_return_value (procedure, pspec);
if (pspec && ! name_valid)
{
switch (plug_in->manager->gimp->pdb_compat_mode)
{
case GIMP_PDB_COMPAT_ON:
break;
case GIMP_PDB_COMPAT_WARN:
gimp_message (plug_in->manager->gimp, NULL, GIMP_MESSAGE_WARNING,
"Plug-in \"%s\"\n(%s)\n"
"attempted to install procedure \"%s\" "
"with invalid return-value name \"%s\".\n"
"This is deprecated.\n"
"The return-value name was changed to \"%s\".",
gimp_object_get_name (plug_in),
gimp_file_get_utf8_name (plug_in->file),
gimp_object_get_name (proc),
proc_install->return_vals[i].name,
pspec->name);
break;
case GIMP_PDB_COMPAT_OFF:
gimp_message (plug_in->manager->gimp, NULL, GIMP_MESSAGE_ERROR,
"Plug-in \"%s\"\n(%s)\n"
"attempted to install procedure \"%s\" "
"with invalid return-value name \"%s\".\n"
"This is not allowed.",
gimp_object_get_name (plug_in),
gimp_file_get_utf8_name (plug_in->file),
gimp_object_get_name (proc),
proc_install->return_vals[i].name);
g_object_unref (proc);
return;
}
}
}
/* Sanity check menu path */
@ -1006,33 +1061,3 @@ gimp_plug_in_handle_has_init (GimpPlugIn *plug_in)
gimp_plug_in_close (plug_in, TRUE);
}
}
/*
* XXX: this function should be removed when/if it becomes public in
* glib, i.e. when this patch is merged:
* https://gitlab.gnome.org/GNOME/glib/merge_requests/1302
* See #4392.
*/
static gboolean
gimp_plug_in_is_valid_property_name (const gchar *name)
{
const gchar *p;
/* First character must be a letter. */
if ((name[0] < 'A' || name[0] > 'Z') &&
(name[0] < 'a' || name[0] > 'z'))
return FALSE;
for (p = name; *p != 0; p++)
{
const gchar c = *p;
if (c != '-' && c != '_' &&
(c < '0' || c > '9') &&
(c < 'A' || c > 'Z') &&
(c < 'a' || c > 'z'))
return FALSE;
}
return TRUE;
}

View File

@ -784,7 +784,7 @@ plug_in_proc_arg_deserialize (GScanner *scanner,
token = G_TOKEN_LEFT_PAREN;
pspec = gimp_pdb_compat_param_spec (gimp, arg_type, name, desc);
pspec = gimp_pdb_compat_param_spec (gimp, arg_type, name, desc, NULL);
if (return_value)
gimp_procedure_add_return_value (procedure, pspec);