1 # -*- coding: iso-8859-1 -*-
2 from enigma import eConsoleAppContainer,eTPM
3 from Components.Console import Console
4 from Components.About import about
5 from Components.DreamInfoHandler import DreamInfoHandler
6 from Components.Language import language
7 from Components.Sources.List import List
8 from Components.Ipkg import IpkgComponent
9 from Components.Network import iNetwork
10 from Tools.Directories import pathExists, fileExists, resolveFilename, SCOPE_METADIR
11 from Tools.HardwareInfo import HardwareInfo
14 from os import urandom
16 rootkey = ['\x9f', '|', '\xe4', 'G', '\xc9', '\xb4', '\xf4', '#', '&', '\xce', '\xb3', '\xfe', '\xda', '\xc9', 'U', '`', '\xd8', '\x8c', 's', 'o', '\x90', '\x9b', '\\', 'b', '\xc0', '\x89', '\xd1', '\x8c', '\x9e', 'J', 'T', '\xc5', 'X', '\xa1', '\xb8', '\x13', '5', 'E', '\x02', '\xc9', '\xb2', '\xe6', 't', '\x89', '\xde', '\xcd', '\x9d', '\x11', '\xdd', '\xc7', '\xf4', '\xe4', '\xe4', '\xbc', '\xdb', '\x9c', '\xea', '}', '\xad', '\xda', 't', 'r', '\x9b', '\xdc', '\xbc', '\x18', '3', '\xe7', '\xaf', '|', '\xae', '\x0c', '\xe3', '\xb5', '\x84', '\x8d', '\r', '\x8d', '\x9d', '2', '\xd0', '\xce', '\xd5', 'q', '\t', '\x84', 'c', '\xa8', ')', '\x99', '\xdc', '<', '"', 'x', '\xe8', '\x87', '\x8f', '\x02', ';', 'S', 'm', '\xd5', '\xf0', '\xa3', '_', '\xb7', 'T', '\t', '\xde', '\xa7', '\xf1', '\xc9', '\xae', '\x8a', '\xd7', '\xd2', '\xcf', '\xb2', '.', '\x13', '\xfb', '\xac', 'j', '\xdf', '\xb1', '\x1d', ':', '?']
19 return reduce( lambda x,y:(x<<8L)+y, map(ord, s))
23 for byte in range(128):
24 res += chr((l >> (1024 - (byte + 1) * 8)) & 0xff)
27 def rsa_pub1024(src, mod):
28 return long2bin(pow(bin2long(src), 65537, bin2long(mod)))
30 def decrypt_block(src, mod):
31 if len(src) != 128 and len(src) != 202:
33 dest = rsa_pub1024(src[:128], mod)
34 hash = hashlib.sha1(dest[1:107])
36 hash.update(src[131:192])
37 result = hash.digest()
38 if result == dest[107:127]:
42 def validate_cert(cert, key):
43 buf = decrypt_block(cert[8:], key)
46 return buf[36:107] + cert[139:196]
50 xor = lambda a,b: ''.join(chr(ord(c)^ord(d)) for c,d in zip(a,b*100))
53 result = xor(random, x)
59 class SoftwareTools(DreamInfoHandler):
60 lastDownloadDate = None
61 NetworkConnectionAvailable = None
64 available_updatelist = []
65 available_packetlist = []
66 installed_packetlist = {}
70 aboutInfo = about.getImageVersionString()
71 if aboutInfo.startswith("dev-"):
72 self.ImageVersion = 'Experimental'
74 self.ImageVersion = 'Stable'
75 self.language = language.getLanguage()[:2] # getLanguage returns e.g. "fi_FI" for "language_country"
76 DreamInfoHandler.__init__(self, self.statusCallback, blocking = False, neededTag = 'ALL_TAGS', neededFlag = self.ImageVersion)
77 self.directory = resolveFilename(SCOPE_METADIR)
78 self.hardware_info = HardwareInfo()
80 self.NotifierCallback = None
81 self.Console = Console()
82 self.UpdateConsole = Console()
84 self.unwanted_extensions = ('-dbg', '-dev', '-doc')
85 self.ipkg = IpkgComponent()
86 self.ipkg.addCallback(self.ipkgCallback)
88 def statusCallback(self, status, progress):
91 def startSoftwareTools(self, callback = None):
92 if callback is not None:
93 self.NotifierCallback = callback
94 iNetwork.checkNetworkState(self.checkNetworkCB)
96 def checkNetworkCB(self,data):
99 self.NetworkConnectionAvailable = True
102 self.NetworkConnectionAvailable = False
105 def getUpdates(self, callback = None):
106 if self.lastDownloadDate is None:
107 if self.hardware_info.device_name != "dm7025":
109 l2cert = etpm.getCert(eTPM.TPMD_DT_LEVEL2_CERT)
112 l2key = validate_cert(l2cert, rootkey)
115 l3cert = etpm.getCert(eTPM.TPMD_DT_LEVEL3_CERT)
118 l3key = validate_cert(l3cert, l2key)
124 val = etpm.challenge(rnd)
125 result = decrypt_block(val, l3key)
126 if self.hardware_info.device_name == "dm7025" or result[80:88] == rnd:
127 if self.NetworkConnectionAvailable == True:
128 self.lastDownloadDate = time()
129 if self.list_updating is False and callback is None:
130 self.list_updating = True
131 self.ipkg.startCmd(IpkgComponent.CMD_UPDATE)
132 elif self.list_updating is False and callback is not None:
133 self.list_updating = True
134 self.NotifierCallback = callback
135 self.ipkg.startCmd(IpkgComponent.CMD_UPDATE)
136 elif self.list_updating is True and callback is not None:
137 self.NotifierCallback = callback
139 self.list_updating = False
140 if callback is not None:
142 elif self.NotifierCallback is not None:
143 self.NotifierCallback(False)
145 self.NetworkConnectionAvailable = False
146 self.list_updating = False
147 if callback is not None:
149 elif self.NotifierCallback is not None:
150 self.NotifierCallback(False)
152 if self.NetworkConnectionAvailable == True:
153 self.lastDownloadDate = time()
154 if self.list_updating is False and callback is None:
155 self.list_updating = True
156 self.ipkg.startCmd(IpkgComponent.CMD_UPDATE)
157 elif self.list_updating is False and callback is not None:
158 self.list_updating = True
159 self.NotifierCallback = callback
160 self.ipkg.startCmd(IpkgComponent.CMD_UPDATE)
161 elif self.list_updating is True and callback is not None:
162 self.NotifierCallback = callback
164 if self.list_updating and callback is not None:
165 if self.hardware_info.device_name != "dm7025":
167 l2cert = etpm.getCert(eTPM.TPMD_DT_LEVEL2_CERT)
170 l2key = validate_cert(l2cert, rootkey)
173 l3cert = etpm.getCert(eTPM.TPMD_DT_LEVEL3_CERT)
176 l3key = validate_cert(l3cert, l2key)
182 val = etpm.challenge(rnd)
183 result = decrypt_block(val, l3key)
184 if self.hardware_info.device_name == "dm7025" or result[80:88] == rnd:
185 self.NotifierCallback = callback
186 self.startIpkgListAvailable()
188 self.list_updating = False
189 if callback is not None:
191 elif self.NotifierCallback is not None:
192 self.NotifierCallback(False)
194 def ipkgCallback(self, event, param):
195 if event == IpkgComponent.EVENT_ERROR:
196 self.list_updating = False
197 if self.NotifierCallback is not None:
198 self.NotifierCallback(False)
199 elif event == IpkgComponent.EVENT_DONE:
200 if self.list_updating:
201 self.startIpkgListAvailable()
202 #print event, "-", param
205 def startIpkgListAvailable(self, callback = None):
206 if callback is not None:
207 self.list_updating = True
208 if self.list_updating:
209 if not self.UpdateConsole:
210 self.UpdateConsole = Console()
212 self.UpdateConsole.ePopen(cmd, self.IpkgListAvailableCB, callback)
214 def IpkgListAvailableCB(self, result, retval, extra_args = None):
215 (callback) = extra_args
217 if self.list_updating:
218 self.available_packetlist = []
219 for x in result.splitlines():
220 tokens = x.split(' - ')
221 name = tokens[0].strip()
222 if not any(name.endswith(x) for x in self.unwanted_extensions):
224 version = l > 1 and tokens[1].strip() or ""
225 descr = l > 2 and tokens[2].strip() or ""
226 self.available_packetlist.append([name, version, descr])
228 self.startInstallMetaPackage()
230 if self.UpdateConsole:
231 if len(self.UpdateConsole.appContainers) == 0:
234 self.list_updating = False
235 if self.UpdateConsole:
236 if len(self.UpdateConsole.appContainers) == 0:
237 if callback is not None:
240 def startInstallMetaPackage(self, callback = None):
241 if callback is not None:
242 self.list_updating = True
243 if self.list_updating:
244 if self.NetworkConnectionAvailable == True:
245 if not self.UpdateConsole:
246 self.UpdateConsole = Console()
247 cmd = "opkg install enigma2-meta enigma2-plugins-meta enigma2-skins-meta enigma2-drivers-meta"
248 self.UpdateConsole.ePopen(cmd, self.InstallMetaPackageCB, callback)
250 self.InstallMetaPackageCB(True)
252 def InstallMetaPackageCB(self, result, retval = None, extra_args = None):
253 (callback) = extra_args
255 self.fillPackagesIndexList()
257 self.startIpkgListInstalled()
259 if self.UpdateConsole:
260 if len(self.UpdateConsole.appContainers) == 0:
263 self.list_updating = False
264 if self.UpdateConsole:
265 if len(self.UpdateConsole.appContainers) == 0:
266 if callback is not None:
269 def startIpkgListInstalled(self, callback = None):
270 if callback is not None:
271 self.list_updating = True
272 if self.list_updating:
273 if not self.UpdateConsole:
274 self.UpdateConsole = Console()
275 cmd = "opkg list-installed"
276 self.UpdateConsole.ePopen(cmd, self.IpkgListInstalledCB, callback)
278 def IpkgListInstalledCB(self, result, retval, extra_args = None):
279 (callback) = extra_args
281 self.installed_packetlist = {}
282 for x in result.splitlines():
283 tokens = x.split(' - ')
284 name = tokens[0].strip()
285 if not any(name.endswith(x) for x in self.unwanted_extensions):
287 version = l > 1 and tokens[1].strip() or ""
288 self.installed_packetlist[name] = version
289 for package in self.packagesIndexlist[:]:
290 if not self.verifyPrerequisites(package[0]["prerequisites"]):
291 self.packagesIndexlist.remove(package)
292 for package in self.packagesIndexlist[:]:
293 attributes = package[0]["attributes"]
294 if attributes.has_key("packagetype"):
295 if attributes["packagetype"] == "internal":
296 self.packagesIndexlist.remove(package)
300 if self.UpdateConsole:
301 if len(self.UpdateConsole.appContainers) == 0:
304 self.list_updating = False
305 if self.UpdateConsole:
306 if len(self.UpdateConsole.appContainers) == 0:
307 if callback is not None:
310 def countUpdates(self, callback = None):
311 self.available_updates = 0
312 self.available_updatelist = []
313 for package in self.packagesIndexlist[:]:
314 attributes = package[0]["attributes"]
315 packagename = attributes["packagename"]
316 for x in self.available_packetlist:
317 if x[0] == packagename:
318 if self.installed_packetlist.has_key(packagename):
319 if self.installed_packetlist[packagename] != x[1]:
320 self.available_updates +=1
321 self.available_updatelist.append([packagename])
323 self.list_updating = False
324 if self.UpdateConsole:
325 if len(self.UpdateConsole.appContainers) == 0:
326 if callback is not None:
329 elif self.NotifierCallback is not None:
330 self.NotifierCallback(True)
331 self.NotifierCallback = None
333 def startIpkgUpdate(self, callback = None):
335 self.Console = Console()
337 self.Console.ePopen(cmd, self.IpkgUpdateCB, callback)
339 def IpkgUpdateCB(self, result, retval, extra_args = None):
340 (callback) = extra_args
343 if len(self.Console.appContainers) == 0:
344 if callback is not None:
348 def cleanupSoftwareTools(self):
349 self.list_updating = False
350 if self.NotifierCallback is not None:
351 self.NotifierCallback = None
353 if self.Console is not None:
354 if len(self.Console.appContainers):
355 for name in self.Console.appContainers.keys():
356 self.Console.kill(name)
357 if self.UpdateConsole is not None:
358 if len(self.UpdateConsole.appContainers):
359 for name in self.UpdateConsole.appContainers.keys():
360 self.UpdateConsole.kill(name)
362 def verifyPrerequisites(self, prerequisites):
363 if prerequisites.has_key("hardware"):
364 hardware_found = False
365 for hardware in prerequisites["hardware"]:
366 if hardware == self.hardware_info.device_name:
367 hardware_found = True
368 if not hardware_found:
372 iSoftwareTools = SoftwareTools()