diff options
-rw-r--r-- | libmproxy/cmdline.py | 36 | ||||
-rw-r--r-- | libmproxy/console.py | 1 | ||||
-rw-r--r-- | libmproxy/flow.py | 13 | ||||
-rw-r--r-- | libmproxy/plugins.py | 46 | ||||
-rw-r--r-- | libmproxy/script.py | 75 | ||||
-rwxr-xr-x | test/scripts/a | 9 | ||||
-rw-r--r-- | test/scripts/a.py (renamed from test/plugins/a.py) | 0 | ||||
-rwxr-xr-x | test/scripts/err_data | 2 | ||||
-rwxr-xr-x | test/scripts/err_return | 6 | ||||
-rw-r--r-- | test/scripts/loaderr.py | 3 | ||||
-rw-r--r-- | test/scripts/nonexecutable | 0 | ||||
-rw-r--r-- | test/scripts/syntaxerr.py (renamed from test/plugins/syntaxerr.py) | 0 | ||||
-rw-r--r-- | test/test_plugins.py | 35 | ||||
-rw-r--r-- | test/test_proxy.py | 2 | ||||
-rw-r--r-- | test/test_script.py | 51 |
15 files changed, 128 insertions, 151 deletions
diff --git a/libmproxy/cmdline.py b/libmproxy/cmdline.py index 5f51b854..8be419a6 100644 --- a/libmproxy/cmdline.py +++ b/libmproxy/cmdline.py @@ -25,9 +25,8 @@ def get_common_options(options): refresh_server_playback = not options.norefresh, rheaders = options.rheaders, rfile = options.rfile, - request_script = options.request_script, - response_script = options.response_script, server_replay = options.server_replay, + script = options.script, stickycookie = stickycookie, stickyauth = stickyauth, wfile = options.wfile, @@ -42,6 +41,16 @@ def common_options(parser): help = "Address to bind proxy to (defaults to all interfaces)" ) parser.add_option( + "--anticache", + action="store_true", dest="anticache", default=False, + help="Strip out request headers that might cause the server to return 304-not-modified." + ) + parser.add_option( + "--confdir", + action="store", type = "str", dest="confdir", default='~/.mitmproxy', + help = "Configuration directory. (~/.mitmproxy)" + ) + parser.add_option( "-d", action="store_true", dest="autodecode", help="Automatically decode compressed server responses." @@ -52,11 +61,6 @@ def common_options(parser): help="Show event log." ) parser.add_option( - "--confdir", - action="store", type = "str", dest="confdir", default='~/.mitmproxy', - help = "Configuration directory. (~/.mitmproxy)" - ) - parser.add_option( "-n", action="store_true", dest="no_server", help="Don't start a proxy server." @@ -77,19 +81,9 @@ def common_options(parser): help="Read flows from file." ) parser.add_option( - "--anticache", - action="store_true", dest="anticache", default=False, - help="Strip out request headers that might cause the server to return 304-not-modified." - ) - parser.add_option( - "--reqscript", - action="store", dest="request_script", default=None, - help="Script to run when a request is recieved." - ) - parser.add_option( - "--respscript", - action="store", dest="response_script", default=None, - help="Script to run when a response is recieved." + "-s", + action="store", dest="script", default=None, + help="Run a script." ) parser.add_option( "-t", @@ -143,7 +137,7 @@ def common_options(parser): group = optparse.OptionGroup(parser, "Server Replay") group.add_option( - "-s", + "-S", action="store", dest="server_replay", default=None, metavar="PATH", help="Replay server responses from a saved file." ) diff --git a/libmproxy/console.py b/libmproxy/console.py index 39fb871f..ae3210e7 100644 --- a/libmproxy/console.py +++ b/libmproxy/console.py @@ -852,6 +852,7 @@ class Options(object): "request_script", "response_script", "rfile", + "script", "rheaders", "server_replay", "stickycookie", diff --git a/libmproxy/flow.py b/libmproxy/flow.py index 57bcc878..92a4e812 100644 --- a/libmproxy/flow.py +++ b/libmproxy/flow.py @@ -462,8 +462,8 @@ class FlowMaster(controller.Master): self.state = state self.server_playback = None self.client_playback = None - self.scripts = {} self.kill_nonreplay = False + self.plugin = None self.stickycookie_state = False self.stickycookie_txt = None @@ -481,11 +481,8 @@ class FlowMaster(controller.Master): raise NotImplementedError #end nocover - def set_response_script(self, s): - self.scripts["response"] = s - - def set_request_script(self, s): - self.scripts["request"] = s + def set_plugin(self, p): + self.plugin = p def set_stickycookie(self, txt): if txt: @@ -582,8 +579,6 @@ class FlowMaster(controller.Master): if self.stickyauth_state: self.stickyauth_state.handle_request(f) - if "request" in self.scripts: - self._runscript(f, self.scripts["request"]) if self.anticache: f.request.anticache() if self.anticomp: @@ -600,8 +595,6 @@ class FlowMaster(controller.Master): def process_new_response(self, f): if self.stickycookie_state: self.stickycookie_state.handle_response(f) - if "response" in self.scripts: - self._runscript(f, self.scripts["response"]) def replay_request(self, f): """ diff --git a/libmproxy/plugins.py b/libmproxy/plugins.py deleted file mode 100644 index 09c2edf8..00000000 --- a/libmproxy/plugins.py +++ /dev/null @@ -1,46 +0,0 @@ -import imp, os, traceback - - -class Context: - def __init__(self, master, state): - self.master, self.state = master, state - - def log(self, *args, **kwargs): - self.master.log(*args, **kwargs) - - -class Plugin: - def __init__(self, path, master): - self.path = path - self.ctx = Context(master, master.state) - self.mod = None - self.ns = None - self.load() - - def load(self): - """ - Loads a module and runs the start method. - """ - ns = {} - self.mod = execfile(os.path.expanduser(self.path), {}, ns) - self.ns = ns - self.run("start") - - def run(self, name, *args, **kwargs): - """ - Runs a plugin method. - - Returns: - - (True, retval) on success. - (False, None) on nonexistent method. - (Fals, (exc, traceback string)) if there was an exception. - """ - f = self.ns.get(name) - if f: - try: - return (True, f(self.ctx, *args, **kwargs)) - except Exception, v: - return (False, (v, traceback.format_exc(v))) - else: - return (False, None) diff --git a/libmproxy/script.py b/libmproxy/script.py index 92563cde..da3131a8 100644 --- a/libmproxy/script.py +++ b/libmproxy/script.py @@ -1,26 +1,59 @@ -""" - The mitmproxy scripting interface is simple - a serialized representation - of a flow is passed to the script on stdin, and a possibly modified flow is - then read by mitmproxy from the scripts stdout. This module provides two - convenience functions to make loading and returning data from scripts - simple. -""" -import sys -import flow - -#begin nocover -def load_flow(): - """ - Load a flow from the stdin. Returns a Flow object. - """ - data = sys.stdin.read() - return flow.Flow.script_deserialize(data) +import imp, os, traceback + +class ScriptError(Exception): + pass + +class Context: + def __init__(self, master, state): + self.master, self.state = master, state + + def log(self, *args, **kwargs): + self.master.log(*args, **kwargs) -def return_flow(f): +class Script: """ - Print a flow to stdout. + The instantiator should do something along this vein: + + s = Script(path, master) + s.load() + s.run("start") """ - print >> sys.stdout, f.script_serialize() - + def __init__(self, path, master): + self.path = path + self.ctx = Context(master, master.state) + self.mod = None + self.ns = None + + def load(self): + """ + Loads a module. + + Raises ScriptError on failure, with argument equal to an error + message that may be a formatted traceback. + """ + ns = {} + try: + self.mod = execfile(os.path.expanduser(self.path), {}, ns) + except Exception, v: + raise ScriptError(traceback.format_exc(v)) + self.ns = ns + + def run(self, name, *args, **kwargs): + """ + Runs a plugin method. + + Returns: + (True, retval) on success. + (False, None) on nonexistent method. + (Fals, (exc, traceback string)) if there was an exception. + """ + f = self.ns.get(name) + if f: + try: + return (True, f(self.ctx, *args, **kwargs)) + except Exception, v: + return (False, (v, traceback.format_exc(v))) + else: + return (False, None) diff --git a/test/scripts/a b/test/scripts/a deleted file mode 100755 index fb4a7b82..00000000 --- a/test/scripts/a +++ /dev/null @@ -1,9 +0,0 @@ -#!/usr/bin/env python -import sys -sys.path.insert(0, "..") -from libmproxy import script - -f = script.load_flow() -f.request.host = "TESTOK" -print >> sys.stderr, "DEBUG" -script.return_flow(f) diff --git a/test/plugins/a.py b/test/scripts/a.py index 0a21b619..0a21b619 100644 --- a/test/plugins/a.py +++ b/test/scripts/a.py diff --git a/test/scripts/err_data b/test/scripts/err_data deleted file mode 100755 index 4bb1b1ba..00000000 --- a/test/scripts/err_data +++ /dev/null @@ -1,2 +0,0 @@ -#!/usr/bin/env python -print "NONSENSE" diff --git a/test/scripts/err_return b/test/scripts/err_return deleted file mode 100755 index 09e9eb5e..00000000 --- a/test/scripts/err_return +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env python -import sys -sys.path.insert(0, "..") -print >> sys.stderr, "output" -sys.exit(1) - diff --git a/test/scripts/loaderr.py b/test/scripts/loaderr.py new file mode 100644 index 00000000..8dc4d56d --- /dev/null +++ b/test/scripts/loaderr.py @@ -0,0 +1,3 @@ + + +a = x diff --git a/test/scripts/nonexecutable b/test/scripts/nonexecutable deleted file mode 100644 index e69de29b..00000000 --- a/test/scripts/nonexecutable +++ /dev/null diff --git a/test/plugins/syntaxerr.py b/test/scripts/syntaxerr.py index 219d6b84..219d6b84 100644 --- a/test/plugins/syntaxerr.py +++ b/test/scripts/syntaxerr.py diff --git a/test/test_plugins.py b/test/test_plugins.py deleted file mode 100644 index 135d93ce..00000000 --- a/test/test_plugins.py +++ /dev/null @@ -1,35 +0,0 @@ -import os -from libmproxy import plugins, flow -import libpry - -class uPlugin(libpry.AutoTree): - def test_simple(self): - s = flow.State() - fm = flow.FlowMaster(None, s) - - p = plugins.Plugin(os.path.join("plugins", "a.py"), fm) - assert "here" in p.ns - assert p.run("here") == (True, 1) - assert p.run("here") == (True, 2) - - ret = p.run("errargs") - assert not ret[0] - assert len(ret[1]) == 2 - - # Check reload - p.load() - assert p.run("here") == (True, 1) - - def test_err(self): - s = flow.State() - fm = flow.FlowMaster(None, s) - - libpry.raises(IOError, plugins.Plugin, "nonexistent", fm) - libpry.raises(SyntaxError, plugins.Plugin, os.path.join("plugins", "syntaxerr.py"), fm) - - - -tests = [ - uPlugin(), -] - diff --git a/test/test_proxy.py b/test/test_proxy.py index 83898d11..196942b3 100644 --- a/test/test_proxy.py +++ b/test/test_proxy.py @@ -1,6 +1,6 @@ import cStringIO, time, re import libpry -from libmproxy import proxy, controller, utils, dump, script +from libmproxy import proxy, controller, utils, dump import email.utils import tutils diff --git a/test/test_script.py b/test/test_script.py new file mode 100644 index 00000000..f6cfcced --- /dev/null +++ b/test/test_script.py @@ -0,0 +1,51 @@ +import os +from libmproxy import script, flow +import libpry + +class uScript(libpry.AutoTree): + def test_simple(self): + s = flow.State() + fm = flow.FlowMaster(None, s) + + p = script.Script(os.path.join("scripts", "a.py"), fm) + p.load() + assert "here" in p.ns + assert p.run("here") == (True, 1) + assert p.run("here") == (True, 2) + + ret = p.run("errargs") + assert not ret[0] + assert len(ret[1]) == 2 + + # Check reload + p.load() + assert p.run("here") == (True, 1) + + def test_err(self): + s = flow.State() + fm = flow.FlowMaster(None, s) + + s = script.Script("nonexistent", fm) + libpry.raises( + script.ScriptError, + s.load + ) + + s = script.Script(os.path.join("scripts", "syntaxerr.py"), fm) + libpry.raises( + script.ScriptError, + s.load + ) + + s = script.Script(os.path.join("scripts", "loaderr.py"), fm) + libpry.raises( + script.ScriptError, + s.load + ) + + + +tests = [ + uScript(), +] + |