diff --git a/libmproxy/console.py b/libmproxy/console.py index 5ed672447..0df1339cb 100644 --- a/libmproxy/console.py +++ b/libmproxy/console.py @@ -61,8 +61,11 @@ def format_flow(f, focus, padding=3): ] if f.response or f.error or f.is_replay(): txt.append("\n" + " "*(padding+2)) + met = "" if f.is_replay(): txt.append(("method", "[replay] ")) + elif f.modified(): + txt.append(("method", "[edited] ")) if not (f.response or f.error): txt.append(("text", "waiting for response...")) @@ -504,6 +507,9 @@ class ConnectionView(WWrap): try: newflow, serr = self.flow.run_script(path) except flow.RunException, e: + if e.errout: + serr = "Script error code: %s\n\n"%e.returncode + e.errout + self.master.spawn_external_viewer(serr, None) self.master.statusbar.message("Script error: %s"%e) return if serr: diff --git a/libmproxy/flow.py b/libmproxy/flow.py index d3bba4b38..cf39bed96 100644 --- a/libmproxy/flow.py +++ b/libmproxy/flow.py @@ -6,7 +6,12 @@ import subprocess, base64, sys from contrib import bson import proxy, threading -class RunException(Exception): pass +class RunException(Exception): + def __init__(self, msg, returncode, errout): + Exception.__init__(self, msg) + self.returncode = returncode + self.errout = errout + class ReplayConnection: pass @@ -58,6 +63,7 @@ class Flow: Returns a (flow, stderr output) tuple, or raises RunException if there's an error. """ + self.backup() data = self.script_serialize() try: p = subprocess.Popen( @@ -67,13 +73,21 @@ class Flow: stderr=subprocess.PIPE, ) except OSError, e: - raise RunException(e.args[1]) + raise RunException(e.args[1], None, None) so, se = p.communicate(data) if p.returncode: - raise RunException("Script returned error code %s"%p.returncode) + raise RunException( + "Script returned error code %s"%p.returncode, + p.returncode, + se + ) f = Flow.script_deserialize(so) if not f: - raise RunException("Invalid response from script.") + raise RunException( + "Invalid response from script.", + p.returncode, + se + ) return f, se def dump(self): @@ -106,6 +120,14 @@ class Flow: def __eq__(self, other): return self.get_state() == other.get_state() + def modified(self): + # FIXME: Save a serialization in backup, compare current with + # backup to detect if flow has _really_ been modified. + if self._backup: + return True + else: + return False + def backup(self): if not self._backup: self._backup = [ @@ -119,6 +141,7 @@ class Flow: if self._backup: restore = [i.copy() if i else None for i in self._backup] self.connection, self.request, self.response, self.error = restore + self._backup = None def match(self, pattern): if pattern: diff --git a/test/test_flow.py b/test/test_flow.py index 3ff106d84..470547a5e 100644 --- a/test/test_flow.py +++ b/test/test_flow.py @@ -28,7 +28,9 @@ class uFlow(libpry.AutoTree): def test_backup(self): f = utils.tflow() + assert not f.modified() f.backup() + assert f.modified() f.revert() def test_getset_state(self):