diff options
Diffstat (limited to 'libmproxy/console/common.py')
-rw-r--r-- | libmproxy/console/common.py | 135 |
1 files changed, 60 insertions, 75 deletions
diff --git a/libmproxy/console/common.py b/libmproxy/console/common.py index fa21c93e..bc8a2aad 100644 --- a/libmproxy/console/common.py +++ b/libmproxy/console/common.py @@ -1,18 +1,18 @@ from __future__ import absolute_import + import urwid import urwid.util import os + from .. import utils from ..protocol.http import CONTENT_MISSING, decoded +from . import signals try: import pyperclip except: pyperclip = False -VIEW_LIST = 0 -VIEW_FLOW = 1 - VIEW_FLOW_REQUEST = 0 VIEW_FLOW_RESPONSE = 1 @@ -29,6 +29,14 @@ METHOD_OPTIONS = [ ] +def is_keypress(k): + """ + Is this input event a keypress? + """ + if isinstance(k, basestring): + return True + + def highlight_key(s, k): l = [] parts = s.split(k, 1) @@ -41,6 +49,8 @@ def highlight_key(s, k): KEY_MAX = 30 + + def format_keyvals(lst, key="key", val="text", indent=0): """ Format a list of (key, value) tuples. @@ -103,10 +113,8 @@ else: SYMBOL_RETURN = u"<-" - def raw_format_flow(f, focus, extended, padding): f = dict(f) - pile = [] req = [] if extended: @@ -122,7 +130,7 @@ def raw_format_flow(f, focus, extended, padding): req.append(fcol(SYMBOL_REPLAY, "replay")) req.append(fcol(f["req_method"], "method")) - preamble = sum(i[1] for i in req) + len(req) -1 + preamble = sum(i[1] for i in req) + len(req) - 1 if f["intercepted"] and not f["acked"]: uc = "intercept" @@ -182,23 +190,19 @@ def raw_format_flow(f, focus, extended, padding): 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(data) except IOError, v: - master.statusbar.message(v.strerror) + signals.status_message.send(message=v.strerror) def ask_save_path(prompt, data, master, state): - master.path_prompt( - prompt, - state.last_saveload, - save_data, - data, - master, - state + signals.status_prompt_path.send( + prompt = prompt, + callback = save_data, + args = (data, master, state) ) @@ -238,28 +242,27 @@ def copy_flow(part, scope, flow, master, state): if not data: if scope == "q": - master.statusbar.message("No request content to copy.") + signals.status_message.send(message="No request content to copy.") elif scope == "s": - master.statusbar.message("No response content to copy.") + signals.status_message.send(message="No response content to copy.") else: - master.statusbar.message("No contents to copy.") + signals.status_message.send(message="No contents to copy.") return try: master.add_event(str(len(data))) pyperclip.copy(data) - except RuntimeError: + except (RuntimeError, UnicodeDecodeError): 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?", - ( + ask_save_path("Save data", data, master, state) + signals.status_prompt_onekey.send( + prompt = "Cannot copy binary data to clipboard. Save as file?", + keys = ( ("yes", "y"), ("no", "n"), ), - save + callback = save ) @@ -271,39 +274,35 @@ def ask_copy_part(scope, flow, master, state): if scope != "s": choices.append(("url", "u")) - master.prompt_onekey( - "Copy", - choices, - copy_flow, - scope, - flow, - master, - state + signals.status_prompt_onekey.send( + prompt = "Copy", + keys = choices, + callback = copy_flow, + args = (scope, flow, 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). + 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. + # 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", - ( + signals.status_prompt_onekey.send( + prompt = "Save", + keys = ( ("request", "q"), ("response", "s"), ), - ask_save_body, - master, - state, - flow + callback = ask_save_body, + args = (master, state, flow) ) elif response_has_content: ask_save_body("s", master, state, flow) @@ -311,18 +310,24 @@ def ask_save_body(part, master, state, flow): 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) + 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) + ask_save_path( + "Save response content", + flow.response.get_decoded_content(), + master, + state + ) else: - master.statusbar.message("No content to save.") + signals.status_message.send(message="No content to save.") -class FlowCache: - @utils.LRUCache(200) - def format_flow(self, *args): - return raw_format_flow(*args) -flowcache = FlowCache() +flowcache = utils.LRUCache(800) def format_flow(f, focus, extended=False, hostheader=False, padding=2): @@ -348,7 +353,6 @@ def format_flow(f, focus, extended=False, hostheader=False, padding=2): duration = 0 if f.response.timestamp_end and f.request.timestamp_start: duration = f.response.timestamp_end - f.request.timestamp_start - size = f.response.size() roundtrip = utils.pretty_duration(duration) d.update(dict( @@ -362,26 +366,7 @@ def format_flow(f, focus, extended=False, hostheader=False, padding=2): d["resp_ctype"] = t[0].split(";")[0] else: d["resp_ctype"] = "" - return flowcache.format_flow(tuple(sorted(d.items())), focus, extended, padding) - - -def int_version(v): - SIG = 3 - v = urwid.__version__.split("-")[0].split(".") - x = 0 - for i in range(min(SIG, len(v))): - x += int(v[i]) * 10**(SIG-i) - return x - - -# We have to do this to be portable over 0.9.8 and 0.9.9 If compatibility -# becomes a pain to maintain, we'll just mandate 0.9.9 or newer. -class WWrap(urwid.WidgetWrap): - if int_version(urwid.__version__) >= 990: - def set_w(self, x): - self._w = x - def get_w(self): - return self._w - w = property(get_w, set_w) - - + return flowcache.get( + raw_format_flow, + tuple(sorted(d.items())), focus, extended, padding + ) |