aboutsummaryrefslogtreecommitdiffstats
path: root/libmproxy
diff options
context:
space:
mode:
Diffstat (limited to 'libmproxy')
-rw-r--r--libmproxy/console/__init__.py4
-rw-r--r--libmproxy/console/connlist.py5
-rw-r--r--libmproxy/console/connview.py6
-rw-r--r--libmproxy/flow.py37
4 files changed, 43 insertions, 9 deletions
diff --git a/libmproxy/console/__init__.py b/libmproxy/console/__init__.py
index 6fc37a47..ca80d013 100644
--- a/libmproxy/console/__init__.py
+++ b/libmproxy/console/__init__.py
@@ -516,9 +516,7 @@ class ConsoleMaster(flow.FlowMaster):
def focus_current(self):
if self.currentflow:
try:
- ids = [id(i) for i in self.state.view]
- idx = ids.index(id(self.currentflow))
- self.conn_list_view.set_focus(idx)
+ self.conn_list_view.set_focus(self.state.index(self.currentflow))
except (IndexError, ValueError):
pass
diff --git a/libmproxy/console/connlist.py b/libmproxy/console/connlist.py
index 957e797b..f54b8061 100644
--- a/libmproxy/console/connlist.py
+++ b/libmproxy/console/connlist.py
@@ -8,6 +8,7 @@ def _mkhelp():
("a", "accept this intercepted connection"),
("C", "clear connection list or eventlog"),
("d", "delete flow"),
+ ("D", "duplicate flow"),
("e", "toggle eventlog"),
("l", "set limit filter pattern"),
("L", "load saved flows"),
@@ -101,6 +102,10 @@ class ConnectionItem(common.WWrap):
self.flow.kill(self.master)
self.state.delete_flow(self.flow)
self.master.sync_list_view()
+ elif key == "D":
+ f = self.master.duplicate_flow(self.flow)
+ self.master.currentflow = f
+ self.master.focus_current()
elif key == "l":
self.master.prompt("Limit: ", self.state.limit_txt, self.master.set_limit)
self.master.sync_list_view()
diff --git a/libmproxy/console/connview.py b/libmproxy/console/connview.py
index d668bfe2..ed038a11 100644
--- a/libmproxy/console/connview.py
+++ b/libmproxy/console/connview.py
@@ -10,6 +10,7 @@ def _mkhelp():
("a", "accept this intercepted connection"),
("b", "save request/response body"),
("d", "delete flow"),
+ ("D", "duplicate flow"),
("e", "edit request/response"),
("m", "change body display mode"),
(None,
@@ -463,6 +464,11 @@ class ConnectionView(common.WWrap):
f = self.flow
f.kill(self.master)
self.state.delete_flow(f)
+ elif key == "D":
+ f = self.master.duplicate_flow(self.flow)
+ self.master.view_flow(f)
+ self.master.currentflow = f
+ self.master.statusbar.message("Duplicated.")
elif key == "e":
if self.state.view_flow_mode == common.VIEW_FLOW_REQUEST:
self.master.prompt_onekey(
diff --git a/libmproxy/flow.py b/libmproxy/flow.py
index 81199035..db4cde5e 100644
--- a/libmproxy/flow.py
+++ b/libmproxy/flow.py
@@ -851,6 +851,17 @@ class Flow:
self.intercepting = False
self._backup = None
+ def copy(self):
+ rc = self.request.copy()
+ f = Flow(rc)
+ if self.response:
+ f.response = self.response.copy()
+ f.response.request = rc
+ if self.error:
+ f.error = self.error.copy()
+ f.error.request = rc
+ return f
+
@classmethod
def _from_state(klass, state):
f = klass(None)
@@ -997,6 +1008,9 @@ class State(object):
def flow_count(self):
return len(self._flow_map)
+ def index(self, f):
+ return self._flow_list.index(f)
+
def active_flow_count(self):
c = 0
for i in self._flow_list:
@@ -1011,6 +1025,7 @@ class State(object):
f = Flow(req)
self._flow_list.append(f)
self._flow_map[req] = f
+ assert len(self._flow_list) == len(self._flow_map)
if f.match(self._limit):
self.view.append(f)
return f
@@ -1235,17 +1250,27 @@ class FlowMaster(controller.Master):
return controller.Master.tick(self, q)
+ def duplicate_flow(self, f):
+ return self.load_flow(f.copy())
+
+ def load_flow(self, f):
+ """
+ Loads a flow, and returns a new flow object.
+ """
+ if f.request:
+ fr = self.handle_request(f.request)
+ if f.response:
+ self.handle_response(f.response)
+ if f.error:
+ self.handle_error(f.error)
+ return fr
+
def load_flows(self, fr):
"""
Load flows from a FlowReader object.
"""
for i in fr.stream():
- if i.request:
- self.handle_request(i.request)
- if i.response:
- self.handle_response(i.response)
- if i.error:
- self.handle_error(i.error)
+ self.load_flow(i)
def process_new_request(self, f):
if self.stickycookie_state: