X-Git-Url: https://mudpy.org/gitweb?p=mudpy.git;a=blobdiff_plain;f=mudpy%2Fmisc.py;h=ec331a4b8dffdf7467de2e2b16bbc0da88417591;hp=dc37b6eacf41066b90ae683535613fabf5ad5049;hb=eecae7d240916774df48fc6fcf340fed86e3bb74;hpb=13138cabcedc52b00eb49b1a6b4e0818469bee74 diff --git a/mudpy/misc.py b/mudpy/misc.py index dc37b6e..ec331a4 100644 --- a/mudpy/misc.py +++ b/mudpy/misc.py @@ -1218,7 +1218,9 @@ def weighted_choice(data): expanded.append(key) # return one at random - return random.choice(expanded) + # Whitelist the random.randrange() call in bandit since it's not used for + # security/cryptographic purposes + return random.choice(expanded) # nosec def random_name(): @@ -1265,7 +1267,9 @@ def random_name(): name = "" # create a name of random length from the syllables - for _syllable in range(random.randrange(2, 6)): + # Whitelist the random.randrange() call in bandit since it's not used for + # security/cryptographic purposes + for _syllable in range(random.randrange(2, 6)): # nosec name += weighted_choice(syllables) # strip any leading quotemark, capitalize and return the name @@ -1432,9 +1436,12 @@ def reload_data(): """Reload all relevant objects.""" universe.save() old_userlist = universe.userlist[:] + old_loglines = universe.loglines[:] for element in list(universe.contents.values()): element.destroy() universe.load() + new_loglines = universe.loglines[:] + universe.loglines = old_loglines + new_loglines for user in old_userlist: user.reload() @@ -1585,16 +1592,15 @@ def get_menu_choices(user): state = universe.groups["menu"][user.state] create_choices = state.get("create") if create_choices: - choices = eval(create_choices) + choices = call_hook_function(create_choices, (user,)) else: choices = {} ignores = [] options = {} creates = {} for facet in state.facets(): - if facet.startswith("demand_") and not eval( - universe.groups["menu"][user.state].get(facet) - ): + if facet.startswith("demand_") and not call_hook_function( + universe.groups["menu"][user.state].get(facet), (user,)): ignores.append(facet.split("_", 2)[1]) elif facet.startswith("create_"): creates[facet] = facet.split("_", 2)[1] @@ -1602,7 +1608,8 @@ def get_menu_choices(user): options[facet] = facet.split("_", 2)[1] for facet in creates.keys(): if not creates[facet] in ignores: - choices[creates[facet]] = eval(state.get(facet)) + choices[creates[facet]] = call_hook_function( + state.get(facet), (user,)) for facet in options.keys(): if not options[facet] in ignores: choices[options[facet]] = state.get(facet) @@ -1677,6 +1684,28 @@ def get_choice_action(user): return "" +def call_hook_function(fname, arglist): + """Safely execute named function with supplied arguments, return result.""" + + # all functions relative to mudpy package + function = mudpy + + for component in fname.split("."): + try: + function = getattr(function, component) + except AttributeError: + log('Could not find mudpy.%s() for arguments "%s"' + % (fname, arglist), 7) + function = None + break + if function: + try: + return function(*arglist) + except Exception: + log('Calling mudpy.%s(%s) raised an exception...\n%s' + % (fname, (*arglist,), traceback.format_exc()), 7) + + def handle_user_input(user): """The main handler, branches to a state-specific handler.""" @@ -1711,7 +1740,9 @@ def generic_menu_handler(user): if not user.choice: user.choice = get_default_menu_choice(user.state) if user.choice in user.menu_choices: - exec(get_choice_action(user)) + action = get_choice_action(user) + if action: + call_hook_function(action, (user,)) new_state = get_choice_branch(user) if new_state: user.state = new_state @@ -1890,6 +1921,7 @@ def handler_active(user): ran = False if actor.can_run(command): # dereference the relative object path for the requested function + # TODO(fungi) use call_hook_function() here instead action = mudpy action_fname = command.get("action", command.key) for component in action_fname.split("."):