Fix for issues when using \ and " on the commander bar

This commit is contained in:
Henrique 2019-11-12 18:57:39 -05:00
parent d9572ef4a7
commit c7ffc22819
4 changed files with 63 additions and 17 deletions

View File

@ -13,6 +13,46 @@ import sys
from mitmproxy import exceptions
import mitmproxy.types
def maybequote(value):
"""
This function takes the output from the lexer and puts it between quotes
in the following cases:
* There is a space in the string: The only way a token from the lexer can have a space in it is if it was between quotes
* There is one or more quotes in the middle of the string: The only way for a token to have a quote in it that is not escaped is if it was escaped prior to being processed by the lexer. For example, the string `"s1 \" s2"` would come back from the lexer as `s1 " s2`.
Any quotes that are in the middle of the string and that are not escaped will also be escaped (by placing a \ in front of it).
This function only deals with double quotes and they are the only ones that should be used.
"""
new_value = ""
last_pos = len(value) - 1
for pos, char in enumerate(value):
if pos == 0:
new_value += char
continue
# if pos == last_pos:
# new_value += char
# break
if char in " \n\r\t":
new_value += char
continue
if char == '"':
if value[pos-1] != '\\':
new_value += '\\'
new_value += char
value = new_value
if ((" " in value) or ('"' in value)) and not (value.startswith("\"") or value.startswith("'")):
return "\"%s\"" % value
return value
def verify_arg_signature(f: typing.Callable, args: list, kwargs: dict) -> None:
sig = inspect.signature(f)
@ -201,9 +241,11 @@ class CommandManager(mitmproxy.types._CommandBase):
else:
valid = True
# if ctx.log:
# ctx.log.info('[gilga] before parse.append. value = %s' % parts[i])
parse.append(
ParseResult(
value=parts[i],
value=maybequote(parts[i]),
type=typ,
valid=valid,
)
@ -236,13 +278,21 @@ class CommandManager(mitmproxy.types._CommandBase):
"""
Execute a command string. May raise CommandError.
"""
if cmdstr == '':
raise exceptions.CommandError("Invalid command: %s" % cmdstr)
try:
parts = list(lexer(cmdstr))
parts, _ = self.parse_partial(cmdstr)
except ValueError as e:
raise exceptions.CommandError("Command error: %s" % e)
if not len(parts) >= 1:
if len(parts) == 0:
raise exceptions.CommandError("Invalid command: %s" % cmdstr)
return self.call_strings(parts[0], parts[1:])
params = []
for p in parts:
params.append(p.value)
return self.call_strings(params[0], params[1:])
def dump(self, out=sys.stdout) -> None:
cmds = list(self.commands.values())

View File

@ -501,6 +501,7 @@ def _make():
pp.Word(alphlatinB) |\
pp.QuotedString("\"", escChar='\\') |\
pp.QuotedString("'", escChar='\\')
for klass in filter_rex:
f = pp.Literal("~%s" % klass.code) + pp.WordEnd() + rex.copy()
f.setParseAction(klass.make)

View File

@ -70,16 +70,11 @@ class CommandBuffer:
else:
self._cursor = x
def maybequote(self, value):
if " " in value and not value.startswith("\""):
return "\"%s\"" % value
return value
def parse_quoted(self, txt):
parts, remhelp = self.master.commands.parse_partial(txt)
for i, p in enumerate(parts):
parts[i] = mitmproxy.command.ParseResult(
value = self.maybequote(p.value),
value = p.value,
type = p.type,
valid = p.valid
)
@ -145,7 +140,7 @@ class CommandBuffer:
def backspace(self) -> None:
if self.cursor == 0:
return
self.text = self.flatten(self.text[:self.cursor - 1] + self.text[self.cursor:])
self.text = self.text[:self.cursor - 1] + self.text[self.cursor:]
self.cursor = self.cursor - 1
self.completion = None
@ -153,8 +148,8 @@ class CommandBuffer:
"""
Inserts text at the cursor.
"""
self.text = self.flatten(self.text[:self.cursor] + k + self.text[self.cursor:])
self.cursor += 1
self.text = self.text[:self.cursor] + k + self.text[self.cursor:]
self.cursor += len(k)
self.completion = None

View File

@ -249,10 +249,10 @@ class TestCommand:
["str"]
],
[
"flow \"one two\"",
"flow \"three four\"",
[
command.ParseResult(value = "flow", type = mitmproxy.types.Cmd, valid = True),
command.ParseResult(value = "one two", type = flow.Flow, valid = False),
command.ParseResult(value = '"three four"', type = flow.Flow, valid = False),
],
["str"]
],
@ -270,7 +270,7 @@ def test_simple():
c = command.CommandManager(tctx.master)
a = TAddon()
c.add("one.two", a.cmd1)
assert c.commands["one.two"].help == "cmd1 help"
assert(c.commands["one.two"].help == "cmd1 help")
assert(c.execute("one.two foo") == "ret foo")
assert(c.call("one.two", "foo") == "ret foo")
with pytest.raises(exceptions.CommandError, match="Unknown"):
@ -281,7 +281,7 @@ def test_simple():
c.execute("one.two too many args")
with pytest.raises(exceptions.CommandError, match="Unknown"):
c.call("nonexistent")
with pytest.raises(exceptions.CommandError, match="No escaped"):
with pytest.raises(exceptions.CommandError, match="Unknown"):
c.execute("\\")
c.add("empty", a.empty)