diff options
-rw-r--r-- | libmproxy/console/common.py | 119 | ||||
-rw-r--r-- | libmproxy/console/flowlist.py | 13 | ||||
-rw-r--r-- | libmproxy/console/flowview.py | 15 |
3 files changed, 113 insertions, 34 deletions
diff --git a/libmproxy/console/common.py b/libmproxy/console/common.py index 12fdfe27..a9bd846b 100644 --- a/libmproxy/console/common.py +++ b/libmproxy/console/common.py @@ -207,7 +207,7 @@ def raw_format_flow(f, focus, extended, padding): # Save file to disk -def save_data(path, data, master, state): +def save_data(path, data): if not path: return try: @@ -217,32 +217,32 @@ def save_data(path, data, master, state): signals.status_message.send(message=v.strerror) -def ask_save_overwite(path, data, master, state): +def ask_save_overwrite(path, data): if not path: return path = os.path.expanduser(path) if os.path.exists(path): - def save_overwite(k): + def save_overwrite(k): if k == "y": - save_data(path, data, master, state) + save_data(path, data) signals.status_prompt_onekey.send( - prompt = "'" + path + "' already exists. Overwite?", + prompt = "'" + path + "' already exists. Overwrite?", keys = ( ("yes", "y"), ("no", "n"), ), - callback = save_overwite + callback = save_overwrite ) else: - save_data(path, data, master, state) + save_data(path, data) -def ask_save_path(prompt, data, master, state): +def ask_save_path(prompt, data): signals.status_prompt_path.send( prompt = prompt, - callback = ask_save_overwite, - args = (data, master, state) + callback = ask_save_overwrite, + args = (data, ) ) @@ -277,26 +277,60 @@ def copy_flow_format_data(part, scope, flow): return data, False -def copy_flow(part, scope, flow, master, state): - """ - part: _c_ontent, _h_eaders+content, _u_rl - scope: _a_ll, re_q_uest, re_s_ponse - """ - data, err = copy_flow_format_data(part, scope, flow) +def export_prompt(k, flow): + if k == "c": + copy_as_curl_command(flow) + elif k == "p": + copy_as_python_code(flow) + elif k == "r": + copy_as_raw_request(flow) - if err: - signals.status_message.send(message=err) - return - if not data: - if scope == "q": - signals.status_message.send(message="No request content to copy.") - elif scope == "s": - signals.status_message.send(message="No response content to copy.") - else: - signals.status_message.send(message="No contents to copy.") +def copy_as_curl_command(flow): + data = "curl " + + for k, v in flow.request.headers.fields: + data += "-H '%s:%s' " % (k, v) + + if flow.request.method != "GET": + data += "-X %s " % flow.request.method + + full_url = flow.request.scheme + "://" + flow.request.host + flow.request.path + data += "'%s'" % full_url + + if flow.request.content: + data += " --data-binary '%s'" % flow.request.content + + copy_to_clipboard_or_prompt(data) + + +def copy_as_python_code(flow): + if flow.request.method != "GET": + signals.status_message.send(message="Currently, only GET methods are supported") return + data = ("import requests\n" + "headers = {%s}\n" + "url = '%s'\n" + "resp = requests.get(url, headers=headers)") + + headers = "\n" + for k, v in flow.request.headers.fields: + headers += " '%s': '%s',\n" % (k, v) + + full_url = flow.request.scheme + "://" + flow.request.host + flow.request.path + + data = data % (headers, full_url) + + copy_to_clipboard_or_prompt(data) + + +def copy_as_raw_request(flow): + data = netlib.http.http1.assemble_request(flow.request) + copy_to_clipboard_or_prompt(data) + + +def copy_to_clipboard_or_prompt(data): # pyperclip calls encode('utf-8') on data to be copied without checking. # if data are already encoded that way UnicodeDecodeError is thrown. toclip = "" @@ -310,7 +344,7 @@ def copy_flow(part, scope, flow, master, state): except (RuntimeError, UnicodeDecodeError, AttributeError): def save(k): if k == "y": - ask_save_path("Save data", data, master, state) + ask_save_path("Save data", data) signals.status_prompt_onekey.send( prompt = "Cannot copy data to clipboard. Save as file?", keys = ( @@ -321,6 +355,29 @@ def copy_flow(part, scope, flow, master, state): ) +def copy_flow(part, scope, flow, master, state): + """ + part: _c_ontent, _h_eaders+content, _u_rl + scope: _a_ll, re_q_uest, re_s_ponse + """ + data, err = copy_flow_format_data(part, scope, flow) + + if err: + signals.status_message.send(message=err) + return + + if not data: + if scope == "q": + signals.status_message.send(message="No request content to copy.") + elif scope == "s": + signals.status_message.send(message="No response content to copy.") + else: + signals.status_message.send(message="No contents to copy.") + return + + copy_to_clipboard_or_prompt(data) + + def ask_copy_part(scope, flow, master, state): choices = [ ("content", "c"), @@ -367,16 +424,12 @@ def ask_save_body(part, master, state, flow): elif part == "q" and request_has_content: ask_save_path( "Save request content", - flow.request.get_decoded_content(), - master, - state + flow.request.get_decoded_content() ) elif part == "s" and response_has_content: ask_save_path( "Save response content", - flow.response.get_decoded_content(), - master, - state + flow.response.get_decoded_content() ) else: signals.status_message.send(message="No content to save.") diff --git a/libmproxy/console/flowlist.py b/libmproxy/console/flowlist.py index 2b77f4a3..2c18d197 100644 --- a/libmproxy/console/flowlist.py +++ b/libmproxy/console/flowlist.py @@ -16,6 +16,7 @@ def _mkhelp(): ("C", "clear flow list or eventlog"), ("d", "delete flow"), ("D", "duplicate flow"), + ("E", "export"), ("e", "toggle eventlog"), ("F", "toggle follow flow list"), ("l", "set limit filter pattern"), @@ -254,6 +255,18 @@ class ConnectionItem(urwid.WidgetWrap): ) elif key == "P": common.ask_copy_part("a", self.flow, self.master, self.state) + elif key == "E": + signals.status_prompt_onekey.send( + self, + prompt = "Export", + keys = ( + ("as curl command", "c"), + ("as python code", "p"), + ("as raw request", "r"), + ), + callback = common.export_prompt, + args = (self.flow,) + ) elif key == "b": common.ask_save_body(None, self.master, self.state, self.flow) else: diff --git a/libmproxy/console/flowview.py b/libmproxy/console/flowview.py index 0038558b..7962c69c 100644 --- a/libmproxy/console/flowview.py +++ b/libmproxy/console/flowview.py @@ -25,8 +25,9 @@ def _mkhelp(): ("A", "accept all intercepted flows"), ("a", "accept this intercepted flow"), ("b", "save request/response body"), - ("d", "delete flow"), ("D", "duplicate flow"), + ("d", "delete flow"), + ("E", "export"), ("e", "edit request/response"), ("f", "load full body data"), ("m", "change body display mode for this entity"), @@ -574,6 +575,18 @@ class FlowView(tabs.Tabs): callback = self.master.save_one_flow, args = (self.flow,) ) + elif key == "E": + signals.status_prompt_onekey.send( + self, + prompt = "Export", + keys = ( + ("as curl command", "c"), + ("as python code", "p"), + ("as raw request", "r"), + ), + callback = common.export_prompt, + args = (self.flow,) + ) elif key == "|": signals.status_prompt_path.send( prompt = "Send flow to script", |