diff --git a/CHANGELOG.md b/CHANGELOG.md index 564e39b191..9050969d28 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,8 @@ Update to Python 3 - Have the default Unloggedin-look command look for optional `connection_screen()` callable in `mygame/server/conf/connection_screen.py`. This allows for more flexible welcome screens that are calculated on the fly. +- `@py` command now defaults to escaping html tags in its output when viewing in the webclient. + Use new `/clientraw` switch to get old behavior (issue #1369). ### Web diff --git a/evennia/commands/default/system.py b/evennia/commands/default/system.py index 66d66eefbe..94b0b45cd5 100644 --- a/evennia/commands/default/system.py +++ b/evennia/commands/default/system.py @@ -133,11 +133,13 @@ def _py_code(caller, buf): Execute the buffer. """ measure_time = caller.db._py_measure_time + client_raw = caller.db._py_clientraw string = "Executing code%s ..." % ( " (measure timing)" if measure_time else "") caller.msg(string) _run_code_snippet(caller, buf, mode="exec", measure_time=measure_time, + client_raw=client_raw, show_input=False) return True @@ -148,15 +150,16 @@ def _py_quit(caller): def _run_code_snippet(caller, pycode, mode="eval", measure_time=False, - show_input=True): + client_raw=False, show_input=True): """ Run code and try to display information to the caller. Args: - caller (Object): the caller. - pycode (str): the Python code to run. - m_time (bool, optional): should we measure the time of execution? - show_input (bookl, optional): should we display the input? + caller (Object): The caller. + pycode (str): The Python code to run. + measure_time (bool, optional): Should we measure the time of execution? + client_raw (bool, optional): Should we turn off all client-specific escaping? + show_input (bookl, optional): Should we display the input? """ # Try to retrieve the session @@ -211,9 +214,11 @@ def _run_code_snippet(caller, pycode, mode="eval", measure_time=False, for session in sessions: try: - caller.msg(ret, session=session, options={"raw": True}) + caller.msg(ret, session=session, options={"raw": True, + "client_raw": client_raw}) except TypeError: - caller.msg(ret, options={"raw": True}) + caller.msg(ret, options={"raw": True, + "client_raw": client_raw}) class CmdPy(COMMAND_DEFAULT_CLASS): @@ -227,6 +232,9 @@ class CmdPy(COMMAND_DEFAULT_CLASS): Switches: time - output an approximate execution time for edit - open a code editor for multi-line code experimentation + clientraw - turn off all client-specific escaping. Note that this may + lead to different output depending on prototocol (such as angular brackets + being parsed as HTML in the webclient but not in telnet clients) Separate multiple commands by ';' or open the editor using the /edit switch. A few variables are made available for convenience @@ -250,7 +258,7 @@ class CmdPy(COMMAND_DEFAULT_CLASS): """ key = "@py" aliases = ["!"] - switch_options = ("time", "edit") + switch_options = ("time", "edit", "clientraw") locks = "cmd:perm(py) or perm(Developer)" help_category = "System" @@ -262,6 +270,7 @@ class CmdPy(COMMAND_DEFAULT_CLASS): if "edit" in self.switches: caller.db._py_measure_time = "time" in self.switches + caller.db._py_clientraw = "clientraw" in self.switches EvEditor(self.caller, loadfunc=_py_load, savefunc=_py_code, quitfunc=_py_quit, key="Python exec: :w or :!", persistent=True, codefunc=_py_code) @@ -272,7 +281,8 @@ class CmdPy(COMMAND_DEFAULT_CLASS): self.msg(string) return - _run_code_snippet(caller, self.args, measure_time="time" in self.switches) + _run_code_snippet(caller, self.args, measure_time="time" in self.switches, + client_raw="clientraw" in self.switches) # helper function. Kept outside so it can be imported and run # by other commands. diff --git a/evennia/server/portal/webclient.py b/evennia/server/portal/webclient.py index 8d3acc5e88..ad7b56a3d6 100644 --- a/evennia/server/portal/webclient.py +++ b/evennia/server/portal/webclient.py @@ -16,6 +16,7 @@ from the command line and interprets it as an Evennia Command: `["text", ["look" """ import re import json +import html from twisted.internet.protocol import Protocol from django.conf import settings from evennia.server.session import Session @@ -198,6 +199,7 @@ class WebSocketClient(WebSocketServerProtocol, Session): options = kwargs.pop("options", {}) raw = options.get("raw", flags.get("RAW", False)) + client_raw = options.get("client_raw", False) nocolor = options.get("nocolor", flags.get("NOCOLOR", False)) screenreader = options.get("screenreader", flags.get("SCREENREADER", False)) prompt = options.get("send_prompt", False) @@ -208,7 +210,10 @@ class WebSocketClient(WebSocketServerProtocol, Session): text = _RE_SCREENREADER_REGEX.sub("", text) cmd = "prompt" if prompt else "text" if raw: - args[0] = text + if client_raw: + args[0] = text + else: + args[0] = html.escape(text) # escape html! else: args[0] = parse_html(text, strip_ansi=nocolor)