1 # -*- coding: iso-8859-1 -*-
3 from Tools.Directories import crawlDirectory, resolveFilename, SCOPE_CONFIG, SCOPE_SKIN, SCOPE_METADIR, copyfile, copytree
4 from Components.NimManager import nimmanager
5 from Components.Ipkg import IpkgComponent
6 from Components.config import config, configfile
7 from Tools.HardwareInfo import HardwareInfo
8 from enigma import eConsoleAppContainer, eDVBDB
10 from re import compile as re_compile, search as re_search, IGNORECASE
12 class InfoHandlerParseError(Exception):
13 def __init__(self, value):
16 return repr(self.value)
18 class InfoHandler(xml.sax.ContentHandler):
19 def __init__(self, prerequisiteMet, directory, language = None):
21 self.directory = directory
23 self.globalprerequisites = {}
24 self.prerequisites = {}
26 self.validFileTypes = ["skin", "config", "services", "favourites", "package"]
27 self.prerequisitesMet = prerequisiteMet
29 self.language = language
30 self.translatedPackageInfos = {}
31 self.foundTranslation = None
33 def printError(self, error):
34 print "Error in defaults xml files:", error
35 raise InfoHandlerParseError, error
37 def startElement(self, name, attrs):
38 #print name, ":", attrs.items()
39 self.elements.append(name)
41 if name in ("hardware", "bcastsystem", "satellite", "tag", "flag"):
42 if not attrs.has_key("type"):
43 self.printError(str(name) + " tag with no type attribute")
44 if self.elements[-3] in ("default", "package"):
45 prerequisites = self.globalprerequisites
47 prerequisites = self.prerequisites
48 if not prerequisites.has_key(name):
49 prerequisites[name] = []
50 prerequisites[name].append(str(attrs["type"]))
53 self.foundTranslation = None
55 if not attrs.has_key("language"):
56 print "info tag with no language attribute"
58 if attrs["language"] == 'en': # read default translations
59 self.foundTranslation = False
61 elif attrs["language"] == self.language:
62 self.foundTranslation = True
66 if attrs.has_key("type"):
67 if attrs["type"] == "directories":
68 self.attributes["filestype"] = "directories"
69 elif attrs["type"] == "package":
70 self.attributes["filestype"] = "package"
71 # TODO add a compressed archive type
74 self.prerequisites = {}
75 if not attrs.has_key("type"):
76 self.printError("file tag with no type attribute")
78 if not attrs.has_key("name"):
79 self.printError("file tag with no name attribute")
81 if not attrs.has_key("directory"):
82 directory = self.directory
84 if not type in self.validFileTypes:
85 self.printError("file tag with invalid type attribute")
88 self.fileattrs = attrs
91 if attrs.has_key("details"):
92 self.attributes["details"] = str(attrs["details"])
93 if attrs.has_key("name"):
94 self.attributes["name"] = str(attrs["name"].encode("utf-8"))
95 if attrs.has_key("packagename"):
96 self.attributes["packagename"] = str(attrs["packagename"].encode("utf-8"))
97 if attrs.has_key("packagetype"):
98 self.attributes["packagetype"] = str(attrs["packagetype"].encode("utf-8"))
99 if attrs.has_key("shortdescription"):
100 self.attributes["shortdescription"] = str(attrs["shortdescription"].encode("utf-8"))
102 if name == "screenshot":
103 if attrs.has_key("src"):
104 if self.foundTranslation is False:
105 self.attributes["screenshot"] = str(attrs["src"])
106 elif self.foundTranslation is True:
107 self.translatedPackageInfos["screenshot"] = str(attrs["src"])
109 def endElement(self, name):
110 #print "endElement", name
111 #print "self.elements:", self.elements
114 #print "prerequisites:", self.prerequisites
115 if len(self.prerequisites) == 0 or self.prerequisitesMet(self.prerequisites):
116 if not self.attributes.has_key(self.filetype):
117 self.attributes[self.filetype] = []
118 if self.fileattrs.has_key("directory"):
119 directory = str(self.fileattrs["directory"])
120 if len(directory) < 1 or directory[0] != "/":
121 directory = self.directory + directory
123 directory = self.directory
124 self.attributes[self.filetype].append({ "name": str(self.fileattrs["name"]), "directory": directory })
126 if name in ( "default", "package" ):
127 self.list.append({"attributes": self.attributes, 'prerequisites': self.globalprerequisites ,"translation": self.translatedPackageInfos})
129 self.globalprerequisites = {}
131 def characters(self, data):
132 if self.elements[-1] == "author":
133 self.attributes["author"] = str(data)
134 if self.elements[-1] == "name":
135 self.attributes["name"] = str(data)
136 if self.foundTranslation is False:
137 if self.elements[-1] == "author":
138 self.attributes["author"] = str(data)
139 if self.elements[-1] == "name":
140 self.attributes["name"] = str(data)
141 if self.elements[-1] == "packagename":
142 self.attributes["packagename"] = str(data.encode("utf-8"))
143 if self.elements[-1] == "shortdescription":
144 self.attributes["shortdescription"] = str(data.encode("utf-8"))
145 if self.elements[-1] == "description":
146 self.data += data.strip()
147 self.attributes["description"] = str(self.data.encode("utf-8"))
148 elif self.foundTranslation is True:
149 if self.elements[-1] == "author":
150 self.translatedPackageInfos["author"] = str(data)
151 if self.elements[-1] == "name":
152 self.translatedPackageInfos["name"] = str(data)
153 if self.elements[-1] == "description":
154 self.data += data.strip()
155 self.translatedPackageInfos["description"] = str(self.data.encode("utf-8"))
156 if self.elements[-1] == "name":
157 self.translatedPackageInfos["name"] = str(data.encode("utf-8"))
158 if self.elements[-1] == "shortdescription":
159 self.translatedPackageInfos["shortdescription"] = str(data.encode("utf-8"))
160 #print "characters", data
163 class DreamInfoHandler:
169 def __init__(self, statusCallback, blocking = False, neededTag = None, neededFlag = None, language = None):
170 self.hardware_info = HardwareInfo()
173 self.neededTag = neededTag
174 self.neededFlag = neededFlag
175 self.language = language
177 # caution: blocking should only be used, if further execution in enigma2 depends on the outcome of
179 self.blocking = blocking
181 self.currentlyInstallingMetaIndex = None
183 self.console = eConsoleAppContainer()
184 self.console.appClosed.append(self.installNext)
185 self.reloadFavourites = False
187 self.statusCallback = statusCallback
188 self.setStatus(self.STATUS_INIT)
190 self.packageslist = []
191 self.packagesIndexlist = []
192 self.packageDetails = []
194 def readInfo(self, directory, file):
195 print "Reading .info file", file
196 handler = InfoHandler(self.prerequisiteMet, directory)
198 xml.sax.parse(file, handler)
199 for entry in handler.list:
200 self.packageslist.append((entry,file))
201 except InfoHandlerParseError:
202 print "file", file, "ignored due to errors in the file"
205 def readIndex(self, directory, file):
206 print "Reading .xml meta index file", file
207 handler = InfoHandler(self.prerequisiteMet, directory, self.language)
209 xml.sax.parse(file, handler)
210 for entry in handler.list:
211 self.packagesIndexlist.append((entry,file))
212 except InfoHandlerParseError:
213 print "file", file, "ignored due to errors in the file"
216 def readDetails(self, directory, file):
217 self.packageDetails = []
218 print "Reading .xml meta details file", file
219 handler = InfoHandler(self.prerequisiteMet, directory, self.language)
221 xml.sax.parse(file, handler)
222 for entry in handler.list:
223 self.packageDetails.append((entry,file))
224 except InfoHandlerParseError:
225 print "file", file, "ignored due to errors in the file"
229 # prerequisites = True: give only packages matching the prerequisites
230 def fillPackagesList(self, prerequisites = True):
231 self.packageslist = []
233 if not isinstance(self.directory, list):
234 self.directory = [self.directory]
236 for directory in self.directory:
237 packages += crawlDirectory(directory, ".*\.info$")
239 for package in packages:
240 self.readInfo(package[0] + "/", package[0] + "/" + package[1])
243 for package in self.packageslist[:]:
244 if not self.prerequisiteMet(package[0]["prerequisites"]):
245 self.packageslist.remove(package)
246 return self.packageslist
248 # prerequisites = True: give only packages matching the prerequisites
249 def fillPackagesIndexList(self, prerequisites = True):
250 self.packagesIndexlist = []
253 if not isinstance(self.directory, list):
254 self.directory = [self.directory]
256 for indexfile in os.listdir(self.directory[0]):
257 if indexfile.startswith("index"):
258 if indexfile.endswith("_en.xml"): #we first catch all english indexfiles
259 indexfileList.append(os.path.splitext(indexfile)[0][:-3])
261 if len(indexfileList):
262 for file in indexfileList:
263 neededFile = self.directory[0] + "/" + file
264 if self.language is not None:
265 if os.path.exists(neededFile + '_' + self.language + '.xml' ):
266 #print "translated index file found",neededFile + '_' + self.language + '.xml'
267 self.readIndex(self.directory[0] + "/", neededFile + '_' + self.language + '.xml')
269 #print "reading original index file"
270 self.readIndex(self.directory[0] + "/", neededFile + '_en.xml')
273 for package in self.packagesIndexlist[:]:
274 if not self.prerequisiteMet(package[0]["prerequisites"]):
275 self.packagesIndexlist.remove(package)
276 return self.packagesIndexlist
278 # prerequisites = True: give only packages matching the prerequisites
279 def fillPackageDetails(self, details = None):
280 self.packageDetails = []
281 detailsfile = details
282 if not isinstance(self.directory, list):
283 self.directory = [self.directory]
284 self.readDetails(self.directory[0] + "/", self.directory[0] + "/" + detailsfile)
285 return self.packageDetails
287 def prerequisiteMet(self, prerequisites):
288 # TODO: we need to implement a hardware detection here...
289 print "prerequisites:", prerequisites
291 if self.neededTag is None:
292 if prerequisites.has_key("tag"):
294 elif self.neededTag == 'ALL_TAGS':
297 if prerequisites.has_key("tag"):
298 if not self.neededTag in prerequisites["tag"]:
303 if self.neededFlag is None:
304 if prerequisites.has_key("flag"):
307 if prerequisites.has_key("flag"):
308 if not self.neededFlag in prerequisites["flag"]:
311 return True # No flag found, assuming all flags valid
313 if prerequisites.has_key("satellite"):
314 for sat in prerequisites["satellite"]:
315 if int(sat) not in nimmanager.getConfiguredSats():
317 if prerequisites.has_key("bcastsystem"):
319 for bcastsystem in prerequisites["bcastsystem"]:
320 if nimmanager.hasNimType(bcastsystem):
324 if prerequisites.has_key("hardware"):
325 hardware_found = False
326 for hardware in prerequisites["hardware"]:
327 if hardware == self.hardware_info.device_name:
328 hardware_found = True
329 if not hardware_found:
333 def installPackages(self, indexes):
334 print "installing packages", indexes
335 if len(indexes) == 0:
336 self.setStatus(self.STATUS_DONE)
338 self.installIndexes = indexes
339 print "+++++++++++++++++++++++bla"
340 self.currentlyInstallingMetaIndex = 0
341 self.installPackage(self.installIndexes[self.currentlyInstallingMetaIndex])
343 def installPackage(self, index):
344 print "self.packageslist:", self.packageslist
345 if len(self.packageslist) <= index:
346 print "no package with index", index, "found... installing nothing"
348 print "installing package with index", index, "and name", self.packageslist[index][0]["attributes"]["name"]
350 attributes = self.packageslist[index][0]["attributes"]
351 self.installingAttributes = attributes
352 self.attributeNames = ["skin", "config", "favourites", "package", "services"]
353 self.currentAttributeIndex = 0
354 self.currentIndex = -1
357 def setStatus(self, status):
359 self.statusCallback(self.status, None)
361 def installNext(self, *args, **kwargs):
362 if self.reloadFavourites:
363 self.reloadFavourites = False
364 db = eDVBDB.getInstance().reloadBouquets()
366 self.currentIndex += 1
367 attributes = self.installingAttributes
368 #print "attributes:", attributes
370 if self.currentAttributeIndex >= len(self.attributeNames): # end of package reached
371 print "end of package reached"
372 if self.currentlyInstallingMetaIndex is None or self.currentlyInstallingMetaIndex >= len(self.installIndexes) - 1:
373 print "set status to DONE"
374 self.setStatus(self.STATUS_DONE)
377 print "increment meta index to install next package"
378 self.currentlyInstallingMetaIndex += 1
379 self.currentAttributeIndex = 0
380 self.installPackage(self.installIndexes[self.currentlyInstallingMetaIndex])
383 self.setStatus(self.STATUS_WORKING)
385 print "currentAttributeIndex:", self.currentAttributeIndex
386 currentAttribute = self.attributeNames[self.currentAttributeIndex]
388 print "installing", currentAttribute, "with index", self.currentIndex
390 if attributes.has_key(currentAttribute):
391 if self.currentIndex >= len(attributes[currentAttribute]): # all jobs done for current attribute
392 self.currentIndex = -1
393 self.currentAttributeIndex += 1
396 else: # nothing to install here
397 self.currentIndex = -1
398 self.currentAttributeIndex += 1
402 if currentAttribute == "skin":
403 skin = attributes["skin"][self.currentIndex]
404 self.installSkin(skin["directory"], skin["name"])
405 elif currentAttribute == "config":
406 if self.currentIndex == 0:
407 from Components.config import configfile
409 config = attributes["config"][self.currentIndex]
410 self.mergeConfig(config["directory"], config["name"])
411 elif currentAttribute == "favourites":
412 favourite = attributes["favourites"][self.currentIndex]
413 self.installFavourites(favourite["directory"], favourite["name"])
414 elif currentAttribute == "package":
415 package = attributes["package"][self.currentIndex]
416 self.installIPK(package["directory"], package["name"])
417 elif currentAttribute == "services":
418 service = attributes["services"][self.currentIndex]
419 self.mergeServices(service["directory"], service["name"])
421 def readfile(self, filename):
422 if not os.path.isfile(filename):
425 lines = fd.readlines()
429 def mergeConfig(self, directory, name, merge = True):
430 print "merging config:", directory, " - ", name
431 if os.path.isfile(directory + name):
432 config.loadFromFile(directory + name)
436 def installIPK(self, directory, name):
438 os.system("ipkg install " + directory + name)
441 self.ipkg = IpkgComponent()
442 self.ipkg.addCallback(self.ipkgCallback)
443 self.ipkg.startCmd(IpkgComponent.CMD_INSTALL, {'package': directory + name})
445 def ipkgCallback(self, event, param):
447 if event == IpkgComponent.EVENT_DONE:
449 elif event == IpkgComponent.EVENT_ERROR:
452 def installSkin(self, directory, name):
453 print "installing skin:", directory, " - ", name
454 print "cp -a %s %s" % (directory, resolveFilename(SCOPE_SKIN))
456 copytree(directory, resolveFilename(SCOPE_SKIN))
459 if self.console.execute("cp -a %s %s" % (directory, resolveFilename(SCOPE_SKIN))):
460 print "execute failed"
463 def mergeServices(self, directory, name, merge = False):
464 print "merging services:", directory, " - ", name
465 if os.path.isfile(directory + name):
466 db = eDVBDB.getInstance()
467 db.reloadServicelist()
468 db.loadServicelist(directory + name)
472 def installFavourites(self, directory, name):
473 print "installing favourites:", directory, " - ", name
474 self.reloadFavourites = True
477 copyfile(directory + name, resolveFilename(SCOPE_CONFIG))
480 if self.console.execute("cp %s %s" % ((directory + name), resolveFilename(SCOPE_CONFIG))):
481 print "execute failed"