1 from Components.config import config, ConfigSubsection, ConfigSelection, ConfigPIN, ConfigText, ConfigYesNo, ConfigSubList, ConfigInteger
2 #from Screens.ChannelSelection import service_types_tv
3 from Screens.InputBox import PinInput
4 from Screens.MessageBox import MessageBox
5 from Tools.BoundFunction import boundFunction
6 from ServiceReference import ServiceReference
7 from Tools import Notifications
8 from Tools.Directories import resolveFilename, SCOPE_CONFIG
9 from enigma import eTimer
12 TYPE_SERVICE = "SERVICE"
13 TYPE_BOUQUETSERVICE = "BOUQUETSERVICE"
14 TYPE_BOUQUET = "BOUQUET"
15 LIST_BLACKLIST = "blacklist"
16 LIST_WHITELIST = "whitelist"
18 IMG_WHITESERVICE = LIST_WHITELIST + "-" + TYPE_SERVICE
19 IMG_WHITEBOUQUET = LIST_WHITELIST + "-" + TYPE_BOUQUET
20 IMG_BLACKSERVICE = LIST_BLACKLIST + "-" + TYPE_SERVICE
21 IMG_BLACKBOUQUET = LIST_BLACKLIST + "-" + TYPE_BOUQUET
23 def InitParentalControl():
24 config.ParentalControl = ConfigSubsection()
25 config.ParentalControl.configured = ConfigYesNo(default = False)
26 config.ParentalControl.mode = ConfigSelection(default = "simple", choices = [("simple", _("simple")), ("complex", _("complex"))])
27 config.ParentalControl.storeservicepin = ConfigSelection(default = "never", choices = [("never", _("never")), ("5", _("5 minutes")), ("30", _("30 minutes")), ("60", _("60 minutes")), ("standby", _("until standby/restart"))])
28 config.ParentalControl.storeservicepincancel = ConfigSelection(default = "never", choices = [("never", _("never")), ("5", _("5 minutes")), ("30", _("30 minutes")), ("60", _("60 minutes")), ("standby", _("until standby/restart"))])
29 config.ParentalControl.servicepinactive = ConfigYesNo(default = False)
30 config.ParentalControl.setuppinactive = ConfigYesNo(default = False)
31 config.ParentalControl.type = ConfigSelection(default = "blacklist", choices = [(LIST_WHITELIST, _("whitelist")), (LIST_BLACKLIST, _("blacklist"))])
32 config.ParentalControl.setuppin = ConfigPIN(default = -1)
34 config.ParentalControl.retries = ConfigSubsection()
35 config.ParentalControl.retries.setuppin = ConfigSubsection()
36 config.ParentalControl.retries.setuppin.tries = ConfigInteger(default = 3)
37 config.ParentalControl.retries.setuppin.time = ConfigInteger(default = 3)
38 config.ParentalControl.retries.servicepin = ConfigSubsection()
39 config.ParentalControl.retries.servicepin.tries = ConfigInteger(default = 3)
40 config.ParentalControl.retries.servicepin.time = ConfigInteger(default = 3)
41 # config.ParentalControl.configured = configElement("config.ParentalControl.configured", configSelection, 1, (("yes", _("yes")), ("no", _("no"))))
42 #config.ParentalControl.mode = configElement("config.ParentalControl.mode", configSelection, 0, (("simple", _("simple")), ("complex", _("complex"))))
43 #config.ParentalControl.storeservicepin = configElement("config.ParentalControl.storeservicepin", configSelection, 0, (("never", _("never")), ("5_minutes", _("5 minutes")), ("30_minutes", _("30 minutes")), ("60_minutes", _("60 minutes")), ("restart", _("until restart"))))
44 #config.ParentalControl.servicepinactive = configElement("config.ParentalControl.servicepinactive", configSelection, 1, (("yes", _("yes")), ("no", _("no"))))
45 #config.ParentalControl.setuppinactive = configElement("config.ParentalControl.setuppinactive", configSelection, 1, (("yes", _("yes")), ("no", _("no"))))
46 #config.ParentalControl.type = configElement("config.ParentalControl.type", configSelection, 0, (("whitelist", _("whitelist")), ("blacklist", _("blacklist"))))
47 #config.ParentalControl.setuppin = configElement("config.ParentalControl.setuppin", configSequence, "0000", configSequenceArg().get("PINCODE", (4, "")))
49 config.ParentalControl.servicepin = ConfigSubList()
52 config.ParentalControl.servicepin.append(ConfigPIN(default = -1))
53 #config.ParentalControl.servicepin.append(configElement("config.ParentalControl.servicepin.level" + str(i), configSequence, "0000", configSequenceArg().get("PINCODE", (4, ""))))
55 class ParentalControl:
57 #Do not call open on init, because bouquets are not ready at that moment
59 self.serviceLevel = {}
60 #Instead: Use Flags to see, if we already initialized config and called open
61 self.configInitialized = False
62 self.filesOpened = False
63 #This is the timer that is used to see, if the time for caching the pin is over
64 #Of course we could also work without a timer and compare the times every
65 #time we call isServicePlayable. But this might probably slow down zapping,
66 #That's why I decided to use a timer
67 self.sessionPinTimer = eTimer()
68 self.sessionPinTimer.callback.append(self.resetSessionPin)
70 def serviceMethodWrapper(self, service, method, *args):
71 #This method is used to call all functions that need a service as Parameter:
72 #It takes either a Service- Reference or a Bouquet- Reference and passes
73 #Either the service or all services contained in the bouquet to the method given
74 #That way all other functions do not need to distinguish between service and bouquet.
75 if "FROM BOUQUET" in service:
76 method( service , TYPE_BOUQUET , *args )
77 servicelist = self.readServicesFromBouquet(service,"C")
78 for ref in servicelist:
80 method( sRef , TYPE_BOUQUETSERVICE , *args )
82 ref = ServiceReference(service)
84 method( sRef , TYPE_SERVICE , *args )
86 def setServiceLevel(self, service, type, level):
87 self.serviceLevel[service] = level
89 def isServicePlayable(self, ref, callback):
90 if not config.ParentalControl.configured.value or not config.ParentalControl.servicepinactive.value:
92 #Check if we already read the whitelists and blacklists. If not: call open
93 if self.filesOpened == False:
95 #Check if configuration has already been read or if the significant values have changed.
96 #If true: read the configuration
97 if self.configInitialized == False or self.storeServicePin != config.ParentalControl.storeservicepin.value or self.storeServicePinCancel != config.ParentalControl.storeservicepincancel.value:
98 self.getConfigValues()
99 service = ref.toCompareString()
100 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)):
101 #Check if the session pin is cached and return the cached value, if it is.
102 if self.sessionPinCached == True:
103 #As we can cache successful pin- entries as well as canceled pin- entries,
104 #We give back the last action
105 return self.sessionPinCachedValue
106 self.callback = callback
107 #Someone started to implement different levels of protection. Seems they were never completed
108 #I did not throw out this code, although it is of no use at the moment
110 if self.serviceLevel.has_key(service):
111 levelNeeded = self.serviceLevel[service]
112 pinList = self.getPinList()[:levelNeeded + 1]
113 Notifications.AddNotificationWithCallback(boundFunction(self.servicePinEntered, ref), PinInput, triesEntry = config.ParentalControl.retries.servicepin, pinList = pinList, service = ServiceReference(ref).getServiceName(), title = _("this service is protected by a parental control pin"), windowTitle = _("Parental control"))
118 def protectService(self, service):
119 if config.ParentalControl.type.value == LIST_WHITELIST:
120 if self.whitelist.has_key(service):
121 self.serviceMethodWrapper(service, self.removeServiceFromList, self.whitelist)
122 #self.deleteWhitelistService(service)
124 if not self.blacklist.has_key(service):
125 self.serviceMethodWrapper(service, self.addServiceToList, self.blacklist)
126 #self.addBlacklistService(service)
127 #print "whitelist:", self.whitelist
128 #print "blacklist:", self.blacklist
130 def unProtectService(self, service):
132 #print "config.ParentalControl.type.value:", config.ParentalControl.type.value
133 if config.ParentalControl.type.value == LIST_WHITELIST:
134 if not self.whitelist.has_key(service):
135 self.serviceMethodWrapper(service, self.addServiceToList, self.whitelist)
136 #self.addWhitelistService(service)
138 if self.blacklist.has_key(service):
139 self.serviceMethodWrapper(service, self.removeServiceFromList, self.blacklist)
140 #self.deleteBlacklistService(service)
141 #print "whitelist:", self.whitelist
142 #print "blacklist:", self.blacklist
144 def getProtectionLevel(self, service):
145 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)):
146 if self.serviceLevel.has_key(service):
147 return self.serviceLevel[service]
153 def getProtectionType(self, service):
154 #New method used in ParentalControlList: This method does not only return
155 #if a service is protected or not, it also returns, why (whitelist or blacklist, service or bouquet)
156 if self.filesOpened == False:
159 if (config.ParentalControl.type.value == LIST_WHITELIST):
160 if self.whitelist.has_key(service):
161 if TYPE_SERVICE in self.whitelist[service]:
162 sImage = IMG_WHITESERVICE
164 sImage = IMG_WHITEBOUQUET
165 elif (config.ParentalControl.type.value == LIST_BLACKLIST):
166 if self.blacklist.has_key(service):
167 if TYPE_SERVICE in self.blacklist[service]:
168 sImage = IMG_BLACKSERVICE
170 sImage = IMG_BLACKBOUQUET
171 bLocked = self.getProtectionLevel(service) != -1
172 return (bLocked,sImage)
174 def getConfigValues(self):
175 #Read all values from configuration
176 self.checkPinInterval = False
177 self.checkPinIntervalCancel = False
178 self.checkSessionPin = False
179 self.checkSessionPinCancel = False
181 self.sessionPinCached = False
182 self.pinIntervalSeconds = 0
183 self.pinIntervalSecondsCancel = 0
185 self.storeServicePin = config.ParentalControl.storeservicepin.value
186 self.storeServicePinCancel = config.ParentalControl.storeservicepincancel.value
188 if self.storeServicePin == "never":
190 elif self.storeServicePin == "standby":
191 self.checkSessionPin = True
193 self.checkPinInterval = True
194 iMinutes = float(self.storeServicePin)
195 iSeconds = iMinutes*60
196 self.pinIntervalSeconds = iSeconds
198 if self.storeServicePinCancel == "never":
200 elif self.storeServicePinCancel == "standby":
201 self.checkSessionPinCancel = True
203 self.checkPinIntervalCancel = True
204 iMinutes = float(self.storeServicePinCancel)
205 iSeconds = iMinutes*60
206 self.pinIntervalSecondsCancel = iSeconds
208 self.configInitialized = True
209 # Reset PIN cache on standby: Use StandbyCounter- Config- Callback
210 config.misc.standbyCounter.addNotifier(self.standbyCounterCallback, initial_call = False)
212 def standbyCounterCallback(self, configElement):
213 self.resetSessionPin()
215 def resetSessionPin(self):
216 #Reset the session pin, stop the timer
217 self.sessionPinCached = False
218 self.sessionPinTimer.stop()
220 def getCurrentTimeStamp(self):
223 def getPinList(self):
224 return [ x.value for x in config.ParentalControl.servicepin ]
226 def servicePinEntered(self, service, result):
228 if result is not None and result:
229 #This is the new function of caching the service pin
230 #save last session and time of last entered pin...
231 if self.checkSessionPin == True:
232 self.sessionPinCached = True
233 self.sessionPinCachedValue = True
234 if self.checkPinInterval == True:
235 self.sessionPinCached = True
236 self.sessionPinCachedValue = True
237 self.sessionPinTimer.start(self.pinIntervalSeconds*1000,1)
238 self.callback(ref = service)
240 #This is the new function of caching cancelling of service pin
241 if result is not None:
242 Notifications.AddNotification(MessageBox, _("The pin code you entered is wrong."), MessageBox.TYPE_ERROR)
244 if self.checkSessionPinCancel == True:
245 self.sessionPinCached = True
246 self.sessionPinCachedValue = False
247 if self.checkPinIntervalCancel == True:
248 self.sessionPinCached = True
249 self.sessionPinCachedValue = False
250 self.sessionPinTimer.start(self.pinIntervalSecondsCancel*1000,1)
252 def saveListToFile(self,sWhichList):
253 #Replaces saveWhiteList and saveBlackList:
254 #I don't like to have two functions with identical code...
255 if sWhichList == LIST_BLACKLIST:
256 vList = self.blacklist
258 vList = self.whitelist
259 file = open(resolveFilename(SCOPE_CONFIG, sWhichList), 'w')
260 for sService,sType in vList.iteritems():
261 #Only Services that are selected directly and Bouqets are saved.
262 #Services that are added by a bouquet are not saved.
263 #This is the reason for the change in self.whitelist and self.blacklist
264 if TYPE_SERVICE in sType or TYPE_BOUQUET in sType:
265 file.write(str(sService) + "\n")
268 def openListFromFile(self,sWhichList):
269 #Replaces openWhiteList and openBlackList:
270 #I don't like to have two functions with identical code...
271 if sWhichList == LIST_BLACKLIST:
273 vList = self.blacklist
276 vList = self.whitelist
278 file = open(resolveFilename(SCOPE_CONFIG, sWhichList ), 'r')
279 lines = file.readlines()
282 self.serviceMethodWrapper(sPlain, self.addServiceToList, vList)
287 def addServiceToList(self, service, type, vList):
288 #Replaces addWhitelistService and addBlacklistService
289 #The lists are not only lists of service references any more.
290 #They are named lists with the service as key and an array of types as value:
292 if vList.has_key(service):
293 if not type in vList[service]:
294 vList[service].append(type)
296 vList[service] = [type]
298 def removeServiceFromList(self, service, type, vList):
299 #Replaces deleteWhitelistService and deleteBlacklistService
300 if vList.has_key(service):
301 if type in vList[service]:
302 vList[service].remove(type)
303 if not vList[service]:
305 if self.serviceLevel.has_key(service):
306 self.serviceLevel.remove(service)
308 def readServicesFromBouquet(self,sBouquetSelection,formatstring):
309 #This method gives back a list of services for a given bouquet
310 from enigma import eServiceCenter, eServiceReference
311 from Screens.ChannelSelection import service_types_tv
312 serviceHandler = eServiceCenter.getInstance()
313 refstr = sBouquetSelection
314 root = eServiceReference(refstr)
315 list = serviceHandler.list(root)
317 services = list.getContent("CN", True) #(servicecomparestring, name)
321 # we need to open the files in case we havent's read them yet
322 if not self.filesOpened:
324 self.saveListToFile(LIST_BLACKLIST)
325 self.saveListToFile(LIST_WHITELIST)
328 self.openListFromFile(LIST_BLACKLIST)
329 self.openListFromFile(LIST_WHITELIST)
330 self.filesOpened = True
332 parentalControl = ParentalControl()