From 8e7d14bae4d3c836f029a1235eb227380acc3f75 Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Mon, 16 Feb 2015 21:59:10 +0100 Subject: Fix plugins to work on 0.4.10 --- module/plugins/internal/BasePlugin.py | 95 ---- module/plugins/internal/CaptchaService.py | 522 --------------------- module/plugins/internal/DeadCrypter.py | 31 -- module/plugins/internal/DeadHoster.py | 31 -- module/plugins/internal/Extractor.py | 139 ------ module/plugins/internal/MultiHook.py | 308 ------------- module/plugins/internal/MultiHoster.py | 85 ---- module/plugins/internal/SevenZip.py | 155 ------- module/plugins/internal/SimpleCrypter.py | 157 ------- module/plugins/internal/SimpleDereferer.py | 98 ---- module/plugins/internal/SimpleHoster.py | 701 ----------------------------- module/plugins/internal/UnRar.py | 248 ---------- module/plugins/internal/UnZip.py | 68 --- module/plugins/internal/UpdateManager.py | 300 ------------ module/plugins/internal/XFSAccount.py | 174 ------- module/plugins/internal/XFSCrypter.py | 45 -- module/plugins/internal/XFSHoster.py | 326 -------------- module/plugins/internal/__init__.py | 1 - 18 files changed, 3484 deletions(-) delete mode 100644 module/plugins/internal/BasePlugin.py delete mode 100644 module/plugins/internal/CaptchaService.py delete mode 100644 module/plugins/internal/DeadCrypter.py delete mode 100644 module/plugins/internal/DeadHoster.py delete mode 100644 module/plugins/internal/Extractor.py delete mode 100644 module/plugins/internal/MultiHook.py delete mode 100644 module/plugins/internal/MultiHoster.py delete mode 100644 module/plugins/internal/SevenZip.py delete mode 100644 module/plugins/internal/SimpleCrypter.py delete mode 100644 module/plugins/internal/SimpleDereferer.py delete mode 100644 module/plugins/internal/SimpleHoster.py delete mode 100644 module/plugins/internal/UnRar.py delete mode 100644 module/plugins/internal/UnZip.py delete mode 100644 module/plugins/internal/UpdateManager.py delete mode 100644 module/plugins/internal/XFSAccount.py delete mode 100644 module/plugins/internal/XFSCrypter.py delete mode 100644 module/plugins/internal/XFSHoster.py delete mode 100644 module/plugins/internal/__init__.py (limited to 'module/plugins/internal') diff --git a/module/plugins/internal/BasePlugin.py b/module/plugins/internal/BasePlugin.py deleted file mode 100644 index 792497449..000000000 --- a/module/plugins/internal/BasePlugin.py +++ /dev/null @@ -1,95 +0,0 @@ -# -*- coding: utf-8 -*- - -import re - -from urllib import unquote -from urlparse import urljoin, urlparse - -from module.network.HTTPRequest import BadHeader -from module.plugins.internal.SimpleHoster import create_getInfo, fileUrl -from module.plugins.Hoster import Hoster - - -class BasePlugin(Hoster): - __name__ = "BasePlugin" - __type__ = "hoster" - __version__ = "0.34" - - __pattern__ = r'^unmatchable$' - - __description__ = """Base plugin when any other didnt fit""" - __license__ = "GPLv3" - __authors__ = [("RaNaN", "RaNaN@pyload.org"), - ("Walter Purcaro", "vuolter@gmail.com")] - - - @classmethod - def getInfo(cls, url="", html=""): #@TODO: Move to hoster class in 0.4.10 - url = unquote(url) - url_p = urlparse(url) - return {'name' : (url_p.path.split('/')[-1] - or url_p.query.split('=', 1)[::-1][0].split('&', 1)[0] - or url_p.netloc.split('.', 1)[0]), - 'size' : 0, - 'status': 3 if url else 8, - 'url' : url} - - - def setup(self): - self.chunkLimit = -1 - self.multiDL = True - self.resumeDownload = True - - - def process(self, pyfile): - """main function""" - - pyfile.name = self.getInfo(pyfile.url)['name'] - - if not pyfile.url.startswith("http"): - self.fail(_("No plugin matched")) - - for _i in xrange(5): - try: - link = fileUrl(self, unquote(pyfile.url)) - - if link: - self.download(link, ref=False, disposition=True) - else: - self.fail(_("File not found")) - - except BadHeader, e: - if e.code is 404: - self.offline() - - elif e.code in (401, 403): - self.logDebug("Auth required", "Received HTTP status code: %d" % e.code) - - account = self.core.accountManager.getAccountPlugin('Http') - servers = [x['login'] for x in account.getAllAccounts()] - server = urlparse(pyfile.url).netloc - - if server in servers: - self.logDebug("Logging on to %s" % server) - self.req.addAuth(account.getAccountData(server)['password']) - else: - pwd = self.getPassword() - if ':' in pwd: - self.req.addAuth(pwd) - else: - self.fail(_("Authorization required")) - else: - self.fail(e) - else: - break - else: - self.fail(_("No file downloaded")) #@TODO: Move to hoster class in 0.4.10 - - check = self.checkDownload({'empty file': re.compile(r'\A\Z'), - 'html file' : re.compile(r'\A\s*)?\d{3}(\Z|\s+)')}) - if check: - self.fail(check.capitalize()) - - -getInfo = create_getInfo(BasePlugin) diff --git a/module/plugins/internal/CaptchaService.py b/module/plugins/internal/CaptchaService.py deleted file mode 100644 index 6f2c8e06d..000000000 --- a/module/plugins/internal/CaptchaService.py +++ /dev/null @@ -1,522 +0,0 @@ -# -*- coding: utf-8 -*- - -import re -import time - -from base64 import b64encode -from random import random, randint -from urlparse import urljoin, urlparse - -from module.common.json_layer import json_loads -from module.plugins.Plugin import Base - - -#@TODO: Extend (new) Plugin class; remove all `html` args -class CaptchaService(Base): - __name__ = "CaptchaService" - __version__ = "0.25" - - __description__ = """Base captcha service plugin""" - __license__ = "GPLv3" - __authors__ = [("pyLoad Team", "admin@pyload.org")] - - - key = None #: last key detected - - - def __init__(self, plugin): - self.plugin = plugin - super(CaptchaService, self).__init__(plugin.core) - - - def detect_key(self, html=None): - raise NotImplementedError - - - def challenge(self, key=None, html=None): - raise NotImplementedError - - - def result(self, server, challenge): - raise NotImplementedError - - -class ReCaptcha(CaptchaService): - __name__ = "ReCaptcha" - __version__ = "0.14" - - __description__ = """ReCaptcha captcha service plugin""" - __license__ = "GPLv3" - __authors__ = [("pyLoad Team", "admin@pyload.org"), - ("Walter Purcaro", "vuolter@gmail.com"), - ("zapp-brannigan", "fuerst.reinje@web.de")] - - - KEY_V2_PATTERN = r'(?:data-sitekey=["\']|["\']sitekey["\']:\s*["\'])([\w-]+)' - KEY_V1_PATTERN = r'(?:recaptcha(?:/api|\.net)/(?:challenge|noscript)\?k=|Recaptcha\.create\s*\(\s*["\'])([\w-]+)' - - - def detect_key(self, html=None): - if not html: - if hasattr(self.plugin, "html") and self.plugin.html: - html = self.plugin.html - else: - errmsg = _("ReCaptcha html not found") - self.plugin.fail(errmsg) - raise TypeError(errmsg) - - m = re.search(self.KEY_V2_PATTERN, html) or re.search(self.KEY_V1_PATTERN, html) - if m: - self.key = m.group(1).strip() - self.logDebug("Key: %s" % self.key) - return self.key - else: - self.logDebug("Key not found") - return None - - - def challenge(self, key=None, html=None, version=None): - if not key: - if self.detect_key(html): - key = self.key - else: - errmsg = _("ReCaptcha key not found") - self.plugin.fail(errmsg) - raise TypeError(errmsg) - - if version in (1, 2): - return getattr(self, "_challenge_v%s" % version)(key) - - elif not html and hasattr(self.plugin, "html") and self.plugin.html: - version = 2 if re.search(self.KEY_V2_PATTERN, self.plugin.html) else 1 - return self.challenge(key, self.plugin.html, version) - - else: - errmsg = _("ReCaptcha html not found") - self.plugin.fail(errmsg) - raise TypeError(errmsg) - - - def _challenge_v1(self, key): - html = self.plugin.req.load("http://www.google.com/recaptcha/api/challenge", - get={'k': key}) - try: - challenge = re.search("challenge : '(.+?)',", html).group(1) - server = re.search("server : '(.+?)',", html).group(1) - - except AttributeError: - errmsg = _("ReCaptcha challenge pattern not found") - self.plugin.fail(errmsg) - raise AttributeError(errmsg) - - self.logDebug("Challenge: %s" % challenge) - - return self.result(server, challenge), challenge - - - def result(self, server, challenge): - result = self.plugin.decryptCaptcha("%simage" % server, - get={'c': challenge}, - cookies=True, - forceUser=True, - imgtype="jpg") - - self.logDebug("Result: %s" % result) - - return result - - - def _collectApiInfo(self): - html = self.plugin.req.load("http://www.google.com/recaptcha/api.js") - a = re.search(r'po.src = \'(.*?)\';', html).group(1) - vers = a.split("/")[5] - - self.logDebug("API version: %s" %vers) - - language = a.split("__")[1].split(".")[0] - - self.logDebug("API language: %s" % language) - - html = self.plugin.req.load("https://apis.google.com/js/api.js") - b = re.search(r'"h":"(.*?)","', html).group(1) - jsh = b.decode('unicode-escape') - - self.logDebug("API jsh-string: %s" % jsh) - - return vers, language, jsh - - - def _prepareTimeAndRpc(self): - self.plugin.req.load("http://www.google.com/recaptcha/api2/demo") - - millis = int(round(time.time() * 1000)) - - self.logDebug("Time: %s" % millis) - - rand = randint(1, 99999999) - a = "0.%s" % str(rand * 2147483647) - rpc = int(100000000 * float(a)) - - self.logDebug("Rpc-token: %s" % rpc) - - return millis, rpc - - - def _challenge_v2(self, key, parent=None): - if parent is None: - try: - parent = urljoin("http://", urlparse(self.plugin.pyfile.url).netloc) - - except Exception: - parent = "" - - botguardstring = "!A" - vers, language, jsh = self._collectApiInfo() - millis, rpc = self._prepareTimeAndRpc() - - html = self.plugin.req.load("https://www.google.com/recaptcha/api2/anchor", - get={'k' : key, - 'hl' : language, - 'v' : vers, - 'usegapi' : "1", - 'jsh' : "%s#id=IO_%s" % (jsh, millis), - 'parent' : parent, - 'pfname' : "", - 'rpctoken': rpc}) - - token1 = re.search(r'id="recaptcha-token" value="(.*?)">', html) - self.logDebug("Token #1: %s" % token1.group(1)) - - html = self.plugin.req.load("https://www.google.com/recaptcha/api2/frame", - get={'c' : token1.group(1), - 'hl' : language, - 'v' : vers, - 'bg' : botguardstring, - 'k' : key, - 'usegapi': "1", - 'jsh' : jsh}).decode('unicode-escape') - - token2 = re.search(r'"finput","(.*?)",', html) - self.logDebug("Token #2: %s" % token2.group(1)) - - token3 = re.search(r'."asconf".\s,".*?".\s,"(.*?)".', html) - self.logDebug("Token #3: %s" % token3.group(1)) - - html = self.plugin.req.load("https://www.google.com/recaptcha/api2/reload", - post={'k' : key, - 'c' : token2.group(1), - 'reason': "fi", - 'fbg' : token3.group(1)}) - - token4 = re.search(r'"rresp","(.*?)",', html) - self.logDebug("Token #4: %s" % token4.group(1)) - - millis_captcha_loading = int(round(time.time() * 1000)) - captcha_response = self.plugin.decryptCaptcha("https://www.google.com/recaptcha/api2/payload", - get={'c':token4.group(1), 'k':key}, - cookies=True, - forceUser=True) - response = b64encode('{"response":"%s"}' % captcha_response) - - self.logDebug("Result: %s" % response) - - timeToSolve = int(round(time.time() * 1000)) - millis_captcha_loading - timeToSolveMore = timeToSolve + int(float("0." + str(randint(1, 99999999))) * 500) - - html = self.plugin.req.load("https://www.google.com/recaptcha/api2/userverify", - post={'k' : key, - 'c' : token4.group(1), - 'response': response, - 't' : timeToSolve, - 'ct' : timeToSolveMore, - 'bg' : botguardstring}) - - token5 = re.search(r'"uvresp","(.*?)",', html) - self.logDebug("Token #5: %s" % token5.group(1)) - - result = token5.group(1) - - return result, None - - - -class AdsCaptcha(CaptchaService): - __name__ = "AdsCaptcha" - __version__ = "0.08" - - __description__ = """AdsCaptcha captcha service plugin""" - __license__ = "GPLv3" - __authors__ = [("pyLoad Team", "admin@pyload.org")] - - - CAPTCHAID_PATTERN = r'api\.adscaptcha\.com/Get\.aspx\?[^"\']*CaptchaId=(\d+)' - PUBLICKEY_PATTERN = r'api\.adscaptcha\.com/Get\.aspx\?[^"\']*PublicKey=([\w-]+)' - - - def detect_key(self, html=None): - if not html: - if hasattr(self.plugin, "html") and self.plugin.html: - html = self.plugin.html - else: - errmsg = _("AdsCaptcha html not found") - self.plugin.fail(errmsg) - raise TypeError(errmsg) - - m = re.search(self.PUBLICKEY_PATTERN, html) - n = re.search(self.CAPTCHAID_PATTERN, html) - if m and n: - self.key = (m.group(1).strip(), n.group(1).strip()) #: key is the tuple(PublicKey, CaptchaId) - self.logDebug("Key|id: %s | %s" % self.key) - return self.key - else: - self.logDebug("Key or id not found") - return None - - - def challenge(self, key=None, html=None): - if not key: - if self.detect_key(html): - key = self.key - else: - errmsg = _("AdsCaptcha key not found") - self.plugin.fail(errmsg) - raise TypeError(errmsg) - - PublicKey, CaptchaId = key - - html = self.plugin.req.load("http://api.adscaptcha.com/Get.aspx", - get={'CaptchaId': CaptchaId, - 'PublicKey': PublicKey}) - try: - challenge = re.search("challenge: '(.+?)',", html).group(1) - server = re.search("server: '(.+?)',", html).group(1) - - except AttributeError: - errmsg = _("AdsCaptcha challenge pattern not found") - self.plugin.fail(errmsg) - raise AttributeError(errmsg) - - self.logDebug("Challenge: %s" % challenge) - - return self.result(server, challenge), challenge - - - def result(self, server, challenge): - result = self.plugin.decryptCaptcha("%sChallenge.aspx" % server, - get={'cid': challenge, 'dummy': random()}, - cookies=True, - imgtype="jpg") - - self.logDebug("Result: %s" % result) - - return result - - -class SolveMedia(CaptchaService): - __name__ = "SolveMedia" - __version__ = "0.12" - - __description__ = """SolveMedia captcha service plugin""" - __license__ = "GPLv3" - __authors__ = [("pyLoad Team", "admin@pyload.org")] - - - KEY_PATTERN = r'api\.solvemedia\.com/papi/challenge\.(?:no)?script\?k=(.+?)["\']' - - - def detect_key(self, html=None): - if not html: - if hasattr(self.plugin, "html") and self.plugin.html: - html = self.plugin.html - else: - errmsg = _("SolveMedia html not found") - self.plugin.fail(errmsg) - raise TypeError(errmsg) - - m = re.search(self.KEY_PATTERN, html) - if m: - self.key = m.group(1).strip() - self.logDebug("Key: %s" % self.key) - return self.key - else: - self.logDebug("Key not found") - return None - - - def challenge(self, key=None, html=None): - if not key: - if self.detect_key(html): - key = self.key - else: - errmsg = _("SolveMedia key not found") - self.plugin.fail(errmsg) - raise TypeError(errmsg) - - html = self.plugin.req.load("http://api.solvemedia.com/papi/challenge.noscript", - get={'k': key}) - try: - challenge = re.search(r'', - html).group(1) - server = "http://api.solvemedia.com/papi/media" - - except AttributeError: - errmsg = _("SolveMedia challenge pattern not found") - self.plugin.fail(errmsg) - raise AttributeError(errmsg) - - self.logDebug("Challenge: %s" % challenge) - - result = self.result(server, challenge) - - try: - magic = re.search(r'name="magic" value="(.+?)"', html).group(1) - - except AttributeError: - self.logDebug("Magic code not found") - - else: - if not self._verify(key, magic, result, challenge): - self.logDebug("Captcha code was invalid") - - return result, challenge - - - def _verify(self, key, magic, result, challenge, ref=None): #@TODO: Clean up - if ref is None: - try: - ref = self.plugin.pyfile.url - - except Exception: - ref = "" - - html = self.plugin.req.load("http://api.solvemedia.com/papi/verify.noscript", - post={'adcopy_response' : result, - 'k' : key, - 'l' : "en", - 't' : "img", - 's' : "standard", - 'magic' : magic, - 'adcopy_challenge' : challenge, - 'ref' : ref}) - try: - html = self.plugin.req.load(re.search(r'URL=(.+?)">', html).group(1)) - gibberish = re.search(r'id=gibberish>(.+?)', html).group(1) - - except Exception: - return False - - else: - return True - - - def result(self, server, challenge): - result = self.plugin.decryptCaptcha(server, - get={'c': challenge}, - cookies=True, - imgtype="gif") - - self.logDebug("Result: %s" % result) - - return result - - -class AdYouLike(CaptchaService): - __name__ = "AdYouLike" - __version__ = "0.05" - - __description__ = """AdYouLike captcha service plugin""" - __license__ = "GPLv3" - __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] - - - AYL_PATTERN = r'Adyoulike\.create\s*\((.+?)\)' - CALLBACK_PATTERN = r'(Adyoulike\.g\._jsonp_\d+)' - - - def detect_key(self, html=None): - if not html: - if hasattr(self.plugin, "html") and self.plugin.html: - html = self.plugin.html - else: - errmsg = _("AdYouLike html not found") - self.plugin.fail(errmsg) - raise TypeError(errmsg) - - m = re.search(self.AYL_PATTERN, html) - n = re.search(self.CALLBACK_PATTERN, html) - if m and n: - self.key = (m.group(1).strip(), n.group(1).strip()) - self.logDebug("Ayl|callback: %s | %s" % self.key) - return self.key #: key is the tuple(ayl, callback) - else: - self.logDebug("Ayl or callback not found") - return None - - - def challenge(self, key=None, html=None): - if not key: - if self.detect_key(html): - key = self.key - else: - errmsg = _("AdYouLike key not found") - self.plugin.fail(errmsg) - raise TypeError(errmsg) - - ayl, callback = key - - # {"adyoulike":{"key":"P~zQ~O0zV0WTiAzC-iw0navWQpCLoYEP"}, - # "all":{"element_id":"ayl_private_cap_92300","lang":"fr","env":"prod"}} - ayl = json_loads(ayl) - - html = self.plugin.req.load("http://api-ayl.appspot.com/challenge", - get={'key' : ayl['adyoulike']['key'], - 'env' : ayl['all']['env'], - 'callback': callback}) - try: - challenge = json_loads(re.search(callback + r'\s*\((.+?)\)', html).group(1)) - - except AttributeError: - errmsg = _("AdYouLike challenge pattern not found") - self.plugin.fail(errmsg) - raise AttributeError(errmsg) - - self.logDebug("Challenge: %s" % challenge) - - return self.result(ayl, challenge), challenge - - - def result(self, server, challenge): - # Adyoulike.g._jsonp_5579316662423138 - # ({"translations":{"fr":{"instructions_visual":"Recopiez « Soonnight » ci-dessous :"}}, - # "site_under":true,"clickable":true,"pixels":{"VIDEO_050":[],"DISPLAY":[],"VIDEO_000":[],"VIDEO_100":[], - # "VIDEO_025":[],"VIDEO_075":[]},"medium_type":"image/adyoulike", - # "iframes":{"big":""},"shares":{},"id":256, - # "token":"e6QuI4aRSnbIZJg02IsV6cp4JQ9~MjA1","formats":{"small":{"y":300,"x":0,"w":300,"h":60}, - # "big":{"y":0,"x":0,"w":300,"h":250},"hover":{"y":440,"x":0,"w":300,"h":60}}, - # "tid":"SqwuAdxT1EZoi4B5q0T63LN2AkiCJBg5"}) - - if isinstance(server, basestring): - server = json_loads(server) - - if isinstance(challenge, basestring): - challenge = json_loads(challenge) - - try: - instructions_visual = challenge['translations'][server['all']['lang']]['instructions_visual'] - result = re.search(u'«(.+?)»', instructions_visual).group(1).strip() - - except AttributeError: - errmsg = _("AdYouLike result not found") - self.plugin.fail(errmsg) - raise AttributeError(errmsg) - - result = {'_ayl_captcha_engine' : "adyoulike", - '_ayl_env' : server['all']['env'], - '_ayl_tid' : challenge['tid'], - '_ayl_token_challenge': challenge['token'], - '_ayl_response' : response} - - self.logDebug("Result: %s" % result) - - return result diff --git a/module/plugins/internal/DeadCrypter.py b/module/plugins/internal/DeadCrypter.py deleted file mode 100644 index ce56947fc..000000000 --- a/module/plugins/internal/DeadCrypter.py +++ /dev/null @@ -1,31 +0,0 @@ -# -*- coding: utf-8 -*- - -from pyload.plugin.Crypter import Crypter as _Crypter -from pyload.plugin.internal.SimpleCrypter import create_getInfo - - -class DeadCrypter(_Crypter): - __name__ = "DeadCrypter" - __type__ = "crypter" - __version__ = "0.04" - - __pattern__ = r'^unmatchable$' - - __description__ = """Crypter is no longer available""" - __license__ = "GPLv3" - __authors__ = [("stickell", "l.stickell@yahoo.it")] - - - @classmethod - def apiInfo(cls, url="", get={}, post={}): - api = super(DeadCrypter, self).apiInfo(url, get, post) - api['status'] = 1 - return api - - - def setup(self): - self.pyfile.error = "Crypter is no longer available" - self.offline() #@TODO: self.offline("Crypter is no longer available") - - -getInfo = create_getInfo(DeadCrypter) diff --git a/module/plugins/internal/DeadHoster.py b/module/plugins/internal/DeadHoster.py deleted file mode 100644 index 132e4741a..000000000 --- a/module/plugins/internal/DeadHoster.py +++ /dev/null @@ -1,31 +0,0 @@ -# -*- coding: utf-8 -*- - -from pyload.plugin.Hoster import Hoster as _Hoster -from pyload.plugin.internal.SimpleHoster import create_getInfo - - -class DeadHoster(_Hoster): - __name__ = "DeadHoster" - __type__ = "hoster" - __version__ = "0.14" - - __pattern__ = r'^unmatchable$' - - __description__ = """Hoster is no longer available""" - __license__ = "GPLv3" - __authors__ = [("zoidberg", "zoidberg@mujmail.cz")] - - - @classmethod - def apiInfo(cls, url="", get={}, post={}): - api = super(DeadHoster, self).apiInfo(url, get, post) - api['status'] = 1 - return api - - - def setup(self): - self.pyfile.error = "Hoster is no longer available" - self.offline() #@TODO: self.offline("Hoster is no longer available") - - -getInfo = create_getInfo(DeadHoster) diff --git a/module/plugins/internal/Extractor.py b/module/plugins/internal/Extractor.py deleted file mode 100644 index b445f1497..000000000 --- a/module/plugins/internal/Extractor.py +++ /dev/null @@ -1,139 +0,0 @@ -# -*- coding: utf-8 -*- - -import os - -from module.PyFile import PyFile - - -class ArchiveError(Exception): - pass - - -class CRCError(Exception): - pass - - -class PasswordError(Exception): - pass - - -class Extractor: - __name__ = "Extractor" - __version__ = "0.20" - - __description__ = """Base extractor plugin""" - __license__ = "GPLv3" - __authors__ = [("RaNaN", "ranan@pyload.org"), - ("Walter Purcaro", "vuolter@gmail.com"), - ("Immenz", "immenz@gmx.net")] - - - EXTENSIONS = [] - VERSION = "" - - - @classmethod - def isArchive(cls, filename): - name = os.path.basename(filename).lower() - return any(name.endswith(ext) for ext in cls.EXTENSIONS) and not cls.isMultipart(filename) - - - @classmethod - def isMultipart(cls,filename): - return False - - - @classmethod - def isUsable(cls): - """ Check if system statisfy dependencies - :return: boolean - """ - return None - - - @classmethod - def getTargets(cls, files_ids): - """ Filter suited targets from list of filename id tuple list - :param files_ids: List of filepathes - :return: List of targets, id tuple list - """ - return [(fname, id, fout) for fname, id, fout in files_ids if cls.isArchive(fname)] - - - def __init__(self, manager, filename, out, - fullpath=True, - overwrite=False, - excludefiles=[], - renice=0, - delete=False, - keepbroken=False, - fid=None): - """ Initialize extractor for specific file """ - self.manager = manager - self.filename = filename - self.out = out - self.fullpath = fullpath - self.overwrite = overwrite - self.excludefiles = excludefiles - self.renice = renice - self.delete = delete - self.keepbroken = keepbroken - self.files = [] #: Store extracted files here - - pyfile = self.manager.core.files.getFile(fid) if fid else None - self.notifyProgress = lambda x: pyfile.setProgress(x) if pyfile else lambda x: None - - - def init(self): - """ Initialize additional data structures """ - pass - - - def check(self): - """Check if password if needed. Raise ArchiveError if integrity is - questionable. - - :return: boolean - :raises ArchiveError - """ - raise PasswordError - - - def isPassword(self, password): - """ Check if the given password is/might be correct. - If it can not be decided at this point return true. - - :param password: - :return: boolean - """ - return None - - - def repair(self): - return None - - - def extract(self, password=None): - """Extract the archive. Raise specific errors in case of failure. - - :param progress: Progress function, call this to update status - :param password password to use - :raises PasswordError - :raises CRCError - :raises ArchiveError - :return: - """ - raise NotImplementedError - - - def getDeleteFiles(self): - """Return list of files to delete, do *not* delete them here. - - :return: List with paths of files to delete - """ - return [self.filename] - - - def list(self, password=None): - """Populate self.files at some point while extracting""" - return self.files diff --git a/module/plugins/internal/MultiHook.py b/module/plugins/internal/MultiHook.py deleted file mode 100644 index 652443098..000000000 --- a/module/plugins/internal/MultiHook.py +++ /dev/null @@ -1,308 +0,0 @@ -# -*- coding: utf-8 -*- - -import re - -from time import sleep - -from module.plugins.Hook import Hook -from module.utils import decode, remove_chars - - -class MultiHook(Hook): - __name__ = "MultiHook" - __type__ = "hook" - __version__ = "0.37" - - __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), - ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ), - ("revertfailed" , "bool" , "Revert to standard download if fails", True ), - ("retry" , "int" , "Number of retries before revert" , 10 ), - ("retryinterval" , "int" , "Retry interval in minutes" , 1 ), - ("reload" , "bool" , "Reload plugin list" , True ), - ("reloadinterval", "int" , "Reload interval in hours" , 12 )] - - __description__ = """Hook plugin for multi hoster/crypter""" - __license__ = "GPLv3" - __authors__ = [("pyLoad Team", "admin@pyload.org"), - ("Walter Purcaro", "vuolter@gmail.com")] - - - MIN_INTERVAL = 1 * 60 * 60 - - DOMAIN_REPLACEMENTS = [(r'180upload\.com' , "hundredeightyupload.com"), - (r'1fichier\.com' , "onefichier.com" ), - (r'2shared\.com' , "twoshared.com" ), - (r'4shared\.com' , "fourshared.com" ), - (r'bayfiles\.net' , "bayfiles.com" ), - (r'cloudnator\.com' , "shragle.com" ), - (r'dfiles\.eu' , "depositfiles.com" ), - (r'easy-share\.com' , "crocko.com" ), - (r'freakshare\.net' , "freakshare.com" ), - (r'hellshare\.com' , "hellshare.cz" ), - (r'ifile\.it' , "filecloud.io" ), - (r'nowdownload\.\w+', "nowdownload.sx" ), - (r'nowvideo\.\w+' , "nowvideo.sx" ), - (r'putlocker\.com' , "firedrive.com" ), - (r'share-?rapid\.cz', "multishare.cz" ), - (r'ul\.to' , "uploaded.to" ), - (r'uploaded\.net' , "uploaded.to" ), - (r'uploadhero\.co' , "uploadhero.com" ), - (r'zshares\.net' , "zshare.net" ), - (r'(\d+.+)' , "X\1" )] - - - def setup(self): - self.plugins = [] - self.supported = [] - self.new_supported = [] - - self.account = None - self.pluginclass = None - self.pluginmodule = None - self.pluginname = None - self.plugintype = None - - self._initPlugin() - - - def _initPlugin(self): - plugin, type = self.core.pluginManager.findPlugin(self.__name__) - - if not plugin: - self.logWarning("Hook plugin will be deactivated due missing plugin reference") - self.setConfig('activated', False) - else: - self.pluginname = self.__name__ - self.plugintype = type - self.pluginmodule = self.core.pluginManager.loadModule(type, self.__name__) - self.pluginclass = getattr(self.pluginmodule, self.__name__) - - - def _loadAccount(self): - self.account = self.core.accountManager.getAccountPlugin(self.pluginname) - - if self.account and not self.account.canUse(): - self.account = None - - if not self.account and hasattr(self.pluginclass, "LOGIN_ACCOUNT") and self.pluginclass.LOGIN_ACCOUNT: - self.logWarning("Hook plugin will be deactivated due missing account reference") - self.setConfig('activated', False) - - - def coreReady(self): - self._loadAccount() - - - def getURL(self, *args, **kwargs): #@TODO: Remove in 0.4.10 - """ see HTTPRequest for argument list """ - h = pyreq.getHTTPRequest(timeout=120) - try: - if not 'decode' in kwargs: - kwargs['decode'] = True - rep = h.load(*args, **kwargs) - finally: - h.close() - - return rep - - - def getConfig(self, option, default=''): - """getConfig with default value - sublass may not implements all config options""" - try: - return self.getConf(option) - - except KeyError: - return default - - - def pluginsCached(self): - if self.plugins: - return self.plugins - - for _i in xrange(3): - try: - pluginset = self._pluginSet(self.getHosters() if self.plugintype == "hoster" else self.getCrypters()) - - except Exception, e: - self.logError(e, "Waiting 1 minute and retry") - sleep(60) - - else: - break - else: - return list() - - try: - configmode = self.getConfig("pluginmode", 'all') - if configmode in ("listed", "unlisted"): - pluginlist = self.getConfig("pluginlist", '').replace('|', ',').replace(';', ',').split(',') - configset = self._pluginSet(pluginlist) - - if configmode == "listed": - pluginset &= configset - else: - pluginset -= configset - - except Exception, e: - self.logError(e) - - self.plugins = list(pluginset) - - return self.plugins - - - def _pluginSet(self, plugins): - plugins = set((decode(x).strip().lower() for x in plugins if '.' in x)) - - for rf, rt in self.DOMAIN_REPLACEMENTS: - regex = re.compile(rf) - for p in filter(lambda x: regex.match(x), plugins): - plugins.remove(p) - plugins.add(re.sub(rf, rt, p)) - - plugins.discard('') - - return plugins - - - def getHosters(self): - """Load list of supported hoster - - :return: List of domain names - """ - raise NotImplementedError - - - def getCrypters(self): - """Load list of supported crypters - - :return: List of domain names - """ - raise NotImplementedError - - - def periodical(self): - """reload plugin list periodically""" - self.logInfo(_("Reloading supported %s list") % self.plugintype) - - old_supported = self.supported - - self.supported = [] - self.new_supported = [] - self.plugins = [] - - self.overridePlugins() - - old_supported = [plugin for plugin in old_supported if plugin not in self.supported] - - if old_supported: - self.logDebug("Unload: %s" % ", ".join(old_supported)) - for plugin in old_supported: - self.unloadPlugin(plugin) - - if self.getConfig("reload", True): - self.interval = max(self.getConfig("reloadinterval", 12) * 60 * 60, self.MIN_INTERVAL) - else: - self.core.scheduler.removeJob(self.cb) - self.cb = None - - - def overridePlugins(self): - excludedList = [] - - if self.plugintype == "hoster": - pluginMap = dict((name.lower(), name) for name in self.core.pluginManager.hosterPlugins.iterkeys()) - accountList = [account.type.lower() for account in self.core.api.getAccounts(False) if account.valid and account.premium] - else: - pluginMap = {} - accountList = [name[::-1].replace("Folder"[::-1], "", 1).lower()[::-1] for name in self.core.pluginManager.crypterPlugins.iterkeys()] - - for plugin in self.pluginsCached(): - name = remove_chars(plugin, "-.") - - if name in accountList: - excludedList.append(plugin) - else: - if name in pluginMap: - self.supported.append(pluginMap[name]) - else: - self.new_supported.append(plugin) - - if not self.supported and not self.new_supported: - self.logError(_("No %s loaded") % self.plugintype) - return - - # inject plugin plugin - self.logDebug("Overwritten %ss: %s" % (self.plugintype, ", ".join(sorted(self.supported)))) - - for plugin in self.supported: - hdict = self.core.pluginManager.plugins[self.plugintype][plugin] - hdict['new_module'] = self.pluginmodule - hdict['new_name'] = self.pluginname - - if excludedList: - self.logInfo(_("%ss not overwritten: %s") % (self.plugintype.capitalize(), ", ".join(sorted(excludedList)))) - - if self.new_supported: - plugins = sorted(self.new_supported) - - self.logDebug("New %ss: %s" % (self.plugintype, ", ".join(plugins))) - - # create new regexp - regexp = r'.*(?P%s).*' % "|".join([x.replace(".", "\.") for x in plugins]) - if hasattr(self.pluginclass, "__pattern__") and isinstance(self.pluginclass.__pattern__, basestring) and '://' in self.pluginclass.__pattern__: - regexp = r'%s|%s' % (self.pluginclass.__pattern__, regexp) - - self.logDebug("Regexp: %s" % regexp) - - hdict = self.core.pluginManager.plugins[self.plugintype][self.pluginname] - hdict['pattern'] = regexp - hdict['re'] = re.compile(regexp) - - - def unloadPlugin(self, plugin): - hdict = self.core.pluginManager.plugins[self.plugintype][plugin] - if "module" in hdict: - del hdict['module'] - - if "new_module" in hdict: - del hdict['new_module'] - del hdict['new_name'] - - - def unload(self): - """Remove override for all plugins. Scheduler job is removed by hookmanager""" - for plugin in self.supported: - self.unloadPlugin(plugin) - - # reset pattern - hdict = self.core.pluginManager.plugins[self.plugintype][self.pluginname] - - hdict['pattern'] = getattr(self.pluginclass, "__pattern__", r'^unmatchable$') - hdict['re'] = re.compile(hdict['pattern']) - - - def downloadFailed(self, pyfile): - """remove plugin override if download fails but not if file is offline/temp.offline""" - if pyfile.status != 8 or not self.getConfig("revertfailed", True): - return - - hdict = self.core.pluginManager.plugins[self.plugintype][pyfile.pluginname] - if "new_name" in hdict and hdict['new_name'] == self.pluginname: - if pyfile.error == "MultiHook": - self.logDebug("Unload MultiHook", pyfile.pluginname, hdict) - self.unloadPlugin(pyfile.pluginname) - pyfile.setStatus("queued") - pyfile.sync() - else: - retries = max(self.getConfig("retry", 10), 0) - wait_time = max(self.getConfig("retryinterval", 1), 0) - - if 0 < retries > pyfile.plugin.retries: - self.logInfo(_("Retrying: %s") % pyfile.name) - pyfile.setCustomStatus("MultiHook", "queued") - pyfile.sync() - - pyfile.plugin.retries += 1 - pyfile.plugin.setWait(wait_time) - pyfile.plugin.wait() diff --git a/module/plugins/internal/MultiHoster.py b/module/plugins/internal/MultiHoster.py deleted file mode 100644 index 63b7d76b1..000000000 --- a/module/plugins/internal/MultiHoster.py +++ /dev/null @@ -1,85 +0,0 @@ -# -*- coding: utf-8 -*- - -import re - -from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo, replace_patterns, set_cookies - - -class MultiHoster(SimpleHoster): - __name__ = "MultiHoster" - __type__ = "hoster" - __version__ = "0.37" - - __pattern__ = r'^unmatchable$' - - __description__ = """Multi hoster plugin""" - __license__ = "GPLv3" - __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] - - - LOGIN_ACCOUNT = True - - - def setup(self): - self.chunkLimit = 1 - self.multiDL = bool(self.account) - self.resumeDownload = self.premium - - - def prepare(self): - self.info = {} - self.html = "" - self.link = "" #@TODO: Move to hoster class in 0.4.10 - self.directDL = False #@TODO: Move to hoster class in 0.4.10 - - if self.LOGIN_ACCOUNT and not self.account: - self.fail(_("Required account not found")) - - self.req.setOption("timeout", 120) - - if isinstance(self.COOKIES, list): - set_cookies(self.req.cj, self.COOKIES) - - if self.DIRECT_LINK is None: - self.directDL = self.__pattern__ != r'^unmatchable$' and re.match(self.__pattern__, self.pyfile.url) - else: - self.directDL = self.DIRECT_LINK - - self.pyfile.url = replace_patterns(self.pyfile.url, self.URL_REPLACEMENTS) - - - def process(self, pyfile): - self.prepare() - - if self.directDL: - self.checkInfo() - self.logDebug("Looking for direct download link...") - self.handleDirect(pyfile) - - if not self.link and not self.lastDownload: - self.preload() - - self.checkErrors() - self.checkStatus(getinfo=False) - - if self.premium and (not self.CHECK_TRAFFIC or self.checkTrafficLeft()): - self.logDebug("Handled as premium download") - self.handlePremium(pyfile) - - elif not self.LOGIN_ACCOUNT or (not self.CHECK_TRAFFIC or self.checkTrafficLeft()): - self.logDebug("Handled as free download") - self.handleFree(pyfile) - - self.downloadLink(self.link, True) - self.checkFile() - - - def handlePremium(self, pyfile): - return self.handleFree(pyfile) - - - def handleFree(self, pyfile): - if self.premium: - raise NotImplementedError - else: - self.fail(_("Required premium account not found")) diff --git a/module/plugins/internal/SevenZip.py b/module/plugins/internal/SevenZip.py deleted file mode 100644 index 7ad6b0d7a..000000000 --- a/module/plugins/internal/SevenZip.py +++ /dev/null @@ -1,155 +0,0 @@ -# -*- coding: utf-8 -*- - -import os -import re - -from subprocess import Popen, PIPE - -from module.plugins.internal.UnRar import ArchiveError, CRCError, PasswordError, UnRar, renice -from module.utils import fs_encode, save_join - - -class SevenZip(UnRar): - __name__ = "SevenZip" - __version__ = "0.08" - - __description__ = """7-Zip extractor plugin""" - __license__ = "GPLv3" - __authors__ = [("Michael Nowak", ""), - ("Walter Purcaro", "vuolter@gmail.com")] - - - CMD = "7z" - VERSION = "" - - EXTENSIONS = [".7z", ".xz", ".zip", ".gz", ".gzip", ".tgz", ".bz2", ".bzip2", - ".tbz2", ".tbz", ".tar", ".wim", ".swm", ".lzma", ".rar", ".cab", - ".arj", ".z", ".taz", ".cpio", ".rpm", ".deb", ".lzh", ".lha", - ".chm", ".chw", ".hxs", ".iso", ".msi", ".doc", ".xls", ".ppt", - ".dmg", ".xar", ".hfs", ".exe", ".ntfs", ".fat", ".vhd", ".mbr", - ".squashfs", ".cramfs", ".scap"] - - - #@NOTE: there are some more uncovered 7z formats - re_filelist = re.compile(r'([\d\:]+)\s+([\d\:]+)\s+([\w\.]+)\s+(\d+)\s+(\d+)\s+(.+)') - re_wrongpwd = re.compile(r'(Can not open encrypted archive|Wrong password)', re.I) - re_wrongcrc = re.compile(r'Encrypted\s+\=\s+\+', re.I) - re_version = re.compile(r'7-Zip\s(?:\[64\]\s)?(\d+\.\d+)', re.I) - - - @classmethod - def isUsable(cls): - if os.name == "nt": - cls.CMD = os.path.join(pypath, "7z.exe") - p = Popen([cls.CMD], stdout=PIPE, stderr=PIPE) - out,err = p.communicate() - else: - p = Popen([cls.CMD], stdout=PIPE, stderr=PIPE) - out, err = p.communicate() - - cls.VERSION = cls.re_version.search(out).group(1) - - return True - - - def check(self): - file = fs_encode(self.filename) - - p = self.call_cmd("t", file) - out, err = p.communicate() - - if p.returncode > 1: - raise CRCError(err) - - p = self.call_cmd("l", "-slt", file) - out, err = p.communicate() - - if p.returncode > 1: - raise ArchiveError(_("Process return code: %d") % p.returncode) - - # check if output or error macthes the 'wrong password'-Regexp - if self.re_wrongpwd.search(out): - raise PasswordError - - # check if output matches 'Encrypted = +' - if self.re_wrongcrc.search(out): - raise CRCError(_("Header protected")) - - - def isPassword(self, password): - p = self.call_cmd("l", fs_encode(self.filename), password=password) - p.communicate() - return p.returncode == 0 - - - def repair(self): - return False - - - def extract(self, password=None): - command = "x" if self.fullpath else "e" - - p = self.call_cmd(command, '-o' + self.out, fs_encode(self.filename), password=password) - - renice(p.pid, self.renice) - - # communicate and retrieve stderr - self._progress(p) - err = p.stderr.read().strip() - - if err: - if self.re_wrongpwd.search(err): - raise PasswordError - - elif self.re_wrongcrc.search(err): - raise CRCError(err) - - else: #: raise error if anything is on stderr - raise ArchiveError(err) - - if p.returncode > 1: - raise ArchiveError(_("Process return code: %d") % p.returncode) - - self.files = self.list(password) - - - def list(self, password=None): - command = "l" if self.fullpath else "l" - - p = self.call_cmd(command, fs_encode(self.filename), password=password) - out, err = p.communicate() - - if "Can not open" in err: - raise ArchiveError(_("Cannot open file")) - - if p.returncode > 1: - raise ArchiveError(_("Process return code: %d") % p.returncode) - - result = set() - for groups in self.re_filelist.findall(out): - f = groups[-1].strip() - result.add(save_join(self.out, f)) - - return list(result) - - - def call_cmd(self, command, *xargs, **kwargs): - args = [] - - #overwrite flag - if self.overwrite: - args.append("-y") - - #set a password - if "password" in kwargs and kwargs["password"]: - args.append("-p'%s'" % kwargs["password"]) - else: - args.append("-p-") - - #@NOTE: return codes are not reliable, some kind of threading, cleanup whatever issue - call = [self.CMD, command] + args + list(xargs) - - self.manager.logDebug(" ".join(call)) - - p = Popen(call, stdout=PIPE, stderr=PIPE) - return p diff --git a/module/plugins/internal/SimpleCrypter.py b/module/plugins/internal/SimpleCrypter.py deleted file mode 100644 index dc34f864f..000000000 --- a/module/plugins/internal/SimpleCrypter.py +++ /dev/null @@ -1,157 +0,0 @@ -# -*- coding: utf-8 -*- - -import re - -from urlparse import urljoin, urlparse - -from pyload.plugin.Crypter import Crypter -from pyload.plugin.internal.SimpleHoster import SimpleHoster, create_getInfo, replace_patterns, set_cookies -from pyload.utils import fixup - - -class SimpleCrypter(Crypter, SimpleHoster): - __name__ = "SimpleCrypter" - __type__ = "crypter" - __version__ = "0.43" - - __pattern__ = r'^unmatchable$' - __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), #: Overrides core.config['general']['folder_per_package'] - ("subfolder_per_package", "bool", "Create a subfolder for each package", True)] - - __description__ = """Simple decrypter plugin""" - __license__ = "GPLv3" - __authors__ = [("stickell", "l.stickell@yahoo.it"), - ("zoidberg", "zoidberg@mujmail.cz"), - ("Walter Purcaro", "vuolter@gmail.com")] - - - """ - Following patterns should be defined by each crypter: - - LINK_PATTERN: Download link or regex to catch links in group(1) - example: LINK_PATTERN = r'