-from Components.config import config, ConfigSubsection, ConfigSelection, ConfigPIN, ConfigYesNo, ConfigSubList, ConfigInteger
+from Components.config import config, ConfigSubsection, ConfigSelection, ConfigPIN, ConfigText, ConfigYesNo, ConfigSubList, ConfigInteger
+#from Screens.ChannelSelection import service_types_tv
from Screens.InputBox import PinInput
from Screens.MessageBox import MessageBox
from Tools.BoundFunction import boundFunction
from ServiceReference import ServiceReference
from Tools import Notifications
from Tools.Directories import resolveFilename, SCOPE_CONFIG
+from enigma import eTimer
+import time
+
+TYPE_SERVICE = "SERVICE"
+TYPE_BOUQUETSERVICE = "BOUQUETSERVICE"
+TYPE_BOUQUET = "BOUQUET"
+LIST_BLACKLIST = "blacklist"
+LIST_WHITELIST = "whitelist"
+
+IMG_WHITESERVICE = LIST_WHITELIST + "-" + TYPE_SERVICE
+IMG_WHITEBOUQUET = LIST_WHITELIST + "-" + TYPE_BOUQUET
+IMG_BLACKSERVICE = LIST_BLACKLIST + "-" + TYPE_SERVICE
+IMG_BLACKBOUQUET = LIST_BLACKLIST + "-" + TYPE_BOUQUET
def InitParentalControl():
config.ParentalControl = ConfigSubsection()
config.ParentalControl.configured = ConfigYesNo(default = False)
config.ParentalControl.mode = ConfigSelection(default = "simple", choices = [("simple", _("simple")), ("complex", _("complex"))])
- config.ParentalControl.storeservicepin = ConfigSelection(default = "never", choices = [("never", _("never")), ("5_minutes", _("5 minutes")), ("30_minutes", _("30 minutes")), ("60_minutes", _("60 minutes")), ("restart", _("until restart"))])
+ config.ParentalControl.storeservicepin = ConfigSelection(default = "never", choices = [("never", _("never")), ("5", _("5 minutes")), ("30", _("30 minutes")), ("60", _("60 minutes")), ("standby", _("until standby/restart"))])
+ config.ParentalControl.storeservicepincancel = ConfigSelection(default = "never", choices = [("never", _("never")), ("5", _("5 minutes")), ("30", _("30 minutes")), ("60", _("60 minutes")), ("standby", _("until standby/restart"))])
config.ParentalControl.servicepinactive = ConfigYesNo(default = False)
config.ParentalControl.setuppinactive = ConfigYesNo(default = False)
- config.ParentalControl.type = ConfigSelection(default = "blacklist", choices = [("whitelist", _("whitelist")), ("blacklist", _("blacklist"))])
+ config.ParentalControl.type = ConfigSelection(default = "blacklist", choices = [(LIST_WHITELIST, _("whitelist")), (LIST_BLACKLIST, _("blacklist"))])
config.ParentalControl.setuppin = ConfigPIN(default = -1)
config.ParentalControl.retries = ConfigSubsection()
class ParentalControl:
def __init__(self):
- self.open()
+ #Do not call open on init, because bouquets are not ready at that moment
+# self.open()
self.serviceLevel = {}
-
- def addWhitelistService(self, service):
- self.whitelist.append(service)
+ #Instead: Use Flags to see, if we already initialized config and called open
+ self.configInitialized = False
+ self.filesOpened = False
+ #This is the timer that is used to see, if the time for caching the pin is over
+ #Of course we could also work without a timer and compare the times every
+ #time we call isServicePlayable. But this might probably slow down zapping,
+ #That's why I decided to use a timer
+ self.sessionPinTimer = eTimer()
+ self.sessionPinTimer.callback.append(self.resetSessionPin)
- def addBlacklistService(self, service):
- self.blacklist.append(service)
-
- def setServiceLevel(self, service, level):
- self.serviceLevel[service] = level
-
- def deleteWhitelistService(self, service):
- self.whitelist.remove(service)
- if self.serviceLevel.has_key(service):
- self.serviceLevel.remove(service)
+ def serviceMethodWrapper(self, service, method, *args):
+ #This method is used to call all functions that need a service as Parameter:
+ #It takes either a Service- Reference or a Bouquet- Reference and passes
+ #Either the service or all services contained in the bouquet to the method given
+ #That way all other functions do not need to distinguish between service and bouquet.
+ if "FROM BOUQUET" in service:
+ method( service , TYPE_BOUQUET , *args )
+ servicelist = self.readServicesFromBouquet(service,"C")
+ for ref in servicelist:
+ sRef = str(ref[0])
+ method( sRef , TYPE_BOUQUETSERVICE , *args )
+ else:
+ ref = ServiceReference(service)
+ sRef = str(ref)
+ method( sRef , TYPE_SERVICE , *args )
- def deleteBlacklistService(self, service):
- self.blacklist.remove(service)
- if self.serviceLevel.has_key(service):
- self.serviceLevel.remove(service)
+ def setServiceLevel(self, service, type, level):
+ self.serviceLevel[service] = level
def isServicePlayable(self, ref, callback):
if not config.ParentalControl.configured.value or not config.ParentalControl.servicepinactive.value:
return True
- #print "whitelist:", self.whitelist
- #print "blacklist:", self.blacklist
- #print "config.ParentalControl.type.value:", config.ParentalControl.type.value
- #print "not in whitelist:", (service not in self.whitelist)
- #print "checking parental control for service:", ref.toString()
+ #Check if we already read the whitelists and blacklists. If not: call open
+ if self.filesOpened == False:
+ self.open()
+ #Check if configuration has already been read or if the significant values have changed.
+ #If true: read the configuration
+ if self.configInitialized == False or self.storeServicePin != config.ParentalControl.storeservicepin.value or self.storeServicePinCancel != config.ParentalControl.storeservicepincancel.value:
+ self.getConfigValues()
service = ref.toCompareString()
- if (config.ParentalControl.type.value == "whitelist" and service not in self.whitelist) or (config.ParentalControl.type.value == "blacklist" and service in self.blacklist):
+ if (config.ParentalControl.type.value == LIST_WHITELIST and not self.whitelist.has_key(service)) or (config.ParentalControl.type.value == LIST_BLACKLIST and self.blacklist.has_key(service)):
+ #Check if the session pin is cached and return the cached value, if it is.
+ if self.sessionPinCached == True:
+ #As we can cache successful pin- entries as well as canceled pin- entries,
+ #We give back the last action
+ return self.sessionPinCachedValue
self.callback = callback
- #print "service:", ServiceReference(service).getServiceName()
+ #Someone started to implement different levels of protection. Seems they were never completed
+ #I did not throw out this code, although it is of no use at the moment
levelNeeded = 0
if self.serviceLevel.has_key(service):
levelNeeded = self.serviceLevel[service]
return True
def protectService(self, service):
- #print "protect"
- #print "config.ParentalControl.type.value:", config.ParentalControl.type.value
- if config.ParentalControl.type.value == "whitelist":
- if service in self.whitelist:
- self.deleteWhitelistService(service)
+ if config.ParentalControl.type.value == LIST_WHITELIST:
+ if self.whitelist.has_key(service):
+ self.serviceMethodWrapper(service, self.removeServiceFromList, self.whitelist)
+ #self.deleteWhitelistService(service)
else: # blacklist
- if service not in self.blacklist:
- self.addBlacklistService(service)
+ if not self.blacklist.has_key(service):
+ self.serviceMethodWrapper(service, self.addServiceToList, self.blacklist)
+ #self.addBlacklistService(service)
#print "whitelist:", self.whitelist
#print "blacklist:", self.blacklist
-
def unProtectService(self, service):
#print "unprotect"
#print "config.ParentalControl.type.value:", config.ParentalControl.type.value
- if config.ParentalControl.type.value == "whitelist":
- if service not in self.whitelist:
- self.addWhitelistService(service)
+ if config.ParentalControl.type.value == LIST_WHITELIST:
+ if not self.whitelist.has_key(service):
+ self.serviceMethodWrapper(service, self.addServiceToList, self.whitelist)
+ #self.addWhitelistService(service)
else: # blacklist
- if service in self.blacklist:
- self.deleteBlacklistService(service)
+ if self.blacklist.has_key(service):
+ self.serviceMethodWrapper(service, self.removeServiceFromList, self.blacklist)
+ #self.deleteBlacklistService(service)
#print "whitelist:", self.whitelist
#print "blacklist:", self.blacklist
def getProtectionLevel(self, service):
- if (config.ParentalControl.type.value == "whitelist" and service not in self.whitelist) or (config.ParentalControl.type.value == "blacklist" and service in self.blacklist):
+ if (config.ParentalControl.type.value == LIST_WHITELIST and not self.whitelist.has_key(service)) or (config.ParentalControl.type.value == LIST_BLACKLIST and self.blacklist.has_key(service)):
if self.serviceLevel.has_key(service):
return self.serviceLevel[service]
else:
return 0
else:
return -1
+
+ def getProtectionType(self, service):
+ #New method used in ParentalControlList: This method does not only return
+ #if a service is protected or not, it also returns, why (whitelist or blacklist, service or bouquet)
+ if self.filesOpened == False:
+ self.open()
+ sImage = ""
+ if (config.ParentalControl.type.value == LIST_WHITELIST):
+ if self.whitelist.has_key(service):
+ if TYPE_SERVICE in self.whitelist[service]:
+ sImage = IMG_WHITESERVICE
+ else:
+ sImage = IMG_WHITEBOUQUET
+ elif (config.ParentalControl.type.value == LIST_BLACKLIST):
+ if self.blacklist.has_key(service):
+ if TYPE_SERVICE in self.blacklist[service]:
+ sImage = IMG_BLACKSERVICE
+ else:
+ sImage = IMG_BLACKBOUQUET
+ bLocked = self.getProtectionLevel(service) != -1
+ return (bLocked,sImage)
+
+ def getConfigValues(self):
+ #Read all values from configuration
+ self.checkPinInterval = False
+ self.checkPinIntervalCancel = False
+ self.checkSessionPin = False
+ self.checkSessionPinCancel = False
+
+ self.sessionPinCached = False
+ self.pinIntervalSeconds = 0
+ self.pinIntervalSecondsCancel = 0
+
+ self.storeServicePin = config.ParentalControl.storeservicepin.value
+ self.storeServicePinCancel = config.ParentalControl.storeservicepincancel.value
+
+ if self.storeServicePin == "never":
+ pass
+ elif self.storeServicePin == "standby":
+ self.checkSessionPin = True
+ else:
+ self.checkPinInterval = True
+ iMinutes = float(self.storeServicePin)
+ iSeconds = iMinutes*60
+ self.pinIntervalSeconds = iSeconds
+
+ if self.storeServicePinCancel == "never":
+ pass
+ elif self.storeServicePinCancel == "standby":
+ self.checkSessionPinCancel = True
+ else:
+ self.checkPinIntervalCancel = True
+ iMinutes = float(self.storeServicePinCancel)
+ iSeconds = iMinutes*60
+ self.pinIntervalSecondsCancel = iSeconds
+ self.configInitialized = True
+ # Reset PIN cache on standby: Use StandbyCounter- Config- Callback
+ config.misc.standbyCounter.addNotifier(self.standbyCounterCallback, initial_call = False)
+
+ def standbyCounterCallback(self, configElement):
+ self.resetSessionPin()
+
+ def resetSessionPin(self):
+ #Reset the session pin, stop the timer
+ self.sessionPinCached = False
+ self.sessionPinTimer.stop()
+
+ def getCurrentTimeStamp(self):
+ return time.time()
+
def getPinList(self):
return [ x.value for x in config.ParentalControl.servicepin ]
-
+
def servicePinEntered(self, service, result):
-# levelNeeded = 0
- #if self.serviceLevel.has_key(service):
- #levelNeeded = self.serviceLevel[service]
-#
- #print "getPinList():", self.getPinList()
- #pinList = self.getPinList()[:levelNeeded + 1]
- #print "pinList:", pinList
-#
-# print "pin entered for service", service, "and pin was", pin
- #if pin is not None and int(pin) in pinList:
+
if result is not None and result:
- #print "pin ok, playing service"
+ #This is the new function of caching the service pin
+ #save last session and time of last entered pin...
+ if self.checkSessionPin == True:
+ self.sessionPinCached = True
+ self.sessionPinCachedValue = True
+ if self.checkPinInterval == True:
+ self.sessionPinCached = True
+ self.sessionPinCachedValue = True
+ self.sessionPinTimer.start(self.pinIntervalSeconds*1000,1)
self.callback(ref = service)
else:
+ #This is the new function of caching cancelling of service pin
if result is not None:
Notifications.AddNotification(MessageBox, _("The pin code you entered is wrong."), MessageBox.TYPE_ERROR)
- #print "wrong pin entered"
+ else:
+ if self.checkSessionPinCancel == True:
+ self.sessionPinCached = True
+ self.sessionPinCachedValue = False
+ if self.checkPinIntervalCancel == True:
+ self.sessionPinCached = True
+ self.sessionPinCachedValue = False
+ self.sessionPinTimer.start(self.pinIntervalSecondsCancel*1000,1)
- def saveWhitelist(self):
- file = open(resolveFilename(SCOPE_CONFIG, "whitelist"), 'w')
- for x in self.whitelist:
- file.write(x + "\n")
- file.close
-
- def openWhitelist(self):
- self.whitelist = []
- try:
- file = open(resolveFilename(SCOPE_CONFIG, "whitelist"), 'r')
- lines = file.readlines()
- for x in lines:
- ref = ServiceReference(x.strip())
- self.whitelist.append(str(ref))
- file.close
- except:
- pass
-
- def saveBlacklist(self):
- file = open(resolveFilename(SCOPE_CONFIG, "blacklist"), 'w')
- for x in self.blacklist:
- file.write(x + "\n")
+ def saveListToFile(self,sWhichList):
+ #Replaces saveWhiteList and saveBlackList:
+ #I don't like to have two functions with identical code...
+ if sWhichList == LIST_BLACKLIST:
+ vList = self.blacklist
+ else:
+ vList = self.whitelist
+ file = open(resolveFilename(SCOPE_CONFIG, sWhichList), 'w')
+ for sService,sType in vList.iteritems():
+ #Only Services that are selected directly and Bouqets are saved.
+ #Services that are added by a bouquet are not saved.
+ #This is the reason for the change in self.whitelist and self.blacklist
+ if TYPE_SERVICE in sType or TYPE_BOUQUET in sType:
+ file.write(str(sService) + "\n")
file.close
- def openBlacklist(self):
- self.blacklist = []
+ def openListFromFile(self,sWhichList):
+ #Replaces openWhiteList and openBlackList:
+ #I don't like to have two functions with identical code...
+ if sWhichList == LIST_BLACKLIST:
+ self.blacklist = {}
+ vList = self.blacklist
+ else:
+ self.whitelist = {}
+ vList = self.whitelist
try:
- file = open(resolveFilename(SCOPE_CONFIG, "blacklist"), 'r')
+ file = open(resolveFilename(SCOPE_CONFIG, sWhichList ), 'r')
lines = file.readlines()
for x in lines:
- ref = ServiceReference(x.strip())
- self.blacklist.append(str(ref))
+ sPlain = x.strip()
+ self.serviceMethodWrapper(sPlain, self.addServiceToList, vList)
file.close
except:
pass
+
+ def addServiceToList(self, service, type, vList):
+ #Replaces addWhitelistService and addBlacklistService
+ #The lists are not only lists of service references any more.
+ #They are named lists with the service as key and an array of types as value:
+
+ if vList.has_key(service):
+ if not type in vList[service]:
+ vList[service].append(type)
+ else:
+ vList[service] = [type]
+
+ def removeServiceFromList(self, service, type, vList):
+ #Replaces deleteWhitelistService and deleteBlacklistService
+ if vList.has_key(service):
+ if type in vList[service]:
+ vList[service].remove(type)
+ if not vList[service]:
+ del vList[service]
+ if self.serviceLevel.has_key(service):
+ self.serviceLevel.remove(service)
+
+ def readServicesFromBouquet(self,sBouquetSelection,formatstring):
+ #This method gives back a list of services for a given bouquet
+ from enigma import eServiceCenter, eServiceReference
+ from Screens.ChannelSelection import service_types_tv
+ serviceHandler = eServiceCenter.getInstance()
+ refstr = sBouquetSelection
+ root = eServiceReference(refstr)
+ list = serviceHandler.list(root)
+ if list is not None:
+ services = list.getContent("CN", True) #(servicecomparestring, name)
+ return services
def save(self):
- self.saveBlacklist()
- self.saveWhitelist()
+ self.saveListToFile(LIST_BLACKLIST)
+ self.saveListToFile(LIST_WHITELIST)
def open(self):
- self.openBlacklist()
- self.openWhitelist()
+ self.openListFromFile(LIST_BLACKLIST)
+ self.openListFromFile(LIST_WHITELIST)
+ self.filesOpened = True
parentalControl = ParentalControl()
class ProtectedScreen:
def __init__(self):
if self.isProtected():
- self.onFirstExecBegin.append(boundFunction(self.session.openWithCallback, self.pinEntered, PinInput, pinList = [self.protectedWithPin()], triesEntry = self.getTriesEntry(), title = self.getPinText(), windowTitle = _("Change pin code")))
+ self.onFirstExecBegin.append(boundFunction(self.session.openWithCallback, self.pinEntered, PinInput, pinList = [self.protectedWithPin()], triesEntry = self.getTriesEntry(), title = self.getPinText(), windowTitle = _("Enter pin code")))
def getTriesEntry(self):
return config.ParentalControl.retries.setuppin
self.list = []
ConfigListScreen.__init__(self, self.list, session = self.session, on_change = self.changedEntry)
self.createSetup()
-
+
self["actions"] = NumberActionMap(["SetupActions"],
{
- "cancel": self.keyCancel,
- "save": self.keyCancel
+ "cancel": self.keyCancel,
+ "save": self.keyCancel
}, -2)
self["key_red"] = StaticText(_("Cancel"))
self["key_green"] = StaticText(_("OK"))
def isProtected(self):
return config.ParentalControl.setuppinactive.value and config.ParentalControl.configured.value
-
+
def createSetup(self):
self.editListEntry = None
self.changePin = None
self.changeSetupPin = None
-
+
self.list = []
self.list.append(getConfigListEntry(_("Enable parental control"), config.ParentalControl.configured))
print "config.ParentalControl.configured.value", config.ParentalControl.configured.value
elif config.ParentalControl.mode.value == "simple":
self.changePin = getConfigListEntry(_("Change service pin"), NoSave(ConfigNothing()))
self.list.append(self.changePin)
- #self.list.append(getConfigListEntry(_("Remember service pin"), config.ParentalControl.storeservicepin))
+ #Added Option to remember the service pin
+ self.list.append(getConfigListEntry(_("Remember service pin"), config.ParentalControl.storeservicepin))
+ #Added Option to remember the cancellation of service pin entry
+ self.list.append(getConfigListEntry(_("Remember service pin cancel"), config.ParentalControl.storeservicepincancel))
self.editListEntry = getConfigListEntry(_("Edit services list"), NoSave(ConfigNothing()))
self.list.append(self.editListEntry)
-
+ #New funtion: Possibility to add Bouquets to whitelist / blacklist
+ self.editBouquetListEntry = getConfigListEntry(_("Edit bouquets list"), NoSave(ConfigNothing()))
+ self.list.append(self.editBouquetListEntry)
+ #New option to reload service lists (for example if bouquets have changed)
+ self.reloadLists = getConfigListEntry(_("Reload Black-/Whitelists"), NoSave(ConfigNothing()))
+ self.list.append(self.reloadLists)
+
self["config"].list = self.list
self["config"].setList(self.list)
print "self[\"config\"].l.getCurrentSelection()", self["config"].l.getCurrentSelection()
if self["config"].l.getCurrentSelection() == self.editListEntry:
self.session.open(ParentalControlEditor)
+ elif self["config"].l.getCurrentSelection() == self.editBouquetListEntry:
+ self.session.open(ParentalControlBouquetEditor)
elif self["config"].l.getCurrentSelection() == self.changePin:
if config.ParentalControl.mode.value == "complex":
pass
self.session.open(ParentalControlChangePin, config.ParentalControl.servicepin[0], _("service pin"))
elif self["config"].l.getCurrentSelection() == self.changeSetupPin:
self.session.open(ParentalControlChangePin, config.ParentalControl.setuppin, _("setup pin"))
+ elif self["config"].l.getCurrentSelection() == self.reloadLists:
+ parentalControl.open()
else:
ConfigListScreen.keyRight(self)
print "current selection:", self["config"].l.getCurrentSelection()
def keyNumberGlobal(self, number):
pass
+
# for summary:
def changedEntry(self):
for x in self.onChangedEntry:
if not self.servicesList.has_key(key):
self.servicesList[key] = []
self.servicesList[key].append(s)
-
+
def chooseLetter(self):
print "choose letter"
mylist = []
for x in self.servicesList.keys():
if x == chr(SPECIAL_CHAR):
- x = ("special characters", x)
+ x = (_("special characters"), x)
else:
x = (x, x)
mylist.append(x)
if result is not None:
print "result:", result
self.currentLetter = result[1]
- self.list = [ParentalControlEntryComponent(x[0], x[1], parentalControl.getProtectionLevel(x[0]) != -1) for x in self.servicesList[result[1]]]
+ #Replace getProtectionLevel by new getProtectionType
+ self.list = [ParentalControlEntryComponent(x[0], x[1], parentalControl.getProtectionType(x[0])) for x in self.servicesList[result[1]]]
self.servicelist.setList(self.list)
else:
parentalControl.save()
self.close()
+class ParentalControlBouquetEditor(Screen):
+ #This new class allows adding complete bouquets to black- and whitelists
+ #The servicereference that is stored for bouquets is their refstr as listed in bouquets.tv
+ def __init__(self, session):
+ Screen.__init__(self, session)
+ self.skinName = "ParentalControlEditor"
+ self.list = []
+ self.bouquetslist = ParentalControlList(self.list)
+ self["servicelist"] = self.bouquetslist;
+ self.readBouquetList()
+ self.onLayoutFinish.append(self.selectBouquet)
+
+ self["actions"] = NumberActionMap(["DirectionActions", "ColorActions", "OkCancelActions"],
+ {
+ "ok": self.select,
+ "cancel": self.cancel
+ }, -1)
+
+ def cancel(self):
+ parentalControl.save()
+ self.close()
+
+ def select(self):
+ self.bouquetslist.toggleSelectedLock()
+
+ def readBouquetList(self):
+ serviceHandler = eServiceCenter.getInstance()
+ refstr = '1:134:1:0:0:0:0:0:0:0:FROM BOUQUET \"bouquets.tv\" ORDER BY bouquet'
+ bouquetroot = eServiceReference(refstr)
+ self.bouquetlist = {}
+ list = serviceHandler.list(bouquetroot)
+ if list is not None:
+ self.bouquetlist = list.getContent("CN", True)
+
+ def selectBouquet(self):
+ self.list = [ParentalControlEntryComponent(x[0], x[1], parentalControl.getProtectionType(x[0])) for x in self.bouquetlist]
+ self.bouquetslist.setList(self.list)
+
class ParentalControlChangePin(Screen, ConfigListScreen, ProtectedScreen):
def __init__(self, session, pin, pinname):
Screen.__init__(self, session)
self.pin2.addEndNotifier(boundFunction(self.valueChanged, 2))
self.list.append(getConfigListEntry(_("New pin"), NoSave(self.pin1)))
self.list.append(getConfigListEntry(_("Reenter new pin"), NoSave(self.pin2)))
- ConfigListScreen.__init__(self, self.list, session = self.session, on_change = self.changedEntry)
+ ConfigListScreen.__init__(self, self.list)
# print "old pin:", pin
#if pin.value != "aaaa":
#self.onFirstExecBegin.append(boundFunction(self.session.openWithCallback, self.pinEntered, PinInput, pinList = [self.pin.value], title = _("please enter the old pin"), windowTitle = _("Change pin code")))
ProtectedScreen.__init__(self)
-
+
self["actions"] = NumberActionMap(["DirectionActions", "ColorActions", "OkCancelActions"],
{
"cancel": self.cancel,