From 81508f295cffc40c479fe72f24bdf1dbbedf5d92 Mon Sep 17 00:00:00 2001 From: mkaay Date: Wed, 5 May 2010 23:03:43 +0200 Subject: refactored plugins, new plugin manager --- module/DownloadThread.py | 4 +- module/FileList.py | 23 +- module/HookManager.py | 19 +- module/PluginManager.py | 99 ++++++++ module/ThreadManager.py | 4 +- module/XMLConfigParser.py | 18 +- module/config/core_default.xml | 57 +++++ module/network/MultipartPostHandler.py | 139 +++++++++++ module/plugins/Container.py | 29 +++ module/plugins/Crypter.py | 28 +++ module/plugins/Hook.py | 16 +- module/plugins/Hoster.py | 29 +++ module/plugins/Plugin.py | 29 ++- module/plugins/container/CCF.py | 21 +- module/plugins/container/LinkList.py | 21 +- module/plugins/container/RSDF.py | 21 +- module/plugins/crypter/DDLMusicOrg.py | 56 +++++ module/plugins/crypter/FourChanOrg.py | 39 ++++ module/plugins/crypter/HoerbuchIn.py | 46 ++++ module/plugins/crypter/LixIn.py | 34 +++ module/plugins/crypter/OneKhDe.py | 36 +++ module/plugins/crypter/RSLayerCom.py | 37 +++ module/plugins/crypter/RelinkUs.py | 58 +++++ module/plugins/crypter/SecuredIn.py | 334 ++++++++++++++++++++++++++ module/plugins/crypter/SerienjunkiesOrg.py | 217 +++++++++++++++++ module/plugins/crypter/StealthTo.py | 45 ++++ module/plugins/crypter/YoutubeChannel.py | 52 +++++ module/plugins/crypter/__init__.py | 0 module/plugins/decrypter/DDLMusicOrg.py | 58 ----- module/plugins/decrypter/FourChanOrg.py | 41 ---- module/plugins/decrypter/HoerbuchIn.py | 48 ---- module/plugins/decrypter/LixIn.py | 36 --- module/plugins/decrypter/OneKhDe.py | 38 --- module/plugins/decrypter/RSLayerCom.py | 39 ---- module/plugins/decrypter/RelinkUs.py | 60 ----- module/plugins/decrypter/SecuredIn.py | 335 --------------------------- module/plugins/decrypter/SerienjunkiesOrg.py | 217 ----------------- module/plugins/decrypter/StealthTo.py | 47 ---- module/plugins/decrypter/YoutubeChannel.py | 54 ----- module/plugins/decrypter/__init__.py | 0 module/plugins/hooks/ClickAndLoad.py | 14 +- module/plugins/hooks/ContainerDownload.py | 14 +- module/plugins/hooks/ExternalScripts.py | 14 +- module/plugins/hooks/LinuxFileEvents.py | 11 +- module/plugins/hoster/DepositfilesCom.py | 22 +- module/plugins/hoster/DuckloadCom.py | 22 +- module/plugins/hoster/FilefactoryCom.py | 22 +- module/plugins/hoster/FilesmonsterCom.py | 24 +- module/plugins/hoster/FreakshareNet.py | 22 +- module/plugins/hoster/GigasizeCom.py | 22 +- module/plugins/hoster/HotfileCom.py | 22 +- module/plugins/hoster/MegauploadCom.py | 22 +- module/plugins/hoster/MegavideoCom.py | 23 +- module/plugins/hoster/MyvideoDe.py | 23 +- module/plugins/hoster/NetloadIn.py | 22 +- module/plugins/hoster/RapidshareCom.py | 22 +- module/plugins/hoster/ShareonlineBiz.py | 22 +- module/plugins/hoster/ShragleCom.py | 22 +- module/plugins/hoster/StorageTo.py | 21 +- module/plugins/hoster/UploadedTo.py | 22 +- module/plugins/hoster/XupIn.py | 22 +- module/plugins/hoster/YoupornCom.py | 22 +- module/plugins/hoster/YoutubeCom.py | 22 +- module/plugins/hoster/ZippyshareCom.py | 22 +- module/plugins/hoster/ZshareNet.py | 22 +- 65 files changed, 1646 insertions(+), 1356 deletions(-) create mode 100644 module/PluginManager.py create mode 100644 module/network/MultipartPostHandler.py create mode 100644 module/plugins/Container.py create mode 100644 module/plugins/Crypter.py create mode 100644 module/plugins/Hoster.py create mode 100644 module/plugins/crypter/DDLMusicOrg.py create mode 100644 module/plugins/crypter/FourChanOrg.py create mode 100644 module/plugins/crypter/HoerbuchIn.py create mode 100644 module/plugins/crypter/LixIn.py create mode 100644 module/plugins/crypter/OneKhDe.py create mode 100644 module/plugins/crypter/RSLayerCom.py create mode 100644 module/plugins/crypter/RelinkUs.py create mode 100644 module/plugins/crypter/SecuredIn.py create mode 100644 module/plugins/crypter/SerienjunkiesOrg.py create mode 100644 module/plugins/crypter/StealthTo.py create mode 100644 module/plugins/crypter/YoutubeChannel.py create mode 100644 module/plugins/crypter/__init__.py delete mode 100644 module/plugins/decrypter/DDLMusicOrg.py delete mode 100644 module/plugins/decrypter/FourChanOrg.py delete mode 100644 module/plugins/decrypter/HoerbuchIn.py delete mode 100644 module/plugins/decrypter/LixIn.py delete mode 100644 module/plugins/decrypter/OneKhDe.py delete mode 100644 module/plugins/decrypter/RSLayerCom.py delete mode 100644 module/plugins/decrypter/RelinkUs.py delete mode 100644 module/plugins/decrypter/SecuredIn.py delete mode 100644 module/plugins/decrypter/SerienjunkiesOrg.py delete mode 100644 module/plugins/decrypter/StealthTo.py delete mode 100644 module/plugins/decrypter/YoutubeChannel.py delete mode 100644 module/plugins/decrypter/__init__.py (limited to 'module') diff --git a/module/DownloadThread.py b/module/DownloadThread.py index 3cfaed780..fe371ceba 100644 --- a/module/DownloadThread.py +++ b/module/DownloadThread.py @@ -39,7 +39,7 @@ class Status(object): self.url = None self.exists = False self.waituntil = 0 - self.plugin = pyfile.modul.__name__ + self.plugin = pyfile.plugin.__name__ self.want_reconnect = False self.error = "" @@ -130,7 +130,7 @@ class DownloadThread(Thread): pyfile.plugin.req.set_timeout(self.parent.parent.config['general']['max_download_time']) - if pyfile.plugin.props["type"] == "container": + if pyfile.plugin.__type__ == "container": status.type = "decrypting" else: status.type = "downloading" diff --git a/module/FileList.py b/module/FileList.py index 665e4bec5..b785af6de 100644 --- a/module/FileList.py +++ b/module/FileList.py @@ -119,8 +119,8 @@ class FileList(object): for thread_list only, returns all elements that are suitable for downloadthread """ files = [] - files += [[x for x in p.files if x.status.type == None and x.plugin.props['type'] == "container" and not x.active] for p in self.data["queue"] + self.data["packages"]] - files += [[x for x in p.files if (x.status.type == None or x.status.type == "reconnected") and not x.active and not x.modul.__name__ in occ] for p in self.data["queue"]] + files += [[x for x in p.files if x.status.type == None and x.plugin.__type__ == "container" and not x.active] for p in self.data["queue"] + self.data["packages"]] + files += [[x for x in p.files if (x.status.type == None or x.status.type == "reconnected") and not x.active and not x.plugin.__name__ in occ] for p in self.data["queue"]] return reduce(concat, files, []) @@ -148,7 +148,7 @@ class FileList(object): info["status_error"] = pyfile.status.error info["size"] = pyfile.status.size() info["active"] = pyfile.active - info["plugin"] = pyfile.plugin.props['name'] + info["plugin"] = pyfile.plugin.__name__ try: info["package"] = pypack.data["id"] except: @@ -422,25 +422,10 @@ class PyLoadFile(): def init(self): self.active = False - pluginName = self._get_my_plugin() - if pluginName: - for dir in ["hoster", "decrypter", "container"]: - try: - self.modul = __import__("%s.%s" % (dir, pluginName), globals(), locals(), [pluginName], -1) - except ImportError: - pass - pluginClass = getattr(self.modul, pluginName) - else: - self.modul = module.plugins.Plugin - pluginClass = module.plugins.Plugin.Plugin + pluginClass = self.core.pluginManager.getPluginFromPattern(self.url) self.plugin = pluginClass(self) self.status = Status(self) self.status.filename = self.url - - def _get_my_plugin(self): - for plugin, plugin_pattern in self.core.plugins_avaible.items(): - if re.match(plugin_pattern, self.url) != None: - return plugin def init_download(self): if self.core.config['proxy']['activated']: diff --git a/module/HookManager.py b/module/HookManager.py index fa6df3323..d37c904a9 100644 --- a/module/HookManager.py +++ b/module/HookManager.py @@ -17,10 +17,8 @@ @author: mkaay @interface-version: 0.1 """ -from glob import glob + import logging -from os.path import basename -from os.path import join from threading import Lock from module.XMLConfigParser import XMLConfigParser @@ -28,9 +26,9 @@ from module.XMLConfigParser import XMLConfigParser class HookManager(): def __init__(self, core): self.core = core - self.configParser = XMLConfigParser(join(core.path, "module", "config", "plugin.xml")) + self.configParser = self.core.parser_plugins self.configParser.loadData() - self.config = self.configParser.getConfig() + self.config = self.configParser.getConfig() self.logger = logging.getLogger("log") self.plugins = [] self.lock = Lock() @@ -39,19 +37,20 @@ class HookManager(): def createIndex(self): self.lock.acquire() - pluginFiles = glob(join(self.core.plugin_folder, "hooks", "*.py")) plugins = [] - for pluginFile in pluginFiles: - pluginName = basename(pluginFile).replace(".py", "") - if pluginName == "__init__": + pluginStr = self.core.config["plugins"]["load_hook_plugins"] + for pluginModule in pluginStr.split(","): + pluginModule = pluginModule.strip() + if not pluginModule: continue + pluginName = pluginModule.split(".")[-1] if pluginName in self.config.keys(): if not self.config[pluginName]["activated"]: self.logger.info("Deactivated %s" % pluginName) continue else: self.configParser.set(pluginName, {"option": "activated", "type": "bool", "name": "Activated"}, True) - module = __import__("module.plugins.hooks." + pluginName, globals(), locals(), [pluginName], -1) + module = __import__(pluginModule, globals(), locals(), [pluginName], -1) pluginClass = getattr(module, pluginName) try: plugin = pluginClass(self.core) diff --git a/module/PluginManager.py b/module/PluginManager.py new file mode 100644 index 000000000..f4a3ee8ee --- /dev/null +++ b/module/PluginManager.py @@ -0,0 +1,99 @@ +# -*- 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 + @interface-version: 0.1 +""" + +import logging +import re +from threading import Lock + +from module.XMLConfigParser import XMLConfigParser +from module.plugins.Hoster import Hoster + +from sys import version_info + +class PluginManager(): + def __init__(self, core): + self.core = core + self.configParser = self.core.xmlconfig + self.configParser.loadData() + self.config = self.configParser.getConfig() + self.logger = logging.getLogger("log") + self.crypterPlugins = [] + self.containerPlugins = [] + self.hosterPlugins = [] + self.captchaPlugins = [] + self.accountPlugins = [] + self.lock = Lock() + self.createIndex() + + def createIndex(self): + self.lock.acquire() + + self.crypterPlugins = self.parse(self.core.config["plugins"]["load_crypter_plugins"], _("Crypter")) + self.containerPlugins = self.parse(self.core.config["plugins"]["load_container_plugins"], _("Container")) + self.hosterPlugins = self.parse(self.core.config["plugins"]["load_hoster_plugins"], _("Hoster")) + self.captchaPlugins = self.parse(self.core.config["plugins"]["load_captcha_plugins"], _("Captcha")) + #self.accountPlugins = self.parse(self.core.config["plugins"]["load_account_plugins"], _("Account")) + + self.lock.release() + self.logger.info(_("created index of plugins")) + + def parse(self, pluginStr, ptype): + plugins = [] + for pluginModule in pluginStr.split(","): + pluginModule = pluginModule.strip() + if not pluginModule: + continue + pluginName = pluginModule.split(".")[-1] + if pluginName.endswith("_25") and not version_info == (2, 5): + continue + elif pluginName.endswith("_26") and not version_info == (2, 6): + continue + module = __import__(pluginModule, globals(), locals(), [pluginName], -1) + pluginClass = getattr(module, pluginName) + try: + plugins.append(pluginClass) + self.logger.debug(_("%(type)s: %(name)s added") % {"name":pluginName, "type":ptype}) + except: + pass + return plugins + + def getPluginFromPattern(self, urlPattern): + plugins = [] + plugins.extend(self.crypterPlugins) + plugins.extend(self.containerPlugins) + plugins.extend(self.hosterPlugins) + for plugin in plugins: + if not plugin.__pattern__: + continue + if re.match(plugin.__pattern__, urlPattern): + return plugin + return Hoster + + def getCaptchaPlugin(self, name): + for plugin in self.captchaPlugins: + if plugin.__name__ == name: + return plugin + return None + + def getAccountPlugin(self, name): # not implemeted yet! + for plugin in self.accountPlugins: + if plugin.__name__ == name: + return plugin + return None diff --git a/module/ThreadManager.py b/module/ThreadManager.py index be4fc46d2..bf632b180 100644 --- a/module/ThreadManager.py +++ b/module/ThreadManager.py @@ -89,7 +89,7 @@ class ThreadManager(Thread): if not pyfile.plugin.multi_dl: self.occ_plugins.append(pyfile.modul.__name__) pyfile.active = True - if pyfile.plugin.props['type'] == "container": + if pyfile.plugin.__type__ == "container": self.parent.logger.info(_("Get links from: %s") % pyfile.url) else: self.parent.logger.info(_("Download starts: %s") % pyfile.url) @@ -122,7 +122,7 @@ class ThreadManager(Thread): self.py_downloading.remove(pyfile) if pyfile.status.type == "finished": - if pyfile.plugin.props['type'] == "container": + if pyfile.plugin.__type__ == "container": newLinks = 0 if pyfile.plugin.links: if isinstance(pyfile.plugin.links, dict): diff --git a/module/XMLConfigParser.py b/module/XMLConfigParser.py index 575dbd219..b691ecb8e 100644 --- a/module/XMLConfigParser.py +++ b/module/XMLConfigParser.py @@ -21,7 +21,7 @@ from os.path import exists from xml.dom.minidom import parse import re -from shutil import copy +from shutil import copy, move class XMLConfigParser(): def __init__(self, data, forceDefault=False, defaultFile=None): @@ -54,8 +54,12 @@ class XMLConfigParser(): with open(file, 'r') as fh: self.xml = parse(fh) if not self.xml.documentElement.getAttribute("version") == self.version: - print "Cant Update %s" % self.file - exit() #ok? + print _("Cant Update %s, your config version is outdated") % self.file + i = raw_input(_("backup old file and copy new one? [%s]/%s") % (_("yes")[0], _("no")[0])) + if i == "" or i == _("yes")[0]: + move(self.file, self.file.replace(".xml", "_backup.xml")) + self.loadData(self) + return self.root = self.xml.documentElement self._read_config() @@ -63,7 +67,7 @@ class XMLConfigParser(): try: copy(self.file_default, self.file) except: - print "%s not found" % self.file_default + print _("%s not found") % self.file_default exit() #ok? def saveData(self): @@ -215,7 +219,9 @@ class XMLConfigParser(): self.config[section] return True except: - return False + if self.forceDefault: + return False + return self.defaultParser.isValidSection(section) def checkInput(self, section, option, value): oinput = self.getInputValues(section, option) @@ -247,7 +253,7 @@ class Config(object): def __getitem__(self, key): if self.parser.isValidSection(key): return Section(self.parser, key) - raise Exception("invalid section") + raise Exception(_("invalid section")) def keys(self): return self.parser.config.keys() diff --git a/module/config/core_default.xml b/module/config/core_default.xml index e80892d46..4a0145bac 100644 --- a/module/config/core_default.xml +++ b/module/config/core_default.xml @@ -56,4 +56,61 @@ http://localhost:8080 http + + + module.plugins.hooks.ClickAndLoad, + module.plugins.hooks.ContainerDownload, + module.plugins.hooks.ExternalScripts, + + + module.plugins.captcha.GigasizeCom, + module.plugins.captcha.LinksaveIn, + module.plugins.captcha.MegauploadCom, + module.plugins.captcha.NetloadIn, + module.plugins.captcha.ShareonlineBiz, + + + module.plugins.container.CCF, + module.plugins.container.DLC_25, + module.plugins.container.DLC_26, + module.plugins.container.RSDF, + module.plugins.container.LinkList, + + + module.plugins.crypter.DDLMusicOrg, + module.plugins.crypter.FourChanOrg, + module.plugins.crypter.HoerbuchIn, + module.plugins.crypter.LixIn, + module.plugins.crypter.OneKhDe, + module.plugins.crypter.RelinkUs, + module.plugins.crypter.RSLayerCom, + module.plugins.crypter.SecuredIn, + module.plugins.crypter.SerienjunkiesOrg, + module.plugins.crypter.StealthTo, + module.plugins.crypter.YoutubeChannel, + + + module.plugins.hoster.DepositfilesCom, + module.plugins.hoster.DuckloadCom, + module.plugins.hoster.FilefactoryCom, + module.plugins.hoster.FilesmonsterCom, + module.plugins.hoster.FreakshareNet, + module.plugins.hoster.GigasizeCom, + module.plugins.hoster.HotfileCom, + module.plugins.hoster.MegauploadCom, + module.plugins.hoster.MegavideoCom, + module.plugins.hoster.MyvideoDe, + module.plugins.hoster.NetloadIn, + module.plugins.hoster.RapidshareCom, + module.plugins.hoster.ShareonlineBiz, + module.plugins.hoster.ShragleCom, + module.plugins.hoster.StorageTo, + module.plugins.hoster.UploadedTo, + module.plugins.hoster.XupIn, + module.plugins.hoster.YoupornCom, + module.plugins.hoster.YoutubeCom, + module.plugins.hoster.ZippyshareCom, + module.plugins.hoster.ZshareNet, + + diff --git a/module/network/MultipartPostHandler.py b/module/network/MultipartPostHandler.py new file mode 100644 index 000000000..6804bcc90 --- /dev/null +++ b/module/network/MultipartPostHandler.py @@ -0,0 +1,139 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +#### +# 02/2006 Will Holcomb +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# 7/26/07 Slightly modified by Brian Schneider +# in order to support unicode files ( multipart_encode function ) +""" +Usage: + Enables the use of multipart/form-data for posting forms + +Inspirations: + Upload files in python: + http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/146306 + urllib2_file: + Fabien Seisen: + +Example: + import MultipartPostHandler, urllib2, cookielib + + cookies = cookielib.CookieJar() + opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookies), + MultipartPostHandler.MultipartPostHandler) + params = { "username" : "bob", "password" : "riviera", + "file" : open("filename", "rb") } + opener.open("http://wwww.bobsite.com/upload/", params) + +Further Example: + The main function of this file is a sample which downloads a page and + then uploads it to the W3C validator. +""" + +import urllib +import urllib2 +import mimetools, mimetypes +import os, stat +from cStringIO import StringIO + +class Callable: + def __init__(self, anycallable): + self.__call__ = anycallable + +# Controls how sequences are uncoded. If true, elements may be given multiple values by +# assigning a sequence. +doseq = 1 + +class MultipartPostHandler(urllib2.BaseHandler): + handler_order = urllib2.HTTPHandler.handler_order - 10 # needs to run first + + def http_request(self, request): + data = request.get_data() + if data is not None and type(data) != str: + v_files = [] + v_vars = [] + try: + for(key, value) in data.items(): + if type(value) == file: + v_files.append((key, value)) + else: + v_vars.append((key, value)) + except TypeError: + systype, value, traceback = sys.exc_info() + raise TypeError, "not a valid non-string sequence or mapping object", traceback + + if len(v_files) == 0: + data = urllib.urlencode(v_vars, doseq) + else: + boundary, data = self.multipart_encode(v_vars, v_files) + + contenttype = 'multipart/form-data; boundary=%s' % boundary + if(request.has_header('Content-Type') + and request.get_header('Content-Type').find('multipart/form-data') != 0): + print "Replacing %s with %s" % (request.get_header('content-type'), 'multipart/form-data') + request.add_unredirected_header('Content-Type', contenttype) + + request.add_data(data) + + return request + + def multipart_encode(vars, files, boundary = None, buf = None): + if boundary is None: + boundary = mimetools.choose_boundary() + if buf is None: + buf = StringIO() + for(key, value) in vars: + buf.write('--%s\r\n' % boundary) + buf.write('Content-Disposition: form-data; name="%s"' % key) + buf.write('\r\n\r\n' + value + '\r\n') + for(key, fd) in files: + file_size = os.fstat(fd.fileno())[stat.ST_SIZE] + filename = fd.name.split('/')[-1] + contenttype = mimetypes.guess_type(filename)[0] or 'application/octet-stream' + buf.write('--%s\r\n' % boundary) + buf.write('Content-Disposition: form-data; name="%s"; filename="%s"\r\n' % (key, filename)) + buf.write('Content-Type: %s\r\n' % contenttype) + # buffer += 'Content-Length: %s\r\n' % file_size + fd.seek(0) + buf.write('\r\n' + fd.read() + '\r\n') + buf.write('--' + boundary + '--\r\n\r\n') + buf = buf.getvalue() + return boundary, buf + multipart_encode = Callable(multipart_encode) + + https_request = http_request + +def main(): + import tempfile, sys + + validatorURL = "http://validator.w3.org/check" + opener = urllib2.build_opener(MultipartPostHandler) + + def validateFile(url): + temp = tempfile.mkstemp(suffix=".html") + os.write(temp[0], opener.open(url).read()) + params = { "ss" : "0", # show source + "doctype" : "Inline", + "uploaded_file" : open(temp[1], "rb") } + print opener.open(validatorURL, params).read() + os.remove(temp[1]) + + if len(sys.argv[1:]) > 0: + for arg in sys.argv[1:]: + validateFile(arg) + else: + validateFile("http://www.google.com") + +if __name__=="__main__": + main() \ No newline at end of file diff --git a/module/plugins/Container.py b/module/plugins/Container.py new file mode 100644 index 000000000..2a7196f14 --- /dev/null +++ b/module/plugins/Container.py @@ -0,0 +1,29 @@ +# -*- 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 +""" + +from module.plugins.Plugin import Plugin + +class Container(Plugin): + __name__ = "Container" + __version__ = "0.1" + __pattern__ = None + __type__ = "container" + __description__ = """Base container plugin""" + __author_name__ = ("mkaay") + __author_mail__ = ("mkaay@mkaay.de") diff --git a/module/plugins/Crypter.py b/module/plugins/Crypter.py new file mode 100644 index 000000000..31ea43262 --- /dev/null +++ b/module/plugins/Crypter.py @@ -0,0 +1,28 @@ +# -*- 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 +""" + +from module.plugins.Plugin import Plugin + +class Crypter(Plugin): + __version__ = "0.1" + __pattern__ = None + __type__ = "container" + __description__ = """Base crypter plugin""" + __author_name__ = ("mkaay") + __author_mail__ = ("mkaay@mkaay.de") diff --git a/module/plugins/Hook.py b/module/plugins/Hook.py index 4a385c417..81188c147 100644 --- a/module/plugins/Hook.py +++ b/module/plugins/Hook.py @@ -22,22 +22,22 @@ import logging class Hook(): + __name__ = "Hook" + __version__ = "0.2" + __type__ = "hook" + __description__ = """interface for hook""" + __author_name__ = ("mkaay") + __author_mail__ = ("mkaay@mkaay.de") + def __init__(self, core): self.logger = logging.getLogger("log") self.configParser = core.parser_plugins self.config = {} - props = {} - props['name'] = "Hook" - props['version'] = "0.2" - props['description'] = """interface for hook""" - props['author_name'] = ("mkaay") - props['author_mail'] = ("mkaay@mkaay.de") - self.props = props self.core = core def readConfig(self): self.configParser.loadData() - section = self.props['name'] + section = self.__name__ try: self.config = self.configParser.getConfig()[section] except: diff --git a/module/plugins/Hoster.py b/module/plugins/Hoster.py new file mode 100644 index 000000000..0ed528924 --- /dev/null +++ b/module/plugins/Hoster.py @@ -0,0 +1,29 @@ +# -*- 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 +""" + +from module.plugins.Plugin import Plugin + +class Hoster(Plugin): + __name__ = "Hoster" + __version__ = "0.1" + __pattern__ = None + __type__ = "hoster" + __description__ = """Base hoster plugin""" + __author_name__ = ("mkaay") + __author_mail__ = ("mkaay@mkaay.de") diff --git a/module/plugins/Plugin.py b/module/plugins/Plugin.py index c4ac8ee12..107c4f0ca 100644 --- a/module/plugins/Plugin.py +++ b/module/plugins/Plugin.py @@ -32,19 +32,17 @@ from os import makedirs from module.DownloadThread import CaptchaError class Plugin(): - + __name__ = "Plugin" + __version__ = "0.4" + __pattern__ = None + __type__ = "hoster" + __description__ = """Base Plugin""" + __author_name__ = ("RaNaN", "spoob", "mkaay") + __author_mail__ = ("RaNaN@pyload.org", "spoob@pyload.org", "mkaay@mkaay.de") + def __init__(self, parent): self.configparser = parent.core.parser_plugins self.config = {} - props = {} - props['name'] = "BasePlugin" - props['version'] = "0.3" - props['pattern'] = None - props['type'] = "hoster" - props['description'] = """Base Plugin""" - props['author_name'] = ("RaNaN", "spoob", "mkaay") - props['author_mail'] = ("RaNaN@pyload.org", "spoob@pyload.org", "mkaay@mkaay.de") - self.props = props self.parent = parent self.req = Request() self.html = 0 @@ -115,20 +113,20 @@ class Plugin(): def set_config(self): for k, v in self.config.items(): - self.configparser.set(self.props['name'], {"option": k}, v) + self.configparser.set(self.__name__, {"option": k}, v) def remove_config(self, option): - self.configparser.remove(self.props['name'], option) + self.configparser.remove(self.__name__, option) def get_config(self, value, default=None): self.configparser.loadData() - return self.configparser.get(self.props['name'], value, default=default) + return self.configparser.get(self.__name__, value, default=default) def read_config(self): self.configparser.loadData() try: self.verify_config() - self.config = self.configparser.getConfig()[self.props['name']] + self.config = self.configparser.getConfig()[self.__name__] except: pass @@ -136,8 +134,7 @@ class Plugin(): pass def init_ocr(self): - modul = __import__("module.plugins.captcha." + self.props['name'], fromlist=['captcha']) - captchaClass = getattr(modul, self.props['name']) + captchaClass = self.core.pluginManager.getCaptchaPlugin(self.__name__) self.ocr = captchaClass() def __call__(self): diff --git a/module/plugins/container/CCF.py b/module/plugins/container/CCF.py index 9d7116900..1e25ef623 100644 --- a/module/plugins/container/CCF.py +++ b/module/plugins/container/CCF.py @@ -5,22 +5,19 @@ import re import tempfile import urllib2 -from module.plugins.Plugin import Plugin +from module.plugins.Container import Container from module.network.MultipartPostHandler import MultipartPostHandler -class CCF(Plugin): +class CCF(Container): + __name__ = "CCF" + __version__ = "0.1" + __pattern__ = r"(?!http://).*\.ccf" + __description__ = """CCF Container Convert Plugin""" + __author_name__ = ("Willnix") + __author_mail__ = ("Willnix@pyload.org") def __init__(self, parent): - Plugin.__init__(self, parent) - props = {} - props['name'] = "CCF" - props['type'] = "container" - props['pattern'] = r"(?!http://).*\.ccf" - props['version'] = "0.1" - props['description'] = """CCF Container Convert Plugin""" - props['author_name'] = ("Willnix") - props['author_mail'] = ("Willnix@pyload.org") - self.props = props + Container.__init__(self, parent) self.parent = parent self.multi_dl = True self.links = [] diff --git a/module/plugins/container/LinkList.py b/module/plugins/container/LinkList.py index b45ab83d0..cadf491a9 100644 --- a/module/plugins/container/LinkList.py +++ b/module/plugins/container/LinkList.py @@ -2,21 +2,18 @@ # -*- coding: utf-8 -*- -from module.plugins.Plugin import Plugin +from module.plugins.Container import Container -class LinkList(Plugin): +class LinkList(Container): + __name__ = "LinkList" + __version__ = "0.1" + __pattern__ = r"(?!http://).*\.txt" + __description__ = """Read Link Lists in txt format""" + __author_name__ = ("spoob") + __author_mail__ = ("spoob@pyload.org") def __init__(self, parent): - Plugin.__init__(self, parent) - props = {} - props['name'] = "LinkList" - props['type'] = "container" - props['pattern'] = r"(?!http://).*\.txt" - props['version'] = "0.1" - props['description'] = """Read Link Lists in txt format""" - props['author_name'] = ("Spoob") - props['author_mail'] = ("spoob@pyload.org") - self.props = props + Container.__init__(self, parent) self.parent = parent self.html = None self.read_config() diff --git a/module/plugins/container/RSDF.py b/module/plugins/container/RSDF.py index 9604495fd..c906fe05a 100644 --- a/module/plugins/container/RSDF.py +++ b/module/plugins/container/RSDF.py @@ -4,21 +4,18 @@ import base64 import binascii -from module.plugins.Plugin import Plugin +from module.plugins.Container import Container -class RSDF(Plugin): +class RSDF(Container): + __name__ = "RSDF" + __version__ = "0.2" + __pattern__ = r"(?!http://).*\.rsdf" + __description__ = """RSDF Container Decode Plugin""" + __author_name__ = ("RaNaN", "spoob") + __author_mail__ = ("RaNaN@pyload.org", "spoob@pyload.org") def __init__(self, parent): - Plugin.__init__(self, parent) - props = {} - props['name'] = "RSDF" - props['type'] = "container" - props['pattern'] = r"(?!http://).*\.rsdf" - props['version'] = "0.2" - props['description'] = """RSDF Container Decode Plugin""" - props['author_name'] = ("RaNaN", "spoob") - props['author_mail'] = ("RaNaN@pyload.org", "spoob@pyload.org") - self.props = props + Container.__init__(self, parent) self.parent = parent self.multi_dl = True self.links = [] diff --git a/module/plugins/crypter/DDLMusicOrg.py b/module/plugins/crypter/DDLMusicOrg.py new file mode 100644 index 000000000..1c5632cda --- /dev/null +++ b/module/plugins/crypter/DDLMusicOrg.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import re +from time import sleep + +from module.plugins.Crypter import Crypter + +class DDLMusicOrg(Crypter): + __name__ = "DDLMusicOrg" + __type__ = "container" + __pattern__ = r"http://[\w\.]*?ddl-music\.org/captcha/ddlm_cr\d\.php\?\d+\?\d+" + __version__ = "0.1" + __description__ = """ddl-music.org Container Plugin""" + __author_name__ = ("mkaay") + __author_mail__ = ("mkaay@mkaay.de") + + def __init__(self, parent): + Crypter.__init__(self, parent) + self.parent = parent + self.html = None + self.multi_dl = False + + def download_html(self): + url = self.parent.url + self.html = self.req.load(url, cookies=True) + + def file_exists(self): + """ returns True or False + """ + if not self.html: + self.download_html() + if re.search(r"Wer dies nicht rechnen kann", self.html) != None: + return True + return False + + def proceed(self, url, location): + for i in range(5): + self.download_html() + posturl = re.search(r"id=\"captcha\" action=\"(/captcha/ddlm_cr\d\.php)\"", self.html).group(1) + math = re.search(r"(\d+) ([\+-]) (\d+) =\s+", htmlwithlink) + if m: + self.links = [m.group(1)] + return + self.links = False diff --git a/module/plugins/crypter/FourChanOrg.py b/module/plugins/crypter/FourChanOrg.py new file mode 100644 index 000000000..cbcdd920c --- /dev/null +++ b/module/plugins/crypter/FourChanOrg.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import re + +from module.plugins.Crypter import Crypter + +class FourChanOrg(Crypter): + __name__ = "FourChanOrg" + __type__ = "container" + __pattern__ = r"http://(www\.)?(img\.)?(zip\.)?4chan.org/\w+/(res/|imgboard\.html)" + __version__ = "0.1" + __description__ = """4chan.org Thread Download Plugin""" + __author_name__ = ("Spoob") + __author_mail__ = ("Spoob@pyload.org") + + def __init__(self, parent): + Crypter.__init__(self, parent) + self.parent = parent + self.html = None + + def file_exists(self): + """ returns True or False + """ + return True + + def proceed(self, url, location): + url = self.parent.url + html = self.req.load(url) + link_pattern = "" + temp_links = [] + if "imagebord.html" in url: + link_pattern = '[Reply]' + temp_links = re.findall(link_pattern, html) + for link in re.findall(link_pattern, html): + temp_links.append(link) + else: + temp_links = re.findall('File : " + container + ":(.*?)
", self.html).group(1) + tmp = re.findall('
Part \d+', download_content) + if tmp == []: continue + for link in tmp: + link_html = self.req.load(link, cookies=True) + temp_links.append(re.search('