예제 #1
0
 def __init__(self, f, *args, **kwargs):
   self.batchname = f.__name__
   self.__function = f
   self.__functionArgs = args
   self.__functionKwargs = kwargs
   try:
     for item in inspect.stack():
       if progressive_load.loaders.has_key(item[3]):
         self.loadername = item[3]
         progressive_load.loaders[self.loadername].batches.append(self)
         return
     raise
   except:
     PMS.Log("(Framework) ERROR: Unable to find a progressive loader for the batch named '%s'" % self.batchname)
     return
예제 #2
0
def __save():
    global __prefs
    global __prefsPath
    Thread.Lock("Framework.Prefs", addToLog=False)
    try:
        userPrefs = XML.Element("PluginPreferences")
        for pref in __prefs:
            if pref.has_key("value"):
                userPrefs.append(XML.Element(pref["id"], pref["value"]))
        f = open(__prefsPath, "w")
        f.write(XML.StringFromElement(userPrefs))
        f.close()
        PMS.Log("(Framework) Saved the user preferences file")
    finally:
        Thread.Unlock("Framework.Prefs", addToLog=False)
예제 #3
0
 def __call__(self, f):
     self.name = f.__name__
     if progressive_load.loaders.has_key(self.name):
         self = progressive_load.loaders[self.name]
     else:
         PMS.Log("(Framework) Started a new progressive loader named '%s'" %
                 self.name)
         self.__function = f
         self.last_fetch_time = Datetime.Now()
         progressive_load.loaders[self.name] = self
         Thread.Create(progressive_load.__runLoader, self)
     i = 0
     while i < 10 and len(self.container) == 0:
         Thread.Sleep(0.1)
     return self.getContainer()
예제 #4
0
def __save():
    global __saveScheduled
    Thread.Lock("Framework.HTTPCache", addToLog=False)
    try:
        # Save the cache
        Data.__pickle("%s/HTTPCache" % Data.__dataPath, __cache)

        # Save the cookie jar
        if __cookieJar is not None:
            __cookieJar.save("%s/HTTPCookies" % Data.__dataPath)

    finally:
        __saveScheduled = False
        Thread.Unlock("Framework.HTTPCache", addToLog=False)
        PMS.Log("(Framework) Saved shared HTTP data")
예제 #5
0
 def __init__(self, f, *args, **kwargs):
   self.taskname = f.__name__
   self.__function = f
   self.__args = args
   self.__kwargs = kwargs
   
   try:
     for item in inspect.stack():
       if parallel.tasksets.has_key(item[3]):
         self.tasksetname = item[3]
         parallel.tasksets[self.tasksetname].append(self)
         return
     raise
   except:
     PMS.Log("(Framework) ERROR: Unable to find a task set for the task named '%s'" % self.taskname)
     return
예제 #6
0
def __checkFrameworkCompatibility():
    try:
        lastFrameworkVersion = Dict.Get("Framework.LastCompatibilityVersion")
        if lastFrameworkVersion != PMS.FrameworkCompatibilityVersion: raise
        return True
    except:
        PMS.Log(
            "(Framework) Data stored by an earlier framework version has been removed due to incompatibilities."
        )
        if os.path.exists(Prefs.__prefsPath): os.unlink(Prefs.__prefsPath)
        if os.path.exists(Database.__databasePath):
            os.unlink(Database.__databasePath)
        shutil.rmtree(Data.__dataPath)
        os.makedirs(Data.__dataItemPath)
        Dict.__loadDefaults()
        Dict.__save(addToLog=False)
        return False
예제 #7
0
 def __init__(self,
              key,
              title,
              prompt,
              subtitle=None,
              summary=None,
              thumb=None,
              art=None,
              **kwargs):
     PMS.Log(
         "(Framework) WARNING: SearchDirectoryItem is deprecated. Use InputDirectoryItem instead."
     )
     InputDirectoryItem.__init__(self,
                                 key=key,
                                 title=title,
                                 prompt=prompt,
                                 subtitle=subtitle,
                                 summary=summary,
                                 thumb=thumb,
                                 art=art,
                                 **kwargs)
예제 #8
0
def __autoUpdateCachedPages():
    global __cache
    for url in __cache:
        item = __cache[url]
        if item.has_key("UpdateTime"):
            # Check whether the page would expire before the next cache update is triggered
            if item["UpdateTime"] < (Datetime.Now() + Datetime.Delta(
                    seconds=__autoUpdateCacheTime)):
                if item.has_key("Headers"):
                    headers = item["Headers"]
                else:
                    headers = {}
                PMS.Log(
                    "(Framework) Automatically updating the cached copy of %s"
                    % url)
                Request(url,
                        headers=headers,
                        cacheTime=item["CacheTime"],
                        autoUpdate=True,
                        encoding=item["Encoding"],
                        errors=item["Errors"],
                        addToLog=False)
예제 #9
0
def SetDefaultLocale(loc="en-us"):
    global defaultLangDict
    global defaultCountryDict
    global __defaultLocale
    global CurrentLocale
    if loc == __defaultLocale: return

    __defaultLocale = loc

    pos = __defaultLocale.find("-")

    if pos > -1:
        lang = __defaultLocale[:pos]
        langPath = os.path.join(Plugin.__bundlePath,
                                "Contents/Strings/%s.json" % lang)
        if os.path.exists(langPath):
            f = open(langPath, "r")
            defaultLangDict = JSON.ObjectFromString(f.read())
            f.close()
            PMS.Log("(Framework) Loaded %s strings" % lang)
        else:
            PMS.Log("(Framework) Couldn't find %s strings" % lang)

        locPath = os.path.join(Plugin.__bundlePath,
                               "Contents/Strings/%s.json" % __defaultLocale)
        if os.path.exists(locPath):
            f = open(locPath, "r")
            defaultCountryDict = JSON.ObjectFromString(f.read())
            f.close()
            PMS.Log("(Framework) Loaded %s strings" % __defaultLocale)
        else:
            PMS.Log("(Framework) Couldn't find %s strings" % __defaultLocale)

    else:
        langPath = os.path.join(Plugin.__bundlePath,
                                "Contents/Strings/%s.json" % __defaultLocale)
        if os.path.exists(langPath):
            f = open(langPath, "r")
            defaultLangDict = JSON.ObjectFromString(f.read())
            f.close()
            PMS.Log("(Framework) Loaded %s strings" % __defaultLocale)
        else:
            PMS.Log("(Framework) Couldn't find %s strings" % __defaultLocale)

    if CurrentLocale == None: CurrentLocale = loc
예제 #10
0
def __loadLocale(loc):
    global CurrentLocale
    if loc == CurrentLocale:
        return None

    global langDict
    global countryDict
    pos = loc.find("-")

    if pos > -1:

        lang = loc[:pos]
        langPath = os.path.join(Plugin.__bundlePath,
                                "Contents/Strings/%s.json" % lang)
        if os.path.exists(langPath):
            f = open(langPath, "r")
            langDict = JSON.ObjectFromString(f.read())
            f.close()
            PMS.Log("(Framework) Loaded %s strings" % lang)
        else:
            PMS.Log("(Framework) Couldn't find %s strings" % lang)

        locPath = os.path.join(Plugin.__bundlePath,
                               "Contents/Strings/%s.json" % loc)
        if os.path.exists(locPath):
            f = open(locPath, "r")
            countryDict = JSON.ObjectFromString(f.read())
            f.close()
            PMS.Log("(Framework) Loaded %s strings" % loc)
        else:
            PMS.Log("(Framework) Couldn't find %s strings" % loc)

    else:
        langPath = os.path.join(Plugin.__bundlePath,
                                "Contents/Strings/%s.json" % loc)
        if os.path.exists(langPath):
            f = open(langPath, "r")
            langDict = JSON.ObjectFromString(f.read())
            f.close()
            PMS.Log("(Framework) Loaded %s strings" % loc)
        else:
            PMS.Log("(Framework) Couldn't find %s strings" % loc)

    CurrentLocale = loc
예제 #11
0
def __scanModules():
    global __modBundled
    global __modLibs

    for path, dirs, files in os.walk(
            os.path.join(__bundlePath, "Contents/Code")):
        for d in dirs:
            __modBundled.append(d)
        for f in files:
            if f.endswith(".py"):
                if f != "__init__.py":
                    __modBundled.append(f[:-3])
            elif not f.endswith(".pyc"):
                PMS.Log(
                    "(Framework) WARNING: Non-code file named '%s' found inside the Code directory. Future framework versions will abort at this point."
                    % f)

    for path, dirs, files in os.walk(os.path.join(sys.path[0],
                                                  "../Libraries")):
        for d in dirs:
            __modLibs.append(d)
        for f in files:
            if f != "__init__.py" and f.endswith(".py"):
                __modLibs.append(f[:-3])
예제 #12
0
def SaveObject(itemName, obj):
    __pickle(__path(itemName), obj)
    PMS.Log("(Framework) Saved the data item named '%s' as an object" %
            itemName)
예제 #13
0
def Save(itemName, data):
    __write(__path(itemName), data)
    PMS.Log("(Framework) Saved the data item named '%s'" % itemName)
예제 #14
0
def __rollback():
    global __changed
    __db.rollback()
    PMS.Log("(Framework) Rolled back the database")
    __changed = False
예제 #15
0
def __commit():
    global __changed
    __db.commit()
    PMS.Log("(Framework) Committed the database")
    __changed = False
예제 #16
0
def LoadShared(itemName, binary=False):
    data = __load("%s/%s" % (__sharedResourcePath, itemName), binary)
    if data is not None:
        PMS.Log("(Framework) Loaded shared resource named '%s'" % itemName)
        return data
예제 #17
0
def __exit():
    if Database.__db is not None:
        Database.__db.close()
    PMS.Log("(Framework) Plug-in stopped")
    sys.exit()
예제 #18
0
def __run(_bundlePath):
    #
    # Initializes the framework, verifies the plug-in & extracts information, then enters a
    # run loop for handling requests.
    #
    global Identifier
    global Debug
    global __bundlePath
    global __pluginModule
    global __logFilePath
    global __requestHandlers
    global LastPrefix

    FirstRun = False
    random.seed()

    # Set up the support file paths
    pmsPath = "%s/Library/Application Support/Plex Media Server" % os.environ[
        "HOME"]
    supportFilesPath = "%s/Plug-in Support" % pmsPath
    frameworkSupportFilesPath = "%s/Framework Support" % pmsPath
    logFilesPath = "%s/Library/Logs/PMS Plugin Logs" % os.environ["HOME"]

    # Make sure framework directories exist
    def checkpath(path):
        try:
            if not os.path.exists(path): os.makedirs(path)
        except:
            pass

    checkpath("%s/Preferences" % supportFilesPath)
    checkpath("%s/Databases" % supportFilesPath)
    checkpath(logFilesPath)
    checkpath(frameworkSupportFilesPath)

    # Set the bundle path
    __bundlePath = _bundlePath.rstrip('/')

    # Add the bundle path to the system path, including any libraries
    if os.path.isdir("%s/Contents" % __bundlePath):
        sys.path.append("%s/Contents" % __bundlePath)
        if os.path.isdir("%s/Contents/Libraries" % __bundlePath):
            sys.path.append("%s/Contents/Libraries" % __bundlePath)
    else:
        print "Couldn't find bundle directory"
        return None

    # Open the Info.plist file
    f = open("%s/Contents/Info.plist" % __bundlePath, "r")
    infoplist = XML.ElementFromString(f.read())
    f.close()
    if infoplist is None:
        print "Couldn't load Info.plist file from plug-in"
        return

    # Get the plug-in identifier
    Identifier = infoplist.xpath(
        '//key[text()="CFBundleIdentifier"]//following-sibling::string/text()'
    )[0]
    if Identifier is None:
        print "Invalid Info.plist file in plug-in"
        return None

    # Set up the log file
    __logFilePath = "%s/%s.log" % (logFilesPath, Identifier)
    if os.path.exists(__logFilePath):
        if os.path.exists("%s.old" % __logFilePath):
            os.remove("%s.old" % __logFilePath)
        os.rename(__logFilePath, "%s.old" % __logFilePath)

    # Now we can start logging
    PMS.Log("(Framework) Bundle verification complete", False)

    # Check whether debugging is enabled
    try:
        _debug = infoplist.xpath(
            '//key[text()="PlexPluginDebug"]//following-sibling::string/text()'
        )[0]
        if _debug == "1":
            Debug = True
            PMS.Log("(Framework) Debugging is enabled")
    except:
        pass

    # Log the system encoding (set during bootstrap)
    PMS.Log("(Framework) Default encoding is " + sys.getdefaultencoding())

    # Set up framework paths
    Prefs.__prefsPath = "%s/Preferences/%s.xml" % (supportFilesPath,
                                                   Identifier)
    Data.__dataPath = "%s/Data/%s" % (supportFilesPath, Identifier)
    Data.__dataItemPath = "%s/DataItems" % Data.__dataPath
    if not os.path.isdir(Data.__dataItemPath):
        FirstRun = True
        os.makedirs(Data.__dataItemPath)
    Resource.__resourcePath = "%s/Contents/Resources" % __bundlePath
    Helper.__helperPath = "%s/Contents/Helpers" % __bundlePath
    Resource.__sharedResourcePath = "%s/Plug-ins/Framework.bundle/Contents/Resources/Versions/1/Resources" % pmsPath
    Database.__databasePath = "%s/Databases/%s.db" % (supportFilesPath,
                                                      Identifier)
    os.chdir(Data.__dataItemPath)
    Locale.SetDefaultLocale()
    PMS.Log("(Framework) Configured framework modules")

    # Attempt to import the plug-in module - if debugging is enabled, don't catch exceptions
    if Debug:
        import Code as _plugin
        PMS.Log("(Framework) Imported plug-in module")
    else:
        try:
            import Code as _plugin
            PMS.Log("(Framework) Imported plug-in module")
        except ImportError:
            PMS.Log("(Framework) Couldn't import plug-in from bundle")
            __exit()
            return

    # Load the list of trusted plug-ins
    _trusted = []
    try:
        _trustedJSON = Resource.LoadShared("trust.json")
        if _trustedJSON:
            _trusted = JSON.ObjectFromString(_trustedJSON)
    except:
        pass

    # Populate the permission lists
    __setupPermissionLists()

    # Register the plug-in with the framework
    __pluginModule = _plugin

    # Check the imported module to make sure nothing untoward is happening!
    if Identifier in _trusted:
        PMS.Log("(Framework) Plug-in is trusted, skipping module check")
    else:
        __scanModules()
        _allowed = []
        for n in PMS.__dict__:
            if n[0] != "_":
                if type(PMS.__dict__[n]).__name__ == "module":
                    _allowed.append(n)
        for n in __modWhitelist:
            _allowed.append(n)
        __checkModule(_plugin, _allowed)
        PMS.Log("(Framework) Checked module imports")

    # Initialize the framework modules
    Dict.__load()
    if not FirstRun:
        __checkFrameworkCompatibility()
    Prefs.__load()
    HTTP.__loadCookieJar()
    HTTP.__loadCache()
    PMS.Log("(Framework) Initialized framework modules")

    # Call the plug-in's Start method
    PMS.Log("(Framework) Attempting to start the plug-in...")
    __call(__pluginModule.Start)
    PMS.Log("(Framework) Plug-in started", False)

    # Start timers
    __startCacheManager(firstRun=FirstRun)

    PMS.Log("(Framework) Entering run loop")
    # Enter a run loop to handle requests
    while True:
        try:
            # Read the input
            path = raw_input()
            path = path.lstrip("GET ").strip()
            LastPrefix = None

            # Read headers
            headers = {}
            stop = False
            while stop == False:
                line = raw_input()
                if len(line) == 1:
                    stop = True
                else:
                    split = string.split(line.strip(), ":", maxsplit=1)
                    if len(split) == 2:
                        headers[split[0].strip()] = split[1].strip()

            # Set the locale
            if headers.has_key("X-Plex-Language"):
                loc = headers["X-Plex-Language"].lower()
                Locale.__loadLocale(loc)

            # Set the version
            if headers.has_key("X-Plex-Version"):
                Client.__setVersion(headers["X-Plex-Version"])

            # Extract arguments
            kwargs = {}
            mpath = path
            if path.find("?") >= 0:
                parts = path.split("?")
                mpath = parts[0]
                args = parts[1].split("&")
                for arg in args:
                    kwarg = arg.split("=")
                    if len(kwarg) == 2:
                        name = urllib.unquote(kwarg[0])
                        value = urllib.unquote(kwarg[1])
                        kwargs[name] = value
            if mpath[-1] == "/":
                mpath = mpath[:-1]

            # Split the path into components and decode.
            pathNouns = path.split('/')
            pathNouns = [urllib.unquote(p) for p in pathNouns]

            # If no input was given, return an error
            if len(pathNouns) <= 1:
                __return("%s\r\n\r\n" % PMS.Error['BadRequest'])

            # Otherwise, attempt to handle the request
            else:
                result = None
                pathNouns.pop(0)
                count = len(pathNouns)
                if pathNouns[-1] == "":
                    pathNouns.pop(len(pathNouns) - 1)
                PMS.Log("(Framework) Handling request :  %s" % path, False)

                # Check for a management request
                if pathNouns[0] == ":":
                    result = __handlePMSRequest(pathNouns, path, **kwargs)

                else:
                    handler = None
                    isPrefixHandler = False

                    # See if there's a prefix handler available
                    for key in __prefixHandlers:
                        if mpath.count(key, 0, len(key)) == 1:
                            LastPrefix = key
                    if mpath in __prefixHandlers:
                        handler = __prefixHandlers[mpath]["handler"]
                        isPrefixHandler = True

                    else:
                        # Check each request handler to see if it handles the current prefix
                        popped = False
                        for key in __requestHandlers:
                            if handler is None:
                                if path.count(key, 0, len(key)) == 1:
                                    # Remove the prefix from the path
                                    keyNounCount = len(key.split('/')) - 1
                                    for i in range(keyNounCount):
                                        pathNouns.pop(0)
                                    count = count - keyNounCount
                                    # Find the request handler
                                    handler = __requestHandlers[key]["handler"]
                                    LastPrefix = key
                                    popped = True

                        # If no path request handler was found, make sure we still pop the prefix so internal requests work
                        for key in __prefixHandlers:
                            if popped == False:
                                if mpath.count(key, 0, len(key)) == 1:
                                    keyNounCount = len(key.split('/')) - 1
                                    for i in range(keyNounCount):
                                        pathNouns.pop(0)
                                    popped = True

                    # Check whether we should handle the request internally
                    handled = False
                    if count > 0:
                        if pathNouns[0] == ":":
                            handled = True
                            result = __handleInternalRequest(
                                pathNouns, path, **kwargs)

                    # Check if the App Store has flagged the plug-in as broken
                    if os.path.exists(
                            os.path.join(frameworkSupportFilesPath,
                                         "%s.broken" % Identifier)):
                        #TODO: Localise this bit, use message from the App Store if available
                        handled = True
                        result = PMS.Objects.MessageContainer(
                            "Please try again later",
                            "This plug-in is currently unavailable")
                        PMS.Log("(Framework) Plug-in is flagged as broken")

                    # If the request hasn't been handled, and we have a valid request handler, call it
                    else:
                        if not handled and handler is not None:
                            if isPrefixHandler:
                                result = handler(**kwargs)
                            else:
                                result = handler(pathNouns, path, **kwargs)

                # If the request wasn't handled, return an error
                if result == None:
                    PMS.Log("(Framework) Request not handled by plug-in",
                            False)
                    response = "%s\r\n\r\n" % PMS.Error['NotFound']

                # If the plugin returned an error, return it to PMS
                elif result in PMS.Error.values():
                    PMS.Log(
                        "(Framework) Plug-in returned an error :  %s" % result,
                        False)
                    response = "%s\r\n" % result

                # Otherwise, check if a valid object was returned, and return the result
                elif __objectManager.ObjectHasBase(result, Objects.Object):
                    PMS.Log("(Framework) Response OK")
                    resultStr = result.Content()
                    resultStatus = result.Status()
                    resultHeaders = result.Headers()
                    if resultStr is not None:
                        resultLen = len(resultStr)
                        if resultLen > 0:
                            resultHeaders += "Content-Length: %i\r\n" % resultLen
                        resultStr = "\r\n%s" % resultStr
                    else:
                        resultStr = ""
                    response = str("%s\r\n%s" %
                                   (resultStatus, resultHeaders)) + str(
                                       resultStr) + str("\r\n")

                __return(response)

        # If a KeyboardInterrupt (SIGINT) is raised, stop the plugin
        except KeyboardInterrupt:
            # Save data & exit
            __saveData()
            __exit()

        except EOFError:
            # Save data & exit
            __saveData()
            __exit()

        # If another exception is raised, deal with the problem
        except:
            __except()
            __return("%s\r\n\r\n" % PMS.Error['InternalError'])

        # Make sure the plugin's data is saved
        finally:
            __saveData()
예제 #19
0
 def ConnectRoute_inner(f):
   if f.__name__ not in controllers:
     controllers[f.__name__] = f
   routemap.connect(None, path, controller=f.__name__, action=action, **kwargs)
   PMS.Log("(Framework) Created a new route: %s => %s" % (path, f.__name__))
   return f
예제 #20
0
파일: HTTP.py 프로젝트: toxictigga/wdmcgen2
def SetTimeout(timeout):
    socket.setdefaulttimeout(timeout)
    PMS.Log("(Framework) Set the default socket timeout to %.1f seconds" %
            timeout)
예제 #21
0
def Request(url,
            values=None,
            headers={},
            cacheTime=None,
            autoUpdate=False,
            encoding=None,
            errors=None,
            addToLog=True):
    global __cache
    global __saveScheduled
    now = Datetime.Now()

    # If no cache time is given, use the default
    if cacheTime is None:
        cacheTime = __cacheTime

    # Attempt to return a cached copy, fetching again if an exception occurs
    try:
        # Make sure we don't cache POST requests
        if values == None and cacheTime > 0:
            if __cache.has_key(url):
                cachedAt = __cache[url]["CheckTime"]
                expiresAt = cachedAt + Datetime.Delta(seconds=cacheTime)
                if Datetime.Now() < expiresAt:
                    if addToLog:
                        PMS.Log(
                            "(Framework) Loaded %s from the cache (expires at %s)"
                            % (url, expiresAt))
                    return __cache[url]["Content"]
    except:
        if addToLog:
            PMS.Log(
                "(Framework) Couldn't load %s from the cache, attempting to fetch again."
            )

    # Try to fetch the page from the server
    try:
        # Encode the values
        data = None
        if values is not None: data = urllib.urlencode(values)
        h = __headers.copy()
        for header in headers:
            h[header] = headers[header]
        request = urllib2.Request(url, data, h)
        f = urllib2.urlopen(request)
        response = f.read()

        # If the response is gzipped, unzip it
        if f.headers.get('Content-Encoding') == "gzip":
            if addToLog:
                PMS.Log("(Framework) Received gzipped response from %s" % url)
            stream = StringIO.StringIO(response)
            gzipper = gzip.GzipFile(fileobj=stream)
            response = gzipper.read()
        else:
            if addToLog: PMS.Log("(Framework) Received response from %s" % url)

        # Try to decode the response if manually specified
        try:
            if not (encoding is None and errors is None):
                if encoding is None: encoding = "utf8"
                if errors is None: errors = "strict"
                response = str(
                    response.decode(encoding, errors).encode("utf8", errors))
        except:
            if addToLog:
                PMS.Log(
                    "(Framework) Unable to decode response from '%s' with codec %s"
                    % (url, encoding))

    # Handle common errors
    except urllib2.HTTPError:
        PMS.Log("(Framework) HTTPError when requesting '%s'" % url)
        return None
    except urllib2.URLError:
        PMS.Log("(Framework) URLError when requesting '%s'" % url)
        return None

    Thread.Lock("Framework.HTTPCache", addToLog=False)
    try:
        # Cache the data if required
        if response is not None and cacheTime > 0:
            item = {}
            item["Content"] = response
            item["CheckTime"] = Datetime.Now()
            if autoUpdate:
                item["UpdateTime"] = Datetime.Now() + Datetime.Delta(
                    seconds=cacheTime)
                item["CacheTime"] = cacheTime
                item["Headers"] = headers
                item["Encoding"] = encoding
                item["Errors"] = errors
            __cache[url] = item
            if addToLog: PMS.Log("(Framework) Cached response from %s" % url)

        if not __saveScheduled:
            Thread.CreateTimer(5, __save)
            __saveScheduled = True
    finally:
        Thread.Unlock("Framework.HTTPCache", addToLog=False)

    # Return the data
    return response
예제 #22
0
def __startTimedThread(function, *args, **kwargs):
    if function.__name__[0] != "_":
        PMS.Log(
            "(Framework) Started a new thread named '%s' after a timed interval"
            % function.__name__)
    function(*args, **kwargs)