class RunSoftwareUpdate(Screen, HelpableScreen): skin = """ <screen name="RunSoftwareUpdate" position="center,center" size="720,435" resolution="1280,720"> <widget name="update" position="10,10" size="700,400" font="Regular;20" halign="center" transparent="1" valign="center" /> <widget name="activity" position="10,420" size="700,5" /> </screen>""" def __init__(self, session, *args): Screen.__init__(self, session) HelpableScreen.__init__(self) self.setTitle(_("Software Update")) self.onTimerTick = [] self["update"] = ScrollLabel( _("Software update starting, please wait.\n\n")) self["activity"] = Slider(0, 100) self["actions"] = HelpableActionMap( self, ["OkCancelActions", "NavigationActions"], { "cancel": (self.keyCancel, _("Stop the update, if running, then exit")), "ok": (self.keyCancel, _("Stop the update, if running, then exit")), "top": (self.top, _("Move to first line / screen")), "pageUp": (self.pageUp, _("Move up a page / screen")), "up": (self.pageUp, _("Move up a page / screen")), # "first": (self.top, _("Move to first line / screen")), "left": (self.pageUp, _("Move up a page / screen")), "right": (self.pageDown, _("Move down a page / screen")), # "last": (self.bottom, _("Move to last line / screen")), "down": (self.pageDown, _("Move down a page / screen")), "pageDown": (self.pageDown, _("Move down a page / screen")), "bottom": (self.bottom, _("Move to last line / screen")) }, prio=0, description=_("Software Update Actions")) self.activity = 0 self.timer = eTimer() self.timer.callback.append(self.timeout) self.packageTotal = 0 self.downloadCount = 0 self.updateCount = 0 self.installCount = 0 self.removeCount = 0 self.deselectCount = 0 self.upgradeCount = 0 self.configureCount = 0 self.errorCount = 0 self.updateFlag = True self.opkg = OpkgComponent() self.opkg.addCallback(self.opkgCallback) self.onLayoutFinish.append(self.layoutFinished) def layoutFinished(self): self.opkg.startCmd(OpkgComponent.CMD_UPDATE) self.timer.start(25, True) def timeout(self): if self.activity < 0: self.timer.stop() self["activity"].hide() else: self.activity += 1 if self.activity == 100: self.activity = 0 self["activity"].setValue(self.activity) self.timer.start(100, True) for callback in self.onTimerTick: callback() def opkgCallback(self, event, parameter): if event == OpkgComponent.EVENT_DOWNLOAD: self.downloadCount += 1 if parameter.find( "_" ) == -1: # Only display the downloading of the feed packages. self["update"].appendText("%s: '%s'.\n" % (_("Downloading"), parameter)) elif event == OpkgComponent.EVENT_UPDATED: self.updateCount += 1 self["update"].appendText("%s: %s\n" % (_("Updated"), parameter)) elif event == OpkgComponent.EVENT_UPVERSION: self.upgradeCount += 1 self["update"].appendText("%s %s/%s: '%s'.\n" % (_("Updating"), self.upgradeCount, self.packageTotal, parameter)) elif event == OpkgComponent.EVENT_INSTALL: self.installCount += 1 self["update"].appendText("%s: '%s'.\n" % (_("Installing"), parameter)) elif event == OpkgComponent.EVENT_REMOVE: self.removeCount += 1 self["update"].appendText("%s: '%s'.\n" % (_("Removing"), parameter)) elif event == OpkgComponent.EVENT_CONFIGURING: self.configureCount += 1 self["update"].appendText("%s: '%s'.\n" % (_("Configuring"), parameter)) elif event == OpkgComponent.EVENT_MODIFIED: if config.plugins.softwaremanager.overwriteConfigFiles.value in ( "N", "Y"): self.opkg.write( True and config.plugins.softwaremanager.overwriteConfigFiles.value) else: self.session.openWithCallback( self.modificationCallback, MessageBox, _("Configuration file '%s' has been modified since it was installed, would you like to keep the modified version?" ) % parameter) elif event == OpkgComponent.EVENT_ERROR: self.errorCount += 1 elif event == OpkgComponent.EVENT_DONE: if self.updateFlag: self.updateFlag = False self.opkg.startCmd(OpkgComponent.CMD_UPGRADE_LIST) elif self.opkg.currentCommand == OpkgComponent.CMD_UPGRADE_LIST: self.packageTotal = len(self.opkg.getFetchedList()) if self.packageTotal: self.opkg.startCmd(OpkgComponent.CMD_UPGRADE, args={"testMode": False}) else: self.activity = -1 self["update"].appendText( "%s\n\n%s" % (_("No updates available."), _("Press OK on your remote control to continue."))) else: if self.errorCount == 0: self["update"].appendText("\n%s\n\n" % _("Update completed.")) self["update"].appendText( "%s\n" % ngettext("%d package was identified for upgrade.", "%d packages were identified for upgrade.", self.packageTotal) % self.packageTotal) self["update"].appendText("%s\n" % ngettext( "%d package was downloaded.", "%d packages were downloaded.", self.downloadCount) % self.downloadCount) self["update"].appendText( "%s\n" % ngettext("%d feed catalog package was updated.", "%d feed catalog packages were updated.", self.updateCount) % self.updateCount) self["update"].appendText("%s\n" % ngettext( "%d package was installed.", "%d packages were installed.", self.installCount) % self.installCount) self["update"].appendText("%s\n" % ngettext( "%d package was removed.", "%d packages were removed.", self.removeCount) % self.removeCount) self["update"].appendText("%s\n" % ngettext( "%d package was upgraded.", "%d packages were upgraded.", self.upgradeCount) % self.upgradeCount) self["update"].appendText("%s\n" % ngettext( "%d package was configured.", "%d packages were configured.", self.configureCount) % self.configureCount) if self.deselectCount: self["update"].appendText( "%s\n" % ngettext("%d package was deselected.", "%d packages were deselected.", self.deselectCount) % self.deselectCount) self["update"].appendText("\n%s\n" % _( "Deselected packages usually occur because those packaged are incompatible with existing packages. While this is mostly harmless it is possible that your %s %s may experience issues." ) % (displayBrand, displayModel)) else: error = _( "Your receiver might be unusable now. Please consult the manual for further assistance before rebooting your %s %s." ) % (displayBrand, displayModel) if self.upgradeCount == 0: error = _( "No updates were available. Please try again later." ) self["update"].appendText("%s: %s\n" % (_("Error"), error)) self.activity = -1 self["update"].appendText( "\n%s" % _("Press OK on your remote control to continue.")) def modificationCallback(self, answer): self.opkg.write("N" if answer else "Y") def keyCancel(self): if self.opkg.isRunning(): self.opkg.stop() self.opkg.removeCallback(self.opkgCallback) if self.upgradeCount != 0 and self.errorCount == 0: self.restoreMetrixHD() else: self.close() def keyCancelCallback(self, answer): if answer: self.session.open(TryQuitMainloop, retvalue=QUIT_REBOOT) self.close() def top(self): self["update"].moveTop() def pageUp(self): self["update"].pageUp() def pageDown(self): self["update"].pageDown() def bottom(self): self["update"].moveBottom() def createSummary(self): return RunSoftwareUpdateSummary def restoreMetrixHD( self ): # TODO: call this only after metrix update / move this to Metrix Plugin try: if config.skin.primary_skin.value == "MetrixHD/skin.MySkin.xml": if not exists("/usr/share/enigma2/MetrixHD/skin.MySkin.xml"): from Plugins.SystemPlugins.SoftwareManager.BackupRestore import RestoreMyMetrixHD self.session.openWithCallback(self.restoreMetrixHDCallback, RestoreMyMetrixHD) return elif config.plugins.MyMetrixLiteOther.EHDenabled.value != '0': from Plugins.Extensions.MyMetrixLite.ActivateSkinSettings import ActivateSkinSettings ActivateSkinSettings().RefreshIcons() except: pass self.restoreMetrixHDCallback() def restoreMetrixHDCallback(self, ret=None): self.session.openWithCallback( self.keyCancelCallback, MessageBox, _("Upgrade finished.") + " " + _("Do you want to reboot your %s %s?") % (displayBrand, displayModel))
class Opkg(Screen): def __init__(self, session, cmdList=[]): Screen.__init__(self, session) self.cmdList = cmdList self.sliderPackages = {} self.slider = Slider(0, len(cmdList)) self["slider"] = self.slider self.activityslider = Slider(0, 100) self["activityslider"] = self.activityslider self.status = Label(_("Preparing... Please wait")) self["status"] = self.status self.package = Label() self["package"] = self.package self.packages = 0 self.error = 0 self.processed_packages = [] self.activity = 0 self.activityTimer = eTimer() self.activityTimer.callback.append(self.doActivityTimer) #self.activityTimer.start(100, False) self.opkg = OpkgComponent() self.opkg.addCallback(self.opkgCallback) self.runningCmd = None self.runNextCmd() self["actions"] = ActionMap(["WizardActions"], { "ok": self.exit, "back": self.exit }, -1) def runNextCmd(self): if self.runningCmd is None: self.runningCmd = 0 else: self.runningCmd += 1 print(len(self.cmdList), self.runningCmd) if len(self.cmdList) - 1 < self.runningCmd: self.activityslider.setValue(0) self.slider.setValue(len(self.cmdList)) self.package.setText("") self.status.setText( ngettext( "Done - Installed, updated or removed %d package (%s)", "Done - Installed, updated or removed %d packages (%s)", self.packages) % (self.packages, ngettext("with %d error", "with %d errors", self.error) % self.error)) return False else: cmd = self.cmdList[self.runningCmd] self.slider.setValue(self.runningCmd) self.opkg.startCmd(cmd[0], args=cmd[1]) self.startActivityTimer() def doActivityTimer(self): if not self.opkg.isRunning(): self.stopActivityTimer() else: self.activity += 1 if self.activity == 100: self.activity = 0 self.activityslider.setValue(self.activity) def startActivityTimer(self): self.activityTimer.start(100, False) def stopActivityTimer(self): self.activityTimer.stop() def opkgCallback(self, event, param): if event == OpkgComponent.EVENT_DOWNLOAD: self.status.setText(_("Downloading")) elif event == OpkgComponent.EVENT_UPGRADE: if param in self.sliderPackages: self.slider.setValue(self.sliderPackages[param]) self.package.setText(param) self.status.setText(_("Updating")) if not param in self.processed_packages: self.processed_packages.append(param) self.packages += 1 elif event == OpkgComponent.EVENT_INSTALL: self.package.setText(param) self.status.setText(_("Installing")) if not param in self.processed_packages: self.processed_packages.append(param) self.packages += 1 elif event == OpkgComponent.EVENT_REMOVE: self.package.setText(param) self.status.setText(_("Removing")) if not param in self.processed_packages: self.processed_packages.append(param) self.packages += 1 elif event == OpkgComponent.EVENT_CONFIGURING: self.package.setText(param) self.status.setText(_("Configuring")) elif event == OpkgComponent.EVENT_ERROR: self.error += 1 elif event == OpkgComponent.EVENT_DONE: self.runNextCmd() elif event == OpkgComponent.EVENT_MODIFIED: self.session.openWithCallback( self.modificationCallback, MessageBox, _("A configuration file (%s) has been modified since it was installed. Would you like to keep the modified version?" ) % (param)) def modificationCallback(self, res): self.opkg.write(res and "N" or "Y") def exit(self): if not self.opkg.isRunning(): self.close()
class UpdatePlugin(Screen, ProtectedScreen): skin = """ <screen name="UpdatePlugin" position="center,center" size="550,300"> <widget name="activityslider" position="0,0" size="550,5" /> <widget name="slider" position="0,150" size="550,30" /> <widget source="package" render="Label" position="10,30" size="540,20" font="Regular;18" halign="center" valign="center" backgroundColor="#25062748" transparent="1" /> <widget source="status" render="Label" position="10,180" size="540,100" font="Regular;20" halign="center" valign="center" backgroundColor="#25062748" transparent="1" /> </screen>""" def __init__(self, session, *args): Screen.__init__(self, session) ProtectedScreen.__init__(self) self.sliderPackages = { "enigma2": 1, "openvision": 2 } self.setTitle(_("Software update")) self.slider = Slider(0, 4) self["slider"] = self.slider self.activityslider = Slider(0, 100) self["activityslider"] = self.activityslider self.status = StaticText(_("Please wait...")) self["status"] = self.status self.package = StaticText(_("Package list update")) self["package"] = self.package self.oktext = _("Press OK on your remote control to continue.") self.packages = 0 self.error = 0 self.processed_packages = [] self.total_packages = None self.channellist_only = 0 self.channellist_name = '' self.updating = False self.opkg = OpkgComponent() self.opkg.addCallback(self.opkgCallback) self.onClose.append(self.__close) self["actions"] = ActionMap(["WizardActions"], { "ok": self.exit, "back": self.exit }, -1) self.activity = 0 self.activityTimer = eTimer() self.activityTimer.callback.append(self.checkTraficLight) self.activityTimer.callback.append(self.doActivityTimer) self.activityTimer.start(100, True) def isProtected(self): return config.ParentalControl.setuppinactive.value and\ (not config.ParentalControl.config_sections.main_menu.value and not config.ParentalControl.config_sections.configuration.value or hasattr(self.session, 'infobar') and self.session.infobar is None) and\ config.ParentalControl.config_sections.software_update.value def checkTraficLight(self): self.activityTimer.callback.remove(self.checkTraficLight) self.activityTimer.start(100, False) status = None message = None abort = False picon = MessageBox.TYPE_ERROR url = "https://openvision.tech/trafficlight" # try to fetch the trafficlight json from the website try: status = dict(json.load(urlopen(url, timeout=5))) print("[SoftwareUpdate] status is: ", status) except: pass # process the status fetched if status is not None: try: # get image version and machine name machine = getBoxType() version = open("/etc/issue").readlines()[-2].split()[1] # do we have an entry for this version if version in status and machine in status[version]['machines']: if 'abort' in status[version]: abort = status[version]['abort'] if 'from' in status[version]: starttime = datetime.datetime.strptime(status[version]['from'], '%Y%m%d%H%M%S') else: starttime = datetime.datetime.now() if 'to' in status[version]: endtime = datetime.datetime.strptime(status[version]['to'], '%Y%m%d%H%M%S') else: endtime = datetime.datetime.now() if (starttime <= datetime.datetime.now() and endtime >= datetime.datetime.now()): message = str(status[version]['message']) # check if we have per-language messages if type(message) is dict: lang = language.getLanguage() if lang in message: message = message[lang] elif 'en_EN' in message: message = message['en_EN'] else: message = _("The current image might not be stable.\nFor more information see %s.") % ("openvision.tech") except Exception as e: print("[SoftwareUpdate] status error: ", str(e)) message = _("The current image might not be stable.\nFor more information see %s.") % ("openvision.tech") # or display a generic warning if fetching failed else: message = _("The status of the current image could not be checked because %s can not be reached.") % ("openvision.tech") # show the user the message first if message is not None: if abort: self.session.openWithCallback(self.close, MessageBox, message, type=MessageBox.TYPE_ERROR, picon = picon) else: message += "\n\n" + _("Do you want to update your receiver?") self.session.openWithCallback(self.startActualUpdate, MessageBox, message, picon = picon) # no message, continue with the update else: self.startActualUpdate(True) def getLatestImageTimestamp(self): def gettime(url): try: return time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime(calendar.timegm(urlopen("%s/Packages.gz" % url).info().getdate('Last-Modified'))-time.altzone)) except: return "" return sorted([gettime(open("/etc/opkg/%s" % file, "r").readlines()[0].split()[2]) for file in os.listdir("/etc/opkg") if not file.startswith("3rd-party") and file not in ("arch.conf", "opkg.conf", "picons-feed.conf")], reverse=True)[0] def startActualUpdate(self,answer): if answer: self.updating = True self.opkg.startCmd(OpkgComponent.CMD_UPDATE) else: self.close() def doActivityTimer(self): self.activity += 1 if self.activity == 100: self.activity = 0 self.activityslider.setValue(self.activity) def showUpdateCompletedMessage(self): self.setEndMessage(ngettext("Update completed, %d package was installed.", "Update completed, %d packages were installed.", self.packages) % self.packages) def opkgCallback(self, event, param): if event == OpkgComponent.EVENT_DOWNLOAD: self.status.setText(_("Downloading")) elif event == OpkgComponent.EVENT_UPGRADE: if param in self.sliderPackages: self.slider.setValue(self.sliderPackages[param]) self.package.setText(param) self.status.setText(_("Updating") + ": %s/%s" % (self.packages, self.total_packages)) if not param in self.processed_packages: self.processed_packages.append(param) self.packages += 1 elif event == OpkgComponent.EVENT_INSTALL: self.package.setText(param) self.status.setText(_("Installing")) if not param in self.processed_packages: self.processed_packages.append(param) self.packages += 1 elif event == OpkgComponent.EVENT_REMOVE: self.package.setText(param) self.status.setText(_("Removing")) if not param in self.processed_packages: self.processed_packages.append(param) self.packages += 1 elif event == OpkgComponent.EVENT_CONFIGURING: self.package.setText(param) self.status.setText(_("Configuring")) elif event == OpkgComponent.EVENT_MODIFIED: if config.plugins.softwaremanager.overwriteConfigFiles.value in ("N", "Y"): self.opkg.write(True and config.plugins.softwaremanager.overwriteConfigFiles.value) else: self.session.openWithCallback( self.modificationCallback, MessageBox, _("A configuration file (%s) has been modified since it was installed.\nDo you want to keep your modifications?") % (param) ) elif event == OpkgComponent.EVENT_ERROR: self.error += 1 elif event == OpkgComponent.EVENT_DONE: if self.updating: self.updating = False self.opkg.startCmd(OpkgComponent.CMD_UPGRADE_LIST) elif self.opkg.currentCommand == OpkgComponent.CMD_UPGRADE_LIST: self.total_packages = len(self.opkg.getFetchedList()) if self.total_packages: latestImageTimestamp = self.getLatestImageTimestamp() if latestImageTimestamp: message = _("Do you want to update your receiver to %s?") % latestImageTimestamp + "\n" else: message = _("Do you want to update your receiver?") + "\n" message += "(" + (ngettext("%s updated package available", "%s updated packages available", self.total_packages) % self.total_packages) + ")" if self.total_packages > 150: choices = [(_("Update and reboot"), "cold")] message += " " + _("Reflash recommended!") else: choices = [(_("Update and reboot (recommended)"), "cold"), (_("Update and ask to reboot"), "hot")] choices.append((_("Update channel list only"), "channels")) choices.append((_("Show packages to be updated"), "showlist")) else: message = _("No updates available") choices = [] if fileExists("/home/root/opkgupgrade.log"): choices.append((_("Show latest update log"), "log")) choices.append((_("Show latest commits"), "commits")) choices.append((_("Cancel"), "")) self.session.openWithCallback(self.startActualUpgrade, ChoiceBox, title=message, list=choices, windowTitle=self.title) elif self.channellist_only > 0: if self.channellist_only == 1: self.setEndMessage(_("Could not find installed channel list.")) elif self.channellist_only == 2: self.slider.setValue(2) self.opkg.startCmd(OpkgComponent.CMD_REMOVE, {'package': self.channellist_name}) self.channellist_only += 1 elif self.channellist_only == 3: self.slider.setValue(3) self.opkg.startCmd(OpkgComponent.CMD_INSTALL, {'package': self.channellist_name}) self.channellist_only += 1 elif self.channellist_only == 4: self.showUpdateCompletedMessage() eDVBDB.getInstance().reloadBouquets() eDVBDB.getInstance().reloadServicelist() elif self.error == 0: self.showUpdateCompletedMessage() else: self.activityTimer.stop() self.activityslider.setValue(0) error = _("Your receiver might be unusable now. Please consult the manual for further assistance before rebooting your receiver.") if self.packages == 0: error = _("No updates available. Please try again later.") if self.updating: error = _("Update failed. Your receiver does not have a working internet connection.") self.status.setText(_("Error") + " - " + error) elif event == OpkgComponent.EVENT_LISTITEM: if 'enigma2-plugin-settings-' in param[0] and self.channellist_only > 0: self.channellist_name = param[0] self.channellist_only = 2 #print(event, "-", param) pass def setEndMessage(self, txt): self.slider.setValue(4) self.activityTimer.stop() self.activityslider.setValue(0) self.package.setText(txt) self.status.setText(self.oktext) def startActualUpgrade(self, answer): if not answer or not answer[1]: self.close() return if answer[1] == "cold": self.session.open(TryQuitMainloop,retvalue=42) self.close() elif answer[1] == "channels": self.channellist_only = 1 self.slider.setValue(1) self.opkg.startCmd(OpkgComponent.CMD_LIST, args = {'installed_only': True}) elif answer[1] == "commits": self.session.openWithCallback(boundFunction(self.opkgCallback, OpkgComponent.EVENT_DONE, None), CommitInfo) elif answer[1] == "showlist": text = "\n".join([x[0] for x in sorted(self.opkg.getFetchedList(), key=lambda d: d[0])]) self.session.openWithCallback(boundFunction(self.opkgCallback, OpkgComponent.EVENT_DONE, None), TextBox, text, _("Packages to update"), True) elif answer[1] == "log": text = open("/home/root/opkgupgrade.log", "r").read() self.session.openWithCallback(boundFunction(self.opkgCallback, OpkgComponent.EVENT_DONE, None), TextBox, text, _("Latest update log"), True) else: self.opkg.startCmd(OpkgComponent.CMD_UPGRADE, args = {'test_only': False}) def modificationCallback(self, res): self.opkg.write(res and "N" or "Y") def exit(self): if not self.opkg.isRunning(): if self.packages != 0 and self.error == 0 and self.channellist_only == 0: self.session.openWithCallback(self.exitAnswer, MessageBox, _("Update completed. Do you want to reboot your receiver?")) else: self.close() else: if not self.updating: self.close() def exitAnswer(self, result): if result is not None and result: self.session.open(TryQuitMainloop, retvalue=2) self.close() def __close(self): self.opkg.removeCallback(self.opkgCallback)
class UpdatePlugin(Screen, ProtectedScreen): skin = """ <screen name="UpdatePlugin" position="center,center" size="550,300"> <widget name="activityslider" position="0,0" size="550,5" /> <widget name="slider" position="0,150" size="550,30" /> <widget source="package" render="Label" position="10,30" size="540,20" font="Regular;18" halign="center" valign="center" backgroundColor="#25062748" transparent="1" /> <widget source="status" render="Label" position="10,180" size="540,100" font="Regular;20" halign="center" valign="center" backgroundColor="#25062748" transparent="1" /> </screen>""" def __init__(self, session, *args): Screen.__init__(self, session) ProtectedScreen.__init__(self) self.sliderPackages = {"gigablue-": 1, "enigma2": 2, "teamblue-": 3} self.setTitle(_("Software update")) self.slider = Slider(0, 4) self["slider"] = self.slider self.activityslider = Slider(0, 100) self["activityslider"] = self.activityslider self.status = StaticText(_("Please wait...")) self["status"] = self.status self.package = StaticText(_("Package list update")) self["package"] = self.package self.oktext = _("Press OK on your remote control to continue.") self.packages = 0 self.error = 0 self.processed_packages = [] self.total_packages = None self.channellist_only = 0 self.channellist_name = '' self.updating = False self.opkg = OpkgComponent() self.opkg.addCallback(self.opkgCallback) self.onClose.append(self.__close) self["actions"] = ActionMap(["WizardActions"], { "ok": self.exit, "back": self.exit }, -1) self.activity = 0 self.activityTimer = eTimer() self.activityTimer.callback.append(self.checkTraficLight) self.activityTimer.callback.append(self.doActivityTimer) self.activityTimer.start(100, True) def isProtected(self): return config.ParentalControl.setuppinactive.value and\ (not config.ParentalControl.config_sections.main_menu.value and not config.ParentalControl.config_sections.configuration.value or hasattr(self.session, 'infobar') and self.session.infobar is None) and\ config.ParentalControl.config_sections.software_update.value def checkTraficLight(self): self.activityTimer.callback.remove(self.checkTraficLight) self.activityTimer.start(100, False) message = "" picon = None default = True url = "http://images.teamblue.tech/status/%s-%s/" % (getImageVersion(), getImageType()) # print "[SoftwareUpdate] url status: ", url try: # TODO: Use Twisted's URL fetcher, urlopen is evil. And it can # run in parallel to the package update. try: status = urlopen(url, timeout=5).read().split('!', 1) print status except: # bypass the certificate check from ssl import _create_unverified_context status = urlopen( url, timeout=5, context=_create_unverified_context()).read().split('!', 1) print status # prefer getMachineBuild if getMachineBuild() in status[0].split(','): message = len(status) > 1 and status[1] or _( "The current software might not be stable.\nFor more information see %s." ) % ("http://images.teamblue.tech") picon = MessageBox.TYPE_ERROR default = False # only use getBoxType if no getMachineBuild elif getBoxType() in status[0].split(','): message = len(status) > 1 and status[1] or _( "The current software might not be stable.\nFor more information see %s." ) % ("http://images.teamblue.tech") picon = MessageBox.TYPE_ERROR default = False except: message = _( "The status of the current software could not be checked because %s can not be reached." ) % ("http://images.teamblue.tech") picon = MessageBox.TYPE_ERROR default = False if default: self.showDisclaimer() else: message += "\n" + _("Do you want to update your receiver?") self.session.openWithCallback(self.startActualUpdate, MessageBox, message, default=default, picon=picon) def showDisclaimer(self, justShow=False): if config.usage.show_update_disclaimer.value or justShow: message = _( "With this disclaimer the teamBlue team is informing you that we are working with nightly builds and it might be that after the upgrades your set top box \ is not anymore working as expected. Therefore it is recommended to create backups. If something went wrong you can easily and quickly restore. \ If you discover 'bugs' please keep them reported on www.teamblue.tech.\n\nDo you understand this?" ) list = not justShow and [ (_("no"), False), (_("yes"), True), (_("yes") + " " + _("and never show this message again"), "never") ] or [] self.session.openWithCallback(boundFunction( self.disclaimerCallback, justShow), MessageBox, message, list=list, title=_("Disclaimer")) else: self.startActualUpdate(True) def disclaimerCallback(self, justShow, answer): if answer == "never": config.usage.show_update_disclaimer.value = False config.usage.show_update_disclaimer.save() if justShow and answer: self.ipkgCallback(IpkgComponent.EVENT_DONE, None) else: self.startActualUpdate(answer) def getLatestImageTimestamp(self): url = "http://images.teamblue.tech/status/%s-%s/buildtimestamp-%s" % ( getImageVersion(), getImageType(), getBoxType()) # print "[SoftwareUpdate] url buildtimestamp: ", url try: # TODO: Use Twisted's URL fetcher, urlopen is evil. And it can # run in parallel to the package update. from time import strftime from datetime import datetime try: latestImageTimestamp = datetime.fromtimestamp( int(urlopen(url, timeout=5).read())).strftime( _("%Y-%m-%d %H:%M")) except: # bypass the certificate check from ssl import _create_unverified_context latestImageTimestamp = datetime.fromtimestamp( int( urlopen(url, timeout=5, context=_create_unverified_context()).read()) ).strftime(_("%Y-%m-%d %H:%M")) except: latestImageTimestamp = "" print "[SoftwareUpdate] latestImageTimestamp:", latestImageTimestamp return latestImageTimestamp def startActualUpdate(self, answer): if answer: self.updating = True self.opkg.startCmd(OpkgComponent.CMD_UPDATE) else: self.close() def doActivityTimer(self): self.activity += 1 if self.activity == 100: self.activity = 0 self.activityslider.setValue(self.activity) def showUpdateCompletedMessage(self): self.setEndMessage( ngettext("Update completed, %d package was installed.", "Update completed, %d packages were installed.", self.packages) % self.packages) def opkgCallback(self, event, param): if event == OpkgComponent.EVENT_DOWNLOAD: self.status.setText(_("Downloading")) elif event == OpkgComponent.EVENT_UPGRADE: if param in self.sliderPackages: self.slider.setValue(self.sliderPackages[param]) self.package.setText(param) self.status.setText( _("Updating") + ": %s/%s" % (self.packages, self.total_packages)) if not param in self.processed_packages: self.processed_packages.append(param) self.packages += 1 elif event == OpkgComponent.EVENT_INSTALL: self.package.setText(param) self.status.setText(_("Installing")) if not param in self.processed_packages: self.processed_packages.append(param) self.packages += 1 elif event == OpkgComponent.EVENT_REMOVE: self.package.setText(param) self.status.setText(_("Removing")) if not param in self.processed_packages: self.processed_packages.append(param) self.packages += 1 elif event == OpkgComponent.EVENT_CONFIGURING: self.package.setText(param) self.status.setText(_("Configuring")) elif event == OpkgComponent.EVENT_MODIFIED: if config.plugins.softwaremanager.overwriteConfigFiles.value in ( "N", "Y"): self.opkg.write( True and config.plugins.softwaremanager.overwriteConfigFiles.value) else: self.session.openWithCallback( self.modificationCallback, MessageBox, _("A configuration file (%s) has been modified since it was installed.\nDo you want to keep your modifications?" ) % (param)) elif event == OpkgComponent.EVENT_ERROR: self.error += 1 elif event == OpkgComponent.EVENT_DONE: if self.updating: self.updating = False self.opkg.startCmd(OpkgComponent.CMD_UPGRADE_LIST) elif self.opkg.currentCommand == OpkgComponent.CMD_UPGRADE_LIST: self.total_packages = len(self.opkg.getFetchedList()) if self.total_packages: latestImageTimestamp = self.getLatestImageTimestamp() if latestImageTimestamp: message = _( "Latest available teamBlue %s build is from: %s" ) % (getImageVersion(), self.getLatestImageTimestamp()) + "\n" message += _( "Do you want to update your receiver?") + "\n" else: message = _( "Do you want to update your receiver?") + "\n" message += "(" + (ngettext( "%s updated package available", "%s updated packages available", self.total_packages) % self.total_packages) + ")" if self.total_packages > 150: message += " " + _("Reflash recommended!") choices = [ (_("Update and reboot (recommended)"), "cold"), (_("Update and ask to reboot"), "hot"), #(_("Update channel list only"), "channels"), (_("Show packages to be updated"), "showlist") ] else: message = _("No updates available") choices = [] if fileExists("/home/root/opkgupgrade.log"): choices.append((_("Show latest update log"), "log")) choices.append((_("Show latest commits"), "commits")) if not config.usage.show_update_disclaimer.value: choices.append((_("Show disclaimer"), "disclaimer")) choices.append((_("Cancel"), "")) self.session.openWithCallback(self.startActualUpgrade, ChoiceBox, title=message, list=choices, windowTitle=self.title) elif self.channellist_only > 0: if self.channellist_only == 1: self.setEndMessage( _("Could not find installed channel list.")) elif self.channellist_only == 2: self.slider.setValue(2) self.opkg.startCmd(OpkgComponent.CMD_REMOVE, {'package': self.channellist_name}) self.channellist_only += 1 elif self.channellist_only == 3: self.slider.setValue(3) self.opkg.startCmd(OpkgComponent.CMD_INSTALL, {'package': self.channellist_name}) self.channellist_only += 1 elif self.channellist_only == 4: self.showUpdateCompletedMessage() eDVBDB.getInstance().reloadBouquets() eDVBDB.getInstance().reloadServicelist() elif self.error == 0: self.showUpdateCompletedMessage() else: self.activityTimer.stop() self.activityslider.setValue(0) error = _( "Your receiver might be unusable now. Please consult the manual for further assistance before rebooting your receiver." ) if self.packages == 0: error = _("No updates available. Please try again later.") if self.updating: error = _( "Update failed. Your receiver does not have a working internet connection." ) self.status.setText(_("Error") + " - " + error) elif event == OpkgComponent.EVENT_LISTITEM: if 'enigma2-plugin-settings-' in param[ 0] and self.channellist_only > 0: self.channellist_name = param[0] self.channellist_only = 2 #print event, "-", param pass def setEndMessage(self, txt): self.slider.setValue(4) self.activityTimer.stop() self.activityslider.setValue(0) self.package.setText(txt) self.status.setText(self.oktext) def startActualUpgrade(self, answer): if not answer or not answer[1]: self.close() return if answer[1] == "cold": self.session.open(TryQuitMainloop, retvalue=42) self.close() elif answer[1] == "channels": self.channellist_only = 1 self.slider.setValue(1) self.opkg.startCmd(OpkgComponent.CMD_LIST, args={'installed_only': True}) elif answer[1] == "commits": self.session.openWithCallback( boundFunction(self.opkgCallback, OpkgComponent.EVENT_DONE, None), CommitInfo) elif answer[1] == "disclaimer": self.showDisclaimer(justShow=True) elif answer[1] == "showlist": text = "\n".join([ x[0] for x in sorted(self.opkg.getFetchedList(), key=lambda d: d[0]) ]) self.session.openWithCallback( boundFunction(self.opkgCallback, OpkgComponent.EVENT_DONE, None), TextBox, text, _("Packages to update"), True) elif answer[1] == "log": text = open("/home/root/opkgupgrade.log", "r").read() self.session.openWithCallback( boundFunction(self.opkgCallback, OpkgComponent.EVENT_DONE, None), TextBox, text, _("Latest update log"), True) else: self.opkg.startCmd(OpkgComponent.CMD_UPGRADE, args={'test_only': False}) def modificationCallback(self, res): self.opkg.write(res and "N" or "Y") def exit(self): if not self.opkg.isRunning(): if self.packages != 0 and self.error == 0 and self.channellist_only == 0: self.session.openWithCallback( self.exitAnswer, MessageBox, _("Update completed. Do you want to reboot your receiver?") ) else: self.close() else: if not self.updating: self.close() def exitAnswer(self, result): if result is not None and result: self.session.open(TryQuitMainloop, retvalue=2) self.close() def __close(self): self.opkg.removeCallback(self.opkgCallback)