From dde0ff50a5e3c3e6f7e839c76b92076bfbeba583 Mon Sep 17 00:00:00 2001 From: Ryan Welton Date: Mon, 8 Jun 2015 22:27:14 -0400 Subject: Add copy as curl command --- libmproxy/console/common.py | 59 ++++++++++++++++++++++++++++++------------- libmproxy/console/flowlist.py | 3 +++ libmproxy/console/flowview.py | 3 +++ 3 files changed, 48 insertions(+), 17 deletions(-) (limited to 'libmproxy') diff --git a/libmproxy/console/common.py b/libmproxy/console/common.py index 12fdfe27..f28db013 100644 --- a/libmproxy/console/common.py +++ b/libmproxy/console/common.py @@ -276,27 +276,30 @@ def copy_flow_format_data(part, scope, flow): raise ValueError("Unknown part: {}".format(part)) return data, False +def copy_as_curl_command(flow): -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 flow.request.content is None or flow.request.content == CONTENT_MISSING: + return None, "Request content is missing" - if err: - signals.status_message.send(message=err) - return + headerString = "" + for k,v in flow.request.headers: + headerString += " -H \"" + k + ":" + v + "\" " + + data = "curl" + + if flow.request.method != "GET": + data += " -X " + flow.request.method + + full_url = flow.request.scheme + "://" + flow.request.host + flow.request.path + data += headerString + " \"" + full_url + "\"" + + if flow.request.content != None and flow.request.content != "": + data += " --data-binary " + "'" + flow.request.content + "'" + + copy_to_clipboard_or_prompt(data) - 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 +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 = "" @@ -320,6 +323,28 @@ def copy_flow(part, scope, flow, master, state): callback = save ) +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 = [ diff --git a/libmproxy/console/flowlist.py b/libmproxy/console/flowlist.py index 2b77f4a3..6edf5212 100644 --- a/libmproxy/console/flowlist.py +++ b/libmproxy/console/flowlist.py @@ -13,6 +13,7 @@ def _mkhelp(): ("A", "accept all intercepted flows"), ("a", "accept this intercepted flow"), ("b", "save request/response body"), + ("Z", "copy request as curl command"), ("C", "clear flow list or eventlog"), ("d", "delete flow"), ("D", "duplicate flow"), @@ -254,6 +255,8 @@ class ConnectionItem(urwid.WidgetWrap): ) elif key == "P": common.ask_copy_part("a", self.flow, self.master, self.state) + elif key == "Z": + common.copy_as_curl_command(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..518817d4 100644 --- a/libmproxy/console/flowview.py +++ b/libmproxy/console/flowview.py @@ -25,6 +25,7 @@ def _mkhelp(): ("A", "accept all intercepted flows"), ("a", "accept this intercepted flow"), ("b", "save request/response body"), + ("Z", "copy as curl command"), ("d", "delete flow"), ("D", "duplicate flow"), ("e", "edit request/response"), @@ -574,6 +575,8 @@ class FlowView(tabs.Tabs): callback = self.master.save_one_flow, args = (self.flow,) ) + elif key == "Z": + common.copy_as_curl_command(self.flow) elif key == "|": signals.status_prompt_path.send( prompt = "Send flow to script", -- cgit v1.2.3 From b424c1d43fd5ae8d103cdc64ba36d3a014093903 Mon Sep 17 00:00:00 2001 From: Ryan Welton Date: Tue, 9 Jun 2015 12:28:37 -0400 Subject: Switch to single quotes --- libmproxy/console/common.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'libmproxy') diff --git a/libmproxy/console/common.py b/libmproxy/console/common.py index f28db013..90c10b8f 100644 --- a/libmproxy/console/common.py +++ b/libmproxy/console/common.py @@ -283,7 +283,7 @@ def copy_as_curl_command(flow): headerString = "" for k,v in flow.request.headers: - headerString += " -H \"" + k + ":" + v + "\" " + headerString += " -H '" + k + ":" + v + "' " data = "curl" @@ -291,7 +291,7 @@ def copy_as_curl_command(flow): data += " -X " + flow.request.method full_url = flow.request.scheme + "://" + flow.request.host + flow.request.path - data += headerString + " \"" + full_url + "\"" + data += " " + headerString + "'" + full_url + "'" if flow.request.content != None and flow.request.content != "": data += " --data-binary " + "'" + flow.request.content + "'" -- cgit v1.2.3 From 6a235a1b1128662dd8ba1f515e7fc6611d8a030c Mon Sep 17 00:00:00 2001 From: Ryan Welton Date: Tue, 9 Jun 2015 13:51:11 -0400 Subject: Was needlessly passing un-used parameters + clean up misspelling --- libmproxy/console/common.py | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) (limited to 'libmproxy') diff --git a/libmproxy/console/common.py b/libmproxy/console/common.py index 90c10b8f..a31eb870 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) ) @@ -313,7 +313,7 @@ def copy_to_clipboard_or_prompt(data): 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 = ( @@ -392,16 +392,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.") -- cgit v1.2.3 From fa007a7707bc6761083dfda151fd800ae79f2761 Mon Sep 17 00:00:00 2001 From: Marcelo Glezer Date: Sat, 10 Oct 2015 23:21:08 -0300 Subject: fixed TypeError: ask_save_overwrite() takes exactly 2 arguments (xxxxx given) --- libmproxy/console/common.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'libmproxy') diff --git a/libmproxy/console/common.py b/libmproxy/console/common.py index a31eb870..540a96a3 100644 --- a/libmproxy/console/common.py +++ b/libmproxy/console/common.py @@ -242,7 +242,7 @@ def ask_save_path(prompt, data): signals.status_prompt_path.send( prompt = prompt, callback = ask_save_overwrite, - args = (data) + args = (data, ) ) -- cgit v1.2.3 From b2e3d2ce7054a15d0b2a707709105c6cc0638151 Mon Sep 17 00:00:00 2001 From: Marcelo Glezer Date: Sun, 11 Oct 2015 00:42:46 -0300 Subject: headers enumartion was failing in copy as curl and protocol was None when copy to clipboard was called. first wip fix --- libmproxy/console/common.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'libmproxy') diff --git a/libmproxy/console/common.py b/libmproxy/console/common.py index 540a96a3..ff820987 100644 --- a/libmproxy/console/common.py +++ b/libmproxy/console/common.py @@ -242,7 +242,7 @@ def ask_save_path(prompt, data): signals.status_prompt_path.send( prompt = prompt, callback = ask_save_overwrite, - args = (data, ) + args = (data, ) ) @@ -282,7 +282,7 @@ def copy_as_curl_command(flow): return None, "Request content is missing" headerString = "" - for k,v in flow.request.headers: + for k,v in flow.request.headers.fields: headerString += " -H '" + k + ":" + v + "' " data = "curl" -- cgit v1.2.3 From 9facd190c6937287eb93b430c24d13c13b5560b8 Mon Sep 17 00:00:00 2001 From: Marcelo Glezer Date: Sun, 11 Oct 2015 11:04:18 -0300 Subject: refactored export as curl to be 'E' to export and 'c' to as curl command --- libmproxy/console/common.py | 4 ++++ libmproxy/console/flowlist.py | 14 +++++++++++--- libmproxy/console/flowview.py | 16 ++++++++++++---- 3 files changed, 27 insertions(+), 7 deletions(-) (limited to 'libmproxy') diff --git a/libmproxy/console/common.py b/libmproxy/console/common.py index ff820987..6a7064ff 100644 --- a/libmproxy/console/common.py +++ b/libmproxy/console/common.py @@ -276,6 +276,10 @@ def copy_flow_format_data(part, scope, flow): raise ValueError("Unknown part: {}".format(part)) return data, False +def export_prompt(k, flow): + if k == "c": + copy_as_curl_command(flow) + def copy_as_curl_command(flow): if flow.request.content is None or flow.request.content == CONTENT_MISSING: diff --git a/libmproxy/console/flowlist.py b/libmproxy/console/flowlist.py index 6edf5212..6c0ff3d0 100644 --- a/libmproxy/console/flowlist.py +++ b/libmproxy/console/flowlist.py @@ -13,10 +13,10 @@ def _mkhelp(): ("A", "accept all intercepted flows"), ("a", "accept this intercepted flow"), ("b", "save request/response body"), - ("Z", "copy request as curl command"), ("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"), @@ -255,8 +255,16 @@ class ConnectionItem(urwid.WidgetWrap): ) elif key == "P": common.ask_copy_part("a", self.flow, self.master, self.state) - elif key == "Z": - common.copy_as_curl_command(self.flow) + elif key == "E": + signals.status_prompt_onekey.send( + self, + prompt = "Export", + keys = ( + ("as curl command", "c"), + ), + 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 518817d4..95d52c98 100644 --- a/libmproxy/console/flowview.py +++ b/libmproxy/console/flowview.py @@ -25,9 +25,9 @@ def _mkhelp(): ("A", "accept all intercepted flows"), ("a", "accept this intercepted flow"), ("b", "save request/response body"), - ("Z", "copy as curl command"), - ("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"), @@ -575,8 +575,16 @@ class FlowView(tabs.Tabs): callback = self.master.save_one_flow, args = (self.flow,) ) - elif key == "Z": - common.copy_as_curl_command(self.flow) + elif key == "E": + signals.status_prompt_onekey.send( + self, + prompt = "Export", + keys = ( + ("as curl command", "c"), + ), + callback = common.export_prompt, + args = (self.flow,) + ) elif key == "|": signals.status_prompt_path.send( prompt = "Send flow to script", -- cgit v1.2.3 From 0bb13c61d6ec7e0fae45a6aab0fe59ba1b6e6a48 Mon Sep 17 00:00:00 2001 From: Shadab Zafar Date: Wed, 13 Jan 2016 16:17:01 +0530 Subject: Refactor copy_as_curl_command --- libmproxy/console/common.py | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) (limited to 'libmproxy') diff --git a/libmproxy/console/common.py b/libmproxy/console/common.py index 6a7064ff..29e86b79 100644 --- a/libmproxy/console/common.py +++ b/libmproxy/console/common.py @@ -281,24 +281,22 @@ def export_prompt(k, flow): copy_as_curl_command(flow) def copy_as_curl_command(flow): - if flow.request.content is None or flow.request.content == CONTENT_MISSING: return None, "Request content is missing" - headerString = "" - for k,v in flow.request.headers.fields: - headerString += " -H '" + k + ":" + v + "' " + data = "curl " - data = "curl" + for k, v in flow.request.headers.fields: + data += "-H '%s:%s' " % (k, v) if flow.request.method != "GET": - data += " -X " + flow.request.method + data += "-X %s " % flow.request.method full_url = flow.request.scheme + "://" + flow.request.host + flow.request.path - data += " " + headerString + "'" + full_url + "'" + data += "'%s'" % full_url - if flow.request.content != None and flow.request.content != "": - data += " --data-binary " + "'" + flow.request.content + "'" + if flow.request.content: + data += " --data-binary '%s'" % flow.request.content copy_to_clipboard_or_prompt(data) -- cgit v1.2.3 From 1079e00641f0a7d0f1bb0e82d9f5e7830683a1a1 Mon Sep 17 00:00:00 2001 From: Shadab Zafar Date: Wed, 13 Jan 2016 16:36:44 +0530 Subject: Use signals.status_message for empty content --- libmproxy/console/common.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'libmproxy') diff --git a/libmproxy/console/common.py b/libmproxy/console/common.py index 29e86b79..50dfa7dc 100644 --- a/libmproxy/console/common.py +++ b/libmproxy/console/common.py @@ -282,7 +282,8 @@ def export_prompt(k, flow): def copy_as_curl_command(flow): if flow.request.content is None or flow.request.content == CONTENT_MISSING: - return None, "Request content is missing" + signals.status_message.send(message="Request content is missing") + return data = "curl " -- cgit v1.2.3 From 34ec2d1370d0066c47f37819b543ec8465332c12 Mon Sep 17 00:00:00 2001 From: Shadab Zafar Date: Wed, 13 Jan 2016 16:37:28 +0530 Subject: Export/Copy request as python code Press E followed by p to copy code to clipboard. The code uses the python requests module. Only GET methods are currently supported, but can easily be extended to POST etc. --- libmproxy/console/common.py | 30 ++++++++++++++++++++++++++++++ libmproxy/console/flowlist.py | 1 + libmproxy/console/flowview.py | 3 ++- 3 files changed, 33 insertions(+), 1 deletion(-) (limited to 'libmproxy') diff --git a/libmproxy/console/common.py b/libmproxy/console/common.py index 50dfa7dc..2ea77449 100644 --- a/libmproxy/console/common.py +++ b/libmproxy/console/common.py @@ -276,9 +276,13 @@ def copy_flow_format_data(part, scope, flow): raise ValueError("Unknown part: {}".format(part)) return data, False + def export_prompt(k, flow): if k == "c": copy_as_curl_command(flow) + elif k == "p": + copy_as_python_code(flow) + def copy_as_curl_command(flow): if flow.request.content is None or flow.request.content == CONTENT_MISSING: @@ -302,6 +306,31 @@ def copy_as_curl_command(flow): copy_to_clipboard_or_prompt(data) +def copy_as_python_code(flow): + if flow.request.content is None or flow.request.content == CONTENT_MISSING: + signals.status_message.send(message="Request content is missing") + return + + 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_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. @@ -326,6 +355,7 @@ def copy_to_clipboard_or_prompt(data): callback = save ) + def copy_flow(part, scope, flow, master, state): """ part: _c_ontent, _h_eaders+content, _u_rl diff --git a/libmproxy/console/flowlist.py b/libmproxy/console/flowlist.py index 6c0ff3d0..b52c0fea 100644 --- a/libmproxy/console/flowlist.py +++ b/libmproxy/console/flowlist.py @@ -261,6 +261,7 @@ class ConnectionItem(urwid.WidgetWrap): prompt = "Export", keys = ( ("as curl command", "c"), + ("as python code", "p"), ), callback = common.export_prompt, args = (self.flow,) diff --git a/libmproxy/console/flowview.py b/libmproxy/console/flowview.py index 95d52c98..3a745262 100644 --- a/libmproxy/console/flowview.py +++ b/libmproxy/console/flowview.py @@ -27,7 +27,7 @@ def _mkhelp(): ("b", "save request/response body"), ("D", "duplicate flow"), ("d", "delete flow"), - ("E", "export"), + ("E", "export"), ("e", "edit request/response"), ("f", "load full body data"), ("m", "change body display mode for this entity"), @@ -581,6 +581,7 @@ class FlowView(tabs.Tabs): prompt = "Export", keys = ( ("as curl command", "c"), + ("as python code", "p"), ), callback = common.export_prompt, args = (self.flow,) -- cgit v1.2.3 From 152e395fa49fc534e6897cf2411b7ce27e1d379f Mon Sep 17 00:00:00 2001 From: Shadab Zafar Date: Wed, 13 Jan 2016 19:21:13 +0530 Subject: Copy as raw request Issue #807 I am not entirely sure what needs to be returned in this case. --- libmproxy/console/common.py | 12 ++++++++++++ libmproxy/console/flowlist.py | 1 + libmproxy/console/flowview.py | 1 + 3 files changed, 14 insertions(+) (limited to 'libmproxy') diff --git a/libmproxy/console/common.py b/libmproxy/console/common.py index 2ea77449..db40201f 100644 --- a/libmproxy/console/common.py +++ b/libmproxy/console/common.py @@ -282,6 +282,8 @@ def export_prompt(k, flow): copy_as_curl_command(flow) elif k == "p": copy_as_python_code(flow) + elif k == "r": + copy_as_raw_request(flow) def copy_as_curl_command(flow): @@ -331,6 +333,16 @@ def copy_as_python_code(flow): copy_to_clipboard_or_prompt(data) +def copy_as_raw_request(flow): + if flow.request.content is None or flow.request.content == CONTENT_MISSING: + signals.status_message.send(message="Request content is missing") + return + + 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. diff --git a/libmproxy/console/flowlist.py b/libmproxy/console/flowlist.py index b52c0fea..2c18d197 100644 --- a/libmproxy/console/flowlist.py +++ b/libmproxy/console/flowlist.py @@ -262,6 +262,7 @@ class ConnectionItem(urwid.WidgetWrap): keys = ( ("as curl command", "c"), ("as python code", "p"), + ("as raw request", "r"), ), callback = common.export_prompt, args = (self.flow,) diff --git a/libmproxy/console/flowview.py b/libmproxy/console/flowview.py index 3a745262..7962c69c 100644 --- a/libmproxy/console/flowview.py +++ b/libmproxy/console/flowview.py @@ -582,6 +582,7 @@ class FlowView(tabs.Tabs): keys = ( ("as curl command", "c"), ("as python code", "p"), + ("as raw request", "r"), ), callback = common.export_prompt, args = (self.flow,) -- cgit v1.2.3 From 8fa16ce8953bb464765544cc1bd77ad42e269fba Mon Sep 17 00:00:00 2001 From: Shadab Zafar Date: Mon, 25 Jan 2016 22:31:22 +0530 Subject: Remove restrictions based on request content --- libmproxy/console/common.py | 13 ------------- 1 file changed, 13 deletions(-) (limited to 'libmproxy') diff --git a/libmproxy/console/common.py b/libmproxy/console/common.py index db40201f..a9bd846b 100644 --- a/libmproxy/console/common.py +++ b/libmproxy/console/common.py @@ -287,10 +287,6 @@ def export_prompt(k, flow): def copy_as_curl_command(flow): - if flow.request.content is None or flow.request.content == CONTENT_MISSING: - signals.status_message.send(message="Request content is missing") - return - data = "curl " for k, v in flow.request.headers.fields: @@ -309,10 +305,6 @@ def copy_as_curl_command(flow): def copy_as_python_code(flow): - if flow.request.content is None or flow.request.content == CONTENT_MISSING: - signals.status_message.send(message="Request content is missing") - return - if flow.request.method != "GET": signals.status_message.send(message="Currently, only GET methods are supported") return @@ -334,12 +326,7 @@ def copy_as_python_code(flow): def copy_as_raw_request(flow): - if flow.request.content is None or flow.request.content == CONTENT_MISSING: - signals.status_message.send(message="Request content is missing") - return - data = netlib.http.http1.assemble_request(flow.request) - copy_to_clipboard_or_prompt(data) -- cgit v1.2.3