From c57efffe01bdc29e08b5eaa1a9b7071336bd4bb1 Mon Sep 17 00:00:00 2001 From: Marcelo Glezer Date: Thu, 15 Jan 2015 09:36:59 -0300 Subject: extracted server_copy_response to common --- libmproxy/console/common.py | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) (limited to 'libmproxy/console/common.py') diff --git a/libmproxy/console/common.py b/libmproxy/console/common.py index 3e6e5ccc..3ba89f8e 100644 --- a/libmproxy/console/common.py +++ b/libmproxy/console/common.py @@ -3,7 +3,10 @@ import urwid import urwid.util from .. import utils from ..protocol.http import CONTENT_MISSING - +try: + import pyperclip +except: + pyperclip = False VIEW_LIST = 0 VIEW_FLOW = 1 @@ -161,6 +164,21 @@ def raw_format_flow(f, focus, extended, padding): pile.append(urwid.Columns(resp, dividechars=1)) return urwid.Pile(pile) +def server_copy_response( k, response, statusbar): + if pyperclip: + if k == "c": + try: + pyperclip.copy(response.get_decoded_content()) + except TypeError: + statusbar.message("Content is binary or can be converted to text") + elif k == "h": + try: + pyperclip.copy(str(response.headers)) + except TypeError: + statusbar.message("Error converting headers to text") + else: + statusbar.message("No clipboard support on your system, sorry.") + class FlowCache: @utils.LRUCache(200) -- cgit v1.2.3 From 8f66fe1bfc16d0bb63acc267632471640939371e Mon Sep 17 00:00:00 2001 From: Marcelo Glezer Date: Thu, 15 Jan 2015 12:37:26 -0300 Subject: added support for saving file if content is binary. still wip --- libmproxy/console/common.py | 44 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 4 deletions(-) (limited to 'libmproxy/console/common.py') diff --git a/libmproxy/console/common.py b/libmproxy/console/common.py index 3ba89f8e..84dc8aef 100644 --- a/libmproxy/console/common.py +++ b/libmproxy/console/common.py @@ -1,6 +1,7 @@ from __future__ import absolute_import import urwid import urwid.util +import os from .. import utils from ..protocol.http import CONTENT_MISSING try: @@ -164,20 +165,55 @@ def raw_format_flow(f, focus, extended, padding): pile.append(urwid.Columns(resp, dividechars=1)) return urwid.Pile(pile) -def server_copy_response( k, response, statusbar): +## common save body parts +def _save_body(path, master, state, content): + if not path: + return + state.last_saveload = path + path = os.path.expanduser(path) + try: + f = file(path, "wb") + f.write(str(content)) + f.close() + except IOError, v: + master.statusbar.message(v.strerror) + +def save_body(k, master, state, content): + if k == "y": + master.path_prompt( + "Save response body: ", + state.last_saveload, + _save_body, + master, + state, + content, + ) + +## common server_copy_response parts +def server_copy_response( k, master, state, response): if pyperclip: if k == "c": try: pyperclip.copy(response.get_decoded_content()) except TypeError: - statusbar.message("Content is binary or can be converted to text") + master.prompt_onekey( + "Content is binary do you want to save it to a file instead?", + ( + ("yes", "y"), + ("no", "n"), + ), + save_body, + master, + state, + response.get_decoded_content(), + ) elif k == "h": try: pyperclip.copy(str(response.headers)) except TypeError: - statusbar.message("Error converting headers to text") + master.statusbar.message("Error converting headers to text") else: - statusbar.message("No clipboard support on your system, sorry.") + master.statusbar.message("No clipboard support on your system, sorry.") class FlowCache: -- cgit v1.2.3 From 3bcf0cbba894ad12d4cfc438d26cdf22d640416c Mon Sep 17 00:00:00 2001 From: Marcelo Glezer Date: Thu, 15 Jan 2015 12:57:00 -0300 Subject: used save_body from common when b key is pressed --- libmproxy/console/common.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'libmproxy/console/common.py') diff --git a/libmproxy/console/common.py b/libmproxy/console/common.py index 84dc8aef..29e59373 100644 --- a/libmproxy/console/common.py +++ b/libmproxy/console/common.py @@ -166,7 +166,7 @@ def raw_format_flow(f, focus, extended, padding): return urwid.Pile(pile) ## common save body parts -def _save_body(path, master, state, content): +def save_body(path, master, state, content): if not path: return state.last_saveload = path @@ -178,12 +178,12 @@ def _save_body(path, master, state, content): except IOError, v: master.statusbar.message(v.strerror) -def save_body(k, master, state, content): +def ask_save_body(k, master, state, content): if k == "y": master.path_prompt( "Save response body: ", state.last_saveload, - _save_body, + save_body, master, state, content, @@ -202,7 +202,7 @@ def server_copy_response( k, master, state, response): ("yes", "y"), ("no", "n"), ), - save_body, + ask_save_body, master, state, response.get_decoded_content(), -- cgit v1.2.3 From 9fc68d320c80ad07398a234630f6b59546a444e0 Mon Sep 17 00:00:00 2001 From: Marcelo Glezer Date: Fri, 16 Jan 2015 12:13:55 -0300 Subject: added support for copying request (content|header) to clipboard --- libmproxy/console/common.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'libmproxy/console/common.py') diff --git a/libmproxy/console/common.py b/libmproxy/console/common.py index 29e59373..33738c0a 100644 --- a/libmproxy/console/common.py +++ b/libmproxy/console/common.py @@ -181,7 +181,7 @@ def save_body(path, master, state, content): def ask_save_body(k, master, state, content): if k == "y": master.path_prompt( - "Save response body: ", + "Save message content: ", state.last_saveload, save_body, master, @@ -189,12 +189,12 @@ def ask_save_body(k, master, state, content): content, ) -## common server_copy_response parts -def server_copy_response( k, master, state, response): +## common copy_message parts +def copy_message( k, master, state, message): if pyperclip: if k == "c": try: - pyperclip.copy(response.get_decoded_content()) + pyperclip.copy(message.get_decoded_content()) except TypeError: master.prompt_onekey( "Content is binary do you want to save it to a file instead?", @@ -205,17 +205,16 @@ def server_copy_response( k, master, state, response): ask_save_body, master, state, - response.get_decoded_content(), + message.get_decoded_content(), ) elif k == "h": try: - pyperclip.copy(str(response.headers)) + pyperclip.copy(str(message.headers)) except TypeError: master.statusbar.message("Error converting headers to text") else: master.statusbar.message("No clipboard support on your system, sorry.") - class FlowCache: @utils.LRUCache(200) def format_flow(self, *args): -- cgit v1.2.3 From ae83d39eba4a5518537d799fc4bd61d083f32944 Mon Sep 17 00:00:00 2001 From: Marcelo Glezer Date: Fri, 16 Jan 2015 13:08:25 -0300 Subject: added support for 'b' key in flowlist --- libmproxy/console/common.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'libmproxy/console/common.py') diff --git a/libmproxy/console/common.py b/libmproxy/console/common.py index 33738c0a..2f6c909c 100644 --- a/libmproxy/console/common.py +++ b/libmproxy/console/common.py @@ -189,8 +189,36 @@ def ask_save_body(k, master, state, content): content, ) +def which_body_save(k, master, state, flow): + if k == "q": + master.path_prompt( + "Save request content: ", + state.last_saveload, + save_body, + master, + state, + flow.request.get_decoded_content(), + ) + elif k == "r": + if flow.response: + master.path_prompt( + "Save response content: ", + state.last_saveload, + save_body, + master, + state, + flow.response.get_decoded_content(), + ) + else: + master.statusbar.message("Flow has no response") + ## common copy_message parts def copy_message( k, master, state, message): + if not message: + # only response could be None + master.statusbar.message("Flow has no response") + return + if pyperclip: if k == "c": try: -- cgit v1.2.3 From 75cca63b2687db5da0793c2e6d60d38531f18b59 Mon Sep 17 00:00:00 2001 From: Marcelo Glezer Date: Tue, 3 Feb 2015 15:41:09 -0300 Subject: added copy to clipboard support for url --- libmproxy/console/common.py | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'libmproxy/console/common.py') diff --git a/libmproxy/console/common.py b/libmproxy/console/common.py index 2f6c909c..b7c46476 100644 --- a/libmproxy/console/common.py +++ b/libmproxy/console/common.py @@ -240,6 +240,11 @@ def copy_message( k, master, state, message): pyperclip.copy(str(message.headers)) except TypeError: master.statusbar.message("Error converting headers to text") + elif k == "u": + try: + pyperclip.copy(message.url) + except TypeError: + master.statusbar.message("Error copying url to clipboard") else: master.statusbar.message("No clipboard support on your system, sorry.") -- cgit v1.2.3 From 64c02a16c389d4fdee396f132a76a627302c7511 Mon Sep 17 00:00:00 2001 From: Marcelo Glezer Date: Fri, 6 Feb 2015 00:44:43 -0300 Subject: save_flow now uses with, and pyperclip requirement updated to 1.5.8 --- libmproxy/console/common.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'libmproxy/console/common.py') diff --git a/libmproxy/console/common.py b/libmproxy/console/common.py index b7c46476..6141bc1c 100644 --- a/libmproxy/console/common.py +++ b/libmproxy/console/common.py @@ -172,9 +172,8 @@ def save_body(path, master, state, content): state.last_saveload = path path = os.path.expanduser(path) try: - f = file(path, "wb") - f.write(str(content)) - f.close() + with file(path, "wb") as f: + f.write(content) except IOError, v: master.statusbar.message(v.strerror) -- cgit v1.2.3 From f49dcb0d91031c75231b4659f141aece5a43f8d1 Mon Sep 17 00:00:00 2001 From: Marcelo Glezer Date: Fri, 6 Feb 2015 00:59:05 -0300 Subject: removed str() cast and changed 'failed copy trying save instead' message --- libmproxy/console/common.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'libmproxy/console/common.py') diff --git a/libmproxy/console/common.py b/libmproxy/console/common.py index 6141bc1c..c0929d58 100644 --- a/libmproxy/console/common.py +++ b/libmproxy/console/common.py @@ -224,7 +224,7 @@ def copy_message( k, master, state, message): pyperclip.copy(message.get_decoded_content()) except TypeError: master.prompt_onekey( - "Content is binary do you want to save it to a file instead?", + "Cannot copy binary data to clipboard. Save as file?", ( ("yes", "y"), ("no", "n"), @@ -236,7 +236,7 @@ def copy_message( k, master, state, message): ) elif k == "h": try: - pyperclip.copy(str(message.headers)) + pyperclip.copy(message.headers) except TypeError: master.statusbar.message("Error converting headers to text") elif k == "u": -- cgit v1.2.3 From 02e0bad684d4405ca5ae2c8335661e2db20c9627 Mon Sep 17 00:00:00 2001 From: Maximilian Hils Date: Fri, 6 Feb 2015 23:32:22 +0100 Subject: improve clipboard UX --- libmproxy/console/common.py | 141 +++++++++++++++++++++++++------------------- 1 file changed, 79 insertions(+), 62 deletions(-) (limited to 'libmproxy/console/common.py') diff --git a/libmproxy/console/common.py b/libmproxy/console/common.py index c0929d58..aaec81b5 100644 --- a/libmproxy/console/common.py +++ b/libmproxy/console/common.py @@ -165,87 +165,104 @@ def raw_format_flow(f, focus, extended, padding): pile.append(urwid.Columns(resp, dividechars=1)) return urwid.Pile(pile) -## common save body parts -def save_body(path, master, state, content): + +# Save file to disk +def save_data(path, data, master, state): if not path: return state.last_saveload = path path = os.path.expanduser(path) try: with file(path, "wb") as f: - f.write(content) + f.write(data) except IOError, v: master.statusbar.message(v.strerror) -def ask_save_body(k, master, state, content): - if k == "y": - master.path_prompt( - "Save message content: ", - state.last_saveload, - save_body, - master, - state, - content, - ) -def which_body_save(k, master, state, flow): - if k == "q": - master.path_prompt( - "Save request content: ", - state.last_saveload, - save_body, - master, - state, - flow.request.get_decoded_content(), - ) - elif k == "r": - if flow.response: - master.path_prompt( - "Save response content: ", - state.last_saveload, - save_body, +def ask_save_path(prompt, data, master, state): + master.path_prompt( + prompt, + state.last_saveload, + save_data, + data, + master, + state + ) + + +def ask_save_body(part, master, state, flow): + """ + Save either the request or the response body to disk. + part can either be "q" (request), "s" (response) or None (ask user if necessary). + """ + + request_has_content = flow.request and flow.request.content + response_has_content = flow.response and flow.response.content + + if part is None: + # We first need to determine whether we want to save the request or the response content. + if request_has_content and response_has_content: + master.prompt_onekey( + "Save", + ( + ("request", "q"), + ("response", "s"), + ), + ask_save_body, master, state, - flow.response.get_decoded_content(), + flow ) + elif response_has_content: + ask_save_body("s", master, state, flow) else: - master.statusbar.message("Flow has no response") + ask_save_body("q", master, state, flow) + + elif part == "q" and request_has_content: + ask_save_path("Save request content: ", flow.request.get_decoded_content(), master, state) + elif part == "s" and response_has_content: + ask_save_path("Save response content: ", flow.response.get_decoded_content(), master, state) + else: + master.statusbar.message("No content to save.") -## common copy_message parts -def copy_message( k, master, state, message): + +# common copy_message parts +def copy_message(k, master, state, message): + if not pyperclip: + master.statusbar.message("No clipboard support on your system, sorry.") + return None if not message: # only response could be None - master.statusbar.message("Flow has no response") + master.statusbar.message("Flow has no response") return - if pyperclip: - if k == "c": - try: - pyperclip.copy(message.get_decoded_content()) - except TypeError: - master.prompt_onekey( - "Cannot copy binary data to clipboard. Save as file?", - ( - ("yes", "y"), - ("no", "n"), - ), - ask_save_body, - master, - state, - message.get_decoded_content(), - ) - elif k == "h": - try: - pyperclip.copy(message.headers) - except TypeError: - master.statusbar.message("Error converting headers to text") - elif k == "u": - try: - pyperclip.copy(message.url) - except TypeError: - master.statusbar.message("Error copying url to clipboard") - else: - master.statusbar.message("No clipboard support on your system, sorry.") + data = None + if k == "c": + data = message.get_decoded_content() + elif k == "h": + data = message.headers + elif k == "u": + data = message.url + + if not data: + master.statusbar.message("No content to copy.") + return + + try: + pyperclip.copy(data) + except TypeError: + def save(k): + if k == "y": + ask_save_path("Save data: ", data, master, state) + master.prompt_onekey( + "Cannot copy binary data to clipboard. Save as file?", + ( + ("yes", "y"), + ("no", "n"), + ), + save + ) + class FlowCache: @utils.LRUCache(200) -- cgit v1.2.3 From 65c14724f56d03f13439e980cbaddef3509f0b3c Mon Sep 17 00:00:00 2001 From: Maximilian Hils Date: Sat, 7 Feb 2015 00:33:29 +0100 Subject: make copy context-sensitive --- libmproxy/console/common.py | 122 +++++++++++++++++++++++++++++--------------- 1 file changed, 82 insertions(+), 40 deletions(-) (limited to 'libmproxy/console/common.py') diff --git a/libmproxy/console/common.py b/libmproxy/console/common.py index aaec81b5..e4a4acba 100644 --- a/libmproxy/console/common.py +++ b/libmproxy/console/common.py @@ -3,7 +3,8 @@ import urwid import urwid.util import os from .. import utils -from ..protocol.http import CONTENT_MISSING +from ..protocol.http import CONTENT_MISSING, decoded + try: import pyperclip except: @@ -190,6 +191,86 @@ def ask_save_path(prompt, data, master, state): ) +def copy_flow_format_data(part, scope, flow): + if part == "u": + data = flow.request.url + else: + data = "" + if scope in ("q", "a"): + with decoded(flow.request): + if part == "h": + data += flow.request.assemble() + elif part == "c": + data += flow.request.content + else: + raise ValueError("Unknown part: {}".format(part)) + if scope == "a" and flow.request.content and flow.response: + # Add padding between request and response + data += "\r\n" * 2 + if scope in ("s", "a") and flow.response: + with decoded(flow.response): + if part == "h": + data += flow.response.assemble() + elif part == "c": + data += flow.response.content + else: + raise ValueError("Unknown part: {}".format(part)) + return data + + +def copy_flow(part, scope, flow, master, state): + """ + part: _c_ontent, _a_ll, _u_rl + scope: _a_ll, re_q_uest, re_s_ponse + """ + data = copy_flow_format_data(part, scope, flow) + + if not data: + if scope == "q": + master.statusbar.message("No request content to copy.") + elif scope == "s": + master.statusbar.message("No response content to copy.") + else: + master.statusbar.message("No contents to copy.") + return + + try: + master.add_event(str(len(data))) + pyperclip.copy(data) + except RuntimeError: + def save(k): + if k == "y": + ask_save_path("Save data: ", data, master, state) + + master.prompt_onekey( + "Cannot copy binary data to clipboard. Save as file?", + ( + ("yes", "y"), + ("no", "n"), + ), + save + ) + + +def ask_copy_part(scope, flow, master, state): + choices = [ + ("content", "c"), + ("headers+content", "h") + ] + if scope != "s": + choices.append(("url", "u")) + + master.prompt_onekey( + "Copy", + choices, + copy_flow, + scope, + flow, + master, + state + ) + + def ask_save_body(part, master, state, flow): """ Save either the request or the response body to disk. @@ -226,44 +307,6 @@ def ask_save_body(part, master, state, flow): master.statusbar.message("No content to save.") -# common copy_message parts -def copy_message(k, master, state, message): - if not pyperclip: - master.statusbar.message("No clipboard support on your system, sorry.") - return None - if not message: - # only response could be None - master.statusbar.message("Flow has no response") - return - - data = None - if k == "c": - data = message.get_decoded_content() - elif k == "h": - data = message.headers - elif k == "u": - data = message.url - - if not data: - master.statusbar.message("No content to copy.") - return - - try: - pyperclip.copy(data) - except TypeError: - def save(k): - if k == "y": - ask_save_path("Save data: ", data, master, state) - master.prompt_onekey( - "Cannot copy binary data to clipboard. Save as file?", - ( - ("yes", "y"), - ("no", "n"), - ), - save - ) - - class FlowCache: @utils.LRUCache(200) def format_flow(self, *args): @@ -313,7 +356,6 @@ def format_flow(f, focus, extended=False, hostheader=False, padding=2): return flowcache.format_flow(tuple(sorted(d.items())), focus, extended, padding) - def int_version(v): SIG = 3 v = urwid.__version__.split("-")[0].split(".") -- cgit v1.2.3 From ba42984b593246b0105a077311e16a2ca71f79eb Mon Sep 17 00:00:00 2001 From: Marcelo Glezer Date: Tue, 10 Feb 2015 15:24:21 -0300 Subject: added support for creating new requests. still wip (not working for https) --- libmproxy/console/common.py | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'libmproxy/console/common.py') diff --git a/libmproxy/console/common.py b/libmproxy/console/common.py index e4a4acba..a2cfd57b 100644 --- a/libmproxy/console/common.py +++ b/libmproxy/console/common.py @@ -17,6 +17,17 @@ VIEW_FLOW = 1 VIEW_FLOW_REQUEST = 0 VIEW_FLOW_RESPONSE = 1 +METHOD_OPTIONS = [ + ("get", "g"), + ("post", "p"), + ("put", "u"), + ("head", "h"), + ("trace", "t"), + ("delete", "d"), + ("options", "o"), + ("edit raw", "e"), +] + def highlight_key(s, k): l = [] -- cgit v1.2.3