# -*- coding: utf-8 -*- """ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . @author: mkaay, RaNaN """ import re import sys from os import listdir, makedirs from os.path import isfile, join, exists, abspath from sys import version_info from itertools import chain from traceback import print_exc try: from ast import literal_eval except ImportError: # python 2.5 from module.lib.SafeEval import safe_eval as literal_eval from module.ConfigParser import IGNORE NO_AUTOLOAD = ("XMPPInterface", "MultiHome", "Ev0InFetcher") class PluginManager(): def __init__(self, core): self.core = core #self.config = self.core.config self.log = core.log self.crypterPlugins = {} self.containerPlugins = {} self.hosterPlugins = {} self.captchaPlugins = {} self.accountPlugins = {} self.hookPlugins = {} self.plugins = {"crypter": self.crypterPlugins, "container": self.containerPlugins, "hoster": self.hosterPlugins, "captcha": self.captchaPlugins, "accounts": self.accountPlugins, "hooks": self.hookPlugins} self.createIndex() def createIndex(self): """create information for all plugins available""" sys.path.append(abspath("")) if not exists("userplugins"): makedirs("userplugins") if not exists(join("userplugins", "__init__.py")): f = open(join("userplugins", "__init__.py"), "wb") f.close() self.rePattern = re.compile(r'__pattern__.*=.*r("|\')([^"\']+)') self.reVersion = re.compile(r'__version__.*=.*("|\')([0-9.]+)') self.reConfig = re.compile(r'__config__.*=.*\[([^\]]+)', re.MULTILINE) self.crypterPlugins = self.parse(_("Crypter"), "crypter", pattern=True) self.containerPlugins = self.parse(_("Container"), "container", pattern=True) self.hosterPlugins = self.parse(_("Hoster"), "hoster", pattern=True) self.captchaPlugins = self.parse(_("Captcha"), "captcha") self.accountPlugins = self.parse(_("Account"), "accounts", create=True) self.hookPlugins = self.parse(_("Hook"), "hooks") self.log.debug("created index of plugins") def parse(self, typ, folder, create=False, pattern=False, home={}): """ returns dict with information home contains parsed plugins from module. { name : {path, version, config, (pattern, re), (plugin, class)} } """ plugins = {} if home: pfolder = join("userplugins", folder) if not exists(pfolder): makedirs(pfolder) if not exists(join(pfolder, "__init__.py")): f = open(join(pfolder, "__init__.py"), "wb") f.close() else: pfolder = join(pypath, "module", "plugins", folder) for f in listdir(pfolder): if (isfile(join(pfolder, f)) and f.endswith(".py") or f.endswith("_25.pyc") or f.endswith( "_26.pyc") or f.endswith("_27.pyc")) and not f.startswith("_"): data = open(join(pfolder, f)) content = data.read() data.close() if f.endswith("_25.pyc") and not version_info[0:2] == (2, 5): continue elif f.endswith("_26.pyc") and not version_info[0:2] == (2, 6): continue elif f.endswith("_27.pyc") and not version_info[0:2] == (2, 7): continue name = f[:-3] if name[-1] == ".": name = name[:-4] version = self.reVersion.findall(content) if version: version = float(version[0][1]) else: version = 0 if home and home.has_key(name): if home[name]["v"] >= version: continue plugins[name] = {} plugins[name]["v"] = version module = f.replace(".pyc", "").replace(".py", "") if home: if name in IGNORE: del plugins[name] continue path = "userplugins.%s.%s" % (folder, module) else: path = "module.plugins.%s.%s" % (folder, module) plugins[name]["name"] = module plugins[name]["path"] = path if pattern: pattern = self.rePattern.findall(content) if pattern: pattern = pattern[0][1] else: pattern = "^unmachtable$" plugins[name]["pattern"] = pattern try: plugins[name]["re"] = re.compile(pattern) except: self.log.error(_("%s has a invalid pattern.") % name) config = self.reConfig.findall(content) if config: config = literal_eval(config[0].strip().replace("\n", "").replace("\r", "")) if type(config[0]) == tuple: config = [list(x) for x in config] else: config = [list(config)] if folder == "hooks": config.append(["load", "bool", "Load on startup", True if name not in NO_AUTOLOAD else False]) for item in config: self.core.config.addPluginConfig([name] + item) if not home: temp = self.parse(typ, folder, create, pattern, plugins) plugins.update(temp) return plugins def parseUrls(self, urls): """parse plugins for given list of urls""" last = None res = [] # tupels of (url, plugin) for url in urls: if type(url) not in (str, unicode, buffer): continue found = False if last and last[1]["re"].match(url): res.append((url, last[0])) continue for name, value in chain(self.crypterPlugins.iteritems(), self.hosterPlugins.iteritems(), self.containerPlugins.iteritems()): if value["re"].match(url): res.append((url, name)) last = (name, value) found = True break if not found: res.append((url, "BasePlugin")) return res def getPlugin(self, name, original=False): """return plugin module from hoster|decrypter|container""" plugin = None if self.containerPlugins.has_key(name): plugin = self.containerPlugins[name] if self.crypterPlugins.has_key(name): plugin = self.crypterPlugins[name] if self.hosterPlugins.has_key(name): plugin = self.hosterPlugins[name] if plugin.has_key("new_module") and not original: return plugin["new_module"] if plugin.has_key("module"): return plugin["module"] plugin["module"] = __import__(plugin["path"], globals(), locals(), [plugin["name"]], -1) return plugin["module"] def getPluginName(self, name): """ used to obtain new name if other plugin was injected""" plugin = None if self.containerPlugins.has_key(name): plugin = self.containerPlugins[name] if self.crypterPlugins.has_key(name): plugin = self.crypterPlugins[name] if self.hosterPlugins.has_key(name): plugin = self.hosterPlugins[name] if plugin.has_key("new_name"): return plugin["new_name"] return plugin["name"] def getCaptchaPlugin(self, name): """return captcha modul if existent""" if self.captchaPlugins.has_key(name): plugin = self.captchaPlugins[name] if plugin.has_key("class"): return plugin["class"] module = __import__(plugin["path"], globals(), locals(), [plugin["name"]], -1) plugin["class"] = getattr(module, name) return plugin["class"] return None def getAccountPlugin(self, name): """return account class if existent""" if self.accountPlugins.has_key(name): plugin = self.accountPlugins[name] if plugin.has_key("class"): return plugin["class"] module = __import__(plugin["path"], globals(), locals(), [plugin["name"]], -1) plugin["class"] = getattr(module, plugin["name"]) return plugin["class"] return None def getAccountPlugins(self): """return list of account plugin names""" res = [] for name in self.accountPlugins.keys(): res.append(name) return res def getHookPlugins(self): """return list of hook classes""" classes = [] for name, value in self.hookPlugins.iteritems(): if value.has_key("class"): classes.append(value["class"]) continue try: if not self.core.config.getPlugin(name, "load"): continue except: if self.core.debug: print_exc() self.log.debug("Failed to load %s" % name) continue try: module = __import__(value["path"], globals(), locals(), [value["name"]], -1) pluginClass = getattr(module, name) except Exception, e: self.log.error(_("Error importing %(name)s: %(msg)s") % {"name": name, "msg": str(e)}) self.log.error(_("You should fix dependicies or deactivate load on startup.")) if self.core.debug: print_exc() continue value["class"] = pluginClass classes.append(pluginClass) return classes def reloadPlugins(self): """ reloads and reindexes plugins """ pass if __name__ == "__main__": _ = lambda x: x pypath = "/home/christian/Projekte/pyload-0.4/module/plugins" from time import time p = PluginManager(None) a = time() test = ["http://www.youtube.com/watch?v=%s" % x for x in range(0, 100)] print p.parseUrls(test) b = time() print b - a, "s"