console: suport unary attributes

Attributes with no value are treated as unary, e.g. "Secure" rather than
"Secure=". If you really want to have an empty attribute value you can
edit the header directly.

Behind the scenes, restructure GridEditor to know about data conversion
in and out of the editor.
This commit is contained in:
Aldo Cortesi 2015-04-17 12:54:29 +12:00
parent 7abaf3c362
commit e963a9da48
3 changed files with 66 additions and 28 deletions

View File

@ -290,7 +290,7 @@ class FlowView(tabs.Tabs):
signals.flow_change.send(self, flow = self.flow) signals.flow_change.send(self, flow = self.flow)
def set_path_components(self, lst, conn): def set_path_components(self, lst, conn):
conn.set_path_components([i[0] for i in lst]) conn.set_path_components(lst)
signals.flow_change.send(self, flow = self.flow) signals.flow_change.send(self, flow = self.flow)
def set_form(self, lst, conn): def set_form(self, lst, conn):
@ -316,17 +316,8 @@ class FlowView(tabs.Tabs):
conn.set_cookies(od) conn.set_cookies(od)
signals.flow_change.send(self, flow = self.flow) signals.flow_change.send(self, flow = self.flow)
def set_setcookies(self, lst, conn): def set_setcookies(self, data, conn):
vals = [] conn.set_cookies(data)
for i in lst:
vals.append(
[
i[0],
[i[1], odict.ODictCaseless(i[2])]
]
)
od = odict.ODict(vals)
conn.set_cookies(od)
signals.flow_change.send(self, flow = self.flow) signals.flow_change.send(self, flow = self.flow)
def edit(self, part): def edit(self, part):
@ -352,13 +343,10 @@ class FlowView(tabs.Tabs):
) )
) )
if message == self.flow.response and part == "c": if message == self.flow.response and part == "c":
flattened = []
for k, v in message.get_cookies().items():
flattened.append([k, v[0], v[1].lst])
self.master.view_grideditor( self.master.view_grideditor(
grideditor.SetCookieEditor( grideditor.SetCookieEditor(
self.master, self.master,
flattened, message.get_cookies(),
self.set_setcookies, self.set_setcookies,
message message
) )
@ -397,7 +385,6 @@ class FlowView(tabs.Tabs):
) )
elif part == "p": elif part == "p":
p = message.get_path_components() p = message.get_path_components()
p = [[i] for i in p]
self.master.view_grideditor( self.master.view_grideditor(
grideditor.PathEditor( grideditor.PathEditor(
self.master, self.master,

View File

@ -7,7 +7,7 @@ import urwid
from . import common, signals from . import common, signals
from .. import utils, filt, script from .. import utils, filt, script
from netlib import http_uastrings, http_cookies from netlib import http_uastrings, http_cookies, odict
FOOTER = [ FOOTER = [
@ -231,8 +231,10 @@ class GridWalker(urwid.ListWalker):
def _insert(self, pos): def _insert(self, pos):
self.focus = pos self.focus = pos
self.lst.insert( self.lst.insert(
self.focus, [ self.focus,
[c.blank() for c in self.editor.columns], set([])] [
[c.blank() for c in self.editor.columns], set([])
]
) )
self.focus_col = 0 self.focus_col = 0
self.start_edit() self.start_edit()
@ -318,7 +320,7 @@ class GridEditor(urwid.WidgetWrap):
columns = None columns = None
def __init__(self, master, value, callback, *cb_args, **cb_kwargs): def __init__(self, master, value, callback, *cb_args, **cb_kwargs):
value = copy.deepcopy(value) value = self.data_in(copy.deepcopy(value))
self.master, self.value, self.callback = master, value, callback self.master, self.value, self.callback = master, value, callback
self.cb_args, self.cb_kwargs = cb_args, cb_kwargs self.cb_args, self.cb_kwargs = cb_args, cb_kwargs
@ -410,7 +412,7 @@ class GridEditor(urwid.WidgetWrap):
for i in self.walker.lst: for i in self.walker.lst:
if not i[1] and any([x for x in i[0]]): if not i[1] and any([x for x in i[0]]):
res.append(i[0]) res.append(i[0])
self.callback(res, *self.cb_args, **self.cb_kwargs) self.callback(self.data_out(res), *self.cb_args, **self.cb_kwargs)
signals.pop_view_state.send(self) signals.pop_view_state.send(self)
elif key in ["h", "left"]: elif key in ["h", "left"]:
self.walker.left() self.walker.left()
@ -427,6 +429,19 @@ class GridEditor(urwid.WidgetWrap):
elif column.keypress(key, self) and not self.handle_key(key): elif column.keypress(key, self) and not self.handle_key(key):
return self._w.keypress(size, key) return self._w.keypress(size, key)
def data_out(self, data):
"""
Called on raw list data, before data is returned through the
callback.
"""
return data
def data_in(self, data):
"""
Called to prepare provided data.
"""
return data
def is_error(self, col, val): def is_error(self, col, val):
""" """
Return False, or a string error message. Return False, or a string error message.
@ -597,6 +612,12 @@ class PathEditor(GridEditor):
TextColumn("Component"), TextColumn("Component"),
] ]
def data_in(self, data):
return [[i] for i in data]
def data_out(self, data):
return [i[0] for i in data]
class ScriptEditor(GridEditor): class ScriptEditor(GridEditor):
title = "Editing scripts" title = "Editing scripts"
@ -623,6 +644,12 @@ class HostPatternEditor(GridEditor):
except re.error as e: except re.error as e:
return "Invalid regex: %s" % str(e) return "Invalid regex: %s" % str(e)
def data_in(self, data):
return [[i] for i in data]
def data_out(self, data):
return [i[0] for i in data]
class CookieEditor(GridEditor): class CookieEditor(GridEditor):
title = "Editing request Cookie header" title = "Editing request Cookie header"
@ -639,6 +666,15 @@ class CookieAttributeEditor(GridEditor):
TextColumn("Value"), TextColumn("Value"),
] ]
def data_out(self, data):
ret = []
for i in data:
if not i[1]:
ret.append([i[0], None])
else:
ret.append(i)
return ret
class SetCookieEditor(GridEditor): class SetCookieEditor(GridEditor):
title = "Editing response SetCookie header" title = "Editing response SetCookie header"
@ -647,3 +683,20 @@ class SetCookieEditor(GridEditor):
TextColumn("Value"), TextColumn("Value"),
SubgridColumn("Attributes", CookieAttributeEditor), SubgridColumn("Attributes", CookieAttributeEditor),
] ]
def data_in(self, data):
flattened = []
for k, v in data.items():
flattened.append([k, v[0], v[1].lst])
return flattened
def data_out(self, data):
vals = []
for i in data:
vals.append(
[
i[0],
[i[1], odict.ODictCaseless(i[2])]
]
)
return odict.ODict(vals)

View File

@ -197,13 +197,12 @@ class Options(urwid.WidgetWrap):
def ignorepatterns(self): def ignorepatterns(self):
def _set(ignore): def _set(ignore):
patterns = (x[0] for x in ignore) self.master.set_ignore_filter(ignore)
self.master.set_ignore_filter(patterns)
signals.update_settings.send(self) signals.update_settings.send(self)
self.master.view_grideditor( self.master.view_grideditor(
grideditor.HostPatternEditor( grideditor.HostPatternEditor(
self.master, self.master,
[[x] for x in self.master.get_ignore_filter()], self.master.get_ignore_filter(),
_set _set
) )
) )
@ -241,13 +240,12 @@ class Options(urwid.WidgetWrap):
def tcp_proxy(self): def tcp_proxy(self):
def _set(tcp): def _set(tcp):
patterns = (x[0] for x in tcp) self.master.set_tcp_filter(tcp)
self.master.set_tcp_filter(patterns)
signals.update_settings.send(self) signals.update_settings.send(self)
self.master.view_grideditor( self.master.view_grideditor(
grideditor.HostPatternEditor( grideditor.HostPatternEditor(
self.master, self.master,
[[x] for x in self.master.get_tcp_filter()], self.master.get_tcp_filter(),
_set _set
) )
) )