diff options
author | Joshua Leung <aligorith@gmail.com> | 2016-03-24 05:15:04 +0300 |
---|---|---|
committer | Joshua Leung <aligorith@gmail.com> | 2016-03-24 05:15:04 +0300 |
commit | c4956faf993c6fcd8e8726ed9d05d07682798454 (patch) | |
tree | a5b27a425c934f03c130328195c657e73f30c94f /source/blender/blenkernel/intern | |
parent | 322f86d6b330ebeb1da5c1f527714745dc901460 (diff) |
Drivers UI: Added name validation/linting for Driver Variables
When attempting to change a driver variable name to an "invalid" name,
an indicator will now be shown beside the offending variable name.
Clicking on this icon will show a popup which provides more information
about why the variable name cannot be used.
Reasons that it knows about are:
1) Starts with number
2) Has a dot
3) Has a space
4) Starts with or contains a special character
5) Starts with an underscore (Python does allow this, but it's bad practice,
and makes checking security of drivers harder)
6) Is a reserved Python keyword
Diffstat (limited to 'source/blender/blenkernel/intern')
-rw-r--r-- | source/blender/blenkernel/intern/fcurve.c | 65 |
1 files changed, 64 insertions, 1 deletions
diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index abf847274c4..e2b1acddc9c 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -1593,6 +1593,69 @@ void driver_change_variable_type(DriverVar *dvar, int type) DRIVER_TARGETS_LOOPER_END } +/* Validate driver name (after being renamed) */ +void driver_variable_name_validate(DriverVar *dvar) +{ + /* Special character blacklist */ + const char special_char_blacklist[] = { + '~', '`', '!', '@', '#', '$', '%', '^', '&', '*', '+', '=', '-', + '/', '\\', '?', ':', ';', '<', '>', '{', '}', '[', ']', '|', + ' ', '.', '\t', '\n', '\r' + }; + + /* sanity checks */ + if (dvar == NULL) + return; + + /* clear all invalid-name flags */ + dvar->flag &= ~DVAR_ALL_INVALID_FLAGS; + + /* 1) Must start with a letter */ + /* XXX: We assume that valid unicode letters in other languages are ok too, hence the blacklisting */ + if (ELEM(dvar->name[0], '0', '1', '2', '3', '4', '5', '6', '7', '8', '9')) { + dvar->flag |= DVAR_FLAG_INVALID_START_NUM; + } + else if (dvar->name[0] == '_') { + /* NOTE: We don't allow names to start with underscores (i.e. it helps when ruling out security risks) */ + dvar->flag |= DVAR_FLAG_INVALID_START_CHAR; + } + + /* 2) Must not contain invalid stuff in the middle of the string */ + if (strchr(dvar->name, ' ')) { + dvar->flag |= DVAR_FLAG_INVALID_HAS_SPACE; + } + if (strchr(dvar->name, '.')) { + dvar->flag |= DVAR_FLAG_INVALID_HAS_DOT; + } + + /* 3) Check for special characters - Either at start, or in the middle */ + for (int i = 0; i < sizeof(special_char_blacklist); i++) { + char *match = strchr(dvar->name, special_char_blacklist[i]); + + if (match == dvar->name) + dvar->flag |= DVAR_FLAG_INVALID_START_CHAR; + else if (match != NULL) + dvar->flag |= DVAR_FLAG_INVALID_HAS_SPECIAL; + } + + /* 4) Check if the name is a reserved keyword + * NOTE: These won't confuse Python, but it will be impossible to use the variable + * in an expression without Python misinterpreting what these are for + */ + if (STREQ(dvar->name, "if") || STREQ(dvar->name, "elif") || STREQ(dvar->name, "else") || + STREQ(dvar->name, "for") || STREQ(dvar->name, "while") || STREQ(dvar->name, "def") || + STREQ(dvar->name, "True") || STREQ(dvar->name, "False") || STREQ(dvar->name, "import") || + STREQ(dvar->name, "pass") || STREQ(dvar->name, "with")) + { + dvar->flag |= DVAR_FLAG_INVALID_PY_KEYWORD; + } + + + /* If any these conditions match, the name is invalid */ + if (dvar->flag & DVAR_ALL_INVALID_FLAGS) + dvar->flag |= DVAR_FLAG_INVALID_NAME; +} + /* Add a new driver variable */ DriverVar *driver_add_new_variable(ChannelDriver *driver) { @@ -1619,7 +1682,7 @@ DriverVar *driver_add_new_variable(ChannelDriver *driver) if (driver->type == DRIVER_TYPE_PYTHON) driver->flag |= DRIVER_FLAG_RENAMEVAR; #endif - + /* return the target */ return dvar; } |