aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libmproxy/console/__init__.py18
-rw-r--r--libmproxy/console/flowview.py6
-rw-r--r--libmproxy/console/grideditor.py63
-rw-r--r--libmproxy/flow.py9
-rw-r--r--test/test_flow.py11
5 files changed, 69 insertions, 38 deletions
diff --git a/libmproxy/console/__init__.py b/libmproxy/console/__init__.py
index 960e4bd7..10c189e5 100644
--- a/libmproxy/console/__init__.py
+++ b/libmproxy/console/__init__.py
@@ -119,6 +119,10 @@ class StatusBar(common.WWrap):
def get_status(self):
r = []
+ if self.master.replacehooks.count():
+ r.append("[")
+ r.append(("heading_key", "R"))
+ r.append("eplace]")
if self.master.client_playback:
r.append("[")
r.append(("heading_key", "cplayback"))
@@ -543,8 +547,8 @@ class ConsoleMaster(flow.FlowMaster):
self.header = None
self.make_view()
- def view_grideditor(self, title, value, callback, *args, **kwargs):
- self.body = grideditor.GridEditor(self, title, value, callback, *args, **kwargs)
+ def view_grideditor(self, title, columns, value, callback, *args, **kwargs):
+ self.body = grideditor.GridEditor(self, title, columns, value, callback, *args, **kwargs)
self.header = None
self.help_context = grideditor.help_context
self.statusbar = StatusBar(self, self.footer_text_help)
@@ -705,6 +709,9 @@ class ConsoleMaster(flow.FlowMaster):
else:
self.view_flowlist()
+ def set_replace(self, r):
+ pass
+
def loop(self):
changed = True
try:
@@ -782,6 +789,13 @@ class ConsoleMaster(flow.FlowMaster):
self.set_reverse_proxy
)
self.sync_list_view()
+ elif k == "R":
+ self.view_grideditor(
+ "Editing replacements",
+ 3,
+ self.replacehooks.get_specs(),
+ self.set_replace
+ )
elif k == "s":
if self.script:
self.load_script(None)
diff --git a/libmproxy/console/flowview.py b/libmproxy/console/flowview.py
index 6f864f92..5044990b 100644
--- a/libmproxy/console/flowview.py
+++ b/libmproxy/console/flowview.py
@@ -395,7 +395,7 @@ class ConnectionView(common.WWrap):
conn.set_form_urlencoded(flow.ODict(lst))
def edit_form(self, conn):
- self.master.view_grideditor("Editing form", conn.get_form_urlencoded().lst, self.set_form, conn)
+ self.master.view_grideditor("Editing form", 2, conn.get_form_urlencoded().lst, self.set_form, conn)
def edit_form_confirm(self, key, conn):
if key == "y":
@@ -427,9 +427,9 @@ class ConnectionView(common.WWrap):
else:
self.edit_form(conn)
elif part == "h":
- self.master.view_grideditor("Editing headers", conn.headers.lst, self.set_headers, conn)
+ self.master.view_grideditor("Editing headers", 2, conn.headers.lst, self.set_headers, conn)
elif part == "q":
- self.master.view_grideditor("Editing query", conn.get_query().lst, self.set_query, conn)
+ self.master.view_grideditor("Editing query", 2, conn.get_query().lst, self.set_query, conn)
elif part == "u" and self.state.view_flow_mode == common.VIEW_FLOW_REQUEST:
self.master.prompt_edit("URL", conn.get_url(), self.set_url)
elif part == "m" and self.state.view_flow_mode == common.VIEW_FLOW_REQUEST:
diff --git a/libmproxy/console/grideditor.py b/libmproxy/console/grideditor.py
index 479486e0..19fa4374 100644
--- a/libmproxy/console/grideditor.py
+++ b/libmproxy/console/grideditor.py
@@ -67,31 +67,32 @@ class SEdit(common.WWrap):
class GridItem(common.WWrap):
- def __init__(self, focused, editing, maxk, k, v):
+ def __init__(self, focused, editing, maxk, values):
self.focused, self.editing, self.maxk = focused, editing, maxk
- if focused == 0 and editing:
- self.editing = self.kf = SEdit(k)
- else:
- self.kf = SText(k, True if focused == 0 else False)
- if focused == 1 and editing:
- self.editing = self.vf = SEdit(v)
- else:
- self.vf = SText(v, True if focused == 1 else False)
+ self.fields = []
+ for i, v in enumerate(values):
+ if focused == i and editing:
+ self.editing = SEdit(v)
+ self.fields.append(self.editing)
+ else:
+ self.fields.append(
+ SText(v, True if focused == i else False)
+ )
+
+ fspecs = self.fields[:]
+ fspecs[0] = ("fixed", maxk + 2, fspecs[0])
w = urwid.Columns(
- [
- ("fixed", maxk + 2, self.kf),
- self.vf
- ],
+ fspecs,
dividechars = 2
)
if focused is not None:
w.set_focus_column(focused)
common.WWrap.__init__(self, w)
- def get_kv(self):
- return (self.kf.get_text(), self.vf.get_text())
+ def get_value(self):
+ return [i.get_text() for i in self.fields]
def keypress(self, s, k):
if self.editing:
@@ -105,10 +106,13 @@ class GridItem(common.WWrap):
KEY_MAX = 30
class GridWalker(urwid.ListWalker):
def __init__(self, lst, editor):
+ self.maxk = 20
+ if lst:
+ for i, r in enumerate(lst):
+ assert len(r) == editor.columns
+ self.maxk = max(len(r), self.maxk)
+ self.maxk = min(self.maxk, KEY_MAX)
self.lst, self.editor = lst, editor
- self.maxk = min(max(len(v[0]) for v in lst), KEY_MAX) if lst else 20
- if self.maxk < 20:
- self.maxk = 20
self.focus = 0
self.focus_col = 0
self.editing = False
@@ -134,7 +138,7 @@ class GridWalker(urwid.ListWalker):
def _insert(self, pos):
self.focus = pos
- self.lst.insert(self.focus, ("", ""))
+ self.lst.insert(self.focus, [""]*self.editor.columns)
self.focus_col = 0
self.start_edit()
@@ -146,27 +150,27 @@ class GridWalker(urwid.ListWalker):
def start_edit(self):
if self.lst:
- self.editing = GridItem(self.focus_col, True, self.maxk, *self.lst[self.focus])
+ self.editing = GridItem(self.focus_col, True, self.maxk, self.lst[self.focus])
self._modified()
def stop_edit(self):
if self.editing:
- self.lst[self.focus] = self.editing.get_kv()
+ self.lst[self.focus] = self.editing.get_value()
self.editing = False
self._modified()
def left(self):
- self.focus_col = 0
+ self.focus_col = max(self.focus_col - 1, 0)
self._modified()
def right(self):
- self.focus_col = 1
+ self.focus_col = min(self.focus_col + 1, self.editor.columns-1)
self._modified()
def tab_next(self):
self.stop_edit()
- if self.focus_col == 0:
- self.focus_col = 1
+ if self.focus_col < self.editor.columns-1:
+ self.focus_col += 1
elif self.focus != len(self.lst)-1:
self.focus_col = 0
self.focus += 1
@@ -176,7 +180,7 @@ class GridWalker(urwid.ListWalker):
if self.editing:
return self.editing, self.focus
elif self.lst:
- return GridItem(self.focus_col, False, self.maxk, *self.lst[self.focus]), self.focus
+ return GridItem(self.focus_col, False, self.maxk, self.lst[self.focus]), self.focus
else:
return None, None
@@ -187,12 +191,12 @@ class GridWalker(urwid.ListWalker):
def get_next(self, pos):
if pos+1 >= len(self.lst):
return None, None
- return GridItem(None, False, self.maxk, *self.lst[pos+1]), pos+1
+ return GridItem(None, False, self.maxk, self.lst[pos+1]), pos+1
def get_prev(self, pos):
if pos-1 < 0:
return None, None
- return GridItem(None, False, self.maxk, *self.lst[pos-1]), pos-1
+ return GridItem(None, False, self.maxk, self.lst[pos-1]), pos-1
class GridListBox(urwid.ListBox):
@@ -201,9 +205,10 @@ class GridListBox(urwid.ListBox):
class GridEditor(common.WWrap):
- def __init__(self, master, title, value, callback, *cb_args, **cb_kwargs):
+ def __init__(self, master, title, columns, value, callback, *cb_args, **cb_kwargs):
value = copy.deepcopy(value)
self.master, self.title, self.value, self.callback = master, title, value, callback
+ self.columns = columns
self.cb_args, self.cb_kwargs = cb_args, cb_kwargs
p = urwid.Text(title)
p = urwid.Padding(p, align="left", width=("relative", 100))
diff --git a/libmproxy/flow.py b/libmproxy/flow.py
index 438cb9ad..59520167 100644
--- a/libmproxy/flow.py
+++ b/libmproxy/flow.py
@@ -58,6 +58,15 @@ class ReplaceHooks:
if (fpatt, rex, s) == self.lst[i][:3]:
del self.lst[i]
+ def get_specs(self):
+ """
+ Retrieve the hook specifcations. Returns a list of (fpatt, rex, s) tuples.
+ """
+ return [i[:3] for i in self.lst]
+
+ def count(self):
+ return len(self.lst)
+
def run(self, f):
for _, rex, s, cpatt in self.lst:
if cpatt(f):
diff --git a/test/test_flow.py b/test/test_flow.py
index cd4de7ea..68555bd5 100644
--- a/test/test_flow.py
+++ b/test/test_flow.py
@@ -1046,13 +1046,16 @@ class uReplaceHooks(libpry.AutoTree):
h.add("~q", "foo", "bar")
h.add("~s", "foo", "bar")
- assert len(h.lst) == 2
+
+ v = h.get_specs()
+ assert v == [('~q', 'foo', 'bar'), ('~s', 'foo', 'bar')]
+ assert h.count() == 2
h.remove("~q", "foo", "bar")
- assert len(h.lst) == 1
+ assert h.count() == 1
h.remove("~q", "foo", "bar")
- assert len(h.lst) == 1
+ assert h.count() == 1
h.clear()
- assert len(h.lst) == 0
+ assert h.count() == 0
f = tutils.tflow()
f.request.content = "foo"