diff options
Diffstat (limited to 'module/plugins')
142 files changed, 1484 insertions, 1277 deletions
diff --git a/module/plugins/accounts/AlldebridCom.py b/module/plugins/accounts/AlldebridCom.py index 1f2371e28..c830f0c09 100644 --- a/module/plugins/accounts/AlldebridCom.py +++ b/module/plugins/accounts/AlldebridCom.py @@ -37,7 +37,7 @@ class AlldebridCom(Account): exp_data[1]) * 60 * 60 + (int(exp_data[2]) - 1) * 60 #Get expiration date from API - except: + except Exception: data = self.getAccountData(user) html = req.load("http://www.alldebrid.com/api.php", get={'action': "info_user", 'login': user, 'pw': data['password']}) diff --git a/module/plugins/accounts/CatShareNet.py b/module/plugins/accounts/CatShareNet.py index bcb14bee3..ec4d706ae 100644 --- a/module/plugins/accounts/CatShareNet.py +++ b/module/plugins/accounts/CatShareNet.py @@ -10,39 +10,44 @@ from module.plugins.Account import Account class CatShareNet(Account): __name__ = "CatShareNet" __type__ = "account" - __version__ = "0.02" + __version__ = "0.05" __description__ = """CatShareNet account plugin""" __license__ = "GPLv3" __authors__ = [("prOq", None)] - PREMIUM_PATTERN = r'class="nav-collapse collapse pull-right">[\s\w<>=-."/:]*\sz.</a></li>\s*<li><a href="/premium">.*\s*<span style="color: red">(.*?)</span>[\s\w<>/]*href="/logout"' - VALID_UNTIL_PATTERN = r'<div class="span6 pull-right">[\s\w<>=-":;]*<span style="font-size:13px;">.*?<strong>(.*?)</strong></span>' + PREMIUM_PATTERN = r'<a href="/premium">Konto:[\s\n]*Premium' + VALID_UNTIL_PATTERN = r'>Konto premium.*?<strong>(.*?)</strong></span>' + TRAFFIC_LEFT_PATTERN = r'<a href="/premium">([0-9.]+ [kMG]B)' def loadAccountInfo(self, user, req): - premium = False - validuntil = -1 + premium = False + validuntil = -1 + trafficleft = -1 html = req.load("http://catshare.net/", decode=True) + if re.search(self.PREMIUM_PATTERN, html): + premium = True + try: - m = re.search(self.PREMIUM_PATTERN, html) - if "Premium" in m.group(1): - premium = True - except: + expiredate = re.search(self.VALID_UNTIL_PATTERN, html).group(1) + self.logDebug("Expire date: " + expiredate) + + validuntil = mktime(strptime(expiredate, "%Y-%m-%d %H:%M:%S")) + + except Exception: pass try: - m = re.search(self.VALID_UNTIL_PATTERN, html) - expiredate = m.group(1) - if "-" not in expiredate: - validuntil = mktime(strptime(expiredate, "%d.%m.%Y")) - except: + trafficleft = self.parseTraffic(re.search(self.TRAFFIC_LEFT_PATTERN, html).group(1)) + + except Exception: pass - return {'premium': premium, 'trafficleft': -1, 'validuntil': validuntil} + return {'premium': premium, 'trafficleft': trafficleft, 'validuntil': validuntil} def login(self, user, data, req): diff --git a/module/plugins/accounts/ExashareCom.py b/module/plugins/accounts/ExashareCom.py new file mode 100644 index 000000000..431798522 --- /dev/null +++ b/module/plugins/accounts/ExashareCom.py @@ -0,0 +1,16 @@ +# -*- coding: utf-8 -*- + +from module.plugins.internal.XFSAccount import XFSAccount + + +class ExashareCom(XFSAccount): + __name__ = "ExashareCom" + __type__ = "account" + __version__ = "0.01" + + __description__ = """Exashare.com account plugin""" + __license__ = "GPLv3" + __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] + + + HOSTER_DOMAIN = "exashare.com" diff --git a/module/plugins/accounts/File4safeCom.py b/module/plugins/accounts/File4SafeCom.py index 50fe1aac8..50fe1aac8 100644 --- a/module/plugins/accounts/File4safeCom.py +++ b/module/plugins/accounts/File4SafeCom.py diff --git a/module/plugins/accounts/JunkyvideoCom.py b/module/plugins/accounts/JunkyvideoCom.py new file mode 100644 index 000000000..8275ff176 --- /dev/null +++ b/module/plugins/accounts/JunkyvideoCom.py @@ -0,0 +1,16 @@ +# -*- coding: utf-8 -*- + +from module.plugins.internal.XFSAccount import XFSAccount + + +class JunkyvideoCom(XFSAccount): + __name__ = "JunkyvideoCom" + __type__ = "account" + __version__ = "0.01" + + __description__ = """Junkyvideo.com account plugin""" + __license__ = "GPLv3" + __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] + + + HOSTER_DOMAIN = "junkyvideo.com" diff --git a/module/plugins/accounts/Keep2shareCc.py b/module/plugins/accounts/Keep2ShareCc.py index e855fb977..9f28799a2 100644 --- a/module/plugins/accounts/Keep2shareCc.py +++ b/module/plugins/accounts/Keep2ShareCc.py @@ -10,14 +10,15 @@ from module.plugins.Account import Account class Keep2ShareCc(Account): __name__ = "Keep2ShareCc" __type__ = "account" - __version__ = "0.04" + __version__ = "0.05" __description__ = """Keep2Share.cc account plugin""" __license__ = "GPLv3" - __authors__ = [("aeronaut", "aeronaut@pianoguy.de")] + __authors__ = [("aeronaut", "aeronaut@pianoguy.de"), + ("Walter Purcaro", "vuolter@gmail.com")] - VALID_UNTIL_PATTERN = r'Premium expires: <b>(.+?)</b>' + VALID_UNTIL_PATTERN = r'Premium expires:\s*<b>(.+?)<' TRAFFIC_LEFT_PATTERN = r'Available traffic \(today\):\s*<b><a href="/user/statistic.html">(.+?)<' LOGIN_FAIL_PATTERN = r'Please fix the following input errors' @@ -25,8 +26,8 @@ class Keep2ShareCc(Account): def loadAccountInfo(self, user, req): validuntil = None - trafficleft = None - premium = None + trafficleft = -1 + premium = False html = req.load("http://keep2share.cc/site/profile.html", decode=True) @@ -46,19 +47,15 @@ class Keep2ShareCc(Account): self.logError(e) else: - if validuntil > mktime(gmtime()): - premium = True - else: - premium = False - validuntil = None + premium = True if validuntil > mktime(gmtime()) else False - m = re.search(self.TRAFFIC_LEFT_PATTERN, html) - if m: - try: - trafficleft = self.parseTraffic(m.group(1)) + m = re.search(self.TRAFFIC_LEFT_PATTERN, html) + if m: + try: + trafficleft = self.parseTraffic(m.group(1)) - except Exception, e: - self.logError(e) + except Exception, e: + self.logError(e) return {'validuntil': validuntil, 'trafficleft': trafficleft, 'premium': premium} diff --git a/module/plugins/accounts/NetloadIn.py b/module/plugins/accounts/NetloadIn.py index 1abd7fa84..1abd7fa84 100755..100644 --- a/module/plugins/accounts/NetloadIn.py +++ b/module/plugins/accounts/NetloadIn.py diff --git a/module/plugins/accounts/NoPremiumPl.py b/module/plugins/accounts/NoPremiumPl.py index f2223b7d9..a36b114eb 100644 --- a/module/plugins/accounts/NoPremiumPl.py +++ b/module/plugins/accounts/NoPremiumPl.py @@ -35,7 +35,7 @@ class NoPremiumPl(Account): self._req = req try: result = loads(self.runAuthQuery()) - except: + except Exception: # todo: return or let it be thrown? return @@ -60,7 +60,7 @@ class NoPremiumPl(Account): try: response = loads(self.runAuthQuery()) - except: + except Exception: self.wrongPassword() if "errno" in response.keys(): diff --git a/module/plugins/accounts/RapideoPl.py b/module/plugins/accounts/RapideoPl.py index 438ce7ad3..426c680a6 100644 --- a/module/plugins/accounts/RapideoPl.py +++ b/module/plugins/accounts/RapideoPl.py @@ -35,7 +35,7 @@ class RapideoPl(Account): self._req = req try: result = loads(self.runAuthQuery()) - except: + except Exception: # todo: return or let it be thrown? return @@ -59,7 +59,7 @@ class RapideoPl(Account): self._req = req try: response = loads(self.runAuthQuery()) - except: + except Exception: self.wrongPassword() if "errno" in response.keys(): diff --git a/module/plugins/accounts/RapidgatorNet.py b/module/plugins/accounts/RapidgatorNet.py index b29d94228..a7aa6ce09 100644 --- a/module/plugins/accounts/RapidgatorNet.py +++ b/module/plugins/accounts/RapidgatorNet.py @@ -7,7 +7,7 @@ from module.common.json_layer import json_loads class RapidgatorNet(Account): __name__ = "RapidgatorNet" __type__ = "account" - __version__ = "0.06" + __version__ = "0.07" __description__ = """Rapidgator.net account plugin""" __license__ = "GPLv3" @@ -18,8 +18,13 @@ class RapidgatorNet(Account): def loadAccountInfo(self, user, req): + validuntil = None + trafficleft = None + premium = False + sid = None + try: - sid = self.getAccountData(user).get('SID') + sid = self.getAccountData(user).get('sid') assert sid json = req.load("%s/info?sid=%s" % (self.API_URL, sid)) @@ -30,15 +35,19 @@ class RapidgatorNet(Account): if "reset_in" in json['response']: self.scheduleRefresh(user, json['response']['reset_in']) - return {"validuntil": json['response']['expire_date'], - "trafficleft": float(json['response']['traffic_left']) / 1024, #@TODO: Remove `/ 1024` in 0.4.10 - "premium": True} + validuntil = json['response']['expire_date'], + trafficleft = float(json['response']['traffic_left']) / 1024, #@TODO: Remove `/ 1024` in 0.4.10 + premium = True else: self.logError(json['response_details']) + except Exception, e: self.logError(e) - return {"validuntil": None, "trafficleft": None, "premium": False} + return {'validuntil' : validuntil, + 'trafficleft': trafficleft + 'premium' : premium, + 'sid' : sid} def login(self, user, data, req): @@ -50,7 +59,7 @@ class RapidgatorNet(Account): json = json_loads(json) if json['response_status'] == 200: - data['SID'] = str(json['response']['session_id']) + data['sid'] = str(json['response']['session_id']) return else: self.logError(json['response_details']) diff --git a/module/plugins/accounts/RehostTo.py b/module/plugins/accounts/RehostTo.py index 897f888b0..04e71c9ad 100644 --- a/module/plugins/accounts/RehostTo.py +++ b/module/plugins/accounts/RehostTo.py @@ -18,13 +18,13 @@ class RehostTo(Account): trafficleft = None validuntil = -1 session = "" - + html = req.load("http://rehost.to/api.php", get={'cmd' : "login", 'user': user, 'pass': self.getAccountData(user)['password']}) try: session = html.split(",")[1].split("=")[1] - + html = req.load("http://rehost.to/api.php", get={'cmd': "get_premium_credits", 'long_ses': session}) @@ -32,11 +32,11 @@ class RehostTo(Account): self.logDebug(html) else: traffic, valid = html.split(",") - + premium = True trafficleft = self.parseTraffic(traffic + "MB") validuntil = float(valid) - + finally: return {'premium' : premium, 'trafficleft': trafficleft, diff --git a/module/plugins/accounts/ShareonlineBiz.py b/module/plugins/accounts/ShareonlineBiz.py index 3ee6e04af..7e05e2e76 100644 --- a/module/plugins/accounts/ShareonlineBiz.py +++ b/module/plugins/accounts/ShareonlineBiz.py @@ -8,7 +8,7 @@ from module.plugins.Account import Account class ShareonlineBiz(Account): __name__ = "ShareonlineBiz" __type__ = "account" - __version__ = "0.30" + __version__ = "0.31" __description__ = """Share-online.biz account plugin""" __license__ = "GPLv3" @@ -40,7 +40,7 @@ class ShareonlineBiz(Account): if api['a'].lower() != "not_available": req.cj.setCookie("share-online.biz", 'a', api['a']) - premium = api['group'] == "Premium" + premium = api['group'] in ("Premium", "PrePaid") validuntil = float(api['expire_date']) @@ -51,7 +51,10 @@ class ShareonlineBiz(Account): maxtraffic /= 1024 #@TODO: Remove `/ 1024` in 0.4.10 trafficleft /= 1024 #@TODO: Remove `/ 1024` in 0.4.10 - return {'premium': premium, 'validuntil': validuntil, 'trafficleft': trafficleft, 'maxtraffic': maxtraffic} + return {'premium' : premium, + 'validuntil' : validuntil, + 'trafficleft': trafficleft, + 'maxtraffic' : maxtraffic} def login(self, user, data, req): diff --git a/module/plugins/accounts/ZeveraCom.py b/module/plugins/accounts/ZeveraCom.py index 6c69a974f..15b6d9379 100644 --- a/module/plugins/accounts/ZeveraCom.py +++ b/module/plugins/accounts/ZeveraCom.py @@ -8,7 +8,7 @@ from module.plugins.Account import Account class ZeveraCom(Account): __name__ = "ZeveraCom" __type__ = "account" - __version__ = "0.24" + __version__ = "0.25" __description__ = """Zevera.com account plugin""" __license__ = "GPLv3" @@ -39,7 +39,7 @@ class ZeveraCom(Account): api = self.api_response(req) - if api != "No trafic": + if "No trafic" not in api or "Expired" not in api: validuntil = mktime(strptime(api['endsubscriptiondate'], "%Y/%m/%d %H:%M:%S")) trafficleft = float(api['availabletodaytraffic']) * 1024 if api['orondaytrafficlimit'] != '0' else -1 premium = True diff --git a/module/plugins/captcha/LinksaveIn.py b/module/plugins/captcha/LinksaveIn.py index 56cbd58a0..de6b0e7ff 100644 --- a/module/plugins/captcha/LinksaveIn.py +++ b/module/plugins/captcha/LinksaveIn.py @@ -79,7 +79,7 @@ class LinksaveIn(OCR): rgb_c = lut[pix[x, y]] try: cstat[rgb_c] += 1 - except: + except Exception: cstat[rgb_c] = 1 if rgb_bg == rgb_c: stat[bgpath] += 1 diff --git a/module/plugins/captcha/captcha.py b/module/plugins/captcha/captcha.py index 0f233ec00..e89ec2e81 100644 --- a/module/plugins/captcha/captcha.py +++ b/module/plugins/captcha/captcha.py @@ -102,7 +102,7 @@ class OCR(object): try: with open(tmpTxt.name, 'r') as f: self.result_captcha = f.read().replace("\n", "") - except: + except Exception: self.result_captcha = "" self.logger.debug(self.result_captcha) @@ -111,7 +111,7 @@ class OCR(object): os.remove(tmpTxt.name) if subset and (digits or lowercase or uppercase): os.remove(tmpSub.name) - except: + except Exception: pass @@ -166,7 +166,7 @@ class OCR(object): count += 1 if pixels[x, y-1] != 255: count += 1 - except: + except Exception: pass # not enough neighbors are dark pixels so mark this pixel diff --git a/module/plugins/container/CCF.py b/module/plugins/container/CCF.py index bca535175..c6e642cca 100644 --- a/module/plugins/container/CCF.py +++ b/module/plugins/container/CCF.py @@ -16,9 +16,9 @@ from module.utils import save_join class CCF(Container): __name__ = "CCF" - __version__ = "0.20" + __version__ = "0.21" - __pattern__ = r'.+\.ccf' + __pattern__ = r'.+\.ccf$' __description__ = """CCF container decrypter plugin""" __license__ = "GPLv3" diff --git a/module/plugins/container/DLC.py b/module/plugins/container/DLC.py new file mode 100644 index 000000000..53349c5c7 --- /dev/null +++ b/module/plugins/container/DLC.py @@ -0,0 +1,71 @@ +# -*- coding: utf-8 -*- + +from __future__ import with_statement + +import re +import xml.dom.minidom + +from base64 import standard_b64decode +from Crypto.Cipher import AES + +from module.plugins.Container import Container +from module.utils import decode + + +class DLC(Container): + __name__ = "DLC" + __version__ = "0.22" + __pattern__ = r'.+\.dlc$' + + __description__ = """DLC container decrypter plugin""" + __license__ = "GPLv3" + __authors__ = [("RaNaN", "RaNaN@pyload.org"), + ("spoob", "spoob@pyload.org"), + ("mkaay", "mkaay@mkaay.de"), + ("Schnusch", "Schnusch@users.noreply.github.com"), + ("Walter Purcaro", "vuolter@gmail.com")] + + + def setup(self): + self.key = "cb99b5cbc24db398" + self.iv = "9bc24cb995cb8db3" + self.api_url = "http://service.jdownloader.org/dlcrypt/service.php?srcType=dlc&destType=pylo&data=" + + + def decrypt(self, pyfile): + with open(pyfile.url.replace("\n", "")) as dlc: + data = dlc.read().strip() + + data += '=' * (-len(data) % 4) + + dlckey = data[-88:] + dlcdata = data[:-88] + dlcdata = standard_b64decode(dlcdata) + + rc = self.load(self.api_url + dlckey) + rc = re.search(r'<rc>(.+)</rc>', rc).group(1) + rc = standard_b64decode(rc) + + obj = AES.new(self.key, AES.MODE_CBC, self.iv) + dlckey = obj.decrypt(rc) + obj = AES.new(dlckey, AES.MODE_CBC, dlckey) + + self.data = standard_b64decode(obj.decrypt(dlcdata)) + self.packages = [(entry[0] if entry[0] else pyfile.name, entry[1], entry[0] if entry[0] else pyfile.name) \ + for entry in self.getPackages()] + + + def getPackages(self): + root = xml.dom.minidom.parseString(self.data).documentElement + content = root.getElementsByTagName("content")[0] + return self.parsePackages(content) + + + def parsePackages(self, startNode): + return [(standard_b64decode(decode(node.getAttribute("name"))), self.parseLinks(node)) \ + for node in startNode.getElementsByTagName("package")] + + + def parseLinks(self, startNode): + return [standard_b64decode(node.getElementsByTagName("url")[0].firstChild.data) \ + for node in startNode.getElementsByTagName("file")] diff --git a/module/plugins/container/DLC_25.pyc b/module/plugins/container/DLC_25.pyc Binary files differdeleted file mode 100644 index b8fde0051..000000000 --- a/module/plugins/container/DLC_25.pyc +++ /dev/null diff --git a/module/plugins/container/DLC_26.pyc b/module/plugins/container/DLC_26.pyc Binary files differdeleted file mode 100644 index 41a4e0cb8..000000000 --- a/module/plugins/container/DLC_26.pyc +++ /dev/null diff --git a/module/plugins/container/DLC_27.pyc b/module/plugins/container/DLC_27.pyc Binary files differdeleted file mode 100644 index a6bffaf74..000000000 --- a/module/plugins/container/DLC_27.pyc +++ /dev/null diff --git a/module/plugins/container/LinkList.py b/module/plugins/container/LinkList.py index c6173ad73..9c76c4341 100644 --- a/module/plugins/container/LinkList.py +++ b/module/plugins/container/LinkList.py @@ -8,9 +8,9 @@ from module.utils import fs_encode class LinkList(Container): __name__ = "LinkList" - __version__ = "0.12" + __version__ = "0.13" - __pattern__ = r'.+\.txt' + __pattern__ = r'.+\.txt$' __config__ = [("clear", "bool", "Clear Linklist after adding", False), ("encoding", "string", "File encoding (default utf-8)", "")] @@ -23,7 +23,7 @@ class LinkList(Container): def decrypt(self, pyfile): try: file_enc = codecs.lookup(self.getConfig("encoding")).name - except: + except Exception: file_enc = "utf-8" file_name = fs_encode(pyfile.url) @@ -64,7 +64,7 @@ class LinkList(Container): try: txt = open(file_name, 'wb') txt.close() - except: + except Exception: self.logWarning(_("LinkList could not be cleared")) for name, links in packages.iteritems(): diff --git a/module/plugins/container/RSDF.py b/module/plugins/container/RSDF.py index 0c43f0e6c..0c36293ec 100644 --- a/module/plugins/container/RSDF.py +++ b/module/plugins/container/RSDF.py @@ -12,9 +12,9 @@ from module.utils import fs_encode class RSDF(Container): __name__ = "RSDF" - __version__ = "0.24" + __version__ = "0.25" - __pattern__ = r'.+\.rsdf' + __pattern__ = r'.+\.rsdf$' __description__ = """RSDF container decrypter plugin""" __license__ = "GPLv3" @@ -39,7 +39,7 @@ class RSDF(Container): with open(infile, 'r') as rsdf: data = rsdf.read() except IOError, e: - self.fail(str(e)) + self.fail(e) if re.search(r"<title>404 - Not Found</title>", data) is None: data = binascii.unhexlify(''.join(data.split())) diff --git a/module/plugins/crypter/C1neonCom.py b/module/plugins/crypter/C1NeonCom.py index 926633ff7..926633ff7 100644 --- a/module/plugins/crypter/C1neonCom.py +++ b/module/plugins/crypter/C1NeonCom.py diff --git a/module/plugins/crypter/ChipDe.py b/module/plugins/crypter/ChipDe.py index 133e5a005..2fc36c355 100644 --- a/module/plugins/crypter/ChipDe.py +++ b/module/plugins/crypter/ChipDe.py @@ -22,7 +22,7 @@ class ChipDe(Crypter): self.html = self.load(pyfile.url) try: f = re.search(r'"(http://video\.chip\.de/.+)"', self.html) - except: + except Exception: self.fail(_("Failed to find the URL")) else: self.urls = [f.group(1)] diff --git a/module/plugins/crypter/CloudzillaToFolder.py b/module/plugins/crypter/CloudzillaToFolder.py index c156d4de4..76019d928 100644 --- a/module/plugins/crypter/CloudzillaToFolder.py +++ b/module/plugins/crypter/CloudzillaToFolder.py @@ -10,7 +10,7 @@ from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo class CloudzillaToFolder(SimpleHoster): __name__ = "CloudzillaToFolder" __type__ = "crypter" - __version__ = "0.01" + __version__ = "0.02" __pattern__ = r'http://(?:www\.)?cloudzilla\.to/share/folder/(?P<ID>[\w^_]+)' @@ -36,8 +36,4 @@ class CloudzillaToFolder(SimpleHoster): self.retry(reason="Wrong password") - def getLinks(self): - return [urljoin("http://www.cloudzilla.to", link) for link in super(CloudzillaToFolder, self).getLinks()] - - getInfo = create_getInfo(CloudzillaToFolder) diff --git a/module/plugins/crypter/DevhostStFolder.py b/module/plugins/crypter/DevhostStFolder.py index 5ac9d4faf..8779cae5e 100644 --- a/module/plugins/crypter/DevhostStFolder.py +++ b/module/plugins/crypter/DevhostStFolder.py @@ -13,7 +13,7 @@ from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo class DevhostStFolder(SimpleCrypter): __name__ = "DevhostStFolder" __type__ = "crypter" - __version__ = "0.03" + __version__ = "0.04" __pattern__ = r'http://(?:www\.)?d-h\.st/users/(?P<USER>\w+)(/\?fld_id=(?P<ID>\d+))?' __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), @@ -54,8 +54,4 @@ class DevhostStFolder(SimpleCrypter): return {'name': name, 'folder': folder} - def getLinks(self): - return [urljoin("http://d-h.st", link) for link in re.findall(self.LINK_PATTERN, self.html)] - - getInfo = create_getInfo(DevhostStFolder) diff --git a/module/plugins/crypter/EasybytezComFolder.py b/module/plugins/crypter/EasybytezComFolder.py index 04f9b853b..6c643e83f 100644 --- a/module/plugins/crypter/EasybytezComFolder.py +++ b/module/plugins/crypter/EasybytezComFolder.py @@ -17,8 +17,6 @@ class EasybytezComFolder(XFSCrypter): __authors__ = [("stickell", "l.stickell@yahoo.it")] - HOSTER_DOMAIN = "easybytez.com" - LOGIN_ACCOUNT = True diff --git a/module/plugins/crypter/FilecryptCc.py b/module/plugins/crypter/FilecryptCc.py index af31dc743..096fd414d 100644 --- a/module/plugins/crypter/FilecryptCc.py +++ b/module/plugins/crypter/FilecryptCc.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- - +# http://filecrypt.cc/Container/64E039F859.html import base64 import binascii import re @@ -14,7 +14,7 @@ from module.plugins.internal.CaptchaService import ReCaptcha class FilecryptCc(Crypter): __name__ = "FilecryptCc" __type__ = "crypter" - __version__ = "0.09" + __version__ = "0.11" __pattern__ = r'https?://(?:www\.)?filecrypt\.cc/Container/\w+' @@ -108,20 +108,21 @@ class FilecryptCc(Crypter): post={'button.x': captcha_code[0], 'button.y': captcha_code[1]}, cookies=True, decode=True) + else: recaptcha = ReCaptcha(self) captcha_key = recaptcha.detect_key() if captcha_key: - self.siteWithLinks = self.load(self.pyfile.url, - post={'g-recaptcha-response': recaptcha.challenge(captcha_key, True)}, - cookies=True, - decode=True) + response, challenge = recaptcha.challenge(captcha_key) + self.siteWithLinks = self.load(self.pyfile.url, + post={'g-recaptcha-response': response}, + decode=True) else: - self.logDebug("No captcha found") + self.logInfo(_("No captcha found")) self.siteWithLinks = self.html - if "recaptcha_image" in self.siteWithLinks: + if "recaptcha_image" in self.siteWithLinks or "data-sitekey" in self.siteWithLinks: self.invalidCaptcha() self.retry() diff --git a/module/plugins/crypter/Go4UpCom.py b/module/plugins/crypter/Go4UpCom.py index 102bc32b5..a7e16c0ab 100644 --- a/module/plugins/crypter/Go4UpCom.py +++ b/module/plugins/crypter/Go4UpCom.py @@ -40,7 +40,7 @@ class Go4UpCom(SimpleCrypter): for html in pages: try: links.append(re.search(r'<b><a href="(.+?)"', html).group(1)) - except: + except Exception: continue return links diff --git a/module/plugins/crypter/JunocloudMeFolder.py b/module/plugins/crypter/JunocloudMeFolder.py deleted file mode 100644 index 990f25902..000000000 --- a/module/plugins/crypter/JunocloudMeFolder.py +++ /dev/null @@ -1,23 +0,0 @@ -# -*- coding: utf-8 -*- - -from module.plugins.internal.XFSCrypter import XFSCrypter, create_getInfo - - -class JunocloudMeFolder(XFSCrypter): - __name__ = "JunocloudMeFolder" - __type__ = "crypter" - __version__ = "0.03" - - __pattern__ = r'http://(?:www\.)?junocloud\.me/folders/(?P<ID>\d+/\w+)' - __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), - ("subfolder_per_package", "bool", "Create a subfolder for each package", True)] - - __description__ = """Junocloud.me folder decrypter plugin""" - __license__ = "GPLv3" - __authors__ = [("guidobelix", "guidobelix@hotmail.it")] - - - HOSTER_DOMAIN = "junocloud.me" - - -getInfo = create_getInfo(JunocloudMeFolder) diff --git a/module/plugins/crypter/LinkCryptWs.py b/module/plugins/crypter/LinkCryptWs.py index 996a92c7b..c67372e3d 100644 --- a/module/plugins/crypter/LinkCryptWs.py +++ b/module/plugins/crypter/LinkCryptWs.py @@ -279,7 +279,7 @@ class LinkCryptWs(Crypter): (vcrypted, vjk) = self._getCipherParams(cnl_section) for (crypted, jk) in zip(vcrypted, vjk): package_links.extend(self._getLinks(crypted, jk)) - except: + except Exception: self.logError(_("Unable to decrypt CNL links (JS Error) try to get over links")) return self.handleWebLinks() diff --git a/module/plugins/crypter/MegaCoNzFolder.py b/module/plugins/crypter/MegaCoNzFolder.py index bec4eba22..954bfb9a5 100644 --- a/module/plugins/crypter/MegaCoNzFolder.py +++ b/module/plugins/crypter/MegaCoNzFolder.py @@ -29,4 +29,4 @@ class MegaCoNzFolder(Crypter): self.urls = re.findall(r'(https://mega.co.nz/#N!.+?)<', self.html) if not self.urls: #@TODO: Remove in 0.4.10 - self.fail("No link grabbed") + self.fail(_("No link grabbed")) diff --git a/module/plugins/crypter/Movie2kTo.py b/module/plugins/crypter/Movie2KTo.py index 76bf702ac..76bf702ac 100644 --- a/module/plugins/crypter/Movie2kTo.py +++ b/module/plugins/crypter/Movie2KTo.py diff --git a/module/plugins/crypter/NCryptIn.py b/module/plugins/crypter/NCryptIn.py index 8b7214157..f75f6d484 100644 --- a/module/plugins/crypter/NCryptIn.py +++ b/module/plugins/crypter/NCryptIn.py @@ -13,7 +13,7 @@ from module.plugins.internal.CaptchaService import ReCaptcha class NCryptIn(Crypter): __name__ = "NCryptIn" __type__ = "crypter" - __version__ = "1.33" + __version__ = "1.34" __pattern__ = r'http://(?:www\.)?ncrypt\.in/(?P<TYPE>folder|link|frame)-([^/\?]+)' __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), @@ -156,7 +156,7 @@ class NCryptIn(Crypter): captcha_key = re.search(r'\?k=(.*?)"', form).group(1) self.logDebug("Resolving ReCaptcha with key [%s]" % captcha_key) recaptcha = ReCaptcha(self) - challenge, response = recaptcha.challenge(captcha_key) + response, challenge = recaptcha.challenge(captcha_key) postData['recaptcha_challenge_field'] = challenge postData['recaptcha_response_field'] = response @@ -205,7 +205,7 @@ class NCryptIn(Crypter): elif link_source_type == "web": return self.handleWebLinks() else: - self.error('Unknown source type "%s" (this is probably a bug)' % link_source_type) + self.error(_('Unknown source type "%s"') % link_source_type) def handleSingleLink(self): @@ -229,7 +229,7 @@ class NCryptIn(Crypter): (vcrypted, vjk) = self._getCipherParams() for (crypted, jk) in zip(vcrypted, vjk): package_links.extend(self._getLinks(crypted, jk)) - except: + except Exception: self.fail(_("Unable to decrypt CNL2 links")) return package_links diff --git a/module/plugins/crypter/OronComFolder.py b/module/plugins/crypter/OronComFolder.py index 9e06bdf32..9e06bdf32 100755..100644 --- a/module/plugins/crypter/OronComFolder.py +++ b/module/plugins/crypter/OronComFolder.py diff --git a/module/plugins/crypter/RapidfileshareNetFolder.py b/module/plugins/crypter/RapidfileshareNetFolder.py deleted file mode 100644 index fc3d4241e..000000000 --- a/module/plugins/crypter/RapidfileshareNetFolder.py +++ /dev/null @@ -1,23 +0,0 @@ -# -*- coding: utf-8 -*- - -from module.plugins.internal.XFSCrypter import XFSCrypter, create_getInfo - - -class RapidfileshareNetFolder(XFSCrypter): - __name__ = "RapidfileshareNetFolder" - __type__ = "crypter" - __version__ = "0.03" - - __pattern__ = r'http://(?:www\.)?rapidfileshare\.net/users/\w+/\d+/\w+' - __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), - ("subfolder_per_package", "bool", "Create a subfolder for each package", True)] - - __description__ = """Rapidfileshare.net folder decrypter plugin""" - __license__ = "GPLv3" - __authors__ = [("guidobelix", "guidobelix@hotmail.it")] - - - HOSTER_DOMAIN = "rapidfileshare.net" - - -getInfo = create_getInfo(RapidfileshareNetFolder) diff --git a/module/plugins/crypter/RelinkUs.py b/module/plugins/crypter/RelinkUs.py index c5a3f1011..a6014c866 100644 --- a/module/plugins/crypter/RelinkUs.py +++ b/module/plugins/crypter/RelinkUs.py @@ -191,7 +191,7 @@ class RelinkUs(Crypter): elif source == 'web': return self.handleWEBLinks() else: - self.error('Unknown source type "%s" (this is probably a bug)' % source) + self.error(_('Unknown source type "%s"') % source) def handleCNL2Links(self): @@ -204,7 +204,7 @@ class RelinkUs(Crypter): (vcrypted, vjk) = self._getCipherParams(cnl2_form) for (crypted, jk) in zip(vcrypted, vjk): package_links.extend(self._getLinks(crypted, jk)) - except: + except Exception: self.logDebug("Unable to decrypt CNL2 links") return package_links @@ -223,8 +223,10 @@ class RelinkUs(Crypter): with open(dlc_filepath, "wb") as f: f.write(dlc) package_links.append(dlc_filepath) - except: - self.fail("Unable to download DLC container") + + except Exception: + self.fail(_("Unable to download DLC container")) + return package_links diff --git a/module/plugins/crypter/SafelinkingNet.py b/module/plugins/crypter/SafelinkingNet.py index a56a0a44c..8e46e1e41 100644 --- a/module/plugins/crypter/SafelinkingNet.py +++ b/module/plugins/crypter/SafelinkingNet.py @@ -14,7 +14,7 @@ from module.plugins.internal.CaptchaService import SolveMedia class SafelinkingNet(Crypter): __name__ = "SafelinkingNet" __type__ = "crypter" - __version__ = "0.13" + __version__ = "0.14" __pattern__ = r'https?://(?:www\.)?safelinking\.net/([pd])/\w+' __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), @@ -57,7 +57,7 @@ class SafelinkingNet(Crypter): else: self.fail(_("Error parsing captcha")) - challenge, response = captcha.challenge(captchaKey) + response, challenge = captcha.challenge(captchaKey) postData['adcopy_challenge'] = challenge postData['adcopy_response'] = response diff --git a/module/plugins/crypter/ShareLinksBiz.py b/module/plugins/crypter/ShareLinksBiz.py index d2e8138f6..df53b5879 100644 --- a/module/plugins/crypter/ShareLinksBiz.py +++ b/module/plugins/crypter/ShareLinksBiz.py @@ -235,7 +235,7 @@ class ShareLinksBiz(Crypter): try: (crypted, jk) = self._getCipherParams() package_links.extend(self._getLinks(crypted, jk)) - except: + except Exception: self.fail(_("Unable to decrypt CNL2 links")) return package_links diff --git a/module/plugins/crypter/TusfilesNetFolder.py b/module/plugins/crypter/TusfilesNetFolder.py index 20bed0ab1..cb8efc9a8 100644 --- a/module/plugins/crypter/TusfilesNetFolder.py +++ b/module/plugins/crypter/TusfilesNetFolder.py @@ -22,8 +22,6 @@ class TusfilesNetFolder(XFSCrypter): ("stickell", "l.stickell@yahoo.it")] - HOSTER_DOMAIN = "tusfiles.net" - PAGES_PATTERN = r'>\((\d+) \w+\)<' URL_REPLACEMENTS = [(__pattern__ + ".*", r'https://www.tusfiles.net/go/\g<ID>/')] diff --git a/module/plugins/hooks/AndroidPhoneNotify.py b/module/plugins/hooks/AndroidPhoneNotify.py index 18e1cce66..fbc2acd5c 100644 --- a/module/plugins/hooks/AndroidPhoneNotify.py +++ b/module/plugins/hooks/AndroidPhoneNotify.py @@ -9,7 +9,7 @@ from module.plugins.Hook import Hook class AndroidPhoneNotify(Hook): __name__ = "AndroidPhoneNotify" __type__ = "hook" - __version__ = "0.02" + __version__ = "0.03" __config__ = [("apikey" , "str" , "API key" , "" ), ("notifycaptcha" , "bool", "Notify captcha request" , True ), @@ -51,7 +51,7 @@ class AndroidPhoneNotify(Hook): self.notify(_("Package finished"), pypack.name) - def allDownloadsProcessed(self, thread): + def allDownloadsProcessed(self): if not self.getConfig("notifyprocessed"): return False diff --git a/module/plugins/hooks/Captcha9kw.py b/module/plugins/hooks/Captcha9Kw.py index 600694e78..600694e78 100755..100644 --- a/module/plugins/hooks/Captcha9kw.py +++ b/module/plugins/hooks/Captcha9Kw.py diff --git a/module/plugins/hooks/ClickAndLoad.py b/module/plugins/hooks/ClickAndLoad.py index 222310c25..94a240d4c 100644 --- a/module/plugins/hooks/ClickAndLoad.py +++ b/module/plugins/hooks/ClickAndLoad.py @@ -18,10 +18,55 @@ def forward(source, destination): destination.shutdown(socket.SHUT_WR) +#: socket.create_connection wrapper for python 2.5 +def create_connection(address, timeout=object(), source_address=None): + try: + return socket.create_connection(address, + socket._GLOBAL_DEFAULT_TIMEOUT if type(timeout) == object else timeout, + source_address) + + except SyntaxError: + """Connect to *address* and return the socket object. + + Convenience function. Connect to *address* (a 2-tuple ``(host, + port)``) and return the socket object. Passing the optional + *timeout* parameter will set the timeout on the socket instance + before attempting to connect. If no *timeout* is supplied, the + global default timeout setting returned by :func:`getdefaulttimeout` + is used. If *source_address* is set it must be a tuple of (host, port) + for the socket to bind as a source address before making the connection. + An host of \'\' or port 0 tells the OS to use the default. + """ + + host, port = address + err = None + for res in getaddrinfo(host, port, 0, SOCK_STREAM): + af, socktype, proto, canonname, sa = res + sock = None + try: + sock = socket(af, socktype, proto) + if type(timeout) != object: + sock.settimeout(timeout) + if source_address: + sock.bind(source_address) + sock.connect(sa) + return sock + + except socket.error, _: + err = _ + if sock is not None: + sock.close() + + if err is not None: + raise err + else: + raise socket.error("getaddrinfo returns an empty list") + + class ClickAndLoad(Hook): __name__ = "ClickAndLoad" __type__ = "hook" - __version__ = "0.26" + __version__ = "0.31" __config__ = [("activated", "bool", "Activated" , True ), ("port" , "int" , "Port" , 9666 ), @@ -46,7 +91,7 @@ class ClickAndLoad(Hook): @threaded def proxy(self, ip, webport, cnlport): - hookManager.startThread(self.server, ip, webport, cnlport) + self.manager.startThread(self.server, ip, webport, cnlport) lock = Lock() lock.acquire() lock.acquire() @@ -62,14 +107,13 @@ class ClickAndLoad(Hook): while True: server_socket = dock_socket.accept()[0] - client_socket = socket.create_connection(("127.0.0.1", webport)) + client_socket = create_connection(("127.0.0.1", webport)) - hookManager.startThread(forward, server_socket, client_socket) - hookManager.startThread(forward, client_socket, server_socket) + self.manager.startThread(forward, server_socket, client_socket) + self.manager.startThread(forward, client_socket, server_socket) except socket.error, e: self.logError(e) - self.server(ip, webport, cnlport) finally: dock_socket.close() diff --git a/module/plugins/hooks/DeathByCaptcha.py b/module/plugins/hooks/DeathByCaptcha.py index 050b6fe15..d513c446d 100644 --- a/module/plugins/hooks/DeathByCaptcha.py +++ b/module/plugins/hooks/DeathByCaptcha.py @@ -135,7 +135,7 @@ class DeathByCaptcha(Hook): def submit(self, captcha, captchaType="file", match=None): - #workaround multipart-post bug in HTTPRequest.py + #@NOTE: Workaround multipart-post bug in HTTPRequest.py if re.match("^\w*$", self.getConfig("passkey")): multipart = True data = (FORM_FILE, captcha) diff --git a/module/plugins/hooks/ExternalScripts.py b/module/plugins/hooks/ExternalScripts.py index fc0cae44f..b2b4548a2 100644 --- a/module/plugins/hooks/ExternalScripts.py +++ b/module/plugins/hooks/ExternalScripts.py @@ -13,7 +13,7 @@ from module.utils import save_join class ExternalScripts(Hook): __name__ = "ExternalScripts" __type__ = "hook" - __version__ = "0.26" + __version__ = "0.27" __config__ = [("activated", "bool", "Activated", True)] @@ -59,7 +59,7 @@ class ExternalScripts(Hook): if not exists(path): try: makedirs(path) - except: + except Exception: self.logDebug("Script folder %s not created" % folder) return @@ -136,11 +136,11 @@ class ExternalScripts(Hook): self.callScript(script) - def allDownloadsFinished(self, thread): + def allDownloadsFinished(self): for script in chain(self.scripts['all_downloads_finished'], self.scripts['all_dls_finished']): self.callScript(script) - def allDownloadsProcessed(self, thread): + def allDownloadsProcessed(self): for script in chain(self.scripts['all_downloads_processed'], self.scripts['all_dls_processed']): self.callScript(script) diff --git a/module/plugins/hooks/ExtractArchive.py b/module/plugins/hooks/ExtractArchive.py index 2e9efa2b0..5c4e9bc82 100644 --- a/module/plugins/hooks/ExtractArchive.py +++ b/module/plugins/hooks/ExtractArchive.py @@ -6,8 +6,6 @@ import os import sys from copy import copy -from os import remove, chmod, makedirs -from os.path import exists, basename, isfile, isdir from traceback import print_exc # monkey patch bug in python 2.6 and lower @@ -47,18 +45,17 @@ if sys.version_info < (2, 7) and os.name != "nt": if os.name != "nt": from grp import getgrnam - from os import chown from pwd import getpwnam from module.plugins.Hook import Hook, threaded, Expose from module.plugins.internal.Extractor import ArchiveError, CRCError, PasswordError -from module.utils import save_join, uniqify +from module.utils import fs_decode, save_join, uniqify class ExtractArchive(Hook): __name__ = "ExtractArchive" __type__ = "hook" - __version__ = "1.03" + __version__ = "1.10" __config__ = [("activated" , "bool" , "Activated" , True ), ("fullpath" , "bool" , "Extract full path" , True ), @@ -77,7 +74,9 @@ class ExtractArchive(Hook): __description__ = """Extract different kind of archives""" __license__ = "GPLv3" - __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] + __authors__ = [("RaNaN", "ranan@pyload.org"), + ("AndroKev", ""), + ("Walter Purcaro", "vuolter@gmail.com")] event_list = ["allDownloadsProcessed"] @@ -93,17 +92,18 @@ class ExtractArchive(Hook): def setup(self): - self.plugins = [] - self.passwords = [] - names = [] + self.interval = 300 + self.extractors = [] + self.passwords = [] + names = [] for p in ("UnRar", "SevenZip", "UnZip"): try: module = self.core.pluginManager.loadModule("internal", p) klass = getattr(module, p) if klass.checkDeps(): names.append(p) - self.plugins.append(klass) + self.extractors.append(klass) except OSError, e: if e.errno == 2: @@ -123,66 +123,48 @@ class ExtractArchive(Hook): else: self.logInfo(_("No Extract plugins activated")) - # queue with package ids - self.queue = [] - def periodical(self): - if not self.queue or self.extracting: - return - - local = copy(self.queue) - self.queue[:] = [] - - self.extractPackages(*local) + if not self.extracting: + self.extractPackage(*self.getQueue()) @Expose - def extractPackage(self, id): - """ Extract package wrapper""" - self.extractPackages(id) - - - @Expose - def extractPackages(self, *ids): + def extractPackage(self, *ids): """ Extract packages with given id""" self.manager.startThread(self.extract, ids) def packageFinished(self, pypack): - if self.getConfig("queue") or self.extracting: + if self.extracting or self.getConfig("queue"): self.logInfo(_("Package %s queued for later extracting") % pypack.name) - self.queue.append(pypack.id) + self.addToQueue(pypack.id) else: self.extractPackage(pypack.id) @threaded - def allDownloadsProcessed(self, thread): - local = copy(self.queue) - self.queue[:] = [] - - if self.extract(local): #: check only if all gone fine, no failed reporting for now + def allDownloadsProcessed(self): + if self.extract(self.getQueue()): #@NOTE: check only if all gone fine, no failed reporting for now self.manager.dispatchEvent("all_archives_extracted") self.manager.dispatchEvent("all_archives_processed") def extract(self, ids): - self.extracting = True - processed = [] extracted = [] failed = [] - clearlist = lambda string: [x.lstrip('.') for x in string.replace(' ', '').replace(',', '|').replace(';', '|').split('|')] + clearList = lambda string: [x.lstrip('.') for x in string.replace(' ', '').replace(',', '|').replace(';', '|').split('|')] destination = self.getConfig("destination") subfolder = self.getConfig("subfolder") fullpath = self.getConfig("fullpath") overwrite = self.getConfig("overwrite") - extensions = clearlist(self.getConfig("extensions")) - excludefiles = clearlist(self.getConfig("excludefiles")) + extensions = clearList(self.getConfig("extensions")) + excludefiles = clearList(self.getConfig("excludefiles")) + excludefiles = self.getConfig("excludefiles") renice = self.getConfig("renice") recursive = self.getConfig("recursive") delete = self.getConfig("delete") @@ -197,25 +179,27 @@ class ExtractArchive(Hook): # dl folder dl = self.config['general']['download_folder'] - #iterate packages -> plugins -> targets + #iterate packages -> extractors -> targets for pid in ids: - p = self.core.files.getPackage(pid) - self.logInfo(_("Check package: %s") % p.name) - if not p: + pypack = self.core.files.getPackage(pid) + + self.logInfo(_("Check package: %s") % pypack.name) + + if not pypack: continue # determine output folder - out = save_join(dl, p.folder, destination, "") #: force trailing slash + out = save_join(dl, pypack.folder, destination, "") #: force trailing slash if subfolder: - out = save_join(out, p.folder) + out = save_join(out, pypack.folder) - if not exists(out): - makedirs(out) + if not os.path.exists(out): + os.makedirs(out) - files_ids = [(save_join(dl, p.folder, x['name']), x['id']) for x in p.getChildren().itervalues()] matched = False success = True + files_ids = [(save_join(dl, pypack.folder, x['name']), x['id']) for x in pypack.getChildren().itervalues()] # check as long there are unseen files while files_ids: @@ -224,42 +208,41 @@ class ExtractArchive(Hook): if extensions: files_ids = [(file, id) for file, id in files_ids if filter(lambda ext: file.endswith(ext), extensions)] - for plugin in self.plugins: - targets = plugin.getTargets(files_ids) - + for Extractor in self.extractors: + targets = Extractor.getTargets(files_ids) if targets: - self.logDebug("Targets for %s: %s" % (plugin.__name__, targets)) + self.logDebug("Targets for %s: %s" % (Extractor.__name__, targets)) matched = True - for target, fid in targets: - if target in processed: - self.logDebug(basename(target), "skipped") + for filename, fid in targets: + fname = os.path.basename(filename) + + if filename in processed: + self.logDebug(fname, "Skipped") continue - processed.append(target) # prevent extracting same file twice + processed.append(filename) # prevent extracting same file twice - self.logInfo(basename(target), _("Extract to: %s") % out) + self.logInfo(fname, _("Extract to: %s") % out) try: - klass = plugin(self, - target, - out, - p.password, - fullpath, - overwrite, - excludefiles, - renice, - delete, - keepbroken) + self.extracting = True + + klass = Extractor(self, + filename, + out, + fullpath, + overwrite, + excludefiles, + renice, + delete, + keepbroken, + fid) klass.init() - new_files = self._extract(klass, fid) + new_files = self._extract(klass, fid, pypack.password) except Exception, e: - self.logError(basename(target), e) - new_files = None - - if new_files is None: - self.logWarning(basename(target), _("No files extracted")) + self.logError(fname, e) success = False continue @@ -267,10 +250,10 @@ class ExtractArchive(Hook): self.setPermissions(new_files) for file in new_files: - if not exists(file): + if not os.path.exists(file): self.logDebug("New file %s does not exists" % file) continue - if recursive and isfile(file): + if recursive and os.path.isfile(file): new_files_ids.append((file, fid)) # append as new target files_ids = new_files_ids # also check extracted files @@ -278,10 +261,10 @@ class ExtractArchive(Hook): if matched: if success: extracted.append(pid) - self.manager.dispatchEvent("package_extracted", p) + self.manager.dispatchEvent("package_extracted", pypack) else: failed.append(pid) - self.manager.dispatchEvent("package_extract_failed", p) + self.manager.dispatchEvent("package_extract_failed", pypack) else: self.logInfo(_("No files found to extract")) @@ -295,124 +278,103 @@ class ExtractArchive(Hook): return True if not failed else False - def _extract(self, plugin, fid): + def _extract(self, archive, fid, password): pyfile = self.core.files.getFile(fid) + fname = os.path.basename(fs_decode(archive.target)) pyfile.setCustomStatus(_("extracting")) + pyfile.setProgress(0) try: - progress = lambda x: pyfile.setProgress(x) - encrypted = False - passwords = self.getPasswords() - - try: - self.logInfo(basename(plugin.file), "Verifying...") - - tmp_password = plugin.password - plugin.password = "" #: Force verifying without password - - plugin.verify() - - except PasswordError: - encrypted = True - - except CRCError: - self.logWarning(basename(plugin.file), _("Archive damaged")) - - if not self.getConfig("repair"): - raise CRCError - - elif plugin.repair(): - self.logInfo(basename(plugin.file), _("Successfully repaired")) - - elif not self.getConfig("keepbroken"): - raise ArchiveError(_("Broken archive")) - - else: - self.logInfo(basename(plugin.file), _("All OK")) - - plugin.password = tmp_password - - if not encrypted: - plugin.extract(progress) + success = False + if not archive.checkArchive(): + archive.extract(password) + success = True else: - self.logInfo(basename(plugin.file), _("Password protected")) + self.logInfo(fname, _("Password protected")) + self.logDebug("Password: %s" % (password or "No provided")) - if plugin.password: - passwords.insert(0, plugin.password) - passwords = uniqify(self.passwords) - self.logDebug("Password: %s" % plugin.password) - else: - self.logDebug("No package password provided") - - for pw in passwords: + for pw in set(self.getPasswords(False) + [password]): try: self.logDebug("Try password: %s" % pw) - - if plugin.setPassword(pw): - plugin.extract(progress) + if archive.checkPassword(pw): + archive.extract(pw) self.addPassword(pw) + success = True break - else: - raise PasswordError except PasswordError: self.logDebug("Password was wrong") else: raise PasswordError + pyfile.setProgress(100) + pyfile.setStatus("processing") + if self.core.debug: self.logDebug("Would delete: %s" % ", ".join(plugin.getDeleteFiles())) if self.getConfig("delete"): - files = plugin.getDeleteFiles() + files = archive.getDeleteFiles() self.logInfo(_("Deleting %s files") % len(files)) for f in files: - if exists(f): - remove(f) + if os.path.exists(f): + os.remove(f) else: self.logDebug("%s does not exists" % f) - self.logInfo(basename(plugin.file), _("Extracting finished")) + self.logInfo(fname, _("Extracting finished")) - extracted_files = plugin.getExtractedFiles() - self.manager.dispatchEvent("archive_extracted", pyfile, plugin.out, plugin.file, extracted_files) + extracted_files = archive.getExtractedFiles() + self.manager.dispatchEvent("archive_extracted", pyfile, archive.out, archive.file, extracted_files) return extracted_files except PasswordError: - self.logError(basename(plugin.file), _("Wrong password" if passwords else "No password found")) - plugin.password = "" + self.logError(fname, _("Wrong password" if password else "No password found")) except CRCError: - self.logError(basename(plugin.file), _("CRC Mismatch")) + self.logError(fname, _("CRC Mismatch")) except ArchiveError, e: - self.logError(basename(plugin.file), _("Archive Error"), e) + self.logError(fname, _("Archive Error"), e) except Exception, e: if self.core.debug: print_exc() - self.logError(basename(plugin.file), _("Unknown Error"), e) + self.logError(fname, _("Unknown Error"), e) + + finally: + pyfile.finishIfDone() self.manager.dispatchEvent("archive_extract_failed", pyfile) - self.logError(basename(plugin.file), _("Extract failed")) + raise Exception(_("Extract failed")) + + + def getQueue(self): + return self.getStorage("ExtractArchive", []) + + + def addToQueue(self, item): + queue = self.getQueue() + return self.setStorage("ExtractArchive", queue + [item] if item not in queue else queue) @Expose - def getPasswords(self): + def getPasswords(self, reload=True): """ List of saved passwords """ + if reload: + self.reloadPasswords() + return self.passwords def reloadPasswords(self): - passwordfile = self.getConfig("passwordfile") - try: passwords = [] - with open(passwordfile, "a+") as f: + with open(self.getConfig("passwordfile")) as f: for pw in f.read().splitlines(): passwords.append(pw) @@ -426,13 +388,10 @@ class ExtractArchive(Hook): @Expose def addPassword(self, pw): """ Adds a password to saved list""" - passwordfile = self.getConfig("passwordfile") - - self.passwords.insert(0, pw) - self.passwords = uniqify(self.passwords) - try: - with open(passwordfile, "wb") as f: + self.passwords = uniqify([pw] + self.passwords) + + with open(self.getConfig("passwordfile"), "wb") as f: for pw in self.passwords: f.write(pw + '\n') @@ -442,20 +401,21 @@ class ExtractArchive(Hook): def setPermissions(self, files): for f in files: - if not exists(f): + if not os.path.exists(f): continue try: if self.config['permission']['change_file']: - if isfile(f): - chmod(f, int(self.config['permission']['file'], 8)) - elif isdir(f): - chmod(f, int(self.config['permission']['folder'], 8)) + if os.path.isfile(f): + os.chmod(f, int(self.config['permission']['file'], 8)) + + elif os.path.isdir(f): + os.chmod(f, int(self.config['permission']['folder'], 8)) if self.config['permission']['change_dl'] and os.name != "nt": uid = getpwnam(self.config['permission']['user'])[2] gid = getgrnam(self.config['permission']['group'])[2] - chown(f, uid, gid) + os.chown(f, uid, gid) except Exception, e: self.logWarning(_("Setting User and Group failed"), e) diff --git a/module/plugins/hooks/IRCInterface.py b/module/plugins/hooks/IRCInterface.py index efd4e411d..98fa1d030 100644 --- a/module/plugins/hooks/IRCInterface.py +++ b/module/plugins/hooks/IRCInterface.py @@ -61,7 +61,7 @@ class IRCInterface(Thread, Hook): try: if self.getConfig("info_pack"): self.response(_("Package finished: %s") % pypack.name) - except: + except Exception: pass @@ -70,7 +70,7 @@ class IRCInterface(Thread, Hook): if self.getConfig("info_file"): self.response( _("Download finished: %(name)s @ %(plugin)s ") % {"name": pyfile.name, "plugin": pyfile.pluginname}) - except: + except Exception: pass @@ -183,7 +183,7 @@ class IRCInterface(Thread, Hook): trigger = temp[0] if len(temp) > 1: args = temp[1:] - except: + except Exception: pass handler = getattr(self, "event_%s" % trigger, self.event_pass) @@ -347,7 +347,7 @@ class IRCInterface(Thread, Hook): return ["INFO: Added %d links to Package %s [#%d]" % (len(links), pack['name'], id)] - except: + except Exception: # create new package id = self.core.api.addPackage(pack, links, 1) return ["INFO: Created new Package %s [#%d] with %d links." % (pack, id, len(links))] diff --git a/module/plugins/hooks/ImageTyperz.py b/module/plugins/hooks/ImageTyperz.py index d448d1be9..d62fed385 100644 --- a/module/plugins/hooks/ImageTyperz.py +++ b/module/plugins/hooks/ImageTyperz.py @@ -69,7 +69,7 @@ class ImageTyperz(Hook): try: balance = float(res) - except: + except Exception: raise ImageTyperzException("Invalid response") self.logInfo(_("Account balance: $%s left") % res) @@ -82,7 +82,7 @@ class ImageTyperz(Hook): req.c.setopt(LOW_SPEED_TIME, 80) try: - #workaround multipart-post bug in HTTPRequest.py + #@NOTE: Workaround multipart-post bug in HTTPRequest.py if re.match("^\w*$", self.getConfig("passkey")): multipart = True data = (FORM_FILE, captcha) diff --git a/module/plugins/hooks/LinkdecrypterCom.py b/module/plugins/hooks/LinkdecrypterCom.py index d4924a687..f85a598bc 100644 --- a/module/plugins/hooks/LinkdecrypterCom.py +++ b/module/plugins/hooks/LinkdecrypterCom.py @@ -8,7 +8,7 @@ from module.plugins.internal.MultiHook import MultiHook class LinkdecrypterCom(MultiHook): __name__ = "LinkdecrypterCom" __type__ = "hook" - __version__ = "1.01" + __version__ = "1.02" __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ), @@ -21,8 +21,5 @@ class LinkdecrypterCom(MultiHook): def getCrypters(self): - try: - html = self.getURL("http://linkdecrypter.com/") - return re.search(r'>Supported\(\d+\)</b>: <i>(.+?) \+ RSDF', html).group(1).split(', ') - except Exception: - return list() + return re.search(r'>Supported\(\d+\)</b>: <i>(.[\w.\-, ]+)', + self.getURL("http://linkdecrypter.com/").replace("(g)", "")).group(1).split(', ') diff --git a/module/plugins/hooks/SkipRev.py b/module/plugins/hooks/SkipRev.py index 6b4e715da..51d385bb4 100644 --- a/module/plugins/hooks/SkipRev.py +++ b/module/plugins/hooks/SkipRev.py @@ -18,7 +18,7 @@ def _setup(self): class SkipRev(Hook): __name__ = "SkipRev" __type__ = "hook" - __version__ = "0.23" + __version__ = "0.24" __config__ = [("tokeep", "int", "Number of rev files to keep for package (-1 to auto)", -1)] @@ -34,7 +34,7 @@ class SkipRev(Hook): def _pyname(self, pyfile): if hasattr(pyfile.pluginmodule, "getInfo"): - return next(getattr(pyfile.pluginmodule, "getInfo")([pyfile.url]))[0] + return getattr(pyfile.pluginmodule, "getInfo")([pyfile.url]).next()[0] else: self.logWarning("Unable to grab file name") return urlparse(unquote(pyfile.url)).path.split('/')[-1] diff --git a/module/plugins/hooks/UpdateManager.py b/module/plugins/hooks/UpdateManager.py index c72699228..b6a8bac7c 100644 --- a/module/plugins/hooks/UpdateManager.py +++ b/module/plugins/hooks/UpdateManager.py @@ -16,14 +16,14 @@ from module.utils import save_join class UpdateManager(Hook): __name__ = "UpdateManager" __type__ = "hook" - __version__ = "0.42" + __version__ = "0.43" __config__ = [("activated" , "bool" , "Activated" , True ), ("mode" , "pyLoad + plugins;plugins only", "Check updates for" , "pyLoad + plugins"), ("interval" , "int" , "Check interval in hours" , 8 ), ("autorestart" , "bool" , "Automatically restart pyLoad when required" , True ), ("reloadplugins", "bool" , "Monitor plugins for code changes in debug mode", True ), - ("nodebugupdate", "bool" , "Don't check for updates in debug mode" , True )] + ("nodebugupdate", "bool" , "Don't check for updates in debug mode" , False )] __description__ = """ Check for updates """ __license__ = "GPLv3" @@ -117,7 +117,7 @@ class UpdateManager(Hook): def server_request(self): try: return getURL(self.SERVER_URL, get={'v': self.core.api.getServerVersion()}).splitlines() - except: + except Exception: self.logWarning(_("Unable to contact server to get updates")) @@ -192,7 +192,7 @@ class UpdateManager(Hook): # Protect UpdateManager from self-removing try: blacklisted.remove(("hook", "UpdateManager")) - except: + except Exception: pass for t, n in blacklisted: diff --git a/module/plugins/hooks/WindowsPhoneToastNotify.py b/module/plugins/hooks/WindowsPhoneToastNotify.py index 886d4ca6a..20686ee36 100644 --- a/module/plugins/hooks/WindowsPhoneToastNotify.py +++ b/module/plugins/hooks/WindowsPhoneToastNotify.py @@ -10,7 +10,7 @@ from module.plugins.Hook import Hook class WindowsPhoneToastNotify(Hook): __name__ = "WindowsPhoneToastNotify" __type__ = "hook" - __version__ = "0.04" + __version__ = "0.05" __config__ = [("id" , "str" , "Push ID" , "" ), ("url" , "str" , "Push url" , "" ), @@ -53,7 +53,7 @@ class WindowsPhoneToastNotify(Hook): self.notify(_("Package finished"), pypack.name) - def allDownloadsProcessed(self, thread): + def allDownloadsProcessed(self): if not self.getConfig("notifyprocessed"): return False diff --git a/module/plugins/hooks/XFileSharingPro.py b/module/plugins/hooks/XFileSharingPro.py index 0745a6c7e..e6e30ca8f 100644 --- a/module/plugins/hooks/XFileSharingPro.py +++ b/module/plugins/hooks/XFileSharingPro.py @@ -8,7 +8,7 @@ from module.plugins.Hook import Hook class XFileSharingPro(Hook): __name__ = "XFileSharingPro" __type__ = "hook" - __version__ = "0.30" + __version__ = "0.31" __config__ = [("activated" , "bool", "Activated" , True ), ("use_hoster_list" , "bool", "Load listed hosters only" , False), @@ -30,15 +30,15 @@ class XFileSharingPro(Hook): HOSTER_BUILTIN = [#WORKING HOSTERS: "180upload.com", "backin.net", "eyesfile.ca", "file4safe.com", "fileband.com", "filedwon.com", - "fileparadox.in", "filevice.com", "hostingbulk.com", "linestorage.com", "ravishare.com", "ryushare.com", - "salefiles.com", "sendmyway.com", "sharesix.com", "thefile.me", "verzend.be", "xvidstage.com", + "fileparadox.in", "filevice.com", "hostingbulk.com", "junkyvideo.com", "linestorage.com", "ravishare.com", + "ryushare.com", "salefiles.com", "sendmyway.com", "sharesix.com", "thefile.me", "verzend.be", "xvidstage.com", #NOT TESTED: "101shared.com", "4upfiles.com", "filemaze.ws", "filenuke.com", "linkzhost.com", "mightyupload.com", "rockdizfile.com", "sharebeast.com", "sharerepo.com", "shareswift.com", "uploadbaz.com", "uploadc.com", "vidbull.com", "zalaa.com", "zomgupload.com", #NOT WORKING: "amonshare.com", "banicrazy.info", "boosterking.com", "host4desi.com", "laoupload.com", "rd-fs.com"] - CRYPTER_BUILTIN = [] + CRYPTER_BUILTIN = ["junocloud.me", "rapidfileshare.net"] # def pluginConfigChanged(self.__name__, plugin, name, value): diff --git a/module/plugins/hooks/XMPPInterface.py b/module/plugins/hooks/XMPPInterface.py index bbeab4341..b8e9fc1ad 100644 --- a/module/plugins/hooks/XMPPInterface.py +++ b/module/plugins/hooks/XMPPInterface.py @@ -69,7 +69,7 @@ class XMPPInterface(IRCInterface, JabberClient): try: if self.getConfig("info_pack"): self.announce(_("Package finished: %s") % pypack.name) - except: + except Exception: pass @@ -78,7 +78,7 @@ class XMPPInterface(IRCInterface, JabberClient): if self.getConfig("info_file"): self.announce( _("Download finished: %(name)s @ %(plugin)s") % {"name": pyfile.name, "plugin": pyfile.pluginname}) - except: + except Exception: pass @@ -152,7 +152,7 @@ class XMPPInterface(IRCInterface, JabberClient): trigger = temp[0] if len(temp) > 1: args = temp[1:] - except: + except Exception: pass handler = getattr(self, "event_%s" % trigger, self.event_pass) diff --git a/module/plugins/hoster/BasePlugin.py b/module/plugins/hoster/BasePlugin.py index 6d3132e65..4f9e25a35 100644 --- a/module/plugins/hoster/BasePlugin.py +++ b/module/plugins/hoster/BasePlugin.py @@ -6,14 +6,14 @@ from urllib import unquote from urlparse import urljoin, urlparse from module.network.HTTPRequest import BadHeader -from module.plugins.internal.SimpleHoster import create_getInfo +from module.plugins.internal.SimpleHoster import create_getInfo, fileUrl from module.plugins.Hoster import Hoster class BasePlugin(Hoster): __name__ = "BasePlugin" __type__ = "hoster" - __version__ = "0.30" + __version__ = "0.33" __pattern__ = r'^unmatchable$' @@ -35,7 +35,8 @@ class BasePlugin(Hoster): def setup(self): - self.chunkLimit = -1 + self.chunkLimit = -1 + self.multiDL = True self.resumeDownload = True @@ -49,7 +50,12 @@ class BasePlugin(Hoster): for _i in xrange(5): try: - self.downloadFile(pyfile) + 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: @@ -85,33 +91,4 @@ class BasePlugin(Hoster): self.fail(check.capitalize()) - def downloadFile(self, pyfile): - url = pyfile.url - - for i in xrange(1, 7): #@TODO: retrieve the pycurl.MAXREDIRS value set by req - header = self.load(url, ref=True, cookies=True, just_header=True, decode=True) - - if 'location' not in header or not header['location']: - if 'code' in header and header['code'] not in (200, 201, 203, 206): - self.logDebug("Received HTTP status code: %d" % header['code']) - self.fail(_("File not found")) - else: - break - - location = header['location'] - - self.logDebug("Redirect #%d to: %s" % (i, location)) - - if urlparse(location).scheme: - url = location - else: - p = urlparse(url) - base = "%s://%s" % (p.scheme, p.netloc) - url = urljoin(base, location) - else: - self.fail(_("Too many redirects")) - - self.download(unquote(url), disposition=True) - - getInfo = create_getInfo(BasePlugin) diff --git a/module/plugins/hoster/BillionuploadsCom.py b/module/plugins/hoster/BillionuploadsCom.py index b20ace0f1..7d7e2624a 100644 --- a/module/plugins/hoster/BillionuploadsCom.py +++ b/module/plugins/hoster/BillionuploadsCom.py @@ -15,8 +15,6 @@ class BillionuploadsCom(XFSHoster): __authors__ = [("zoidberg", "zoidberg@mujmail.cz")] - HOSTER_DOMAIN = "billionuploads.com" - NAME_PATTERN = r'<td class="dofir" title="(?P<N>.+?)"' SIZE_PATTERN = r'<td class="dofir">(?P<S>[\d.,]+) (?P<U>[\w^_]+)' diff --git a/module/plugins/hoster/BitshareCom.py b/module/plugins/hoster/BitshareCom.py index f7b4d2709..657e70e56 100644 --- a/module/plugins/hoster/BitshareCom.py +++ b/module/plugins/hoster/BitshareCom.py @@ -11,7 +11,7 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class BitshareCom(SimpleHoster): __name__ = "BitshareCom" __type__ = "hoster" - __version__ = "0.52" + __version__ = "0.53" __pattern__ = r'http://(?:www\.)?bitshare\.com/(files/)?(?(1)|\?f=)(?P<ID>\w+)(?(1)/(?P<NAME>.+?)\.html)' @@ -114,7 +114,7 @@ class BitshareCom(SimpleHoster): # Try up to 3 times for i in xrange(3): - challenge, response = recaptcha.challenge() + response, challenge = recaptcha.challenge() res = self.load("http://bitshare.com/files-ajax/" + self.file_id + "/request.html", post={"request" : "validateCaptcha", "ajaxid" : self.ajaxid, diff --git a/module/plugins/hoster/CatShareNet.py b/module/plugins/hoster/CatShareNet.py index f2ddd64a0..339253aeb 100644 --- a/module/plugins/hoster/CatShareNet.py +++ b/module/plugins/hoster/CatShareNet.py @@ -9,7 +9,7 @@ from module.plugins.internal.CaptchaService import ReCaptcha class CatShareNet(SimpleHoster): __name__ = "CatShareNet" __type__ = "hoster" - __version__ = "0.09" + __version__ = "0.11" __pattern__ = r'http://(?:www\.)?catshare\.net/\w{16}' @@ -26,8 +26,9 @@ class CatShareNet(SimpleHoster): OFFLINE_PATTERN = ur'Podany plik zostaÅ usuniÄty\s*</div>' IP_BLOCKED_PATTERN = ur'>Nasz serwis wykryÅ ÅŒe Twój adres IP nie pochodzi z Polski.<' - SECONDS_PATTERN = 'var\scount\s=\s(\d+);' - LINK_FREE_PATTERN = r'<form action="(.+?)" method="GET">' + WAIT_PATTERN = r'var\scount\s=\s(\d+);' + + LINK_FREE_PATTERN = LINK_PREMIUM_PATTERN = r'<form action="(.+?)" method="GET">' def setup(self): @@ -43,14 +44,9 @@ class CatShareNet(SimpleHoster): def handleFree(self, pyfile): - m = re.search(self.SECONDS_PATTERN, self.html) - if m: - wait_time = int(m.group(1)) - self.wait(wait_time, True) - recaptcha = ReCaptcha(self) - challenge, response = recaptcha.challenge() + response, challenge = recaptcha.challenge() self.html = self.load(pyfile.url, post={'recaptcha_challenge_field': challenge, 'recaptcha_response_field' : response}) diff --git a/module/plugins/hoster/CloudzillaTo.py b/module/plugins/hoster/CloudzillaTo.py index 58b1ac0dd..ee966c280 100644 --- a/module/plugins/hoster/CloudzillaTo.py +++ b/module/plugins/hoster/CloudzillaTo.py @@ -47,7 +47,7 @@ class CloudzillaTo(SimpleHoster): self.fail(ticket['error']) if 'wait' in ticket: - self.wait(int(ticket['wait']), int(ticket['wait']) > 5) + self.wait(ticket['wait'], int(ticket['wait']) > 5) self.link = "http://%(server)s/download/%(file_id)s/%(ticket_id)s" % {'server' : ticket['server'], 'file_id' : self.info['pattern']['ID'], diff --git a/module/plugins/hoster/CramitIn.py b/module/plugins/hoster/CramitIn.py index f444718bc..44dac958d 100644 --- a/module/plugins/hoster/CramitIn.py +++ b/module/plugins/hoster/CramitIn.py @@ -15,8 +15,6 @@ class CramitIn(XFSHoster): __authors__ = [("zoidberg", "zoidberg@mujmail.cz")] - HOSTER_DOMAIN = "cramit.in" - INFO_PATTERN = r'<span class=t2>\s*(?P<N>.*?)</span>.*?<small>\s*\((?P<S>.*?)\)' LINK_PATTERN = r'href="(http://cramit\.in/file_download/.*?)"' diff --git a/module/plugins/hoster/CrockoCom.py b/module/plugins/hoster/CrockoCom.py index 31d0eec95..474042a5a 100644 --- a/module/plugins/hoster/CrockoCom.py +++ b/module/plugins/hoster/CrockoCom.py @@ -9,7 +9,7 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class CrockoCom(SimpleHoster): __name__ = "CrockoCom" __type__ = "hoster" - __version__ = "0.18" + __version__ = "0.19" __pattern__ = r'http://(?:www\.)?(crocko|easy-share)\.com/\w+' @@ -52,7 +52,7 @@ class CrockoCom(SimpleHoster): recaptcha = ReCaptcha(self) for _i in xrange(5): - inputs['recaptcha_challenge_field'], inputs['recaptcha_response_field'] = recaptcha.challenge() + inputs['recaptcha_response_field'], inputs['recaptcha_challenge_field'] = recaptcha.challenge() self.download(action, post=inputs) if self.checkDownload({"captcha": recaptcha.KEY_AJAX_PATTERN}): diff --git a/module/plugins/hoster/DateiTo.py b/module/plugins/hoster/DateiTo.py index 99b86e000..e5061e026 100644 --- a/module/plugins/hoster/DateiTo.py +++ b/module/plugins/hoster/DateiTo.py @@ -9,7 +9,7 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class DateiTo(SimpleHoster): __name__ = "DateiTo" __type__ = "hoster" - __version__ = "0.06" + __version__ = "0.07" __pattern__ = r'http://(?:www\.)?datei\.to/datei/(?P<ID>\w+)\.html' @@ -52,7 +52,7 @@ class DateiTo(SimpleHoster): data = dict(x.split('=') for x in m.group(2).split('&')) if url.endswith('recaptcha.php'): - data['recaptcha_challenge_field'], data['recaptcha_response_field'] = recaptcha.challenge() + data['recaptcha_response_field'], data['recaptcha_challenge_field'] = recaptcha.challenge() else: self.fail(_("Too bad...")) diff --git a/module/plugins/hoster/DepositfilesCom.py b/module/plugins/hoster/DepositfilesCom.py index 9d060e75d..3af309cae 100644 --- a/module/plugins/hoster/DepositfilesCom.py +++ b/module/plugins/hoster/DepositfilesCom.py @@ -11,7 +11,7 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class DepositfilesCom(SimpleHoster): __name__ = "DepositfilesCom" __type__ = "hoster" - __version__ = "0.52" + __version__ = "0.53" __pattern__ = r'https?://(?:www\.)?(depositfiles\.com|dfiles\.(eu|ru))(/\w{1,3})?/files/(?P<ID>\w+)' @@ -77,7 +77,7 @@ class DepositfilesCom(SimpleHoster): if '<input type=button value="Continue" onclick="check_recaptcha' in self.html: if 'response' in params: self.invalidCaptcha() - params['challenge'], params['response'] = recaptcha.challenge(captcha_key) + params['response'], params['challenge'] = recaptcha.challenge(captcha_key) self.logDebug(params) continue @@ -95,7 +95,7 @@ class DepositfilesCom(SimpleHoster): try: self.download(link, disposition=True) - except: + except Exception: self.retry(wait_time=60) diff --git a/module/plugins/hoster/DlFreeFr.py b/module/plugins/hoster/DlFreeFr.py index ec40b64ce..4776bf470 100644 --- a/module/plugins/hoster/DlFreeFr.py +++ b/module/plugins/hoster/DlFreeFr.py @@ -36,7 +36,7 @@ class CustomBrowser(Browser): class DlFreeFr(SimpleHoster): __name__ = "DlFreeFr" __type__ = "hoster" - __version__ = "0.27" + __version__ = "0.28" __pattern__ = r'http://(?:www\.)?dl\.free\.fr/(\w+|getfile\.pl\?file=/\w+)' @@ -92,7 +92,8 @@ class DlFreeFr(SimpleHoster): action, inputs = self.parseHtmlForm('action="getfile.pl"') adyoulike = AdYouLike(self) - inputs.update(adyoulike.challenge()) + response, challenge = adyoulike.challenge() + inputs.update(response) self.load("http://dl.free.fr/getfile.pl", post=inputs) headers = self.getLastHeaders() diff --git a/module/plugins/hoster/EasybytezCom.py b/module/plugins/hoster/EasybytezCom.py index cd54bdc70..693910c1b 100644 --- a/module/plugins/hoster/EasybytezCom.py +++ b/module/plugins/hoster/EasybytezCom.py @@ -16,8 +16,6 @@ class EasybytezCom(XFSHoster): ("stickell", "l.stickell@yahoo.it")] - HOSTER_DOMAIN = "easybytez.com" - OFFLINE_PATTERN = r'>File not available' LINK_PATTERN = r'(http://(\w+\.(easybytez|easyload|ezbytez|zingload)\.(com|to)|\d+\.\d+\.\d+\.\d+)/files/\d+/\w+/.+?)["\'<]' diff --git a/module/plugins/hoster/ExashareCom.py b/module/plugins/hoster/ExashareCom.py new file mode 100644 index 000000000..536c09b6d --- /dev/null +++ b/module/plugins/hoster/ExashareCom.py @@ -0,0 +1,38 @@ +# -*- coding: utf-8 -*- + +import re + +from module.plugins.internal.XFSHoster import XFSHoster, create_getInfo + + +class ExashareCom(XFSHoster): + __name__ = "ExashareCom" + __type__ = "hoster" + __version__ = "0.01" + + __pattern__ = r'http://(?:www\.)?exashare\.com/\w{12}' + + __description__ = """Exashare.com hoster plugin""" + __license__ = "GPLv3" + __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] + + + INFO_PATTERN = r'>(?P<NAME>.+?)<small>\( (?P<S>[\d.,]+) (?P<U>[\w^_]+)' + LINK_FREE_PATTERN = r'file: "(.+?)"' + + + def setup(self): + self.multiDL = True + self.chunkLimit = 1 + self.resumeDownload = self.premium + + + def handleFree(self, pyfile): + m = re.search(self.LINK_FREE_PATTERN, self.html) + if m is None: + self.error(_("Free download link not found")) + else: + self.link = m.group(1) + + +getInfo = create_getInfo(ExashareCom) diff --git a/module/plugins/hoster/ExtabitCom.py b/module/plugins/hoster/ExtabitCom.py index 5c2976a29..68695faad 100644 --- a/module/plugins/hoster/ExtabitCom.py +++ b/module/plugins/hoster/ExtabitCom.py @@ -11,7 +11,7 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo, s class ExtabitCom(SimpleHoster): __name__ = "ExtabitCom" __type__ = "hoster" - __version__ = "0.64" + __version__ = "0.65" __pattern__ = r'http://(?:www\.)?extabit\.com/(file|go|fid)/(?P<ID>\w+)' @@ -50,7 +50,7 @@ class ExtabitCom(SimpleHoster): for _i in xrange(5): get_data = {"type": "recaptcha"} - get_data['challenge'], get_data['capture'] = recaptcha.challenge(captcha_key) + get_data['capture'], get_data['challenge'] = recaptcha.challenge(captcha_key) res = json_loads(self.load("http://extabit.com/file/%s/" % fileID, get=get_data)) if "ok" in res: self.correctCaptcha() diff --git a/module/plugins/hoster/FilecloudIo.py b/module/plugins/hoster/FilecloudIo.py index bc328ddbd..fb1aea58f 100644 --- a/module/plugins/hoster/FilecloudIo.py +++ b/module/plugins/hoster/FilecloudIo.py @@ -10,7 +10,7 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class FilecloudIo(SimpleHoster): __name__ = "FilecloudIo" __type__ = "hoster" - __version__ = "0.06" + __version__ = "0.08" __pattern__ = r'http://(?:www\.)?(?:filecloud\.io|ifile\.it|mihd\.net)/(?P<ID>\w+)' @@ -59,7 +59,7 @@ class FilecloudIo(SimpleHoster): if captcha_key is None: self.error(_("ReCaptcha key not found")) - challenge, response = recaptcha.challenge(captcha_key) + response, challenge = recaptcha.challenge(captcha_key) self.account.form_data = {"recaptcha_challenge_field": challenge, "recaptcha_response_field" : response} self.account.relogin(self.user) @@ -78,7 +78,7 @@ class FilecloudIo(SimpleHoster): data['ctype'] = "recaptcha" for _i in xrange(5): - data['recaptcha_challenge'], data['recaptcha_response'] = recaptcha.challenge(captcha_key) + data['recaptcha_response'], data['recaptcha_challenge'] = recaptcha.challenge(captcha_key) json_url = "http://filecloud.io/download-request.json" res = self.load(json_url, post=data) diff --git a/module/plugins/hoster/FilefactoryCom.py b/module/plugins/hoster/FilefactoryCom.py index 2c8ec58f4..30c1b85ec 100644 --- a/module/plugins/hoster/FilefactoryCom.py +++ b/module/plugins/hoster/FilefactoryCom.py @@ -56,7 +56,7 @@ class FilefactoryCom(SimpleHoster): m = re.search(self.WAIT_PATTERN, self.html) if m: - self.wait(int(m.group(1))) + self.wait(m.group(1)) self.download(dl_link, disposition=True) diff --git a/module/plugins/hoster/FileomCom.py b/module/plugins/hoster/FileomCom.py index 2b6fd34db..306953b84 100644 --- a/module/plugins/hoster/FileomCom.py +++ b/module/plugins/hoster/FileomCom.py @@ -18,8 +18,6 @@ class FileomCom(XFSHoster): __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] - HOSTER_DOMAIN = "fileom.com" - NAME_PATTERN = r'Filename: <span>(?P<N>.+?)<' SIZE_PATTERN = r'File Size: <span class="size">(?P<S>[\d.,]+) (?P<U>[\w^_]+)' diff --git a/module/plugins/hoster/FilepostCom.py b/module/plugins/hoster/FilepostCom.py index 4dd36c6e4..25def94e8 100644 --- a/module/plugins/hoster/FilepostCom.py +++ b/module/plugins/hoster/FilepostCom.py @@ -12,7 +12,7 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class FilepostCom(SimpleHoster): __name__ = "FilepostCom" __type__ = "hoster" - __version__ = "0.32" + __version__ = "0.33" __pattern__ = r'https?://(?:www\.)?(?:filepost\.com/files|fp\.io)/(?P<ID>[^/]+)' @@ -74,7 +74,7 @@ class FilepostCom(SimpleHoster): for i in xrange(5): get_dict['JsHttpRequest'] = str(int(time() * 10000)) + '-xml' if i: - post_dict['recaptcha_challenge_field'], post_dict['recaptcha_response_field'] = recaptcha.challenge( + post_dict['recaptcha_response_field'], post_dict['recaptcha_challenge_field'] = recaptcha.challenge( captcha_key) self.logDebug(u"RECAPTCHA: %s : %s : %s" % ( captcha_key, post_dict['recaptcha_challenge_field'], post_dict['recaptcha_response_field'])) diff --git a/module/plugins/hoster/FilerNet.py b/module/plugins/hoster/FilerNet.py index a668a834b..c5007e945 100644 --- a/module/plugins/hoster/FilerNet.py +++ b/module/plugins/hoster/FilerNet.py @@ -16,7 +16,7 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class FilerNet(SimpleHoster): __name__ = "FilerNet" __type__ = "hoster" - __version__ = "0.13" + __version__ = "0.16" __pattern__ = r'https?://(?:www\.)?filer\.net/get/\w+' @@ -53,30 +53,22 @@ class FilerNet(SimpleHoster): if 'hash' not in inputs: self.error(_("Unable to detect hash")) - recaptcha = ReCaptcha(self) - - for _i in xrange(5): - challenge, response = recaptcha.challenge() - - #@NOTE: Work-around for v0.4.9 just_header issue - #@TODO: Check for v0.4.10 - self.req.http.c.setopt(pycurl.FOLLOWLOCATION, 0) - self.load(pyfile.url, post={'recaptcha_challenge_field': challenge, - 'recaptcha_response_field' : response, - 'hash' : inputs['hash']}) - self.req.http.c.setopt(pycurl.FOLLOWLOCATION, 1) - - if 'location' in self.req.http.header.lower(): - self.link = re.search(r'location: (\S+)', self.req.http.header, re.I).group(1) - self.correctCaptcha() - break - else: - self.invalidCaptcha() - - - def downloadLink(self, link): - if link and isinstance(link, basestring): - self.download(urljoin("http://filer.net/", link), disposition=True) + recaptcha = ReCaptcha(self) + response, challenge = recaptcha.challenge() + + #@NOTE: Work-around for v0.4.9 just_header issue + #@TODO: Check for v0.4.10 + self.req.http.c.setopt(pycurl.FOLLOWLOCATION, 0) + self.load(pyfile.url, post={'recaptcha_challenge_field': challenge, + 'recaptcha_response_field' : response, + 'hash' : inputs['hash']}) + self.req.http.c.setopt(pycurl.FOLLOWLOCATION, 1) + + if 'location' in self.req.http.header.lower(): + self.link = re.search(r'location: (\S+)', self.req.http.header, re.I).group(1) + self.correctCaptcha() + else: + self.invalidCaptcha() getInfo = create_getInfo(FilerNet) diff --git a/module/plugins/hoster/FilerioCom.py b/module/plugins/hoster/FilerioCom.py index db81f5b16..c6ebbd444 100644 --- a/module/plugins/hoster/FilerioCom.py +++ b/module/plugins/hoster/FilerioCom.py @@ -15,8 +15,6 @@ class FilerioCom(XFSHoster): __authors__ = [("zoidberg", "zoidberg@mujmail.cz")] - HOSTER_DOMAIN = "filerio.in" - URL_REPLACEMENTS = [(r'filekeen\.com', "filerio.in")] OFFLINE_PATTERN = r'>"File Not Found|File has been removed' diff --git a/module/plugins/hoster/FilesMailRu.py b/module/plugins/hoster/FilesMailRu.py index 18fca7176..7bd099282 100644 --- a/module/plugins/hoster/FilesMailRu.py +++ b/module/plugins/hoster/FilesMailRu.py @@ -21,7 +21,7 @@ def getInfo(urls): url_pattern = '<a href="(.+?)" onclick="return Act\(this\, \'dlink\'\, event\)">(.+?)</a>' file_name = re.search(url_pattern, html).group(0).split(', event)">')[1].split('</a>')[0] result.append((file_name, 0, 2, url)) - except: + except Exception: pass # status 1=OFFLINE, 2=OK, 3=UNKNOWN diff --git a/module/plugins/hoster/FileserveCom.py b/module/plugins/hoster/FileserveCom.py index 515ec9029..6f316cea3 100644 --- a/module/plugins/hoster/FileserveCom.py +++ b/module/plugins/hoster/FileserveCom.py @@ -33,7 +33,7 @@ def checkFile(plugin, urls): class FileserveCom(Hoster): __name__ = "FileserveCom" __type__ = "hoster" - __version__ = "0.53" + __version__ = "0.54" __pattern__ = r'http://(?:www\.)?fileserve\.com/file/(?P<ID>[^/]+)' @@ -161,7 +161,7 @@ class FileserveCom(Hoster): recaptcha = ReCaptcha(self) for _i in xrange(5): - challenge, response = recaptcha.challenge(captcha_key) + response, challenge = recaptcha.challenge(captcha_key) res = json_loads(self.load(self.URLS[2], post={'recaptcha_challenge_field' : challenge, 'recaptcha_response_field' : response, diff --git a/module/plugins/hoster/FourSharedCom.py b/module/plugins/hoster/FourSharedCom.py index 78aeece44..a3f53ac5e 100644 --- a/module/plugins/hoster/FourSharedCom.py +++ b/module/plugins/hoster/FourSharedCom.py @@ -53,7 +53,7 @@ class FourSharedCom(SimpleHoster): m = re.search(self.ID_PATTERN, self.html) res = self.load('http://www.4shared.com/web/d2/getFreeDownloadLimitInfo?fileId=%s' % m.group(1)) self.logDebug(res) - except: + except Exception: pass self.wait(20) diff --git a/module/plugins/hoster/FshareVn.py b/module/plugins/hoster/FshareVn.py index 872511afc..4912974ad 100644 --- a/module/plugins/hoster/FshareVn.py +++ b/module/plugins/hoster/FshareVn.py @@ -25,7 +25,7 @@ def doubleDecode(m): class FshareVn(SimpleHoster): __name__ = "FshareVn" __type__ = "hoster" - __version__ = "0.19" + __version__ = "0.20" __pattern__ = r'http://(?:www\.)?fshare\.vn/file/.+' @@ -58,7 +58,7 @@ class FshareVn(SimpleHoster): self.checkErrors() action, inputs = self.parseHtmlForm('frm_download') - self.url = urljoin(pyfile.url, action) + url = urljoin(pyfile.url, action) if not inputs: self.error(_("No FORM")) @@ -69,7 +69,7 @@ class FshareVn(SimpleHoster): if password: self.logInfo(_("Password protected link, trying ") + password) inputs['link_file_pwd_dl'] = password - self.html = self.load(self.url, post=inputs, decode=True) + self.html = self.load(url, post=inputs, decode=True) if 'name="link_file_pwd_dl"' in self.html: self.fail(_("Incorrect password")) @@ -77,7 +77,7 @@ class FshareVn(SimpleHoster): self.fail(_("No password found")) else: - self.html = self.load(self.url, post=inputs, decode=True) + self.html = self.load(url, post=inputs, decode=True) self.checkErrors() @@ -87,11 +87,9 @@ class FshareVn(SimpleHoster): m = re.search(self.LINK_FREE_PATTERN, self.html) if m is None: self.error(_("LINK_FREE_PATTERN not found")) - self.url = m.group(1) - self.logDebug("FREE DL URL: %s" % self.url) - + + self.link = m.group(1) self.wait() - self.download(self.url) def checkErrors(self): diff --git a/module/plugins/hoster/Ftp.py b/module/plugins/hoster/Ftp.py index 8562778c4..22fc5f67a 100644 --- a/module/plugins/hoster/Ftp.py +++ b/module/plugins/hoster/Ftp.py @@ -35,7 +35,7 @@ class Ftp(Hoster): pyfile.name = parsed_url.path.rpartition('/')[2] try: pyfile.name = unquote(str(pyfile.name)).decode('utf8') - except: + except Exception: pass if not "@" in netloc: diff --git a/module/plugins/hoster/HellshareCz.py b/module/plugins/hoster/HellshareCz.py index 47b981dd7..05caf052d 100644 --- a/module/plugins/hoster/HellshareCz.py +++ b/module/plugins/hoster/HellshareCz.py @@ -8,7 +8,7 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class HellshareCz(SimpleHoster): __name__ = "HellshareCz" __type__ = "hoster" - __version__ = "0.84" + __version__ = "0.85" __pattern__ = r'http://(?:www\.)?hellshare\.(?:cz|com|sk|hu|pl)/[^?]*/\d+' @@ -32,10 +32,4 @@ class HellshareCz(SimpleHoster): self.chunkLimit = 1 - def downloadLink(self, link): - if link and isinstance(link, basestring): - self.correctCaptcha() - self.download(urljoin("http://www.hellshare.com/", link), disposition=True) - - getInfo = create_getInfo(HellshareCz) diff --git a/module/plugins/hoster/HugefilesNet.py b/module/plugins/hoster/HugefilesNet.py index f7221f8c5..b7e599a50 100644 --- a/module/plugins/hoster/HugefilesNet.py +++ b/module/plugins/hoster/HugefilesNet.py @@ -17,8 +17,6 @@ class HugefilesNet(XFSHoster): __authors__ = [("stickell", "l.stickell@yahoo.it")] - HOSTER_DOMAIN = "hugefiles.net" - SIZE_PATTERN = r'File Size:</span>\s*<span[^>]*>(?P<S>[^<]+)</span></div>' FORM_INPUTS_MAP = {'ctype': re.compile(r'\d+')} diff --git a/module/plugins/hoster/HundredEightyUploadCom.py b/module/plugins/hoster/HundredEightyUploadCom.py index 4fc96a2b1..32d36ddb9 100644 --- a/module/plugins/hoster/HundredEightyUploadCom.py +++ b/module/plugins/hoster/HundredEightyUploadCom.py @@ -15,7 +15,5 @@ class HundredEightyUploadCom(XFSHoster): __authors__ = [("stickell", "l.stickell@yahoo.it")] - HOSTER_DOMAIN = "180upload.com" - getInfo = create_getInfo(HundredEightyUploadCom) diff --git a/module/plugins/hoster/JunocloudMe.py b/module/plugins/hoster/JunocloudMe.py index 56d6588fa..415d5e2d0 100644 --- a/module/plugins/hoster/JunocloudMe.py +++ b/module/plugins/hoster/JunocloudMe.py @@ -15,8 +15,6 @@ class JunocloudMe(XFSHoster): __authors__ = [("guidobelix", "guidobelix@hotmail.it")] - HOSTER_DOMAIN = "junocloud.me" - URL_REPLACEMENTS = [(r'//(www\.)?junocloud', "//dl3.junocloud")] OFFLINE_PATTERN = r'>No such file with this filename<' diff --git a/module/plugins/hoster/Keep2shareCc.py b/module/plugins/hoster/Keep2ShareCc.py index 05b3c639d..34bc3de54 100644 --- a/module/plugins/hoster/Keep2shareCc.py +++ b/module/plugins/hoster/Keep2ShareCc.py @@ -2,7 +2,7 @@ import re -from urlparse import urljoin, urlparse +from urlparse import urljoin from module.plugins.internal.CaptchaService import ReCaptcha from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo @@ -11,7 +11,7 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class Keep2ShareCc(SimpleHoster): __name__ = "Keep2ShareCc" __type__ = "hoster" - __version__ = "0.19" + __version__ = "0.21" __pattern__ = r'https?://(?:www\.)?(keep2share|k2s|keep2s)\.cc/file/(?P<ID>\w+)' @@ -29,7 +29,8 @@ class Keep2ShareCc(SimpleHoster): OFFLINE_PATTERN = r'File not found or deleted|Sorry, this file is blocked or deleted|Error 404' TEMP_OFFLINE_PATTERN = r'Downloading blocked due to' - LINK_FREE_PATTERN = LINK_PREMIUM_PATTERN = r'"([^"]+url.html?file=.+?)"|window\.location\.href = \'(.+?)\';' + LINK_FREE_PATTERN = r'"([^"]+url.html?file=.+?)"|window\.location\.href = \'(.+?)\';' + LINK_PREMIUM_PATTERN = r'window\.location\.href = \'(.+?)\';' CAPTCHA_PATTERN = r'src="(/file/captcha\.html.+?)"' @@ -64,9 +65,9 @@ class Keep2ShareCc(SimpleHoster): self.info.pop('error', None) - def handleFree(self): + def handleFree(self, pyfile): self.fid = re.search(r'<input type="hidden" name="slow_id" value="([^"]+)">', self.html).group(1) - self.html = self.load(self.pyfile.url, post={'yt0': '', 'slow_id': self.fid}) + self.html = self.load(pyfile.url, post={'yt0': '', 'slow_id': self.fid}) self.checkErrors() @@ -77,54 +78,37 @@ class Keep2ShareCc(SimpleHoster): self.wait(30) - self.html = self.load(self.pyfile.url, post={'uniqueId': self.fid, 'free': 1}) - - self.checkErrors() + self.html = self.load(pyfile.url) m = re.search(self.LINK_FREE_PATTERN, self.html) if m is None: - self.error(_("LINK_FREE_PATTERN not found")) + self.error(_("Free download link not found")) self.link = m.group(1) def handleCaptcha(self): recaptcha = ReCaptcha(self) + post_data = {'free' : 1, + 'freeDownloadRequest': 1, + 'uniqueId' : self.fid, + 'yt0' : ''} - for _i in xrange(5): - post_data = {'free' : 1, - 'freeDownloadRequest': 1, - 'uniqueId' : self.fid, - 'yt0' : ''} - - m = re.search(self.CAPTCHA_PATTERN, self.html) - if m: - captcha_url = urljoin("http://k2s.cc/", m.group(1)) - post_data['CaptchaForm[code]'] = self.decryptCaptcha(captcha_url) - else: - challenge, response = recaptcha.challenge() - post_data.update({'recaptcha_challenge_field': challenge, - 'recaptcha_response_field' : response}) - - self.html = self.load(self.pyfile.url, post=post_data) - - if 'recaptcha' not in self.html: - self.correctCaptcha() - break - else: - self.invalidCaptcha() + m = re.search(self.CAPTCHA_PATTERN, self.html) + if m: + captcha_url = urljoin("http://k2s.cc/", m.group(1)) + post_data['CaptchaForm[code]'] = self.decryptCaptcha(captcha_url) else: - self.fail(_("All captcha attempts failed")) - + response, challenge = recaptcha.challenge() + post_data.update({'recaptcha_challenge_field': challenge, + 'recaptcha_response_field' : response}) - def downloadLink(self, link): - if not link or not isinstance(link, basestring): - return + self.html = self.load(self.pyfile.url, post=post_data) - link = self.directLink(self, link, self.resumeDownload) - - if link: - self.download(urljoin("http://k2s.cc/", link), disposition=True) + if 'verification code is incorrect' not in self.html: + self.correctCaptcha() + else: + self.invalidCaptcha() getInfo = create_getInfo(Keep2ShareCc) diff --git a/module/plugins/hoster/KingfilesNet.py b/module/plugins/hoster/KingfilesNet.py index a75ef5f3e..eb4d34cc2 100644 --- a/module/plugins/hoster/KingfilesNet.py +++ b/module/plugins/hoster/KingfilesNet.py @@ -9,7 +9,7 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class KingfilesNet(SimpleHoster): __name__ = "KingfilesNet" __type__ = "hoster" - __version__ = "0.06" + __version__ = "0.07" __pattern__ = r'http://(?:www\.)?kingfiles\.net/(?P<ID>\w{12})' @@ -46,7 +46,7 @@ class KingfilesNet(SimpleHoster): self.html = self.load(pyfile.url, post=post_data, cookies=True, decode=True) solvemedia = SolveMedia(self) - challenge, response = solvemedia.challenge() + response, challenge = solvemedia.challenge() # Make the downloadlink appear and load the file m = re.search(self.RAND_ID_PATTERN, self.html) diff --git a/module/plugins/hoster/LetitbitNet.py b/module/plugins/hoster/LetitbitNet.py index 6d5641778..cd922aea7 100644 --- a/module/plugins/hoster/LetitbitNet.py +++ b/module/plugins/hoster/LetitbitNet.py @@ -36,7 +36,7 @@ def getInfo(urls): class LetitbitNet(SimpleHoster): __name__ = "LetitbitNet" __type__ = "hoster" - __version__ = "0.29" + __version__ = "0.30" __pattern__ = r'https?://(?:www\.)?(letitbit|shareflare)\.net/download/.+' @@ -96,7 +96,7 @@ class LetitbitNet(SimpleHoster): self.logDebug(res) recaptcha = ReCaptcha(self) - challenge, response = recaptcha.challenge() + response, challenge = recaptcha.challenge() post_data = {"recaptcha_challenge_field": challenge, "recaptcha_response_field": response, diff --git a/module/plugins/hoster/LoadTo.py b/module/plugins/hoster/LoadTo.py index b21a69b5f..6f4e8d73c 100644 --- a/module/plugins/hoster/LoadTo.py +++ b/module/plugins/hoster/LoadTo.py @@ -13,7 +13,7 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class LoadTo(SimpleHoster): __name__ = "LoadTo" __type__ = "hoster" - __version__ = "0.19" + __version__ = "0.20" __pattern__ = r'http://(?:www\.)?load\.to/\w+' @@ -49,7 +49,7 @@ class LoadTo(SimpleHoster): # Set Timer - may be obsolete m = re.search(self.WAIT_PATTERN, self.html) if m: - self.wait(int(m.group(1))) + self.wait(m.group(1)) # Load.to is using solvemedia captchas since ~july 2014: solvemedia = SolveMedia(self) @@ -58,7 +58,7 @@ class LoadTo(SimpleHoster): if captcha_key is None: self.download(download_url) else: - challenge, response = solvemedia.challenge(captcha_key) + response, challenge = solvemedia.challenge(captcha_key) self.download(download_url, post={"adcopy_challenge": challenge, "adcopy_response": response}) diff --git a/module/plugins/hoster/LuckyShareNet.py b/module/plugins/hoster/LuckyShareNet.py index 09300a41a..74bf877f1 100644 --- a/module/plugins/hoster/LuckyShareNet.py +++ b/module/plugins/hoster/LuckyShareNet.py @@ -11,7 +11,7 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class LuckyShareNet(SimpleHoster): __name__ = "LuckyShareNet" __type__ = "hoster" - __version__ = "0.05" + __version__ = "0.06" __pattern__ = r'https?://(?:www\.)?luckyshare\.net/(?P<ID>\d{10,})' @@ -47,12 +47,12 @@ class LuckyShareNet(SimpleHoster): self.logDebug("JSON: " + rep) json = self.parseJson(rep) - self.wait(int(json['time'])) + self.wait(json['time']) recaptcha = ReCaptcha(self) for _i in xrange(5): - challenge, response = recaptcha.challenge() + response, challenge = recaptcha.challenge() rep = self.load(r"http://luckyshare.net/download/verify/challenge/%s/response/%s/hash/%s" % (challenge, response, json['hash']), decode=True) self.logDebug("JSON: " + rep) diff --git a/module/plugins/hoster/MediafireCom.py b/module/plugins/hoster/MediafireCom.py index 81bd36f73..bc81c8202 100644 --- a/module/plugins/hoster/MediafireCom.py +++ b/module/plugins/hoster/MediafireCom.py @@ -33,7 +33,7 @@ def checkHTMLHeader(url): return url, 2 else: break - except: + except Exception: return url, 3 else: return url, 0 @@ -54,7 +54,7 @@ def getInfo(urls): class MediafireCom(SimpleHoster): __name__ = "MediafireCom" __type__ = "hoster" - __version__ = "0.83" + __version__ = "0.84" __pattern__ = r'http://(?:www\.)?mediafire\.com/(file/|(view/?|download\.php)?\?)(\w{11}|\w{15})($|/)' @@ -121,7 +121,7 @@ class MediafireCom(SimpleHoster): def checkCaptcha(self): solvemedia = SolveMedia(self) - challenge, response = solvemedia.challenge() + response, challenge = solvemedia.challenge() self.html = self.load(self.link, post={'adcopy_challenge': challenge, 'adcopy_response' : response}, diff --git a/module/plugins/hoster/MegaCoNz.py b/module/plugins/hoster/MegaCoNz.py index fbd34c563..4ad20b265 100644 --- a/module/plugins/hoster/MegaCoNz.py +++ b/module/plugins/hoster/MegaCoNz.py @@ -124,7 +124,7 @@ class MegaCoNz(Hoster): df = open(file_decrypted, "wb") except IOError, e: - self.fail(str(e)) + self.fail(e) chunk_size = 2 ** 15 # buffer size, 32k # file_mac = [0, 0, 0, 0] # calculate CBC-MAC for checksum @@ -160,7 +160,7 @@ class MegaCoNz(Hoster): # if file_mac[0] ^ file_mac[1], file_mac[2] ^ file_mac[3] != meta_mac: # os.remove(file_decrypted) - # self.fail("Checksum mismatch") + # self.fail(_("Checksum mismatch")) os.remove(file_crypted) self.lastDownload = fs_decode(file_decrypted) diff --git a/module/plugins/hoster/MovReelCom.py b/module/plugins/hoster/MovReelCom.py index 9bb63701c..9b8679c10 100644 --- a/module/plugins/hoster/MovReelCom.py +++ b/module/plugins/hoster/MovReelCom.py @@ -15,8 +15,6 @@ class MovReelCom(XFSHoster): __authors__ = [("JorisV83", "jorisv83-pyload@yahoo.com")] - HOSTER_DOMAIN = "movreel.com" - LINK_PATTERN = r'<a href="([^"]+)">Download Link' diff --git a/module/plugins/hoster/MultihostersCom.py b/module/plugins/hoster/MultihostersCom.py index c5a48310e..bcd7c6237 100644 --- a/module/plugins/hoster/MultihostersCom.py +++ b/module/plugins/hoster/MultihostersCom.py @@ -1,12 +1,12 @@ # -*- coding: utf-8 -*- -from module.plugins.hosters.ZeveraCom import ZeveraCom +from module.plugins.hoster.ZeveraCom import ZeveraCom class MultihostersCom(ZeveraCom): __name__ = "MultihostersCom" __type__ = "hoster" - __version__ = "0.02" + __version__ = "0.03" __pattern__ = r'https?://(?:www\.)multihosters\.com/(getFiles\.ashx|Members/download\.ashx)\?.*ourl=.+' diff --git a/module/plugins/hoster/NetloadIn.py b/module/plugins/hoster/NetloadIn.py index 35c814656..3efbdce23 100644 --- a/module/plugins/hoster/NetloadIn.py +++ b/module/plugins/hoster/NetloadIn.py @@ -23,7 +23,7 @@ def getInfo(urls): for url in chunk: match = id_regex.search(url) if match: - ids = ids + match.group(1) + ";" + ids = ids + match.group('ID') + ";" api = getURL(apiurl, get={'auth' : "Zf9SnQh9WiReEsb18akjvQGqT0I830e8", @@ -62,9 +62,9 @@ def getInfo(urls): class NetloadIn(Hoster): __name__ = "NetloadIn" __type__ = "hoster" - __version__ = "0.47" + __version__ = "0.49" - __pattern__ = r'https?://(?:[^/]*\.)?netload\.in/(?:datei(.*?)(?:\.htm|/)|index\.php?id=10&file_id=)' + __pattern__ = r'https?://(?:www\.)?netload\.in/(?P<PATH>datei|index\.php\?id=10&file_id=)(?P<ID>\w+)' __description__ = """Netload.in hoster plugin""" __license__ = "GPLv3" @@ -73,6 +73,9 @@ class NetloadIn(Hoster): ("Gregy", "gregy@gregy.cz")] + RECAPTCHA_KEY = "6LcLJMQSAAAAAJzquPUPKNovIhbK6LpSqCjYrsR1" + + def setup(self): self.multiDL = self.resumeDownload = self.premium @@ -118,7 +121,7 @@ class NetloadIn(Hoster): if match: #normalize url - self.url = 'http://www.netload.in/datei%s.htm' % match.group(1) + self.url = 'http://www.netload.in/datei%s.htm' % match.group('ID') self.logDebug("URL: %s" % self.url) else: self.api_data = False @@ -126,7 +129,7 @@ class NetloadIn(Hoster): apiurl = "http://api.netload.in/info.php" html = self.load(apiurl, cookies=False, - get={"file_id": match.group(1), "auth": "Zf9SnQh9WiReEsb18akjvQGqT0I830e8", "bz": "1", + get={"file_id": match.group('ID'), "auth": "Zf9SnQh9WiReEsb18akjvQGqT0I830e8", "bz": "1", "md5": "1"}, decode=True).strip() if not html and n <= 3: self.setWait(2) @@ -235,7 +238,7 @@ class NetloadIn(Hoster): recaptcha = ReCaptcha(self) for _i in xrange(5): - challenge, response = recaptcha.challenge() + response, challenge = recaptcha.challenge(self.RECAPTCHA_KEY) response_page = self.load("http://www.netload.in/index.php?id=10", post={'captcha_check' : '1', @@ -254,7 +257,7 @@ class NetloadIn(Hoster): download_url = self.get_file_url(response_page) self.logDebug("Download URL after get_file: " + download_url) if not download_url.startswith("http://"): - self.error("download url: %s" % download_url) + self.error(_("Download url: %s") % download_url) self.wait() self.url = download_url diff --git a/module/plugins/hoster/NitroflareCom.py b/module/plugins/hoster/NitroflareCom.py index 2367493e5..e21d067b3 100644 --- a/module/plugins/hoster/NitroflareCom.py +++ b/module/plugins/hoster/NitroflareCom.py @@ -16,64 +16,86 @@ from module.plugins.internal.SimpleHoster import SimpleHoster class NitroflareCom(SimpleHoster): __name__ = "NitroflareCom" __type__ = "hoster" - __version__ = "0.03" + __version__ = "0.07" __pattern__ = r'https?://(?:www\.)?nitroflare\.com/view/(?P<ID>[\w^_]+)' __description__ = """Nitroflare.com hoster plugin""" __license__ = "GPLv3" - __authors__ = [("sahil", ""), + __authors__ = [("sahil", "sahilshekhawat01@gmail.com"), ("Walter Purcaro", "vuolter@gmail.com")] - # URL_REPLACEMENTS = [("http://", "https://")] - LINK_FREE_PATTERN = r'(https?://[\w\\-]+\\.nitroflare\\.com/[^<>\"]*?)"' + INFO_PATTERN = r'title="(?P<N>.+?)".+>(?P<S>[\d.,]+) (?P<U>[\w^_]+)' + OFFLINE_PATTERN = r'>File doesn\'t exist' + + LINK_FREE_PATTERN = r'(https?://[\w\-]+\.nitroflare\.com/.+?)"' + + RECAPTCHA_KEY = "6Lenx_USAAAAAF5L1pmTWvWcH73dipAEzNnmNLgy" + + PREMIUM_ONLY_PATTERN = r'This file is available with Premium only' + WAIT_PATTERN = r'You have to wait .+?<' + ERROR_PATTERN = r'downloading is not possible' + + + def checkErrors(self): + if not self.html: + return + + if not self.premium and re.search(self.PREMIUM_ONLY_PATTERN, self.html): + self.fail(_("Link require a premium account to be handled")) + + elif hasattr(self, 'WAIT_PATTERN'): + m = re.search(self.WAIT_PATTERN, self.html) + if m: + wait_time = sum([int(v) * {"hr": 3600, "hour": 3600, "min": 60, "sec": 1}[u.lower()] for v, u in + re.findall(r'(\d+)\s*(hr|hour|min|sec)', m.group(0), re.I)]) + self.wait(wait_time, wait_time > 300) + return + + elif hasattr(self, 'ERROR_PATTERN'): + m = re.search(self.ERROR_PATTERN, self.html) + if m: + errmsg = self.info['error'] = m.group(1) + self.error(errmsg) + + self.info.pop('error', None) def handleFree(self, pyfile): - file_info = self.load("https://nitroflare.com/api/getDownloadLink", - get={'file': self.info['pattern']['ID']}) - - self.logWarning(file_info[3:]) - file_info = json_loads(file_info[3:]) # removing non ascii characters - if file_info['type'] == "success": - result = file_info['result'] # already a dict - if result['linkType'] == "free": - delay = result['delay'] # Don't need the delay for free downloads - captch_key = result['recaptchaPublic'] - filename = result['name'] - recaptcha = ReCaptcha(self) - # try upto 3 times to solve reCaptcha - for i in xrange(3): - challenge, response = recaptcha.challenge(key=captch_key) - res = self.load("https://nitroflare.com/ajax/freeDownload.php", - post={"method": "fetchDownload", - "recaptcha_challenge_field": challenge, - "recaptcha_response_field": response}) - if self.handleCaptchaErrors(res): - break - if "The captcha wasn't entered correctly" or "You have to fill the captcha" in res: - continue - else: - break - - if "The captcha wasn't entered correctly" or "You have to fill the captcha" in res: - self.logError("Captcha Failed") - self.offline() - # Captcha failed - else: - self.logInfo("result of the captcha is") - self.logInfo(res) - # self.offline() - download_link = re.search(self.DOWNLOAD_PATTERN, res) - if download_link is None: - print "downloasd link failed" - # Download link failed - else: - self.download(download_link) - else: - print "link is invalid" - self.offline() - # Link is invalid - # self.download() + # used here to load the cookies which will be required later + self.load(pyfile.url, post={'goToFreePage': ""}) + + self.html = self.load("http://nitroflare.com/ajax/freeDownload.php", + post={'method': "startTimer", 'fileId': self.info['pattern']['ID']})[4:] + + self.checkErrors() + + try: + js_file = self.load("http://nitroflare.com/js/downloadFree.js?v=1.0.1") + var_time = re.search("var time = (\\d+);", js_file) + wait_time = int(var_time.groups()[0]) + + except Exception: + wait_time = 60 + + self.wait(wait_time) + + recaptcha = ReCaptcha(self) + response, challenge = recaptcha.challenge(self.RECAPTCHA_KEY) + + self.html = self.load("http://nitroflare.com/ajax/freeDownload.php", + post={'method' : "fetchDownload", + 'recaptcha_challenge_field': challenge, + 'recaptcha_response_field' : response})[3:] + + self.logDebug(self.html) + + if "The captcha wasn't entered correctly" in self.html: + return + + if "You have to fill the captcha" in self.html: + return + + self.link = re.search(self.LINK_FREE_PATTERN, self.html) diff --git a/module/plugins/hoster/NoPremiumPl.py b/module/plugins/hoster/NoPremiumPl.py index 361d48c2d..43ae8b3cc 100644 --- a/module/plugins/hoster/NoPremiumPl.py +++ b/module/plugins/hoster/NoPremiumPl.py @@ -83,14 +83,14 @@ class NoPremiumPl(MultiHoster): # error code isn't yet added to plugin self.fail( parsed["errstring"] - or "Unknown error (code: %s)" % parsed["errno"] + or _("Unknown error (code: %s)") % parsed["errno"] ) if "sdownload" in parsed: if parsed["sdownload"] == "1": self.fail( - "Download from %s is possible only using NoPremium.pl webiste \ - directly. Update this plugin." % parsed["hosting"]) + _("Download from %s is possible only using NoPremium.pl website \ + directly") % parsed["hosting"]) pyfile.name = parsed["filename"] pyfile.size = parsed["filesize"] diff --git a/module/plugins/hoster/NosuploadCom.py b/module/plugins/hoster/NosuploadCom.py index 8a03d7090..aeedd54f6 100644 --- a/module/plugins/hoster/NosuploadCom.py +++ b/module/plugins/hoster/NosuploadCom.py @@ -17,8 +17,6 @@ class NosuploadCom(XFSHoster): __authors__ = [("igel", "igelkun@myopera.com")] - HOSTER_DOMAIN = "nosupload.com" - SIZE_PATTERN = r'<p><strong>Size:</strong> (?P<S>[\d.,]+) (?P<U>[\w^_]+)</p>' LINK_PATTERN = r'<a class="select" href="(http://.+?)">Download</a>' diff --git a/module/plugins/hoster/NovafileCom.py b/module/plugins/hoster/NovafileCom.py index 9754ceed1..bdd66473b 100644 --- a/module/plugins/hoster/NovafileCom.py +++ b/module/plugins/hoster/NovafileCom.py @@ -20,8 +20,6 @@ class NovafileCom(XFSHoster): ("stickell", "l.stickell@yahoo.it")] - HOSTER_DOMAIN = "novafile.com" - ERROR_PATTERN = r'class="alert[^"]*alert-separate"[^>]*>\s*(?:<p>)?(.*?)\s*</' WAIT_PATTERN = r'<p>Please wait <span id="count"[^>]*>(\d+)</span> seconds</p>' diff --git a/module/plugins/hoster/OboomCom.py b/module/plugins/hoster/OboomCom.py index 588d8f64a..725763345 100644 --- a/module/plugins/hoster/OboomCom.py +++ b/module/plugins/hoster/OboomCom.py @@ -13,7 +13,7 @@ from module.plugins.internal.CaptchaService import ReCaptcha class OboomCom(Hoster): __name__ = "OboomCom" __type__ = "hoster" - __version__ = "0.30" + __version__ = "0.31" __pattern__ = r'https?://(?:www\.)?oboom\.com/(#(id=|/)?)?(?P<ID>\w{8})' @@ -74,7 +74,7 @@ class OboomCom(Hoster): recaptcha = ReCaptcha(self) for _i in xrange(5): - challenge, response = recaptcha.challenge(self.RECAPTCHA_KEY) + response, challenge = recaptcha.challenge(self.RECAPTCHA_KEY) apiUrl = "https://www.oboom.com/1.0/download/ticket" params = {"recaptcha_challenge_field": challenge, "recaptcha_response_field": response, diff --git a/module/plugins/hoster/OneFichierCom.py b/module/plugins/hoster/OneFichierCom.py index f9c0dbe85..2e9e52813 100644 --- a/module/plugins/hoster/OneFichierCom.py +++ b/module/plugins/hoster/OneFichierCom.py @@ -8,7 +8,7 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class OneFichierCom(SimpleHoster): __name__ = "OneFichierCom" __type__ = "hoster" - __version__ = "0.76" + __version__ = "0.77" __pattern__ = r'https?://(?:www\.)?(?:(?P<ID1>\w+)\.)?(?P<HOST>1fichier\.com|alterupload\.com|cjoint\.net|d(es)?fichiers\.com|dl4free\.com|megadl\.fr|mesfichiers\.org|piecejointe\.net|pjointe\.com|tenvoi\.com)(?:/\?(?P<ID2>\w+))?' @@ -54,7 +54,7 @@ class OneFichierCom(SimpleHoster): def handlePremium(self, pyfile): - return self.handleFree(pyfile) + self.download(pyfile.url, post={'dl': "Download", 'did': 0}) getInfo = create_getInfo(OneFichierCom) diff --git a/module/plugins/hoster/PutdriveCom.py b/module/plugins/hoster/PutdriveCom.py index 67732a4cd..7f4b7b6cc 100644 --- a/module/plugins/hoster/PutdriveCom.py +++ b/module/plugins/hoster/PutdriveCom.py @@ -1,12 +1,12 @@ # -*- coding: utf-8 -*- -from module.plugins.hosters.ZeveraCom import ZeveraCom +from module.plugins.hoster.ZeveraCom import ZeveraCom class PutdriveCom(ZeveraCom): __name__ = "PutdriveCom" __type__ = "hoster" - __version__ = "0.01" + __version__ = "0.02" __pattern__ = r'https?://(?:www\.)putdrive\.com/(getFiles\.ashx|Members/download\.ashx)\?.*ourl=.+' diff --git a/module/plugins/hoster/RapideoPl.py b/module/plugins/hoster/RapideoPl.py index 2f7365e3b..85591f51f 100644 --- a/module/plugins/hoster/RapideoPl.py +++ b/module/plugins/hoster/RapideoPl.py @@ -83,14 +83,14 @@ class RapideoPl(MultiHoster): # error code isn't yet added to plugin self.fail( parsed["errstring"] - or "Unknown error (code: %s)" % parsed["errno"] + or _("Unknown error (code: %s)") % parsed["errno"] ) if "sdownload" in parsed: if parsed["sdownload"] == "1": self.fail( - "Download from %s is possible only using Rapideo.pl webiste \ - directly. Update this plugin." % parsed["hosting"]) + _("Download from %s is possible only using Rapideo.pl website \ + directly") % parsed["hosting"]) pyfile.name = parsed["filename"] pyfile.size = parsed["filesize"] diff --git a/module/plugins/hoster/RapidfileshareNet.py b/module/plugins/hoster/RapidfileshareNet.py index 3473b1c7c..0bbaed57f 100644 --- a/module/plugins/hoster/RapidfileshareNet.py +++ b/module/plugins/hoster/RapidfileshareNet.py @@ -15,8 +15,6 @@ class RapidfileshareNet(XFSHoster): __authors__ = [("guidobelix", "guidobelix@hotmail.it")] - HOSTER_DOMAIN = "rapidfileshare.net" - NAME_PATTERN = r'<input type="hidden" name="fname" value="(?P<N>.+?)">' SIZE_PATTERN = r'>http://www.rapidfileshare.net/\w+?</font> \((?P<S>[\d.,]+) (?P<U>[\w^_]+)\)</font>' diff --git a/module/plugins/hoster/RapidgatorNet.py b/module/plugins/hoster/RapidgatorNet.py index 84c3b20d6..f7e6534f2 100644 --- a/module/plugins/hoster/RapidgatorNet.py +++ b/module/plugins/hoster/RapidgatorNet.py @@ -13,7 +13,7 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo, s class RapidgatorNet(SimpleHoster): __name__ = "RapidgatorNet" __type__ = "hoster" - __version__ = "0.29" + __version__ = "0.31" __pattern__ = r'http://(?:www\.)?(rapidgator\.net|rg\.to)/file/\w+' @@ -46,7 +46,7 @@ class RapidgatorNet(SimpleHoster): def setup(self): if self.account: - self.sid = self.account.getAccountInfo(self.user).get('SID', None) + self.sid = self.account.getAccountInfo(self.user).get('sid', None) else: self.sid = None @@ -107,7 +107,7 @@ class RapidgatorNet(SimpleHoster): jsvars.get('startTimerUrl', '/download/AjaxStartTimer'), jsvars['fid']) jsvars.update(self.getJsonResponse(url)) - self.wait(int(jsvars.get('secs', 45)), False) + self.wait(jsvars.get('secs', 45), False) url = "http://rapidgator.net%s?sid=%s" % ( jsvars.get('getDownloadUrl', '/download/AjaxGetDownload'), jsvars['sid']) @@ -128,7 +128,7 @@ class RapidgatorNet(SimpleHoster): break else: captcha, captcha_key = self.getCaptcha() - challenge, response = captcha.challenge(captcha_key) + response, challenge = captcha.challenge(captcha_key) self.html = self.load(url, post={'DownloadCaptchaForm[captcha]': "", 'adcopy_challenge' : challenge, @@ -146,17 +146,17 @@ class RapidgatorNet(SimpleHoster): m = re.search(self.ADSCAPTCHA_PATTERN, self.html) if m: captcha_key = m.group(1) - captcha = AdsCaptcha(self) + captcha = AdsCaptcha(self) else: m = re.search(self.RECAPTCHA_PATTERN, self.html) if m: captcha_key = m.group(1) - captcha = ReCaptcha(self) + captcha = ReCaptcha(self) else: m = re.search(self.SOLVEMEDIA_PATTERN, self.html) if m: captcha_key = m.group(1) - captcha = SolveMedia(self) + captcha = SolveMedia(self) else: self.error(_("Captcha")) diff --git a/module/plugins/hoster/RapiduNet.py b/module/plugins/hoster/RapiduNet.py index 0c40d95b9..b6806e49b 100644 --- a/module/plugins/hoster/RapiduNet.py +++ b/module/plugins/hoster/RapiduNet.py @@ -13,7 +13,7 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class RapiduNet(SimpleHoster): __name__ = "RapiduNet" __type__ = "hoster" - __version__ = "0.05" + __version__ = "0.06" __pattern__ = r'https?://(?:www\.)?rapidu\.net/(?P<ID>\d{10})' @@ -59,7 +59,7 @@ class RapiduNet(SimpleHoster): recaptcha = ReCaptcha(self) for _i in xrange(10): - challenge, response = recaptcha.challenge(self.RECAPTCHA_KEY) + response, challenge = recaptcha.challenge(self.RECAPTCHA_KEY) jsvars = self.getJsonResponse("https://rapidu.net/ajax.php", get={'a': "getCheckCaptcha"}, diff --git a/module/plugins/hoster/RarefileNet.py b/module/plugins/hoster/RarefileNet.py index 2be952efe..a45e4ed4d 100644 --- a/module/plugins/hoster/RarefileNet.py +++ b/module/plugins/hoster/RarefileNet.py @@ -17,8 +17,6 @@ class RarefileNet(XFSHoster): __authors__ = [("zoidberg", "zoidberg@mujmail.cz")] - HOSTER_DOMAIN = "rarefile.net" - LINK_PATTERN = r'<a href="(.+?)">\1</a>' diff --git a/module/plugins/hoster/RemixshareCom.py b/module/plugins/hoster/RemixshareCom.py index 11c9f3b0f..590f8daf5 100644 --- a/module/plugins/hoster/RemixshareCom.py +++ b/module/plugins/hoster/RemixshareCom.py @@ -54,7 +54,7 @@ class RemixshareCom(SimpleHoster): seconds = re.search(self.WAIT_PATTERN, self.html) if seconds: self.logDebug("Wait " + seconds.group(1)) - self.wait(int(seconds.group(1))) + self.wait(seconds.group(1)) # Finally start downloading... self.download(dl_url, disposition=True) diff --git a/module/plugins/hoster/SafesharingEu.py b/module/plugins/hoster/SafesharingEu.py index bb6e0f646..08612e413 100644 --- a/module/plugins/hoster/SafesharingEu.py +++ b/module/plugins/hoster/SafesharingEu.py @@ -15,8 +15,6 @@ class SafesharingEu(XFSHoster): __authors__ = [("zapp-brannigan", "fuerst.reinje@web.de")] - HOSTER_DOMAIN = "safesharing.eu" - ERROR_PATTERN = r'(?:<div class="alert alert-danger">)(.+?)(?:</div>)' diff --git a/module/plugins/hoster/SecureUploadEu.py b/module/plugins/hoster/SecureUploadEu.py index 64e6456a9..6bfbce328 100644 --- a/module/plugins/hoster/SecureUploadEu.py +++ b/module/plugins/hoster/SecureUploadEu.py @@ -15,8 +15,6 @@ class SecureUploadEu(XFSHoster): __authors__ = [("z00nx", "z00nx0@gmail.com")] - HOSTER_DOMAIN = "secureupload.eu" - INFO_PATTERN = r'<h3>Downloading (?P<N>[^<]+) \((?P<S>[^<]+)\)</h3>' diff --git a/module/plugins/hoster/Share4webCom.py b/module/plugins/hoster/Share4WebCom.py index 7a276c1fe..7a276c1fe 100644 --- a/module/plugins/hoster/Share4webCom.py +++ b/module/plugins/hoster/Share4WebCom.py diff --git a/module/plugins/hoster/ShareonlineBiz.py b/module/plugins/hoster/ShareonlineBiz.py index 636e5824d..6f49711b8 100644 --- a/module/plugins/hoster/ShareonlineBiz.py +++ b/module/plugins/hoster/ShareonlineBiz.py @@ -14,7 +14,7 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class ShareonlineBiz(SimpleHoster): __name__ = "ShareonlineBiz" __type__ = "hoster" - __version__ = "0.47" + __version__ = "0.48" __pattern__ = r'https?://(?:www\.)?(share-online\.biz|egoshare\.com)/(download\.php\?id=|dl/)(?P<ID>\w+)' @@ -69,7 +69,7 @@ class ShareonlineBiz(SimpleHoster): recaptcha = ReCaptcha(self) for _i in xrange(5): - challenge, response = recaptcha.challenge(self.RECAPTCHA_KEY) + response, challenge = recaptcha.challenge(self.RECAPTCHA_KEY) m = re.search(r'var wait=(\d+);', self.html) self.setWait(int(m.group(1)) if m else 30) @@ -164,7 +164,7 @@ class ShareonlineBiz(SimpleHoster): try: self.logError(errmsg, re.search(self.ERROR_PATTERN, self.html).group(1)) - except: + except Exception: self.logError("Unknown error occurred", errmsg) if errmsg is "invalid": diff --git a/module/plugins/hoster/SpeedyshareCom.py b/module/plugins/hoster/SpeedyshareCom.py index 0acdb7647..f21b0a3a7 100644 --- a/module/plugins/hoster/SpeedyshareCom.py +++ b/module/plugins/hoster/SpeedyshareCom.py @@ -13,7 +13,7 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class SpeedyshareCom(SimpleHoster): __name__ = "SpeedyshareCom" __type__ = "hoster" - __version__ = "0.04" + __version__ = "0.05" __pattern__ = r'https?://(?:www\.)?(speedyshare\.com|speedy\.sh)/\w+' @@ -38,10 +38,7 @@ class SpeedyshareCom(SimpleHoster): def handleFree(self, pyfile): m = re.search(self.LINK_FREE_PATTERN, self.html) if m is None: - self.error(_("Download link not found")) - - dl_link = urljoin("http://www.speedyshare.com", m.group(1)) - self.download(dl_link, disposition=True) + self.link = m.group(1) getInfo = create_getInfo(SpeedyshareCom) diff --git a/module/plugins/hoster/StreamcloudEu.py b/module/plugins/hoster/StreamcloudEu.py index b9d6d9ae6..54f430508 100644 --- a/module/plugins/hoster/StreamcloudEu.py +++ b/module/plugins/hoster/StreamcloudEu.py @@ -17,8 +17,6 @@ class StreamcloudEu(XFSHoster): __authors__ = [("seoester", "seoester@googlemail.com")] - HOSTER_DOMAIN = "streamcloud.eu" - WAIT_PATTERN = r'var count = (\d+)' LINK_PATTERN = r'file: "(http://(stor|cdn)\d+\.streamcloud\.eu:?\d*/.*/video\.(mp4|flv))",' diff --git a/module/plugins/hoster/TurbobitNet.py b/module/plugins/hoster/TurbobitNet.py index ccca76018..03e18a9cd 100644 --- a/module/plugins/hoster/TurbobitNet.py +++ b/module/plugins/hoster/TurbobitNet.py @@ -17,7 +17,7 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo, t class TurbobitNet(SimpleHoster): __name__ = "TurbobitNet" __type__ = "hoster" - __version__ = "0.17" + __version__ = "0.19" __pattern__ = r'http://(?:www\.)?turbobit\.net/(?:download/free/)?(?P<ID>\w+)' @@ -35,15 +35,15 @@ class TurbobitNet(SimpleHoster): SIZE_PATTERN = r'class="file-size">(?P<S>[\d.,]+) (?P<U>[\w^_]+)' OFFLINE_PATTERN = r'<h2>File Not Found</h2>|html\(\'File (?:was )?not found' - LINK_PATTERN = r'(/download/redirect/[^"\']+)' + LINK_FREE_PATTERN = LINK_PREMIUM_PATTERN = r'(/download/redirect/[^"\']+)' LIMIT_WAIT_PATTERN = r'<div id=\'timeout\'>(\d+)<' CAPTCHA_PATTERN = r'<img alt="Captcha" src="(.+?)"' def handleFree(self, pyfile): - self.url = "http://turbobit.net/download/free/%s" % self.info['pattern']['ID'] - self.html = self.load(self.url, ref=True, decode=True) + self.html = self.load("http://turbobit.net/download/free/%s" % self.info['pattern']['ID'], + decode=True) rtUpdate = self.getRtUpdate() @@ -51,14 +51,13 @@ class TurbobitNet(SimpleHoster): self.req.http.c.setopt(HTTPHEADER, ["X-Requested-With: XMLHttpRequest"]) - self.url = self.getDownloadUrl(rtUpdate) - - self.wait() - self.html = self.load(self.url) + self.html = self.load(self.getDownloadUrl(rtUpdate)) self.req.http.c.setopt(HTTPHEADER, ["X-Requested-With:"]) - self.downloadFile() + m = re.search(self.LINK_FREE_PATTERN, self.html) + if m: + self.link = m.group(1) def solveCaptcha(self): @@ -76,7 +75,7 @@ class TurbobitNet(SimpleHoster): if inputs['captcha_type'] == 'recaptcha': recaptcha = ReCaptcha(self) - inputs['recaptcha_challenge_field'], inputs['recaptcha_response_field'] = recaptcha.challenge() + inputs['recaptcha_response_field'], inputs['recaptcha_challenge_field'] = recaptcha.challenge() else: m = re.search(self.CAPTCHA_PATTERN, self.html) if m is None: @@ -141,13 +140,17 @@ class TurbobitNet(SimpleHoster): self.logDebug("URL", self.js.engine, out) if out.startswith('/download/'): return "http://turbobit.net%s" % out.strip() + except Exception, e: self.logError(e) else: if self.retries >= 2: # retry with updated js self.delStorage("rtUpdate") - self.retry() + else: + self.retry() + + self.wait() def decrypt(self, data): @@ -161,17 +164,4 @@ class TurbobitNet(SimpleHoster): return "%s GMT%+03d%02d" % (time.strftime("%a %b %d %Y %H:%M:%S", lt), -tz // 3600, tz % 3600) - def handlePremium(self, pyfile): - self.logDebug("Premium download as user %s" % self.user) - self.downloadFile() - - - def downloadFile(self): - m = re.search(self.LINK_PATTERN, self.html) - if m is None: - self.error(_("Download link not found")) - self.url = "http://turbobit.net" + m.group(1) - self.download(self.url) - - getInfo = create_getInfo(TurbobitNet) diff --git a/module/plugins/hoster/TusfilesNet.py b/module/plugins/hoster/TusfilesNet.py index 9d0a86fe9..9fdb6eae1 100644 --- a/module/plugins/hoster/TusfilesNet.py +++ b/module/plugins/hoster/TusfilesNet.py @@ -17,8 +17,6 @@ class TusfilesNet(XFSHoster): ("guidobelix", "guidobelix@hotmail.it")] - HOSTER_DOMAIN = "tusfiles.net" - INFO_PATTERN = r'\](?P<N>.+) - (?P<S>[\d.,]+) (?P<U>[\w^_]+)\[' OFFLINE_PATTERN = r'>File Not Found|<Title>TusFiles - Fast Sharing Files!|The file you are trying to download is no longer available' diff --git a/module/plugins/hoster/UlozTo.py b/module/plugins/hoster/UlozTo.py index cadd51149..3552942ff 100644 --- a/module/plugins/hoster/UlozTo.py +++ b/module/plugins/hoster/UlozTo.py @@ -15,7 +15,7 @@ def convertDecimalPrefix(m): class UlozTo(SimpleHoster): __name__ = "UlozTo" __type__ = "hoster" - __version__ = "1.02" + __version__ = "1.04" __pattern__ = r'http://(?:www\.)?(uloz\.to|ulozto\.(cz|sk|net)|bagruj\.cz|zachowajto\.pl)/(?:live/)?(?P<ID>\w+/[^/?]*)' @@ -39,6 +39,7 @@ class UlozTo(SimpleHoster): def setup(self): + self.chunkLimit = 16 if self.premium else 1 self.multiDL = self.premium self.resumeDownload = True @@ -55,7 +56,7 @@ class UlozTo(SimpleHoster): self.error(_("TOKEN_PATTERN not found")) token = m.group(1) - self.html = self.load(pyfile.url, get={"do": "askAgeForm-submit"}, + self.html = self.load(pyfile.url, get={'do': "askAgeForm-submit"}, post={"agree": "Confirm", "_token_": token}, cookies=True) if self.PASSWD_PATTERN in self.html: @@ -63,7 +64,7 @@ class UlozTo(SimpleHoster): if password: self.logInfo(_("Password protected link, trying ") + password) - self.html = self.load(pyfile.url, get={"do": "passwordProtectedForm-submit"}, + self.html = self.load(pyfile.url, get={'do': "passwordProtectedForm-submit"}, post={"password": password, "password_send": 'Send'}, cookies=True) if self.PASSWD_PATTERN in self.html: @@ -72,7 +73,7 @@ class UlozTo(SimpleHoster): self.fail(_("No password found")) if re.search(self.VIPLINK_PATTERN, self.html): - self.html = self.load(pyfile.url, get={"disclaimer": "1"}) + self.html = self.load(pyfile.url, get={'disclaimer': "1"}) self.getFileInfo() @@ -104,7 +105,7 @@ class UlozTo(SimpleHoster): # New version - better to get new parameters (like captcha reload) because of image url - since 6.12.2013 self.logDebug('Using "new" version') - xapca = self.load("http://www.ulozto.net/reloadXapca.php", get={"rnd": str(int(time.time()))}) + xapca = self.load("http://www.ulozto.net/reloadXapca.php", get={'rnd': str(int(time.time()))}) self.logDebug("xapca = " + str(xapca)) data = json_loads(xapca) @@ -120,7 +121,7 @@ class UlozTo(SimpleHoster): def handlePremium(self, pyfile): - self.download(pyfile.url, get={'do': directDownload}, disposition=True) + self.download(pyfile.url, get={'do': "directDownload"}, disposition=True) def doCheckDownload(self): diff --git a/module/plugins/hoster/UnibytesCom.py b/module/plugins/hoster/UnibytesCom.py index cd4e506c4..16b1f82ab 100644 --- a/module/plugins/hoster/UnibytesCom.py +++ b/module/plugins/hoster/UnibytesCom.py @@ -62,7 +62,7 @@ class UnibytesCom(SimpleHoster): if last_step == 'timer': m = re.search(self.WAIT_PATTERN, self.html) - self.wait(int(m.group(1)) if m else 60, False) + self.wait(m.group(1) if m else 60, False) elif last_step in ("captcha", "last"): post_data['captcha'] = self.decryptCaptcha(urljoin(domain, "/captcha.jpg")) diff --git a/module/plugins/hoster/UpleaCom.py b/module/plugins/hoster/UpleaCom.py index 4ea4e345f..c544c1222 100644 --- a/module/plugins/hoster/UpleaCom.py +++ b/module/plugins/hoster/UpleaCom.py @@ -19,8 +19,6 @@ class UpleaCom(XFSHoster): __authors__ = [("Redleon", None)] - HOSTER_DOMAIN = "uplea.com" - NAME_PATTERN = r'class="agmd size18">(?P<N>.+?)<' SIZE_PATTERN = r'size14">(?P<S>[\d.,]+) (?P<U>[\w^_])</span>' @@ -41,13 +39,13 @@ class UpleaCom(XFSHoster): def handleFree(self, pyfile): m = re.search(self.STEP_PATTERN, self.html) if m is None: - self.error("STEP_PATTERN not found") + self.error(_("STEP_PATTERN not found")) self.html = self.load(urljoin("http://uplea.com/", m.group(1))) m = re.search(self.WAIT_PATTERN, self.html) if m: - self.wait(int(m.group(1)), True) + self.wait(m.group(1), True) self.retry() m = re.search(self.LINK_PATTERN, self.html) diff --git a/module/plugins/hoster/UploadableCh.py b/module/plugins/hoster/UploadableCh.py index e28944ab9..be4cb5b06 100644 --- a/module/plugins/hoster/UploadableCh.py +++ b/module/plugins/hoster/UploadableCh.py @@ -11,7 +11,7 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class UploadableCh(SimpleHoster): __name__ = "UploadableCh" __type__ = "hoster" - __version__ = "0.06" + __version__ = "0.07" __pattern__ = r'http://(?:www\.)?uploadable\.ch/file/(?P<ID>\w+)' @@ -46,7 +46,7 @@ class UploadableCh(SimpleHoster): recaptcha = ReCaptcha(self) - challenge, response = recaptcha.challenge(self.RECAPTCHA_KEY) + response, challenge = recaptcha.challenge(self.RECAPTCHA_KEY) # Submit the captcha solution self.load("http://www.uploadable.ch/checkReCaptcha.php", diff --git a/module/plugins/hoster/UploadedTo.py b/module/plugins/hoster/UploadedTo.py index 833468a80..9aef13cde 100644 --- a/module/plugins/hoster/UploadedTo.py +++ b/module/plugins/hoster/UploadedTo.py @@ -9,237 +9,120 @@ import re from time import sleep from module.network.RequestFactory import getURL -from module.plugins.Hoster import Hoster -from module.plugins.Plugin import chunks from module.plugins.internal.CaptchaService import ReCaptcha -from module.utils import html_unescape, parseFileSize +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo -key = "bGhGMkllZXByd2VEZnU5Y2NXbHhYVlZ5cEE1bkEzRUw=".decode('base64') - - -def getID(url): - """ returns id from file url""" - m = re.match(UploadedTo.__pattern__, url) - return m.group('ID') - - -def getAPIData(urls): - post = {"apikey": key} - - idMap = {} - - for i, url in enumerate(urls): - id = getID(url) - post['id_%s' % i] = id - idMap[id] = url - - for _i in xrange(5): - api = unicode(getURL("http://uploaded.net/api/filemultiple", post=post, decode=False), 'iso-8859-1') - if api != "can't find request": - break - else: - sleep(3) - - result = {} - - if api: - for line in api.splitlines(): - data = line.split(",", 4) - if data[1] in idMap: - result[data[1]] = (data[0], data[2], data[4], data[3], idMap[data[1]]) - - return result - - -def parseFileInfo(self, url='', html=''): - if not html and hasattr(self, "html"): - html = self.html +class UploadedTo(SimpleHoster): + __name__ = "UploadedTo" + __type__ = "hoster" + __version__ = "0.78" - name = url - size = 0 - fileid = None + __pattern__ = r'https?://(?:www\.)?(uploaded\.(to|net)|ul\.to)(/file/|/?\?id=|.*?&id=|/)(?P<ID>\w+)' - if re.search(self.OFFLINE_PATTERN, html): - # File offline - status = 1 - else: - m = re.search(self.INFO_PATTERN, html) - if m: - name, fileid = html_unescape(m.group('N')), m.group('ID') - size = parseFileSize(m.group('S')) - status = 2 - else: - status = 3 + __description__ = """Uploaded.net hoster plugin""" + __license__ = "GPLv3" + __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] - return name, size, status, fileid + API_KEY = "bGhGMkllZXByd2VEZnU5Y2NXbHhYVlZ5cEE1bkEzRUw=" #@NOTE: base64 encoded -def getInfo(urls): - for chunk in chunks(urls, 80): - result = [] + URL_REPLACEMENTS = [(__pattern__ + ".*", r'http://uploaded.net/file/\g<ID>')] - api = getAPIData(chunk) + INFO_PATTERN = r'<a href="file/(?P<ID>\w+)" id="filename">(?P<N>[^<]+)</a> \s*<small[^>]*>(?P<S>[^<]+)</small>' + OFFLINE_PATTERN = r'<small class="cL">Error: 404' - for data in api.itervalues(): - if data[0] == "online": - result.append((html_unescape(data[2]), data[1], 2, data[4])) + LINK_PREMIUM_PATTERN = r'<div class="tfree".*\s*<form method="post" action="(.+?)"' - elif data[0] == "offline": - result.append((data[4], 0, 1, data[4])) + DL_LIMIT_ERROR = r'You have reached the max. number of possible free downloads for this hour' - yield result + @classmethod + def apiInfo(cls, url="", get={}, post={}): + info = super(UploadedTo, cls).apiInfo(url) -class UploadedTo(Hoster): - __name__ = "UploadedTo" - __type__ = "hoster" - __version__ = "0.75" + for _i in xrange(5): + api = getURL("http://uploaded.net/api/filemultiple", + post={"apikey": cls.API_KEY.decode('base64'), 'id_0': re.match(cls.__pattern__, url).group('ID')}, + decode=True) + if api != "can't find request": + api = api.splitlines()[0].split(",", 4) - __pattern__ = r'https?://(?:www\.)?(uploaded\.(to|net)|ul\.to)(/file/|/?\?id=|.*?&id=|/)(?P<ID>\w+)' + if api[0] == "online": + info.update({'name': api[4], 'size': api[2], 'status': 2}) - __description__ = """Uploaded.net hoster plugin""" - __license__ = "GPLv3" - __authors__ = [("spoob", "spoob@pyload.org"), - ("mkaay", "mkaay@mkaay.de"), - ("zoidberg", "zoidberg@mujmail.cz"), - ("netpok", "netpok@gmail.com"), - ("stickell", "l.stickell@yahoo.it")] + elif api[0] == "offline": + info['status'] = 1 + break + else: + sleep(3) - INFO_PATTERN = r'<a href="file/(?P<ID>\w+)" id="filename">(?P<N>[^<]+)</a> \s*<small[^>]*>(?P<S>[^<]+)</small>' - OFFLINE_PATTERN = r'<small class="cL">Error: 404</small>' - DL_LIMIT_PATTERN = r'You have reached the max. number of possible free downloads for this hour' + return info def setup(self): self.multiDL = self.resumeDownload = self.premium self.chunkLimit = 1 # critical problems with more chunks - - self.fileID = getID(self.pyfile.url) - self.pyfile.url = "http://uploaded.net/file/%s" % self.fileID - - - def process(self, pyfile): self.load("http://uploaded.net/language/en", just_header=True) - api = getAPIData([pyfile.url]) - # TODO: fallback to parse from site, because api sometimes delivers wrong status codes + def checkErrors(self): + if 'var free_enabled = false;' in self.html: + self.logError(_("Free-download capacities exhausted")) + self.retry(24, 5 * 60) - if not api: - self.logWarning(_("No response for API call")) + m = re.search(r"Current waiting period: <span>(\d+)</span> seconds", self.html) + if m: + self.wait(m.group(1)) + else: + self.fail(_("File not downloadable for free users")) - self.html = unicode(self.load(pyfile.url, decode=False), 'iso-8859-1') - name, size, status, self.fileID = parseFileInfo(self) - self.logDebug(name, size, status, self.fileID) - if status == 1: - self.offline() - elif status == 2: - pyfile.name, pyfile.size = name, size - else: - self.error(_("file info")) + if "limit-size" in self.html: + self.fail(_("File too big for free download")) - elif api == 'Access denied': - self.fail(_("API key invalid")) + elif "limit-slot" in self.html: # Temporary restriction so just wait a bit + self.wait(30 * 60, True) + self.retry() - else: - if self.fileID not in api: - self.offline() + elif "limit-parallel" in self.html: + self.fail(_("Cannot download in parallel")) - self.data = api[self.fileID] - if self.data[0] != "online": - self.offline() + elif "limit-dl" in self.html or self.DL_LIMIT_ERROR in self.html: # limit-dl + self.wait(3 * 60 * 60, True) + self.retry() - pyfile.name = html_unescape(self.data[2]) + elif '"err":"captcha"' in self.html: + self.invalidCaptcha() - # pyfile.name = self.get_file_name() - if self.premium: - self.handlePremium() - else: - self.handleFree() - - - def handlePremium(self): - info = self.account.getAccountInfo(self.user, True) - self.logDebug("%(name)s: Use Premium Account (%(left)sGB left)" % {"name": self.__name__, - "left": info['trafficleft'] / 1024 / 1024}) - if int(self.data[1]) / 1024 > info['trafficleft']: - self.logInfo(_("Not enough traffic left")) - self.account.empty(self.user) - self.resetAccount() - self.fail(_("Traffic exceeded")) - - header = self.load("http://uploaded.net/file/%s" % self.fileID, just_header=True) - if 'location' in header: - #Direct download - self.logDebug("Direct download link detected") - self.download(header['location']) - else: - #Indirect download - self.html = self.load("http://uploaded.net/file/%s" % self.fileID) - m = re.search(r'<div class="tfree".*\s*<form method="post" action="(.*?)"', self.html) - if m is None: - self.fail(_("Download URL not m. Try to enable direct downloads")) - url = m.group(1) - self.download(url, post={}) + def handleFree(self, pyfile): + self.html = self.load("http://uploaded.net/js/download.js", decode=True) + recaptcha = ReCaptcha(self) + response, challenge = recaptcha.challenge() - def handleFree(self): - self.html = self.load(self.pyfile.url, decode=True) + self.html = self.load("http://uploaded.net/io/ticket/captcha/%s" % self.info['pattern']['ID'], + post={'recaptcha_challenge_field': challenge, + 'recaptcha_response_field' : response}) - if 'var free_enabled = false;' in self.html: - self.logError(_("Free-download capacities exhausted")) - self.retry(24, 5 * 60) + if "type:'download'" in self.html: + self.correctCaptcha() + try: + self.link = re.search("url:'([^']+)", self.html).group(1) - m = re.search(r"Current waiting period: <span>(\d+)</span> seconds", self.html) - if m is None: - self.fail(_("File not downloadable for free users")) - self.setWait(int(m.group(1))) + except Exception: + pass - self.html = self.load("http://uploaded.net/js/download.js", decode=True) + self.checkErrors() - url = "http://uploaded.net/io/ticket/captcha/%s" % self.fileID - downloadURL = "" - recaptcha = ReCaptcha(self) + def checkFile(self): + if self.checkDownload({'limit-dl': self.DL_LIMIT_ERROR}): + self.wait(3 * 60 * 60, True) + self.retry() - for _i in xrange(5): - challenge, response = recaptcha.challenge() - options = {"recaptcha_challenge_field": challenge, "recaptcha_response_field": response} - self.wait() - - result = self.load(url, post=options) - self.logDebug("Result: %s" % result) - - if "limit-size" in result: - self.fail(_("File too big for free download")) - elif "limit-slot" in result: # Temporary restriction so just wait a bit - self.setWait(30 * 60, True) - self.wait() - self.retry() - elif "limit-parallel" in result: - self.fail(_("Cannot download in parallel")) - elif "limit-dl" in result or self.DL_LIMIT_PATTERN in result: # limit-dl - self.setWait(3 * 60 * 60, True) - self.wait() - self.retry() - elif '"err":"captcha"' in result: - self.invalidCaptcha() - elif "type:'download'" in result: - self.correctCaptcha() - downloadURL = re.search("url:'([^']+)", result).group(1) - break - else: - self.error(_("Unknown error: %s") % result) + return super(UploadedTo, self).checkFile() - if not downloadURL: - self.fail(_("No Download url retrieved/all captcha attempts failed")) - self.download(downloadURL, disposition=True) - check = self.checkDownload({"limit-dl": self.DL_LIMIT_PATTERN}) - if check == "limit-dl": - self.setWait(3 * 60 * 60, True) - self.wait() - self.retry() +getInfo = create_getInfo(UploadedTo) diff --git a/module/plugins/hoster/UpstoreNet.py b/module/plugins/hoster/UpstoreNet.py index f287a2b51..db9fa53a1 100644 --- a/module/plugins/hoster/UpstoreNet.py +++ b/module/plugins/hoster/UpstoreNet.py @@ -9,7 +9,7 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class UpstoreNet(SimpleHoster): __name__ = "UpstoreNet" __type__ = "hoster" - __version__ = "0.04" + __version__ = "0.05" __pattern__ = r'https?://(?:www\.)?upstore\.net/' @@ -52,7 +52,7 @@ class UpstoreNet(SimpleHoster): self.wait(wait_time) # then, handle the captcha - challenge, response = recaptcha.challenge() + response, challenge = recaptcha.challenge() post_data.update({'recaptcha_challenge_field': challenge, 'recaptcha_response_field' : response}) diff --git a/module/plugins/hoster/UptoboxCom.py b/module/plugins/hoster/UptoboxCom.py index 21d781f55..dedb6ed1f 100644 --- a/module/plugins/hoster/UptoboxCom.py +++ b/module/plugins/hoster/UptoboxCom.py @@ -15,8 +15,6 @@ class UptoboxCom(XFSHoster): __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] - HOSTER_DOMAIN = "uptobox.com" - INFO_PATTERN = r'"para_title">(?P<N>.+) \((?P<S>[\d.,]+) (?P<U>[\w^_]+)\)' OFFLINE_PATTERN = r'>(File not found|Access Denied|404 Not Found)' diff --git a/module/plugins/hoster/VidPlayNet.py b/module/plugins/hoster/VidPlayNet.py index 76af05edd..f1a32a897 100644 --- a/module/plugins/hoster/VidPlayNet.py +++ b/module/plugins/hoster/VidPlayNet.py @@ -18,8 +18,6 @@ class VidPlayNet(XFSHoster): __authors__ = [("t4skforce", "t4skforce1337[AT]gmail[DOT]com")] - HOSTER_DOMAIN = "vidplay.net" - NAME_PATTERN = r'<b>Password:</b></div>\s*<h[1-6]>(?P<N>[^<]+)</h[1-6]>' diff --git a/module/plugins/hoster/Vipleech4uCom.py b/module/plugins/hoster/Vipleech4UCom.py index 2ae41b942..2ae41b942 100644 --- a/module/plugins/hoster/Vipleech4uCom.py +++ b/module/plugins/hoster/Vipleech4UCom.py diff --git a/module/plugins/hoster/WebshareCz.py b/module/plugins/hoster/WebshareCz.py index e3424fc21..98187d46a 100644 --- a/module/plugins/hoster/WebshareCz.py +++ b/module/plugins/hoster/WebshareCz.py @@ -9,7 +9,7 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class WebshareCz(SimpleHoster): __name__ = "WebshareCz" __type__ = "hoster" - __version__ = "0.15" + __version__ = "0.16" __pattern__ = r'https?://(?:www\.)?webshare\.cz/(?:#/)?file/(?P<ID>\w+)' @@ -21,7 +21,7 @@ class WebshareCz(SimpleHoster): @classmethod def getInfo(cls, url="", html=""): - info = super(WebshareCz, self).getInfo(url, html) + info = super(WebshareCz, cls).getInfo(url, html) if url: info['pattern'] = re.match(cls.__pattern__, url).groupdict() diff --git a/module/plugins/hoster/YibaishiwuCom.py b/module/plugins/hoster/YibaishiwuCom.py index adc403de4..cf1550ebc 100644 --- a/module/plugins/hoster/YibaishiwuCom.py +++ b/module/plugins/hoster/YibaishiwuCom.py @@ -50,7 +50,7 @@ class YibaishiwuCom(SimpleHoster): self.logDebug("Trying URL: " + url) self.download(url) break - except: + except Exception: continue else: self.fail(_("No working link found")) diff --git a/module/plugins/hoster/YoutubeCom.py b/module/plugins/hoster/YoutubeCom.py index 90c6df3c2..5c2489d3c 100644 --- a/module/plugins/hoster/YoutubeCom.py +++ b/module/plugins/hoster/YoutubeCom.py @@ -13,40 +13,36 @@ from module.utils import html_unescape def which(program): """Works exactly like the unix command which - Courtesy of http://stackoverflow.com/a/377028/675646""" - def is_exe(fpath): - return os.path.isfile(fpath) and os.access(fpath, os.X_OK) + isExe = lambda x: os.path.isfile(x) and os.access(x, os.X_OK) fpath, fname = os.path.split(program) if fpath: - if is_exe(program): + if isExe(program): return program else: for path in os.environ['PATH'].split(os.pathsep): path = path.strip('"') exe_file = os.path.join(path, program) - if is_exe(exe_file): + if isExe(exe_file): return exe_file - return None - class YoutubeCom(Hoster): __name__ = "YoutubeCom" __type__ = "hoster" - __version__ = "0.40" + __version__ = "0.41" - __pattern__ = r'https?://(?:[^/]*\.)?(?:youtube\.com|youtu\.be)/watch.*?[?&]v=.+' - __config__ = [("quality", "sd;hd;fullhd;240p;360p;480p;720p;1080p;3072p", "Quality Setting", "hd"), - ("fmt", "int", "FMT/ITAG Number (5-102, 0 for auto)", 0), - (".mp4", "bool", "Allow .mp4", True), - (".flv", "bool", "Allow .flv", True), - (".webm", "bool", "Allow .webm", False), - (".3gp", "bool", "Allow .3gp", False), - ("3d", "bool", "Prefer 3D", False)] + __pattern__ = r'https?://(?:[^/]*\.)?(youtube\.com|youtu\.be)/watch\?(?:.*&)?v=.+' + __config__ = [("quality", "sd;hd;fullhd;240p;360p;480p;720p;1080p;3072p", "Quality Setting" , "hd" ), + ("fmt" , "int" , "FMT/ITAG Number (0 for auto)", 0 ), + (".mp4" , "bool" , "Allow .mp4" , True ), + (".flv" , "bool" , "Allow .flv" , True ), + (".webm" , "bool" , "Allow .webm" , False), + (".3gp" , "bool" , "Allow .3gp" , False), + ("3d" , "bool" , "Prefer 3D" , False)] __description__ = """Youtube.com hoster plugin""" __license__ = "GPLv3" @@ -90,7 +86,7 @@ class YoutubeCom(Hoster): def process(self, pyfile): pyfile.url = replace_patterns(pyfile.url, self.URL_REPLACEMENTS) - html = self.load(pyfile.url, decode=True) + html = self.load(pyfile.url, decode=True) if re.search(r'<div id="player-unavailable" class="\s*player-width player-height\s*">', html): self.offline() @@ -100,32 +96,40 @@ class YoutubeCom(Hoster): #get config use3d = self.getConfig("3d") + if use3d: quality = {"sd": 82, "hd": 84, "fullhd": 85, "240p": 83, "360p": 82, "480p": 82, "720p": 84, "1080p": 85, "3072p": 85} else: quality = {"sd": 18, "hd": 22, "fullhd": 37, "240p": 5, "360p": 18, "480p": 35, "720p": 22, "1080p": 37, "3072p": 38} + desired_fmt = self.getConfig("fmt") - if desired_fmt and desired_fmt not in self.formats: - self.logWarning(_("FMT %d unknown, using default") % desired_fmt) - desired_fmt = 0 + if not desired_fmt: desired_fmt = quality.get(self.getConfig("quality"), 18) + elif desired_fmt not in self.formats: + self.logWarning(_("FMT %d unknown, using default") % desired_fmt) + desired_fmt = 0 + #parse available streams - streams = re.search(r'"url_encoded_fmt_stream_map": "(.*?)",', html).group(1) + streams = re.search(r'"url_encoded_fmt_stream_map":"(.+?)",', html).group(1) streams = [x.split('\u0026') for x in streams.split(',')] streams = [dict((y.split('=', 1)) for y in x) for x in streams] streams = [(int(x['itag']), unquote(x['url'])) for x in streams] - #self.logDebug("Found links: %s" % streams) + + # self.logDebug("Found links: %s" % streams) + self.logDebug("AVAILABLE STREAMS: %s" % [x[0] for x in streams]) #build dictionary of supported itags (3D/2D) allowed = lambda x: self.getConfig(self.formats[x][0]) streams = [x for x in streams if x[0] in self.formats and allowed(x[0])] + if not streams: self.fail(_("No available stream meets your preferences")) + fmt_dict = dict([x for x in streams if self.formats[x[0]][4] == use3d] or streams) self.logDebug("DESIRED STREAM: ITAG:%d (%s) %sfound, %sallowed" % @@ -136,15 +140,18 @@ class YoutubeCom(Hoster): if desired_fmt in fmt_dict and allowed(desired_fmt): fmt = desired_fmt else: - sel = lambda x: self.formats[x][3] # select quality index + sel = lambda x: self.formats[x][3] # select quality index comp = lambda x, y: abs(sel(x) - sel(y)) self.logDebug("Choosing nearest fmt: %s" % [(x, allowed(x), comp(x, desired_fmt)) for x in fmt_dict.keys()]) + fmt = reduce(lambda x, y: x if comp(x, desired_fmt) <= comp(y, desired_fmt) and sel(x) > sel(y) else y, fmt_dict.keys()) self.logDebug("Chosen fmt: %s" % fmt) + url = fmt_dict[fmt] + self.logDebug("URL: %s" % url) #set file name @@ -167,9 +174,9 @@ class YoutubeCom(Hoster): m = "0" pyfile.name += " (starting at %s:%s)" % (m, s) - pyfile.name += file_suffix - filename = self.download(url) + pyfile.name += file_suffix + filename = self.download(url) if ffmpeg and time: inputfile = filename + "_" diff --git a/module/plugins/hoster/ZeveraCom.py b/module/plugins/hoster/ZeveraCom.py index fb251142e..665b64789 100644 --- a/module/plugins/hoster/ZeveraCom.py +++ b/module/plugins/hoster/ZeveraCom.py @@ -10,7 +10,7 @@ from module.plugins.internal.MultiHoster import MultiHoster, create_getInfo class ZeveraCom(MultiHoster): __name__ = "ZeveraCom" __type__ = "hoster" - __version__ = "0.27" + __version__ = "0.28" __pattern__ = r'https?://(?:www\.)zevera\.com/(getFiles\.ashx|Members/download\.ashx)\?.*ourl=.+' @@ -21,7 +21,7 @@ class ZeveraCom(MultiHoster): def handlePremium(self, pyfile): - return "https://%s/getFiles.ashx?ourl=%s" % (self.account.HOSTER_DOMAIN, pyfile.url) + self.link = "https://%s/getFiles.ashx?ourl=%s" % (self.account.HOSTER_DOMAIN, pyfile.url) def checkFile(self): diff --git a/module/plugins/hoster/ZippyshareCom.py b/module/plugins/hoster/ZippyshareCom.py index 2648f532f..f32c5877f 100644 --- a/module/plugins/hoster/ZippyshareCom.py +++ b/module/plugins/hoster/ZippyshareCom.py @@ -2,42 +2,51 @@ import re -from urlparse import urljoin - +from module.plugins.internal.CaptchaService import ReCaptcha from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class ZippyshareCom(SimpleHoster): __name__ = "ZippyshareCom" __type__ = "hoster" - __version__ = "0.66" + __version__ = "0.68" - __pattern__ = r'(?P<HOST>http://www\d{0,2}\.zippyshare\.com)/v(?:/|iew\.jsp.*key=)(?P<KEY>\d+)' + __pattern__ = r'http://www\d{0,2}\.zippyshare\.com/v(/|iew\.jsp.*key=)(?P<KEY>[\w^_]+)' __description__ = """Zippyshare.com hoster plugin""" __license__ = "GPLv3" __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] - NAME_PATTERN = r'("\d{6,}/"[ ]*\+.+?"/|<title>Zippyshare.com - )(?P<N>.+?)("|</title>)' - SIZE_PATTERN = r'>Size:.+?">(?P<S>[\d.,]+) (?P<U>[\w^_]+)' + COOKIES = [("zippyshare.com", "ziplocale", "en")] - OFFLINE_PATTERN = r'>File does not exist on this server<' + NAME_PATTERN = r'("\d{6,}/"[ ]*\+.+?"/|<title>Zippyshare.com - )(?P<N>.+?)("|</title>)' + SIZE_PATTERN = r'>Size:.+?">(?P<S>[\d.,]+) (?P<U>[\w^_]+)' + OFFLINE_PATTERN = r'>File does not exist on this server' - COOKIES = [("zippyshare.com", "ziplocale", "en")] + LINK_PREMIUM_PATTERN = r'document.location = \'(.+?)\'' def setup(self): - self.multiDL = True self.chunkLimit = -1 + self.multiDL = True self.resumeDownload = True def handleFree(self, pyfile): - checksum = self.get_checksum() - p_url = '/'.join(("d", self.info['pattern']['KEY'], str(checksum), self.pyfile.name)) + recaptcha = ReCaptcha(self) + captcha_key = recaptcha.detect_key() + + if captcha_key: + try: + self.link = re.search(self.LINK_PREMIUM_PATTERN, self.html) + recaptcha.challenge() - self.link = urljoin(self.info['pattern']['HOST'], p_url) + except Exception, e: + self.error(e) + + else: + self.link = '/'.join(("d", self.info['pattern']['KEY'], str(self.get_checksum()), self.pyfile.name)) def get_checksum(self): @@ -51,8 +60,8 @@ class ZippyshareCom(SimpleHoster): c1, c2 = map(int, re.search(r'\(\'downloadB\'\).omg\) \* \((\d+)%(\d+)', self.html).groups()) b = (a1 % a2) * (c1 % c2) + 18 - except Exception, e: - self.error(_("Unable to calculate checksum"), e) + except Exception: + self.error(_("Unable to calculate checksum")) else: return b diff --git a/module/plugins/internal/CaptchaService.py b/module/plugins/internal/CaptchaService.py index b429fd6e0..c6e83fe7d 100644 --- a/module/plugins/internal/CaptchaService.py +++ b/module/plugins/internal/CaptchaService.py @@ -1,24 +1,24 @@ # -*- coding: utf-8 -*- import re +import time -from base64 import urlsafe_b64encode -from random import random +from base64 import b64encode +from random import random, randint +from urlparse import urljoin, urlparse from module.common.json_layer import json_loads class CaptchaService: __name__ = "CaptchaService" - __version__ = "0.16" + __version__ = "0.20" __description__ = """Base captcha service plugin""" __license__ = "GPLv3" __authors__ = [("pyLoad Team", "admin@pyload.org")] - KEY_PATTERN = None - key = None #: last key detected @@ -27,25 +27,10 @@ class CaptchaService: def detect_key(self, html=None): - if not html: - if hasattr(self.plugin, "html") and self.plugin.html: - html = self.plugin.html - else: - errmsg = _("%s html not found") % self.__name__ - self.plugin.fail(errmsg) #@TODO: replace all plugin.fail(errmsg) with plugin.error(errmsg) in 0.4.10 - raise TypeError(errmsg) - - m = re.search(self.KEY_PATTERN, html) - if m: - self.key = m.group(1).strip() - self.plugin.logDebug("%s key: %s" % (self.__name__, self.key)) - return self.key - else: - self.plugin.logDebug("%s key not found" % self.__name__) - return None + raise NotImplementedError - def challenge(self, key=None): + def challenge(self, key=None, html=None): raise NotImplementedError @@ -55,15 +40,17 @@ class CaptchaService: class ReCaptcha(CaptchaService): __name__ = "ReCaptcha" - __version__ = "0.09" + __version__ = "0.11" __description__ = """ReCaptcha captcha service plugin""" __license__ = "GPLv3" - __authors__ = [("pyLoad Team", "admin@pyload.org")] + __authors__ = [("pyLoad Team", "admin@pyload.org"), + ("Walter Purcaro", "vuolter@gmail.com"), + ("zapp-brannigan", "fuerst.reinje@web.de")] - KEY_PATTERN = r'(?:class="g-recaptcha"\s+data-sitekey="|recaptcha(?:/api|\.net)/(?:challenge|noscript)\?k=)([\w-]+)' - KEY_AJAX_PATTERN = r'Recaptcha\.create\s*\(\s*["\']([\w-]+)' + 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): @@ -75,7 +62,7 @@ class ReCaptcha(CaptchaService): self.plugin.fail(errmsg) raise TypeError(errmsg) - m = re.search(self.KEY_PATTERN, html) or re.search(self.KEY_AJAX_PATTERN, html) + 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.plugin.logDebug("ReCaptcha key: %s" % self.key) @@ -85,9 +72,24 @@ class ReCaptcha(CaptchaService): return None - def challenge(self, key=None, userverify=False): + def challenge(self, key=None, html=None, version=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) + + challenge = "challenge_v%s" % (version if version in (1, 2) else + 2 if re.search(self.KEY_V2_PATTERN, html) else 1) + + return getattr(self, challenge)(key, html) + + + def challenge_v1(self, key=None, html=None): if not key: - if self.detect_key(): + if self.detect_key(html): key = self.key else: errmsg = _("ReCaptcha key not found") @@ -106,22 +108,7 @@ class ReCaptcha(CaptchaService): self.plugin.logDebug("ReCaptcha challenge: %s" % challenge) - response = challenge, self.result(server, challenge) - - return self.userverify(*response) if userverify else response - - - def userverify(self, challenge, result): - response = self.plugin.req.load("https://www.google.com/recaptcha/api2/userverify", - post={'c' : challenge, - 'response': urlsafe_b64encode('{"response":"%s"}' % result)}) - try: - return re.search(r'"uvresp","(.+?)"', response).group(1) - - except AttributeError: - errmsg = _("ReCaptcha userverify response not found") - self.plugin.fail(errmsg) - raise AttributeError(errmsg) + return self.result(server, challenge), challenge def result(self, server, challenge): @@ -136,9 +123,122 @@ class ReCaptcha(CaptchaService): 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.plugin.logDebug("ReCaptcha API version: %s" %vers) + + language = a.split("__")[1].split(".")[0] + + self.plugin.logDebug("ReCaptcha 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.plugin.logDebug("ReCaptcha 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.plugin.logDebug("ReCaptcha time: %s" % millis) + + rand = randint(1, 99999999) + a = "0.%s" % str(rand * 2147483647) + rpc = int(100000000 * float(a)) + + self.plugin.logDebug("ReCaptcha rpc-token: %s" % rpc) + + return millis, rpc + + + def challenge_v2(self, key=None, html=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) + + 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.plugin.logDebug("ReCaptcha 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, + 'usegapi': "1", + 'jsh' : jsh}).decode('unicode-escape') + + token2 = re.search(r'"finput","(.*?)",', html) + self.plugin.logDebug("ReCaptcha token #2: %s" % token2.group(1)) + + token3 = re.search(r'."asconf".\s.\s,"(.*?)".', html) + self.plugin.logDebug("ReCaptcha token #3: %s" % token3.group(1)) + + html = self.plugin.req.load("https://www.google.com/recaptcha/api2/reload", + post={'c' : token2.group(1), + 'reason': "fi", + 'fbg' : token3.group(1)}) + + token4 = re.search(r'"rresp","(.*?)",', html) + self.plugin.logDebug("ReCaptcha 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)}, forceUser=True) + response = b64encode('{"response":"%s"}' % captcha_response) + + self.plugin.logDebug("ReCaptcha 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={'c' : token4.group(1), + 'response': response, + 't' : timeToSolve, + 'ct' : timeToSolveMore, + 'bg' : botguardstring}) + + token5 = re.search(r'"uvresp","(.*?)",', html) + self.plugin.logDebug("ReCaptcha token #5: %s" % token5.group(1)) + + return token5.group(1), None + + class AdsCaptcha(CaptchaService): __name__ = "AdsCaptcha" - __version__ = "0.06" + __version__ = "0.07" __description__ = """AdsCaptcha captcha service plugin""" __license__ = "GPLv3" @@ -169,9 +269,9 @@ class AdsCaptcha(CaptchaService): return None - def challenge(self, key=None): + def challenge(self, key=None, html=None): if not key: - if self.detect_key(): + if self.detect_key(html): key = self.key else: errmsg = _("AdsCaptcha key not found") @@ -192,7 +292,7 @@ class AdsCaptcha(CaptchaService): self.plugin.logDebug("AdsCaptcha challenge: %s" % challenge) - return challenge, self.result(server, challenge) + return self.result(server, challenge), challenge def result(self, server, challenge): @@ -208,7 +308,7 @@ class AdsCaptcha(CaptchaService): class SolveMedia(CaptchaService): __name__ = "SolveMedia" - __version__ = "0.06" + __version__ = "0.08" __description__ = """SolveMedia captcha service plugin""" __license__ = "GPLv3" @@ -218,9 +318,28 @@ class SolveMedia(CaptchaService): KEY_PATTERN = r'api\.solvemedia\.com/papi/challenge\.(?:no)?script\?k=(.+?)["\']' - def challenge(self, key=None): + 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.plugin.logDebug("SolveMedia key: %s" % self.key) + return self.key + else: + self.plugin.logDebug("SolveMedia key not found") + return None + + + def challenge(self, key=None, html=None): if not key: - if self.detect_key(): + if self.detect_key(html): key = self.key else: errmsg = _("SolveMedia key not found") @@ -240,7 +359,7 @@ class SolveMedia(CaptchaService): self.plugin.logDebug("SolveMedia challenge: %s" % challenge) - return challenge, self.result(server, challenge) + return self.result(server, challenge), challenge def result(self, server, challenge): @@ -253,7 +372,7 @@ class SolveMedia(CaptchaService): class AdYouLike(CaptchaService): __name__ = "AdYouLike" - __version__ = "0.02" + __version__ = "0.04" __description__ = """AdYouLike captcha service plugin""" __license__ = "GPLv3" @@ -284,9 +403,9 @@ class AdYouLike(CaptchaService): return None - def challenge(self, key=None): + def challenge(self, key=None, html=None): if not key: - if self.detect_key(): + if self.detect_key(html): key = self.key else: errmsg = _("AdYouLike key not found") @@ -313,7 +432,7 @@ class AdYouLike(CaptchaService): self.plugin.logDebug("AdYouLike challenge: %s" % challenge) - return self.result(ayl, challenge) + return self.result(ayl, challenge), challenge def result(self, server, challenge): diff --git a/module/plugins/internal/DeadCrypter.py b/module/plugins/internal/DeadCrypter.py index 0fa23eef3..866d177cf 100644 --- a/module/plugins/internal/DeadCrypter.py +++ b/module/plugins/internal/DeadCrypter.py @@ -1,8 +1,5 @@ # -*- coding: utf-8 -*- -from urllib import unquote -from urlparse import urlparse - from module.plugins.internal.SimpleCrypter import create_getInfo from module.plugins.Crypter import Crypter as _Crypter diff --git a/module/plugins/internal/DeadHoster.py b/module/plugins/internal/DeadHoster.py index cc7adf4df..a6ad92607 100644 --- a/module/plugins/internal/DeadHoster.py +++ b/module/plugins/internal/DeadHoster.py @@ -1,8 +1,5 @@ # -*- coding: utf-8 -*- -from urllib import unquote -from urlparse import urlparse - from module.plugins.internal.SimpleHoster import create_getInfo from module.plugins.Hoster import Hoster as _Hoster diff --git a/module/plugins/internal/Extractor.py b/module/plugins/internal/Extractor.py index 0b2462dac..ddf0f8a85 100644 --- a/module/plugins/internal/Extractor.py +++ b/module/plugins/internal/Extractor.py @@ -1,5 +1,11 @@ # -*- coding: utf-8 -*- +import os + +from module.PyFile import PyFile +from module.utils import fs_encode + + class ArchiveError(Exception): pass @@ -14,7 +20,7 @@ class PasswordError(Exception): class Extractor: __name__ = "Extractor" - __version__ = "0.13" + __version__ = "0.15" __description__ = """Base extractor plugin""" __license__ = "GPLv3" @@ -26,6 +32,12 @@ class Extractor: @classmethod + def isArchive(cls, filename): + name = os.path.basename(filename).lower() + return any(name.endswith(ext) for ext in cls.EXTENSIONS) + + + @classmethod def checkDeps(cls): """ Check if system statisfy dependencies :return: boolean @@ -34,46 +46,36 @@ class Extractor: @classmethod - def isArchive(cls, file): - raise NotImplementedError - - - @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 """ - targets = [] - - for file, id in files_ids: - if cls.isArchive(file): - targets.append((file, id)) - - return targets - + raise NotImplementedError - def __init__(self, m, file, out, password, fullpath, overwrite, excludefiles, renice, delete, keepbroken): - """Initialize extractor for specific file - :param m: ExtractArchive Hook plugin - :param file: Absolute filepath - :param out: Absolute path to destination directory - :param fullpath: extract to fullpath - :param overwrite: Overwrite existing archives - :param renice: Renice value - """ - self.m = m - self.file = file - self.out = out - self.password = password - self.fullpath = fullpath - self.overwrite = overwrite - self.excludefiles = excludefiles - self.renice = renice - self.delete = delete - self.keepbroken = keepbroken - self.files = [] #: Store extracted files here + 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.target = fs_encode(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): @@ -81,44 +83,31 @@ class Extractor: pass - def verify(self): + def checkArchive(self): """Check if password if needed. Raise ArchiveError if integrity is questionable. + :return: boolean :raises ArchiveError """ - pass + return False - def isPassword(self, password): + def checkPassword(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 """ - if isinstance(password, basestring): - return True - else: - return False - - - def setPassword(self, password): - if self.isPassword(password): - self.password = password - return True - else: - return False - - - def repair(self): - return False + return True - def extract(self, progress=lambda x: 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 @@ -132,7 +121,7 @@ class Extractor: :return: List with paths of files to delete """ - raise NotImplementedError + return [self.target] def getExtractedFiles(self): diff --git a/module/plugins/internal/MultiHook.py b/module/plugins/internal/MultiHook.py index 795565d73..652443098 100644 --- a/module/plugins/internal/MultiHook.py +++ b/module/plugins/internal/MultiHook.py @@ -11,7 +11,7 @@ from module.utils import decode, remove_chars class MultiHook(Hook): __name__ = "MultiHook" __type__ = "hook" - __version__ = "0.36" + __version__ = "0.37" __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ), @@ -201,7 +201,7 @@ class MultiHook(Hook): self.unloadPlugin(plugin) if self.getConfig("reload", True): - self.interval = max(self.getConfig("reloadinterval", 12), self.MIN_INTERVAL) + self.interval = max(self.getConfig("reloadinterval", 12) * 60 * 60, self.MIN_INTERVAL) else: self.core.scheduler.removeJob(self.cb) self.cb = None diff --git a/module/plugins/internal/MultiHoster.py b/module/plugins/internal/MultiHoster.py index ba613c997..ad5b6283e 100644 --- a/module/plugins/internal/MultiHoster.py +++ b/module/plugins/internal/MultiHoster.py @@ -8,7 +8,7 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo, r class MultiHoster(SimpleHoster): __name__ = "MultiHoster" __type__ = "hoster" - __version__ = "0.33" + __version__ = "0.36" __pattern__ = r'^unmatchable$' @@ -27,9 +27,10 @@ class MultiHoster(SimpleHoster): def prepare(self): - self.info = {} - self.link = "" #@TODO: Move to hoster class in 0.4.10 - self.directDL = False #@TODO: Move to hoster class in 0.4.10 + 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")) @@ -40,7 +41,7 @@ class MultiHoster(SimpleHoster): set_cookies(self.req.cj, self.COOKIES) if self.DIRECT_LINK is None: - self.directDL = self.__pattern__ != r'^unmatchable$' + self.directDL = self.__pattern__ != r'^unmatchable$' and re.match(self.__pattern__, self.pyfile.url) else: self.directDL = self.DIRECT_LINK @@ -51,10 +52,8 @@ class MultiHoster(SimpleHoster): def process(self, pyfile): self.prepare() - if self.__pattern__ != r'^unmatchable$' and re.match(self.__pattern__, pyfile.url): - self.checkInfo() - if self.directDL: + self.checkInfo() self.logDebug("Looking for direct download link...") self.handleDirect(pyfile) @@ -72,17 +71,10 @@ class MultiHoster(SimpleHoster): self.logDebug("Handled as free download") self.handleFree(pyfile) - self.downloadLink(self.link) + self.downloadLink(self.link, True) self.checkFile() - #@TODO: Remove in 0.4.10 - def downloadLink(self, link): - if link and isinstance(link, basestring): - self.correctCaptcha() - self.download(link, disposition=True) - - def handlePremium(self, pyfile): return self.handleFree(pyfile) diff --git a/module/plugins/internal/SevenZip.py b/module/plugins/internal/SevenZip.py new file mode 100644 index 000000000..508cf9c8d --- /dev/null +++ b/module/plugins/internal/SevenZip.py @@ -0,0 +1,163 @@ +# -*- coding: utf-8 -*- + +import os +import re + +from subprocess import Popen, PIPE + +from module.plugins.internal.UnRar import UnRar, renice +from module.utils import save_join + + +class SevenZip(UnRar): + __name__ = "SevenZip" + __version__ = "0.02" + + __description__ = """7-Zip extractor plugin""" + __license__ = "GPLv3" + __authors__ = [("Michael Nowak", ""), + ("Walter Purcaro", "vuolter@gmail.com")] + + + CMD = "7z" + + 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) + + + @classmethod + def checkDeps(cls): + if os.name == "nt": + cls.CMD = os.path.join(pypath, "7z.exe") + p = Popen([cls.CMD], stdout=PIPE, stderr=PIPE) + p.communicate() + else: + p = Popen([cls.CMD], stdout=PIPE, stderr=PIPE) + p.communicate() + + return True + + + def checkArchive(self): + p = self.call_cmd("l", "-slt", self.target) + out, err = p.communicate() + + if p.returncode > 1: + raise ArchiveError("Process terminated") + + # check if output or error macthes the 'wrong password'-Regexp + if self.re_wrongpwd.search(out): + return True + + # check if output matches 'Encrypted = +' + if self.re_wrongcrc.search(out): + return True + + # check if archive is empty + self.files = self.list() + if not self.files: + raise ArchiveError("Empty Archive") + + return False + + + def checkPassword(self, password): + p = self.call_cmd("l", self.target, password=password) + p.communicate() + return p.returncode == 0 + + + def extract(self, password=None): + command = "x" if self.fullpath else "e" + + p = self.call_cmd(command, '-o' + self.out, self.target, password=password) + + renice(p.pid, self.renice) + + progressstring = "" + while True: + c = p.stdout.read(1) + # quit loop on eof + if not c: + break + # reading a percentage sign -> set progress and restart + if c == '%': + self.notifyProgress(int(progressstring)) + progressstring = "" + # not reading a digit -> therefore restart + elif c not in digits: + progressstring = "" + # add digit to progressstring + else: + progressstring += c + + # retrieve stderr + err = p.stderr.read() + + if self.re_wrongpwd.search(err): + raise PasswordError + + elif self.re_wrongcrc.search(err): + raise CRCError + + elif err.strip(): #: raise error if anything is on stderr + raise ArchiveError(err.strip()) + + if p.returncode > 1: + raise ArchiveError("Process terminated") + + if not self.files: + self.files = self.list(password) + + + def list(self, password=None): + command = "l" if self.fullpath else "l" + + p = self.call_cmd(command, self.target, password=password) + out, err = p.communicate() + code = p.returncode + + if "Can not open" in err: + raise ArchiveError("Cannot open file") + + if code != 0: + raise ArchiveError("Process terminated unsuccessful") + + 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([decode(arg) for arg in call])) + + p = Popen(call, stdout=PIPE, stderr=PIPE) + return p diff --git a/module/plugins/internal/SimpleCrypter.py b/module/plugins/internal/SimpleCrypter.py index d33ad77e9..b2622b5e0 100644 --- a/module/plugins/internal/SimpleCrypter.py +++ b/module/plugins/internal/SimpleCrypter.py @@ -12,7 +12,7 @@ from module.utils import fixup class SimpleCrypter(Crypter, SimpleHoster): __name__ = "SimpleCrypter" __type__ = "crypter" - __version__ = "0.39" + __version__ = "0.42" __pattern__ = r'^unmatchable$' __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), #: Overrides core.config['general']['folder_per_package'] @@ -71,12 +71,12 @@ class SimpleCrypter(Crypter, SimpleHoster): #@TODO: Remove in 0.4.10 def init(self): account_name = (self.__name__ + ".py").replace("Folder.py", "").replace(".py", "") - account = self.core.accountManager.getAccountPlugin(account_name) + account = self.pyfile.m.core.accountManager.getAccountPlugin(account_name) if account and account.canUse(): self.user, data = account.selectAccount() - self.req = account.getAccountRequest(self.user) - self.premium = account.isPremium(self.user) + self.req = account.getAccountRequest(self.user) + self.premium = account.isPremium(self.user) self.account = account @@ -85,6 +85,7 @@ class SimpleCrypter(Crypter, SimpleHoster): self.pyfile.error = "" #@TODO: Remove in 0.4.10 self.info = {} + self.html = "" self.links = [] #@TODO: Move to hoster class in 0.4.10 if self.LOGIN_PREMIUM and not self.premium: @@ -118,7 +119,7 @@ class SimpleCrypter(Crypter, SimpleHoster): self.packages = [(self.info['name'], self.links, self.info['folder'])] elif not self.urls and not self.packages: #@TODO: Remove in 0.4.10 - self.fail("No link grabbed") + self.fail(_("No link grabbed")) def checkNameSize(self, getinfo=True): @@ -151,17 +152,17 @@ class SimpleCrypter(Crypter, SimpleHoster): Returns the links extracted from self.html You should override this only if it's impossible to extract links using only the LINK_PATTERN. """ - parsed = urlparse(self.pyfile.url) - base = "%s://%s" % (parsed.scheme, parsed.netloc) + url_p = urlparse(self.pyfile.url) + baseurl = "%s://%s" % (url_p.scheme, url_p.netloc) - return [urljoin(base, link) if not urlparse(link).scheme else link \ - for link in re.finditer(self.LINK_PATTERN, self.html)] + return [urljoin(baseurl, link) if not urlparse(link).scheme else link \ + for link in re.findall(self.LINK_PATTERN, self.html)] def handlePages(self, pyfile): try: pages = int(re.search(self.PAGES_PATTERN, self.html).group(1)) - except: + except Exception: pages = 1 for p in xrange(2, pages + 1): diff --git a/module/plugins/internal/SimpleDereferer.py b/module/plugins/internal/SimpleDereferer.py index 53b80f827..bd00f5d25 100644 --- a/module/plugins/internal/SimpleDereferer.py +++ b/module/plugins/internal/SimpleDereferer.py @@ -5,13 +5,13 @@ import re from urllib import unquote from module.plugins.Crypter import Crypter -from module.plugins.internal.SimpleHoster import directLink, set_cookies +from module.plugins.internal.SimpleHoster import fileUrl, set_cookies class SimpleDereferer(Crypter): __name__ = "SimpleDereferer" __type__ = "crypter" - __version__ = "0.03" + __version__ = "0.07" __pattern__ = r'^unmatchable$' __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), @@ -45,7 +45,7 @@ class SimpleDereferer(Crypter): def decrypt(self, pyfile): - link = directLink(self, pyfile.url) + link = fileUrl(self, pyfile.url) if not link: try: @@ -54,10 +54,6 @@ class SimpleDereferer(Crypter): except Exception: self.prepare() self.preload() - - if self.html is None: - self.fail(_("No html retrieved")) - self.checkStatus() link = self.getLink() @@ -66,10 +62,13 @@ class SimpleDereferer(Crypter): self.urls = [link.strip()] #@TODO: Remove `.strip()` in 0.4.10 elif not self.urls and not self.packages: #@TODO: Remove in 0.4.10 - self.fail("No link grabbed") + self.fail(_("No link grabbed")) def prepare(self): + self.info = {} + self.html = "" + self.req.setOption("timeout", 120) if isinstance(self.COOKIES, list): diff --git a/module/plugins/internal/SimpleHoster.py b/module/plugins/internal/SimpleHoster.py index 3f14ca711..c74e33d59 100644 --- a/module/plugins/internal/SimpleHoster.py +++ b/module/plugins/internal/SimpleHoster.py @@ -1,10 +1,11 @@ # -*- coding: utf-8 -*- +import mimetypes +import os import re from datetime import datetime, timedelta from inspect import isclass -from os.path import exists from time import time from urllib import unquote from urlparse import urljoin, urlparse @@ -107,7 +108,13 @@ def parseFileInfo(plugin, url="", html=""): info = plugin.getInfo(url, html) res = info['name'], info['size'], info['status'], info['url'] else: - res = urlparse(unquote(url)).path.split('/')[-1] or _("Unknown"), 0, 3, url + url = unquote(url) + res = ((urlparse(url).path.split('/')[-1] + or urlparse(url).query.split('=', 1)[::-1][0].split('&', 1)[0] + or _("Unknown")), + 0, + 3 if url else 8, + url) return res @@ -133,37 +140,86 @@ def timestamp(): #@TODO: Move to hoster class in 0.4.10 -def directLink(self, url, resumable=False): - link = "" +def fileUrl(self, url, follow_location=None): + link = "" + redirect = 1 - for i in xrange(5 if resumable else 1): - header = self.load(url, ref=True, cookies=True, just_header=True, decode=True) + if type(follow_location) is int: + redirect = max(follow_location, 1) + else: + redirect = 5 + + for i in xrange(redirect): + try: + self.logDebug("Redirect #%d to: %s" % (i, url)) + header = self.load(url, ref=True, cookies=True, just_header=True, decode=True) + + except Exception: #: Bad bad bad... + req = pyreq.getHTTPRequest() + res = req.load(url, cookies=True, just_header=True, decode=True) + + req.close() + + header = {"code": req.code} + for line in res.splitlines(): + line = line.strip() + if not line or ":" not in line: + continue + + key, none, value = line.partition(":") + key = key.lower().strip() + value = value.strip() + + if key in header: + if type(header[key]) == list: + header[key].append(value) + else: + header[key] = [header[key], value] + else: + header[key] = value if 'content-disposition' in header: link = url - elif 'location' in header and header['location']: + elif 'location' in header and header['location'].strip(): location = header['location'] if not urlparse(location).scheme: - parsed = urlparse(url) - base = "%s://%s" % (parsed.scheme, parsed.netloc) - location = urljoin(base, location) + url_p = urlparse(url) + baseurl = "%s://%s" % (url_p.scheme, url_p.netloc) + location = urljoin(baseurl, location) + + if 'code' in header and header['code'] == 302: + link = location - if resumable: + if follow_location: url = location - self.logDebug("Redirect #%d to: %s" % (++i, location)) continue - elif 'code' in header and header['code'] == 302: - link = location + else: + extension = os.path.splitext(urlparse(url).path.split('/')[-1])[-1] - elif 'content-type' in header and header['content-type'] and "html" not in header['content-type']: - link = url + if 'content-type' in header and header['content-type'].strip(): + mimetype = header['content-type'].split(';')[0].strip() + + elif extension: + mimetype = mimetypes.guess_type(extension, False)[0] or "application/octet-stream" + + else: + mimetype = "" + + if mimetype and (link or 'html' not in mimetype): + link = url + else: + link = "" break + else: - self.logError(_("Too many redirects")) + try: + self.logError(_("Too many redirects")) + except Exception: + pass return link @@ -189,7 +245,7 @@ def secondsToMidnight(gmt=0): class SimpleHoster(Hoster): __name__ = "SimpleHoster" __type__ = "hoster" - __version__ = "0.98" + __version__ = "1.12" __pattern__ = r'^unmatchable$' @@ -253,7 +309,7 @@ class SimpleHoster(Hoster): MULTI_HOSTER = False #: Set to True to leech other hoster link (as defined in handleMulti method) LOGIN_ACCOUNT = False #: Set to True to require account login - directLink = directLink #@TODO: Remove in 0.4.10 + directLink = fileUrl #@TODO: Remove in 0.4.10 @classmethod @@ -277,7 +333,7 @@ class SimpleHoster(Hoster): @classmethod def getInfo(cls, url="", html=""): info = cls.apiInfo(url) - online = False + online = False if info['status'] != 2 else True try: info['pattern'] = re.match(cls.__pattern__, url).groupdict() #: pattern groups will be saved here @@ -285,12 +341,12 @@ class SimpleHoster(Hoster): except Exception: info['pattern'] = {} - if not html: + if not html and not online: if not url: info['error'] = "missing url" info['status'] = 1 - elif info['status'] is 3: + elif info['status'] is 3 and not fileUrl(None, url): try: html = getURL(url, cookies=cls.COOKIES, decode=not cls.TEXT_ENCODING) @@ -368,6 +424,7 @@ class SimpleHoster(Hoster): self.pyfile.error = "" #@TODO: Remove in 0.4.10 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 self.multihost = False #@TODO: Move to hoster class in 0.4.10 @@ -434,10 +491,16 @@ class SimpleHoster(Hoster): self.checkFile() - def downloadLink(self, link): + def downloadLink(self, link, disposition=False): #@TODO: Set `disposition=True` in 0.4.10 if link and isinstance(link, basestring): self.correctCaptcha() - self.download(link, disposition=False) #@TODO: Set `disposition=True` in 0.4.10 + + if not urlparse(link).scheme: + url_p = urlparse(self.pyfile.url) + baseurl = "%s://%s" % (url_p.scheme, url_p.netloc) + link = urljoin(baseurl, link) + + self.download(link, ref=False, disposition=disposition) def checkFile(self): @@ -445,7 +508,7 @@ class SimpleHoster(Hoster): self.invalidCaptcha() self.retry(10, reason=_("Wrong captcha")) - elif not self.lastDownload or not exists(fs_encode(self.lastDownload)): + elif not self.lastDownload or not os.path.exists(fs_encode(self.lastDownload)): self.lastDownload = "" self.error(self.pyfile.error or _("No file downloaded")) @@ -472,7 +535,7 @@ class SimpleHoster(Hoster): self.logWarning(_("No html code to check")) return - if hasattr(self, 'PREMIUM_ONLY_PATTERN') and self.premium and re.search(self.PREMIUM_ONLY_PATTERN, self.html): + if hasattr(self, 'PREMIUM_ONLY_PATTERN') and not self.premium and re.search(self.PREMIUM_ONLY_PATTERN, self.html): self.fail(_("Link require a premium account to be handled")) elif hasattr(self, 'ERROR_PATTERN'): @@ -577,16 +640,12 @@ class SimpleHoster(Hoster): if not hasattr(self, 'LINK_FREE_PATTERN'): self.logError(_("Free download not implemented")) - try: - m = re.search(self.LINK_FREE_PATTERN, self.html) - if m is None: - self.error(_("Free download link not found")) - + m = re.search(self.LINK_FREE_PATTERN, self.html) + if m is None: + self.error(_("Free download link not found")) + else: self.link = m.group(1) - except Exception, e: - self.fail(e) - def handlePremium(self, pyfile): if not hasattr(self, 'LINK_PREMIUM_PATTERN'): @@ -594,16 +653,12 @@ class SimpleHoster(Hoster): self.logDebug("Handled as free download") self.handleFree(pyfile) - try: - m = re.search(self.LINK_PREMIUM_PATTERN, self.html) - if m is None: - self.error(_("Premium download link not found")) - + m = re.search(self.LINK_PREMIUM_PATTERN, self.html) + if m is None: + self.error(_("Premium download link not found")) + else: self.link = m.group(1) - except Exception, e: - self.fail(e) - def longWait(self, wait_time=None, max_tries=3): if wait_time and isinstance(wait_time, (int, long, float)): diff --git a/module/plugins/internal/UnRar.py b/module/plugins/internal/UnRar.py index 572fe95b9..7f1b08caf 100644 --- a/module/plugins/internal/UnRar.py +++ b/module/plugins/internal/UnRar.py @@ -4,7 +4,6 @@ import os import re from glob import glob -from os.path import basename, dirname, join from string import digits from subprocess import Popen, PIPE @@ -13,30 +12,31 @@ from module.utils import save_join, decode def renice(pid, value): - if os.name != "nt" and value: + if value and os.name != "nt": try: Popen(["renice", str(value), str(pid)], stdout=PIPE, stderr=PIPE, bufsize=-1) - except: - print "Renice failed" + except Exception: + pass class UnRar(Extractor): __name__ = "UnRar" - __version__ = "1.01" + __version__ = "1.04" __description__ = """Rar extractor plugin""" __license__ = "GPLv3" - __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] + __authors__ = [("RaNaN", "RaNaN@pyload.org"), + ("Walter Purcaro", "vuolter@gmail.com")] CMD = "unrar" - EXTENSIONS = ["rar", "zip", "cab", "arj", "lzh", "tar", "gz", "bz2", "ace", "uue", "jar", "iso", "7z", "xz", "z"] - + EXTENSIONS = [".rar", ".zip", ".cab", ".arj", ".lzh", ".tar", ".gz", ".bz2", + ".ace", ".uue", ".jar", ".iso", ".7z", ".xz", ".z"] #@NOTE: there are some more uncovered rar formats - re_rarpart = re.compile(r'(.*)\.part(\d+)\.rar$', re.I) - re_rarfile = re.compile(r'.*\.(rar|r\d+)$', re.I) + re_rarpart1 = re.compile(r'\.part(\d+)\.rar$', re.I) + re_rarpart2 = re.compile(r'\.r(\d+)$', re.I) re_filelist = re.compile(r'(.+)\s+(\d+)\s+(\d+)\s+|(.+)\s+(\d+)\s+\d\d-\d\d-\d\d\s+\d\d:\d\d\s+(.+)') re_wrongpwd = re.compile(r'password', re.I) @@ -46,7 +46,7 @@ class UnRar(Extractor): @classmethod def checkDeps(cls): if os.name == "nt": - cls.CMD = join(pypath, "UnRAR.exe") + cls.CMD = os.path.join(pypath, "UnRAR.exe") p = Popen([cls.CMD], stdout=PIPE, stderr=PIPE) p.communicate() else: @@ -54,8 +54,7 @@ class UnRar(Extractor): p = Popen([cls.CMD], stdout=PIPE, stderr=PIPE) p.communicate() - except OSError: - # fallback to rar + except OSError: #: fallback to rar cls.CMD = "rar" p = Popen([cls.CMD], stdout=PIPE, stderr=PIPE) p.communicate() @@ -64,97 +63,50 @@ class UnRar(Extractor): @classmethod - def isArchive(cls, file): - f = basename(file).lower() - return any(f.endswith('.%s' % ext) for ext in cls.EXTENSIONS) - - - @classmethod def getTargets(cls, files_ids): targets = [] - for file, id in files_ids: - if not cls.isArchive(file): + for filename, id in files_ids: + if not cls.isArchive(filename): continue - m = cls.re_rarpart.findall(file) - if m: - # only add first parts - if int(m[0][1]) == 1: - targets.append((file, id)) - else: - targets.append((file, id)) + m = cls.re_rarpart1.match(filename) + if not m or int(m.group(1)) is 1: #@NOTE: only add first part file + targets.append((filename, id)) return targets - def check(self, out="", err=""): - if not out or not err: - return - - if err.strip(): - if self.re_wrongpwd.search(err): - raise PasswordError - - elif self.re_wrongcrc.search(err): - raise CRCError + def checkArchive(self): + p = self.call_cmd("l", "-v", self.target) + out, err = p.communicate() - else: #: raise error if anything is on stderr - raise ArchiveError(err.strip()) + if self.re_wrongpwd.search(err): + return True # output only used to check if passworded files are present for attr in self.re_filelist.findall(out): if attr[0].startswith("*"): - raise PasswordError - - - def verify(self): - p = self.call_cmd("l", "-v", self.file, password=self.password) - - self.check(*p.communicate()) - - if p and p.returncode: - raise ArchiveError("Process terminated") - - if not self.list(): - raise ArchiveError("Empty archive") - - - def isPassword(self, password): - if isinstance(password, basestring): - p = self.call_cmd("l", "-v", self.file, password=password) - out, err = p.communicate() - - if not self.re_wrongpwd.search(err): return True + self.files = self.list() + if not self.files: + raise ArchiveError("Empty Archive") + return False - def repair(self): - p = self.call_cmd("rc", self.file) + def checkPassword(self, password): + # at this point we can only verify header protected files + p = self.call_cmd("l", "-v", self.target, password=password) out, err = p.communicate() + return False if self.re_wrongpwd.search(err) else True - if p.returncode or err.strip(): - p = self.call_cmd("r", self.file) - out, err = p.communicate() - - if p.returncode or err.strip(): - return False - else: - self.file = join(dirname(self.file), re.search(r'(fixed|rebuild)\.%s' % basename(self.file), out).group(0)) - - return True - - - def extract(self, progress=lambda x: None): - self.verify() - - progress(0) + def extract(self, password=None): command = "x" if self.fullpath else "e" - p = self.call_cmd(command, self.file, self.out, password=self.password) + p = self.call_cmd(command, self.target, self.out, password=password) renice(p.pid, self.renice) @@ -165,8 +117,8 @@ class UnRar(Extractor): if not c: break # reading a percentage sign -> set progress and restart - if c is '%': - progress(int(progressstring)) + if c == '%': + self.notifyProgress(int(progressstring)) progressstring = "" # not reading a digit -> therefore restart elif c not in digits: @@ -175,44 +127,57 @@ class UnRar(Extractor): else: progressstring += c - progress(100) + # retrieve stderr + err = p.stderr.read() - self.files = self.list() + if self.re_wrongpwd.search(err): + raise PasswordError - # retrieve stderr - self.check(err=p.stderr.read()) + elif self.re_wrongcrc.search(err): + raise CRCError + + elif err.strip(): #: raise error if anything is on stderr + raise ArchiveError(err.strip()) - if p.returncode: + if p.returncode != 0: raise ArchiveError("Process terminated") + if not self.files: + self.files = self.list(password) + def getDeleteFiles(self): - if ".part" in basename(self.file): - return glob(re.sub("(?<=\.part)([01]+)", "*", self.file, re.I)) + files = [] - # get files which matches .r* and filter unsuited files out - parts = glob(re.sub(r"(?<=\.r)ar$", "*", self.file, re.I)) + for i in [1, 2]: + try: + dir, name = os.path.split(self.target) + part = self.getattr(self, "re_rarpart%d" % i).match(name).group(1) + filename = os.path.join(dir, name.replace(part, '*', 1)) + files.extend(glob(filename)) - return filter(lambda x: self.re_rarfile.match(x), parts) + except Exception: + continue + if self.target not in files: + files.insert(0, self.target) - def list(self): + return files + + + def list(self, password=None): command = "vb" if self.fullpath else "lb" - p = self.call_cmd(command, "-v", self.file, password=self.password) + p = self.call_cmd(command, "-v", self.target, password=password) out, err = p.communicate() - if err.strip(): - self.m.logError(err) - if "Cannot open" in err: - return list() + if "Cannot open" in err: + raise ArchiveError("Cannot open file") - if p.returncode: - self.m.logError("Process terminated") - return list() + if err.strip(): #: only log error at this point + self.manager.logError(err.strip()) result = set() - for f in decode(out).splitlines(): f = f.strip() result.add(save_join(self.out, f)) @@ -248,6 +213,8 @@ class UnRar(Extractor): # NOTE: return codes are not reliable, some kind of threading, cleanup whatever issue call = [self.CMD, command] + args + list(xargs) - self.m.logDebug(" ".join(call)) - return Popen(call, stdout=PIPE, stderr=PIPE) + self.manager.logDebug(" ".join(call)) + + p = Popen(call, stdout=PIPE, stderr=PIPE) + return p diff --git a/module/plugins/internal/UnZip.py b/module/plugins/internal/UnZip.py index 5ec56cbdf..026503be5 100644 --- a/module/plugins/internal/UnZip.py +++ b/module/plugins/internal/UnZip.py @@ -2,6 +2,7 @@ from __future__ import with_statement +import os import sys import zipfile @@ -10,14 +11,15 @@ from module.plugins.internal.Extractor import Extractor, ArchiveError, CRCError, class UnZip(Extractor): __name__ = "UnZip" - __version__ = "1.01" + __version__ = "1.03" __description__ = """Zip extractor plugin""" __license__ = "GPLv3" - __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] + __authors__ = [("RaNaN", "RaNaN@pyload.org"), + ("Walter Purcaro", "vuolter@gmail.com")] - EXTENSIONS = ["zip", "zip64"] + EXTENSIONS = [".zip", ".zip64"] @classmethod @@ -26,61 +28,25 @@ class UnZip(Extractor): @classmethod - def isArchive(cls, file): - return zipfile.is_zipfile(file) + def getTargets(cls, files_ids): + return [(filename, id) for filename, id in files_ids if cls.isArchive(filename)] - def verify(self): + def extract(self, password=None): try: - with zipfile.ZipFile(self.file, 'r', allowZip64=True) as z: + with zipfile.ZipFile(self.target, 'r', allowZip64=True) as z: z.setpassword(self.password) - badcrc = z.testzip() + if not z.testzip(): + z.extractall(self.out) + self.files = z.namelist() + else: + raise CRCError except (BadZipfile, LargeZipFile), e: raise ArchiveError(e) except RuntimeError, e: - if 'encrypted' in e: + if "encrypted" in e: raise PasswordError else: raise ArchiveError(e) - - else: - if badcrc: - raise CRCError - - if not self.list(): - raise ArchiveError("Empty archive") - - - def list(self): - try: - with zipfile.ZipFile(self.file, 'r', allowZip64=True) as z: - z.setpassword(self.password) - return z.namelist() - except Exception: - return list() - - - def extract(self, progress=lambda x: None): - try: - with zipfile.ZipFile(self.file, 'r', allowZip64=True) as z: - progress(0) - z.extractall(self.out, pwd=self.password) - progress(100) - - except (BadZipfile, LargeZipFile), e: - raise ArchiveError(e) - - except RuntimeError, e: - if e is "Bad password for file": - raise PasswordError - else: - raise ArchiveError(e) - - finally: - self.files = self.list() - - - def getDeleteFiles(self): - return [self.file] diff --git a/module/plugins/internal/XFSAccount.py b/module/plugins/internal/XFSAccount.py index c350729ac..c3bd91e52 100644 --- a/module/plugins/internal/XFSAccount.py +++ b/module/plugins/internal/XFSAccount.py @@ -23,7 +23,7 @@ class XFSAccount(Account): HOSTER_DOMAIN = None HOSTER_URL = None - COOKIES = [(HOSTER_DOMAIN, "lang", "english")] + COOKIES = True PREMIUM_PATTERN = r'\(Premium only\)' @@ -46,9 +46,15 @@ class XFSAccount(Account): def init(self): if not self.HOSTER_DOMAIN: self.logError(_("Missing HOSTER_DOMAIN")) + self.COOKIES = False - if not self.HOSTER_URL: - self.HOSTER_URL = "http://www.%s/" % (self.HOSTER_DOMAIN or "") + else: + if not self.HOSTER_URL: + self.HOSTER_URL = "http://www.%s/" % self.HOSTER_DOMAIN + + if isinstance(self.COOKIES, list): + self.COOKIES.insert((self.HOSTER_DOMAIN, "lang", "english")) + set_cookies(req.cj, self.COOKIES) def loadAccountInfo(self, user, req): @@ -57,6 +63,12 @@ class XFSAccount(Account): leechtraffic = None premium = None + if not self.HOSTER_URL: #@TODO: Remove in 0.4.10 + return {'validuntil' : validuntil, + 'trafficleft' : trafficleft, + 'leechtraffic': leechtraffic, + 'premium' : premium} + html = req.load(self.HOSTER_URL, get={'op': "my_account"}, decode=True) premium = True if re.search(self.PREMIUM_PATTERN, html) else False @@ -136,22 +148,25 @@ class XFSAccount(Account): else: self.logDebug("LEECH_TRAFFIC_PATTERN not found") - return {'validuntil': validuntil, 'trafficleft': trafficleft, 'leechtraffic': leechtraffic, 'premium': premium} + return {'validuntil' : validuntil, + 'trafficleft' : trafficleft, + 'leechtraffic': leechtraffic, + 'premium' : premium} def login(self, user, data, req): - if isinstance(self.COOKIES, list): - set_cookies(req.cj, self.COOKIES) + if not self.HOSTER_URL: #@TODO: Remove in 0.4.10 + raise Exception(_("Missing HOSTER_DOMAIN")) url = urljoin(self.HOSTER_URL, "login.html") html = req.load(url, decode=True) action, inputs = parseHtmlForm('name="FL"', html) if not inputs: - inputs = {'op': "login", + inputs = {'op' : "login", 'redirect': self.HOSTER_URL} - inputs.update({'login': user, + inputs.update({'login' : user, 'password': data['password']}) html = req.load(self.HOSTER_URL, post=inputs, decode=True) diff --git a/module/plugins/internal/XFSCrypter.py b/module/plugins/internal/XFSCrypter.py index 3cb837aac..665e13b18 100644 --- a/module/plugins/internal/XFSCrypter.py +++ b/module/plugins/internal/XFSCrypter.py @@ -6,7 +6,7 @@ from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo class XFSCrypter(SimpleCrypter): __name__ = "XFSCrypter" __type__ = "crypter" - __version__ = "0.05" + __version__ = "0.06" __pattern__ = r'^unmatchable$' @@ -19,10 +19,27 @@ class XFSCrypter(SimpleCrypter): URL_REPLACEMENTS = [(r'&?per_page=\d+', ""), (r'[?/&]+$', ""), (r'(.+/[^?]+)$', r'\1?'), (r'$', r'&per_page=10000')] - COOKIES = [(HOSTER_DOMAIN, "lang", "english")] - LINK_PATTERN = r'<(?:td|TD).*?>\s*<a href="(.+?)".*?>.+?(?:</a>)?\s*</(?:td|TD)>' NAME_PATTERN = r'<[tT]itle>.*?\: (?P<N>.+) folder</[tT]itle>' OFFLINE_PATTERN = r'>\s*\w+ (Not Found|file (was|has been) removed)' TEMP_OFFLINE_PATTERN = r'>\s*\w+ server (is in )?(maintenance|maintainance)' + + + def prepare(self): + if not self.HOSTER_DOMAIN: + if self.account: + account = self.account + else: + account_name = (self.__name__ + ".py").replace("Folder.py", "").replace(".py", "") + account = self.pyfile.m.core.accountManager.getAccountPlugin(account_name) + + if account and hasattr(account, "HOSTER_DOMAIN") and account.HOSTER_DOMAIN: + self.HOSTER_DOMAIN = account.HOSTER_DOMAIN + else: + self.fail(_("Missing HOSTER_DOMAIN")) + + if isinstance(self.COOKIES, list): + self.COOKIES.insert((self.HOSTER_DOMAIN, "lang", "english")) + + return super(XFSCrypter, self).prepare() diff --git a/module/plugins/internal/XFSHoster.py b/module/plugins/internal/XFSHoster.py index b32f5978f..2054b1824 100644 --- a/module/plugins/internal/XFSHoster.py +++ b/module/plugins/internal/XFSHoster.py @@ -4,6 +4,7 @@ import re from random import random from time import sleep +from urlparse import urljoin, urlparse from pycurl import FOLLOWLOCATION, LOW_SPEED_TIME @@ -15,7 +16,7 @@ from module.utils import html_unescape class XFSHoster(SimpleHoster): __name__ = "XFSHoster" __type__ = "hoster" - __version__ = "0.35" + __version__ = "0.41" __pattern__ = r'^unmatchable$' @@ -29,7 +30,6 @@ class XFSHoster(SimpleHoster): HOSTER_DOMAIN = None TEXT_ENCODING = False - COOKIES = [(HOSTER_DOMAIN, "lang", "english")] DIRECT_LINK = None MULTI_HOSTER = True #@NOTE: Should be default to False for safe, but I'm lazy... @@ -56,17 +56,28 @@ class XFSHoster(SimpleHoster): def setup(self): - self.chunkLimit = 1 + self.chunkLimit = -1 if self.premium else 1 self.resumeDownload = self.multiDL = self.premium def prepare(self): """ Initialize important variables """ if not self.HOSTER_DOMAIN: - self.fail(_("Missing HOSTER_DOMAIN")) + if self.account: + account = self.account + else: + account = self.pyfile.m.core.accountManager.getAccountPlugin(self.__name__) + + if account and hasattr(account, "HOSTER_DOMAIN") and account.HOSTER_DOMAIN: + self.HOSTER_DOMAIN = account.HOSTER_DOMAIN + else: + self.fail(_("Missing HOSTER_DOMAIN")) + + if isinstance(self.COOKIES, list): + self.COOKIES.insert((self.HOSTER_DOMAIN, "lang", "english")) if not self.LINK_PATTERN: - pattern = r'(https?://(www\.)?([^/]*?%s|\d+\.\d+\.\d+\.\d+)(\:\d+)?(/d/|(/files)?/\d+/\w+/).+?)["\'<]' + pattern = r'(https?://(?:www\.)?([^/]*?%s|\d+\.\d+\.\d+\.\d+)(\:\d+)?(/d/|(/files)?/\d+/\w+/).+?)["\'<]' self.LINK_PATTERN = pattern % self.HOSTER_DOMAIN.replace('.', '\.') self.captcha = None @@ -75,15 +86,19 @@ class XFSHoster(SimpleHoster): super(XFSHoster, self).prepare() if self.DIRECT_LINK is None: - self.directDL = bool(self.premium) + self.directDL = self.premium - def downloadLink(self, link): + def downloadLink(self, link, disposition=False): #@TODO: Set `disposition=True` in 0.4.10 if link and isinstance(link, basestring): - if self.captcha: - self.correctCaptcha() + self.correctCaptcha() + + if not urlparse(link).scheme: + url_p = urlparse(self.pyfile.url) + baseurl = "%s://%s" % (url_p.scheme, url_p.netloc) + link = urljoin(baseurl, link) - self.download(link, ref=True, cookies=True, disposition=False) #@TODO: Set `disposition=True` in 0.4.10 + self.download(link, ref=False, disposition=disposition) elif self.errmsg: if 'captcha' in self.errmsg: @@ -311,25 +326,25 @@ class XFSHoster(SimpleHoster): recaptcha = ReCaptcha(self) try: captcha_key = re.search(self.RECAPTCHA_PATTERN, self.html).group(1) - except: + except Exception: captcha_key = recaptcha.detect_key() else: self.logDebug("ReCaptcha key: %s" % captcha_key) if captcha_key: - inputs['recaptcha_challenge_field'], inputs['recaptcha_response_field'] = recaptcha.challenge(captcha_key) + inputs['recaptcha_response_field'], inputs['recaptcha_challenge_field'] = recaptcha.challenge(captcha_key) return 3 solvemedia = SolveMedia(self) try: captcha_key = re.search(self.SOLVEMEDIA_PATTERN, self.html).group(1) - except: + except Exception: captcha_key = solvemedia.detect_key() else: self.logDebug("SolveMedia key: %s" % captcha_key) if captcha_key: - inputs['adcopy_challenge'], inputs['adcopy_response'] = solvemedia.challenge(captcha_key) + inputs['adcopy_response'], inputs['adcopy_challenge'] = solvemedia.challenge(captcha_key) return 4 return 0 |