diff options
-rw-r--r-- | examples/__init__.py | 0 | ||||
-rw-r--r-- | examples/custom_contentviews.py | 2 | ||||
-rw-r--r-- | examples/iframe_injector.py | 2 | ||||
-rw-r--r-- | examples/modify_form.py | 6 | ||||
-rw-r--r-- | examples/modify_querystring.py | 5 | ||||
-rw-r--r-- | mitmproxy/console/__init__.py | 7 | ||||
-rw-r--r-- | mitmproxy/console/grideditor.py | 4 | ||||
-rwxr-xr-x | release/rtool.py | 31 | ||||
-rw-r--r-- | release/specs/mitmdump.spec | 3 | ||||
-rw-r--r-- | release/specs/mitmproxy.spec | 3 | ||||
-rw-r--r-- | release/specs/mitmweb.spec | 3 | ||||
-rw-r--r-- | release/specs/pathoc.spec | 3 | ||||
-rw-r--r-- | release/specs/pathod.spec | 3 | ||||
-rw-r--r-- | test/mitmproxy/test_examples.py | 119 | ||||
-rw-r--r-- | test/mitmproxy/test_flow_export.py | 1 | ||||
-rw-r--r-- | test/mitmproxy/test_har_extractor.py | 37 |
16 files changed, 159 insertions, 70 deletions
diff --git a/examples/__init__.py b/examples/__init__.py deleted file mode 100644 index e69de29b..00000000 --- a/examples/__init__.py +++ /dev/null diff --git a/examples/custom_contentviews.py b/examples/custom_contentviews.py index 776ba99d..f3b7317f 100644 --- a/examples/custom_contentviews.py +++ b/examples/custom_contentviews.py @@ -64,5 +64,5 @@ def start(context, argv): context.add_contentview(pig_view) -def stop(context): +def done(context): context.remove_contentview(pig_view) diff --git a/examples/iframe_injector.py b/examples/iframe_injector.py index fc38b136..ad844f19 100644 --- a/examples/iframe_injector.py +++ b/examples/iframe_injector.py @@ -14,7 +14,7 @@ def response(context, flow): if flow.request.host in context.iframe_url: return with decoded(flow.response): # Remove content encoding (gzip, ...) - html = BeautifulSoup(flow.response.content) + html = BeautifulSoup(flow.response.content, "lxml") if html.body: iframe = html.new_tag( "iframe", diff --git a/examples/modify_form.py b/examples/modify_form.py index 3e9d15c0..86188781 100644 --- a/examples/modify_form.py +++ b/examples/modify_form.py @@ -1,5 +1,5 @@ def request(context, flow): - if "application/x-www-form-urlencoded" in flow.request.headers.get("content-type", ""): - form = flow.request.get_form_urlencoded() + form = flow.request.urlencoded_form + if form is not None: form["mitmproxy"] = ["rocks"] - flow.request.set_form_urlencoded(form) + flow.request.urlencoded_form = form diff --git a/examples/modify_querystring.py b/examples/modify_querystring.py index 7f31a48f..d682df69 100644 --- a/examples/modify_querystring.py +++ b/examples/modify_querystring.py @@ -1,6 +1,5 @@ - def request(context, flow): - q = flow.request.get_query() + q = flow.request.query if q: q["mitmproxy"] = ["rocks"] - flow.request.set_query(q) + flow.request.query = q diff --git a/mitmproxy/console/__init__.py b/mitmproxy/console/__init__.py index f7e7b0d5..16615cbc 100644 --- a/mitmproxy/console/__init__.py +++ b/mitmproxy/console/__init__.py @@ -50,7 +50,7 @@ class ConsoleState(flow.State): if self.focus is None: self.set_focus(0) elif self.follow_focus: - self.set_focus(len(self.view) - 1) + self.update_focus() self.set_flow_marked(f, False) return f @@ -58,6 +58,8 @@ class ConsoleState(flow.State): super(ConsoleState, self).update_flow(f) if self.focus is None: self.set_focus(0) + elif self.follow_focus: + self.update_focus() return f def set_limit(self, limit): @@ -80,6 +82,9 @@ class ConsoleState(flow.State): else: self.focus = None + def update_focus(self): + self.set_focus(len(self.view) - 1) + def set_focus_flow(self, f): self.set_focus(self.view.index(f)) diff --git a/mitmproxy/console/grideditor.py b/mitmproxy/console/grideditor.py index a11c962c..597a7e7a 100644 --- a/mitmproxy/console/grideditor.py +++ b/mitmproxy/console/grideditor.py @@ -6,7 +6,7 @@ import os import urwid from netlib import odict -from netlib.http import user_agents +from netlib.http import user_agents, cookies from . import common, signals from .. import utils, filt, script @@ -69,7 +69,7 @@ class SubgridColumn: self.subeditor = subeditor def text(self, obj): - p = http_cookies._format_pairs(obj, sep="\n") + p = cookies._format_pairs(obj, sep="\n") return urwid.Text(p) def blank(self): diff --git a/release/rtool.py b/release/rtool.py index 5929452a..221ace0a 100755 --- a/release/rtool.py +++ b/release/rtool.py @@ -34,6 +34,7 @@ else: RELEASE_DIR = join(os.path.dirname(os.path.realpath(__file__))) DIST_DIR = join(RELEASE_DIR, "dist") ROOT_DIR = os.path.normpath(join(RELEASE_DIR, "..")) +RELEASE_SPEC_DIR = join(RELEASE_DIR, "specs") VERSION_FILE = join(ROOT_DIR, "netlib/version.py") BUILD_DIR = join(RELEASE_DIR, "build") @@ -226,20 +227,22 @@ def bdist(ctx, use_existing_wheels, pyinstaller_version): for bdist_project, tools in project["bdists"].items(): with Archive(join(DIST_DIR, archive_name(bdist_project))) as archive: for tool in tools: - spec = join(RELEASE_DIR, "specs/%s.spec" % tool) - print("Building %s binary..." % tool) - subprocess.check_call( - [ - VENV_PYINSTALLER, - "--clean", - "--workpath", PYINSTALLER_TEMP, - "--distpath", PYINSTALLER_DIST, - # This is PyInstaller, so setting a - # different log level obviously breaks it :-) - # "--log-level", "WARN", - spec - ] - ) + # This is PyInstaller, so it messes up paths. + # We need to make sure that we are in the spec folder. + with chdir(RELEASE_SPEC_DIR): + print("Building %s binary..." % tool) + subprocess.check_call( + [ + VENV_PYINSTALLER, + "--clean", + "--workpath", PYINSTALLER_TEMP, + "--distpath", PYINSTALLER_DIST, + # This is PyInstaller, so setting a + # different log level obviously breaks it :-) + # "--log-level", "WARN", + "%s.spec" % tool + ] + ) # Test if it works at all O:-) executable = join(PYINSTALLER_DIST, tool) diff --git a/release/specs/mitmdump.spec b/release/specs/mitmdump.spec index 149678df..fc145185 100644 --- a/release/specs/mitmdump.spec +++ b/release/specs/mitmdump.spec @@ -19,4 +19,5 @@ exe = EXE(pyz, debug=False, strip=None, upx=True, - console=True ) + console=True, + icon='icon.ico' ) diff --git a/release/specs/mitmproxy.spec b/release/specs/mitmproxy.spec index 1c481446..f7ea99f9 100644 --- a/release/specs/mitmproxy.spec +++ b/release/specs/mitmproxy.spec @@ -19,4 +19,5 @@ exe = EXE(pyz, debug=False, strip=None, upx=True, - console=True ) + console=True, + icon='icon.ico' ) diff --git a/release/specs/mitmweb.spec b/release/specs/mitmweb.spec index 79ccf71d..ea6192a4 100644 --- a/release/specs/mitmweb.spec +++ b/release/specs/mitmweb.spec @@ -19,4 +19,5 @@ exe = EXE(pyz, debug=False, strip=None, upx=True, - console=True ) + console=True, + icon='icon.ico' ) diff --git a/release/specs/pathoc.spec b/release/specs/pathoc.spec index 4f1f44be..d4f4d0d9 100644 --- a/release/specs/pathoc.spec +++ b/release/specs/pathoc.spec @@ -19,4 +19,5 @@ exe = EXE(pyz, debug=False, strip=None, upx=True, - console=True ) + console=True, + icon='icon.ico' ) diff --git a/release/specs/pathod.spec b/release/specs/pathod.spec index 3d2a8be2..f3a977f2 100644 --- a/release/specs/pathod.spec +++ b/release/specs/pathod.spec @@ -19,4 +19,5 @@ exe = EXE(pyz, debug=False, strip=None, upx=True, - console=True ) + console=True, + icon='icon.ico' ) diff --git a/test/mitmproxy/test_examples.py b/test/mitmproxy/test_examples.py index 163ace17..803776ac 100644 --- a/test/mitmproxy/test_examples.py +++ b/test/mitmproxy/test_examples.py @@ -1,11 +1,42 @@ import glob +import json +import os +from contextlib import contextmanager + from mitmproxy import utils, script from mitmproxy.proxy import config -from . import tservers +from netlib import tutils as netutils +from netlib.http import Headers +from . import tservers, tutils + +example_dir = utils.Data(__name__).path("../../examples") + + +class DummyContext(object): + """Emulate script.ScriptContext() functionality.""" + + contentview = None + + def log(self, *args, **kwargs): + pass + + def add_contentview(self, view_obj): + self.contentview = view_obj + + def remove_contentview(self, view_obj): + self.contentview = None + + +@contextmanager +def example(command): + command = os.path.join(example_dir, command) + ctx = DummyContext() + s = script.Script(command, ctx) + yield s + s.unload() def test_load_scripts(): - example_dir = utils.Data(__name__).path("../../examples") scripts = glob.glob("%s/*.py" % example_dir) tmaster = tservers.TestMaster(config.ProxyConfig()) @@ -28,3 +59,87 @@ def test_load_scripts(): raise else: s.unload() + + +def test_add_header(): + flow = tutils.tflow(resp=netutils.tresp()) + with example("add_header.py") as ex: + ex.run("response", flow) + assert flow.response.headers["newheader"] == "foo" + + +def test_custom_contentviews(): + with example("custom_contentviews.py") as ex: + pig = ex.ctx.contentview + _, fmt = pig("<html>test!</html>") + assert any('esttay!' in val[0][1] for val in fmt) + assert not pig("gobbledygook") + + +def test_iframe_injector(): + with tutils.raises(script.ScriptException): + with example("iframe_injector.py") as ex: + pass + + flow = tutils.tflow(resp=netutils.tresp(content="<html>mitmproxy</html>")) + with example("iframe_injector.py http://example.org/evil_iframe") as ex: + ex.run("response", flow) + content = flow.response.content + assert 'iframe' in content and 'evil_iframe' in content + + +def test_modify_form(): + form_header = Headers(content_type="application/x-www-form-urlencoded") + flow = tutils.tflow(req=netutils.treq(headers=form_header)) + with example("modify_form.py") as ex: + ex.run("request", flow) + assert flow.request.urlencoded_form["mitmproxy"] == ["rocks"] + + +def test_modify_querystring(): + flow = tutils.tflow(req=netutils.treq(path="/search?q=term")) + with example("modify_querystring.py") as ex: + ex.run("request", flow) + assert flow.request.query["mitmproxy"] == ["rocks"] + + +def test_modify_response_body(): + with tutils.raises(script.ScriptException): + with example("modify_response_body.py") as ex: + pass + + flow = tutils.tflow(resp=netutils.tresp(content="I <3 mitmproxy")) + with example("modify_response_body.py mitmproxy rocks") as ex: + assert ex.ctx.old == "mitmproxy" and ex.ctx.new == "rocks" + ex.run("response", flow) + assert flow.response.content == "I <3 rocks" + + +def test_redirect_requests(): + flow = tutils.tflow(req=netutils.treq(host="example.org")) + with example("redirect_requests.py") as ex: + ex.run("request", flow) + assert flow.request.host == "mitmproxy.org" + + +def test_har_extractor(): + with tutils.raises(script.ScriptException): + with example("har_extractor.py") as ex: + pass + + times = dict( + timestamp_start=746203272, + timestamp_end=746203272, + ) + + flow = tutils.tflow( + req=netutils.treq(**times), + resp=netutils.tresp(**times) + ) + + with example("har_extractor.py -") as ex: + ex.run("response", flow) + + with open(tutils.test_data.path("data/har_extractor.har")) as fp: + test_data = json.load(fp) + assert json.loads(ex.ctx.HARLog.json()) == test_data["test_response"] diff --git a/test/mitmproxy/test_flow_export.py b/test/mitmproxy/test_flow_export.py index 3dc07427..62161d5d 100644 --- a/test/mitmproxy/test_flow_export.py +++ b/test/mitmproxy/test_flow_export.py @@ -1,4 +1,3 @@ -import json from textwrap import dedent import netlib.tutils diff --git a/test/mitmproxy/test_har_extractor.py b/test/mitmproxy/test_har_extractor.py deleted file mode 100644 index 7838f713..00000000 --- a/test/mitmproxy/test_har_extractor.py +++ /dev/null @@ -1,37 +0,0 @@ -import json -import netlib.tutils -from . import tutils - -from examples import har_extractor - - -class Context(object): - pass - - -trequest = netlib.tutils.treq( - timestamp_start=746203272, - timestamp_end=746203272, -) - -tresponse = netlib.tutils.tresp( - timestamp_start=746203272, - timestamp_end=746203272, -) - - -def test_start(): - tutils.raises(ValueError, har_extractor.start, Context(), []) - - -def test_response(): - ctx = Context() - ctx.HARLog = har_extractor._HARLog([]) - ctx.seen_server = set() - - fl = tutils.tflow(req=trequest, resp=tresponse) - har_extractor.response(ctx, fl) - - with open(tutils.test_data.path("data/har_extractor.har")) as fp: - test_data = json.load(fp) - assert json.loads(ctx.HARLog.json()) == test_data["test_response"] |