Add flow detail view as a tab in the flow view

This commit is contained in:
Aldo Cortesi 2015-03-29 19:21:54 +13:00
parent cacd09fafc
commit 8f5cf833d0
5 changed files with 97 additions and 113 deletions

View File

@ -453,15 +453,6 @@ class ConsoleMaster(flow.FlowMaster):
statusbar.StatusBar(self, help.footer)
)
def view_flowdetails(self, flow):
signals.push_view_state.send(self)
self.loop.widget = window.Window(
self,
flowdetailview.FlowDetailsView(flow),
None,
statusbar.StatusBar(self, flowdetailview.footer)
)
def view_grideditor(self, ge):
signals.push_view_state.send(self)
self.help_context = ge.make_help()

View File

@ -1,110 +1,100 @@
from __future__ import absolute_import
import urwid
from . import common, signals
from . import common, signals, searchable
from .. import utils
footer = [
('heading_key', "q"), ":back ",
]
def flowdetails(state, flow):
text = []
class FlowDetailsView(urwid.ListBox):
def __init__(self, flow):
self.flow = flow
urwid.ListBox.__init__(
self,
self.flowtext()
cc = flow.client_conn
sc = flow.server_conn
req = flow.request
resp = flow.response
if sc:
text.append(urwid.Text([("head", "Server Connection:")]))
parts = [
["Address", "%s:%s" % sc.address()],
]
text.extend(
common.format_keyvals(parts, key="key", val="text", indent=4)
)
def keypress(self, size, key):
key = common.shortcuts(key)
if key == "q":
signals.pop_view_state.send(self)
return None
elif key == "?":
key = None
return urwid.ListBox.keypress(self, size, key)
def flowtext(self):
text = []
title = urwid.Text("Flow details")
title = urwid.Padding(title, align="left", width=("relative", 100))
title = urwid.AttrWrap(title, "heading")
text.append(title)
cc = self.flow.client_conn
sc = self.flow.server_conn
req = self.flow.request
resp = self.flow.response
if sc:
text.append(urwid.Text([("head", "Server Connection:")]))
c = sc.cert
if c:
text.append(urwid.Text([("head", "Server Certificate:")]))
parts = [
["Address", "%s:%s" % sc.address()],
]
text.extend(common.format_keyvals(parts, key="key", val="text", indent=4))
c = sc.cert
if c:
text.append(urwid.Text([("head", "Server Certificate:")]))
parts = [
["Type", "%s, %s bits"%c.keyinfo],
["SHA1 digest", c.digest("sha1")],
["Valid to", str(c.notafter)],
["Valid from", str(c.notbefore)],
["Serial", str(c.serial)],
[
"Subject",
urwid.BoxAdapter(
urwid.ListBox(common.format_keyvals(c.subject, key="highlight", val="text")),
len(c.subject)
)
],
[
"Issuer",
urwid.BoxAdapter(
urwid.ListBox(common.format_keyvals(c.issuer, key="highlight", val="text")),
len(c.issuer)
)
]
]
if c.altnames:
parts.append(
[
"Alt names",
", ".join(c.altnames)
]
["Type", "%s, %s bits"%c.keyinfo],
["SHA1 digest", c.digest("sha1")],
["Valid to", str(c.notafter)],
["Valid from", str(c.notbefore)],
["Serial", str(c.serial)],
[
"Subject",
urwid.BoxAdapter(
urwid.ListBox(
common.format_keyvals(
c.subject,
key="highlight",
val="text"
)
),
len(c.subject)
)
text.extend(common.format_keyvals(parts, key="key", val="text", indent=4))
if cc:
text.append(urwid.Text([("head", "Client Connection:")]))
parts = [
["Address", "%s:%s" % cc.address()],
# ["Requests", "%s"%cc.requestcount],
],
[
"Issuer",
urwid.BoxAdapter(
urwid.ListBox(
common.format_keyvals(
c.issuer, key="highlight", val="text"
)
),
len(c.issuer)
)
]
]
text.extend(common.format_keyvals(parts, key="key", val="text", indent=4))
if c.altnames:
parts.append(
[
"Alt names",
", ".join(c.altnames)
]
)
text.extend(
common.format_keyvals(parts, key="key", val="text", indent=4)
)
parts = []
if cc:
text.append(urwid.Text([("head", "Client Connection:")]))
parts.append(["Client conn. established", utils.format_timestamp_with_milli(cc.timestamp_start) if (cc and cc.timestamp_start) else "active"])
parts.append(["Server conn. initiated", utils.format_timestamp_with_milli(sc.timestamp_start) if sc else "active" ])
parts.append(["Server conn. TCP handshake", utils.format_timestamp_with_milli(sc.timestamp_tcp_setup) if (sc and sc.timestamp_tcp_setup) else "active"])
if sc.ssl_established:
parts.append(["Server conn. SSL handshake", utils.format_timestamp_with_milli(sc.timestamp_ssl_setup) if sc.timestamp_ssl_setup else "active"])
parts.append(["Client conn. SSL handshake", utils.format_timestamp_with_milli(cc.timestamp_ssl_setup) if (cc and cc.timestamp_ssl_setup) else "active"])
parts.append(["First request byte", utils.format_timestamp_with_milli(req.timestamp_start)])
parts.append(["Request complete", utils.format_timestamp_with_milli(req.timestamp_end) if req.timestamp_end else "active"])
parts.append(["First response byte", utils.format_timestamp_with_milli(resp.timestamp_start) if resp else "active"])
parts.append(["Response complete", utils.format_timestamp_with_milli(resp.timestamp_end) if (resp and resp.timestamp_end) else "active"])
parts = [
["Address", "%s:%s" % cc.address()],
# ["Requests", "%s"%cc.requestcount],
]
# sort operations by timestamp
parts = sorted(parts, key=lambda p: p[1])
text.extend(
common.format_keyvals(parts, key="key", val="text", indent=4)
)
text.append(urwid.Text([("head", "Timing:")]))
text.extend(common.format_keyvals(parts, key="key", val="text", indent=4))
return text
parts = []
parts.append(["Client conn. established", utils.format_timestamp_with_milli(cc.timestamp_start) if (cc and cc.timestamp_start) else "active"])
parts.append(["Server conn. initiated", utils.format_timestamp_with_milli(sc.timestamp_start) if sc else "active" ])
parts.append(["Server conn. TCP handshake", utils.format_timestamp_with_milli(sc.timestamp_tcp_setup) if (sc and sc.timestamp_tcp_setup) else "active"])
if sc.ssl_established:
parts.append(["Server conn. SSL handshake", utils.format_timestamp_with_milli(sc.timestamp_ssl_setup) if sc.timestamp_ssl_setup else "active"])
parts.append(["Client conn. SSL handshake", utils.format_timestamp_with_milli(cc.timestamp_ssl_setup) if (cc and cc.timestamp_ssl_setup) else "active"])
parts.append(["First request byte", utils.format_timestamp_with_milli(req.timestamp_start)])
parts.append(["Request complete", utils.format_timestamp_with_milli(req.timestamp_end) if req.timestamp_end else "active"])
parts.append(["First response byte", utils.format_timestamp_with_milli(resp.timestamp_start) if resp else "active"])
parts.append(["Response complete", utils.format_timestamp_with_milli(resp.timestamp_end) if (resp and resp.timestamp_end) else "active"])
# sort operations by timestamp
parts = sorted(parts, key=lambda p: p[1])
text.append(urwid.Text([("head", "Timing:")]))
text.extend(common.format_keyvals(parts, key="key", val="text", indent=4))
return searchable.Searchable(state, text)

View File

@ -2,6 +2,7 @@ from __future__ import absolute_import
import os, sys, copy
import urwid
from . import common, grideditor, contentview, signals, searchable, tabs
from . import flowdetailview
from .. import utils, flow, controller
from ..protocol.http import HTTPRequest, HTTPResponse, CONTENT_MISSING, decoded
@ -65,7 +66,6 @@ def _mkhelp():
("w", "save all flows matching current limit"),
("W", "save this flow"),
("x", "delete body"),
("X", "view flow details"),
("z", "encode/decode a request/response"),
("tab", "toggle request/response view"),
("space", "next flow"),
@ -121,6 +121,7 @@ class FlowView(tabs.Tabs):
[
(self.tab_request, self.view_request),
(self.tab_response, self.view_response),
(self.tab_details, self.view_details),
],
tab_offset
)
@ -140,13 +141,17 @@ class FlowView(tabs.Tabs):
else:
return "Response"
def tab_details(self):
return "Detail"
def view_request(self):
return self.conn_text(self.flow.request)
def view_response(self):
return self.conn_text(self.flow.response)
def view_details(self):
return flowdetailview.flowdetails(self.state, self.flow)
def sig_flow_change(self, sender, flow):
if flow == self.flow:
@ -568,8 +573,6 @@ class FlowView(tabs.Tabs):
callback = self.delete_body
)
key = None
elif key == "X":
self.master.view_flowdetails(self.flow)
elif key == "z":
if conn:
self.flow.backup()

View File

@ -36,7 +36,7 @@ class Searchable(urwid.ListBox):
if key == "N":
self.find_next(True)
else:
return super(self.__class__, self).keypress(size, key)
return key
def set_search(self, text):
self.state.last_search = text

View File

@ -8,8 +8,8 @@ class Tabs(urwid.WidgetWrap):
self.show()
def _tab(self, content, attr):
p = urwid.Text(content)
p = urwid.Padding(p, align="left", width=("relative", 100))
p = urwid.Text(content, align="center")
p = urwid.Padding(p, align="center", width=("relative", 100))
p = urwid.AttrWrap(p, attr)
return p
@ -18,7 +18,7 @@ class Tabs(urwid.WidgetWrap):
self.tab_offset = (self.tab_offset + 1)%(len(self.tabs))
self.show()
else:
return key
return self._w.keypress(size, key)
def show(self):
headers = []
@ -28,7 +28,7 @@ class Tabs(urwid.WidgetWrap):
headers.append(self._tab(txt, "heading"))
else:
headers.append(self._tab(txt, "heading_inactive"))
headers = urwid.Columns(headers)
headers = urwid.Columns(headers, dividechars=1)
self._w = urwid.Frame(
body = self.tabs[self.tab_offset][1](),
header = headers