diff --git a/mitmproxy/addons/replace.py b/mitmproxy/addons/replace.py index f929e5e23..54890ce56 100644 --- a/mitmproxy/addons/replace.py +++ b/mitmproxy/addons/replace.py @@ -8,13 +8,13 @@ from mitmproxy import ctx from mitmproxy.utils import strutils -def parse_hook(s): +def parse_replacements(s): """ - Returns a (pattern, regex, replacement) tuple. + Returns a (flow_filter, regex, replacement) tuple. - The general form for a replacement hook is as follows: + The general form for a replacements hook is as follows: - /patt/regex/replacement + [/flow_filter]/regex/replacement The first character specifies the separator. Example: @@ -23,7 +23,7 @@ def parse_hook(s): If only two clauses are specified, the pattern is set to match universally (i.e. ".*"). Example: - /foo/bar/ + /foo/bar Clauses are parsed from left to right. Extra separators are taken to be part of the final clause. For instance, the replacement clause below is @@ -34,15 +34,15 @@ def parse_hook(s): sep, rem = s[0], s[1:] parts = rem.split(sep, 2) if len(parts) == 2: - patt = ".*" - a, b = parts + flow_filter = ".*" + regex, repl = parts elif len(parts) == 3: - patt, a, b = parts + flow_filter, regex, repl = parts else: raise exceptions.OptionsError( - "Invalid replacement specifier: %s" % s + "Invalid replacements specifier: %s" % s ) - return patt, a, b + return flow_filter, regex, repl class Replace: @@ -53,50 +53,50 @@ class Replace: loader.add_option( "replacements", typing.Sequence[str], [], """ - Replacement patterns of the form "/pattern/regex/replacement", where + Replacement pattern of the form "[/flow-filter]/regex/replacement", where the separator can be any character. """ ) def configure(self, updated): """ - .replacements is a list of tuples (fpat, rex, s): + .replacements is a list of tuples (flow_filter_pattern, regex, repl): - fpatt: a string specifying a filter pattern. - rex: a regular expression, as string. - s: the replacement string + flow_filter_pattern: a string specifying a flow filter pattern. + regex: a regular expression, as string. + repl: the replacement string """ if "replacements" in updated: lst = [] for rep in ctx.options.replacements: - fpatt, rex, s = parse_hook(rep) + flow_filter_pattern, regex, repl = parse_replacements(rep) - flt = flowfilter.parse(fpatt) - if not flt: + flow_filter = flowfilter.parse(flow_filter_pattern) + if not flow_filter: raise exceptions.OptionsError( - "Invalid filter pattern: %s" % fpatt + "Invalid replacements flow filter: %s" % flow_filter_pattern ) try: # We should ideally escape here before trying to compile - re.compile(rex) + re.compile(regex) except re.error as e: raise exceptions.OptionsError( - "Invalid regular expression: %s - %s" % (rex, str(e)) + "Invalid regular expression: %s - %s" % (regex, str(e)) ) - if s.startswith("@") and not os.path.isfile(s[1:]): + if repl.startswith("@") and not os.path.isfile(repl[1:]): raise exceptions.OptionsError( - "Invalid file path: {}".format(s[1:]) + "Invalid file path: {}".format(repl[1:]) ) - lst.append((rex, s, flt)) + lst.append((regex, repl, flow_filter)) self.lst = lst def execute(self, f): - for rex, s, flt in self.lst: - if flt(f): + for regex, repl, flow_filter in self.lst: + if flow_filter(f): if f.response: - self.replace(f.response, rex, s) + self.replace(f.response, regex, repl) else: - self.replace(f.request, rex, s) + self.replace(f.request, regex, repl) def request(self, flow): if not flow.reply.has_message: @@ -106,7 +106,7 @@ class Replace: if not flow.reply.has_message: self.execute(flow) - def replace(self, obj, search, replace): + def replace(self, obj, search, repl): """ Replaces a regular expression pattern with repl in the body of the message. Encoded body will be decoded before replacement, and re-encoded afterwards. @@ -114,20 +114,20 @@ class Replace: Returns: The number of replacements made. """ - if replace.startswith("@"): - replace = os.path.expanduser(replace[1:]) + if repl.startswith("@"): + repl = os.path.expanduser(repl[1:]) try: - with open(replace, "rb") as f: - replace = f.read() + with open(repl, "rb") as f: + repl = f.read() except IOError: - ctx.log.warn("Could not read replacement file: %s" % replace) + ctx.log.warn("Could not read replacement file: %s" % repl) return if isinstance(search, str): search = strutils.escaped_str_to_bytes(search) - if isinstance(replace, str): - replace = strutils.escaped_str_to_bytes(replace) + if isinstance(repl, str): + repl = strutils.escaped_str_to_bytes(repl) replacements = 0 if obj.content: - obj.content, replacements = re.subn(search, replace, obj.content, flags=re.DOTALL) + obj.content, replacements = re.subn(search, repl, obj.content, flags=re.DOTALL) return replacements diff --git a/test/mitmproxy/addons/test_replace.py b/test/mitmproxy/addons/test_replace.py index dce58ae00..ab8401488 100644 --- a/test/mitmproxy/addons/test_replace.py +++ b/test/mitmproxy/addons/test_replace.py @@ -6,21 +6,21 @@ from mitmproxy.test import tflow class TestReplace: - def test_parse_hook(self): - x = replace.parse_hook("/foo/bar/voing") + def test_parse_replacements(self): + x = replace.parse_replacements("/foo/bar/voing") assert x == ("foo", "bar", "voing") - x = replace.parse_hook("/foo/bar/vo/ing/") + x = replace.parse_replacements("/foo/bar/vo/ing/") assert x == ("foo", "bar", "vo/ing/") - x = replace.parse_hook("/bar/voing") + x = replace.parse_replacements("/bar/voing") assert x == (".*", "bar", "voing") - with pytest.raises(Exception, match="Invalid replacement"): - replace.parse_hook("/") + with pytest.raises(Exception, match="Invalid replacements"): + replace.parse_replacements("/") def test_configure(self): r = replace.Replace() with taddons.context(r) as tctx: tctx.configure(r, replacements=["one/two/three"]) - with pytest.raises(Exception, match="Invalid filter pattern"): + with pytest.raises(Exception, match="Invalid replacements flow filter"): tctx.configure(r, replacements=["/~b/two/three"]) with pytest.raises(Exception, match="Invalid regular expression"): tctx.configure(r, replacements=["/foo/+/three"])