diff options
Diffstat (limited to 'libmproxy/console/__init__.py')
-rw-r--r-- | libmproxy/console/__init__.py | 445 |
1 files changed, 230 insertions, 215 deletions
diff --git a/libmproxy/console/__init__.py b/libmproxy/console/__init__.py index cc8a0c1f..70bd46d3 100644 --- a/libmproxy/console/__init__.py +++ b/libmproxy/console/__init__.py @@ -1,14 +1,25 @@ from __future__ import absolute_import -import mailcap, mimetypes, tempfile, os, subprocess, glob, time, shlex, stat -import os.path, sys, weakref, traceback -import urwid -from .. import controller, utils, flow, script, proxy -from . import flowlist, flowview, help, common, grideditor, palettes, contentview, flowdetailview -EVENTLOG_SIZE = 500 +import glob +import mailcap +import mimetypes +import tempfile +import os +import os.path +import shlex +import stat +import subprocess +import sys +import time +import traceback +import urwid +import weakref +from .. import controller, utils, flow, script +from . import flowlist, flowview, help, common +from . import grideditor, palettes, contentview, flowdetailview -class Stop(Exception): pass +EVENTLOG_SIZE = 500 class _PathCompleter: @@ -58,7 +69,6 @@ class _PathCompleter: self.final = ret[1] return ret[0] -#begin nocover class PathEdit(urwid.Edit, _PathCompleter): def __init__(self, *args, **kwargs): @@ -75,7 +85,7 @@ class PathEdit(urwid.Edit, _PathCompleter): return urwid.Edit.keypress(self, size, key) -class ActionBar(common.WWrap): +class ActionBar(urwid.WidgetWrap): def __init__(self): self.message("") @@ -84,7 +94,7 @@ class ActionBar(common.WWrap): def path_prompt(self, prompt, text): self.expire = None - self.w = PathEdit(prompt, text) + self._w = PathEdit(prompt, text) def prompt(self, prompt, text = ""): self.expire = None @@ -93,19 +103,19 @@ class ActionBar(common.WWrap): # We can remove it once veryone is beyond 1.0.1 if isinstance(prompt, basestring): prompt = unicode(prompt) - self.w = urwid.Edit(prompt, text or "") + self._w = urwid.Edit(prompt, text or "") def message(self, message, expire=None): self.expire = expire - self.w = urwid.Text(message) + self._w = urwid.Text(message) -class StatusBar(common.WWrap): +class StatusBar(urwid.WidgetWrap): def __init__(self, master, helptext): self.master, self.helptext = master, helptext self.ab = ActionBar() - self.ib = common.WWrap(urwid.Text("")) - self.w = urwid.Pile([self.ib, self.ab]) + self.ib = urwid.WidgetWrap(urwid.Text("")) + self._w = urwid.Pile([self.ib, self.ab]) def get_status(self): r = [] @@ -227,12 +237,12 @@ class StatusBar(common.WWrap): align="right" ), ]), "heading") - self.ib.set_w(status) + self.ib._w = status def update(self, text): self.helptext = text self.redraw() - self.master.drawscreen() + self.master.loop.draw_screen() def selectable(self): return True @@ -250,11 +260,9 @@ class StatusBar(common.WWrap): if expire: expire = time.time() + float(expire)/1000 self.ab.message(msg, expire) - self.master.drawscreen() + self.master.loop.draw_screen() -#end nocover - class ConsoleState(flow.State): def __init__(self): flow.State.__init__(self) @@ -337,7 +345,6 @@ class ConsoleState(flow.State): super(ConsoleState, self).clear() - class Options(object): attributes = [ "app", @@ -367,6 +374,7 @@ class Options(object): "nopop", "palette", ] + def __init__(self, **kwargs): for k, v in kwargs.items(): setattr(self, k, v) @@ -375,11 +383,9 @@ class Options(object): setattr(self, i, None) -#begin nocover - - class ConsoleMaster(flow.FlowMaster): palette = [] + def __init__(self, server, options): flow.FlowMaster.__init__(self, server, ConsoleState()) self.looptime = 0 @@ -439,7 +445,10 @@ class ConsoleMaster(flow.FlowMaster): sys.exit(1) if options.outfile: - err = self.start_stream_to_path(options.outfile[0], options.outfile[1]) + err = self.start_stream_to_path( + options.outfile[0], + options.outfile[1] + ) if err: print >> sys.stderr, "Stream file error:", err sys.exit(1) @@ -550,7 +559,7 @@ class ConsoleMaster(flow.FlowMaster): except: self.statusbar.message("Can't start editor: %s" % " ".join(c)) else: - data = open(name,"rb").read() + data = open(name, "rb").read() self.ui.start() os.unlink(name) return data @@ -587,13 +596,172 @@ class ConsoleMaster(flow.FlowMaster): try: subprocess.call(cmd, shell=shell) except: - self.statusbar.message("Can't start external viewer: %s" % " ".join(c)) + self.statusbar.message( + "Can't start external viewer: %s" % " ".join(c) + ) self.ui.start() os.unlink(name) def set_palette(self, name): self.palette = palettes.palettes[name] + def input_filter(self, keys, raw): + for k in keys: + if self.prompting: + if k == "esc": + self.prompt_cancel() + elif self.onekey: + if k == "enter": + self.prompt_cancel() + elif k in self.onekey: + self.prompt_execute(k) + elif k == "enter": + self.prompt_execute() + else: + self.view.keypress(self.loop.screen_size, k) + else: + k = self.view.keypress(self.loop.screen_size, k) + if k: + self.statusbar.message("") + if k == "?": + self.view_help() + elif k == "c": + if not self.client_playback: + self.path_prompt( + "Client replay: ", + self.state.last_saveload, + self.client_playback_path + ) + else: + self.prompt_onekey( + "Stop current client replay?", + ( + ("yes", "y"), + ("no", "n"), + ), + self.stop_client_playback_prompt, + ) + elif k == "H": + self.view_grideditor( + grideditor.SetHeadersEditor( + self, + self.setheaders.get_specs(), + self.setheaders.set + ) + ) + elif k == "I": + self.view_grideditor( + grideditor.HostPatternEditor( + self, + [[x] for x in self.get_ignore_filter()], + self.edit_ignore_filter + ) + ) + elif k == "T": + self.view_grideditor( + grideditor.HostPatternEditor( + self, + [[x] for x in self.get_tcp_filter()], + self.edit_tcp_filter + ) + ) + elif k == "i": + self.prompt( + "Intercept filter: ", + self.state.intercept_txt, + self.set_intercept + ) + elif k == "Q": + raise urwid.ExitMainLoop + elif k == "q": + self.prompt_onekey( + "Quit", + ( + ("yes", "y"), + ("no", "n"), + ), + self.quit, + ) + elif k == "M": + self.prompt_onekey( + "Global default display mode", + contentview.view_prompts, + self.change_default_display_mode + ) + elif k == "R": + self.view_grideditor( + grideditor.ReplaceEditor( + self, + self.replacehooks.get_specs(), + self.replacehooks.set + ) + ) + elif k == "s": + self.view_grideditor( + grideditor.ScriptEditor( + self, + [[i.command] for i in self.scripts], + self.edit_scripts + ) + ) + #if self.scripts: + # self.load_script(None) + #else: + # self.path_prompt( + # "Set script: ", + # self.state.last_script, + # self.set_script + # ) + elif k == "S": + if not self.server_playback: + self.path_prompt( + "Server replay path: ", + self.state.last_saveload, + self.server_playback_path + ) + else: + self.prompt_onekey( + "Stop current server replay?", + ( + ("yes", "y"), + ("no", "n"), + ), + self.stop_server_playback_prompt, + ) + elif k == "o": + self.prompt_onekey( + "Options", + ( + ("anticache", "a"), + ("anticomp", "c"), + ("showhost", "h"), + ("killextra", "k"), + ("norefresh", "n"), + ("no-upstream-certs", "u"), + ), + self._change_options + ) + elif k == "t": + self.prompt( + "Sticky cookie filter: ", + self.stickycookie_txt, + self.set_stickycookie + ) + elif k == "u": + self.prompt( + "Sticky auth filter: ", + self.stickyauth_txt, + self.set_stickyauth + ) + self.statusbar.redraw() + + def ticker(self, *userdata): + changed = self.tick(self.masterq, timeout=0) + if changed: + self.loop.draw_screen() + self.statusbar.redraw() + self.loop.set_alarm_in(0.01, self.ticker) + def run(self): self.ui = urwid.raw_display.Screen() self.ui.set_terminal_properties(256) @@ -606,8 +774,13 @@ class ConsoleMaster(flow.FlowMaster): self.help_context = None self.prompting = False self.onekey = False - + self.loop = urwid.MainLoop( + self.view, + screen = self.ui, + input_filter = self.input_filter + ) self.view_flowlist() + self.statusbar.redraw() self.server.start_slave( controller.Slave, @@ -627,46 +800,57 @@ class ConsoleMaster(flow.FlowMaster): print >> sys.stderr, "Could not load file:", ret sys.exit(1) + self.loop.set_alarm_in(0.01, self.ticker) try: - self.ui.run_wrapper(self.loop) + self.loop.run() except Exception: - self.ui.stop() + self.loop.stop() sys.stdout.flush() print >> sys.stderr, traceback.format_exc() print >> sys.stderr, "mitmproxy has crashed!" - print >> sys.stderr, "Please lodge a bug report at: https://github.com/mitmproxy/mitmproxy" - print >> sys.stderr, "Shutting down..." + print >> sys.stderr, "Please lodge a bug report at:" + print >> sys.stderr, "\thttps://github.com/mitmproxy/mitmproxy" + print >> sys.stderr, "Shutting down..." sys.stderr.flush() self.shutdown() def make_view(self): self.view = urwid.Frame( - self.body, - header = self.header, - footer = self.statusbar - ) + self.body, + header = self.header, + footer = self.statusbar + ) self.view.set_focus("body") + return self.view def view_help(self): - h = help.HelpView(self, self.help_context, (self.statusbar, self.body, self.header)) + h = help.HelpView( + self, + self.help_context, + (self.statusbar, self.body, self.header) + ) self.statusbar = StatusBar(self, help.footer) self.body = h self.header = None - self.make_view() + self.loop.widget = self.make_view() def view_flowdetails(self, flow): - h = flowdetailview.FlowDetailsView(self, flow, (self.statusbar, self.body, self.header)) + h = flowdetailview.FlowDetailsView( + self, + flow, + (self.statusbar, self.body, self.header) + ) self.statusbar = StatusBar(self, flowdetailview.footer) self.body = h self.header = None - self.make_view() + self.loop.widget = self.make_view() def view_grideditor(self, ge): self.body = ge self.header = None self.help_context = ge.make_help() self.statusbar = StatusBar(self, grideditor.footer) - self.make_view() + self.loop.widget = self.make_view() def view_flowlist(self): if self.ui.started: @@ -682,7 +866,7 @@ class ConsoleMaster(flow.FlowMaster): self.header = None self.state.view_mode = common.VIEW_LIST - self.make_view() + self.loop.widget = self.make_view() self.help_context = flowlist.help_context def view_flow(self, flow): @@ -691,7 +875,7 @@ class ConsoleMaster(flow.FlowMaster): self.statusbar = StatusBar(self, flowview.footer) self.state.set_focus_flow(flow) self.state.view_mode = common.VIEW_FLOW - self.make_view() + self.loop.widget = self.make_view() self.help_context = flowview.help_context def _write_flows(self, path, flows): @@ -796,12 +980,6 @@ class ConsoleMaster(flow.FlowMaster): self.state.default_body_view = v self.refresh_focus() - def drawscreen(self): - size = self.ui.get_cols_rows() - canvas = self.view.render(size, focus=1) - self.ui.draw_screen(size, canvas) - return size - def pop_view(self): if self.state.view_mode == common.VIEW_FLOW: self.view_flow(self.state.view[self.state.focus]) @@ -825,170 +1003,6 @@ class ConsoleMaster(flow.FlowMaster): patterns = (x[0] for x in tcp) self.set_tcp_filter(patterns) - def loop(self): - changed = True - try: - while not self.should_exit.is_set(): - startloop = time.time() - if changed: - self.statusbar.redraw() - size = self.drawscreen() - changed = self.tick(self.masterq, timeout=0.1) - self.ui.set_input_timeouts(max_wait=0) - keys = self.ui.get_input() - if keys: - changed = True - for k in keys: - if self.prompting: - if k == "esc": - self.prompt_cancel() - elif self.onekey: - if k == "enter": - self.prompt_cancel() - elif k in self.onekey: - self.prompt_execute(k) - elif k == "enter": - self.prompt_execute() - else: - self.view.keypress(size, k) - else: - k = self.view.keypress(size, k) - if k: - self.statusbar.message("") - if k == "?": - self.view_help() - elif k == "c": - if not self.client_playback: - self.path_prompt( - "Client replay: ", - self.state.last_saveload, - self.client_playback_path - ) - else: - self.prompt_onekey( - "Stop current client replay?", - ( - ("yes", "y"), - ("no", "n"), - ), - self.stop_client_playback_prompt, - ) - elif k == "H": - self.view_grideditor( - grideditor.SetHeadersEditor( - self, - self.setheaders.get_specs(), - self.setheaders.set - ) - ) - elif k == "I": - self.view_grideditor( - grideditor.HostPatternEditor( - self, - [[x] for x in self.get_ignore_filter()], - self.edit_ignore_filter - ) - ) - elif k == "T": - self.view_grideditor( - grideditor.HostPatternEditor( - self, - [[x] for x in self.get_tcp_filter()], - self.edit_tcp_filter - ) - ) - elif k == "i": - self.prompt( - "Intercept filter: ", - self.state.intercept_txt, - self.set_intercept - ) - elif k == "Q": - raise Stop - elif k == "q": - self.prompt_onekey( - "Quit", - ( - ("yes", "y"), - ("no", "n"), - ), - self.quit, - ) - elif k == "M": - self.prompt_onekey( - "Global default display mode", - contentview.view_prompts, - self.change_default_display_mode - ) - elif k == "R": - self.view_grideditor( - grideditor.ReplaceEditor( - self, - self.replacehooks.get_specs(), - self.replacehooks.set - ) - ) - elif k == "s": - self.view_grideditor( - grideditor.ScriptEditor( - self, - [[i.command] for i in self.scripts], - self.edit_scripts - ) - ) - #if self.scripts: - # self.load_script(None) - #else: - # self.path_prompt( - # "Set script: ", - # self.state.last_script, - # self.set_script - # ) - elif k == "S": - if not self.server_playback: - self.path_prompt( - "Server replay path: ", - self.state.last_saveload, - self.server_playback_path - ) - else: - self.prompt_onekey( - "Stop current server replay?", - ( - ("yes", "y"), - ("no", "n"), - ), - self.stop_server_playback_prompt, - ) - elif k == "o": - self.prompt_onekey( - "Options", - ( - ("anticache", "a"), - ("anticomp", "c"), - ("showhost", "h"), - ("killextra", "k"), - ("norefresh", "n"), - ("no-upstream-certs", "u"), - ), - self._change_options - ) - elif k == "t": - self.prompt( - "Sticky cookie filter: ", - self.stickycookie_txt, - self.set_stickycookie - ) - elif k == "u": - self.prompt( - "Sticky auth filter: ", - self.stickyauth_txt, - self.set_stickyauth - ) - self.looptime = time.time() - startloop - except (Stop, KeyboardInterrupt): - pass - def stop_client_playback_prompt(self, a): if a != "n": self.stop_client_playback() @@ -999,7 +1013,7 @@ class ConsoleMaster(flow.FlowMaster): def quit(self, a): if a != "n": - raise Stop + raise urwid.ExitMainLoop def _change_options(self, a): if a == "a": @@ -1015,7 +1029,8 @@ class ConsoleMaster(flow.FlowMaster): elif a == "n": self.refresh_server_playback = not self.refresh_server_playback elif a == "u": - self.server.config.no_upstream_cert = not self.server.config.no_upstream_cert + self.server.config.no_upstream_cert =\ + not self.server.config.no_upstream_cert def shutdown(self): self.state.killall(self) |