codekingpro/portable-devtools
114k
1from typing import Any2 3import urwid4 5from mitmproxy import exceptions6from mitmproxy.http import Headers7from mitmproxy.tools.console import layoutwidget8from mitmproxy.tools.console import signals9from mitmproxy.tools.console.grideditor import base10from mitmproxy.tools.console.grideditor import col_bytes11from mitmproxy.tools.console.grideditor import col_subgrid12from mitmproxy.tools.console.grideditor import col_text13from mitmproxy.tools.console.grideditor import col_viewany14 15 16class QueryEditor(base.FocusEditor):17 title = "Edit Query"18 columns = [col_text.Column("Key"), col_text.Column("Value")]19 20 def get_data(self, flow):21 return flow.request.query.items(multi=True)22 23 def set_data(self, vals, flow):24 flow.request.query = vals25 26 27class HeaderEditor(base.FocusEditor):28 columns = [col_bytes.Column("Key"), col_bytes.Column("Value")]29 30 31class RequestHeaderEditor(HeaderEditor):32 title = "Edit Request Headers"33 34 def get_data(self, flow):35 return flow.request.headers.fields36 37 def set_data(self, vals, flow):38 flow.request.headers = Headers(vals)39 40 41class ResponseHeaderEditor(HeaderEditor):42 title = "Edit Response Headers"43 44 def get_data(self, flow):45 return flow.response.headers.fields46 47 def set_data(self, vals, flow):48 flow.response.headers = Headers(vals)49 50 51class RequestMultipartEditor(base.FocusEditor):52 title = "Edit Multipart Form"53 columns = [col_bytes.Column("Key"), col_bytes.Column("Value")]54 55 def get_data(self, flow):56 return flow.request.multipart_form.items(multi=True)57 58 def set_data(self, vals, flow):59 flow.request.multipart_form = vals60 61 62class RequestUrlEncodedEditor(base.FocusEditor):63 title = "Edit UrlEncoded Form"64 columns = [col_text.Column("Key"), col_text.Column("Value")]65 66 def get_data(self, flow):67 return flow.request.urlencoded_form.items(multi=True)68 69 def set_data(self, vals, flow):70 flow.request.urlencoded_form = vals71 72 73class PathEditor(base.FocusEditor):74 # TODO: Next row on enter?75 title = "Edit Path Components"76 columns = [77 col_text.Column("Component"),78 ]79 80 def data_in(self, data):81 return [[i] for i in data]82 83 def data_out(self, data):84 return [i[0] for i in data]85 86 def get_data(self, flow):87 return self.data_in(flow.request.path_components)88 89 def set_data(self, vals, flow):90 flow.request.path_components = self.data_out(vals)91 92 93class CommentEditor(base.FocusEditor):94 title = "Edit Comment"95 columns = [col_text.Column("Value")]96 97 def get_data(self, flow):98 return [[flow.comment or ""]]99 100 def set_data(self, vals, flow):101 flow.comment = vals[0][0] if vals and vals[0] else ""102 103 104class CookieEditor(base.FocusEditor):105 title = "Edit Cookies"106 columns = [107 col_text.Column("Name"),108 col_text.Column("Value"),109 ]110 111 def get_data(self, flow):112 return flow.request.cookies.items(multi=True)113 114 def set_data(self, vals, flow):115 flow.request.cookies = vals116 117 118class CookieAttributeEditor(base.FocusEditor):119 title = "Editing Set-Cookie attributes"120 columns = [121 col_text.Column("Name"),122 col_text.Column("Value"),123 ]124 grideditor: base.BaseGridEditor125 126 def data_in(self, data):127 return [(k, v or "") for k, v in data]128 129 def data_out(self, data):130 ret = []131 for i in data:132 if not i[1]:133 ret.append([i[0], None])134 else:135 ret.append(i)136 return ret137 138 def layout_pushed(self, prev):139 if self.grideditor.master.view.focus.flow:140 self._w = base.BaseGridEditor(141 self.grideditor.master,142 self.title,143 self.columns,144 self.grideditor.walker.get_current_value(),145 self.grideditor.set_subeditor_value,146 self.grideditor.walker.focus,147 self.grideditor.walker.focus_col,148 )149 else:150 self._w = urwid.Pile([])151 152 153class SetCookieEditor(base.FocusEditor):154 title = "Edit SetCookie Header"155 columns = [156 col_text.Column("Name"),157 col_text.Column("Value"),158 col_subgrid.Column("Attributes", CookieAttributeEditor),159 ]160 161 def data_in(self, data):162 flattened = []163 for key, (value, attrs) in data:164 flattened.append([key, value, attrs.items(multi=True)])165 return flattened166 167 def data_out(self, data):168 vals = []169 for key, value, attrs in data:170 vals.append([key, (value, attrs)])171 return vals172 173 def get_data(self, flow):174 return self.data_in(flow.response.cookies.items(multi=True))175 176 def set_data(self, vals, flow):177 flow.response.cookies = self.data_out(vals)178 179 180class OptionsEditor(base.GridEditor, layoutwidget.LayoutWidget):181 title = ""182 columns = [col_text.Column("")]183 184 def __init__(self, master, name, vals):185 self.name = name186 super().__init__(master, [[i] for i in vals], self.callback)187 188 def callback(self, vals) -> None:189 try:190 setattr(self.master.options, self.name, [i[0] for i in vals])191 except exceptions.OptionsError as v:192 signals.status_message.send(message=str(v))193 194 def is_error(self, col, val):195 pass196 197 198class DataViewer(base.GridEditor, layoutwidget.LayoutWidget):199 title = ""200 201 def __init__(202 self,203 master,204 vals: (list[list[Any]] | list[Any] | Any),205 ) -> None:206 if vals is not None:207 # Whatever vals is, make it a list of rows containing lists of column values.208 if not isinstance(vals, list):209 vals = [vals]210 if not isinstance(vals[0], list):211 vals = [[i] for i in vals]212 213 self.columns = [col_viewany.Column("")] * len(vals[0])214 super().__init__(master, vals, self.callback)215 216 def callback(self, vals):217 pass218 219 def is_error(self, col, val):220 pass221 