示例#1
0
    def checkPlugins(self):
        navPath = xbmc.getInfoLabel("Container.FolderPath")
        if 'plugin://' not in navPath:
            # No Plugin currently set
            self.lastPluginChecked = ""
            return

        # Check if we are in a plugin location
        pluginName = xbmc.getInfoLabel("Container.FolderName")

        if pluginName in [None, "", self.lastPluginChecked]:
            # No Plugin currently set or this is a Plugin that has already been checked
            return

        # If we reach here we have aPlugin that we need to check
        log("NavigationRestrictions: Checking access to view Plugin: %s" %
            pluginName)
        self.lastPluginChecked = pluginName

        # Check for the case where the user does not want to check plugins
        # but the Pin Sentry plugin is selected, we always need to check this
        # as it is how permissions are set
        if (not Settings.isActivePlugins()) and ('PinSentry'
                                                 not in pluginName):
            return

        securityLevel = 0
        # Check to see if the user should have access to this plugin
        pinDB = PinSentryDB()
        securityLevel = pinDB.getPluginSecurityLevel(pluginName)
        if securityLevel < 1:
            # Check for the special case that we are accessing ourself
            # in which case we have a minimum security level
            if 'PinSentry' in pluginName:
                securityLevel = Settings.getSettingsSecurityLevel()
            else:
                log("NavigationRestrictions: No security enabled for plugin %s"
                    % pluginName)
                return
        del pinDB

        # Check if we have already cached the pin number and at which level
        if PinSentry.getCachedPinLevel() >= securityLevel:
            log("NavigationRestrictions: Already cached pin at level %d, allowing access"
                % PinSentry.getCachedPinLevel())
            return

        # Prompt the user for the pin, returns True if they knew it
        if PinSentry.promptUserForPin(securityLevel):
            log("NavigationRestrictions: Allowed access to plugin %s" %
                pluginName)
        else:
            log("NavigationRestrictions: Not allowed access to plugin %s which has security level %d"
                % (pluginName, securityLevel))
            # Move back to the Video plugin Screen as they are not allowed where they are at the moment
            xbmc.executebuiltin(
                "ActivateWindow(Video,addons://sources/video/)", True)
            # Clear the previous plugin as we will want to prompt for the pin again if the
            # user navigates there again
            self.lastPluginChecked = ""
            PinSentry.displayInvalidPinMessage(securityLevel)
示例#2
0
    def onPlayBackStarted(self):
        if not Settings.isActiveVideoPlaying():
            return

        log("PinSentryPlayer: Notification that something started playing")

        # Only interested if it is not playing music
        if self.isPlayingAudio():
            return

        # Ignore screen saver videos
        if xbmcgui.Window(10000).getProperty("VideoScreensaverRunning"):
            log("PinSentryPlayer: Detected VideoScreensaver playing")
            return

        # Check if the Pin is set, as no point prompting if it is not
        if not PinSentry.isPinSentryEnabled():
            return

        isMusicVideo = False
        isTvShow = False
        # Get the information for what is currently playing
        # http://kodi.wiki/view/InfoLabels#Video_player
        title = xbmc.getInfoLabel("VideoPlayer.TVShowTitle")

        # If the TvShow Title is not set, then Check the ListItem as well
        if title in [None, ""]:
            title = xbmc.getInfoLabel("ListItem.TVShowTitle")

        securityLevel = 0
        # If it is a TvShow, then check to see if it is enabled for this one
        if title not in [None, ""]:
            isTvShow = True
            log("PinSentryPlayer: TVShowTitle: %s" % title)
            pinDB = PinSentryDB()
            securityLevel = pinDB.getTvShowSecurityLevel(title)
            del pinDB
        else:
            # Check if the video is a music video
            isMusicVideo = self.isMusicVideoPlaying()

            # Not a TvShow, so check for the Movie Title
            title = xbmc.getInfoLabel("VideoPlayer.Title")

            # If no title is found, check the ListItem rather then the Player
            if title in [None, ""]:
                title = xbmc.getInfoLabel("ListItem.Title")

            if title not in [None, ""]:
                if not isMusicVideo:
                    # Check for a Movie
                    log("PinSentryPlayer: Title: %s" % title)
                    pinDB = PinSentryDB()
                    securityLevel = pinDB.getMovieSecurityLevel(title)
                    del pinDB
                else:
                    # Now check to see if this is  music video
                    log("PinSentryPlayer: Checking Music video for: %s" %
                        title)
                    pinDB = PinSentryDB()
                    securityLevel = pinDB.getMusicVideoSecurityLevel(title)
                    del pinDB

        # For video files it is possible to set them to always be allowed to play, in this case
        # the security value is -1 and we don't want to perform any new checking
        if securityLevel == -1:
            log("PinSentryPlayer: Security level is -1, so allowing access")
            return

        # Now perform the check that restricts if a file is in a file source
        # that should not be played
        if securityLevel < 1 and Settings.isActiveFileSource(
        ) and Settings.isActiveFileSourcePlaying():
            # Get the path of the file being played
            filePath = xbmc.getInfoLabel("Player.Folderpath")
            if filePath in [None, ""]:
                filePath = xbmc.getInfoLabel("Player.Filenameandpath")
            if filePath in [None, ""]:
                filePath = xbmc.getInfoLabel("ListItem.FolderPath")
            if filePath in [None, ""]:
                filePath = xbmc.getInfoLabel("ListItem.FileNameAndPath")
            log("PinSentryPlayer: Checking file path: %s" % filePath)

            # Get all the sources that are protected
            pinDB = PinSentryDB()
            securityDetails = pinDB.getAllFileSourcesPathsSecurity()
            del pinDB

            # Each key is in path with security applied
            for key in securityDetails.keys():
                if key in filePath:
                    securityLevel = securityDetails[key]
                    log("PinSentryPlayer: Setting path based security to %d" %
                        securityLevel)

        # Now check to see if this item has a certificate restriction
        if securityLevel < 1:
            cert = xbmc.getInfoLabel("VideoPlayer.mpaa")
            if cert in [None, ""]:
                cert = xbmc.getInfoLabel("ListItem.Mpaa")

            if cert not in [None, ""]:
                log("PinSentryPlayer: Checking for certification restrictions: %s"
                    % str(cert))
                # Now split based on a colon and spaces, we only want the last bit of the
                # MPAA setting as the first bit can change based on scraper
                cert = cert.strip().split(':')[-1]
                cert = cert.strip().split()[-1]
                pinDB = PinSentryDB()
                if isTvShow:
                    # Look up the TV Shows Certificate to see if it is restricted
                    securityLevel = pinDB.getTvClassificationSecurityLevel(
                        cert)
                else:
                    # Look up the Movies Certificate to see if it is restricted
                    securityLevel = pinDB.getMovieClassificationSecurityLevel(
                        cert)
                del pinDB

            # If we have still not set security yet, check to make sure that the classification was actually
            # one of our supported types
            if securityLevel < 1:
                if isTvShow:
                    if not Settings.isSupportedTvShowClassification(cert):
                        securityLevel = Settings.getDefaultTvShowsWithoutClassification(
                        )
                        log("PinSentryPlayer: Setting TV Show to level %d as there is no valid MPAA value"
                            % securityLevel)
                elif not isMusicVideo:
                    if not Settings.isSupportedMovieClassification(cert):
                        securityLevel = Settings.getDefaultMoviesWithoutClassification(
                        )
                        log("PinSentryPlayer: Setting Movie to level %d as there is no valid MPAA value"
                            % securityLevel)

            # Check if we have set security based off of the classification
            if securityLevel > 0:
                # Before we check to make sure the user can access this video based on the
                # movie or TV Show classification, check for the case where there is background
                # media playing, this can be the case if TvTunes has started a Video while browsing
                # We do not want to prompt for the user to input the key for this
                isBackgroundMedia = True
                # Total wait for not playing background media is 1 second
                loopCount = 100
                while isBackgroundMedia and (loopCount > 0):
                    loopCount = loopCount - 1
                    if xbmcgui.Window(10025).getProperty(
                            "PlayingBackgroundMedia") in [None, ""]:
                        isBackgroundMedia = False
                        break
                    xbmc.sleep(10)

                if isBackgroundMedia:
                    securityLevel = 0
                    log("PinSentryPlayer: Playing background media")

        # Check if security has been set on this item
        if securityLevel < 1:
            if title in [None, ""]:
                # Not a TvShow or Movie - so allow the user to continue
                # without entering a pin code
                log("PinSentryPlayer: No security enabled, no title available")
            else:
                log("PinSentryPlayer: No security enabled for %s" % title)
            return

        # Check if we have already cached the pin number and at which level
        if PinSentry.getCachedPinLevel() >= securityLevel:
            log("PinSentryPlayer: Already cached pin at level %d, allowing access"
                % PinSentry.getCachedPinLevel())
            return

        # Before we start prompting the user for the pin, check to see if we
        # have already been called and are prompting in another thread
        if xbmcgui.Window(10000).getProperty("PinSentryPrompting"):
            log("PinSentryPlayer: Already prompting for security code")
            return

        # Set the flag so other threads know we are processing this play request
        xbmcgui.Window(10000).setProperty("PinSentryPrompting", "true")

        # Pause the video so that we can prompt for the Pin to be entered
        # On some systems we could get notified that we have started playing a video
        # before it has actually been started, so keep trying to pause until we get
        # one that works
        while not xbmc.getCondVisibility("Player.Paused"):
            self.pause()

        log("PinSentryPlayer: Pausing video to check if OK to play")

        # Prompt the user for the pin, returns True if they knew it
        if PinSentry.promptUserForPin(securityLevel):
            log("PinSentryPlayer: Resuming video")
            # Pausing again will start the video playing again
            self.pause()
        else:
            log("PinSentryPlayer: Stopping video")
            self.stop()
            PinSentry.displayInvalidPinMessage(securityLevel)

        xbmcgui.Window(10000).clearProperty("PinSentryPrompting")
示例#3
0
        # Using ShutDown will perform the default behaviour that Kodi has in the system settings
        xbmc.executebuiltin("ShutDown")


##################################
# Main of the PinSentry Service
##################################
if __name__ == '__main__':
    log("Starting Pin Sentry Service %s" % ADDON.getAddonInfo('version'))

    # Tidy up any old pins and set any warnings when we first start
    Settings.checkPinSettings()

    # Make sure that the database exists if this is the first time
    pinDB = PinSentryDB()
    pinDB.createOrUpdateDB()
    del pinDB

    # Check to see if we need to restrict based on a given user to ensure they
    # are allowed to use the system
    userCtrl = UserPinControl()
    userCtrl.startupCheck()

    playerMonitor = PinSentryPlayer()
    systemMonitor = PinSentryMonitor()
    navRestrictions = NavigationRestrictions()

    # Check if we need to prompt for the pin when the system starts
    if Settings.isPromptForPinOnStartup():
        log("PinSentry: Prompting for pin on startup")
示例#4
0
    def checkSettings(self):
        # Check if we are in the Addon Information page (which can be used to disable the addon)
        # or the actual setting page
        addonSettings = xbmc.getCondVisibility("Window.IsActive(10140)")
        addonInformation = xbmc.getCondVisibility("Window.IsActive(10146)")

        if not addonSettings and not addonInformation:
            # If not looking at an info or settings page, and the time for
            # allowed edits has ended, then reset it
            if self.canChangeSettings > 0:
                # If we have reached the home page, reset the timer
                if xbmc.getCondVisibility("Window.IsVisible(home)"):
                    self.canChangeSettings = 0
                elif time.time() > self.canChangeSettings:
                    self.canChangeSettings = 0
            return

        # Check if the addon is the PinSentry addon
        addonId = xbmc.getInfoLabel("ListItem.Property(Addon.ID)")
        if 'script.pinsentry' not in addonId:
            self.canChangeSettings = 0
            return

        # If we have already allowed the user to change settings, no need to check again
        # Check if we are still in the allowed time limit to edit
        if int(time.time()) < self.canChangeSettings:
            return

        # Need to make sure this user has access to change the settings
        pinDB = PinSentryDB()
        securityLevel = pinDB.getPluginSecurityLevel('PinSentry')
        del pinDB

        if securityLevel < 1:
            # If the user hasn't reset the permissions, then set it to the highest
            # security level available
            securityLevel = Settings.getSettingsSecurityLevel()
            log("NavigationRestrictions: Settings screen requires security level %d"
                % securityLevel)

        # Check if we have already cached the pin number and at which level
        if PinSentry.getCachedPinLevel() >= securityLevel:
            log("NavigationRestrictions: Already cached pin at level %d, allowing access"
                % PinSentry.getCachedPinLevel())
            return

        # Before we prompt the user we need to close the dialog, otherwise the pin
        # dialog will appear behind it
        xbmc.executebuiltin("Dialog.Close(all, true)", True)

        # Prompt the user for the pin, returns True if they knew it
        if PinSentry.promptUserForPin(securityLevel):
            log("NavigationRestrictions: Allowed access to settings")
            # Allow the user 5 minutes to change the settings
            self.canChangeSettings = int(time.time()) + 300
            xbmcgui.Dialog().notification(
                ADDON.getLocalizedString(32001).encode('utf-8'),
                ADDON.getLocalizedString(32110).encode('utf-8'), ICON, 3000,
                False)

            # Open the dialogs that should be shown, we don't reopen the Information dialog
            # as if we do the Close Dialog will not close it and the pin screen will not show correctly
            if addonSettings:
                # Open the addon settings dialog
                xbmc.executebuiltin("Addon.OpenSettings(script.pinsentry)",
                                    False)
        else:
            log("NavigationRestrictions: Not allowed access to settings which has security level %d"
                % securityLevel)
            self.canChangeSettings = False
            PinSentry.displayInvalidPinMessage(securityLevel)
示例#5
0
    def setSecurity(self,
                    type,
                    title,
                    id,
                    oldLevel,
                    classBlocked=False,
                    forceLevel=None):
        log("Setting security for (id:%s) %s" % (id, title))

        level = 1

        # Check if we need to prompt the user or the new security level has been supplied
        if forceLevel is None:
            # Set the new security level to be used
            if oldLevel > 0:
                # Default is to disable it if it was enabled
                level = 0

            numLevels = Settings.getNumberOfLevels()
            if numLevels > 1 or classBlocked:
                # Need to prompt the user to see which pin they are trying to set
                displayNameList = []
                # Add the option to turn it off
                displayNameList.append("%s %s" %
                                       (ADDON.getLocalizedString(32211),
                                        ADDON.getLocalizedString(32013)))
                for i in range(1, numLevels + 1):
                    secLevStr = str(i)
                    if numLevels < 2:
                        # If there is only one security level, use "On" rather than the number
                        secLevStr = ADDON.getLocalizedString(32014)
                    displayString = "%s %s" % (ADDON.getLocalizedString(32211),
                                               secLevStr)
                    displayNameList.append(displayString)

                # Check if we need the option to disable a classification restriction
                if classBlocked:
                    displayNameList.append(ADDON.getLocalizedString(32212))

                select = xbmcgui.Dialog().select(
                    ADDON.getLocalizedString(32001), displayNameList)

                if select != -1:
                    level = select
                    if classBlocked and (select >= (len(displayNameList) - 1)):
                        level = -1
                    log("Setting security level to %d" % level)
                else:
                    log("Exiting set security as no level selected")
                    return
        else:
            level = forceLevel

        # This could take a little time to set the value so show the busy dialog
        xbmc.executebuiltin("ActivateWindow(busydialog)")

        if title not in [None, ""]:
            pinDB = PinSentryDB()
            if type == MenuNavigator.TVSHOWS:
                # Set the security level for this title, setting it to zero
                # will result in the entry being removed from the database
                # as the default for an item is unset
                pinDB.setTvShowSecurityLevel(title, int(id), level)
            elif type == MenuNavigator.MOVIES:
                pinDB.setMovieSecurityLevel(title, int(id), level)
            elif type == MenuNavigator.MOVIESETS:
                pinDB.setMovieSetSecurityLevel(title, int(id), level)
                # As well as setting the security on the Movie set, we need
                # to also set it on each movie in the Movie Set
                self._setSecurityOnMoviesInMovieSets(int(id), level)
            elif type == MenuNavigator.MUSICVIDEOS:
                pinDB.setMusicVideoSecurityLevel(title, int(id), level)
            elif type == MenuNavigator.PLUGINS:
                pinDB.setPluginSecurityLevel(title, id, level)
            elif type == MenuNavigator.FILESOURCE:
                pinDB.setFileSourceSecurityLevel(title, id, level)
            elif type == MenuNavigator.CLASSIFICATIONS_MOVIES:
                pinDB.setMovieClassificationSecurityLevel(id, title, level)
            elif type == MenuNavigator.CLASSIFICATIONS_TV:
                pinDB.setTvClassificationSecurityLevel(id, title, level)
            del pinDB
        else:
            # Handle the bulk operations like set All security for the movies
            self._setBulkSecurity(type, level)

        xbmc.executebuiltin("Dialog.Close(busydialog)")
        xbmc.executebuiltin("Container.Refresh")
示例#6
0
    def _setClassificationList(self, type="", subtype=""):
        classifications = ()
        securityDetails = {}

        # Make the call to the DB to get all the specific security settings
        pinDB = PinSentryDB()

        if type == MenuNavigator.CLASSIFICATIONS_MOVIES:
            classifications = Settings.movieCassificationsNames
            securityDetails = pinDB.getAllMovieClassificationSecurity()
        elif type == MenuNavigator.CLASSIFICATIONS_TV:
            classifications = Settings.tvCassificationsNames
            securityDetails = pinDB.getAllTvClassificationSecurity()

        del pinDB

        # Check if we are showing the root classification listing
        if type in [None, ""]:
            url = self._build_url({
                'mode': 'folder',
                'foldername': MenuNavigator.CLASSIFICATIONS,
                'type': MenuNavigator.CLASSIFICATIONS_MOVIES
            })
            li = xbmcgui.ListItem(ADDON.getLocalizedString(32207),
                                  iconImage=ICON)
            li.setProperty("Fanart_Image", FANART)
            li.addContextMenuItems([], replaceItems=True)
            xbmcplugin.addDirectoryItem(handle=self.addon_handle,
                                        url=url,
                                        listitem=li,
                                        isFolder=True)

            url = self._build_url({
                'mode': 'folder',
                'foldername': MenuNavigator.CLASSIFICATIONS,
                'type': MenuNavigator.CLASSIFICATIONS_TV
            })
            li = xbmcgui.ListItem(ADDON.getLocalizedString(32208),
                                  iconImage=ICON)
            li.setProperty("Fanart_Image", FANART)
            li.addContextMenuItems([], replaceItems=True)
            xbmcplugin.addDirectoryItem(handle=self.addon_handle,
                                        url=url,
                                        listitem=li,
                                        isFolder=True)
        elif subtype in [None, ""]:
            # Get all the different language that are supported
            languages = []
            for classification in classifications:
                if classification['lang'] not in languages:
                    languages.append(classification['lang'])

            # Check to see if we can sort all the entries alphabetically for the given language
            try:
                languages = sorted(languages, key=ADDON.getLocalizedString)
            except:
                # If it fails to sort, then we just list them unsorted
                log("PinSentryPlugin: Failed to sort language list")

            # Now print out the item for each language
            for lang in languages:
                url = self._build_url({
                    'mode': 'folder',
                    'foldername': MenuNavigator.CLASSIFICATIONS,
                    'type': type,
                    'subtype': str(lang)
                })

                iconImage = ICON
                for flag in Settings.flags:
                    if flag['lang'] == lang:
                        iconImage = os_path_join(ICON_DIR, flag['icon'])

                li = xbmcgui.ListItem(ADDON.getLocalizedString(lang),
                                      iconImage=iconImage)
                li.setProperty("Fanart_Image", FANART)
                li.addContextMenuItems([], replaceItems=True)
                xbmcplugin.addDirectoryItem(handle=self.addon_handle,
                                            url=url,
                                            listitem=li,
                                            isFolder=True)
        else:
            for classification in classifications:
                # Check if we are looking for a specific country
                if subtype != str(classification['lang']):
                    continue

                fullName = classification['name'] % ADDON.getLocalizedString(
                    classification['lang'])
                idStr = str(classification['id'])
                securityLevel = 0
                if idStr in securityDetails:
                    securityLevel = securityDetails[idStr]
                    log("PinSentryPlugin: Classification %s has security level %d"
                        % (fullName, securityLevel))

                # Set the icon to the certificate one if available
                iconImage = ICON
                if classification['icon'] not in [None, ""]:
                    iconImage = os_path_join(ICON_DIR, classification['icon'])

                li = xbmcgui.ListItem(fullName, iconImage=iconImage)

                # Add a tick if security is set
                if securityLevel > 0:
                    li.setInfo('video', {'PlayCount': 1})

                li.setProperty("Fanart_Image", FANART)
                li.addContextMenuItems([], replaceItems=True)
                url = self._build_url({
                    'mode': 'setsecurity',
                    'type': type,
                    'id': classification['id'],
                    'title': classification['match'],
                    'level': securityLevel
                })
                xbmcplugin.addDirectoryItem(handle=self.addon_handle,
                                            url=url,
                                            listitem=li,
                                            isFolder=False)

        xbmcplugin.endOfDirectory(self.addon_handle)