Package Peach :: Package Gui :: Module PeachValidator
[hide private]

Source Code for Module Peach.Gui.PeachValidator

  1  ''' 
  2  PeachValidator GUI 
  3   
  4  @author: Michael Eddington 
  5  @version: $Id$ 
  6  ''' 
  7   
  8  # 
  9  # Copyright (c) 2008 Michael Eddington 
 10  # 
 11  # Permission is hereby granted, free of charge, to any person obtaining a copy  
 12  # of this software and associated documentation files (the "Software"), to deal 
 13  # in the Software without restriction, including without limitation the rights  
 14  # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell  
 15  # copies of the Software, and to permit persons to whom the Software is  
 16  # furnished to do so, subject to the following conditions: 
 17  # 
 18  # The above copyright notice and this permission notice shall be included in     
 19  # all copies or substantial portions of the Software. 
 20  # 
 21  # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR  
 22  # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,  
 23  # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE  
 24  # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER  
 25  # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
 26  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
 27  # SOFTWARE. 
 28  # 
 29   
 30  # Authors: 
 31  #   Michael Eddington (mike@phed.org) 
 32   
 33  # $Id$ 
 34   
 35  import sys, os 
 36  sys.path.append("../..") 
 37  sys.path.append(os.getcwd() + "\\..\\..\\") 
 38   
 39  try: 
 40          import Ft.Xml.Domlette 
 41          from Ft.Xml.Domlette import * 
 42          from Ft.Xml.Catalog import GetDefaultCatalog 
 43          from Ft.Xml.InputSource import InputSourceFactory 
 44          from Ft.Lib.Resolvers import SchemeRegistryResolver 
 45          from Ft.Lib import Uri 
 46   
 47  except: 
 48          print "\nError loading 4Suite XML library.  This library" 
 49          print "can be installed from the dependencies folder or" 
 50          print "downloaded from http://4suite.org/.\n\n" 
 51          raise 
 52   
 53  import gui 
 54  import wx 
 55  import wx.propgrid as wxpg 
 56  import re, pickle 
 57   
 58  from Peach.Engine import parser, engine, incoming, dom 
 59  from Peach.Engine.dom import * 
 60  import Peach 
 61  #import Peach.Gui 
 62   
63 -class PeachValidatorGui(gui.PeachValidation):
64
65 - def __init__(self):
66 self.title = "Peach Validation - %s" 67 gui.PeachValidation.__init__(self, None, -1, "") 68 69 self._lastXmlFile = "" 70 self._lastBinFile = "" 71 self._lastPath = "/" 72 73 self.LoadState() 74 75 # Set values 76 self.textFilename.SetValue(self._lastBinFile) 77 self.textPeachXmlFilename.SetValue(self._lastXmlFile) 78 79 self.mutateObj = None 80 81 wx.EVT_CLOSE(self, self.OnClose) 82 83 # Disable controls that shouldn't be used yet 84 85 self.buttonGenerate.Disable() 86 self.comboMutator.Disable() 87 self.textFilename.Disable() 88 self.buttonBrowse.Disable() 89 self.buttonLoad.Disable() 90 91 # Create Tree image list 92 self.treeImages = wx.ImageList(16,16) 93 self.treeImages.NodeTemplate= self.treeImages.Add(wx.Bitmap("icons\\node-template.png", wx.BITMAP_TYPE_ANY)) 94 self.treeImages.NodeBlock = self.treeImages.Add(wx.Bitmap("icons\\node-block.png", wx.BITMAP_TYPE_ANY)) 95 self.treeImages.NodeChoice = self.treeImages.Add(wx.Bitmap("icons\\node-choice.png", wx.BITMAP_TYPE_ANY)) 96 self.treeImages.NodeFlags = self.treeImages.Add(wx.Bitmap("icons\\node-flags.png", wx.BITMAP_TYPE_ANY)) 97 self.treeImages.NodeNumber = self.treeImages.Add(wx.Bitmap("icons\\node-number.png", wx.BITMAP_TYPE_ANY)) 98 self.treeImages.NodeString = self.treeImages.Add(wx.Bitmap("icons\\node-string.png", wx.BITMAP_TYPE_ANY)) 99 self.treeImages.NodeUnknown = self.treeImages.Add(wx.Bitmap("icons\\node-unknown.png", wx.BITMAP_TYPE_ANY)) 100 self.treeImages.NodeBlob = self.treeImages.Add(wx.Bitmap("icons\\node-blob.png", wx.BITMAP_TYPE_ANY)) 101 self.treeImages.NodeError = self.treeImages.Add(wx.Bitmap("icons\\node-error.png", wx.BITMAP_TYPE_ANY)) 102 103 self.ImageLookup = {'block':self.treeImages.NodeBlock, 104 'choice':self.treeImages.NodeChoice, 105 'flags':self.treeImages.NodeFlags, 106 'flag':self.treeImages.NodeFlags, 107 'number':self.treeImages.NodeNumber, 108 'string':self.treeImages.NodeString, 109 'blob':self.treeImages.NodeBlob, 110 'template':self.treeImages.NodeTemplate, 111 } 112 113 self.root = self.treeDataTree.AddRoot("Peach") 114 self.treeDataTree.SetImageList(self.treeImages) 115 self.treeDataTree.SetItemImage(self.root, self.treeImages.NodeTemplate) 116 117 # Adjust size of tree 118 self.SetSize(wx.Size(600, 600)) 119 width, height = self.GetSizeTuple() 120 self.splitterTopBottom.SetSashPosition(height * 0.25, True) 121 self.splitterRightLeft.SetSashPosition(width * 0.35, True) 122 123 self.treeDataTree.SelectItem(self.root, True) 124 self.treeDataTree.Expand(self.root)
125
126 - def OnClose(self, event):
127 self.SaveState() 128 event.Skip()
129
130 - def SaveState(self):
131 ''' 132 Save out our state 133 ''' 134 135 state = [self._lastXmlFile, self._lastBinFile, self._lastPath] 136 137 fd = open(os.path.join(Peach.Gui.__path__[0], "peachvalidator.state"), "wb+") 138 fd.write(pickle.dumps(state)) 139 fd.close()
140
141 - def LoadState(self):
142 ''' 143 Load our state if it exists 144 ''' 145 146 try: 147 fd = open(os.path.join(Peach.Gui.__path__[0], "peachvalidator.state"), "rb") 148 state = pickle.loads(fd.read()) 149 fd.close() 150 151 self._lastXmlFile = state[0] 152 self._lastBinFile = state[1] 153 self._lastPath = state[2] 154 except: 155 pass
156 157
158 - def OnButtonBrowse(self, event):
159 #print "Event handler `OnButtonBrowse' not implemented!" 160 event.Skip() 161 162 dlg = wx.FileDialog(self, 'Choose a file to open', self._lastPath, self._lastBinFile, '*.*', wx.OPEN) 163 if dlg.ShowModal() != wx.ID_OK: 164 dlg.Destroy() 165 return 166 167 fileName = dlg.GetPath() 168 self._lastBinFile = fileName 169 self._lastPath = fileName[:fileName.rfind(os.path.pathsep)] 170 dlg.Destroy() 171 self.textFilename.SetValue(fileName)
172
173 - def OnButtonPeachXmlLoad(self, event): # wxGlade: PeachValidation.<event_handler>
174 event.Skip() 175 176 self.treeDataTree.DeleteChildren(self.root) 177 self.treeDataTree.SetItemImage(self.root, self.treeImages.NodeTemplate) 178 179 self.p = parser.ParseTemplate() 180 self.peach = self.p.parse("file:"+ self.textPeachXmlFilename.GetValue()) 181 182 # Locate all templates and toss into combo 183 self.comboDataModel.Clear() 184 self.mutators = {} 185 for n in self.peach: 186 if n.elementType == 'template': 187 self.comboDataModel.Append(n.name) 188 self.comboDataModel.SetValue(n.name) 189 190 elif n.elementType == 'test': 191 for m in n.mutators: 192 if m.name not in self.mutators.keys(): 193 self.mutators[m.name] = m 194 195 # Populate Mutator drop-down 196 197 self.comboMutator.Clear() 198 for m in self.mutators.keys(): 199 self.comboMutator.Append(m) 200 self.comboMutator.SetValue(m) 201 202 # Enable controls that shouldn't be used yet 203 204 self.buttonGenerate.Disable() 205 self.comboMutator.Disable() 206 self.textFilename.Enable() 207 self.buttonBrowse.Enable() 208 self.buttonLoad.Enable()
209
210 - def OnComboDataModel(self, event): # wxGlade: PeachValidation.<event_handler>
211 #print "Event handler `OnComboDataModel' not implemented!" 212 event.Skip() 213
214 - def OnButtonLoad(self, event):
215 event.Skip() 216 217 self.treeDataTree.DeleteChildren(self.root) 218 self.treeDataTree.SetItemImage(self.root, self.treeImages.NodeTemplate) 219 220 fd = open(self.textFilename.GetValue(), "rb") 221 data = fd.read() 222 fd.close() 223 224 # Locate a template to use 225 self.template = None 226 for n in self.peach: 227 if n.elementType == 'template' and n.name == self.comboDataModel.GetValue(): 228 self.template = n 229 break 230 231 if self.template == None: 232 raise Exception("Couldn't locate template, suck!") 233 234 try: 235 cracker = incoming.DataCracker(self.peach) 236 cracker.haveAllData = True 237 self.template = self.template.copy(None) 238 (rating, pos) = cracker.crackData(self.template, data) 239 if pos < len(data)-1: 240 # not everything was parsed! 241 self.treeDataTree.SetItemImage(self.root, self.treeImages.NodeError) 242 243 # TODO: Display error dialog 244 except: 245 self.treeDataTree.SetItemImage(self.root, self.treeImages.NodeError) 246 247 # Build tree 248 self.BuildTree(self.template) 249 250 self.buttonGenerate.Enable() 251 self.comboMutator.Enable()
252
253 - def BuildTree(self, template):
254 self.treeDataTree.Freeze() 255 256 self.treeDataTree.SetPyData(self.root, template) 257 for child in template: 258 self.AddNodeToTree(self.root, child) 259 260 self.treeDataTree.Thaw() 261 self.treeDataTree.Expand(self.root) 262 self.treeDataTree.SelectItem(self.root, True)
263
264 - def OnTreeSelChanged(self, event):
265 event.Skip() 266 267 # Look at our junk and output some cool stuff 268 # to the text box. 269 itemId = event.GetItem() 270 node = self.treeDataTree.GetPyData(itemId) 271 272 if node == None: 273 return 274 275 value = "%s is a %s element type\n" % (node.name, node.elementType) 276 value += "="*(len(value)-1) 277 value += "\n\n" 278 279 if hasattr(node, 'pos') and hasattr(node, 'rating') and node.pos != None: 280 value += "DataElement.pos = %d\n" % node.pos 281 value += "DataElement.rating = %d\n" % node.rating 282 283 else: 284 value += "Warning: We did not reach, or crack this element!!\n\n" 285 286 if node.elementType == 'string': 287 if node.length != None: 288 value += "String.length: %d\n" % node.length 289 else: 290 value += "String.length: Unknown\n" 291 292 value += "String.nullTerminated: %s\n" % str(node.nullTerminated) 293 value += "String.type: %s\n" % node.type 294 value += "String.padCharacter: %s\n" % repr(node.padCharacter) 295 296 if node.defaultValue != None: 297 value += "String.defaultValue: %s\n" % repr(node.defaultValue) 298 else: 299 value += "String.defaultValue: None\n" 300 value += "\n" 301 302 elif node.elementType == 'number': 303 value += "Number.size: %d\n" % node.size 304 value += "Number.endian: %s\n" % node.endian 305 value += "Number.signed: %s\n" % str(node.signed) 306 307 if node.defaultValue != None: 308 value += "Number.defaultValue: %d\n" % int(node.defaultValue) 309 else: 310 value += "Number.defaultValue: None\n" 311 value += "\n" 312 313 elif node.elementType == 'flags': 314 value += "Flags.size: %d\n" % node.length 315 value += "Flags.endian: %s\n" % node.endian 316 value += "\n" 317 318 elif node.elementType == 'flag': 319 value += "Flag.size: %d\n" % node.length 320 value += "Flag.position: %d\n" % node.position 321 322 if node.defaultValue != None: 323 value += "Flag.defaultValue: %d\n" % int(node.defaultValue) 324 else: 325 value += "Flag.defaultValue: None\n" 326 value += "\n" 327 328 elif node.elementType == 'block': 329 pass 330 331 elif node.elementType == 'blob': 332 if node.length != None: 333 value += "Blob.length: %d\n" % node.length 334 else: 335 value += "Blob.length: Unknown\n" 336 337 if node.defaultValue != None: 338 value += "Blob.defaultValue: %s\n" % repr(node.defaultValue) 339 else: 340 value += "Blob.defaultValue: None\n" 341 value += "\n" 342 343 nodeInternal = None 344 nodeValue = None 345 346 try: 347 if node.currentValue != None: 348 nodeInternal = node.currentValue 349 nodeValue = node.getValue() 350 else: 351 nodeInternal = None 352 nodeValue = node.getValue() 353 354 except: 355 pass 356 357 if nodeInternal != None: 358 value += "Internal value: (%d bytes)\n%s\n\n\n" % (len(nodeInternal), repr(nodeInternal)) 359 else: 360 value += "Internal value: None\n\n" 361 362 if nodeValue != None: 363 value += "Output value: (%d bytes)\n%s\n\n\n" % (len(nodeValue), repr(nodeValue)) 364 365 length = len(nodeValue) 366 if length >= 100: 367 length = 50 368 spaces = '3' 369 elif length >= 10: 370 spaces = '2' 371 else: 372 spaces = '' 373 374 for i in range(length): 375 value += ("[%" + spaces + "d]: %s: %s\n") % (i, hex(ord(nodeValue[i])), repr(nodeValue[i])) 376 377 if length < len(nodeValue): 378 value += ".\n.\n.\n" 379 380 for i in range(len(nodeValue)-10, len(nodeValue)): 381 value += ("[%" + spaces + "d]: %s: %s\n") % (i, hex(ord(nodeValue[i])), repr(nodeValue[i])) 382 else: 383 value += "Output value: None\n\n" 384 385 self.textOutput.SetValue(value)
386
387 - def AddNodeToTree(self, parentId, node):
388 ''' 389 Add a node to the tree. Adds the children of this node as well! 390 391 NOTE: This only builds the tree and links the tree item to the 392 node object. 393 ''' 394 395 if not isinstance(node, DataElement): 396 return 397 398 id = self.treeDataTree.AppendItem(parentId, node.name) 399 self.treeDataTree.SetPyData(id, node) 400 401 try: 402 self.treeDataTree.SetItemImage(id, self.ImageLookup[node.elementType]) 403 404 except: 405 raise Exception("Unknown element type: ", node.elementType) 406 407 try: 408 value = node.getValue() 409 410 except: 411 self.treeDataTree.SetItemImage(id, self.treeImages.NodeError) 412 413 if not hasattr(node, 'pos') or not hasattr(node, 'rating'): 414 self.treeDataTree.SetItemImage(id, self.treeImages.NodeError) 415 416 for child in node._children: 417 self.AddNodeToTree(id, child) 418 419 return id
420
421 - def OnButtonPeachFileBrowse(self, event): # wxGlade: PeachValidation.<event_handler>
422 #print "Event handler `OnButtonPeachFileBrowse' not implemented!" 423 event.Skip() 424 425 dlg = wx.FileDialog(self, 'Choose a Peach XML file to open', self._lastPath, self._lastXmlFile, '*.xml', wx.OPEN) 426 if dlg.ShowModal() != wx.ID_OK: 427 dlg.Destroy() 428 return 429 430 fileName = dlg.GetPath() 431 self._lastXmlFile = fileName 432 self._lastPath = fileName[:fileName.rfind(os.path.pathsep)] 433 434 dlg.Destroy() 435 self.textPeachXmlFilename.SetValue(fileName) 436
437 - def OnButtonGenerate(self, event): # wxGlade: PeachValidation.<event_handler>
438 #print "Event handler `OnButtonGenerate' not implemented!" 439 event.Skip() 440 441 if self.mutateObj == None: 442 self.mutateObj = dom.Action('Mutation', None) 443 self.mutateObj.origionalTemplate = self.template 444 445 # Mutate 446 447 self.mutateObj.template = self.mutateObj.origionalTemplate.copy(self.mutateObj) 448 self.mutators[self.comboMutator.GetValue()].mutator.getActionValue(self.mutateObj) 449 try: 450 self.mutators[self.comboMutator.GetValue()].mutator.next() 451 452 # Build tree 453 self.treeDataTree.DeleteChildren(self.root) 454 self.treeDataTree.SetItemImage(self.root, self.treeImages.NodeTemplate) 455 self.BuildTree(self.mutateObj.template) 456 except: 457 wx.MessageBox('Mutator Completed', 'Info') 458
459 -def RunPeachValidator():
460 app = wx.PySimpleApp(0) 461 wx.InitAllImageHandlers() 462 peachMain = PeachValidatorGui() 463 app.SetTopWindow(peachMain) 464 peachMain.Show() 465 app.MainLoop()
466 467 if __name__ == "__main__": 468 RunPeachValidator() 469 470 # end 471