scyther/gui/Scyther/Scyther.py

235 lines
5.7 KiB
Python
Raw Normal View History

2006-08-02 13:59:57 +01:00
#!/usr/bin/python
#
# Scyther interface
#
#---------------------------------------------------------------------------
""" Import externals """
import os
import os.path
2006-08-02 13:59:57 +01:00
import sys
import StringIO
import tempfile
2006-08-02 13:59:57 +01:00
#---------------------------------------------------------------------------
""" Import scyther components """
import XMLReader
2006-12-14 14:06:50 +00:00
import Error
2006-08-02 13:59:57 +01:00
from Misc import *
#---------------------------------------------------------------------------
2006-12-14 14:06:50 +00:00
"""
Globals
"""
FirstCheck = True
#---------------------------------------------------------------------------
2006-11-23 11:28:51 +00:00
"""
The default path for the binaries is set in __init__.py in the (current)
directory 'Scyther'.
"""
2006-08-09 10:26:15 +01:00
2006-08-09 12:39:35 +01:00
def setBinDir(dir):
2006-08-09 10:26:15 +01:00
global bindir
bindir = dir
2006-08-09 12:54:37 +01:00
def getBinDir():
global bindir
return bindir
2006-08-09 10:26:15 +01:00
#---------------------------------------------------------------------------
2006-12-14 14:06:50 +00:00
def Check():
"""
Various dynamic checks that can be performed before starting the
backend.
"""
global FirstCheck
# First time
if FirstCheck:
"""
Perform any checks that only need to be done the first time.
"""
FirstCheck = False
# Every time
# Check Scyther backend program availability
program = getScytherBackend()
CheckSanity(program)
#---------------------------------------------------------------------------
def CheckSanity(program):
"""
This is where the existence is checked of the Scyther backend.
"""
if not os.path.isfile(program):
raise Error.BinaryError, program
#---------------------------------------------------------------------------
2006-11-23 11:28:51 +00:00
def getScytherBackend():
# Where is my executable?
#
# Auto-detect platform and infer executable name from that
#
if "linux" in sys.platform:
""" linux """
scythername = "scyther-linux"
2006-12-14 14:06:50 +00:00
# elif "darwin" in sys.platform:
2006-08-04 23:00:22 +01:00
2006-12-14 14:06:50 +00:00
# """ OS X """
# # Preferably, we test for architecture (PPC/Intel) until we
# # know how to build a universal binary
# scythername = "scyther-osx"
2006-11-23 11:28:51 +00:00
elif sys.platform.startswith('win'):
2006-11-23 11:28:51 +00:00
""" Windows """
scythername = "scyther-w32.exe"
2006-11-23 11:28:51 +00:00
else:
2006-11-23 11:28:51 +00:00
""" Unsupported"""
2006-12-14 14:06:50 +00:00
raise Error.UnknownPlatformError, sys.platform
2006-11-23 11:28:51 +00:00
program = os.path.join(getBinDir(),scythername)
return program
#---------------------------------------------------------------------------
class Scyther(object):
def __init__ ( self):
2006-08-04 23:00:22 +01:00
2006-08-08 16:54:00 +01:00
# Init
2006-11-23 11:28:51 +00:00
self.program = getScytherBackend()
2006-08-02 13:59:57 +01:00
self.spdl = None
self.inputfile = None
2006-08-08 17:16:28 +01:00
self.options = ""
2006-08-02 13:59:57 +01:00
self.claims = None
2006-08-06 20:52:07 +01:00
self.errors = None
2006-08-06 22:16:14 +01:00
self.errorcount = 0
2006-08-07 11:52:48 +01:00
self.run = False
2006-08-08 16:54:00 +01:00
self.output = None
# defaults
self.xml = True # this results in a claim end, otherwise we simply get the output
2006-08-02 13:59:57 +01:00
def setInput(self,spdl):
self.spdl = spdl
self.inputfile = None
2006-08-02 13:59:57 +01:00
def setFile(self,filename):
self.inputfile = filename
2006-08-02 13:59:57 +01:00
self.spdl = ""
fp = open(filename,"r")
for l in fp.readlines():
self.spdl += l
fp.close()
def addFile(self,filename):
self.inputfile = None
if not self.spdl:
self.spdl = ""
fp = open(filename,"r")
for l in fp.readlines():
self.spdl += l
fp.close()
2006-08-02 13:59:57 +01:00
def verify(self):
2006-11-23 11:28:51 +00:00
""" Should return a list of results """
if self.program == None:
return []
2006-08-02 13:59:57 +01:00
# Generate a temproary file for the error output
errorfile = tempfile.NamedTemporaryFile()
# Generate command line for the Scyther process
2006-08-09 10:33:50 +01:00
self.cmd = "\"%s\"" % self.program
2006-08-08 16:54:00 +01:00
if self.xml:
self.cmd += " --dot-output --xml-output --plain"
self.cmd += " --errors=%s" % (errorfile.name)
2006-08-08 16:54:00 +01:00
self.cmd += " " + self.options
2006-08-02 14:10:38 +01:00
# Start the process, push input, get output
(stdin,stdout) = os.popen2(self.cmd)
2006-08-02 14:10:38 +01:00
if self.spdl:
2006-08-06 20:52:07 +01:00
stdin.write(self.spdl)
stdin.close()
2006-08-08 16:54:00 +01:00
output = stdout.read()
2006-08-06 22:16:14 +01:00
# get errors
2006-08-06 22:16:14 +01:00
# filter out any non-errors (say maybe only claim etc) and count
# them.
2006-08-07 12:02:14 +01:00
self.errors = []
errorfile.seek(0)
for l in errorfile.readlines():
2006-08-07 12:02:14 +01:00
if not l.startswith("claim\t"):
self.errors.append(l.strip())
2006-08-06 22:16:14 +01:00
self.errorcount = len(self.errors)
2006-08-06 20:52:07 +01:00
# close
stdout.close()
errorfile.close()
2006-08-06 20:52:07 +01:00
2006-08-08 16:54:00 +01:00
if self.xml:
2006-08-08 17:16:28 +01:00
self.validxml = False
2006-08-08 16:54:00 +01:00
if len(output) > 0:
2006-08-08 17:16:28 +01:00
if output.startswith("<scyther>"):
self.validxml = True
if self.validxml:
2006-08-08 16:54:00 +01:00
xmlfile = StringIO.StringIO(output)
reader = XMLReader.XMLReader()
self.claims = reader.readXML(xmlfile)
else:
2006-08-08 17:16:28 +01:00
# no xml output... store whatever comes out
2006-08-08 16:54:00 +01:00
self.claims = []
2006-08-08 17:16:28 +01:00
self.output = output
2006-08-08 16:54:00 +01:00
result = self.claims
else:
2006-08-08 16:54:00 +01:00
self.output = output
result = self.output
2006-08-02 13:59:57 +01:00
2006-08-07 11:52:48 +01:00
self.run = True
2006-08-08 16:54:00 +01:00
return result
2006-08-02 13:59:57 +01:00
def getClaim(self,claimid):
if self.claims:
for cl in self.claims:
if cl.id == claimid:
return cl
return None
2006-08-02 13:59:57 +01:00
def __str__(self):
2006-08-07 11:52:48 +01:00
if self.run:
if self.errorcount > 0:
2006-08-07 17:40:46 +01:00
return "%i errors:\n%s" % (self.errorcount, "\n".join(self.errors))
2006-08-07 11:52:48 +01:00
else:
2006-08-08 17:16:28 +01:00
if self.xml and self.validxml:
s = "Verification results:\n"
2006-08-08 16:54:00 +01:00
for cl in self.claims:
s += str(cl) + "\n"
return s
else:
return self.output
2006-08-02 13:59:57 +01:00
else:
return "Scyther has not been run yet."