2006-08-02 13:59:57 +01:00
|
|
|
#!/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
|
2006-08-03 14:40:39 +01:00
|
|
|
import Attackwindow
|
2006-08-02 13:59:57 +01:00
|
|
|
|
|
|
|
#---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
#---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
class ScytherThread(threading.Thread):
|
|
|
|
# Override Thread's __init__ method to accept the parameters needed:
|
2006-08-03 13:06:43 +01:00
|
|
|
def __init__ ( self, mainwin, spdl, details, verifywin ):
|
2006-08-02 13:59:57 +01:00
|
|
|
|
2006-08-03 13:06:43 +01:00
|
|
|
self.mainwin = mainwin
|
|
|
|
self.verifywin = verifywin
|
2006-08-02 13:59:57 +01:00
|
|
|
self.spdl = spdl
|
|
|
|
self.details = details
|
2006-08-04 22:28:58 +01:00
|
|
|
self.verified = False
|
2006-08-02 13:59:57 +01:00
|
|
|
|
|
|
|
self.claims = []
|
|
|
|
|
|
|
|
threading.Thread.__init__ ( self )
|
|
|
|
|
|
|
|
def run(self):
|
|
|
|
|
|
|
|
self.claimResults()
|
|
|
|
|
2006-08-02 22:15:36 +01:00
|
|
|
# Results are done (claimstatus can be reported)
|
|
|
|
|
2006-08-03 13:06:43 +01:00
|
|
|
# Shoot down the verification window and let the RunScyther function handle the rest
|
2006-08-04 22:28:58 +01:00
|
|
|
self.verified = True
|
2006-08-04 22:19:38 +01:00
|
|
|
self.verifywin.Close()
|
2006-08-02 13:59:57 +01:00
|
|
|
|
|
|
|
def claimResults(self):
|
2006-08-02 22:15:36 +01:00
|
|
|
""" Convert spdl to result (using Scyther)
|
|
|
|
|
2006-08-03 13:06:43 +01:00
|
|
|
The list of claim goes back to self.mainwin.claims, which is a
|
2006-08-02 22:15:36 +01:00
|
|
|
property of the main window
|
|
|
|
"""
|
2006-08-02 13:59:57 +01:00
|
|
|
|
|
|
|
scyther = Scyther.Scyther()
|
2006-08-02 23:07:29 +01:00
|
|
|
|
2006-08-03 13:06:43 +01:00
|
|
|
scyther.options = self.mainwin.settings.ScytherArguments()
|
2006-08-02 13:59:57 +01:00
|
|
|
if sys.platform.startswith('win'):
|
2006-08-04 22:02:50 +01:00
|
|
|
""" Windows """
|
2006-08-02 13:59:57 +01:00
|
|
|
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)
|
2006-08-03 13:06:43 +01:00
|
|
|
self.mainwin.claims = scyther.verify()
|
2006-08-02 13:59:57 +01:00
|
|
|
self.summary = str(scyther)
|
|
|
|
|
2006-08-03 13:06:43 +01:00
|
|
|
|
|
|
|
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):
|
|
|
|
|
|
|
|
# create the images in the background
|
|
|
|
self.makeImages()
|
2006-08-02 13:59:57 +01:00
|
|
|
|
2006-08-02 22:15:36 +01:00
|
|
|
def makeImages(self):
|
|
|
|
""" create images """
|
2006-08-03 13:06:43 +01:00
|
|
|
for cl in self.mainwin.claims:
|
2006-08-02 22:15:36 +01:00
|
|
|
for attack in cl.attacks:
|
|
|
|
self.makeImage(attack)
|
2006-08-03 15:14:38 +01:00
|
|
|
if cl.button and len(cl.attacks) > 0:
|
2006-08-03 14:40:39 +01:00
|
|
|
cl.button.Enable()
|
2006-08-02 22:15:36 +01:00
|
|
|
|
|
|
|
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()
|
2006-08-03 14:40:39 +01:00
|
|
|
pr.close()
|
2006-08-02 22:15:36 +01:00
|
|
|
attack.pngfile = fpname2 # this is where the file name is stored
|
|
|
|
|
2006-08-04 22:02:50 +01:00
|
|
|
#---------------------------------------------------------------------------
|
|
|
|
|
2006-08-03 13:06:43 +01:00
|
|
|
class VerificationWindow(wx.Dialog):
|
|
|
|
def __init__(
|
2006-08-04 22:02:50 +01:00
|
|
|
self, parent, ID, title, pos=wx.DefaultPosition, size=wx.DefaultSize,
|
2006-08-03 13:06:43 +01:00
|
|
|
style=wx.DEFAULT_DIALOG_STYLE
|
|
|
|
):
|
|
|
|
|
2006-08-04 22:02:50 +01:00
|
|
|
wx.Dialog.__init__(self,parent,ID,title,pos,size,style)
|
2006-08-03 13:06:43 +01:00
|
|
|
|
|
|
|
sizer = wx.BoxSizer(wx.VERTICAL)
|
|
|
|
|
2006-08-04 22:02:50 +01:00
|
|
|
label = wx.StaticText(self, -1, "Verifying protocol description")
|
2006-08-03 13:06:43 +01:00
|
|
|
sizer.Add(label, 0, wx.ALIGN_CENTRE|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()
|
|
|
|
|
|
|
|
btn = wx.Button(self, wx.ID_CANCEL)
|
|
|
|
btnsizer.AddButton(btn)
|
|
|
|
btnsizer.Realize()
|
|
|
|
|
|
|
|
sizer.Add(btnsizer, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)
|
|
|
|
|
|
|
|
self.SetSizer(sizer)
|
|
|
|
sizer.Fit(self)
|
|
|
|
|
|
|
|
#---------------------------------------------------------------------------
|
|
|
|
|
2006-08-03 14:40:39 +01:00
|
|
|
class ResultWindow(wx.Frame):
|
2006-08-04 22:02:50 +01:00
|
|
|
|
2006-08-03 13:06:43 +01:00
|
|
|
def __init__(
|
2006-08-04 22:02:50 +01:00
|
|
|
self, mainwindow, ID, title, pos=wx.DefaultPosition, size=wx.DefaultSize,
|
2006-08-04 22:19:38 +01:00
|
|
|
style=wx.DEFAULT_DIALOG_STYLE
|
2006-08-03 13:06:43 +01:00
|
|
|
):
|
2006-08-02 13:59:57 +01:00
|
|
|
|
2006-08-03 14:40:39 +01:00
|
|
|
self.mainwindow = mainwindow
|
2006-08-04 22:02:50 +01:00
|
|
|
|
|
|
|
wx.Frame.__init__(self,mainwindow,ID,title,pos,size,style)
|
2006-08-03 14:40:39 +01:00
|
|
|
|
2006-08-04 22:02:50 +01:00
|
|
|
self.thread = None
|
|
|
|
self.Bind(wx.EVT_CLOSE, self.onCloseWindow)
|
2006-08-03 13:06:43 +01:00
|
|
|
|
2006-08-04 22:28:58 +01:00
|
|
|
self.BuildTable()
|
|
|
|
|
|
|
|
|
|
|
|
def onViewButton(self,evt):
|
|
|
|
btn = evt.GetEventObject()
|
|
|
|
(y,x) = self.grid.GetItemPosition(btn)
|
|
|
|
n = len(self.mainwindow.claims)
|
|
|
|
cln = n-y
|
|
|
|
cl = self.mainwindow.claims[cln]
|
|
|
|
w = Attackwindow.AttackWindow(cl)
|
|
|
|
|
|
|
|
def onCloseWindow(self,evt):
|
|
|
|
# TODO we should kill self.thread
|
|
|
|
self.mainwindow.claims = None
|
|
|
|
self.Destroy()
|
|
|
|
|
|
|
|
|
|
|
|
def BuildTable(self):
|
2006-08-03 13:06:43 +01:00
|
|
|
# Now continue with the normal construction of the dialog
|
|
|
|
# contents
|
|
|
|
sizer = wx.BoxSizer(wx.VERTICAL)
|
|
|
|
|
2006-08-04 22:28:58 +01:00
|
|
|
# For these claims...
|
|
|
|
claims = self.mainwindow.claims
|
|
|
|
|
2006-08-03 14:40:39 +01:00
|
|
|
# set up grid
|
2006-08-03 15:45:47 +01:00
|
|
|
self.grid = grid = wx.GridBagSizer(7,1+len(claims))
|
2006-08-03 14:40:39 +01:00
|
|
|
|
2006-08-04 22:02:50 +01:00
|
|
|
def titlebar(x,title,width=1):
|
|
|
|
txt = wx.StaticText(self,-1,title)
|
2006-08-03 15:14:38 +01:00
|
|
|
font = wx.Font(14,wx.NORMAL,wx.NORMAL,wx.NORMAL)
|
|
|
|
txt.SetFont(font)
|
2006-08-04 22:02:50 +01:00
|
|
|
grid.Add(txt,(0,x),(1,width))
|
2006-08-03 15:14:38 +01:00
|
|
|
|
2006-08-04 22:02:50 +01:00
|
|
|
titlebar(0,"Claim",5)
|
|
|
|
if len(claims) > 0:
|
|
|
|
sn = claims[0].stateName(2)
|
|
|
|
resulttxt = sn[0].upper() + sn[1:]
|
|
|
|
else:
|
|
|
|
resultxt = "Results"
|
|
|
|
titlebar(5,resulttxt,2)
|
2006-08-03 14:40:39 +01:00
|
|
|
|
2006-08-04 22:28:58 +01:00
|
|
|
self.lastprot = None
|
|
|
|
self.lastrole = None
|
2006-08-04 22:06:12 +01:00
|
|
|
for index in range(0,len(claims)):
|
2006-08-03 14:49:40 +01:00
|
|
|
# we reverse the display order of the claims!
|
2006-08-04 22:28:58 +01:00
|
|
|
cl = claims[len(claims)-index-1]
|
|
|
|
self.BuildClaim(grid,cl,index+1)
|
2006-08-04 22:02:50 +01:00
|
|
|
|
2006-08-03 14:40:39 +01:00
|
|
|
sizer.Add(grid, 0,wx.ALIGN_CENTRE|wx.ALL,5)
|
|
|
|
|
2006-08-03 13:06:43 +01:00
|
|
|
self.SetSizer(sizer)
|
|
|
|
sizer.Fit(self)
|
|
|
|
|
2006-08-04 22:28:58 +01:00
|
|
|
def BuildClaim(self,grid,cl,ypos):
|
|
|
|
# a support function
|
|
|
|
def addtxt(txt,column):
|
|
|
|
grid.Add(wx.StaticText(self,-1,txt),(ypos,column),(1,1),wx.ALIGN_CENTER_VERTICAL)
|
2006-08-04 22:02:50 +01:00
|
|
|
|
2006-08-04 22:28:58 +01:00
|
|
|
# button for ok/fail
|
|
|
|
tsize = (16,16)
|
|
|
|
if cl.okay:
|
|
|
|
bmp = wx.ArtProvider_GetBitmap(wx.ART_TICK_MARK,wx.ART_CMN_DIALOG,tsize)
|
|
|
|
else:
|
|
|
|
bmp = wx.ArtProvider_GetBitmap(wx.ART_CROSS_MARK,wx.ART_CMN_DIALOG,tsize)
|
|
|
|
if not bmp.Ok():
|
|
|
|
bmp = wx.EmptyBitmap(tsize)
|
|
|
|
bmpfield = wx.StaticBitmap(self,-1,bmp)
|
|
|
|
|
|
|
|
grid.Add(bmpfield,(ypos,0),(1,1),wx.ALIGN_CENTER_VERTICAL)
|
|
|
|
|
|
|
|
# protocol, role, label
|
|
|
|
prot = str(cl.protocol)
|
|
|
|
showPR = False
|
|
|
|
if prot != self.lastprot:
|
|
|
|
self.lastprot = prot
|
|
|
|
showPR = True
|
|
|
|
role = str(cl.role)
|
|
|
|
if role != self.lastrole:
|
|
|
|
self.lastrole = role
|
|
|
|
showPR = True
|
|
|
|
if showPR:
|
|
|
|
addtxt(prot,1)
|
|
|
|
addtxt(role,2)
|
|
|
|
|
|
|
|
addtxt(str(cl.shortlabel),3)
|
|
|
|
|
|
|
|
claimdetails = str(cl.claimtype)
|
|
|
|
if cl.parameter:
|
|
|
|
claimdetails += " %s " % (cl.parameter)
|
|
|
|
addtxt(claimdetails,4)
|
|
|
|
|
|
|
|
# add view button (if needed)
|
|
|
|
n = len(cl.attacks)
|
|
|
|
cl.button = wx.Button(self,-1,"%i %s" % (n,cl.stateName(n)))
|
|
|
|
grid.Add(cl.button,(ypos,5),(1,1),wx.ALIGN_CENTER_VERTICAL)
|
|
|
|
cl.button.Disable()
|
|
|
|
if n > 0:
|
|
|
|
# Aha, something to show
|
|
|
|
self.Bind(wx.EVT_BUTTON, self.onViewButton,cl.button)
|
|
|
|
|
|
|
|
# remark something about completeness
|
|
|
|
remark = ""
|
|
|
|
if not cl.complete:
|
|
|
|
if n == 0:
|
|
|
|
# no attacks, no states within bounds
|
|
|
|
remark = "within bounds"
|
|
|
|
else:
|
|
|
|
# some attacks/states within bounds
|
|
|
|
remark = "at least, maybe more"
|
|
|
|
else:
|
|
|
|
if n == 0:
|
|
|
|
# no attacks, no states
|
|
|
|
remark = "none"
|
|
|
|
else:
|
|
|
|
# there exist n states/attacks (within any number of runs)
|
|
|
|
remark = "exactly"
|
|
|
|
addtxt(" (%s)" % remark,6)
|
|
|
|
|
2006-08-03 14:40:39 +01:00
|
|
|
|
2006-08-03 13:06:43 +01:00
|
|
|
#---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
def RunScyther(mainwin,mode):
|
2006-08-02 13:59:57 +01:00
|
|
|
|
2006-08-04 22:02:50 +01:00
|
|
|
# Verification window
|
2006-08-02 13:59:57 +01:00
|
|
|
|
2006-08-04 22:02:50 +01:00
|
|
|
verifywin = VerificationWindow(mainwin,-1,mode)
|
|
|
|
verifywin.CenterOnScreen()
|
|
|
|
verifywin.Show(True)
|
2006-08-03 13:06:43 +01:00
|
|
|
|
2006-08-04 22:02:50 +01:00
|
|
|
# start the thread
|
|
|
|
|
|
|
|
verifywin.SetCursor(wx.StockCursor(wx.CURSOR_WAIT))
|
2006-08-03 13:06:43 +01:00
|
|
|
|
2006-08-04 22:02:50 +01:00
|
|
|
mainwin.settings.mode = mode
|
|
|
|
t = ScytherThread(mainwin,mainwin.control.GetValue(),"",verifywin)
|
|
|
|
t.start()
|
2006-08-02 13:59:57 +01:00
|
|
|
|
2006-08-04 22:02:50 +01:00
|
|
|
# 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.
|
2006-08-03 13:06:43 +01:00
|
|
|
|
2006-08-04 22:02:50 +01:00
|
|
|
val = verifywin.ShowModal()
|
2006-08-03 13:06:43 +01:00
|
|
|
|
2006-08-04 22:02:50 +01:00
|
|
|
# Cursor back to normal
|
|
|
|
verifywin.SetCursor(wx.StockCursor(wx.CURSOR_ARROW))
|
2006-08-03 13:06:43 +01:00
|
|
|
|
2006-08-04 22:28:58 +01:00
|
|
|
if t.verified:
|
2006-08-04 22:02:50 +01:00
|
|
|
# Great, we verified stuff, progress to the claim report
|
|
|
|
title = "Scyther results : %s" % mode
|
|
|
|
resultwin = ResultWindow(mainwin,-1,title)
|
|
|
|
resultwin.Show(1)
|
2006-08-03 13:06:43 +01:00
|
|
|
|
2006-08-04 22:02:50 +01:00
|
|
|
t = AttackThread(mainwin,resultwin)
|
|
|
|
t.start()
|
2006-08-03 13:06:43 +01:00
|
|
|
|
2006-08-04 22:02:50 +01:00
|
|
|
resultwin.thread = t
|
|
|
|
resultwin.CenterOnScreen()
|
|
|
|
resultwin.Show(True)
|
2006-08-03 13:06:43 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
2006-08-02 13:59:57 +01:00
|
|
|
|
|
|
|
|