# -*- coding: iso-8859-1 -*- import xml.sax from Tools.Directories import crawlDirectory, resolveFilename, SCOPE_CONFIG, SCOPE_SKIN, SCOPE_METADIR, copyfile, copytree from Components.NimManager import nimmanager from Components.Ipkg import IpkgComponent from Components.config import config, configfile from Tools.HardwareInfo import HardwareInfo from enigma import eConsoleAppContainer, eDVBDB import os class InfoHandlerParseError(Exception): def __init__(self, value): self.value = value def __str__(self): return repr(self.value) class InfoHandler(xml.sax.ContentHandler): def __init__(self, prerequisiteMet, directory, language = None): self.attributes = {} self.directory = directory self.list = [] self.globalprerequisites = {} self.prerequisites = {} self.elements = [] self.validFileTypes = ["skin", "config", "services", "favourites", "package"] self.prerequisitesMet = prerequisiteMet self.data = "" self.languagedata = "" self.language = language def printError(self, error): print "Error in defaults xml files:", error raise InfoHandlerParseError, error def startElement(self, name, attrs): #print name, ":", attrs.items() self.elements.append(name) if name in ("hardware", "bcastsystem", "satellite", "tag", "flag"): if not attrs.has_key("type"): self.printError(str(name) + " tag with no type attribute") if self.elements[-3] in ("default", "package"): prerequisites = self.globalprerequisites else: prerequisites = self.prerequisites if not prerequisites.has_key(name): prerequisites[name] = [] prerequisites[name].append(str(attrs["type"])) if name == "files": if attrs.has_key("type"): if attrs["type"] == "directories": self.attributes["filestype"] = "directories" elif attrs["type"] == "package": self.attributes["filestype"] = "package" # TODO add a compressed archive type if name == "file": self.prerequisites = {} if not attrs.has_key("type"): self.printError("file tag with no type attribute") else: if not attrs.has_key("name"): self.printError("file tag with no name attribute") else: if not attrs.has_key("directory"): directory = self.directory type = attrs["type"] if not type in self.validFileTypes: self.printError("file tag with invalid type attribute") else: self.filetype = type self.fileattrs = attrs if name == "package": if attrs.has_key("details"): self.attributes["details"] = str(attrs["details"]) if attrs.has_key("name"): self.attributes["name"] = str(attrs["name"].encode("utf-8")) if attrs.has_key("packagename"): self.attributes["packagename"] = str(attrs["packagename"].encode("utf-8")) if attrs.has_key("shortdescription"): self.attributes["shortdescription"] = str(attrs["shortdescription"].encode("utf-8")) if name == "screenshot": if attrs.has_key("src"): self.attributes["screenshot"] = str(attrs["src"]) def endElement(self, name): #print "end", name #print "self.elements:", self.elements self.elements.pop() if name == "file": #print "prerequisites:", self.prerequisites if len(self.prerequisites) == 0 or self.prerequisitesMet(self.prerequisites): if not self.attributes.has_key(self.filetype): self.attributes[self.filetype] = [] if self.fileattrs.has_key("directory"): directory = str(self.fileattrs["directory"]) if len(directory) < 1 or directory[0] != "/": directory = self.directory + directory else: directory = self.directory self.attributes[self.filetype].append({ "name": str(self.fileattrs["name"]), "directory": directory }) if name in ( "default", "package" ): self.list.append({"attributes": self.attributes, 'prerequisites': self.globalprerequisites}) self.attributes = {} self.globalprerequisites = {} def characters(self, data): if self.elements[-1] == "author": self.attributes["author"] = str(data) if self.elements[-1] == "name": self.attributes["name"] = str(data) if self.elements[-1] == "packagename": self.attributes["packagename"] = str(data.encode("utf-8")) if self.elements[-1] == "shortdescription": self.attributes["shortdescription"] = str(data.encode("utf-8")) if self.elements[-1] == "description": self.data += data.strip() self.attributes["description"] = str(self.data.encode("utf-8")) if self.language is not None: if self.elements[-1] == ("name_" + str(self.language)): self.attributes["name"] = str(data.encode("utf-8")) if self.elements[-1] == ("shortdescription_" + str(self.language)): self.attributes["shortdescription"] = str(data.encode("utf-8")) if self.elements[-1] == ("description_" + str(self.language)): self.languagedata += data.strip() self.attributes["description"] = str(self.languagedata.encode("utf-8")) #print "characters", data class DreamInfoHandler: STATUS_WORKING = 0 STATUS_DONE = 1 STATUS_ERROR = 2 STATUS_INIT = 4 def __init__(self, statusCallback, blocking = False, neededTag = None, neededFlag = None, language = None): self.hardware_info = HardwareInfo() self.directory = "/" self.neededTag = neededTag self.neededFlag = neededFlag self.language = language # caution: blocking should only be used, if further execution in enigma2 depends on the outcome of # the installer! self.blocking = blocking self.currentlyInstallingMetaIndex = None self.console = eConsoleAppContainer() self.console.appClosed.append(self.installNext) self.reloadFavourites = False self.statusCallback = statusCallback self.setStatus(self.STATUS_INIT) self.packageslist = [] self.packagesIndexlist = [] self.packageDetails = [] def readInfo(self, directory, file): print "Reading .info file", file handler = InfoHandler(self.prerequisiteMet, directory) try: xml.sax.parse(file, handler) for entry in handler.list: self.packageslist.append((entry,file)) except InfoHandlerParseError: print "file", file, "ignored due to errors in the file" print handler.list def readIndex(self, directory, file): print "Reading .xml meta index file", file handler = InfoHandler(self.prerequisiteMet, directory, self.language) try: xml.sax.parse(file, handler) for entry in handler.list: self.packagesIndexlist.append((entry,file)) except InfoHandlerParseError: print "file", file, "ignored due to errors in the file" #print handler.list def readDetails(self, directory, file): print "Reading .xml meta details file", file handler = InfoHandler(self.prerequisiteMet, directory, self.language) try: xml.sax.parse(file, handler) for entry in handler.list: self.packageDetails.append((entry,file)) except InfoHandlerParseError: print "file", file, "ignored due to errors in the file" #print handler.list # prerequisites = True: give only packages matching the prerequisites def fillPackagesList(self, prerequisites = True): self.packageslist = [] packages = [] if not isinstance(self.directory, list): self.directory = [self.directory] for directory in self.directory: packages += crawlDirectory(directory, ".*\.info$") for package in packages: self.readInfo(package[0] + "/", package[0] + "/" + package[1]) if prerequisites: for package in self.packageslist[:]: if not self.prerequisiteMet(package[0]["prerequisites"]): self.packageslist.remove(package) return self.packageslist # prerequisites = True: give only packages matching the prerequisites def fillPackagesIndexList(self, prerequisites = True): self.packagesIndexlist = [] if self.language is not None: indexfile = 'index_' + self.language + '.xml' else: indexfile = 'index.xml' if not isinstance(self.directory, list): self.directory = [self.directory] self.readIndex(self.directory[0] + "/", self.directory[0] + "/" + indexfile) if prerequisites: for package in self.packagesIndexlist[:]: if not self.prerequisiteMet(package[0]["prerequisites"]): self.packagesIndexlist.remove(package) return self.packagesIndexlist # prerequisites = True: give only packages matching the prerequisites def fillPackageDetails(self, details = None): self.packageDetails = [] detailsfile = details if not isinstance(self.directory, list): self.directory = [self.directory] self.readDetails(self.directory[0] + "/", self.directory[0] + "/" + detailsfile) return self.packageDetails def prerequisiteMet(self, prerequisites): # TODO: we need to implement a hardware detection here... print "prerequisites:", prerequisites met = True if self.neededTag is None: if prerequisites.has_key("tag"): return False elif self.neededTag == 'ALL_TAGS': return True else: if prerequisites.has_key("tag"): if not self.neededTag in prerequisites["tag"]: return False else: return False if self.neededFlag is None: if prerequisites.has_key("flag"): return False else: if prerequisites.has_key("flag"): if not self.neededFlag in prerequisites["flag"]: return False else: return True # No flag found, assuming all flags valid if prerequisites.has_key("satellite"): for sat in prerequisites["satellite"]: if int(sat) not in nimmanager.getConfiguredSats(): return False if prerequisites.has_key("bcastsystem"): has_system = False for bcastsystem in prerequisites["bcastsystem"]: if nimmanager.hasNimType(bcastsystem): has_system = True if not has_system: return False if prerequisites.has_key("hardware"): hardware_found = False for hardware in prerequisites["hardware"]: if hardware == self.hardware_info.device_name: hardware_found = True if not hardware_found: return False return True def installPackages(self, indexes): print "installing packages", indexes if len(indexes) == 0: self.setStatus(self.STATUS_DONE) return self.installIndexes = indexes print "+++++++++++++++++++++++bla" self.currentlyInstallingMetaIndex = 0 self.installPackage(self.installIndexes[self.currentlyInstallingMetaIndex]) def installPackage(self, index): print "self.packageslist:", self.packageslist if len(self.packageslist) <= index: print "no package with index", index, "found... installing nothing" return print "installing package with index", index, "and name", self.packageslist[index][0]["attributes"]["name"] attributes = self.packageslist[index][0]["attributes"] self.installingAttributes = attributes self.attributeNames = ["skin", "config", "favourites", "package", "services"] self.currentAttributeIndex = 0 self.currentIndex = -1 self.installNext() def setStatus(self, status): self.status = status self.statusCallback(self.status, None) def installNext(self, *args, **kwargs): if self.reloadFavourites: self.reloadFavourites = False db = eDVBDB.getInstance().reloadBouquets() self.currentIndex += 1 attributes = self.installingAttributes #print "attributes:", attributes if self.currentAttributeIndex >= len(self.attributeNames): # end of package reached print "end of package reached" if self.currentlyInstallingMetaIndex is None or self.currentlyInstallingMetaIndex >= len(self.installIndexes) - 1: print "set status to DONE" self.setStatus(self.STATUS_DONE) return else: print "increment meta index to install next package" self.currentlyInstallingMetaIndex += 1 self.currentAttributeIndex = 0 self.installPackage(self.installIndexes[self.currentlyInstallingMetaIndex]) return self.setStatus(self.STATUS_WORKING) print "currentAttributeIndex:", self.currentAttributeIndex currentAttribute = self.attributeNames[self.currentAttributeIndex] print "installing", currentAttribute, "with index", self.currentIndex if attributes.has_key(currentAttribute): if self.currentIndex >= len(attributes[currentAttribute]): # all jobs done for current attribute self.currentIndex = -1 self.currentAttributeIndex += 1 self.installNext() return else: # nothing to install here self.currentIndex = -1 self.currentAttributeIndex += 1 self.installNext() return if currentAttribute == "skin": skin = attributes["skin"][self.currentIndex] self.installSkin(skin["directory"], skin["name"]) elif currentAttribute == "config": if self.currentIndex == 0: from Components.config import configfile configfile.save() config = attributes["config"][self.currentIndex] self.mergeConfig(config["directory"], config["name"]) elif currentAttribute == "favourites": favourite = attributes["favourites"][self.currentIndex] self.installFavourites(favourite["directory"], favourite["name"]) elif currentAttribute == "package": package = attributes["package"][self.currentIndex] self.installIPK(package["directory"], package["name"]) elif currentAttribute == "services": service = attributes["services"][self.currentIndex] self.mergeServices(service["directory"], service["name"]) def readfile(self, filename): if not os.path.isfile(filename): return [] fd = open(filename) lines = fd.readlines() fd.close() return lines def mergeConfig(self, directory, name, merge = True): print "merging config:", directory, " - ", name if os.path.isfile(directory + name): config.loadFromFile(directory + name) configfile.save() self.installNext() def installIPK(self, directory, name): if self.blocking: os.system("ipkg install " + directory + name) self.installNext() else: self.ipkg = IpkgComponent() self.ipkg.addCallback(self.ipkgCallback) self.ipkg.startCmd(IpkgComponent.CMD_INSTALL, {'package': directory + name}) def ipkgCallback(self, event, param): print "ipkgCallback" if event == IpkgComponent.EVENT_DONE: self.installNext() elif event == IpkgComponent.EVENT_ERROR: self.installNext() def installSkin(self, directory, name): print "installing skin:", directory, " - ", name print "cp -a %s %s" % (directory, resolveFilename(SCOPE_SKIN)) if self.blocking: copytree(directory, resolveFilename(SCOPE_SKIN)) self.installNext() else: if self.console.execute("cp -a %s %s" % (directory, resolveFilename(SCOPE_SKIN))): print "execute failed" self.installNext() def mergeServices(self, directory, name, merge = False): print "merging services:", directory, " - ", name if os.path.isfile(directory + name): db = eDVBDB.getInstance() db.reloadServicelist() db.loadServicelist(directory + name) db.saveServicelist() self.installNext() def installFavourites(self, directory, name): print "installing favourites:", directory, " - ", name self.reloadFavourites = True if self.blocking: copyfile(directory + name, resolveFilename(SCOPE_CONFIG)) self.installNext() else: if self.console.execute("cp %s %s" % ((directory + name), resolveFilename(SCOPE_CONFIG))): print "execute failed" self.installNext()