diff options
-rw-r--r-- | mitmproxy/addons/streamfile.py | 2 | ||||
-rw-r--r-- | mitmproxy/options.py | 22 | ||||
-rw-r--r-- | mitmproxy/optmanager.py | 16 | ||||
-rw-r--r-- | mitmproxy/tools/console/master.py | 2 | ||||
-rw-r--r-- | mitmproxy/tools/console/options.py | 41 | ||||
-rw-r--r-- | test/mitmproxy/test_optmanager.py | 7 |
6 files changed, 53 insertions, 37 deletions
diff --git a/mitmproxy/addons/streamfile.py b/mitmproxy/addons/streamfile.py index 377f277d..2fc61015 100644 --- a/mitmproxy/addons/streamfile.py +++ b/mitmproxy/addons/streamfile.py @@ -23,7 +23,7 @@ class StreamFile: def configure(self, options, updated): # We're already streaming - stop the previous stream and restart if "filtstr" in updated: - if options.get("filtstr"): + if options.filtstr: self.filt = flowfilter.parse(options.filtstr) if not self.filt: raise exceptions.OptionsError( diff --git a/mitmproxy/options.py b/mitmproxy/options.py index 8a9385da..bf35cd59 100644 --- a/mitmproxy/options.py +++ b/mitmproxy/options.py @@ -30,19 +30,19 @@ class Options(optmanager.OptManager): app_port: int = APP_PORT, anticache: bool = False, anticomp: bool = False, - client_replay: Sequence[str] = (), + client_replay: Sequence[str] = [], replay_kill_extra: bool = False, keepserving: bool = True, no_server: bool = False, server_replay_nopop: bool = False, refresh_server_playback: bool = False, rfile: Optional[str] = None, - scripts: Sequence[str] = (), + scripts: Sequence[str] = [], showhost: bool = False, - replacements: Sequence[Tuple[str, str, str]] = (), - server_replay_use_headers: Sequence[str] = (), - setheaders: Sequence[Tuple[str, str, str]] = (), - server_replay: Sequence[str] = (), + replacements: Sequence[Tuple[str, str, str]] = [], + server_replay_use_headers: Sequence[str] = [], + setheaders: Sequence[Tuple[str, str, str]] = [], + server_replay: Sequence[str] = [], stickycookie: Optional[str] = None, stickyauth: Optional[str] = None, stream_large_bodies: Optional[int] = None, @@ -51,8 +51,8 @@ class Options(optmanager.OptManager): streamfile: Optional[str] = None, streamfile_append: bool = False, server_replay_ignore_content: bool = False, - server_replay_ignore_params: Sequence[str] = (), - server_replay_ignore_payload_params: Sequence[str] = (), + server_replay_ignore_params: Sequence[str] = [], + server_replay_ignore_payload_params: Sequence[str] = [], server_replay_ignore_host: bool = False, # Proxy options auth_nonanonymous: bool = False, @@ -61,12 +61,12 @@ class Options(optmanager.OptManager): add_upstream_certs_to_client_chain: bool = False, body_size_limit: Optional[int] = None, cadir: str = CA_DIR, - certs: Sequence[Tuple[str, str]] = (), + certs: Sequence[Tuple[str, str]] = [], ciphers_client: str=DEFAULT_CLIENT_CIPHERS, ciphers_server: Optional[str]=None, clientcerts: Optional[str] = None, http2: bool = True, - ignore_hosts: Sequence[str] = (), + ignore_hosts: Sequence[str] = [], listen_host: str = "", listen_port: int = LISTEN_PORT, upstream_bind_address: str = "", @@ -82,7 +82,7 @@ class Options(optmanager.OptManager): ssl_insecure: bool = False, ssl_verify_upstream_trusted_cadir: Optional[str] = None, ssl_verify_upstream_trusted_ca: Optional[str] = None, - tcp_hosts: Sequence[str] = () + tcp_hosts: Sequence[str] = [] ) -> None: # We could replace all assignments with clever metaprogramming, # but type hints are a much more valueable asset. diff --git a/mitmproxy/optmanager.py b/mitmproxy/optmanager.py index 0421d4be..56122baa 100644 --- a/mitmproxy/optmanager.py +++ b/mitmproxy/optmanager.py @@ -2,6 +2,7 @@ import contextlib import blinker import pprint import inspect +import copy from mitmproxy import exceptions from mitmproxy.utils import typecheck @@ -21,6 +22,9 @@ class OptManager: updated. If any handler in the chain raises an exceptions.OptionsError exception, all changes are rolled back, the exception is suppressed, and the .errored signal is notified. + + Optmanager always returns a deep copy of options to ensure that + mutation doesn't change the option state inadvertently. """ _initialized = False attributes = [] @@ -67,7 +71,7 @@ class OptManager: def __getattr__(self, attr): if attr in self._opts: - return self._opts[attr] + return copy.deepcopy(self._opts[attr]) else: raise AttributeError("No such option: %s" % attr) @@ -89,9 +93,6 @@ class OptManager: def keys(self): return set(self._opts.keys()) - def get(self, k, d=None): - return self._opts.get(k, d) - def reset(self): """ Restore defaults for all options. @@ -132,6 +133,13 @@ class OptManager: setattr(self, attr, not getattr(self, attr)) return toggle + def has_changed(self, option): + """ + Has the option changed from the default? + """ + if getattr(self, option) != self._defaults[option]: + return True + def __repr__(self): options = pprint.pformat(self._opts, indent=4).strip(" {}") if "\n" in options: diff --git a/mitmproxy/tools/console/master.py b/mitmproxy/tools/console/master.py index 5d0e0ef4..455824d3 100644 --- a/mitmproxy/tools/console/master.py +++ b/mitmproxy/tools/console/master.py @@ -47,7 +47,7 @@ class Options(mitmproxy.options.Options): focus_follow: bool = False, intercept: Optional[str] = None, filter: Optional[str] = None, - palette: Optional[str] = None, + palette: Optional[str] = palettes.DEFAULT, palette_transparent: bool = False, no_mouse: bool = False, order: Optional[str] = None, diff --git a/mitmproxy/tools/console/options.py b/mitmproxy/tools/console/options.py index 9d698161..94483b3d 100644 --- a/mitmproxy/tools/console/options.py +++ b/mitmproxy/tools/console/options.py @@ -3,7 +3,6 @@ import urwid from mitmproxy import contentviews from mitmproxy.tools.console import common from mitmproxy.tools.console import grideditor -from mitmproxy.tools.console import palettes from mitmproxy.tools.console import select from mitmproxy.tools.console import signals @@ -26,6 +25,12 @@ def _mkhelp(): help_context = _mkhelp() +def checker(opt, options): + def _check(): + return options.has_changed(opt) + return _check + + class Options(urwid.WidgetWrap): def __init__(self, master): @@ -36,25 +41,25 @@ class Options(urwid.WidgetWrap): select.Option( "Header Set Patterns", "H", - lambda: len(master.options.setheaders), + checker("setheaders", master.options), self.setheaders ), select.Option( "Ignore Patterns", "I", - lambda: master.options.ignore_hosts, + checker("ignore_hosts", master.options), self.ignore_hosts ), select.Option( "Replacement Patterns", "R", - lambda: len(master.options.replacements), + checker("replacements", master.options), self.replacepatterns ), select.Option( "Scripts", "S", - lambda: master.options.scripts, + checker("scripts", master.options), self.scripts ), @@ -62,19 +67,19 @@ class Options(urwid.WidgetWrap): select.Option( "Default Display Mode", "M", - lambda: self.master.options.default_contentview != "auto", + checker("default_contentview", master.options), self.default_displaymode ), select.Option( "Palette", "P", - lambda: self.master.palette != palettes.DEFAULT, + checker("palette", master.options), self.palette ), select.Option( "Show Host", "w", - lambda: master.options.showhost, + checker("showhost", master.options), master.options.toggler("showhost") ), @@ -82,19 +87,19 @@ class Options(urwid.WidgetWrap): select.Option( "No Upstream Certs", "U", - lambda: master.options.no_upstream_cert, + checker("no_upstream_cert", master.options), master.options.toggler("no_upstream_cert") ), select.Option( "TCP Proxying", "T", - lambda: master.options.tcp_hosts, + checker("tcp_hosts", master.options), self.tcp_hosts ), select.Option( "Don't Verify SSL/TLS Certificates", "V", - lambda: master.options.ssl_insecure, + checker("ssl_insecure", master.options), master.options.toggler("ssl_insecure") ), @@ -102,37 +107,37 @@ class Options(urwid.WidgetWrap): select.Option( "Anti-Cache", "a", - lambda: master.options.anticache, + checker("anticache", master.options), master.options.toggler("anticache") ), select.Option( "Anti-Compression", "o", - lambda: master.options.anticomp, + checker("anticomp", master.options), master.options.toggler("anticomp") ), select.Option( "Kill Extra", "x", - lambda: master.options.replay_kill_extra, + checker("replay_kill_extra", master.options), master.options.toggler("replay_kill_extra") ), select.Option( "No Refresh", "f", - lambda: not master.options.refresh_server_playback, + checker("refresh_server_playback", master.options), master.options.toggler("refresh_server_playback") ), select.Option( "Sticky Auth", "A", - lambda: master.options.stickyauth, + checker("stickyauth", master.options), self.sticky_auth ), select.Option( "Sticky Cookies", "t", - lambda: master.options.stickycookie, + checker("stickycookie", master.options), self.sticky_cookie ), ] @@ -163,7 +168,7 @@ class Options(urwid.WidgetWrap): self.master.options.reset() signals.update_settings.send(self) signals.status_message.send( - message = "All select.Options cleared", + message = "Options cleared", expire = 1 ) diff --git a/test/mitmproxy/test_optmanager.py b/test/mitmproxy/test_optmanager.py index 47e40d98..345512fd 100644 --- a/test/mitmproxy/test_optmanager.py +++ b/test/mitmproxy/test_optmanager.py @@ -35,6 +35,7 @@ def test_defaults(): "three": "dthree", "four": "dfour", } + assert not o.has_changed("one") newvals = dict( one="xone", two="xtwo", @@ -42,11 +43,13 @@ def test_defaults(): four="xfour", ) o.update(**newvals) + assert o.has_changed("one") for k, v in newvals.items(): - assert v == o.get(k) + assert v == getattr(o, k) o.reset() + assert not o.has_changed("one") for k, v in o._defaults.items(): - assert v == o.get(k) + assert v == getattr(o, k) def test_options(): |