Пример #1
0
def ProcessAppFile(appFile):
    """
    Process the Application File returning the appinfo and the command
    dictionary.
    """
    commands = dict()
    
    # Read in .app file
    appInfo = LoadConfig(appFile)

    # Build command list
    for key in appInfo.keys():
        spList = key.split('.')
        if len(spList) > 1:
            (section, option) = spList
            if section == "commands":
                verb = option
                cmd = appInfo[key]
                # If the named argument python is used, replace it
                if cmd.find("%(python)s") != -1:
                    if sys.platform == 'darwin':
                        cmd = cmd.replace("%(python)s", '/usr/bin/pythonw')
                    else:
                        cmd = cmd.replace("%(python)s", sys.executable)
                commands[verb] = cmd
    return appInfo, commands
Пример #2
0
def ProcessAppFile(appFile):
    """
    Process the Application File returning the appinfo and the command
    dictionary.
    """
    commands = dict()

    # Read in .app file
    appInfo = LoadConfig(appFile)

    # Build command list
    for key in appInfo.keys():
        spList = key.split('.')
        if len(spList) > 1:
            (section, option) = spList
            if section == "commands":
                verb = option
                cmd = appInfo[key]
                # If the named argument python is used, replace it
                if cmd.find("%(python)s") != -1:
                    if sys.platform == 'darwin':
                        cmd = cmd.replace("%(python)s", '/usr/bin/pythonw')
                    else:
                        cmd = cmd.replace("%(python)s", sys.executable)
                commands[verb] = cmd
    return appInfo, commands
Пример #3
0
    def LoadPreferences(self):
        '''
        Read preferences from configuration file.
        '''
        try:
            log.debug("Preferences.LoadPreferences: open file")
            preferences = LoadConfig(self.config.GetPreferences())

            # Remove category from preference
            for p in preferences.keys():
                category = p.split(".")[0]
                pref = p.split(".")[1]

                if category == "Preferences":
                    self.preferences[pref] = preferences[p]

            # Add any default preferences that are missing
            for key in self.default:
                if not self.preferences.has_key(key):
                    
                    # set the initial value of the proxy enabled preference based on whether
                    # the user has specified a proxy host previously
                    # note:  this only happens the first time a preferences file is loaded that
                    # is missing the PROXY_ENABLED preference
                    if key == self.PROXY_ENABLED:
                        if self.preferences.has_key(self.PROXY_HOST) and len(self.preferences[self.PROXY_HOST]) > 0:
                            self.preferences[key] = 1
                            continue
                    self.preferences[key] = self.default[key]
             
        except:
            log.exception("Preferences.LoadPreferences: open file error")
            self.preferences = {}
                
        # Load client profile separately
        try:
            profileFile = os.path.join(self.config.GetConfigDir(),
                                       "profile" )
            self.profile = ClientProfile(profileFile)
                   
        except IOError:
            log.exception("Preferences.LoadPreferences: open file io error")

        # Load bridges separately
        for b in self.bridgeCache.GetBridges():
            self.__bridges[b.GetKey()] = b
    def LoadPreferences(self):
        '''
        Read preferences from configuration file.
        '''
        try:
            log.debug("Preferences.LoadPreferences: open file")
            preferences = LoadConfig(self.config.GetPreferences())

            # Remove category from preference
            for p in preferences.keys():
                category = p.split(".")[0]
                pref = p.split(".")[1]

                if category == "Preferences":
                    self.preferences[pref] = preferences[p]

            # Add any default preferences that are missing
            for key in self.default:
                if not self.preferences.has_key(key):

                    # set the initial value of the proxy enabled preference based on whether
                    # the user has specified a proxy host previously
                    # note:  this only happens the first time a preferences file is loaded that
                    # is missing the PROXY_ENABLED preference
                    if key == self.PROXY_ENABLED:
                        if self.preferences.has_key(self.PROXY_HOST) and len(
                                self.preferences[self.PROXY_HOST]) > 0:
                            self.preferences[key] = 1
                            continue
                    self.preferences[key] = self.default[key]

        except:
            log.exception("Preferences.LoadPreferences: open file error")
            self.preferences = {}

        # Load client profile separately
        try:
            profileFile = os.path.join(self.config.GetConfigDir(), "profile")
            self.profile = ClientProfile(profileFile)

        except IOError:
            log.exception("Preferences.LoadPreferences: open file io error")

        # Load bridges separately
        for b in self.bridgeCache.GetBridges():
            self.__bridges[b.GetKey()] = b
Пример #5
0
    def GetBridges(self):
        # Get bridges from the local config directory
        self.bridges = []
        bridges = {}

        if os.path.exists(self.configPath):
            config = LoadConfig(self.config.GetBridges())
        else:
            # Cache does not exist, return
            return self.bridges

        # Parse config dict and create bridge descriptions
        for key in config.keys():
            bridgeid = key.split(".")[0]
            val = key.split(".")[1]

            if not bridges.has_key(bridgeid):
                bridges[bridgeid] = BridgeDescription(bridgeid, "", "", "", "",
                                                      "")

            if val == "name":
                bridges[bridgeid].name = config[key]
            elif val == "host":
                bridges[bridgeid].host = config[key]
            elif val == "port":
                bridges[bridgeid].port = config[key]
            elif val == "serverType":
                bridges[bridgeid].serverType = config[key]
            elif val == "description":
                bridges[bridgeid].description = config[key]
            elif val == "status":
                bridges[bridgeid].status = config[key]
            elif val == "rank":
                bridges[bridgeid].rank = float(config[key])
            elif val == "portMin":
                bridges[bridgeid].portMin = int(config[key])
            elif val == "portMax":
                bridges[bridgeid].portMax = int(config[key])
            elif val == "userRank":
                bridges[bridgeid].userRank = float(config[key])

        for b in bridges.values():
            self.bridges.append(b)

        return self.bridges
Пример #6
0
    def GetBridges(self):
        # Get bridges from the local config directory
        self.bridges = []
        bridges = {}
       
        if os.path.exists(self.configPath):
            config = LoadConfig(self.config.GetBridges())
        else:
            # Cache does not exist, return
            return self.bridges
        
        # Parse config dict and create bridge descriptions
        for key in config.keys():
            bridgeid = key.split(".")[0]
            val = key.split(".")[1]

            if not bridges.has_key(bridgeid):
                bridges[bridgeid] = BridgeDescription(bridgeid, "", "", "", "", "")
                         
            if val == "name":
                bridges[bridgeid].name = config[key]
            elif val == "host":
                bridges[bridgeid].host = config[key]
            elif val == "port":
                bridges[bridgeid].port = config[key]
            elif val == "serverType":
                bridges[bridgeid].serverType = config[key]
            elif val == "description":
                bridges[bridgeid].description = config[key]
            elif val == "status":
                bridges[bridgeid].status = config[key]
            elif val == "rank":
                bridges[bridgeid].rank = float(config[key])
            elif val == "portMin":
                bridges[bridgeid].portMin = int(config[key])
            elif val == "portMax":
                bridges[bridgeid].portMax = int(config[key])
            elif val == "userRank":
                bridges[bridgeid].userRank = float(config[key])

        for b in bridges.values():
            self.bridges.append(b)
        
        return self.bridges
Пример #7
0
class AppDb:
    """
    The AppDb class provides an interface for the Toolkit to store
    information on a per user basis about what applications are
    installed and how to run them.
    """
    defaultSeparator = ":"

    def __init__(self, path=None, filename="ApplicationDatabase"):
        """
        The constructor for the AppDb, it uses a file for persistent storage.
        """
        self.AppDb = dict()

        if path is None:
            self.path = UserConfig.instance().GetConfigDir()
        else:
            self.path = path

        self.fileName = os.path.join(self.path, filename)

        # Create the file if it doesn't exist
        if not os.path.exists(self.fileName):
            try:
                file(self.fileName,'w').close()
            except:
                log.exception("Couldn't create app db file %s", self.fileName)

        self.Load(self.fileName)

    def Load(self, fileName=None):
        """
        Load the app db from the file it's stored in.
        """
        if fileName == None:
            fileName = self.fileName
            
        try:
            self.AppDb = LoadConfig(fileName, separator=self.defaultSeparator)

            # update the file modification time
            self._UpdateModTime()
        except:
            print sys.exc_info()
            print "Couldn't open application database: %s" % fileName
            

    def _Synch(self):
        """
        Synch the in-memory app db with the file, if necessary
        """
        if os.access(self.fileName,os.R_OK):
            fileLastModified = os.stat(self.fileName)[stat.ST_MTIME]
            if fileLastModified > self.fileLastModified:
                self.Load()
            
    def _UpdateModTime(self):
        """
        Update the last modified time of the appdb file
        """
        if os.access(self.fileName,os.R_OK):
            # store the file modification time
            self.fileLastModified = os.stat(self.fileName)[stat.ST_MTIME]

    def _Flush(self):
        """
        Flush the current db out to file storage.
        """
        try:
            SaveConfig(self.fileName, self.AppDb, self.defaultSeparator)

            # update the file modification time
            self._UpdateModTime()
        except:
            print "Couldn't flush the db to disk."

    def _GetPrivName(self, name):
        """
        Look up the private name for the exposed name.

        returns name as string or None
        """
        pname = None
        for key in self.AppDb.keys():
            (section, option) = key.split(self.defaultSeparator)
            if section == "priv_names":
                if self.AppDb[key] == name:
                    pname = option
        return pname

    def _GetNiceName(self, pName):
        """
        Get a user friendly name for a private name.
        """
        for key in self.AppDb.keys():
            (section, option) = key.split(self.defaultSeparator)
            if section == "priv_names":
                if option == pName:
                    return self.AppDb[key]
        return None

    def _GetPrivVerb(self, verb, mimeType):
        """
        Look up the private verb for the exposed verb.
        """
        pVerb = None

        for key in self.AppDb.keys():
            (section, option) = key.split(self.defaultSeparator)
            if section == "priv_cmds":
                mtCheckKey = self.defaultSeparator.join([mimeType, option])
                if self.AppDb[key] == verb and self.AppDb.has_key(mtCheckKey):
                    pVerb = option

        return pVerb

    def _GetNiceVerb(self, pVerb):
        """
        Get a user friendly name for a private verb.
        """
        for key in self.AppDb.keys():
            (section, option) = key.split(self.defaultSeparator)
            if section == "priv_cmds":
                if option == pVerb:
                    return self.AppDb[key]
        return None

    def GetMimeType(self, name = None, extension = None):
        """
        Find a mimetype for the specified app name or extension.

        returns a mimeType in a string.
        """
        # Ensure that we're in synch with the on-disk appdb
        self._Synch()
        
        mimeType = None

        if name != None:
            privName = self._GetPrivName(name)
            if privName == None:
                return mimeType

            lookupName = self.defaultSeparator.join(["name", privName])

            try:
                mimeType = self.AppDb[lookupName]
            except KeyError:
                mimeType = None

        if extension != None:
            lookupExt = self.defaultSeparator.join(["extension", extension])
            try:
                mimeType = self.AppDb[lookupExt]
            except KeyError:
                mimeType = None

        return mimeType

    def GetNameForMimeType(self, mimeType):
        """
        returns a name in a string.
        """
        # Ensure that we're in synch with the on-disk appdb
        self._Synch()
        
        appName = None

        for key in self.AppDb.keys():
            (section, option) = key.split(self.defaultSeparator)
            if section == "name":
                mt = self.AppDb[key]
                if mt == mimeType:
                    appName = self._GetNiceName(option)

        return appName

    def GetExtForMimeType(self, mimeType):
        """
        returns a extension in a string.
        """
        # Ensure that we're in synch with the on-disk appdb
        self._Synch()
        
        ext = None

        for key in self.AppDb.keys():
            (section, option) = key.split(self.defaultSeparator)
            if section == "extension":
                mt = self.AppDb[key]
                if mt == mimeType:
                    ext = option

        return ext

    def AddMimeType(self, name, extension, mimeType, startable="1"):
        """
        returns a tuple of (int, string). Success is (1, mimeType),
        failure is (0, reason)
        """

        # Ensure that we're in synch with the on-disk appdb
        self._Synch()

        namekey = self._GetPrivName(name)
        if namekey == None:
            namekey = str(GUID())

        privName = self.defaultSeparator.join(["priv_names", namekey])
        nameStr = self.defaultSeparator.join(["name", namekey])
        extStr = self.defaultSeparator.join(["extension", extension])
        mimeStr = self.defaultSeparator.join([mimeType, "None"])
        startableStr = self.defaultSeparator.join(["startable", mimeType])

        self.AppDb[privName] = name
        self.AppDb[nameStr] = mimeType
        self.AppDb[extStr] = mimeType
        self.AppDb[mimeStr] = None
        self.AppDb[startableStr] = startable

        self._Flush()

        return (1, mimeType)

    def RemoveMimeType(self, name = None, extension = None, mimeType = None):
        """
        returns a tuple of (int, string). Success is (1, mimeType),
        failure is (0, reason)
        """

        # Ensure that we're in synch with the on-disk appdb
        self._Synch()

        if name == None and extension == None and mimeType == None:
            return (0, "Not enough information to remove mime type.")

        privName = None
        nameStr = None
        extStr = None
        mimeStr = None

        if name != None and self._GetPrivName(name) != None:
            namekey = self._GetPrivName(name)
            privName = self.defaultSeparator.join(["priv_names", namekey])
            name = self.AppDb[privName]
            mt = self.GetMimeType(name = name)
            mimeStr = self.defaultSeparator.join([mt, "None"])
            nameStr = self.defaultSeparator.join(["name", namekey])
            ext = self.GetExtForMimeType(mt)
            extStr = self.defaultSeparator.join(["extension", ext])
        elif mimeType != None and self.GetNameForMimeType(mimeType) != None:
            mimeStr = self.defaultSeparator.join([mimeType, "None"])
            name = self.GetNameForMimeType(mimeType)
            namekey = self._GetPrivName(name)
            privName = self.defaultSeparator.join(["priv_names", namekey])
            nameStr = self.defaultSeparator.join(["name", namekey])
            ext = self.GetExtForMimeType(mimeType)
            extStr = self.defaultSeparator.join(["extension", ext])
        elif extension != None and None != self.GetNameForMimeType(self.GetMimeType(extension=extension)):
            mimeType = self.GetMimeType(extension = extension)
            mimeStr = self.defaultSeparator.join([mimeType, "None"])
            name = self.GetNameForMimeType(mimeType)
            namekey = self._GetPrivName(name)
            privName = self.defaultSeparator.join(["priv_names", namekey])
            nameStr = self.defaultSeparator.join(["name", namekey])
            ext = self.GetExtForMimeType(mimeType)
            extStr = self.defaultSeparator.join(["extension", extension])

        if privName != None:
            if self.AppDb.has_key(privName):
                del self.AppDb[privName]

        if nameStr != None:
            if self.AppDb.has_key(nameStr):
                del self.AppDb[nameStr]

        if extStr != None:
            if self.AppDb.has_key(extStr):
                del self.AppDb[extStr]

        if mimeStr != None:
            if self.AppDb.has_key(mimeStr):
                del self.AppDb[mimeStr]

        self._Flush()

        return (1, mimeType)

    def GetCommandNames(self, mimeType):
        """
        returns a list of command names for this mime type.
        """
        # Ensure that we're in synch with the on-disk appdb
        self._Synch()

        cmds = list()

        for key in self.AppDb.keys():
            (section, option) = key.split(self.defaultSeparator)
            if section == mimeType:
                nName = self._GetNiceVerb(option)
                if nName != None:
                    cmds.append(nName)

        return cmds

    def GetCommands(self, mimeType):
        """
        returns a dict of [commandname:command] for this mimetype
        """
        # Ensure that we're in synch with the on-disk appdb
        self._Synch()

        cmds = dict()

        for key in self.AppDb.keys():
            (section, option) = key.split(self.defaultSeparator)
            if section == mimeType:
                nName = self._GetNiceVerb(option)
                if nName != None:
                    cmds[nName] = self.GetCommandLine(mimeType,nName)

        return cmds

    def GetCommandLine(self, mimeType, cmdName, vars=None):
        """
        returns a string containing the commandline used to execute the viewer,
        optionally if vars is a dictionary, of name = value, named parameter
        substitution is done for the command line.
        """
        # Ensure that we're in synch with the on-disk appdb
        self._Synch()

        cmdStr = ""

        if mimeType == None or cmdName == None:
            return cmdStr

        pCmd = self._GetPrivVerb(cmdName, mimeType)
        if pCmd != None:
            key = self.defaultSeparator.join([mimeType, pCmd])
        else:
            return cmdStr

        try:
            cmdStr = self.AppDb[key]
        except KeyError:
            return cmdStr

        if vars != None:
            cmdStr = self.AppDb[key] % vars

        return cmdStr

    def AddCommand(self, mimeType, cmdName, cmdString):
        """
        returns a tuple (int, string). Success is (1, cmdName),
        failure is (0, reason).
        """

        # Ensure that we're in synch with the on-disk appdb
        self._Synch()

        pCmd = self._GetPrivVerb(cmdName, mimeType)
        if pCmd == None:
            pCmd = str(GUID())
        cmdkey = self.defaultSeparator.join([mimeType, pCmd])
        pcmdkey = self.defaultSeparator.join(["priv_cmds", pCmd])

        self.AppDb[cmdkey] = cmdString
        self.AppDb[pcmdkey] = cmdName

        self._Flush()

        return (1, cmdName)

    def RemoveCommand(self, mimeType, cmdName):
        """
        returns a tuple (int, string). Success is (1, cmdName),
        failure is (0, reason).
        """

        # Ensure that we're in synch with the on-disk appdb
        self._Synch()

        pCmd = self._GetPrivVerb(cmdName, mimeType)
        cmdkey = self.defaultSeparator.join([mimeType, pCmd])
        if self.AppDb.has_key(cmdkey):
            del self.AppDb[cmdkey]
            
        pcmdkey = self.defaultSeparator.join(["priv_cmds", pCmd])
        if self.AppDb.has_key(pcmdkey):
            del self.AppDb[pcmdkey]

        self._Flush()

        return (1, cmdName)

    def RegisterApplication(self, name, mimeType, extension, commandDict,
                            fileList, srcPath, dstPath, startable="1"):
        """
        Encapsulate all the actions required to register a new application.
        returns 0 on failure, 1 on success
        """

        (ret, retStr) = self.AddMimeType(name, extension, mimeType, startable)

        if ret:
            for cmdName in commandDict.keys():
                cmdStr = commandDict[cmdName]
                (result, resultString) = self.AddCommand(mimeType, cmdName,
                cmdStr)
                if not result:
                    return 0

            noSpaceName = '_'.join(name.split(' '))
            dstPath = os.path.join(dstPath, noSpaceName)

            if not os.path.exists(dstPath):
                try:
                    os.mkdir(dstPath)
                except:
                    print "Couldn't make app directory (%s)." % dstPath

            success = 0
            for appFile in fileList:
                try:
                    srcf = os.path.join(srcPath, appFile)
                    dstf = os.path.join(dstPath, appFile)

                    # Create any destination subdirs
                    dstd = os.path.dirname(dstf)
                    if not os.path.exists(dstd):
                        os.makedirs(dstd)

                    shutil.copy(srcf, dstf)
                    success = 1
                                    
                except:
                    print "Couldn't copy file into place (undoing register)."
                    self.UnregisterApplication(name=name,mimeType=mimeType)
            
        else:
            return 0

        self._Flush()

        return 1

    def ListApplications(self):
        """
        """
        # Ensure that we're in synch with the on-disk appdb
        self._Synch()

        apps = list()

        for key in self.AppDb.keys():
            (section, option) = key.split(self.defaultSeparator)
            if section == 'name':
                name = self._GetNiceName(option)
                if name:
                    apps.append(name)

        return apps

    def ListMimeTypes(self):
        """
        """
        # Ensure that we're in synch with the on-disk appdb
        self._Synch()

        mt = list()

        for key in self.AppDb.keys():
            try:
                (section, option) = key.split(self.defaultSeparator)
            except ValueError:
                continue

            if section != 'name' and section != 'extension':
                mt.append(option)

        return mt

    def ListAppsAsAppDescriptions(self):
        """
        """
        # Ensure that we're in synch with the on-disk appdb
        self._Synch()

        apps = list()

        for key in self.AppDb.keys():
            try:
                (section, option) = key.split(self.defaultSeparator)
            except ValueError:
                continue
            if section == 'name':
                name = self._GetNiceName(option)
                if name:
                    mimetype = self.AppDb[key]
                    startableStr = self.defaultSeparator.join(["startable", mimetype])
                    if startableStr in self.AppDb.keys():
                        startable = self.AppDb[startableStr]
                    else:
                        startable = 1
                    apps.append(ApplicationDescription(None, name, None, None, mimetype, startable))

        return apps

    def UnregisterApplication(self, name=None, mimeType=None, extension=None):
        """
        Encapsulate all the actions required to unregister an application.
        returns 0 on failure, 1 on success
        """

        noSpaceName = '_'.join(name.split(' '))
        dstPath = os.path.join(UserConfig.instance().GetSharedAppDir(), 
                               noSpaceName)

        if os.path.exists(dstPath):
            try:
                shutil.rmtree(dstPath)
                print "Unregistration of application %s complete" % (name)
            except:
                print "App directory error -- can't remove (%s)." % dstPath
        else:
            print "Application %s not found; skipping" % (name)
            return 0


        if mimeType == None:
            mimeType = self.GetMimeType(name, extension)

        if mimeType == None:
            print "MimeType: %s not found." % mimeType
            return 0
        
        cmdList = self.GetCommandNames(mimeType)

        (ret, retStr) = self.RemoveMimeType(name, extension, mimeType)
        if ret:
            for cmdName in cmdList:
                (result, resultString) = self.RemoveCommand(mimeType,
                                                            cmdName)
                if not result:
                    print "Error removing verb, continuing."
                    
        return 1
Пример #8
0
class ClientProfile:
    """
    The client profile is used to represent the clients throughout the AG.
    The client profile is all public data, however only the author of the
    profile is allowed to modify it.
    """

    configSection = 'ClientProfile'
    
    defaultProfile = {
        'ClientProfile.type' : "user",
        'ClientProfile.name' : '<Insert Name Here>',
        'ClientProfile.email' : '<Insert Email Address Here>',
        'ClientProfile.phone' : '<Insert Phone Number Here>',
        'ClientProfile.icon' : '<Leave blank for now>',
        'ClientProfile.id' : '',
        'ClientProfile.location' : '<Insert Postal Address Here>',
        'ClientProfile.techsupportinfo':'',
        'ClientProfile.venueclienturl' : '',
        'ClientProfile.home' : 'https://vv3.mcs.anl.gov:8000/Venues/default',
        'ClientProfile.gmtoffset' : 0,
        'ClientProfile.beacon' : 0,
        'ClientProfile.video' : 0,
        'ClientProfile.audio' : 0,
        'ClientProfile.display' : 0,
        'ClientProfile.lat' : 0,
        'ClientProfile.long' : 0,
        }

    USER = "******"
    NODE = "node"
    
    def __init__(self, profileFile = None):
        """ """
        self.profileFile = profileFile
        self.profileType = ''
        self.name = ''
        self.email = ''
        self.phoneNumber = ''
        self.icon = None
        self.publicId = str(GUID())
        self.location = ''
        self.venueClientURL = ''
        self.homeVenue = ''
        self.privateId = ''
        self.distinguishedName = ''
        self.techSupportInfo = ''
        self.connectionId = ''
        if time.daylight:
            self.gmtoffset = time.altzone
        else:
            self.gmtoffset = time.timezone
        self.beacon = 0
        self.video = self.audio = self.display = 0
        self.lat = self.long = 0

        if profileFile != None and os.path.exists(profileFile):
            self.Load(self.profileFile)
        else:
            self.profile = ClientProfile.defaultProfile.copy()
            self.profile['ClientProfile.id'] = self.publicId
            self._SetFromConfig() # Get the values from the config

    def Load(self, fileName, loadDnDetails=0):
        """
        loadDnDetails is used by the cache to include the reading
          of a DN when reading from the stored profile.
        """
        profile = ClientProfile.defaultProfile.copy()
        self.profile = LoadConfig(fileName, profile)

        self._SetFromConfig() # Get the values from the config

        if loadDnDetails: # DN used with profileCache, not in standard profile.
            if 'ClientProfile.distinguishedname' in self.profile:
                self.distinguishedName = self.profile['ClientProfile.distinguishedname']

    def _SetFromConfig(self):
        if self.CheckProfile():
            self.profileType = self.profile['ClientProfile.type']
            self.name = self.profile['ClientProfile.name']
            self.email = self.profile['ClientProfile.email']
            self.phoneNumber = self.profile['ClientProfile.phone']
            self.icon = self.profile['ClientProfile.icon']
            self.publicId = self.profile['ClientProfile.id']
            self.location = self.profile['ClientProfile.location']
            self.venueClientURL = self.profile['ClientProfile.venueclienturl']
            self.homeVenue = self.profile['ClientProfile.home']
            self.techSupportInfo = self.profile['ClientProfile.techsupportinfo']
        else:
            raise InvalidProfileException

    def Dump(self):
        """
        """
        print "Profile: "
        for k in self.profile.keys():
            print "Key: %s Value: %s" % (k, self.profile[k])
        print "Profile Type: " + self.profileType
        print "Name: " + self.name
        print "Email: " + self.email
        print "Phone Number: " + self.phoneNumber
        print "Location: " + self.location
        print "Venue Client URL: " + self.venueClientURL
        print "Public ID: " + str(self.publicId)
        print "Home Venue: " + self.homeVenue
        print "Beacon: " + str(self.beacon)
        print "Audio: " + str(self.audio)
        print "Display: " + str(self.display)
        print "Video: " + str(self.video)
        print "Location: " + str(self.lat) + " " + str(self.long)

    def __str__(self):
        returnVal =  " Profile Type: " + self.profileType \
                    + "\n Name: " + self.name \
                    + "\n Email: " + self.email\
                    + "\n Phone Number: " + self.phoneNumber\
                    + "\n Location: " + self.location\
                    + "\n Venue Client URL: " + self.venueClientURL\
                    + "\n Public ID: " + str(self.publicId)\
                    + "\n Home Venue: " + self.homeVenue

        return returnVal
        
    def Save(self, fileName, saveDnDetails=0):
        """
        saveDnDetails is used by the cache to include the DN
          in the stored profile.
        """
        config = {}
        config['ClientProfile.type'] = self.GetProfileType()
        config['ClientProfile.name'] = self.GetName()
        config['ClientProfile.email'] = self.GetEmail()
        config['ClientProfile.phone'] = self.GetPhoneNumber()
        config['ClientProfile.location'] = self.GetLocation()
        config['ClientProfile.venueclienturl'] = self.GetVenueClientURL()
        config['ClientProfile.id'] = self.GetPublicId()
        config['ClientProfile.home'] = self.GetHomeVenue()
       
        if saveDnDetails:
            config['ClientProfile.distinguishedname'] = self.GetDistinguishedName()
        
        SaveConfig(fileName, config)

    def IsDefault(self):
        sc = self.profile.copy()
        sc['ClientProfile.id'] = ''
        
        if sc == ClientProfile.defaultProfile:
            return 1
        else:
            return 0

    def CheckProfile(self):
        for x in self.profile.keys():
            (section, option) = string.split(x, '.')
            if (section != ClientProfile.configSection and
                section != string.lower(ClientProfile.configSection)):
                log.error('ClientProfile.CheckProfile: Check profile failed for section: %s option: %s'%(section, option))
                return 0
        return 1
    
    def SetProfileType(self, profileType):
        """ """
        self.profileType = profileType
        self.profile[ClientProfile.configSection + '.type'] = profileType
        
    def GetProfileType(self):
        """ """
        return self.profileType
    
    def SetLocation(self, location):
        """ """
        self.location = location
        self.profile[ClientProfile.configSection + '.location'] = location
    
    def GetLocation(self):
        """ """
        return self.location
    
    def SetEmail(self, email):
        """ """
        self.email = email
        self.profile[ClientProfile.configSection + '.email'] = email
    
    def GetEmail(self):
        """ """
        return self.email
    
    def SetName(self, name):
        """ """
        self.name = name
        self.profile[ClientProfile.configSection + '.name'] = name
        
    def GetName(self):
        """ """
        return self.name

    def GetDistinguishedName(self):
        """ """
        return self.distinguishedName

    def SetPhoneNumber(self, phoneNumber):
        """ """
        self.phoneNumber = phoneNumber
        self.profile[ClientProfile.configSection + '.phone'] = phoneNumber
        
    def GetPhoneNumber(self):
        """ """
        return self.phoneNumber
    
    def SetVenueClientURL(self, venueClientURL):
        """ """
        self.venueClientURL = venueClientURL
        self.profile[ClientProfile.configSection + '.venueclienturl'] = venueClientURL
    
    def GetVenueClientURL(self):
        """ """
        return self.venueClientURL
    
    def SetPublicId(self, publicId):
        """ """
        self.publicId = publicId
        self.profile[ClientProfile.configSection + '.id'] = publicId
        
    def GetPublicId(self):
        """ """
        return self.publicId

    def SetHomeVenue(self, venue):
        self.homeVenue = venue
        self.profile[ClientProfile.configSection + '.home'] = venue

    def GetHomeVenue(self):
        return self.homeVenue
        
    def GetGmtOffset(self):
        return self.gmtoffset
        
    def GetBeaconState(self):
        return self.beacon
        
    def GetVideoState(self):
        return self.video
        
    def GetAudioState(self):
        return self.audio
        
    def GetDisplayState(self):
        return self.display
    
    def GetLat(self):
        return self.lat
        
    def GetLong(self):
        return self.long

    def InformationMatches(self, obj):
        """
        return true (1) if profile information is equivalent
          return false (0) otherwise.
        This was written mostly for the ClientProfileCache to use, so
          if modifying this function keep that purpose in mind.
          Specifically, a profile should be equivalent to its cached 
          profile if the user hasn't changed his/her profile.  This means
          things such as VenueClientURL are not tested below since it can
          change after the venue client reconnects.
        """
        if not isinstance(obj, ClientProfile):
            return 0
        isSame = 0
        try:
            # members not tested for equality 
            #  self.fileType == obj.fileType
            #  self.publicId == obj.publicId
            #  self.privateId == obj.privateId
            #  self.distinguishedName == obj.distinguishedName 
            #  self.venueClientURL == obj.venueClientURL and \
            if self.profileType == obj.profileType and \
               self.name == obj.name and \
               self.email == obj.email and \
               self.phoneNumber == obj.phoneNumber and \
               self.icon == obj.icon and \
               self.location == obj.location and \
               self.homeVenue == obj.homeVenue :
                isSame = 1
        except:
            pass
        return isSame
class ClientProfile:
    """
    The client profile is used to represent the clients throughout the AG.
    The client profile is all public data, however only the author of the
    profile is allowed to modify it.
    """

    configSection = 'ClientProfile'

    defaultProfile = {
        'ClientProfile.type': "user",
        'ClientProfile.name': '<Insert Name Here>',
        'ClientProfile.email': '<Insert Email Address Here>',
        'ClientProfile.phone': '<Insert Phone Number Here>',
        'ClientProfile.icon': '<Leave blank for now>',
        'ClientProfile.id': '',
        'ClientProfile.location': '<Insert Postal Address Here>',
        'ClientProfile.techsupportinfo': '',
        'ClientProfile.venueclienturl': '',
        'ClientProfile.home': 'https://vv3.mcs.anl.gov:8000/Venues/default',
        'ClientProfile.gmtoffset': 0,
        'ClientProfile.beacon': 0,
        'ClientProfile.video': 0,
        'ClientProfile.audio': 0,
        'ClientProfile.display': 0,
        'ClientProfile.lat': 0,
        'ClientProfile.long': 0,
    }

    USER = "******"
    NODE = "node"

    def __init__(self, profileFile=None):
        """ """
        self.profileFile = profileFile
        self.profileType = ''
        self.name = ''
        self.email = ''
        self.phoneNumber = ''
        self.icon = None
        self.publicId = str(GUID())
        self.location = ''
        self.venueClientURL = ''
        self.homeVenue = ''
        self.privateId = ''
        self.distinguishedName = ''
        self.techSupportInfo = ''
        self.connectionId = ''
        if time.daylight:
            self.gmtoffset = time.altzone
        else:
            self.gmtoffset = time.timezone
        self.beacon = 0
        self.video = self.audio = self.display = 0
        self.lat = self.long = 0

        if profileFile != None and os.path.exists(profileFile):
            self.Load(self.profileFile)
        else:
            self.profile = ClientProfile.defaultProfile.copy()
            self.profile['ClientProfile.id'] = self.publicId
            self._SetFromConfig()  # Get the values from the config

    def Load(self, fileName, loadDnDetails=0):
        """
        loadDnDetails is used by the cache to include the reading
          of a DN when reading from the stored profile.
        """
        profile = ClientProfile.defaultProfile.copy()
        self.profile = LoadConfig(fileName, profile)

        self._SetFromConfig()  # Get the values from the config

        if loadDnDetails:  # DN used with profileCache, not in standard profile.
            if 'ClientProfile.distinguishedname' in self.profile:
                self.distinguishedName = self.profile[
                    'ClientProfile.distinguishedname']

    def _SetFromConfig(self):
        if self.CheckProfile():
            self.profileType = self.profile['ClientProfile.type']
            self.name = self.profile['ClientProfile.name']
            self.email = self.profile['ClientProfile.email']
            self.phoneNumber = self.profile['ClientProfile.phone']
            self.icon = self.profile['ClientProfile.icon']
            self.publicId = self.profile['ClientProfile.id']
            self.location = self.profile['ClientProfile.location']
            self.venueClientURL = self.profile['ClientProfile.venueclienturl']
            self.homeVenue = self.profile['ClientProfile.home']
            self.techSupportInfo = self.profile[
                'ClientProfile.techsupportinfo']
        else:
            raise InvalidProfileException

    def Dump(self):
        """
        """
        print "Profile: "
        for k in self.profile.keys():
            print "Key: %s Value: %s" % (k, self.profile[k])
        print "Profile Type: " + self.profileType
        print "Name: " + self.name
        print "Email: " + self.email
        print "Phone Number: " + self.phoneNumber
        print "Location: " + self.location
        print "Venue Client URL: " + self.venueClientURL
        print "Public ID: " + str(self.publicId)
        print "Home Venue: " + self.homeVenue
        print "Beacon: " + str(self.beacon)
        print "Audio: " + str(self.audio)
        print "Display: " + str(self.display)
        print "Video: " + str(self.video)
        print "Location: " + str(self.lat) + " " + str(self.long)

    def __str__(self):
        returnVal =  " Profile Type: " + self.profileType \
                    + "\n Name: " + self.name \
                    + "\n Email: " + self.email\
                    + "\n Phone Number: " + self.phoneNumber\
                    + "\n Location: " + self.location\
                    + "\n Venue Client URL: " + self.venueClientURL\
                    + "\n Public ID: " + str(self.publicId)\
                    + "\n Home Venue: " + self.homeVenue

        return returnVal

    def Save(self, fileName, saveDnDetails=0):
        """
        saveDnDetails is used by the cache to include the DN
          in the stored profile.
        """
        config = {}
        config['ClientProfile.type'] = self.GetProfileType()
        config['ClientProfile.name'] = self.GetName()
        config['ClientProfile.email'] = self.GetEmail()
        config['ClientProfile.phone'] = self.GetPhoneNumber()
        config['ClientProfile.location'] = self.GetLocation()
        config['ClientProfile.venueclienturl'] = self.GetVenueClientURL()
        config['ClientProfile.id'] = self.GetPublicId()
        config['ClientProfile.home'] = self.GetHomeVenue()

        if saveDnDetails:
            config[
                'ClientProfile.distinguishedname'] = self.GetDistinguishedName(
                )

        SaveConfig(fileName, config)

    def IsDefault(self):
        sc = self.profile.copy()
        sc['ClientProfile.id'] = ''

        if sc == ClientProfile.defaultProfile:
            return 1
        else:
            return 0

    def CheckProfile(self):
        for x in self.profile.keys():
            (section, option) = string.split(x, '.')
            if (section != ClientProfile.configSection
                    and section != string.lower(ClientProfile.configSection)):
                log.error(
                    'ClientProfile.CheckProfile: Check profile failed for section: %s option: %s'
                    % (section, option))
                return 0
        return 1

    def SetProfileType(self, profileType):
        """ """
        self.profileType = profileType
        self.profile[ClientProfile.configSection + '.type'] = profileType

    def GetProfileType(self):
        """ """
        return self.profileType

    def SetLocation(self, location):
        """ """
        self.location = location
        self.profile[ClientProfile.configSection + '.location'] = location

    def GetLocation(self):
        """ """
        return self.location

    def SetEmail(self, email):
        """ """
        self.email = email
        self.profile[ClientProfile.configSection + '.email'] = email

    def GetEmail(self):
        """ """
        return self.email

    def SetName(self, name):
        """ """
        self.name = name
        self.profile[ClientProfile.configSection + '.name'] = name

    def GetName(self):
        """ """
        return self.name

    def GetDistinguishedName(self):
        """ """
        return self.distinguishedName

    def SetPhoneNumber(self, phoneNumber):
        """ """
        self.phoneNumber = phoneNumber
        self.profile[ClientProfile.configSection + '.phone'] = phoneNumber

    def GetPhoneNumber(self):
        """ """
        return self.phoneNumber

    def SetVenueClientURL(self, venueClientURL):
        """ """
        self.venueClientURL = venueClientURL
        self.profile[ClientProfile.configSection +
                     '.venueclienturl'] = venueClientURL

    def GetVenueClientURL(self):
        """ """
        return self.venueClientURL

    def SetPublicId(self, publicId):
        """ """
        self.publicId = publicId
        self.profile[ClientProfile.configSection + '.id'] = publicId

    def GetPublicId(self):
        """ """
        return self.publicId

    def SetHomeVenue(self, venue):
        self.homeVenue = venue
        self.profile[ClientProfile.configSection + '.home'] = venue

    def GetHomeVenue(self):
        return self.homeVenue

    def GetGmtOffset(self):
        return self.gmtoffset

    def GetBeaconState(self):
        return self.beacon

    def GetVideoState(self):
        return self.video

    def GetAudioState(self):
        return self.audio

    def GetDisplayState(self):
        return self.display

    def GetLat(self):
        return self.lat

    def GetLong(self):
        return self.long

    def InformationMatches(self, obj):
        """
        return true (1) if profile information is equivalent
          return false (0) otherwise.
        This was written mostly for the ClientProfileCache to use, so
          if modifying this function keep that purpose in mind.
          Specifically, a profile should be equivalent to its cached 
          profile if the user hasn't changed his/her profile.  This means
          things such as VenueClientURL are not tested below since it can
          change after the venue client reconnects.
        """
        if not isinstance(obj, ClientProfile):
            return 0
        isSame = 0
        try:
            # members not tested for equality
            #  self.fileType == obj.fileType
            #  self.publicId == obj.publicId
            #  self.privateId == obj.privateId
            #  self.distinguishedName == obj.distinguishedName
            #  self.venueClientURL == obj.venueClientURL and \
            if self.profileType == obj.profileType and \
               self.name == obj.name and \
               self.email == obj.email and \
               self.phoneNumber == obj.phoneNumber and \
               self.icon == obj.icon and \
               self.location == obj.location and \
               self.homeVenue == obj.homeVenue :
                isSame = 1
        except:
            pass
        return isSame
Пример #10
0
class AppDb:
    """
    The AppDb class provides an interface for the Toolkit to store
    information on a per user basis about what applications are
    installed and how to run them.
    """
    defaultSeparator = ":"

    def __init__(self, path=None, filename="ApplicationDatabase"):
        """
        The constructor for the AppDb, it uses a file for persistent storage.
        """
        self.AppDb = dict()

        if path is None:
            self.path = UserConfig.instance().GetConfigDir()
        else:
            self.path = path

        self.fileName = os.path.join(self.path, filename)

        # Create the file if it doesn't exist
        if not os.path.exists(self.fileName):
            try:
                file(self.fileName, 'w').close()
            except:
                log.exception("Couldn't create app db file %s", self.fileName)

        self.Load(self.fileName)

    def Load(self, fileName=None):
        """
        Load the app db from the file it's stored in.
        """
        if fileName == None:
            fileName = self.fileName

        try:
            self.AppDb = LoadConfig(fileName, separator=self.defaultSeparator)

            # update the file modification time
            self._UpdateModTime()
        except:
            print sys.exc_info()
            print "Couldn't open application database: %s" % fileName

    def _Synch(self):
        """
        Synch the in-memory app db with the file, if necessary
        """
        if os.access(self.fileName, os.R_OK):
            fileLastModified = os.stat(self.fileName)[stat.ST_MTIME]
            if fileLastModified > self.fileLastModified:
                self.Load()

    def _UpdateModTime(self):
        """
        Update the last modified time of the appdb file
        """
        if os.access(self.fileName, os.R_OK):
            # store the file modification time
            self.fileLastModified = os.stat(self.fileName)[stat.ST_MTIME]

    def _Flush(self):
        """
        Flush the current db out to file storage.
        """
        try:
            SaveConfig(self.fileName, self.AppDb, self.defaultSeparator)

            # update the file modification time
            self._UpdateModTime()
        except:
            print "Couldn't flush the db to disk."

    def _GetPrivName(self, name):
        """
        Look up the private name for the exposed name.

        returns name as string or None
        """
        pname = None
        for key in self.AppDb.keys():
            (section, option) = key.split(self.defaultSeparator)
            if section == "priv_names":
                if self.AppDb[key] == name:
                    pname = option
        return pname

    def _GetNiceName(self, pName):
        """
        Get a user friendly name for a private name.
        """
        for key in self.AppDb.keys():
            (section, option) = key.split(self.defaultSeparator)
            if section == "priv_names":
                if option == pName:
                    return self.AppDb[key]
        return None

    def _GetPrivVerb(self, verb, mimeType):
        """
        Look up the private verb for the exposed verb.
        """
        pVerb = None

        for key in self.AppDb.keys():
            (section, option) = key.split(self.defaultSeparator)
            if section == "priv_cmds":
                mtCheckKey = self.defaultSeparator.join([mimeType, option])
                if self.AppDb[key] == verb and self.AppDb.has_key(mtCheckKey):
                    pVerb = option

        return pVerb

    def _GetNiceVerb(self, pVerb):
        """
        Get a user friendly name for a private verb.
        """
        for key in self.AppDb.keys():
            (section, option) = key.split(self.defaultSeparator)
            if section == "priv_cmds":
                if option == pVerb:
                    return self.AppDb[key]
        return None

    def GetMimeType(self, name=None, extension=None):
        """
        Find a mimetype for the specified app name or extension.

        returns a mimeType in a string.
        """
        # Ensure that we're in synch with the on-disk appdb
        self._Synch()

        mimeType = None

        if name != None:
            privName = self._GetPrivName(name)
            if privName == None:
                return mimeType

            lookupName = self.defaultSeparator.join(["name", privName])

            try:
                mimeType = self.AppDb[lookupName]
            except KeyError:
                mimeType = None

        if extension != None:
            lookupExt = self.defaultSeparator.join(["extension", extension])
            try:
                mimeType = self.AppDb[lookupExt]
            except KeyError:
                mimeType = None

        return mimeType

    def GetNameForMimeType(self, mimeType):
        """
        returns a name in a string.
        """
        # Ensure that we're in synch with the on-disk appdb
        self._Synch()

        appName = None

        for key in self.AppDb.keys():
            (section, option) = key.split(self.defaultSeparator)
            if section == "name":
                mt = self.AppDb[key]
                if mt == mimeType:
                    appName = self._GetNiceName(option)

        return appName

    def GetExtForMimeType(self, mimeType):
        """
        returns a extension in a string.
        """
        # Ensure that we're in synch with the on-disk appdb
        self._Synch()

        ext = None

        for key in self.AppDb.keys():
            (section, option) = key.split(self.defaultSeparator)
            if section == "extension":
                mt = self.AppDb[key]
                if mt == mimeType:
                    ext = option

        return ext

    def AddMimeType(self, name, extension, mimeType, startable="1"):
        """
        returns a tuple of (int, string). Success is (1, mimeType),
        failure is (0, reason)
        """

        # Ensure that we're in synch with the on-disk appdb
        self._Synch()

        namekey = self._GetPrivName(name)
        if namekey == None:
            namekey = str(GUID())

        privName = self.defaultSeparator.join(["priv_names", namekey])
        nameStr = self.defaultSeparator.join(["name", namekey])
        extStr = self.defaultSeparator.join(["extension", extension])
        mimeStr = self.defaultSeparator.join([mimeType, "None"])
        startableStr = self.defaultSeparator.join(["startable", mimeType])

        self.AppDb[privName] = name
        self.AppDb[nameStr] = mimeType
        self.AppDb[extStr] = mimeType
        self.AppDb[mimeStr] = None
        self.AppDb[startableStr] = startable

        self._Flush()

        return (1, mimeType)

    def RemoveMimeType(self, name=None, extension=None, mimeType=None):
        """
        returns a tuple of (int, string). Success is (1, mimeType),
        failure is (0, reason)
        """

        # Ensure that we're in synch with the on-disk appdb
        self._Synch()

        if name == None and extension == None and mimeType == None:
            return (0, "Not enough information to remove mime type.")

        privName = None
        nameStr = None
        extStr = None
        mimeStr = None

        if name != None and self._GetPrivName(name) != None:
            namekey = self._GetPrivName(name)
            privName = self.defaultSeparator.join(["priv_names", namekey])
            name = self.AppDb[privName]
            mt = self.GetMimeType(name=name)
            mimeStr = self.defaultSeparator.join([mt, "None"])
            nameStr = self.defaultSeparator.join(["name", namekey])
            ext = self.GetExtForMimeType(mt)
            extStr = self.defaultSeparator.join(["extension", ext])
        elif mimeType != None and self.GetNameForMimeType(mimeType) != None:
            mimeStr = self.defaultSeparator.join([mimeType, "None"])
            name = self.GetNameForMimeType(mimeType)
            namekey = self._GetPrivName(name)
            privName = self.defaultSeparator.join(["priv_names", namekey])
            nameStr = self.defaultSeparator.join(["name", namekey])
            ext = self.GetExtForMimeType(mimeType)
            extStr = self.defaultSeparator.join(["extension", ext])
        elif extension != None and None != self.GetNameForMimeType(
                self.GetMimeType(extension=extension)):
            mimeType = self.GetMimeType(extension=extension)
            mimeStr = self.defaultSeparator.join([mimeType, "None"])
            name = self.GetNameForMimeType(mimeType)
            namekey = self._GetPrivName(name)
            privName = self.defaultSeparator.join(["priv_names", namekey])
            nameStr = self.defaultSeparator.join(["name", namekey])
            ext = self.GetExtForMimeType(mimeType)
            extStr = self.defaultSeparator.join(["extension", extension])

        if privName != None:
            if self.AppDb.has_key(privName):
                del self.AppDb[privName]

        if nameStr != None:
            if self.AppDb.has_key(nameStr):
                del self.AppDb[nameStr]

        if extStr != None:
            if self.AppDb.has_key(extStr):
                del self.AppDb[extStr]

        if mimeStr != None:
            if self.AppDb.has_key(mimeStr):
                del self.AppDb[mimeStr]

        self._Flush()

        return (1, mimeType)

    def GetCommandNames(self, mimeType):
        """
        returns a list of command names for this mime type.
        """
        # Ensure that we're in synch with the on-disk appdb
        self._Synch()

        cmds = list()

        for key in self.AppDb.keys():
            (section, option) = key.split(self.defaultSeparator)
            if section == mimeType:
                nName = self._GetNiceVerb(option)
                if nName != None:
                    cmds.append(nName)

        return cmds

    def GetCommands(self, mimeType):
        """
        returns a dict of [commandname:command] for this mimetype
        """
        # Ensure that we're in synch with the on-disk appdb
        self._Synch()

        cmds = dict()

        for key in self.AppDb.keys():
            (section, option) = key.split(self.defaultSeparator)
            if section == mimeType:
                nName = self._GetNiceVerb(option)
                if nName != None:
                    cmds[nName] = self.GetCommandLine(mimeType, nName)

        return cmds

    def GetCommandLine(self, mimeType, cmdName, vars=None):
        """
        returns a string containing the commandline used to execute the viewer,
        optionally if vars is a dictionary, of name = value, named parameter
        substitution is done for the command line.
        """
        # Ensure that we're in synch with the on-disk appdb
        self._Synch()

        cmdStr = ""

        if mimeType == None or cmdName == None:
            return cmdStr

        pCmd = self._GetPrivVerb(cmdName, mimeType)
        if pCmd != None:
            key = self.defaultSeparator.join([mimeType, pCmd])
        else:
            return cmdStr

        try:
            cmdStr = self.AppDb[key]
        except KeyError:
            return cmdStr

        if vars != None:
            cmdStr = self.AppDb[key] % vars

        return cmdStr

    def AddCommand(self, mimeType, cmdName, cmdString):
        """
        returns a tuple (int, string). Success is (1, cmdName),
        failure is (0, reason).
        """

        # Ensure that we're in synch with the on-disk appdb
        self._Synch()

        pCmd = self._GetPrivVerb(cmdName, mimeType)
        if pCmd == None:
            pCmd = str(GUID())
        cmdkey = self.defaultSeparator.join([mimeType, pCmd])
        pcmdkey = self.defaultSeparator.join(["priv_cmds", pCmd])

        self.AppDb[cmdkey] = cmdString
        self.AppDb[pcmdkey] = cmdName

        self._Flush()

        return (1, cmdName)

    def RemoveCommand(self, mimeType, cmdName):
        """
        returns a tuple (int, string). Success is (1, cmdName),
        failure is (0, reason).
        """

        # Ensure that we're in synch with the on-disk appdb
        self._Synch()

        pCmd = self._GetPrivVerb(cmdName, mimeType)
        cmdkey = self.defaultSeparator.join([mimeType, pCmd])
        if self.AppDb.has_key(cmdkey):
            del self.AppDb[cmdkey]

        pcmdkey = self.defaultSeparator.join(["priv_cmds", pCmd])
        if self.AppDb.has_key(pcmdkey):
            del self.AppDb[pcmdkey]

        self._Flush()

        return (1, cmdName)

    def RegisterApplication(self,
                            name,
                            mimeType,
                            extension,
                            commandDict,
                            fileList,
                            srcPath,
                            dstPath,
                            startable="1"):
        """
        Encapsulate all the actions required to register a new application.
        returns 0 on failure, 1 on success
        """

        (ret, retStr) = self.AddMimeType(name, extension, mimeType, startable)

        if ret:
            for cmdName in commandDict.keys():
                cmdStr = commandDict[cmdName]
                (result,
                 resultString) = self.AddCommand(mimeType, cmdName, cmdStr)
                if not result:
                    return 0

            noSpaceName = '_'.join(name.split(' '))
            dstPath = os.path.join(dstPath, noSpaceName)

            if not os.path.exists(dstPath):
                try:
                    os.mkdir(dstPath)
                except:
                    print "Couldn't make app directory (%s)." % dstPath

            success = 0
            for appFile in fileList:
                try:
                    srcf = os.path.join(srcPath, appFile)
                    dstf = os.path.join(dstPath, appFile)

                    # Create any destination subdirs
                    dstd = os.path.dirname(dstf)
                    if not os.path.exists(dstd):
                        os.makedirs(dstd)

                    shutil.copy(srcf, dstf)
                    success = 1

                except:
                    print "Couldn't copy file into place (undoing register)."
                    self.UnregisterApplication(name=name, mimeType=mimeType)

        else:
            return 0

        self._Flush()

        return 1

    def ListApplications(self):
        """
        """
        # Ensure that we're in synch with the on-disk appdb
        self._Synch()

        apps = list()

        for key in self.AppDb.keys():
            (section, option) = key.split(self.defaultSeparator)
            if section == 'name':
                name = self._GetNiceName(option)
                if name:
                    apps.append(name)

        return apps

    def ListMimeTypes(self):
        """
        """
        # Ensure that we're in synch with the on-disk appdb
        self._Synch()

        mt = list()

        for key in self.AppDb.keys():
            try:
                (section, option) = key.split(self.defaultSeparator)
            except ValueError:
                continue

            if section != 'name' and section != 'extension':
                mt.append(option)

        return mt

    def ListAppsAsAppDescriptions(self):
        """
        """
        # Ensure that we're in synch with the on-disk appdb
        self._Synch()

        apps = list()

        for key in self.AppDb.keys():
            try:
                (section, option) = key.split(self.defaultSeparator)
            except ValueError:
                continue
            if section == 'name':
                name = self._GetNiceName(option)
                if name:
                    mimetype = self.AppDb[key]
                    startableStr = self.defaultSeparator.join(
                        ["startable", mimetype])
                    if startableStr in self.AppDb.keys():
                        startable = self.AppDb[startableStr]
                    else:
                        startable = 1
                    apps.append(
                        ApplicationDescription(None, name, None, None,
                                               mimetype, startable))

        return apps

    def UnregisterApplication(self, name=None, mimeType=None, extension=None):
        """
        Encapsulate all the actions required to unregister an application.
        returns 0 on failure, 1 on success
        """

        noSpaceName = '_'.join(name.split(' '))
        dstPath = os.path.join(UserConfig.instance().GetSharedAppDir(),
                               noSpaceName)

        if os.path.exists(dstPath):
            try:
                shutil.rmtree(dstPath)
                print "Unregistration of application %s complete" % (name)
            except:
                print "App directory error -- can't remove (%s)." % dstPath
        else:
            print "Application %s not found; skipping" % (name)
            return 0

        if mimeType == None:
            mimeType = self.GetMimeType(name, extension)

        if mimeType == None:
            print "MimeType: %s not found." % mimeType
            return 0

        cmdList = self.GetCommandNames(mimeType)

        (ret, retStr) = self.RemoveMimeType(name, extension, mimeType)
        if ret:
            for cmdName in cmdList:
                (result, resultString) = self.RemoveCommand(mimeType, cmdName)
                if not result:
                    print "Error removing verb, continuing."

        return 1