Escape html tag output from @py. Add /clientraw switch. Resolves #1369.

This commit is contained in:
Griatch 2019-03-30 23:01:28 +01:00
parent db3071356c
commit 6bd50543ff
3 changed files with 27 additions and 10 deletions

View file

@ -17,6 +17,8 @@ Update to Python 3
- Have the default Unloggedin-look command look for optional `connection_screen()` callable in - 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 `mygame/server/conf/connection_screen.py`. This allows for more flexible welcome screens
that are calculated on the fly. 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 ### Web

View file

@ -133,11 +133,13 @@ def _py_code(caller, buf):
Execute the buffer. Execute the buffer.
""" """
measure_time = caller.db._py_measure_time measure_time = caller.db._py_measure_time
client_raw = caller.db._py_clientraw
string = "Executing code%s ..." % ( string = "Executing code%s ..." % (
" (measure timing)" if measure_time else "") " (measure timing)" if measure_time else "")
caller.msg(string) caller.msg(string)
_run_code_snippet(caller, buf, mode="exec", _run_code_snippet(caller, buf, mode="exec",
measure_time=measure_time, measure_time=measure_time,
client_raw=client_raw,
show_input=False) show_input=False)
return True return True
@ -148,15 +150,16 @@ def _py_quit(caller):
def _run_code_snippet(caller, pycode, mode="eval", measure_time=False, 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. Run code and try to display information to the caller.
Args: Args:
caller (Object): the caller. caller (Object): The caller.
pycode (str): the Python code to run. pycode (str): The Python code to run.
m_time (bool, optional): should we measure the time of execution? measure_time (bool, optional): Should we measure the time of execution?
show_input (bookl, optional): should we display the input? 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 # Try to retrieve the session
@ -211,9 +214,11 @@ def _run_code_snippet(caller, pycode, mode="eval", measure_time=False,
for session in sessions: for session in sessions:
try: try:
caller.msg(ret, session=session, options={"raw": True}) caller.msg(ret, session=session, options={"raw": True,
"client_raw": client_raw})
except TypeError: except TypeError:
caller.msg(ret, options={"raw": True}) caller.msg(ret, options={"raw": True,
"client_raw": client_raw})
class CmdPy(COMMAND_DEFAULT_CLASS): class CmdPy(COMMAND_DEFAULT_CLASS):
@ -227,6 +232,9 @@ class CmdPy(COMMAND_DEFAULT_CLASS):
Switches: Switches:
time - output an approximate execution time for <cmd> time - output an approximate execution time for <cmd>
edit - open a code editor for multi-line code experimentation 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 Separate multiple commands by ';' or open the editor using the
/edit switch. A few variables are made available for convenience /edit switch. A few variables are made available for convenience
@ -250,7 +258,7 @@ class CmdPy(COMMAND_DEFAULT_CLASS):
""" """
key = "@py" key = "@py"
aliases = ["!"] aliases = ["!"]
switch_options = ("time", "edit") switch_options = ("time", "edit", "clientraw")
locks = "cmd:perm(py) or perm(Developer)" locks = "cmd:perm(py) or perm(Developer)"
help_category = "System" help_category = "System"
@ -262,6 +270,7 @@ class CmdPy(COMMAND_DEFAULT_CLASS):
if "edit" in self.switches: if "edit" in self.switches:
caller.db._py_measure_time = "time" 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, EvEditor(self.caller, loadfunc=_py_load, savefunc=_py_code,
quitfunc=_py_quit, key="Python exec: :w or :!", persistent=True, quitfunc=_py_quit, key="Python exec: :w or :!", persistent=True,
codefunc=_py_code) codefunc=_py_code)
@ -272,7 +281,8 @@ class CmdPy(COMMAND_DEFAULT_CLASS):
self.msg(string) self.msg(string)
return 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 # helper function. Kept outside so it can be imported and run
# by other commands. # by other commands.

View file

@ -16,6 +16,7 @@ from the command line and interprets it as an Evennia Command: `["text", ["look"
""" """
import re import re
import json import json
import html
from twisted.internet.protocol import Protocol from twisted.internet.protocol import Protocol
from django.conf import settings from django.conf import settings
from evennia.server.session import Session from evennia.server.session import Session
@ -198,6 +199,7 @@ class WebSocketClient(WebSocketServerProtocol, Session):
options = kwargs.pop("options", {}) options = kwargs.pop("options", {})
raw = options.get("raw", flags.get("RAW", False)) raw = options.get("raw", flags.get("RAW", False))
client_raw = options.get("client_raw", False)
nocolor = options.get("nocolor", flags.get("NOCOLOR", False)) nocolor = options.get("nocolor", flags.get("NOCOLOR", False))
screenreader = options.get("screenreader", flags.get("SCREENREADER", False)) screenreader = options.get("screenreader", flags.get("SCREENREADER", False))
prompt = options.get("send_prompt", False) prompt = options.get("send_prompt", False)
@ -208,7 +210,10 @@ class WebSocketClient(WebSocketServerProtocol, Session):
text = _RE_SCREENREADER_REGEX.sub("", text) text = _RE_SCREENREADER_REGEX.sub("", text)
cmd = "prompt" if prompt else "text" cmd = "prompt" if prompt else "text"
if raw: if raw:
args[0] = text if client_raw:
args[0] = text
else:
args[0] = html.escape(text) # escape html!
else: else:
args[0] = parse_html(text, strip_ansi=nocolor) args[0] = parse_html(text, strip_ansi=nocolor)