aboutsummaryrefslogtreecommitdiffstats
path: root/libmproxy/console
diff options
context:
space:
mode:
authorAldo Cortesi <aldo@nullcube.com>2012-04-02 10:30:35 +1200
committerAldo Cortesi <aldo@nullcube.com>2012-04-02 10:30:35 +1200
commit15cc09f1b8d49ce57918acbfe8fd249a4977b036 (patch)
tree9696bc74f488a9a18d2e819ee17329b12c5b46f6 /libmproxy/console
parent7fef0ecdf5618d06e78ee8f833525d7784234df8 (diff)
downloadmitmproxy-15cc09f1b8d49ce57918acbfe8fd249a4977b036.tar.gz
mitmproxy-15cc09f1b8d49ce57918acbfe8fd249a4977b036.tar.bz2
mitmproxy-15cc09f1b8d49ce57918acbfe8fd249a4977b036.zip
Start rationalizing content views.
We now no longer have distinction between "pretty" view and hex/raw. Instead, we simply a default AUTO view with a global override (M) and a local override (m).
Diffstat (limited to 'libmproxy/console')
-rw-r--r--libmproxy/console/__init__.py11
-rw-r--r--libmproxy/console/contentview.py131
-rw-r--r--libmproxy/console/flowview.py95
3 files changed, 112 insertions, 125 deletions
diff --git a/libmproxy/console/__init__.py b/libmproxy/console/__init__.py
index ee295755..1e5524d8 100644
--- a/libmproxy/console/__init__.py
+++ b/libmproxy/console/__init__.py
@@ -231,7 +231,7 @@ class ConsoleState(flow.State):
def __init__(self):
flow.State.__init__(self)
self.focus = None
- self.view_body_mode = contentview.VIEW_CONTENT_PRETTY
+ self.default_body_view = contentview.VIEW_AUTO
self.view_flow_mode = common.VIEW_FLOW_REQUEST
self.last_script = ""
self.last_saveload = ""
@@ -686,15 +686,6 @@ class ConsoleMaster(flow.FlowMaster):
return "Invalid reverse proxy specification"
self.server.config.reverse_proxy = s
- def changeview(self, v):
- if v == "r":
- self.state.view_body_mode = contentview.VIEW_CONTENT_RAW
- elif v == "h":
- self.state.view_body_mode = contentview.VIEW_CONTENT_HEX
- elif v == "p":
- self.state.view_body_mode = contentview.VIEW_CONTENT_PRETTY
- self.refresh_flow(self.currentflow)
-
def drawscreen(self):
size = self.ui.get_cols_rows()
canvas = self.view.render(size, focus=1)
diff --git a/libmproxy/console/contentview.py b/libmproxy/console/contentview.py
index 10a33e05..1d621ae2 100644
--- a/libmproxy/console/contentview.py
+++ b/libmproxy/console/contentview.py
@@ -8,47 +8,53 @@ from ..contrib import jsbeautifier
VIEW_CUTOFF = 1024*20
-VIEW_CONTENT_RAW = 0
-VIEW_CONTENT_HEX = 1
-VIEW_CONTENT_PRETTY = 2
-
-CONTENT_VIEWS = {
- VIEW_CONTENT_RAW: "raw",
- VIEW_CONTENT_HEX: "hex",
- VIEW_CONTENT_PRETTY: "pretty"
+VIEW_AUTO = 0
+VIEW_JSON = 1
+VIEW_XML = 2
+VIEW_URLENCODED = 3
+VIEW_MULTIPART = 4
+VIEW_JAVASCRIPT = 5
+VIEW_IMAGE = 6
+VIEW_RAW = 7
+VIEW_HEX = 8
+
+VIEW_NAMES = {
+ VIEW_AUTO: "Auto",
+ VIEW_JSON: "JSON",
+ VIEW_XML: "XML",
+ VIEW_URLENCODED: "URL-encoded",
+ VIEW_MULTIPART: "Multipart Form",
+ VIEW_JAVASCRIPT: "JavaScript",
+ VIEW_IMAGE: "Image",
+ VIEW_RAW: "Raw",
+ VIEW_HEX: "Hex",
}
-VIEW_CONTENT_PRETTY_TYPE_AUTO = 0
-VIEW_CONTENT_PRETTY_TYPE_JSON = 1
-VIEW_CONTENT_PRETTY_TYPE_XML = 2
-VIEW_CONTENT_PRETTY_TYPE_URLENCODED = 3
-VIEW_CONTENT_PRETTY_TYPE_MULTIPART = 4
-VIEW_CONTENT_PRETTY_TYPE_JAVASCRIPT = 5
-VIEW_CONTENT_PRETTY_TYPE_IMAGE = 6
-
-CONTENT_PRETTY_NAMES = {
- VIEW_CONTENT_PRETTY_TYPE_JSON: "JSON",
- VIEW_CONTENT_PRETTY_TYPE_XML: "XML",
- VIEW_CONTENT_PRETTY_TYPE_URLENCODED: "URL-encoded",
- VIEW_CONTENT_PRETTY_TYPE_MULTIPART: "Multipart Form",
- VIEW_CONTENT_PRETTY_TYPE_JAVASCRIPT: "JavaScript",
- VIEW_CONTENT_PRETTY_TYPE_IMAGE: "Image",
+VIEW_SHORTCUTS = {
+ "a": VIEW_AUTO,
+ "i": VIEW_IMAGE,
+ "j": VIEW_JAVASCRIPT,
+ "s": VIEW_JSON,
+ "u": VIEW_URLENCODED,
+ "x": VIEW_XML,
+ "r": VIEW_RAW,
+ "h": VIEW_HEX,
}
CONTENT_TYPES_MAP = {
- "text/html": VIEW_CONTENT_PRETTY_TYPE_XML,
- "application/json": VIEW_CONTENT_PRETTY_TYPE_JSON,
- "text/xml": VIEW_CONTENT_PRETTY_TYPE_XML,
- "multipart/form-data": VIEW_CONTENT_PRETTY_TYPE_MULTIPART,
- "application/x-www-form-urlencoded": VIEW_CONTENT_PRETTY_TYPE_URLENCODED,
- "application/x-javascript": VIEW_CONTENT_PRETTY_TYPE_JAVASCRIPT,
- "application/javascript": VIEW_CONTENT_PRETTY_TYPE_JAVASCRIPT,
- "text/javascript": VIEW_CONTENT_PRETTY_TYPE_JAVASCRIPT,
- "image/png": VIEW_CONTENT_PRETTY_TYPE_IMAGE,
- "image/jpeg": VIEW_CONTENT_PRETTY_TYPE_IMAGE,
- "image/gif": VIEW_CONTENT_PRETTY_TYPE_IMAGE,
- "image/vnd.microsoft.icon": VIEW_CONTENT_PRETTY_TYPE_IMAGE,
- "image/x-icon": VIEW_CONTENT_PRETTY_TYPE_IMAGE,
+ "text/html": VIEW_XML,
+ "application/json": VIEW_JSON,
+ "text/xml": VIEW_XML,
+ "multipart/form-data": VIEW_MULTIPART,
+ "application/x-www-form-urlencoded": VIEW_URLENCODED,
+ "application/x-javascript": VIEW_JAVASCRIPT,
+ "application/javascript": VIEW_JAVASCRIPT,
+ "text/javascript": VIEW_JAVASCRIPT,
+ "image/png": VIEW_IMAGE,
+ "image/jpeg": VIEW_IMAGE,
+ "image/gif": VIEW_IMAGE,
+ "image/vnd.microsoft.icon": VIEW_IMAGE,
+ "image/x-icon": VIEW_IMAGE,
}
def trailer(clen, txt):
@@ -209,36 +215,33 @@ def view_image(hdrs, content):
PRETTY_FUNCTION_MAP = {
- VIEW_CONTENT_PRETTY_TYPE_XML: view_xmlish,
- VIEW_CONTENT_PRETTY_TYPE_JSON: view_json,
- VIEW_CONTENT_PRETTY_TYPE_URLENCODED: view_urlencoded,
- VIEW_CONTENT_PRETTY_TYPE_MULTIPART: view_multipart,
- VIEW_CONTENT_PRETTY_TYPE_JAVASCRIPT: view_javascript,
- VIEW_CONTENT_PRETTY_TYPE_IMAGE: view_image,
+ VIEW_XML: view_xmlish,
+ VIEW_JSON: view_json,
+ VIEW_URLENCODED: view_urlencoded,
+ VIEW_MULTIPART: view_multipart,
+ VIEW_JAVASCRIPT: view_javascript,
+ VIEW_IMAGE: view_image,
+ VIEW_HEX: view_hex,
+ VIEW_RAW: view_raw,
}
-def get_view_func(viewmode, pretty_type, hdrs, content):
+def get_view_func(viewmode, hdrs, content):
"""
Returns a function object.
"""
- if viewmode == VIEW_CONTENT_HEX:
- return view_hex
- elif viewmode == VIEW_CONTENT_RAW:
- return view_raw
- else:
- if pretty_type == VIEW_CONTENT_PRETTY_TYPE_AUTO:
- ctype = hdrs.get("content-type")
- if ctype:
- ctype = ctype[0]
- ct = utils.parse_content_type(ctype) if ctype else None
- if ct:
- pretty_type = CONTENT_TYPES_MAP.get("%s/%s"%(ct[0], ct[1]))
- if not pretty_type and utils.isXML(content):
- pretty_type = VIEW_CONTENT_PRETTY_TYPE_XML
- return PRETTY_FUNCTION_MAP.get(pretty_type, view_raw)
-
-
-def get_content_view(viewmode, pretty_type, hdrItems, content):
+ if viewmode == VIEW_AUTO:
+ ctype = hdrs.get("content-type")
+ if ctype:
+ ctype = ctype[0]
+ ct = utils.parse_content_type(ctype) if ctype else None
+ if ct:
+ viewmode = CONTENT_TYPES_MAP.get("%s/%s"%(ct[0], ct[1]))
+ if not viewmode and utils.isXML(content):
+ viewmode = VIEW_XML
+ return PRETTY_FUNCTION_MAP.get(viewmode, view_raw)
+
+
+def get_content_view(viewmode, hdrItems, content):
"""
Returns a (msg, body) tuple.
"""
@@ -252,11 +255,7 @@ def get_content_view(viewmode, pretty_type, hdrItems, content):
if decoded:
content = decoded
msg.append("[decoded %s]"%enc[0])
-
- if viewmode == VIEW_CONTENT_PRETTY and pretty_type != VIEW_CONTENT_PRETTY_TYPE_AUTO:
- msg.append("[forced to %s]"%(CONTENT_PRETTY_NAMES[pretty_type]))
- func = get_view_func(viewmode, pretty_type, hdrs, content)
-
+ func = get_view_func(viewmode, hdrs, content)
ret = func(hdrs, content)
if not ret:
ret = view_raw(hdrs, content)
diff --git a/libmproxy/console/flowview.py b/libmproxy/console/flowview.py
index bbf3a89a..9dbbcf50 100644
--- a/libmproxy/console/flowview.py
+++ b/libmproxy/console/flowview.py
@@ -27,25 +27,14 @@ def _mkhelp():
("d", "delete flow"),
("D", "duplicate flow"),
("e", "edit request/response"),
- ("m", "change body display mode"),
+ ("m", "change body display mode for this entity"),
(None,
- common.highlight_key("raw", "r") +
- [("text", ": raw data")]
- ),
- (None,
- common.highlight_key("pretty", "p") +
- [("text", ": pretty-print XML, HTML and JSON")]
+ common.highlight_key("automatic", "a") +
+ [("text", ": automatic detection")]
),
(None,
common.highlight_key("hex", "h") +
- [("text", ": hex dump")]
- ),
- ("p", "previous flow"),
- ("r", "replay request"),
- ("T", "override content-type for pretty-printed body"),
- (None,
- common.highlight_key("automatic", "a") +
- [("text", ": automatic detection")]
+ [("text", ": Hex")]
),
(None,
common.highlight_key("image", "i") +
@@ -64,9 +53,16 @@ def _mkhelp():
[("text", ": URL-encoded data")]
),
(None,
+ common.highlight_key("raw", "r") +
+ [("text", ": raw data")]
+ ),
+ (None,
common.highlight_key("xml", "x") +
[("text", ": XML")]
),
+ ("M", "change default body display mode"),
+ ("p", "previous flow"),
+ ("r", "replay request"),
("V", "revert changes to request"),
("v", "view body in external viewer"),
("w", "save all flows matching current limit"),
@@ -128,14 +124,14 @@ class FlowView(common.WWrap):
else:
self.view_request()
- def _cached_conn_text(self, content, hdrItems, viewmode, pretty_type):
+ def _cached_conn_text(self, content, hdrItems, viewmode):
txt = common.format_keyvals(
[(h+":", v) for (h, v) in hdrItems],
key = "header",
val = "text"
)
if content:
- msg, body = contentview.get_content_view(viewmode, pretty_type, hdrItems, content)
+ msg, body = contentview.get_content_view(viewmode, hdrItems, content)
title = urwid.AttrWrap(urwid.Columns([
urwid.Text(
[
@@ -147,7 +143,7 @@ class FlowView(common.WWrap):
" ",
('heading', "["),
('heading_key', "m"),
- ('heading', (":%s]"%contentview.CONTENT_VIEWS[self.master.state.view_body_mode])),
+ ('heading', (":%s]"%contentview.VIEW_NAMES[viewmode])),
],
align="right"
),
@@ -190,24 +186,22 @@ class FlowView(common.WWrap):
)
return f
- def _conn_text(self, conn, viewmode, pretty_type):
+ def _conn_text(self, conn, viewmode):
return cache.callback(
self, "_cached_conn_text",
conn.content,
tuple(tuple(i) for i in conn.headers.lst),
- viewmode,
- pretty_type
+ viewmode
)
def view_request(self):
self.state.view_flow_mode = common.VIEW_FLOW_REQUEST
body = self._conn_text(
self.flow.request,
- self.state.view_body_mode,
self.state.get_flow_setting(
self.flow,
(common.VIEW_FLOW_REQUEST, "prettyview"),
- contentview.VIEW_CONTENT_PRETTY_TYPE_AUTO
+ self.state.default_body_view
)
)
self.w = self.wrap_body(common.VIEW_FLOW_REQUEST, body)
@@ -218,11 +212,10 @@ class FlowView(common.WWrap):
if self.flow.response:
body = self._conn_text(
self.flow.response,
- self.state.view_body_mode,
self.state.get_flow_setting(
self.flow,
(common.VIEW_FLOW_RESPONSE, "prettyview"),
- contentview.VIEW_CONTENT_PRETTY_TYPE_AUTO
+ self.state.default_body_view
)
)
else:
@@ -377,22 +370,19 @@ class FlowView(common.WWrap):
def view_prev_flow(self, flow):
return self._view_nextprev_flow("prev", flow)
- def change_pretty_type(self, t):
- d = {
- "a": contentview.VIEW_CONTENT_PRETTY_TYPE_AUTO,
- "i": contentview.VIEW_CONTENT_PRETTY_TYPE_IMAGE,
- "j": contentview.VIEW_CONTENT_PRETTY_TYPE_JAVASCRIPT,
- "s": contentview.VIEW_CONTENT_PRETTY_TYPE_JSON,
- "u": contentview.VIEW_CONTENT_PRETTY_TYPE_URLENCODED,
- "x": contentview.VIEW_CONTENT_PRETTY_TYPE_XML,
- }
+ def change_this_display_mode(self, t):
self.state.add_flow_setting(
self.flow,
(self.state.view_flow_mode, "prettyview"),
- d.get(t)
+ contentview.VIEW_SHORTCUTS.get(t)
)
self.master.refresh_flow(self.flow)
+ def change_default_display_mode(self, t):
+ v = contentview.VIEW_SHORTCUTS.get(t)
+ self.state.default_body_view = v
+ self.master.refresh_flow(self.flow)
+
def keypress(self, size, key):
if key == " ":
self.view_next_flow(self.flow)
@@ -464,36 +454,43 @@ class FlowView(common.WWrap):
key = None
elif key == "m":
self.master.prompt_onekey(
- "View",
+ "Display mode",
(
- ("raw", "r"),
- ("pretty", "p"),
+ ("auto detect", "a"),
("hex", "h"),
+ ("image", "i"),
+ ("javascript", "j"),
+ ("json", "s"),
+ ("raw", "r"),
+ ("urlencoded", "u"),
+ ("xmlish", "x"),
),
- self.master.changeview
+ self.change_this_display_mode
)
key = None
- elif key == "p":
- self.view_prev_flow(self.flow)
- elif key == "r":
- r = self.master.replay_request(self.flow)
- if r:
- self.master.statusbar.message(r)
- self.master.refresh_flow(self.flow)
- elif key == "T":
+ elif key == "M":
self.master.prompt_onekey(
- "Pretty-Print format",
+ "Global default display mode",
(
("auto detect", "a"),
+ ("hex", "h"),
("image", "i"),
("javascript", "j"),
("json", "s"),
+ ("raw", "r"),
("urlencoded", "u"),
("xmlish", "x"),
),
- self.change_pretty_type
+ self.change_default_display_mode
)
key = None
+ elif key == "p":
+ self.view_prev_flow(self.flow)
+ elif key == "r":
+ r = self.master.replay_request(self.flow)
+ if r:
+ self.master.statusbar.message(r)
+ self.master.refresh_flow(self.flow)
elif key == "V":
self.state.revert(self.flow)
self.master.refresh_flow(self.flow)