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).
This commit is contained in:
Aldo Cortesi 2012-04-02 10:30:35 +12:00
parent 7fef0ecdf5
commit 15cc09f1b8
4 changed files with 125 additions and 150 deletions

View File

@ -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)

View File

@ -8,47 +8,53 @@ from ..contrib import jsbeautifier
VIEW_CUTOFF = 1024*20
VIEW_CONTENT_RAW = 0
VIEW_CONTENT_HEX = 1
VIEW_CONTENT_PRETTY = 2
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
CONTENT_VIEWS = {
VIEW_CONTENT_RAW: "raw",
VIEW_CONTENT_HEX: "hex",
VIEW_CONTENT_PRETTY: "pretty"
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)
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, pretty_type, hdrItems, content):
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)

View File

@ -27,26 +27,15 @@ def _mkhelp():
("d", "delete flow"),
("D", "duplicate flow"),
("e", "edit request/response"),
("m", "change body display mode"),
(None,
common.highlight_key("raw", "r") +
[("text", ": raw data")]
),
(None,
common.highlight_key("pretty", "p") +
[("text", ": pretty-print XML, HTML and JSON")]
),
(None,
common.highlight_key("hex", "h") +
[("text", ": hex dump")]
),
("p", "previous flow"),
("r", "replay request"),
("T", "override content-type for pretty-printed body"),
("m", "change body display mode for this entity"),
(None,
common.highlight_key("automatic", "a") +
[("text", ": automatic detection")]
),
(None,
common.highlight_key("hex", "h") +
[("text", ": Hex")]
),
(None,
common.highlight_key("image", "i") +
[("text", ": Image")]
@ -63,10 +52,17 @@ def _mkhelp():
common.highlight_key("urlencoded", "u") +
[("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,13 +454,34 @@ 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 == "M":
self.master.prompt_onekey(
"Global default display mode",
(
("auto detect", "a"),
("hex", "h"),
("image", "i"),
("javascript", "j"),
("json", "s"),
("raw", "r"),
("urlencoded", "u"),
("xmlish", "x"),
),
self.change_default_display_mode
)
key = None
elif key == "p":
@ -480,20 +491,6 @@ class FlowView(common.WWrap):
if r:
self.master.statusbar.message(r)
self.master.refresh_flow(self.flow)
elif key == "T":
self.master.prompt_onekey(
"Pretty-Print format",
(
("auto detect", "a"),
("image", "i"),
("javascript", "j"),
("json", "s"),
("urlencoded", "u"),
("xmlish", "x"),
),
self.change_pretty_type
)
key = None
elif key == "V":
self.state.revert(self.flow)
self.master.refresh_flow(self.flow)

View File

@ -12,24 +12,21 @@ class uContentView(libpry.AutoTree):
def test_get_view_func(self):
f = cv.get_view_func(
cv.VIEW_CONTENT_HEX,
cv.VIEW_CONTENT_PRETTY_TYPE_AUTO,
cv.VIEW_HEX,
flow.ODictCaseless(),
"foo"
)
assert f is cv.view_hex
f = cv.get_view_func(
cv.VIEW_CONTENT_RAW,
cv.VIEW_CONTENT_PRETTY_TYPE_AUTO,
cv.VIEW_AUTO,
flow.ODictCaseless(),
"foo"
)
assert f is cv.view_raw
f = cv.get_view_func(
cv.VIEW_CONTENT_PRETTY,
cv.VIEW_CONTENT_PRETTY_TYPE_AUTO,
cv.VIEW_AUTO,
flow.ODictCaseless(
[["content-type", "text/html"]],
),
@ -38,8 +35,7 @@ class uContentView(libpry.AutoTree):
assert f is cv.view_xmlish
f = cv.get_view_func(
cv.VIEW_CONTENT_PRETTY,
cv.VIEW_CONTENT_PRETTY_TYPE_AUTO,
cv.VIEW_AUTO,
flow.ODictCaseless(
[["content-type", "text/flibble"]],
),
@ -48,8 +44,7 @@ class uContentView(libpry.AutoTree):
assert f is cv.view_raw
f = cv.get_view_func(
cv.VIEW_CONTENT_PRETTY,
cv.VIEW_CONTENT_PRETTY_TYPE_AUTO,
cv.VIEW_AUTO,
flow.ODictCaseless(
[["content-type", "text/flibble"]],
),
@ -118,33 +113,28 @@ Larry
def test_get_content_view(self):
r = cv.get_content_view(
cv.VIEW_CONTENT_RAW,
cv.VIEW_CONTENT_PRETTY_TYPE_AUTO,
cv.VIEW_RAW,
[["content-type", "application/json"]],
"[1, 2, 3]"
)
assert r[0] == "Raw"
assert "Raw" in r[0]
r = cv.get_content_view(
cv.VIEW_CONTENT_PRETTY,
cv.VIEW_CONTENT_PRETTY_TYPE_AUTO,
cv.VIEW_AUTO,
[["content-type", "application/json"]],
"[1, 2, 3]"
)
assert r[0] == "JSON"
r = cv.get_content_view(
cv.VIEW_CONTENT_PRETTY,
cv.VIEW_CONTENT_PRETTY_TYPE_AUTO,
cv.VIEW_AUTO,
[["content-type", "application/json"]],
"[1, 2"
)
assert r[0] == "Raw"
r = cv.get_content_view(
cv.VIEW_CONTENT_PRETTY,
cv.VIEW_CONTENT_PRETTY_TYPE_AUTO,
cv.VIEW_AUTO,
[
["content-type", "application/json"],
["content-encoding", "gzip"]
@ -154,10 +144,8 @@ Larry
assert "decoded gzip" in r[0]
assert "JSON" in r[0]
r = cv.get_content_view(
cv.VIEW_CONTENT_PRETTY,
cv.VIEW_CONTENT_PRETTY_TYPE_XML,
cv.VIEW_XML,
[
["content-type", "application/json"],
["content-encoding", "gzip"]