Fix for issues when using \ and " on the commander bar
This commit is contained in:
parent
d9572ef4a7
commit
c7ffc22819
|
@ -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())
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue