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
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
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
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
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
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