From e963a9da4887268b03ceecf55086674121047056 Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Fri, 17 Apr 2015 12:54:29 +1200 Subject: [PATCH] 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. --- libmproxy/console/flowview.py | 21 +++-------- libmproxy/console/grideditor.py | 63 ++++++++++++++++++++++++++++++--- libmproxy/console/options.py | 10 +++--- 3 files changed, 66 insertions(+), 28 deletions(-) diff --git a/libmproxy/console/flowview.py b/libmproxy/console/flowview.py index 497248de9..632b725ef 100644 --- a/libmproxy/console/flowview.py +++ b/libmproxy/console/flowview.py @@ -290,7 +290,7 @@ class FlowView(tabs.Tabs): signals.flow_change.send(self, flow = self.flow) 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) def set_form(self, lst, conn): @@ -316,17 +316,8 @@ class FlowView(tabs.Tabs): conn.set_cookies(od) signals.flow_change.send(self, flow = self.flow) - def set_setcookies(self, lst, conn): - vals = [] - for i in lst: - vals.append( - [ - i[0], - [i[1], odict.ODictCaseless(i[2])] - ] - ) - od = odict.ODict(vals) - conn.set_cookies(od) + def set_setcookies(self, data, conn): + conn.set_cookies(data) signals.flow_change.send(self, flow = self.flow) def edit(self, part): @@ -352,13 +343,10 @@ class FlowView(tabs.Tabs): ) ) 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( grideditor.SetCookieEditor( self.master, - flattened, + message.get_cookies(), self.set_setcookies, message ) @@ -397,7 +385,6 @@ class FlowView(tabs.Tabs): ) elif part == "p": p = message.get_path_components() - p = [[i] for i in p] self.master.view_grideditor( grideditor.PathEditor( self.master, diff --git a/libmproxy/console/grideditor.py b/libmproxy/console/grideditor.py index e406fbaf5..e5e644037 100644 --- a/libmproxy/console/grideditor.py +++ b/libmproxy/console/grideditor.py @@ -7,7 +7,7 @@ import urwid from . import common, signals from .. import utils, filt, script -from netlib import http_uastrings, http_cookies +from netlib import http_uastrings, http_cookies, odict FOOTER = [ @@ -231,8 +231,10 @@ class GridWalker(urwid.ListWalker): def _insert(self, pos): self.focus = pos self.lst.insert( - self.focus, [ - [c.blank() for c in self.editor.columns], set([])] + self.focus, + [ + [c.blank() for c in self.editor.columns], set([]) + ] ) self.focus_col = 0 self.start_edit() @@ -318,7 +320,7 @@ class GridEditor(urwid.WidgetWrap): columns = None 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.cb_args, self.cb_kwargs = cb_args, cb_kwargs @@ -410,7 +412,7 @@ class GridEditor(urwid.WidgetWrap): for i in self.walker.lst: if not i[1] and any([x for x in 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) elif key in ["h", "left"]: self.walker.left() @@ -427,6 +429,19 @@ class GridEditor(urwid.WidgetWrap): elif column.keypress(key, self) and not self.handle_key(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): """ Return False, or a string error message. @@ -597,6 +612,12 @@ class PathEditor(GridEditor): 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): title = "Editing scripts" @@ -623,6 +644,12 @@ class HostPatternEditor(GridEditor): except re.error as 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): title = "Editing request Cookie header" @@ -639,6 +666,15 @@ class CookieAttributeEditor(GridEditor): 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): title = "Editing response SetCookie header" @@ -647,3 +683,20 @@ class SetCookieEditor(GridEditor): TextColumn("Value"), 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) diff --git a/libmproxy/console/options.py b/libmproxy/console/options.py index dc7e00d51..c728123f7 100644 --- a/libmproxy/console/options.py +++ b/libmproxy/console/options.py @@ -197,13 +197,12 @@ class Options(urwid.WidgetWrap): def ignorepatterns(self): def _set(ignore): - patterns = (x[0] for x in ignore) - self.master.set_ignore_filter(patterns) + self.master.set_ignore_filter(ignore) signals.update_settings.send(self) self.master.view_grideditor( grideditor.HostPatternEditor( self.master, - [[x] for x in self.master.get_ignore_filter()], + self.master.get_ignore_filter(), _set ) ) @@ -241,13 +240,12 @@ class Options(urwid.WidgetWrap): def tcp_proxy(self): def _set(tcp): - patterns = (x[0] for x in tcp) - self.master.set_tcp_filter(patterns) + self.master.set_tcp_filter(tcp) signals.update_settings.send(self) self.master.view_grideditor( grideditor.HostPatternEditor( self.master, - [[x] for x in self.master.get_tcp_filter()], + self.master.get_tcp_filter(), _set ) )