'''
Accessible Access Control 1.0
2012-2104 Michigan Technological University
Supported in part by NSF grants: DUE-1140512, DUE-1245310 and IIS-1319363
Developer: Yifei Li
Advisors:Dr. Steve Carr, Dr. Jean Mayo, Dr. Ching-Kuang Shene and Dr. Chaoli Wang
'''
'''
Created on Jan 23, 2012
'''
from PyQt4.QtGui import QWidget, QFileDialog, QMessageBox, QGraphicsItem, QListView
from PyQt4.QtCore import pyqtSignal, Qt
from Ui_QueryWindow import Ui_Form
from QueryOutput import QueryOutput
from DomainNode import DomainNode
from TypeNode import TypeNode
from FileNode import FileNode 
from EdgeItem import EdgeItem
import string
import re

class QueryWindow(QWidget):
    # file name, file type
    animateQuery0 = pyqtSignal(str, QGraphicsItem)
    # file name, file type, domains that can execute this file, types these domains can access, filenodes
    animateQuery1 = pyqtSignal(str, QGraphicsItem, list, set, list)
    # file name, access mode, file type, domains that can execute this file, types these domains can access in the mode, filenodes
    animateQuery2 = pyqtSignal(str, str, QGraphicsItem, list, set, list)
    # domain, mode, types, files 
    animateQuery3 = pyqtSignal(QGraphicsItem, str, set, list)
    # binary, file, mode, type of binary, type of file, domains that can execute the binary, intermediate domains
    animateQuery4 = pyqtSignal(str, str, str, QGraphicsItem, QGraphicsItem, list, list, set)
    # file, file type, domains that can execute this file
    animateQuery5 = pyqtSignal(str, QGraphicsItem, list)
    # file, access mode, file type, domains 
    animateQuery6 = pyqtSignal(str, str, QGraphicsItem, list)
    # fileNodes
    animateQuery7 = pyqtSignal(list)
    # mode, type file map
    animateQuery8 = pyqtSignal(str, dict)
    # file name, success, domain node, file type node, domain-type edge, default type node, file node
    animateQuery9 = pyqtSignal(str, bool, QGraphicsItem, QGraphicsItem, QGraphicsItem, QGraphicsItem, QGraphicsItem)
    # file name, success, domain node, file type node, edge, resulting domains
    animateQuery10 = pyqtSignal(str, bool, QGraphicsItem, QGraphicsItem, QGraphicsItem, list)
    
    def __init__(self, scene, parent = None):
        QWidget.__init__(self, parent)
        self.scene = scene
        self.ui = Ui_Form()
        self.ui.setupUi(self)
        self.queryResultTextEdit = QueryOutput(scene,self)
        self.ui.runQueryLayout.addWidget(self.queryResultTextEdit)
        self.setLayout(self.ui.verticalLayout)
        self.ui.queryTypeGroupBox.setLayout(self.ui.queryTypeLayout)
        self.ui.queryInputGroupBox.setLayout(self.ui.queryInputLayout)
        self.ui.runQueryGroupBox.setLayout(self.ui.runQueryLayout)
    
        self.ui.queryListWidget.addItem('Type of a file')
#         self.ui.queryListWidget.addItem('The files which can be accessed by a binary')
#         self.ui.queryListWidget.addItem('The files which can be accessed by a binary in certain mode')
#         self.ui.queryListWidget.addItem('The files which can be accessed from a domain in certain mode')
        self.ui.queryListWidget.addItem('If a binary can access a file in a certain mode')
        self.ui.queryListWidget.addItem('All domains from which a binary can be executed')
        self.ui.queryListWidget.addItem('All domains from which a file can be accessed in a certain access mode')
        self.ui.queryListWidget.addItem('Are there files with no assigned type')
#         self.ui.queryListWidget.addItem('Are there files that cannot be accessed with a certain access mode')
        self.ui.queryListWidget.addItem('Default type of a file created from a domain')
        self.ui.queryListWidget.addItem('Result of executing a binary from a domain')
                
        self.ui.queryListWidget.setCurrentRow(0)
        self.changeQueryInput()
        
        self.ui.queryListWidget.currentRowChanged.connect(self.changeQueryInput)
        self.ui.runQueryButton.clicked.connect(self.runQuery)
        self.ui.clearButton.clicked.connect(self.queryResultTextEdit.clear)
        
        self.animationEnabled = True
        
    def keyPressEvent(self, event):
        if event.key() == Qt.Key_Enter:
            self.runQuery()
    
    def getQueryResultFromCommandLineInput(self, queryId, paras):
        counter = 0
        #self.highlightLastAnswer()
        if queryId == 0:
            filename = paras[0]
            self.runQuery0(filename)
#         elif queryId == 1:
#             self.runQuery1()
#         elif queryId == 2:
#             subjLevel = paras[counter]
#             self.runQuery2(subjLevel)
#         elif queryId == 3:
#             subjLevel = paras[counter]
#             self.runQuery3(subjLevel)
        elif queryId == 1:#4:
            filename1 = paras[counter]
            counter+=1
            filename2 = paras[counter]
            counter+=1
            mode = paras[counter]
            self.runQuery4(filename1, filename2, mode)
        elif queryId == 2:#5:
            filename = paras[counter]
            self.runQuery5(filename)
        elif queryId == 3:#6:
            filename = paras[counter]
            counter+=1
            mode = paras[counter]
            self.runQuery6(filename, mode)
        elif queryId == 4:#7:
            self.runQuery7()
#         elif queryId == 8:
#             self.runQuery8()
        elif queryId == 5:#9:
            mode = paras[counter]
            self.runQuery9()
        elif queryId == 6:#10:
            domain = paras[counter]
            counter+=1
            filename = paras[counter]
            self.runQuery10(domain, filename)
            
    def setQueryForQuestion(self, questionId):
        self.ui.queryListWidget.setCurrentRow(questionId)
        self.changeQueryInput()
        
    def changeQueryInput(self):
        current = self.ui.queryListWidget.currentRow()
        if current == 0:
            self.ui.file1Label.setVisible(True)
            self.ui.file1LineEdit.setVisible(True)
            self.ui.file1Label.setText('File:')
            self.ui.file1Label.adjustSize()
            self.ui.file2Label.setVisible(False)
            self.ui.file2LineEdit.setVisible(False)
            self.ui.modeLabel.setVisible(False)
            self.ui.accessModeComboBox.setVisible(False)
            self.ui.domainLabel.setVisible(False)
            self.ui.domainComboBox.setVisible(False)
#         elif current == 1:
#             self.ui.file1Label.setVisible(True)
#             self.ui.file1LineEdit.setVisible(True)
#             self.ui.file1Label.setText('Binary:')
#             self.ui.file1Label.adjustSize()
#             self.ui.file2Label.setVisible(False)
#             self.ui.file2LineEdit.setVisible(False)
#             self.ui.modeLabel.setVisible(False)
#             self.ui.accessModeComboBox.setVisible(False)
#             self.ui.domainLabel.setVisible(False)
#             self.ui.domainComboBox.setVisible(False)
#         elif current == 2:
#             self.ui.file1Label.setVisible(True)
#             self.ui.file1LineEdit.setVisible(True)
#             self.ui.file1Label.setText('Binary:')
#             self.ui.file1Label.adjustSize()
#             self.ui.file2Label.setVisible(False)
#             self.ui.file2LineEdit.setVisible(False)
#             self.ui.modeLabel.setVisible(True)
#             self.ui.accessModeComboBox.setVisible(True)
#             self.ui.domainLabel.setVisible(False)
#             self.ui.domainComboBox.setVisible(False)
#         elif current == 3:
#             self.ui.file1Label.setVisible(False)
#             self.ui.file1LineEdit.setVisible(False)
#             self.ui.file2Label.setVisible(False)
#             self.ui.file2LineEdit.setVisible(False)
#             self.ui.modeLabel.setVisible(True)
#             self.ui.accessModeComboBox.setVisible(True)
#             self.ui.domainLabel.setVisible(True)
#             self.ui.domainComboBox.setVisible(True)
        elif current == 1:#4:
            self.ui.file1Label.setVisible(True)
            self.ui.file1LineEdit.setVisible(True)
            self.ui.file1Label.setText('Binary')
            self.ui.file1Label.adjustSize()
            self.ui.file2Label.setVisible(True)
            self.ui.file2LineEdit.setVisible(True)
            self.ui.modeLabel.setVisible(True)
            self.ui.accessModeComboBox.setVisible(True)
            self.ui.domainLabel.setVisible(False)
            self.ui.domainComboBox.setVisible(False)
        elif current == 2:#5:
            self.ui.file1Label.setVisible(True)
            self.ui.file1LineEdit.setVisible(True)
            self.ui.file1Label.setText('Binary')
            self.ui.file1Label.adjustSize()
            self.ui.file2Label.setVisible(False)
            self.ui.file2LineEdit.setVisible(False)
            self.ui.modeLabel.setVisible(False)
            self.ui.accessModeComboBox.setVisible(False)
            self.ui.domainLabel.setVisible(False)
            self.ui.domainComboBox.setVisible(False)
        elif current == 3:#6:
            self.ui.file1Label.setVisible(True)
            self.ui.file1LineEdit.setVisible(True)
            self.ui.file1Label.setText('File')
            self.ui.file1Label.adjustSize()
            self.ui.file2Label.setVisible(False)
            self.ui.file2LineEdit.setVisible(False)
            self.ui.modeLabel.setVisible(True)
            self.ui.accessModeComboBox.setVisible(True)
            self.ui.domainLabel.setVisible(False)
            self.ui.domainComboBox.setVisible(False)
        elif current == 4:#7:
            self.ui.file1Label.setVisible(False)
            self.ui.file1LineEdit.setVisible(False)
            self.ui.file2Label.setVisible(False)
            self.ui.file2LineEdit.setVisible(False)
            self.ui.modeLabel.setVisible(False)
            self.ui.accessModeComboBox.setVisible(False)
            self.ui.domainLabel.setVisible(False)
            self.ui.domainComboBox.setVisible(False)
#         elif current == 8:
#             self.ui.file1Label.setVisible(False)
#             self.ui.file1LineEdit.setVisible(False)
#             self.ui.file2Label.setVisible(False)
#             self.ui.file2LineEdit.setVisible(False)
#             self.ui.modeLabel.setVisible(True)
#             self.ui.accessModeComboBox.setVisible(True)
#             self.ui.domainLabel.setVisible(False)
#             self.ui.domainComboBox.setVisible(False)
#         elif current == 9 or current == 10:
        elif current == 5 or current == 6:
            self.ui.file1Label.setVisible(True)
            self.ui.file1LineEdit.setVisible(True)
            self.ui.file2Label.setVisible(False)
            self.ui.file2LineEdit.setVisible(False)
            self.ui.modeLabel.setVisible(False)
            self.ui.accessModeComboBox.setVisible(False)
            self.ui.domainLabel.setVisible(True)
            self.ui.domainComboBox.setVisible(True)
        self.refreshDomainComboBox()
            
    def refreshDomainComboBox(self):
        self.ui.domainComboBox.clear()
        for item in self.scene.items():
            if isinstance(item, DomainNode):
                self.ui.domainComboBox.addItem(item.name)

    def validFileName(self, filename):
        p = re.compile('(/\w+)+$')
        if p.match(filename) is not None:
            return True
        else:
            return False
    
    def findFileType(self, filename):
        '''
        Returns the type node
        '''
        pathComponents = string.split(filename, '/')[1:]
        node = self.scene.typeGraphRoot
        goToNextLevel = False
        recursiveNode = node
        for name in pathComponents:
            for child in node.children:
                if child.name == name:
                    goToNextLevel = True
                    node = child
                    if (child.flag >1 and child.fullPath != filename) or (child.fullPath == filename and not child.inheritFromNode):
                        recursiveNode = node
                        if child.flag == 3:
                            goToNextLevel = False
            if not goToNextLevel:
                return recursiveNode
        return recursiveNode
        
    def findDomainWithEntryPoint(self, entryPoint):
        domainSet = set()
        for domain in self.scene.items():
            if isinstance(domain, DomainNode):
                binaries = self.findDomainEntryPoint(domain)
                if entryPoint in binaries:
                    domainSet.add(domain)
        return domainSet
    
    def getEntryPointFromEdgeDescription(self, desc):
        binaries = set()
        for d in desc:
            d = d.replace(' ', '')
            idx = d.find('{')
            ridx = d.find('}')
            if idx!=-1:
                prefix = d[:idx]
                aset = d[idx+1:ridx].split(',')
                for a in aset:
                    one = prefix+a
                    binaries.add(one)
            else:
                binaries.add(d)
        return binaries
    
    def findDomainEntryPoint(self, domainNode):
        desc = set()
        for e in domainNode.edgeList:
            if e.startItem == domainNode and e.type == EdgeItem.EXEC_CONN:
                desc.add(e.description)
            elif e.startItem == domainNode and e.type == EdgeItem.AUTO_CONN:
                desc.add(e.description)
        return self.getEntryPointFromEdgeDescription(desc)
    
    def findExecutingDomains(self, type): 
        '''
        returns a list of domains from which the file can be executed
        '''
        domains = []
        domainSet = set()
        for e in type.edgeList:
            d = e.startItem
            if isinstance(d, DomainNode): 
                if 'x' in e.description:
                    domainSet.add(d)
        domains = list(domainSet)
        return domains

    def runQuery0(self, filename):
        '''
        Type of a file
        '''
        filetype = self.findFileType(filename).type
        if self.animationEnabled:
            self.animateQuery0.emit(filename, filetype)
        self.queryResultTextEdit.appendPlainText('[query 0]show type for file (%s)' % filename)
        self.queryResultTextEdit.appendPlainText(filetype.name)
        self.queryResultTextEdit.appendPlainText('\n')

    def runQuery1(self, filename):
        '''
        The files which can be accessed by a binary
        '''
        type = self.findFileType(filename).type
        domains = self.findExecutingDomains(type)
                
        types = set([])
        for d in domains:
            for e in d.edgeList:
                t = e.endItem
                if isinstance(t, TypeNode):
                    types.add(t)
        
        files = ''    
        fileNodes = []       
        for item in self.scene.items():
            if isinstance(item, FileNode):
                if item.type in types:
                    fileNodes.append(item)
                    if item.flag == 0:
                        files += '%s' % item.fullPath 
                    elif item.flag == 2 or item.flag == 3:
                        files += '%s/*;' % item.fullPath
        
        if self.animationEnabled:
            self.animateQuery1.emit(filename, type, domains, types, fileNodes)

    
        self.queryResultTextEdit.appendPlainText('[query 1]show accessible files for file (%s)' % filename)
        self.queryResultTextEdit.appendPlainText(files)
        self.queryResultTextEdit.appendPlainText('\n')
        
    def runQuery2(self, filename, mode):
        '''
        The files which can be accessed by a binary in certain mode
        '''
        type = self.findFileType(filename).type
        domains = self.findExecutingDomains(type)
        
        types = set()
        for d in domains:
            for e in d.edgeList:
                t = e.endItem
                if isinstance(t, TypeNode):
                    if mode in e.description:
                        types.add(t)
        
        files = ''      
        fileNodes = []     
        for item in self.scene.items():
            if isinstance(item, FileNode):
                if item.type in types:
                    fileNodes.append(item)
                    if item.flag == 0:
                        files += '%s' % item.fullPath 
                    elif item.flag == 2 or item.flag == 3:
                        files += '%s/*;' % item.fullPath
                        
        if self.animationEnabled:
            self.animateQuery2.emit(filename, mode, type, domains, types, fileNodes)

    
        self.queryResultTextEdit.appendPlainText('[query 2]show accessible files for binary (%s) in mode (%s)' % (filename, mode))
        self.queryResultTextEdit.appendPlainText(files)
        self.queryResultTextEdit.appendPlainText('\n')

    def runQuery3(self, domain, mode):
        '''
        all files that can be accessed in a mode from a domain
        '''
        for item in self.scene.items():
            if isinstance(item, DomainNode):
                if item.name == domain:
                    domainNode = item
                    
        binaries = set()
        if mode == 'x':
            binaries = self.findDomainEntryPoint(domainNode)
        
        types = set()
        for e in domainNode.edgeList:
            if isinstance(e.endItem, TypeNode):
                if mode in e.description:
                    types.add(e.endItem)
        
        files = ''          
        fileNodes = []
        for item in self.scene.items():
            if isinstance(item, FileNode):
                if item.type in types:
                    fileNodes.append(item)
                    if item.flag == 0:
                        files += '%s;' % item.fullPath 
                    elif item.flag == 2 or item.flag == 3:
                        files += '%s/*;' % item.fullPath
        files+= ';'.join(binaries)
                    
        if self.animationEnabled:
            self.animateQuery3.emit(domainNode, mode, types, fileNodes)
            
        self.queryResultTextEdit.appendPlainText('[query 3]files that can be accessed in mode (%s) from domain (%s)' % (mode, domain))
        if files!='':
            self.queryResultTextEdit.appendPlainText(files)
        else:
            self.queryResultTextEdit.appendPlainText('None')
        self.queryResultTextEdit.appendPlainText('\n')
        
    def runQuery4(self, filename1, filename2, mode):
        '''
        If a binary can access a file with a certain access mode
        '''
        type1 = self.findFileType(filename1).type
        type2 = self.findFileType(filename2).type
        domains = self.findExecutingDomains(type1)
        domainsWithEntryPoint = self.findDomainWithEntryPoint(filename1)
        domainsWithEntryPoint2 = self.findDomainWithEntryPoint(filename2)
     
        intermediateDomains = []
        for d in domains:
            for e in d.edgeList:
                t = e.endItem
                if t is type2:
                    if mode in e.description:
                        intermediateDomains.append([d])
                elif mode == 'x' and e.startItem == d and \
                (e.type == EdgeItem.AUTO_CONN or e.type == EdgeItem.EXEC_CONN):
                    if d in domainsWithEntryPoint2:
                        intermediateDomains.append([d, t])
                    
        for d in domainsWithEntryPoint:
            for e in d.edgeList:
                if e.startItem == d and \
                (e.type == EdgeItem.AUTO_CONN or e.type == EdgeItem.EXEC_CONN):
                    endDomain = e.endItem
                    for ee in endDomain.edgeList:
                        if ee.endItem is type2 and mode in ee.description:
                            intermediateDomains.append([d, endDomain])
                        elif mode == 'x' and ee.startItem == endDomain and \
                            (ee.type == EdgeItem.AUTO_CONN or ee.type == EdgeItem.EXEC_CONN):
                            if endDomain in domainsWithEntryPoint2:
                                intermediateDomains.append([d, endDomain, ee.endItem])
        
        if intermediateDomains:   
            result = True
        else:
            result = False
            
        if self.scene.main.ui.actionView_SelfTest.isChecked():
            return type1, type2, domains, domainsWithEntryPoint, intermediateDomains 
        
        if self.animationEnabled:    
            self.animateQuery4.emit(filename1, filename2, mode, type1, type2, domains, intermediateDomains, domainsWithEntryPoint)   

        domainNames = ''
        for dlist in intermediateDomains:
            one = ' to '.join(n.name for n in dlist)
            domainNames += '\'%s\' ' % one
            
        #self.queryResultTextEdit.appendPlainText('[query 4]binary (%s) can access file (%s) with permission (%s)' % (filename1, filename2, mode))
        self.queryResultTextEdit.appendPlainText('[query 1]binary (%s) can access file (%s) with permission (%s)' % (filename1, filename2, mode))
        if domainNames == '':
            self.queryResultTextEdit.appendPlainText('False')    
        else:
            self.queryResultTextEdit.appendPlainText('%s via domain[s] %s' % (str(result), domainNames))    
        self.queryResultTextEdit.appendPlainText('\n')

    def runQuery5(self, filename):
        '''
        Domains from which a binary can be executed
        '''
        type = self.findFileType(filename).type
        domains = self.findExecutingDomains(type)
#         domainSet = set(domains)
        domainSet1 = self.findDomainWithEntryPoint(filename)
#         domainSet = domainSet.union(domainSet1)
#         domains=list(domainSet)
        if self.animationEnabled:
            self.animateQuery5.emit(filename, type, domains)
        
        domainStr = ''
        for d in domains:
            if d in domainSet1:
                domainSet1.remove(d)
            domainStr += '%s ' % d.name 
        
        domainStr1 = ''
        for d in domainSet1:
            domainStr1 += '%s ' % d.name 
#         self.queryResultTextEdit.appendPlainText('[query 5]show domains from which binary (%s) can be executed' % filename)
        self.queryResultTextEdit.appendPlainText('[query 2]show all domains from which binary (%s) can be executed' % filename)
#         self.queryResultTextEdit.appendPlainText(domainStr)
        if domains:
            self.queryResultTextEdit.appendPlainText(domainStr+' can execute the binary based on permission assignment')
        if domainSet1:
            self.queryResultTextEdit.appendPlainText(\
                    domainStr1+' can execute the binary since the binary is an entry point program from the domain(s)')
        if domainStr == '' and domainStr1 == '':
            self.queryResultTextEdit.appendPlainText('None')
        self.queryResultTextEdit.appendPlainText('\n')
        
    def runQuery6(self, filename, mode):
        '''
        Domains from which a file can be accessed in a certain access mode'
        '''
        type = self.findFileType(filename).type
        domains = []
        domainSet1 = set()
        for e in type.edgeList:
            if mode in e.description:
                domains.append(e.startItem)
        if mode == 'x':
#             domainSet = set(domains)
            domainSet1 = self.findDomainWithEntryPoint(filename)
#             domainSet = domainSet.union(domainSet1)
#             domains=list(domainSet)
            
        if self.animationEnabled:    
            self.animateQuery6.emit(filename, mode, type, domains)
        
        domainStr = ''
        for d in domains:
            if d in domainSet1:
                domainSet1.remove(d)
            domainStr += '%s ' % d.name
        domainStr1 = ''
#         self.queryResultTextEdit.appendPlainText('[query 6]show domains file (%s) can access with permission (%s)' % (filename, mode))
        self.queryResultTextEdit.appendPlainText('[query 3]show all domains file (%s) can access with permission (%s)' % (filename, mode))
        if domains:
            self.queryResultTextEdit.appendPlainText(domainStr)
        if mode == 'x' and domainSet1:
            for d in domainSet1:
                domainStr1 += '%s ' % d.name 
            self.queryResultTextEdit.appendPlainText(\
                    domainStr1+' can execute the binary since the binary is an entry point program from the domain(s)')
        if domainStr == '' and domainStr1 == '':
            self.queryResultTextEdit.appendPlainText('None')
        self.queryResultTextEdit.appendPlainText('\n')
    
    def runQuery7(self):
        '''
        Are there files with no assigned type
        '''
        root = self.scene.typeGraphRoot
        noTypeNodes = []
        if root.type is None:
            noTypeNodes = [root]
            nodes = [i for i in root.children]
            while nodes:
                n = nodes.pop(0)
                if n.type is None:
                    noTypeNodes.append(n)
                if n.children:
                    nodes.extend(n.children)
            msg = ''
            for n in noTypeNodes:
                tmp = []
                for i in n.children:
                    if i.type is not None:
                        tmp.append(i)
                if n.flag == 2 or n.flag == 3:
                    if tmp:
                        if n.parent is None:
                            msg += '/* - {'
                        else:
                            msg += '%s/* - {' % str(n.fullPath)
                        for t in tmp:
                            msg += '%s, ' % str(t.fullPath)
                        msg = msg[0:-1]
                        msg += '}\n'
                    else:
                        if n.parent is None:
                            msg += '/*\n'
                        else:
                            msg += '%s/*' % str(n.fullPath)
                else:
                    msg += '%s\n' % str(n.fullPath)                        
        else:
            msg = 'There does not exist any file without an assigned type'
        
        if self.animationEnabled:
            self.animateQuery7.emit(noTypeNodes)
#         self.queryResultTextEdit.appendPlainText('[query 7]files without type assigned')
        self.queryResultTextEdit.appendPlainText('[query 4]files without type assigned')
        self.queryResultTextEdit.appendPlainText(msg)
        self.queryResultTextEdit.appendPlainText('\n')

                
        
    def runQuery8(self, mode):
        '''
        Are there files that cannot be accessed with a certain access mode
        '''
        typeFileMap = {}
        for item in self.scene.items():
            permissions = set()
            if isinstance(item, TypeNode):
                for e in item.edgeList:
                    for i in e.description:
                        permissions.add(i)
                
                if mode not in permissions:
                    typeFileMap[item] = []
                    
        for item in self.scene.items():
            if isinstance(item, FileNode):
                if item.type in typeFileMap:
                    typeFileMap[item.type].append(item)
        
        if len(typeFileMap) > 0:
            self.animateQuery8.emit(mode, typeFileMap)

        msg = ''
        for files in typeFileMap.values():
            for f in files:
                if f.parent is None:
                    msg += '/*;'
                else:
                    msg += '%s/*;' % f.fullPath
                    
        if msg == '':
            msg = 'All files can be accessed with permission %s' % mode
            
        self.queryResultTextEdit.appendPlainText('[query 8]files which cannot be accessed with mode (%s)' % mode)
        self.queryResultTextEdit.appendPlainText(msg)
        self.queryResultTextEdit.appendPlainText('\n')
        
    def runQuery9(self, domain, filename):
        '''
        Resulting type of a file created from a domain
        '''
        edge = EdgeItem(-1, None, None)
        defaultType = None
        TypeNode.counter -= 1
        for item in self.scene.items():
            if isinstance(item, DomainNode):
                if item.name == domain:
                    for e in item.edgeList:
                        if isinstance(e.endItem, TypeNode):
                            if 'c' in e.description:
                                defaultType = e.endItem
                                edge = e
                                break
                    break
        fileNode = self.findFileType(filename)
        if fileNode:
            fileType = fileNode.type
        else:
            fileType = None
        
        # first check if domain has write access to fileType
        success = False
        for e in item.edgeList:
            if e.endItem is fileType:
                if 'w' in e.description:
                    success = True
        staticFlagFound = False    
        if success:
            if defaultType is not None:
                if fileType is not defaultType:
                    if fileNode.flag == 1 or fileNode.flag == 3:
                        staticFlagFound = True
        if self.scene.main.ui.actionView_SelfTest.isChecked():
            return success, fileType, defaultType, fileNode
        
        if self.animationEnabled:
            self.animateQuery9.emit(filename, success, item, fileType, edge, defaultType, fileNode)
            
#         self.queryResultTextEdit.appendPlainText('[query 9]Resulting type of (%s) created from domain (%s)' % (filename, domain))
        self.queryResultTextEdit.appendPlainText('[query 5]Resulting type of (%s) created from domain (%s)' % (filename, domain))
        if not success:
            self.queryResultTextEdit.appendPlainText('Domain %s does not have write access to type %s' % (domain, fileType.name))
        else:
            if defaultType is None or fileType is defaultType:
                self.queryResultTextEdit.appendPlainText(fileType.name)
            else:
                if staticFlagFound:
                    self.queryResultTextEdit.appendPlainText(fileType.name)
                else:
                    self.queryResultTextEdit.appendPlainText(defaultType.name)
        self.queryResultTextEdit.appendPlainText('\n')

    def analyzeEntryPoints(self, entryPoints):
        components = string.count(entryPoints, '}')
        if components == 0:
            files = set([string.strip(f) for f in string.split(entryPoints, ',')])
            return files
        else:
            entryPoints = string.strip(entryPoints)
            files = set()
            while True:
                commaIndex = string.find(entryPoints, ',')
                leftBraceIndex = string.find(entryPoints, '{')
                if commaIndex < leftBraceIndex:
                    files.add(string.lstrip(entryPoints[0:commaIndex]))
                    entryPoints = string.lstrip(entryPoints[commaIndex+1:])
                    continue

                rightBraceIndex = string.find(entryPoints, '}', leftBraceIndex)
                prefix = entryPoints[0:leftBraceIndex]
                subcomponents = string.split(entryPoints[leftBraceIndex+1:rightBraceIndex], ',')
                for f in subcomponents:
                    files.add(prefix+f)

                entryPoints = string.lstrip(entryPoints[rightBraceIndex+1:])
                if entryPoints == '':
                    break
                else:
                    entryPoints = string.lstrip(entryPoints[1:])
            return files
                
            
        
    def runQuery10(self, domain, filename):
        '''result of executing a binary from a domain'''
        typef = self.findFileType(filename).type
        success = False
        files = None
        resultingDomainsSet = set()
        edge = EdgeItem(-1, None, None)

        for item in self.scene.items():
            if isinstance(item, DomainNode):
                if item.name == domain:
                    domainNode = item
        found = False
        for e in domainNode.edgeList:
            if e.startItem is domainNode and e.type == EdgeItem.AUTO_CONN:
                files = self.analyzeEntryPoints(str(e.description))
                if filename in files:
                    success = True
                    edge = e
                    resultingDomainsSet.add(e.endItem)
                    found = True
            elif e.startItem is domainNode and e.type == EdgeItem.EXEC_CONN:
                files = self.analyzeEntryPoints(str(e.description))
                if filename in files:
                    success = True
                    edge = e
                    resultingDomainsSet.add(e.endItem)
                    found = True
        if not found:            
            for e in domainNode.edgeList:
                if e.endItem is typef:
                    if 'x' in e.description:
                        success = True
                        edge = e
                        resultingDomainsSet.add(domainNode)
                        break
        resultingDomains = list(resultingDomainsSet)
        if self.scene.main.ui.actionView_SelfTest.isChecked():
            return filename, success, domainNode, typef, edge, resultingDomains, files
        if self.animationEnabled:
            self.animateQuery10.emit(filename, success, domainNode, typef, edge, resultingDomains)
#         self.queryResultTextEdit.appendPlainText('[query 10]result of executing binary (%s) from domain (%s)' % (filename, domain))
        self.queryResultTextEdit.appendPlainText('[query 6]result of executing binary (%s) from domain (%s)' % (filename, domain))
        if success:
            if edge.type == EdgeItem.TYPE_CONN:
                self.queryResultTextEdit.appendPlainText('Success and the resulting domain is %s' % domain)
            elif edge.type == EdgeItem.AUTO_CONN:
                self.queryResultTextEdit.appendPlainText('Success and the resulting domain is %s' % str(edge.endItem.name))
            elif edge.type == EdgeItem.EXEC_CONN:
                self.queryResultTextEdit.appendPlainText('Success and the resulting domain could be one of %s' % str([str(d.name) for d in resultingDomains]))
        else:
            self.queryResultTextEdit.appendPlainText('Failure')
        self.queryResultTextEdit.appendPlainText('\n')                
        
    def runQuery(self):
        paras = []
        current = self.ui.queryListWidget.currentRow()
        if current == 0:
            filename = string.strip(str(self.ui.file1LineEdit.text()))
            if not self.validFileName(filename):
                QMessageBox.critical(self, 'Error', 
                                     '%s is not a valid file name' % filename)
                return
            paras = [filename]
            self.runQuery0(filename)
#             
#         elif current == 1:
#             filename = string.strip(str(self.ui.file1LineEdit.text()))
#             if not self.validFileName(filename):
#                 QMessageBox.critical(self, 'Error', 
#                                      '%s is not a valid file name' % filename)
#                 return
#             paras = [filename]
#             self.runQuery1(filename)
#             
#         elif current == 2:
#             filename = string.strip(str(self.ui.file1LineEdit.text()))
#             if not self.validFileName(filename):
#                 QMessageBox.critical(self, 'Error', 
#                                      '%s is not a valid file name' % filename)
#                 return
#             mode = str(self.ui.accessModeComboBox.currentText())[0]
#             paras = [filename, mode]
#             self.runQuery2(filename, mode)
#             
#         elif current == 3:
#             domain = str(self.ui.domainComboBox.currentText())
#             mode = str(self.ui.accessModeComboBox.currentText())[0]
#             paras = [domain, mode]
#             self.runQuery3(domain, mode)
            
        elif current == 1:#4:
            #QMessageBox.information(self, 'Information', 'This query question is under construction!')
            filename1 = string.strip(str(self.ui.file1LineEdit.text()))
            if not self.validFileName(filename1):
                QMessageBox.critical(self, 'Error', 
                                     '%s is not a valid file name' % filename1)
                return
            filename2 = string.strip(str(self.ui.file2LineEdit.text()))
            if not self.validFileName(filename2):
                QMessageBox.critical(self, 'Error', 
                                     '%s is not a valid file name' % filename2)
                return
            mode = str(self.ui.accessModeComboBox.currentText())[0]
            paras = [filename1, filename2, mode]
            self.runQuery4(filename1, filename2, mode)
            
        elif current == 2:#5:
            filename = string.strip(str(self.ui.file1LineEdit.text()))
            if not self.validFileName(filename):
                QMessageBox.critical(self, 'Error',
                                     '%s is not a valid file name' % filename)
                return
            paras = [filename]
            self.runQuery5(filename)            
            
        elif current == 3:#6:
            filename = string.strip(str(self.ui.file1LineEdit.text()))
            if not self.validFileName(filename):
                QMessageBox.critical(self, 'Error',
                                     '%s is not a valid file name' % filename)
                return
            mode = str(self.ui.accessModeComboBox.currentText())[0]
            paras = [filename, mode]
            self.runQuery6(filename, mode)
            
        elif current == 4:#7:
            self.runQuery7()
            
#         elif current == 8:
#             mode = str(self.ui.accessModeComboBox.currentText())[0]
#             paras = [mode]
#             self.runQuery8(mode)
            
        elif current == 5:#9:
            filename = string.strip(str(self.ui.file1LineEdit.text()))
            if not self.validFileName(filename):
                QMessageBox.critical(self, 'Error',
                                     '%s is not a valid file name' % filename)
                return
            domain = str(self.ui.domainComboBox.currentText())
            paras = [domain, filename]
            self.runQuery9(domain, filename)
            
        elif current == 6:#10:
            filename = string.strip(str(self.ui.file1LineEdit.text()))
            if not self.validFileName(filename):
                QMessageBox.critical(self, 'Error',
                                     '%s is not a valid file name' % filename)
                return
            domain = str(self.ui.domainComboBox.currentText())
            paras = [filename]
            self.runQuery10(domain, filename)
        paraString = " with parameters "+', ' .join(paras)
        if paras!= []:
            self.scene.main.writeToFile(self.scene.main.logFile, self.scene.main.getCurrentTimeString()+\
                                    "Run Query "+str(current)+paraString+'\n')
        else:
            self.scene.main.writeToFile(self.scene.main.logFile, self.scene.main.getCurrentTimeString()+\
                                    "Run Query "+str(current)+'\n')

            
            
                            

                        
            
            

        
    

        