#!/usr/bin/python #--------------------------------------------------------------------------- """ Import externals """ import wx import wx.lib.newevent import os import sys import re import threading import StringIO #--------------------------------------------------------------------------- """ Import scyther components """ import XMLReader """ Import scyther-gui components """ import Tempfile import Claim import Preference import Scyther #--------------------------------------------------------------------------- """ Global declaration """ (UpdateAttackEvent, EVT_UPDATE_ATTACK) = wx.lib.newevent.NewEvent() busy = threading.Semaphore() #--------------------------------------------------------------------------- class ScytherThread(threading.Thread): # Override Thread's __init__ method to accept the parameters needed: def __init__ ( self, mainwin, spdl, details, verifywin ): self.mainwin = mainwin self.verifywin = verifywin self.spdl = spdl self.details = details self.claims = [] threading.Thread.__init__ ( self ) def run(self): evt = UpdateAttackEvent(status="Running Scyther...") wx.PostEvent(self.mainwin, evt) self.claimResults() # Results are done (claimstatus can be reported) evt = UpdateAttackEvent(status="Done.") wx.PostEvent(self.mainwin, evt) # Shoot down the verification window and let the RunScyther function handle the rest self.mainwin.verified = True self.verifywin.Destroy() def claimResults(self): """ Convert spdl to result (using Scyther) The list of claim goes back to self.mainwin.claims, which is a property of the main window """ scyther = Scyther.Scyther() scyther.options = self.mainwin.settings.ScytherArguments() if sys.platform.startswith('win'): scyther.program = "c:\\Scyther.exe" if not os.path.isfile(scyther.program): print "I can't find the Scyther executable %s" % (scyther.program) scyther.setInput(self.spdl) self.mainwin.claims = scyther.verify() self.summary = str(scyther) class AttackThread(threading.Thread): # Override Thread's __init__ method to accept the parameters needed: def __init__ ( self, mainwin, resultwin ): self.mainwin = mainwin self.resultwin = resultwin threading.Thread.__init__ ( self ) def run(self): evt = UpdateAttackEvent(status="Generating attack graphs...") wx.PostEvent(self.mainwin, evt) # create the images in the background self.makeImages() def makeImages(self): """ create images """ for cl in self.mainwin.claims: for attack in cl.attacks: self.makeImage(attack) def makeImage(self,attack): """ create image for this particular attack """ (fd2,fpname2) = Tempfile.tempcleaned(".png") pw,pr = os.popen2("dot -Tpng -o%s" % (fpname2)) pw.write(attack.scytherDot) pw.close() attack.pngfile = fpname2 # this is where the file name is stored class VerificationWindow(wx.Dialog): def __init__( self, parent, ID, title, size=wx.DefaultSize, pos=wx.DefaultPosition, style=wx.DEFAULT_DIALOG_STYLE ): # Instead of calling wx.Dialog.__init__ we precreate the dialog # so we can set an extra style that must be set before # creation, and then we create the GUI dialog using the Create # method. pre = wx.PreDialog() pre.SetExtraStyle(wx.DIALOG_EX_CONTEXTHELP) pre.Create(parent, ID, title, pos, size, style) # This next step is the most important, it turns this Python # object into the real wrapper of the dialog (instead of pre) # as far as the wxPython extension is concerned. self.PostCreate(pre) # Now continue with the normal construction of the dialog # contents sizer = wx.BoxSizer(wx.VERTICAL) label = wx.StaticText(self, -1, "This is a wx.Dialog") label.SetHelpText("This is the help text for the label") sizer.Add(label, 0, wx.ALIGN_CENTRE|wx.ALL, 5) box = wx.BoxSizer(wx.HORIZONTAL) label = wx.StaticText(self, -1, "Field #1:") label.SetHelpText("This is the help text for the label") box.Add(label, 0, wx.ALIGN_CENTRE|wx.ALL, 5) text = wx.TextCtrl(self, -1, "", size=(80,-1)) text.SetHelpText("Here's some help text for field #1") box.Add(text, 1, wx.ALIGN_CENTRE|wx.ALL, 5) sizer.Add(box, 0, wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5) box = wx.BoxSizer(wx.HORIZONTAL) label = wx.StaticText(self, -1, "Field #2:") label.SetHelpText("This is the help text for the label") box.Add(label, 0, wx.ALIGN_CENTRE|wx.ALL, 5) text = wx.TextCtrl(self, -1, "", size=(80,-1)) text.SetHelpText("Here's some help text for field #2") box.Add(text, 1, wx.ALIGN_CENTRE|wx.ALL, 5) sizer.Add(box, 0, wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5) line = wx.StaticLine(self, -1, size=(20,-1), style=wx.LI_HORIZONTAL) sizer.Add(line, 0, wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.RIGHT|wx.TOP, 5) btnsizer = wx.StdDialogButtonSizer() if wx.Platform != "__WXMSW__": btn = wx.ContextHelpButton(self) btnsizer.AddButton(btn) btn = wx.Button(self, wx.ID_OK) btn.SetHelpText("The OK button completes the dialog") btn.SetDefault() btnsizer.AddButton(btn) btn = wx.Button(self, wx.ID_CANCEL) btn.SetHelpText("The Cancel button cnacels the dialog. (Cool, huh?)") btnsizer.AddButton(btn) btnsizer.Realize() sizer.Add(btnsizer, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5) self.SetSizer(sizer) sizer.Fit(self) #--------------------------------------------------------------------------- class ResultWindow(wx.Dialog): def __init__( self, parent, ID, title, size=wx.DefaultSize, pos=wx.DefaultPosition, style=wx.DEFAULT_DIALOG_STYLE ): # Instead of calling wx.Dialog.__init__ we precreate the dialog # so we can set an extra style that must be set before # creation, and then we create the GUI dialog using the Create # method. pre = wx.PreDialog() pre.SetExtraStyle(wx.DIALOG_EX_CONTEXTHELP) pre.Create(parent, ID, title, pos, size, style) # This next step is the most important, it turns this Python # object into the real wrapper of the dialog (instead of pre) # as far as the wxPython extension is concerned. self.PostCreate(pre) # Now continue with the normal construction of the dialog # contents sizer = wx.BoxSizer(wx.VERTICAL) label = wx.StaticText(self, -1, "This is a wx.Dialog") label.SetHelpText("This is the help text for the label") sizer.Add(label, 0, wx.ALIGN_CENTRE|wx.ALL, 5) box = wx.BoxSizer(wx.HORIZONTAL) label = wx.StaticText(self, -1, "Field #1:") label.SetHelpText("This is the help text for the label") box.Add(label, 0, wx.ALIGN_CENTRE|wx.ALL, 5) text = wx.TextCtrl(self, -1, "", size=(80,-1)) text.SetHelpText("Here's some help text for field #1") box.Add(text, 1, wx.ALIGN_CENTRE|wx.ALL, 5) sizer.Add(box, 0, wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5) box = wx.BoxSizer(wx.HORIZONTAL) label = wx.StaticText(self, -1, "Field #2:") label.SetHelpText("This is the help text for the label") box.Add(label, 0, wx.ALIGN_CENTRE|wx.ALL, 5) text = wx.TextCtrl(self, -1, "", size=(80,-1)) text.SetHelpText("Here's some help text for field #2") box.Add(text, 1, wx.ALIGN_CENTRE|wx.ALL, 5) sizer.Add(box, 0, wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5) line = wx.StaticLine(self, -1, size=(20,-1), style=wx.LI_HORIZONTAL) sizer.Add(line, 0, wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.RIGHT|wx.TOP, 5) btnsizer = wx.StdDialogButtonSizer() if wx.Platform != "__WXMSW__": btn = wx.ContextHelpButton(self) btnsizer.AddButton(btn) btn = wx.Button(self, wx.ID_CLOSE) btn.SetHelpText("Close window") btn.SetDefault() btnsizer.AddButton(btn) sizer.Add(btnsizer, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5) self.SetSizer(sizer) sizer.Fit(self) #--------------------------------------------------------------------------- def RunScyther(mainwin,mode): global busy if (busy.acquire(False)): # Verification window verifywin = VerificationWindow(mainwin,-1,mode) verifywin.CenterOnScreen() # start the thread mainwin.SetCursor(wx.StockCursor(wx.CURSOR_WAIT)) mainwin.verified = False mainwin.settings.mode = mode t = ScytherThread(mainwin,mainwin.control.GetValue(),"",verifywin) t.start() # start the window and show until something happens # if it terminates, this is a cancel, and should also kill the thread. (what happens to a spawned Scyther in that case?) # if the thread terminames, it should close the window normally, and we end up here as well. val = verifywin.ShowModal() verifywin.Destroy() # kill thread anyway del(t) # Cursor back to normal mainwin.SetCursor(wx.StockCursor(wx.CURSOR_ARROW)) if mainwin.verified: # Great, we verified stuff, progress to the claim report print "We verified stuff, hooray" resultwin = ResultWindow(mainwin,-1,mode) t = AttackThread(mainwin,resultwin) t.start() resultwin.CenterOnScreen() val = resultwin.ShowModal() resultwin.Destroy() # kill thread anyway del(t) else: # Verification was cancelled print "We wuz cancelled!" busy.release()