# -*- 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 from re import compile as re_compile, search as re_search, IGNORECASE 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.language = language self.translatedPackageInfos = {} self.foundTranslation = None 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 == "info": self.foundTranslation = None self.data = "" if not attrs.has_key("language"): print "info tag with no language attribute" else: if attrs["language"] == 'en': # read default translations self.foundTranslation = False self.data = "" elif attrs["language"] == self.language: self.foundTranslation = True self.data = "" 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"): if self.foundTranslation is False: self.attributes["screenshot"] = str(attrs["src"]) elif self.foundTranslation is True: self.translatedPackageInfos["screenshot"] = str(attrs["src"]) def endElement(self, name): #print "endElement", 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 ,"translation": self.translatedPackageInfos}) 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.foundTranslation is False: 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")) elif self.foundTranslation is True: if self.elements[-1] == "author": self.translatedPackageInfos["author"] = str(data) if self.elements[-1] == "name": self.translatedPackageInfos["name"] = str(data) if self.elements[-1] == "description": self.data += data.strip() self.translatedPackageInfos["description"] = str(self.data.encode("utf-8")) if self.elements[-1] == "name": self.translatedPackageInfos["name"] = str(data.encode("utf-8")) if self.elements[-1] == "shortdescription": self.translatedPackageInfos["shortdescription"] = str(data.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): self.packageDetails = [] 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 = [] indexfileList = [] if not isinstance(self.directory, list): self.directory = [self.directory] for indexfile in os.listdir(self.directory[0]): if indexfile.startswith("index"): if os.path.splitext(indexfile)[0][-3:-2] is not "_": #we first catch all non translated indexfiles indexfileList.append(os.path.splitext(indexfile)[0]) if len(indexfileList): for file in indexfileList: neededFile = self.directory[0] + "/" + file if self.language is not None: if os.path.exists(neededFile + '_' + self.language + '.xml' ): #print "translated index file found",neededFile + '_' + self.language + '.xml' self.readIndex(self.directory[0] + "/", neededFile + '_' + self.language + '.xml') else: #print "reading original index file" self.readIndex(self.directory[0] + "/", neededFile + '.xml') 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()