1import wx 2import wx.py 3import wx.grid 4import wx.aui 5import wx.html 6 7import wx.lib.agw.aui as aui 8import wx.dataview as dv 9import wx.html2 as webview 10 11if "2.8" in wx.version(): 12 import wx.lib.pubsub.setupkwargs 13 from wx.lib.pubsub import pub 14else: 15 from wx.lib.pubsub import pub 16 17try: 18 from agw import pycollapsiblepane as PCP 19except ImportError: # if it's not there locally, try the wxPython lib. 20 import wx.lib.agw.pycollapsiblepane as PCP 21 22# puedo no hacer paneles y devolverlos directamente como hace el treectrl, no se cual es la ventaja really 23 24# ---------------------------------------------------------------------- 25# http://stackoverflow.com/questions/22265868/how-to-create-a-cmd-with-wxpython 26# esto puede hacer q meta cmd.cmd directamente https://www.blog.pythonlibrary.org/2009/01/01/wxpython-redirecting-stdout-stderr/ 27 28 29class RedirectText(object): 30 def __init__(self, aWxTextCtrl): 31 self.out = aWxTextCtrl 32 33 def write(self, string): 34 self.out.WriteText(string) 35 36 37class ConsolePanel(wx.Panel): 38 def __init__(self, parent, interpreter): 39 # begin wxGlade: MyFrame.__init__ 40 wx.Panel.__init__(self, parent, -1) 41 42 self.history = [] 43 self.index = 0 44 45 self.prompt = ">>" 46 self.textctrl = wx.TextCtrl( 47 self, 48 -1, 49 "", 50 style=wx.TE_PROCESS_ENTER | wx.TE_MULTILINE | wx.TE_RICH, 51 size=(-1, 250), 52 ) 53 self.textctrl.SetForegroundColour(wx.WHITE) 54 self.textctrl.SetBackgroundColour(wx.BLACK) 55 56 self.textctrl.AppendText(self.prompt) 57 58 self.textctrl.Bind(wx.EVT_CHAR, self.__bind_events) 59 60 sizer = wx.BoxSizer() 61 sizer.Add(self.textctrl, 1, wx.EXPAND) 62 self.SetSizer(sizer) 63 64 self._interp = interpreter 65 redir = RedirectText(self.textctrl) 66 67 import sys 68 69 # Create a replacement for stdin. 70 # self.reader = PseudoFileIn(self.readline, self.readlines) 71 # self.reader.input = '' 72 # self.reader.isreading = False 73 74 # sys.stdin=self.reader 75 sys.stdout = redir 76 sys.stderr = redir 77 78 def __bind_events(self, e): 79 if e.GetKeyCode() == 13: 80 self.index = len(self.history) - 1 81 82 self.value = self.textctrl.GetValue() 83 ln = self.get_last_line() 84 85 ln = ln.strip() 86 if ln not in self.history: 87 self.history.append(ln) 88 self.index += 1 89 if ln: 90 import shlex 91 92 cmd = shlex.split(ln) 93 # out en retvalue 94 retvalue = self._interp.onecmd(cmd) 95 if retvalue: 96 self.textctrl.WriteText("\n") 97 self.textctrl.AppendText(retvalue) 98 99 self.textctrl.WriteText("\n") 100 self.textctrl.WriteText(self.prompt) 101 # down 102 elif e.GetKeyCode() == 317: 103 self.index += 1 104 105 if self.index >= len(self.history): 106 self.index = len(self.history) - 1 107 108 self.textctrl.WriteText("\n") 109 self.textctrl.WriteText(self.prompt) 110 self.textctrl.WriteText(self.history[self.index]) 111 112 # up 113 elif e.GetKeyCode() == 315: 114 self.index -= 1 115 116 if self.index < 0: 117 self.index = 0 118 119 self.textctrl.WriteText("\n") 120 self.textctrl.WriteText(self.prompt) 121 self.textctrl.WriteText(self.history[self.index]) 122 else: 123 e.Skip() 124 125 def get_last_line(self): 126 nl = self.textctrl.GetNumberOfLines() 127 ln = self.textctrl.GetLineText(nl - 1) 128 ln = ln[len(self.prompt) :] 129 130 return ln 131 132 133# ---------------------------------------------------------------------- 134 135 136class ListPanel(wx.Panel): 137 def __init__(self, parent, log, model, interpreter): 138 self.log = log 139 self._interp = interpreter 140 wx.Panel.__init__(self, parent, -1) 141 142 self.dvc = dv.DataViewCtrl( 143 self, style=wx.BORDER_THEME | dv.DV_ROW_LINES | dv.DV_VERT_RULES 144 ) 145 146 self.model = model 147 self.dvc.AssociateModel(self.model) 148 149 for row in list(self.model.row_mapper.values()): 150 self.dvc.AppendTextColumn(row.title, row.colid, width=row.width) 151 152 for c in self.dvc.Columns: 153 c.Sortable = True 154 c.Reorderable = True 155 156 self.cp = cp = PCP.PyCollapsiblePane( 157 self, label="Show console", agwStyle=wx.CP_GTK_EXPANDER 158 ) 159 self.MakePaneContent(cp.GetPane()) 160 161 self.Sizer = wx.BoxSizer(wx.VERTICAL) 162 self.Sizer.Add(self.dvc, 1, wx.EXPAND) 163 self.Sizer.Add(cp, 0, wx.RIGHT | wx.LEFT | wx.EXPAND) 164 self.SetSizer(self.Sizer) 165 self.SetAutoLayout(True) 166 167 self.dvc.Bind(dv.EVT_DATAVIEW_SELECTION_CHANGED, self.OnItemSelected) 168 169 def OnItemSelected(self, event): 170 try: 171 items = self.dvc.GetSelections() 172 item = self.model.GetRow(items[0]) 173 except IndexError: 174 pass 175 else: 176 pub.sendMessage("selected_row", row=self.model.data[item]) 177 178 event.Skip() 179 180 def MakePaneContent(self, pane): 181 border = wx.BoxSizer() 182 border.Add(ConsolePanel(pane, self._interp), wx.RIGHT | wx.LEFT | wx.EXPAND) 183 # border.Add(py.shell.Shell(pane, InterpClass=self._interp, size=(-1,250)), wx.RIGHT|wx.LEFT|wx.EXPAND) 184 185 pane.SetSizer(border) 186 187 188class HttpRawPanel(wx.Panel): 189 def __init__(self, parent, frame): 190 self._frame = frame 191 wx.Panel.__init__(self, parent, -1) 192 193 # self.req_txt = wx.TextCtrl(self, -1, "", style=wx.TE_MULTILINE|wx.TE_READONLY) 194 self.req_txt = webview.WebView.New(self) 195 # self.resp_txt = webview.WebView.New(self) 196 self.resp_txt = wx.TextCtrl( 197 self, -1, "", style=wx.TE_MULTILINE | wx.TE_READONLY 198 ) 199 200 sizer = wx.BoxSizer(wx.HORIZONTAL) 201 202 sizer.Add(self.req_txt, 1, wx.EXPAND) 203 sizer.Add(self.resp_txt, 1, wx.EXPAND) 204 205 self.SetSizer(sizer) 206 self.SetAutoLayout(True) 207 208 def CreateHTMLCtrl(self): 209 ctrl = wx.html.HtmlWindow(self, -1, wx.DefaultPosition, wx.Size(400, 300)) 210 if "gtk2" in wx.PlatformInfo or "gtk3" in wx.PlatformInfo: 211 ctrl.SetStandardFonts() 212 213 ctrl.SetPage("") 214 215 return ctrl 216 217 218class MainNotebookPanel(wx.Panel): 219 def __init__(self, parent, frame, interpreter): 220 self._frame = frame 221 wx.Panel.__init__(self, parent, -1) 222 223 bookStyle = aui.AUI_NB_DEFAULT_STYLE 224 bookStyle &= ~(aui.AUI_NB_CLOSE_ON_ACTIVE_TAB) 225 226 self.rawpanel = HttpRawPanel(self, self) 227 self.renderpanel = self.create_web_view() 228 229 self.nb = aui.AuiNotebook(self, style=bookStyle) 230 self.nb.AddPage(self.rawpanel, "HTML Raw") 231 self.nb.AddPage(self.renderpanel, "HTML Render") 232 233 sizer = wx.BoxSizer() 234 sizer.Add(self.nb, 1, wx.EXPAND) 235 self.SetSizer(sizer) 236 wx.CallAfter(self.nb.SendSizeEvent) 237 238 pub.subscribe(self.on_selected_row, "selected_row") 239 240 def create_web_view(self): 241 return webview.WebView.New(self) 242 243 def on_selected_row(self, row): 244 from pygments import highlight 245 from pygments.lexers import get_lexer_by_name 246 from pygments.formatters import HtmlFormatter 247 248 result = highlight( 249 str(row.history), get_lexer_by_name("http"), HtmlFormatter(full=True) 250 ) 251 # result2 = highlight(str(row.history.raw_content), get_lexer_by_name("http"), HtmlFormatter(full=True)) 252 253 self.renderpanel.SetPage(row.history.content, row.url) 254 # self.rawpanel.req_txt.SetValue(str(row.history)) 255 self.rawpanel.req_txt.SetPage(result, "") 256 # self.rawpanel.resp_txt.SetPage(result2, "") 257 self.rawpanel.resp_txt.SetValue(str(row.history.raw_content)) 258 259 260# ---------------------------------------------------------------------- 261 262 263ID_About = wx.NewId() 264 265 266class WfuzzFrame(wx.Frame): 267 def __init__( 268 self, 269 parent, 270 id=-1, 271 title="Wfuzz", 272 pos=wx.DefaultPosition, 273 size=wx.DefaultSize, 274 style=wx.DEFAULT_FRAME_STYLE | wx.SUNKEN_BORDER | wx.CLIP_CHILDREN, 275 ): 276 wx.Frame.__init__(self, parent, id, title, pos, size, style) 277 278 def start_gui(self, controller): 279 self.controller = controller 280 # tell FrameManager to manage this frame 281 self._mgr = wx.aui.AuiManager() 282 self._mgr.SetManagedWindow(self) 283 284 # create menu 285 mb = wx.MenuBar() 286 287 file_menu = wx.Menu() 288 file_menu.Append(wx.ID_EXIT, "Exit") 289 290 help_menu = wx.Menu() 291 help_menu.Append(ID_About, "About...") 292 293 mb.Append(file_menu, "File") 294 mb.Append(help_menu, "Help") 295 296 self.SetMenuBar(mb) 297 298 self.SetMinSize(wx.Size(400, 300)) 299 300 # create some center panes 301 self._mgr.AddPane( 302 MainNotebookPanel(self, self, controller._interp), 303 wx.aui.AuiPaneInfo() 304 .Caption("Raw HTTP Content") 305 .Name("analysis_notebook") 306 .CenterPane(), 307 ) 308 self._mgr.AddPane( 309 self.CreateNotebook(), 310 wx.aui.AuiPaneInfo().Name("main_notebook").CenterPane(), 311 ) 312 self._mgr.Update() 313 314 self.Bind(wx.EVT_CLOSE, self.OnClose) 315 self.Bind(wx.EVT_MENU, self.OnExit, id=wx.ID_EXIT) 316 self.Bind(wx.EVT_MENU, self.OnAbout, id=ID_About) 317 318 pub.subscribe(self.OnAddTab, "create_tab") 319 320 def OnClose(self, event): 321 pub.sendMessage("exit", msg="exiting...") 322 self._mgr.UnInit() 323 del self._mgr 324 self.Destroy() 325 326 def OnExit(self, event): 327 pub.sendMessage("exit", msg="exiting...") 328 self.Close() 329 330 def OnAbout(self, event): 331 msg = "WFuzz GUI\n(c) Copyright 2017, Xavi Mendez" 332 dlg = wx.MessageDialog(self, msg, "About", wx.OK | wx.ICON_INFORMATION) 333 dlg.ShowModal() 334 dlg.Destroy() 335 336 def CreateNotebook(self): 337 bookStyle = aui.AUI_NB_DEFAULT_STYLE 338 # bookStyle &= ~(aui.AUI_NB_CLOSE_ON_ACTIVE_TAB) 339 340 bookStyle = ( 341 aui.AUI_NB_DEFAULT_STYLE | aui.AUI_NB_TAB_EXTERNAL_MOVE | wx.NO_BORDER 342 ) 343 344 client_size = self.GetClientSize() 345 nb = aui.AuiNotebook( 346 self, 347 -1, 348 wx.Point(client_size.x, client_size.y), 349 wx.Size(430, 200), 350 agwStyle=bookStyle, 351 ) 352 353 nb.AddPage( 354 ListPanel(self, self, self.controller._model, self.controller._interp), 355 "Main", 356 ) 357 358 return nb 359 360 def OnAddTab(self, name, model, interp): 361 auibook = self._mgr.GetPane("main_notebook").window 362 363 auibook.AddPage(ListPanel(self, self, model, interp), name, True) 364 365 self._mgr.Update() 366