Remove the use of eval for evaluating custom notification logic

This commit is contained in:
JonnyWong16 2017-07-05 19:13:02 -07:00
parent d4e5a750e0
commit 161e6f70d0
2 changed files with 43 additions and 5 deletions

View file

@ -814,6 +814,7 @@ def parse_condition_logic_string(s, num_cond=0):
bool_next = False bool_next = False
open_bracket_next = True open_bracket_next = True
close_bracket_next = False close_bracket_next = False
nest_and = False
for i, x in enumerate(tokens): for i, x in enumerate(tokens):
if open_bracket_next and x == '(': if open_bracket_next and x == '(':
@ -823,6 +824,7 @@ def parse_condition_logic_string(s, num_cond=0):
bool_next = False bool_next = False
open_bracket_next = True open_bracket_next = True
close_bracket_next = False close_bracket_next = False
nest_and = False
elif close_bracket_next and x == ')': elif close_bracket_next and x == ')':
stack.pop() stack.pop()
@ -832,6 +834,7 @@ def parse_condition_logic_string(s, num_cond=0):
bool_next = True bool_next = True
open_bracket_next = False open_bracket_next = False
close_bracket_next = True close_bracket_next = True
nest_and = False
elif cond_next and re.match(conditions_pattern, x): elif cond_next and re.match(conditions_pattern, x):
try: try:
@ -840,18 +843,33 @@ def parse_condition_logic_string(s, num_cond=0):
raise ValueError('invalid condition logic') raise ValueError('invalid condition logic')
if not 0 < num <= num_cond: if not 0 < num <= num_cond:
raise ValueError('invalid condition number in condition logic') raise ValueError('invalid condition number in condition logic')
stack[-1].append(x) stack[-1].append(num)
if nest_and:
stack.pop()
cond_next = False cond_next = False
bool_next = True bool_next = True
open_bracket_next = False open_bracket_next = False
close_bracket_next = True close_bracket_next = True
nest_and = False
elif bool_next and x in ('and', 'or') and i < len(tokens)-1: elif bool_next and x == 'and' and i < len(tokens)-1:
stack[-1].append([])
stack.append(stack[-1][-1])
stack[-1].append(stack[-2].pop(-2))
stack[-1].append(x) stack[-1].append(x)
cond_next = True cond_next = True
bool_next = False bool_next = False
open_bracket_next = True open_bracket_next = True
close_bracket_next = False close_bracket_next = False
nest_and = True
elif bool_next and x == 'or' and i < len(tokens)-1:
stack[-1].append(x)
cond_next = True
bool_next = False
open_bracket_next = True
close_bracket_next = False
nest_and = False
else: else:
raise ValueError('invalid condition logic') raise ValueError('invalid condition logic')
@ -867,3 +885,24 @@ def nested_list_to_string(l):
l[i] = nested_list_to_string(x) l[i] = nested_list_to_string(x)
s = '(' + ' '.join(l) + ')' s = '(' + ' '.join(l) + ')'
return s return s
def eval_logic_groups_to_bool(logic_groups, eval_conds):
first_cond = logic_groups[0]
if isinstance(first_cond, list):
result = eval_logic_groups_to_bool(first_cond, eval_conds)
else:
result = eval_conds[first_cond]
for op, cond in zip(logic_groups[1::2], logic_groups[2::2]):
if isinstance(cond, list):
eval_cond = eval_logic_groups_to_bool(cond, eval_conds)
else:
eval_cond = eval_conds[cond]
if op == 'and':
result = result and eval_cond
elif op == 'or':
result = result or eval_cond
return result

View file

@ -205,7 +205,6 @@ def notify_custom_conditions(notifier_id=None, parameters=None):
try: try:
# Parse and validate the custom conditions logic # Parse and validate the custom conditions logic
logic_groups = helpers.parse_condition_logic_string(custom_conditions_logic, len(custom_conditions)) logic_groups = helpers.parse_condition_logic_string(custom_conditions_logic, len(custom_conditions))
logic_string = helpers.nested_list_to_string(logic_groups)
except ValueError as e: except ValueError as e:
logger.error(u"PlexPy NotificationHandler :: Unable to parse custom condition logic '%s': %s." logger.error(u"PlexPy NotificationHandler :: Unable to parse custom condition logic '%s': %s."
% (custom_conditions_logic, e)) % (custom_conditions_logic, e))
@ -291,7 +290,7 @@ def notify_custom_conditions(notifier_id=None, parameters=None):
# Format and evaluate the logic string # Format and evaluate the logic string
try: try:
evaluated_logic = bool(eval(logic_string.format(*evaluated_conditions))) evaluated_logic = helpers.eval_logic_groups_to_bool(logic_groups, evaluated_conditions)
except Exception as e: except Exception as e:
logger.error(u"PlexPy NotificationHandler :: Unable to evaluate custom condition logic: %s." % e) logger.error(u"PlexPy NotificationHandler :: Unable to evaluate custom condition logic: %s." % e)
return False return False