Merge commit 'origin/bug_578_translateable_meta_descriptions'
authoracid-burn <acid-burn@opendreambox.org>
Tue, 5 Oct 2010 11:00:54 +0000 (13:00 +0200)
committeracid-burn <acid-burn@opendreambox.org>
Tue, 5 Oct 2010 11:00:54 +0000 (13:00 +0200)
Conflicts:
lib/python/Plugins/Extensions/GraphMultiEPG/meta/plugin_graphmultiepg.xml

1  2 
lib/python/Plugins/SystemPlugins/SoftwareManager/SoftwareTools.py
lib/python/Plugins/SystemPlugins/SoftwareManager/plugin.py

index a29a5e993db1f2b174d6766a02aede8ba1e250e0,e3a9acb7cc776b60594b7b9dec4355102000c1cb..879bec1609c73efee7d790ff14fecb91a5b28616
@@@ -1,5 -1,4 +1,5 @@@
 -from enigma import eConsoleAppContainer
 +# -*- coding: iso-8859-1 -*-
 +from enigma import eConsoleAppContainer,eTPM
  from Components.Console import Console
  from Components.About import about
  from Components.DreamInfoHandler import DreamInfoHandler
@@@ -9,49 -8,9 +9,49 @@@ from Components.Ipkg import IpkgCompone
  from Components.Network import iNetwork
  from Tools.Directories import pathExists, fileExists, resolveFilename, SCOPE_METADIR
  from Tools.HardwareInfo import HardwareInfo
 +import sha
  
  from time import time
  
 +def bin2long(s):
 +      return reduce( lambda x,y:(x<<8L)+y, map(ord, s))
 +
 +def long2bin(l):
 +      res = ""
 +      for byte in range(128):
 +              res += chr((l >> (1024 - (byte + 1) * 8)) & 0xff)
 +      return res
 +
 +def rsa_pub1024(src, mod):
 +      return long2bin(pow(bin2long(src), 65537, bin2long(mod)))
 +      
 +def decrypt_block(src, mod):
 +      if len(src) != 128 and len(src) != 202:
 +              return None
 +      dest = rsa_pub1024(src[:128], mod)
 +      hash = sha.new(dest[1:107])
 +      if len(src) == 202:
 +              hash.update(src[131:192])       
 +      result = hash.digest()
 +      if result == dest[107:127]:
 +              return dest
 +      return None
 +
 +def validate_cert(cert, key):
 +      buf = decrypt_block(cert[8:], key) 
 +      if buf is None:
 +              return None
 +      return buf[36:107] + cert[139:196]
 +
 +def read_random():
 +      try:
 +              fd = open("/dev/urandom", "r")
 +              buf = fd.read(8)
 +              fd.close()
 +              return buf
 +      except:
 +              return None
 +
  class SoftwareTools(DreamInfoHandler):
        lastDownloadDate = None
        NetworkConnectionAvailable = None
@@@ -69,7 -28,7 +69,7 @@@
                else:
                        self.ImageVersion = 'Stable'
                self.language = language.getLanguage()[:2] # getLanguage returns e.g. "fi_FI" for "language_country"
-               DreamInfoHandler.__init__(self, self.statusCallback, blocking = False, neededTag = 'ALL_TAGS', neededFlag = self.ImageVersion, language = self.language)
+               DreamInfoHandler.__init__(self, self.statusCallback, blocking = False, neededTag = 'ALL_TAGS', neededFlag = self.ImageVersion)
                self.directory = resolveFilename(SCOPE_METADIR)
                self.hardware_info = HardwareInfo()
                self.list = List([])
                                self.getUpdates()
  
        def getUpdates(self, callback = None):
 -              if SoftwareTools.NetworkConnectionAvailable == True:
 -                      SoftwareTools.lastDownloadDate = time()
 -                      if SoftwareTools.list_updating is False and callback is None:
 -                              SoftwareTools.list_updating = True
 -                              self.ipkg.startCmd(IpkgComponent.CMD_UPDATE)
 -                      elif SoftwareTools.list_updating is False and callback is not None:
 -                              SoftwareTools.list_updating = True
 -                              self.NotifierCallback = callback
 -                              self.ipkg.startCmd(IpkgComponent.CMD_UPDATE)
 -                      elif SoftwareTools.list_updating is True and callback is not None:
 -                              #update info collecting already in progress
 -                              self.NotifierCallback = callback
 +              if SoftwareTools.lastDownloadDate is None:
 +                      if  self.hardware_info.device_name != "dm7025":
 +                              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', ':', '?']
 +                              etpm = eTPM()
 +                              l2cert = etpm.getCert(eTPM.TPMD_DT_LEVEL2_CERT)
 +                              if l2cert is None:
 +                                      return
 +                              l2key = validate_cert(l2cert, rootkey)
 +                              if l2key is None:
 +                                      return
 +                              l3cert = etpm.getCert(eTPM.TPMD_DT_LEVEL3_CERT)
 +                              if l3cert is None:
 +                                      print "please run the genuine dreambox plugin"
 +                                      return
 +                              l3key = validate_cert(l3cert, l2key)
 +                              if l3key is None:
 +                                      return
 +                              rnd = read_random()
 +                              if rnd is None:
 +                                      return
 +                              val = etpm.challenge(rnd)
 +                              result = decrypt_block(val, l3key)
 +                      if self.hardware_info.device_name == "dm7025" or result[80:88] == rnd:
 +                              if SoftwareTools.NetworkConnectionAvailable == True:
 +                                      SoftwareTools.lastDownloadDate = time()
 +                                      if SoftwareTools.list_updating is False and callback is None:
 +                                              SoftwareTools.list_updating = True
 +                                              self.ipkg.startCmd(IpkgComponent.CMD_UPDATE)
 +                                      elif SoftwareTools.list_updating is False and callback is not None:
 +                                              SoftwareTools.list_updating = True
 +                                              self.NotifierCallback = callback
 +                                              self.ipkg.startCmd(IpkgComponent.CMD_UPDATE)
 +                                      elif SoftwareTools.list_updating is True and callback is not None:
 +                                              self.NotifierCallback = callback
 +                              else:
 +                                      SoftwareTools.list_updating = False
 +                                      if callback is not None:
 +                                              callback(False)
 +                                      elif self.NotifierCallback is not None:
 +                                              self.NotifierCallback(False)
 +                      else:
 +                              SoftwareTools.NetworkConnectionAvailable = False
 +                              SoftwareTools.list_updating = False
 +                              if callback is not None:
 +                                      callback(False)
 +                              elif self.NotifierCallback is not None:
 +                                      self.NotifierCallback(False)            
                else:
 -                      SoftwareTools.list_updating = False
 -                      if callback is not None:
 -                              callback(False)
 -                      elif self.NotifierCallback is not None:
 -                              self.NotifierCallback(False)
 +                      if SoftwareTools.NetworkConnectionAvailable == True:
 +                              SoftwareTools.lastDownloadDate = time()
 +                              if SoftwareTools.list_updating is False and callback is None:
 +                                      SoftwareTools.list_updating = True
 +                                      self.ipkg.startCmd(IpkgComponent.CMD_UPDATE)
 +                              elif SoftwareTools.list_updating is False and callback is not None:
 +                                      SoftwareTools.list_updating = True
 +                                      self.NotifierCallback = callback
 +                                      self.ipkg.startCmd(IpkgComponent.CMD_UPDATE)
 +                              elif SoftwareTools.list_updating is True and callback is not None:
 +                                      self.NotifierCallback = callback
 +                      else:
 +                              SoftwareTools.list_updating = False
 +                              if callback is not None:
 +                                      callback(False)
 +                              elif self.NotifierCallback is not None:
 +                                      self.NotifierCallback(False)
  
        def ipkgCallback(self, event, param):
                if event == IpkgComponent.EVENT_ERROR:
index 998376782764abbb9f2f850e2411fcd7bf723882,286636ccf1ef86e472e281a96896d6a8b0cc4533..0cc577769bc80ef010c10299f39139c9cffcda86
@@@ -14,8 -14,7 +14,8 @@@ from Components.MenuList import MenuLis
  from Components.Sources.List import List
  from Components.Slider import Slider
  from Components.Harddisk import harddiskmanager
 -from Components.config import config,getConfigListEntry, ConfigSubsection, ConfigText, ConfigLocations
 +from Components.config import config,getConfigListEntry, ConfigSubsection, ConfigText, ConfigLocations, ConfigYesNo, ConfigSelection
 +from Components.ConfigList import ConfigListScreen
  from Components.Console import Console
  from Components.MultiContent import MultiContentEntryText, MultiContentEntryPixmapAlphaTest
  from Components.SelectionList import SelectionList
@@@ -27,8 -26,7 +27,8 @@@ from Components.AVSwitch import AVSwitc
  from Components.Network import iNetwork
  from Tools.Directories import pathExists, fileExists, resolveFilename, SCOPE_PLUGINS, SCOPE_CURRENT_PLUGIN, SCOPE_CURRENT_SKIN, SCOPE_METADIR
  from Tools.LoadPixmap import LoadPixmap
 -from enigma import eTimer, quitMainloop, RT_HALIGN_LEFT, RT_VALIGN_CENTER, eListboxPythonMultiContent, eListbox, gFont, getDesktop, ePicLoad
 +from Tools.NumericalTextInput import NumericalTextInput
 +from enigma import eTimer, quitMainloop, RT_HALIGN_LEFT, RT_VALIGN_CENTER, eListboxPythonMultiContent, eListbox, gFont, getDesktop, ePicLoad, eRCInput, getPrevAsciiCode
  from cPickle import dump, load
  from os import path as os_path, system as os_system, unlink, stat, mkdir, popen, makedirs, listdir, access, rename, remove, W_OK, R_OK, F_OK
  from time import time, gmtime, strftime, localtime
@@@ -45,14 -43,6 +45,14 @@@ config.plugins.configurationbackup = Co
  config.plugins.configurationbackup.backuplocation = ConfigText(default = '/media/hdd/', visible_width = 50, fixed_size = False)
  config.plugins.configurationbackup.backupdirs = ConfigLocations(default=['/etc/enigma2/', '/etc/network/interfaces', '/etc/wpa_supplicant.conf', '/etc/resolv.conf', '/etc/default_gw', '/etc/hostname'])
  
 +config.plugins.SoftwareManager = ConfigSubsection()
 +config.plugins.SoftwareManager.overwriteConfigFiles = ConfigSelection(
 +                              [
 +                               ("Y", _("Yes, always")),
 +                               ("N", _("No, never")),                          
 +                               ("ask", _("Always ask"))
 +                              ], "Y")
 +
  def write_cache(cache_file, cache_data):
        #Does a cPickle dump
        if not os_path.isdir( os_path.dirname(cache_file) ):
@@@ -119,16 -109,13 +119,16 @@@ class UpdatePluginMenu(Screen)
                self.menu = args
                self.list = []
                self.oktext = _("\nPress OK on your remote control to continue.")
 +              self.menutext = _("Press MENU on your remote control for additional options.")
 +              self.infotext = _("Press INFO on your remote control for additional information.")
                self.text = ""
                self.backupdirs = ' '.join( config.plugins.configurationbackup.backupdirs.value )
                if self.menu == 0:
 +                      print "building menu entries"
                        self.list.append(("install-extensions", _("Manage extensions"), _("\nManage extensions or plugins for your Dreambox" ) + self.oktext, None))
                        self.list.append(("software-update", _("Software update"), _("\nOnline update of your Dreambox software." ) + self.oktext, None))
                        self.list.append(("software-restore", _("Software restore"), _("\nRestore your Dreambox with a new firmware." ) + self.oktext, None))
 -                      self.list.append(("system-backup", _("Backup system settings"), _("\nBackup your Dreambox settings." ) + self.oktext, None))
 +                      self.list.append(("system-backup", _("Backup system settings"), _("\nBackup your Dreambox settings." ) + self.oktext + "\n\n" + self.infotext, None))
                        self.list.append(("system-restore",_("Restore system settings"), _("\nRestore your Dreambox settings." ) + self.oktext, None))
                        self.list.append(("ipkg-install", _("Install local extension"),  _("\nScan for local extensions and install them." ) + self.oktext, None))
                        for p in plugins.getPlugins(PluginDescriptor.WHERE_SOFTWAREMANAGER):
                elif self.menu == 1:
                        self.list.append(("advancedrestore", _("Advanced restore"), _("\nRestore your backups by date." ) + self.oktext, None))
                        self.list.append(("backuplocation", _("Choose backup location"),  _("\nSelect your backup device.\nCurrent device: " ) + config.plugins.configurationbackup.backuplocation.value + self.oktext, None))
 -                      self.list.append(("backupfiles", _("Choose backup files"),  _("Select files for backup. Currently selected:\n" ) + self.backupdirs + self.oktext, None))
 +                      self.list.append(("backupfiles", _("Choose backup files"),  _("Select files for backup.") + self.oktext + "\n\n" + self.infotext, None))
                        if config.usage.setup_level.index >= 2: # expert+
                                self.list.append(("ipkg-manager", _("Packet management"),  _("\nView, install and remove available or installed packages." ) + self.oktext, None))
                        self.list.append(("ipkg-source",_("Choose upgrade source"), _("\nEdit the upgrade source address." ) + self.oktext, None))
  
                self["menu"] = List(self.list)
                self["key_red"] = StaticText(_("Close"))
 -              self["status"] = StaticText("")
 +              self["status"] = StaticText(self.menutext)
  
 -              self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions", "InfobarEPGActions"],
 +              self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions", "InfobarEPGActions", "MenuActions"],
                {
                        "ok": self.go,
                        "back": self.close,
                        "red": self.close,
 +                      "menu": self.handleMenu,
 +                      "showEventInfo": self.handleInfo,
                }, -1)
                self.onLayoutFinish.append(self.layoutFinished)
                self.backuppath = getBackupPath()
                self.backupfile = getBackupFilename()
                self.fullbackupfilename = self.backuppath + "/" + self.backupfile
                self.onShown.append(self.setWindowTitle)
 -              #self.onClose.append(self.cleanup)
  
        def layoutFinished(self):
                idx = 0
                self["menu"].index = idx
 -              #self.getUpdateInfos()
  
        def setWindowTitle(self):
                self.setTitle(_("Software management"))
                        self.text = _("No network connection available.")
                self["status"].setText(self.text)
  
 +      def handleMenu(self):
 +              self.session.open(SoftwareManagerSetup)
 +              
 +      def handleInfo(self):
 +              current = self["menu"].getCurrent()
 +              if current:
 +                      currentEntry = current[0]
 +                      if currentEntry in ("system-backup","backupfiles"):
 +                              self.session.open(SoftwareManagerInfo, mode = "backupinfo")
  
        def go(self):
 -              #iNetwork.stopPingConsole()
                current = self["menu"].getCurrent()
                if current:
                        currentEntry = current[0]
                        self.exe = True
                        self.session.open(RestoreScreen, runRestore = True)
  
 +class SoftwareManagerSetup(Screen, ConfigListScreen):
 +
 +      skin = """
 +              <screen name="SoftwareManagerSetup" position="center,center" size="560,440" title="SoftwareManager setup">
 +                      <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
 +                      <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on" />
 +                      <ePixmap pixmap="skin_default/buttons/yellow.png" position="280,0" size="140,40" alphatest="on" />
 +                      <ePixmap pixmap="skin_default/buttons/blue.png" position="420,0" size="140,40" alphatest="on" />
 +                      <widget source="key_red" render="Label" position="0,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" transparent="1" />
 +                      <widget source="key_green" render="Label" position="140,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#1f771f" transparent="1" />
 +                      <widget source="key_yellow" render="Label" position="280,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#a08500" transparent="1" />
 +                      <widget source="key_blue" render="Label" position="420,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#18188b" transparent="1" />
 +                      <widget name="config" position="5,50" size="550,350" scrollbarMode="showOnDemand" />
 +                      <ePixmap pixmap="skin_default/div-h.png" position="0,400" zPosition="1" size="560,2" />
 +                      <widget source="introduction" render="Label" position="5,410" size="550,30" zPosition="10" font="Regular;21" halign="center" valign="center" backgroundColor="#25062748" transparent="1" />
 +              </screen>"""
 +
 +      def __init__(self, session, skin_path = None):
 +              Screen.__init__(self, session)
 +              self.session = session
 +              self.skin_path = skin_path
 +              if self.skin_path == None:
 +                      self.skin_path = resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager")
 +
 +              self.onChangedEntry = [ ]
 +              self.setup_title = _("Software manager setup")
 +              self.overwriteConfigfilesEntry = None
 +
 +              self.list = [ ]
 +              ConfigListScreen.__init__(self, self.list, session = session, on_change = self.changedEntry)
 +
 +              self["actions"] = ActionMap(["SetupActions"],
 +                      {
 +                              "cancel": self.keyCancel,
 +                              "save": self.apply,
 +                      }, -2)
 +
 +              self["key_red"] = StaticText(_("Cancel"))
 +              self["key_green"] = StaticText(_("OK"))
 +              self["key_yellow"] = StaticText()
 +              self["key_blue"] = StaticText()
 +              self["introduction"] = StaticText()
 +
 +              self.createSetup()
 +              self.onLayoutFinish.append(self.layoutFinished)
 +
 +      def layoutFinished(self):
 +              self.setTitle(self.setup_title)
 +
 +      def createSetup(self):
 +              self.list = [ ]
 +              self.overwriteConfigfilesEntry = getConfigListEntry(_("Overwrite configuration files ?"), config.plugins.SoftwareManager.overwriteConfigFiles)
 +              self.list.append(self.overwriteConfigfilesEntry)        
 +              self["config"].list = self.list
 +              self["config"].l.setSeperation(400)
 +              self["config"].l.setList(self.list)
 +              if not self.selectionChanged in self["config"].onSelectionChanged:
 +                      self["config"].onSelectionChanged.append(self.selectionChanged)
 +              self.selectionChanged()
 +
 +      def selectionChanged(self):
 +              if self["config"].getCurrent() == self.overwriteConfigfilesEntry:
 +                      self["introduction"].setText(_("Overwrite configuration files during software upgrade?"))
 +              else:
 +                      self["introduction"].setText("")
 +
 +      def newConfig(self):
 +              pass
 +
 +      def keyLeft(self):
 +              ConfigListScreen.keyLeft(self)
 +
 +      def keyRight(self):
 +              ConfigListScreen.keyRight(self)
 +
 +      def confirm(self, confirmed):
 +              if not confirmed:
 +                      print "not confirmed"
 +                      return
 +              else:
 +                      self.keySave()
 +
 +      def apply(self):
 +              self.session.openWithCallback(self.confirm, MessageBox, _("Use this settings?"), MessageBox.TYPE_YESNO, timeout = 20, default = True)
 +
 +      def cancelConfirm(self, result):
 +              if not result:
 +                      return
 +              for x in self["config"].list:
 +                      x[1].cancel()
 +              self.close()
 +
 +      def keyCancel(self):
 +              if self["config"].isChanged():
 +                      self.session.openWithCallback(self.cancelConfirm, MessageBox, _("Really close without saving settings?"), MessageBox.TYPE_YESNO, timeout = 20, default = True)
 +              else:
 +                      self.close()
 +
 +      # for summary:
 +      def changedEntry(self):
 +              for x in self.onChangedEntry:
 +                      x()
 +              self.selectionChanged()
 +
 +      def getCurrentEntry(self):
 +              return self["config"].getCurrent()[0]
 +
 +      def getCurrentValue(self):
 +              return str(self["config"].getCurrent()[1].value)
 +
 +      def createSummary(self):
 +              from Screens.Setup import SetupSummary
 +              return SetupSummary
 +
 +
 +class SoftwareManagerInfo(Screen):
 +      skin = """
 +              <screen name="SoftwareManagerInfo" position="center,center" size="560,440" title="SoftwareManager information">
 +                      <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
 +                      <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on" />
 +                      <ePixmap pixmap="skin_default/buttons/yellow.png" position="280,0" size="140,40" alphatest="on" />
 +                      <ePixmap pixmap="skin_default/buttons/blue.png" position="420,0" size="140,40" alphatest="on" />
 +                      <widget source="key_red" render="Label" position="0,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" transparent="1" />
 +                      <widget source="key_green" render="Label" position="140,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#1f771f" transparent="1" />
 +                      <widget source="key_yellow" render="Label" position="280,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#a08500" transparent="1" />
 +                      <widget source="key_blue" render="Label" position="420,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#18188b" transparent="1" />
 +                      <widget source="list" render="Listbox" position="5,50" size="550,340" scrollbarMode="showOnDemand" selectionDisabled="0">
 +                              <convert type="TemplatedMultiContent">
 +                                      {"template": [
 +                                                      MultiContentEntryText(pos = (5, 0), size = (540, 26), font=0, flags = RT_HALIGN_LEFT | RT_HALIGN_CENTER, text = 0), # index 0 is the name
 +                                              ],
 +                                      "fonts": [gFont("Regular", 24),gFont("Regular", 22)],
 +                                      "itemHeight": 26
 +                                      }
 +                              </convert>
 +                      </widget>
 +                      <ePixmap pixmap="skin_default/div-h.png" position="0,400" zPosition="1" size="560,2" />
 +                      <widget source="introduction" render="Label" position="5,410" size="550,30" zPosition="10" font="Regular;21" halign="center" valign="center" backgroundColor="#25062748" transparent="1" />
 +              </screen>"""
 +
 +      def __init__(self, session, skin_path = None, mode = None):
 +              Screen.__init__(self, session)
 +              self.session = session
 +              self.mode = mode
 +              self.skin_path = skin_path
 +              if self.skin_path == None:
 +                      self.skin_path = resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager")
 +
 +              self["actions"] = ActionMap(["ShortcutActions", "WizardActions"],
 +                      {
 +                              "back": self.close,
 +                              "red": self.close,
 +                      }, -2)
 +
 +              self.list = []
 +              self["list"] = List(self.list)
 +              
 +              self["key_red"] = StaticText(_("Close"))
 +              self["key_green"] = StaticText()
 +              self["key_yellow"] = StaticText()
 +              self["key_blue"] = StaticText()
 +              self["introduction"] = StaticText()
 +
 +              self.onLayoutFinish.append(self.layoutFinished)
 +
 +      def layoutFinished(self):
 +              self.setTitle(_("Softwaremanager information"))
 +              if self.mode is not None:
 +                      self.showInfos()
 +
 +      def showInfos(self):
 +              if self.mode == "backupinfo":
 +                      self.list = []
 +                      backupfiles = config.plugins.configurationbackup.backupdirs.value
 +                      for entry in backupfiles:
 +                              print entry
 +                              self.list.append((entry,))
 +                      self['list'].setList(self.list)
 +                      
  
  class PluginManager(Screen, DreamInfoHandler):
  
                                                status = "remove"
                                        else:
                                                status = "installed"
-                                       self.list.append(self.buildEntryComponent(name, details, description, packagename, status, selected = selectState))
+                                       self.list.append(self.buildEntryComponent(name, _(details), _(description), packagename, status, selected = selectState))
                                else:
                                        if selectState == True:
                                                status = "install"
                                        else:
                                                status = "installable"
-                                       self.list.append(self.buildEntryComponent(name, details, description, packagename, status, selected = selectState))
+                                       self.list.append(self.buildEntryComponent(name, _(details), _(description), packagename, status, selected = selectState))
                        if len(self.list):
                                self.list.sort(key=lambda x: x[0])
                        self["list"].style = "default"
@@@ -1104,8 -904,7 +1104,7 @@@ class PluginDetails(Screen, DreamInfoHa
                self.skin_path = plugin_path
                self.language = language.getLanguage()[:2] # getLanguage returns e.g. "fi_FI" for "language_country"
                self.attributes = None
-               self.translatedAttributes = None
-               DreamInfoHandler.__init__(self, self.statusCallback, blocking = False, language = self.language)
+               DreamInfoHandler.__init__(self, self.statusCallback, blocking = False)
                self.directory = resolveFilename(SCOPE_METADIR)
                if packagedata:
                        self.pluginname = packagedata[0]
                self.package = self.packageDetails[0]
                if self.package[0].has_key("attributes"):
                        self.attributes = self.package[0]["attributes"]
-               if self.package[0].has_key("translation"):
-                       self.translatedAttributes = self.package[0]["translation"]
  
                self.cmdList = []
                self.oktext = _("\nAfter pressing OK, please wait!")
                self.onLayoutFinish.append(self.setInfos)
  
        def setWindowTitle(self):
-               self.setTitle(_("Details for extension: " + self.pluginname))
+               self.setTitle(_("Details for plugin: ") + self.pluginname )
  
        def exit(self):
                self.close(False)
                pass
  
        def setInfos(self):
-               if self.translatedAttributes.has_key("name"):
-                       self.pluginname = self.translatedAttributes["name"]
-               elif self.attributes.has_key("name"):
+               if self.attributes.has_key("screenshot"):
+                       self.loadThumbnail(self.attributes)
+               if self.attributes.has_key("name"):
                        self.pluginname = self.attributes["name"]
                else:
                        self.pluginname = _("unknown")
  
-               if self.translatedAttributes.has_key("author"):
-                       self.author = self.translatedAttributes["author"]
-               elif self.attributes.has_key("author"):
+               if self.attributes.has_key("author"):
                        self.author = self.attributes["author"]
                else:
                        self.author = _("unknown")
  
-               if self.translatedAttributes.has_key("description"):
-                       self.description = self.translatedAttributes["description"]
-               elif self.attributes.has_key("description"):
-                       self.description = self.attributes["description"]
+               if self.attributes.has_key("description"):
+                       self.description = _(self.attributes["description"].replace("\\n", "\n"))
                else:
                        self.description = _("No description available.")
  
-               if self.translatedAttributes.has_key("screenshot"):
-                       self.loadThumbnail(self.translatedAttributes)
-               else:
-                       self.loadThumbnail(self.attributes)
                self["author"].setText(_("Author: ") + self.author)
-               self["detailtext"].setText(self.description.strip())
+               self["detailtext"].setText(_(self.description))
                if self.pluginstate in ('installable', 'install'):
                        self["key_green"].setText(_("Install"))
                else:
                thumbnailUrl = None
                if entry.has_key("screenshot"):
                        thumbnailUrl = entry["screenshot"]
+                       if self.language == "de":
+                               if thumbnailUrl[-7:] == "_en.jpg":
+                                       thumbnailUrl = thumbnailUrl[:-7] + "_de.jpg"
                if thumbnailUrl is not None:
                        self.thumbnail = "/tmp/" + thumbnailUrl.split('/')[-1]
                        print "[PluginDetails] downloading screenshot " + thumbnailUrl + " to " + self.thumbnail
  
  class UpdatePlugin(Screen):
        skin = """
 -              <screen name="UpdatePlugin" position="center,center" size="550,200" title="Software update" >
 +              <screen name="UpdatePlugin" position="center,center" size="550,300" title="Software update" >
                        <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" />
                self["status"] = self.status
                self.package = StaticText()
                self["package"] = self.package
 +              self.oktext = _("Press OK on your remote control to continue.")
  
                self.packages = 0
                self.error = 0
 +              self.processed_packages = []
  
                self.activity = 0
                self.activityTimer = eTimer()
                                self.slider.setValue(self.sliderPackages[param])
                        self.package.setText(param)
                        self.status.setText(_("Upgrading"))
 -                      self.packages += 1
 +                      if not param in self.processed_packages:
 +                              self.processed_packages.append(param)
 +                              self.packages += 1
                elif event == IpkgComponent.EVENT_INSTALL:
                        self.package.setText(param)
                        self.status.setText(_("Installing"))
 -                      self.packages += 1
 +                      if not param in self.processed_packages:
 +                              self.processed_packages.append(param)
 +                              self.packages += 1
 +              elif event == IpkgComponent.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 == IpkgComponent.EVENT_CONFIGURING:
                        self.package.setText(param)
                        self.status.setText(_("Configuring"))
 +                      
                elif event == IpkgComponent.EVENT_MODIFIED:
 -                      self.session.openWithCallback(
 -                              self.modificationCallback,
 -                              MessageBox,
 -                              _("A configuration file (%s) was modified since Installation.\nDo you want to keep your version?") % (param)
 -                      )
 +                      if config.plugins.SoftwareManager.overwriteConfigFiles.value in ("N", "Y"):
 +                              self.ipkg.write(True and config.plugins.SoftwareManager.overwriteConfigFiles.value)
 +                      else:
 +                              self.session.openWithCallback(
 +                                      self.modificationCallback,
 +                                      MessageBox,
 +                                      _("A configuration file (%s) was modified since Installation.\nDo you want to keep your version?") % (param)
 +                              )
                elif event == IpkgComponent.EVENT_ERROR:
                        self.error += 1
                elif event == IpkgComponent.EVENT_DONE:
                                self.activityslider.setValue(0)
                                
                                self.package.setText("")
 -                              self.status.setText(_("Done - Installed or upgraded %d packages") % self.packages)
 +                              self.status.setText(_("Done - Installed or upgraded %d packages") % self.packages + "\n\n" + self.oktext)
                        else:
                                self.activityTimer.stop()
                                self.activityslider.setValue(0)
@@@ -1597,7 -1374,7 +1590,7 @@@ class IPKGSource(Screen)
                self["text"].number(number)
  
  
 -class PacketManager(Screen):
 +class PacketManager(Screen, NumericalTextInput):
        skin = """
                <screen name="PacketManager" position="center,center" size="530,420" title="Packet manager" >
                        <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
                
        def __init__(self, session, plugin_path, args = None):
                Screen.__init__(self, session)
 +              NumericalTextInput.__init__(self)
                self.session = session
                self.skin_path = plugin_path
  
 -              self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions"], 
 +              self.setUseableChars(u'1234567890abcdefghijklmnopqrstuvwxyz')
 +
 +              self["shortcuts"] = NumberActionMap(["ShortcutActions", "WizardActions", "NumberActions", "InputActions", "InputAsciiActions", "KeyboardInputActions" ],
                {
                        "ok": self.go,
                        "back": self.exit,
                        "red": self.exit,
                        "green": self.reload,
 +                      "gotAsciiCode": self.keyGotAscii,
 +                      "1": self.keyNumberGlobal,
 +                      "2": self.keyNumberGlobal,
 +                      "3": self.keyNumberGlobal,
 +                      "4": self.keyNumberGlobal,
 +                      "5": self.keyNumberGlobal,
 +                      "6": self.keyNumberGlobal,
 +                      "7": self.keyNumberGlobal,
 +                      "8": self.keyNumberGlobal,
 +                      "9": self.keyNumberGlobal,
 +                      "0": self.keyNumberGlobal
                }, -1)
                
                self.list = []
                self.onShown.append(self.setWindowTitle)
                self.onLayoutFinish.append(self.rebuildList)
  
 +              rcinput = eRCInput.getInstance()
 +              rcinput.setKeyboardMode(rcinput.kmAscii)                
 +
 +      def keyNumberGlobal(self, val):
 +              key = self.getKey(val)
 +              if key is not None:
 +                      keyvalue = key.encode("utf-8")
 +                      if len(keyvalue) == 1:
 +                              self.setNextIdx(keyvalue[0])
 +              
 +      def keyGotAscii(self):
 +              keyvalue = unichr(getPrevAsciiCode()).encode("utf-8")
 +              if len(keyvalue) == 1:
 +                      self.setNextIdx(keyvalue[0])
 +              
 +      def setNextIdx(self,char):
 +              if char in ("0", "1", "a"):
 +                      self["list"].setIndex(0)
 +              else:
 +                      idx = self.getNextIdx(char)
 +                      if idx and idx <= self["list"].count:
 +                              self["list"].setIndex(idx)
 +
 +      def getNextIdx(self,char):
 +              idx = 0
 +              for i in self["list"].list:
 +                      if i[0][0] == char:
 +                              return idx
 +                      idx += 1
 +
        def exit(self):
                self.ipkg.stop()
                if self.Console is not None:
                        if len(self.Console.appContainers):
                                for name in self.Console.appContainers.keys():
                                        self.Console.kill(name)
 +              rcinput = eRCInput.getInstance()
 +              rcinput.setKeyboardMode(rcinput.kmNone)
                self.close()
  
        def reload(self):