diff options
Diffstat (limited to 'module/plugins/hoster')
67 files changed, 3819 insertions, 1335 deletions
diff --git a/module/plugins/hoster/AlldebridCom.py b/module/plugins/hoster/AlldebridCom.py new file mode 100644 index 000000000..e93e7beb9 --- /dev/null +++ b/module/plugins/hoster/AlldebridCom.py @@ -0,0 +1,91 @@ +#!/usr/nv python
+# -*- coding: utf-8 -*-
+
+import re
+from urllib import quote, unquote
+from random import randrange
+from os import stat
+
+from module.plugins.Hoster import Hoster
+from module.common.json_layer import json_loads
+from module.utils import parseFileSize, fs_encode
+
+
+class AlldebridCom(Hoster):
+ __name__ = "AlldebridCom"
+ __version__ = "0.2"
+ __type__ = "hoster"
+
+ __pattern__ = r"https?://.*alldebrid\..*"
+ __description__ = """Alldebrid.com hoster plugin"""
+ __author_name__ = ("Andy, Voigt")
+ __author_mail__ = ("spamsales@online.de")
+
+ def getFilename(self, url):
+ try:
+ name = unquote(url.rsplit("/", 1)[1])
+ except IndexError:
+ name = "Unknown_Filename..."
+ if name.endswith("..."): #incomplete filename, append random stuff
+ name += "%s.tmp" % randrange(100,999)
+ return name
+
+ def init(self):
+ self.tries = 0
+ self.chunkLimit = 3
+ self.resumeDownload = True
+
+
+ def process(self, pyfile):
+ if not self.account:
+ self.logError(_("Please enter your AllDebrid account or deactivate this plugin"))
+ self.fail("No AllDebrid account provided")
+
+ self.log.debug("AllDebrid: Old URL: %s" % pyfile.url)
+ if re.match(self.__pattern__, pyfile.url):
+ new_url = pyfile.url
+ else:
+ password = self.getPassword().splitlines()
+ if not password: password = ""
+ else: password = password[0]
+
+ url = "http://www.alldebrid.com/service.php?link=%s&json=true&pw=%s" %(pyfile.url, password)
+ page = self.load(url)
+ data = json_loads(page)
+
+ self.log.debug("Json data: %s" % str(data))
+
+ if data["error"]:
+ if data["error"] == "This link isn't available on the hoster website.":
+ self.offline()
+ else:
+ self.logWarning(data["error"])
+ self.tempOffline()
+ else:
+ if self.pyfile.name and not self.pyfile.name.endswith('.tmp'):
+ self.pyfile.name = data["filename"]
+ self.pyfile.size = parseFileSize(data["filesize"])
+ new_url = data["link"]
+
+ if self.getConfig("https"):
+ new_url = new_url.replace("http://", "https://")
+ else:
+ new_url = new_url.replace("https://", "http://")
+
+ self.log.debug("AllDebrid: New URL: %s" % new_url)
+
+ if pyfile.name.startswith("http") or pyfile.name.startswith("Unknown"):
+ #only use when name wasnt already set
+ pyfile.name = self.getFilename(new_url)
+
+ self.download(new_url, disposition=True)
+
+ check = self.checkDownload(
+ {"error": "<title>An error occured while processing your request</title>","empty": re.compile(r"^$")})
+
+ if check == "error":
+ self.retry(reason="An error occured while generating link.", wait_time=60)
+ else:
+ if check == "empty":
+ self.retry(reason="Downloaded File was empty.", wait_time=60)
+
diff --git a/module/plugins/hoster/BasePlugin.py b/module/plugins/hoster/BasePlugin.py index 0e9595265..f1e3006d0 100644 --- a/module/plugins/hoster/BasePlugin.py +++ b/module/plugins/hoster/BasePlugin.py @@ -1,16 +1,18 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- from urlparse import urlparse +from re import search +from urllib import unquote from module.network.HTTPRequest import BadHeader from module.plugins.Hoster import Hoster -from module.utils import html_unescape +from module.utils import html_unescape, remove_chars class BasePlugin(Hoster): __name__ = "BasePlugin" __type__ = "hoster" __pattern__ = r"^unmatchable$" - __version__ = "0.14" + __version__ = "0.15" __description__ = """Base Plugin when any other didnt fit""" __author_name__ = ("RaNaN") __author_mail__ = ("RaNaN@pyload.org") @@ -60,5 +62,28 @@ class BasePlugin(Hoster): def downloadFile(self, pyfile): - pyfile.name = html_unescape(urlparse(pyfile.url).path.split("/")[-1]) - self.download(pyfile.url, disposition=True) + header = self.load(pyfile.url, just_header = True) + #self.logDebug(header) + + if 'location' in header: + self.logDebug("Location: " + header['location']) + url = unquote(header['location']) + else: + url = pyfile.url + + name = html_unescape(unquote(urlparse(url).path.split("/")[-1])) + + if 'content-disposition' in header: + self.logDebug("Content-Disposition: " + header['content-disposition']) + m = search("filename(?P<type>=|\*=(?P<enc>.+)'')(?P<name>.*)", header['content-disposition']) + if m: + disp = m.groupdict() + self.logDebug(disp) + if not disp['enc']: disp['enc'] = 'utf-8' + name = remove_chars(disp['name'], "\"';").strip() + name = unicode(unquote(name), disp['enc']) + + if not name: name = url + pyfile.name = name + self.logDebug("Filename: %s" % pyfile.name) + self.download(url, disposition=True)
\ No newline at end of file diff --git a/module/plugins/hoster/BayfilesCom.py b/module/plugins/hoster/BayfilesCom.py index c771f28c6..190d9a952 100644 --- a/module/plugins/hoster/BayfilesCom.py +++ b/module/plugins/hoster/BayfilesCom.py @@ -26,18 +26,19 @@ class BayfilesCom(SimpleHoster): __name__ = "BayfilesCom" __type__ = "hoster" __pattern__ = r"http://(?:www\.)?bayfiles\.com/file/\w+/\w+/.*" - __version__ = "0.01" + __version__ = "0.04" __description__ = """Bayfiles.com plugin - free only""" __author_name__ = ("zoidberg") __author_mail__ = ("zoidberg@mujmail.cz") FILE_INFO_PATTERN = r'<p title="(?P<N>[^"]+)">[^<]*<strong>(?P<S>[0-9., ]+)(?P<U>[kKMG])i?B</strong></p>' - FILE_OFFLINE_PATTERN = r'<p>The requested file could not be found.</p>' + FILE_OFFLINE_PATTERN = r'(<p>The requested file could not be found.</p>|<title>404 Not Found</title>)' WAIT_PATTERN = r'>Your IP [0-9.]* has recently downloaded a file\. Upgrade to premium or wait (\d+) minutes\.<' VARS_PATTERN = r'var vfid = (\d+);\s*var delay = (\d+);' LINK_PATTERN = r"javascript:window.location.href = '([^']+)';" - + PREMIUM_LINK_PATTERN = r'(?:<a class="highlighted-btn" href="|(?=http://s\d+\.baycdn\.com/dl/))(.*?)"' + def handleFree(self): found = re.search(self.WAIT_PATTERN, self.html) if found: @@ -69,9 +70,24 @@ class BayfilesCom(SimpleHoster): # Get final link and download found = re.search(self.LINK_PATTERN, self.html) if not found: self.parseError("Free link") - url = found.group(1) - self.logDebug("URL: " + url) - + self.startDownload(found.group(1)) + + def handlePremium(self): + found = re.search(self.PREMIUM_LINK_PATTERN, self.html) + if not found: self.parseError("Premium link") + self.startDownload(found.group(1)) + + def startDownload(self, url): + self.logDebug("%s URL: %s" % ("Premium" if self.premium else "Free", url)) self.download(url) + # check download + check = self.checkDownload({ + "waitforfreeslots": re.compile(r"<title>BayFiles</title>"), + "notfound": re.compile(r"<title>404 Not Found</title>") + }) + if check == "waitforfreeslots": + self.retry(60, 300, "Wait for free slot") + elif check == "notfound": + self.retry(60, 300, "404 Not found") -getInfo = create_getInfo(BayfilesCom)
\ No newline at end of file +getInfo = create_getInfo(BayfilesCom) diff --git a/module/plugins/hoster/BitshareCom.py b/module/plugins/hoster/BitshareCom.py index 794e978b2..f5d59d428 100644 --- a/module/plugins/hoster/BitshareCom.py +++ b/module/plugins/hoster/BitshareCom.py @@ -2,6 +2,7 @@ from __future__ import with_statement import re +from pycurl import FOLLOWLOCATION from module.plugins.Hoster import Hoster from module.plugins.ReCaptcha import ReCaptcha @@ -45,22 +46,24 @@ class BitshareCom(Hoster): __name__ = "BitshareCom" __type__ = "hoster" __pattern__ = r"http://(www\.)?bitshare\.com/(files/(?P<id1>[a-zA-Z0-9]+)(/(?P<name>.*?)\.html)?|\?f=(?P<id2>[a-zA-Z0-9]+))" - __version__ = "0.41" + __version__ = "0.45" __description__ = """Bitshare.Com File Download Hoster""" __author_name__ = ("paulking", "fragonib") __author_mail__ = (None, "fragonib[AT]yahoo[DOT]es") HOSTER_DOMAIN = "bitshare.com" FILE_OFFLINE_PATTERN = r'''(>We are sorry, but the requested file was not found in our database|>Error - File not available<|The file was deleted either by the uploader, inactivity or due to copyright claim)''' - FILE_INFO_PATTERN = r'<h1>Downloading\s(?P<name>.+?)\s-\s(?P<size>[\d.]+)\s(?P<units>..)yte</h1>' + FILE_INFO_PATTERN = r'<h1>(Downloading|Streaming)\s(?P<name>.+?)\s-\s(?P<size>[\d.]+)\s(?P<units>..)yte</h1>' FILE_AJAXID_PATTERN = r'var ajaxdl = "(.*?)";' CAPTCHA_KEY_PATTERN = r"http://api\.recaptcha\.net/challenge\?k=(.*?) " def setup(self): - self.multiDL = False + self.multiDL = self.premium self.chunkLimit = 1 def process(self, pyfile): + if self.premium: + self.account.relogin(self.user) self.pyfile = pyfile @@ -71,7 +74,7 @@ class BitshareCom(Hoster): # Load main page self.req.cj.setCookie(self.HOSTER_DOMAIN, "language_selection", "EN") - self.html = self.load(self.pyfile.url, ref=False, decode=True) + self.html = self.load(self.pyfile.url, ref=False, decode=True, cookies = False) # Check offline if re.search(self.FILE_OFFLINE_PATTERN, self.html) is not None: @@ -87,12 +90,20 @@ class BitshareCom(Hoster): # Ajax file id self.ajaxid = re.search(BitshareCom.FILE_AJAXID_PATTERN, self.html).group(1) self.logDebug("File ajax id is [%s]" % self.ajaxid) + + # This may either download our file or forward us to an error page + url = self.getDownloadUrl() + self.logDebug("Downloading file with url [%s]" % url) + self.download(url) - # Handle free downloading - self.handleFree() - - def handleFree(self): - + + def getDownloadUrl(self): + # Return location if direct download is active + if self.premium: + header = self.load(self.pyfile.url, cookies = True, just_header = True) + if 'location' in header: + return header['location'] + # Get download info self.logDebug("Getting download info") response = self.load("http://bitshare.com/files-ajax/" + self.file_id + "/request.html", @@ -107,8 +118,13 @@ class BitshareCom(Hoster): # Waiting if wait > 0: self.logDebug("Waiting %d seconds." % wait) - self.setWait(wait, True) - self.wait() + if wait < 120: + self.setWait(wait, False) + self.wait() + else: + self.setWait(wait - 55, True) + self.wait() + self.retry() # Resolve captcha if captcha == 1: @@ -131,15 +147,14 @@ class BitshareCom(Hoster): post={"request" : "getDownloadURL", "ajaxid" : self.ajaxid}) self.handleErrors(response, '#') url = response.split("#")[-1] - - # Request download URL - # This may either download our file or forward us to an error page - self.logDebug("Downloading file with url [%s]" % url) - self.download(url) + return url + def handleErrors(self, response, separator): self.logDebug("Checking response [%s]" % response) - if "ERROR" in response: + if "ERROR:Session timed out" in response: + self.retry() + elif "ERROR" in response: msg = response.split(separator)[-1] self.fail(msg) @@ -148,5 +163,7 @@ class BitshareCom(Hoster): if "SUCCESS" in response: self.correctCaptcha() return True + elif "ERROR:SESSION ERROR" in response: + self.retry() self.logDebug("Wrong captcha") - self.invalidCaptcha()
\ No newline at end of file + self.invalidCaptcha() diff --git a/module/plugins/hoster/CoolshareCz.py b/module/plugins/hoster/CoolshareCz.py new file mode 100644 index 000000000..7007b6fcb --- /dev/null +++ b/module/plugins/hoster/CoolshareCz.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- +""" + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <http://www.gnu.org/licenses/>. + + @author: zoidberg +""" + +#shares code with WarserverCz + +import re +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo +from module.network.HTTPRequest import BadHeader +from module.utils import html_unescape + +class CoolshareCz(SimpleHoster): + __name__ = "CoolshareCz" + __type__ = "hoster" + __pattern__ = r"http://(?:\w*\.)?coolshare.cz/stahnout/(?P<ID>\d+)/.+" + __version__ = "0.12" + __description__ = """CoolShare.cz""" + __author_name__ = ("zoidberg") + + FILE_NAME_PATTERN = ur'<h1.*?>Stáhnout (?P<N>[^<]+)</h1>' + FILE_SIZE_PATTERN = r'<li>Velikost: <strong>(?P<S>[^<]+)</strong>' + FILE_OFFLINE_PATTERN = r'<h1>Soubor nenalezen</h1>' + + PREMIUM_URL_PATTERN = r'href="(http://[^/]+/dwn-premium.php.*?)"' + DOMAIN = "http://csd01.coolshare.cz" + + SH_CHECK_TRAFFIC = True + + def handleFree(self): + try: + self.download("%s/dwn-free.php?fid=%s" % (self.DOMAIN, self.file_info['ID'])) + except BadHeader, e: + if e.code == 403: + self.setWait(300, True) + self.wait() + self.retry(max_tries = 24, reason = "Download limit reached") + else: raise + + def handlePremium(self): + found = re.search(self.PREMIUM_URL_PATTERN, self.html) + if not found: self.parseError("Premium URL") + url = html_unescape(found.group(1)) + self.logDebug("Premium URL: " + url) + if not url.startswith("http://"): self.resetAccount() + self.download(url) + +getInfo = create_getInfo(CoolshareCz)
\ No newline at end of file diff --git a/module/plugins/hoster/CramitIn.py b/module/plugins/hoster/CramitIn.py new file mode 100644 index 000000000..a7935c744 --- /dev/null +++ b/module/plugins/hoster/CramitIn.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +from module.plugins.hoster.XFileSharingPro import XFileSharingPro, create_getInfo + +class CramitIn(XFileSharingPro): + __name__ = "CramitIn" + __type__ = "hoster" + __pattern__ = r"http://(?:\w*\.)*cramit.in/\w{12}" + __version__ = "0.03" + __description__ = """Cramit.in hoster plugin""" + __author_name__ = ("zoidberg") + __author_mail__ = ("zoidberg@mujmail.cz") + + FILE_INFO_PATTERN = r'<span class=t2>\s*(?P<N>.*?)</span>.*?<small>\s*\((?P<S>.*?)\)' + DIRECT_LINK_PATTERN = r'href="(http://cramit.in/file_download/.*?)"' + HOSTER_NAME = "cramit.in" + + def setup(self): + self.multiDL = self.premium + +getInfo = create_getInfo(CramitIn)
\ No newline at end of file diff --git a/module/plugins/hoster/CrockoCom.py b/module/plugins/hoster/CrockoCom.py index bf058b613..27ab52436 100644 --- a/module/plugins/hoster/CrockoCom.py +++ b/module/plugins/hoster/CrockoCom.py @@ -9,13 +9,13 @@ class CrockoCom(SimpleHoster): __name__ = "CrockoCom" __type__ = "hoster" __pattern__ = r"http://(www\.)?(crocko|easy-share).com/.*" - __version__ = "0.12" + __version__ = "0.13" __description__ = """Crocko Download Hoster""" __author_name__ = ("zoidberg") __author_mail__ = ("zoidberg@mujmail.cz") FILE_NAME_PATTERN = r'<span class="fz24">Download:\s*<strong>(?P<N>.*)' - FILE_NAME_PATTERN = r'<span class="tip1"><span class="inner">(?P<S>[^<]+)</span></span>' + FILE_SIZE_PATTERN = r'<span class="tip1"><span class="inner">(?P<S>[^<]+)</span></span>' FILE_OFFLINE_PATTERN = r"<h1>Sorry,<br />the page you're looking for <br />isn't here.</h1>" DOWNLOAD_URL_PATTERN = r"window.location ='([^']+)';" CAPTCHA_URL_PATTERN = re.compile(r"u='(/file_contents/captcha/\w+)';\s*w='(\d+)';") diff --git a/module/plugins/hoster/CzshareCom.py b/module/plugins/hoster/CzshareCom.py index 0ef9c267c..538e3ed86 100644 --- a/module/plugins/hoster/CzshareCom.py +++ b/module/plugins/hoster/CzshareCom.py @@ -45,7 +45,7 @@ class CzshareCom(SimpleHoster): __name__ = "CzshareCom" __type__ = "hoster" __pattern__ = r"http://(\w*\.)*czshare\.(com|cz)/(\d+/|download.php\?).*" - __version__ = "0.86" + __version__ = "0.88" __description__ = """CZshare.com""" __author_name__ = ("zoidberg") @@ -62,7 +62,7 @@ class CzshareCom(SimpleHoster): USER_CREDIT_PATTERN = r'<div class="credit">\s*kredit: <strong>([0-9., ]+)([kKMG]i?B)</strong>\s*</div><!-- .credit -->' def setup(self): - self.resumeDownload = self.multiDL = True if self.premium else False + self.multiDL = self.resumeDownload = True if self.premium else False self.chunkLimit = 1 def process(self, pyfile): @@ -140,16 +140,29 @@ class CzshareCom(SimpleHoster): inputs['captchastring2'] = self.decryptCaptcha(captcha_url) self.logDebug('CAPTCHA_URL:' + captcha_url + ' CAPTCHA:' + inputs['captchastring2']) + self.html = self.load(parsed_url, cookies=True, post=inputs) + + found = re.search("countdown_number = (\d+);", self.html) + self.setWait(int(found.group(1)) if found else 50) + # download the file, destination is determined by pyLoad - self.download(parsed_url, cookies=True, post=inputs) + self.logDebug("WAIT URL", self.req.lastEffectiveURL) + found = re.search("free_wait.php\?server=(.*?)&(.*)", self.req.lastEffectiveURL) + if not found: + raise PluginParseError('Download URL') + url = "http://%s/download.php?%s" % (found.group(1), found.group(2)) + + self.wait() + self.multiDL = True + self.download(url) def checkDownloadedFile(self): # check download check = self.checkDownload({ "tempoffline": re.compile(r"^Soubor je do.asn. nedostupn.$"), "multi_dl": re.compile(self.MULTIDL_PATTERN), - "captcha_err": re.compile(self.FREE_FORM_PATTERN) + "captcha_err": "<li>Zadaný ověřovací kód nesouhlasí!</li>" }) if check == "tempoffline": @@ -160,7 +173,8 @@ class CzshareCom(SimpleHoster): self.invalidCaptcha() self.retry() - def waitForFreeSlot(self): - self.setWait(900, True) + def waitForFreeSlot(self, wait_time = 300): + self.multiDL = False + self.setWait(wait_time, True) self.wait() self.retry()
\ No newline at end of file diff --git a/module/plugins/hoster/DataportCz.py b/module/plugins/hoster/DataportCz.py index 487766201..cef115941 100644 --- a/module/plugins/hoster/DataportCz.py +++ b/module/plugins/hoster/DataportCz.py @@ -17,33 +17,51 @@ """ import re -from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo, PluginParseError +from pycurl import FOLLOWLOCATION class DataportCz(SimpleHoster): __name__ = "DataportCz" __type__ = "hoster" __pattern__ = r"http://.*dataport.cz/file/.*" - __version__ = "0.33" + __version__ = "0.35" __description__ = """Dataport.cz plugin - free only""" __author_name__ = ("zoidberg") - FILE_NAME_PATTERN = r'<h2 style="color: red;">(?P<N>[^<]+)</h2>' - FILE_SIZE_PATTERN = r'<td>Velikost souboru:</td>\s*<td>(?P<S>[0-9.]+)(?P<U>[kKMG])i?B</td>' - URL_PATTERN = r'<td><a href="([^"]+)"[^>]*class="ui-state-default button hover ui-corner-all "><strong>' - NO_SLOTS_PATTERN = r'<td><a href="http://dataport.cz/kredit/"[^>]*class="ui-state-default button hover ui-corner-all ui-state-disabled">' + FILE_NAME_PATTERN = r'<span itemprop="name">(?P<N>[^<]+)</span>' + FILE_SIZE_PATTERN = r'<td class="fil">Velikost</td>\s*<td>(?P<S>[^<]+)</td>' FILE_OFFLINE_PATTERN = r'<h2>Soubor nebyl nalezen</h2>' - def handleFree(self): - if re.search(self.NO_SLOTS_PATTERN, self.html): - self.setWait(900, True) - self.wait() - self.retry(12, 0, "No free slots") - - found = re.search(self.URL_PATTERN, self.html) - if found is None: - self.fail("Parse error (URL)") - download_url = found.group(1) - - self.download(download_url) + CAPTCHA_URL_PATTERN = r'<section id="captcha_bg">\s*<img src="(.*?)"' + FREE_SLOTS_PATTERN = ur'Počet volných slotů: <span class="darkblue">(\d+)</span><br />' + def handleFree(self): + captchas = {"1": "jkeG", "2": "hMJQ", "3": "vmEK", "4": "ePQM", "5": "blBd"} + + for i in range(60): + action, inputs = self.parseHtmlForm('free_download_form') + self.logDebug(action, inputs) + if not action or not inputs: + raise PluginParseError('free_download_form') + + if "captchaId" in inputs and inputs["captchaId"] in captchas: + inputs['captchaCode'] = captchas[inputs["captchaId"]] + else: + raise PluginParseError('captcha') + + self.html = self.download("http://dataport.cz%s" % action, post = inputs) + + check = self.checkDownload({"captcha": 'alert("\u0160patn\u011b opsan\u00fd k\u00f3d z obr\u00e1zu");', + "slot": 'alert("Je n\u00e1m l\u00edto, ale moment\u00e1ln\u011b nejsou'}) + if check == "captcha": + raise PluginParseError('invalid captcha') + elif check == "slot": + self.logDebug("No free slots - wait 60s and retry") + self.setWait(60, False) + self.wait() + self.html = self.load(self.pyfile.url, decode = True) + continue + else: + break + create_getInfo(DataportCz)
\ No newline at end of file diff --git a/module/plugins/hoster/DateiTo.py b/module/plugins/hoster/DateiTo.py new file mode 100644 index 000000000..529a5a06f --- /dev/null +++ b/module/plugins/hoster/DateiTo.py @@ -0,0 +1,92 @@ +# -*- coding: utf-8 -*- +""" + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <http://www.gnu.org/licenses/>. + + @author: zoidberg +""" + +import re +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo +from module.plugins.ReCaptcha import ReCaptcha + +class DateiTo(SimpleHoster): + __name__ = "DateiTo" + __type__ = "hoster" + __pattern__ = r"http://(?:www\.)?datei\.to/datei/(?P<ID>\w+)\.html" + __version__ = "0.01" + __description__ = """Datei.to plugin - free only""" + __author_name__ = ("zoidberg") + __author_mail__ = ("zoidberg@mujmail.cz") + + FILE_NAME_PATTERN = r'Dateiname:</td>\s*<td colspan="2"><strong>(?P<N>.*?)</' + FILE_SIZE_PATTERN = r'Dateigröße:</td>\s*<td colspan="2">(?P<S>.*?)</' + FILE_OFFLINE_PATTERN = r'>Datei wurde nicht gefunden<|>Bitte wähle deine Datei aus... <' + PARALELL_PATTERN = r'>Du lädst bereits eine Datei herunter<' + + WAIT_PATTERN = r'countdown\({seconds: (\d+)' + DATA_PATTERN = r'url: "(.*?)", data: "(.*?)",' + RECAPTCHA_KEY_PATTERN = r'Recaptcha.create\("(.*?)"' + + def handleFree(self): + url = 'http://datei.to/ajax/download.php' + data = {'P': 'I', 'ID': self.file_info['ID']} + + recaptcha = ReCaptcha(self) + + for i in range(10): + self.logDebug("URL", url, "POST", data) + self.html = self.load(url, post = data) + self.checkErrors() + + if url.endswith('download.php') and 'P' in data: + if data['P'] == 'I': + self.doWait() + + elif data['P'] == 'IV': + break + + found = re.search(self.DATA_PATTERN, self.html) + if not found: self.parseError('data') + url = 'http://datei.to/' + found.group(1) + data = dict(x.split('=') for x in found.group(2).split('&')) + + if url.endswith('recaptcha.php'): + found = re.search(self.RECAPTCHA_KEY_PATTERN, self.html) + recaptcha_key = found.group(1) if found else "6LdBbL8SAAAAAI0vKUo58XRwDd5Tu_Ze1DA7qTao" + + data['recaptcha_challenge_field'], data['recaptcha_response_field'] = recaptcha.challenge(recaptcha_key) + + else: + self.fail('Too bad...') + + download_url = self.html + self.logDebug('Download URL', download_url) + self.download(download_url) + + def checkErrors(self): + found = re.search(self.PARALELL_PATTERN, self.html) + if found: + self.setWait(wait_time + 1, False) + self.wait(300) + self.retry() + + def doWait(self): + found = re.search(self.WAIT_PATTERN, self.html) + wait_time = int(found.group(1)) if found else 30 + self.setWait(wait_time + 1, False) + + self.load('http://datei.to/ajax/download.php', post = {'P': 'Ads'}) + self.wait() + +getInfo = create_getInfo(DateiTo) diff --git a/module/plugins/hoster/DdlstorageCom.py b/module/plugins/hoster/DdlstorageCom.py new file mode 100644 index 000000000..1ad5fa6d8 --- /dev/null +++ b/module/plugins/hoster/DdlstorageCom.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +from module.plugins.hoster.XFileSharingPro import XFileSharingPro, create_getInfo + +class DdlstorageCom(XFileSharingPro): + __name__ = "DdlstorageCom" + __type__ = "hoster" + __pattern__ = r"http://(?:\w*\.)*?ddlstorage.com/\w{12}" + __version__ = "0.06" + __description__ = """DDLStorage.com hoster plugin""" + __author_name__ = ("zoidberg") + __author_mail__ = ("zoidberg@mujmail.cz") + + FILE_INFO_PATTERN = r'<h2>\s*Download File\s*<span[^>]*>(?P<N>[^>]+)</span></h2>\s*[^\(]*\((?P<S>[^\)]+)\)</h2>' + HOSTER_NAME = "ddlstorage.com" + + def setup(self): + self.resumeDownload = self.multiDL = self.premium + self.chunkLimit = 1 + +getInfo = create_getInfo(DdlstorageCom)
\ No newline at end of file diff --git a/module/plugins/hoster/DepositfilesCom.py b/module/plugins/hoster/DepositfilesCom.py index 87e5e7254..9c13a5f3a 100644 --- a/module/plugins/hoster/DepositfilesCom.py +++ b/module/plugins/hoster/DepositfilesCom.py @@ -3,52 +3,35 @@ import re from urllib import unquote -from module.plugins.internal.SimpleHoster import SimpleHoster, parseFileInfo +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo from module.network.RequestFactory import getURL from module.plugins.ReCaptcha import ReCaptcha -def getInfo(urls): - result = [] - - for url in urls: - file_info = parseFileInfo(DepositfilesCom, url, getURL(re.sub(r"\.com(/.*?)?/files", ".com/en/files", url), decode=True)) - result.append(file_info) - - yield result - class DepositfilesCom(SimpleHoster): __name__ = "DepositfilesCom" __type__ = "hoster" __pattern__ = r"http://[\w\.]*?depositfiles\.com(/\w{1,3})?/files/[\w]+" - __version__ = "0.36" + __version__ = "0.42" __description__ = """Depositfiles.com Download Hoster""" __author_name__ = ("spoob", "zoidberg") __author_mail__ = ("spoob@pyload.org", "zoidberg@mujmail.cz") - FILE_INFO_PATTERN = r'File name: <b title="(?P<N>[^"]+)">.*\s*<span class="nowrap">File size: <b>(?P<S>[0-9.]+) (?P<U>[kKMG])i?B</b>' + FILE_NAME_PATTERN = r'File name: <b title="(?P<N>[^"]+)' + FILE_SIZE_PATTERN = r'File size: <b>(?P<S>[0-9.]+) (?P<U>[kKMG])i?B</b>' + FILE_INFO_PATTERN = r'<script type="text/javascript">eval\( unescape\(\'(?P<N>.*?)\'' FILE_OFFLINE_PATTERN = r'<span class="html_download_api-not_exists"></span>' - RECAPTCHA_PATTERN = r"Recaptcha.create\('([^']+)', this\);" + FILE_URL_REPLACEMENTS = [(r"\.com(/.*?)?/files", ".com/en/files"), (r"\.html$", "")] + FILE_NAME_REPLACEMENTS = [(r'\%u([0-9A-Fa-f]{4})', lambda m: unichr(int(m.group(1), 16))), (r'.*<b title="(?P<N>[^"]+).*', "\g<N>" )] + + RECAPTCHA_PATTERN = r"Recaptcha.create\('([^']+)'" DOWNLOAD_LINK_PATTERN = r'<form action="(http://.+?\.depositfiles.com/.+?)" method="get"' def setup(self): - self.resumeDownload = self.multiDL = True if self.account else False - - self.pyfile.url = re.sub(r"\.com(/.*?)?/files", ".com/en/files", self.pyfile.url) - - def process(self, pyfile): - if re.search(r"(.*)\.html", self.pyfile.url): - self.pyfile.url = re.search(r"(.*)\.html", self.pyfile.url).group(1) - - self.html = self.load(self.pyfile.url, cookies=True if self.account else False, decode = True) - self.getFileInfo() - - if self.account: - self.handlePremium() - else: - self.handleFree() + self.multiDL = False + self.resumeDownload = self.premium def handleFree(self): - self.html = self.load(self.pyfile.url, post={"gateway_result":"1"}) + self.html = self.load(self.pyfile.url, post={"gateway_result":"1"}, cookies = True) if re.search(self.FILE_OFFLINE_PATTERN, self.html): self.offline() if re.search(r'File is checked, please try again in a minute.', self.html) is not None: @@ -81,7 +64,7 @@ class DepositfilesCom(SimpleHoster): params = {'fid' : found.group(1)} self.logDebug ("FID: %s" % params['fid']) - captcha_key = None + captcha_key = '6LdRTL8SAAAAAE9UOdWZ4d0Ky-aeA7XfSqyWDM2m' found = re.search(self.RECAPTCHA_PATTERN, self.html) if found: captcha_key = found.group(1) self.logDebug ("CAPTCHA_KEY: %s" % captcha_key) @@ -91,9 +74,9 @@ class DepositfilesCom(SimpleHoster): for i in range(5): self.html = self.load("http://depositfiles.com/get_file.php", get = params) - + if '<input type=button value="Continue" onclick="check_recaptcha' in self.html: - if not captcha_key: raise PluginParseError('Captcha key') + if not captcha_key: self.parseError('Captcha key') if 'response' in params: self.invalidCaptcha() params['challenge'], params['response'] = recaptcha.challenge(captcha_key) self.logDebug(params) @@ -106,15 +89,24 @@ class DepositfilesCom(SimpleHoster): self.logDebug ("LINK: %s" % link) break else: - raise PluginParseError('Download link') + self.parseError('Download link') else: self.fail('No valid captcha response received') try: - self.download(link) + self.download(link, disposition = True) except: self.retry(wait_time = 60) def handlePremium(self): + if '<span class="html_download_api-gold_traffic_limit">' in self.html: + self.logWarning("Download limit reached") + self.retry(25, 3600, "Download limit reached") + elif 'onClick="show_gold_offer' in self.html: + self.account.relogin(self.user) + self.retry() link = unquote(re.search('<div id="download_url">\s*<a href="(http://.+?\.depositfiles.com/.+?)"', self.html).group(1)) - self.download(link)
\ No newline at end of file + self.multiDL = True + self.download(link, disposition = True) + +getInfo = create_getInfo(DepositfilesCom)
\ No newline at end of file diff --git a/module/plugins/hoster/DlFreeFr.py b/module/plugins/hoster/DlFreeFr.py index 7cb58e6f4..5b318fd54 100644 --- a/module/plugins/hoster/DlFreeFr.py +++ b/module/plugins/hoster/DlFreeFr.py @@ -2,36 +2,182 @@ # -*- coding: utf-8 -*- import re -from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo, replace_patterns +from module.common.json_layer import json_loads + +import pycurl +from module.network.Browser import Browser +from module.network.CookieJar import CookieJar + +class CustomBrowser(Browser): + def __init__(self, bucket=None, options={}): + Browser.__init__(self, bucket, options) + + def load(self, *args, **kwargs): + post = kwargs.get("post") + if post is None: + if len(args) > 2: + post = args[2] + if post: + self.http.c.setopt(pycurl.FOLLOWLOCATION, 0) + self.http.c.setopt(pycurl.POST, 1) + self.http.c.setopt(pycurl.CUSTOMREQUEST, "POST") + else: + self.http.c.setopt(pycurl.FOLLOWLOCATION, 1) + self.http.c.setopt(pycurl.POST, 0) + self.http.c.setopt(pycurl.CUSTOMREQUEST, "GET") + return Browser.load(self, *args, **kwargs) + +""" +Class to support adyoulike captcha service +""" +class AdYouLike(): + ADYOULIKE_INPUT_PATTERN = r'Adyoulike.create\((.*?)\);' + ADYOULIKE_CALLBACK = r'Adyoulike.g._jsonp_5579316662423138' + ADYOULIKE_CHALLENGE_PATTERN = ADYOULIKE_CALLBACK + r'\((.*?)\)' + + def __init__(self, plugin, engine = "adyoulike"): + self.plugin = plugin + self.engine = engine + + def challenge(self, html): + adyoulike_data_string = None + found = re.search(self.ADYOULIKE_INPUT_PATTERN, html) + if found: + adyoulike_data_string = found.group(1) + else: + self.plugin.fail("Can't read AdYouLike input data") + + ayl_data = json_loads(adyoulike_data_string) #{"adyoulike":{"key":"P~zQ~O0zV0WTiAzC-iw0navWQpCLoYEP"},"all":{"element_id":"ayl_private_cap_92300","lang":"fr","env":"prod"}} + + res = self.plugin.load(r'http://api-ayl.appspot.com/challenge?key=%(ayl_key)s&env=%(ayl_env)s&callback=%(callback)s' % {"ayl_key": ayl_data[self.engine]["key"], "ayl_env": ayl_data["all"]["env"], "callback": self.ADYOULIKE_CALLBACK}) + + found = re.search(self.ADYOULIKE_CHALLENGE_PATTERN, res) + challenge_string = None + if found: + challenge_string = found.group(1) + else: + self.plugin.fail("Invalid AdYouLike challenge") + challenge_data = json_loads(challenge_string) + + return ayl_data, challenge_data + + def result(self, ayl, challenge): + """ + Adyoulike.g._jsonp_5579316662423138({"translations":{"fr":{"instructions_visual":"Recopiez « Soonnight » ci-dessous :"}},"site_under":true,"clickable":true,"pixels":{"VIDEO_050":[],"DISPLAY":[],"VIDEO_000":[],"VIDEO_100":[],"VIDEO_025":[],"VIDEO_075":[]},"medium_type":"image/adyoulike","iframes":{"big":"<iframe src=\"http://www.soonnight.com/campagn.html\" scrolling=\"no\" height=\"250\" width=\"300\" frameborder=\"0\"></iframe>"},"shares":{},"id":256,"token":"e6QuI4aRSnbIZJg02IsV6cp4JQ9~MjA1","formats":{"small":{"y":300,"x":0,"w":300,"h":60},"big":{"y":0,"x":0,"w":300,"h":250},"hover":{"y":440,"x":0,"w":300,"h":60}},"tid":"SqwuAdxT1EZoi4B5q0T63LN2AkiCJBg5"}) + """ + response = None + try: + instructions_visual = challenge["translations"][ayl["all"]["lang"]]["instructions_visual"] + found = re.search(u".*«(.*)».*", instructions_visual) + if found: + response = found.group(1).strip() + else: + self.plugin.fail("Can't parse instructions visual") + except KeyError: + self.plugin.fail("No instructions visual") + + #TODO: Supports captcha + + if not response: + self.plugin.fail("AdYouLike result failed") + + return {"_ayl_captcha_engine" : self.engine, + "_ayl_env" : ayl["all"]["env"], + "_ayl_tid" : challenge["tid"], + "_ayl_token_challenge" : challenge["token"], + "_ayl_response": response } class DlFreeFr(SimpleHoster): __name__ = "DlFreeFr" __type__ = "hoster" - __pattern__ = r"http://dl\.free\.fr/([a-zA-Z0-9]+|getfile\.pl\?file=/[a-zA-Z0-9]+)$" - __version__ = "0.2" + __pattern__ = r"http://dl\.free\.fr/([a-zA-Z0-9]+|getfile\.pl\?file=/[a-zA-Z0-9]+)" + __version__ = "0.23" __description__ = """dl.free.fr download hoster""" - __author_name__ = ("the-razer", "zoidberg") - __author_mail__ = ("daniel_ AT gmx DOT net", "zoidberg@mujmail.cz") + __author_name__ = ("the-razer", "zoidberg", "Toilal") + __author_mail__ = ("daniel_ AT gmx DOT net", "zoidberg@mujmail.cz", "toilal.dev@gmail.com") FILE_NAME_PATTERN = r"Fichier:</td>\s*<td[^>]*>(?P<N>[^>]*)</td>" - FILE_SIZE_PATTERN = r"Taille:</td>\s*<td[^>]*>(?P<S>[\d.]+[KMG])</td>" + FILE_SIZE_PATTERN = r"Taille:</td>\s*<td[^>]*>(?P<S>[\d.]+[KMG])o" FILE_OFFLINE_PATTERN = r"Erreur 404 - Document non trouv|Fichier inexistant|Le fichier demandé n'a pas été trouvé" - FILE_URL_PATTERN = r'href="(?P<url>http://.*?)">Télécharger ce fichier' - + #FILE_URL_PATTERN = r'href="(?P<url>http://.*?)">Télécharger ce fichier' + def setup(self): self.limitDL = 5 self.resumeDownload = True - self.chunkLimit = 1 + self.chunkLimit = 1 - def handleFree(self): - if "Trop de slots utilisés" in self.html: - self.retry(300) + def init(self): + factory = self.core.requestFactory + self.req = CustomBrowser(factory.bucket, factory.getOptions()) + + def process(self, pyfile): + self.req.setCookieJar(None) + + pyfile.url = replace_patterns(pyfile.url, self.FILE_URL_REPLACEMENTS) + valid_url = pyfile.url + headers = self.load(valid_url, just_header = True) - m = re.search(self.FILE_URL_PATTERN, self.html) - if not m: self.parseError('URL') + self.html = None + if headers.get('code') == 302: + valid_url = headers.get('location') + headers = self.load(valid_url, just_header = True) - url = m.group('url') - self.logDebug("File URL [%s]" % url) - self.download(url) + if headers.get('code') == 200: + content_type = headers.get('content-type') + if content_type and content_type.startswith("text/html"): + # Undirect acces to requested file, with a web page providing it (captcha) + self.html = self.load(valid_url) + self.handleFree() + else: + # Direct access to requested file for users using free.fr as Internet Service Provider. + self.download(valid_url, disposition=True) + elif headers.get('code') == 404: + self.offline() + else: + self.fail("Invalid return code: " + str(headers.get('code'))) + + def handleFree(self): + action, inputs = self.parseHtmlForm('action="getfile.pl"') + + adyoulike = AdYouLike(self) + ayl, challenge = adyoulike.challenge(self.html) + result = adyoulike.result(ayl, challenge) + inputs.update(result) + + data = self.load("http://dl.free.fr/getfile.pl", post = inputs) + headers = self.getLastHeaders() + if headers.get("code") == 302 and headers.has_key("set-cookie") and headers.has_key("location"): + found = re.search("(.*?)=(.*?); path=(.*?); domain=(.*?)", headers.get("set-cookie")) + cj = CookieJar(__name__) + if found: + cj.setCookie(found.group(4), found.group(1), found.group(2), found.group(3)) + else: + self.fail("Cookie error") + location = headers.get("location") + self.req.setCookieJar(cj) + self.download(location, disposition=True); + else: + self.fail("Invalid response") + + def getLastHeaders(self): + #parse header + header = {"code": self.req.code} + for line in self.req.http.header.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 + return header -getInfo = create_getInfo(DlFreeFr)
\ No newline at end of file +getInfo = create_getInfo(DlFreeFr) diff --git a/module/plugins/hoster/EasybytezCom.py b/module/plugins/hoster/EasybytezCom.py index 0b46acb83..5f3159b20 100644 --- a/module/plugins/hoster/EasybytezCom.py +++ b/module/plugins/hoster/EasybytezCom.py @@ -17,128 +17,67 @@ """ import re -from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo from random import random +from pycurl import LOW_SPEED_TIME +from module.plugins.hoster.XFileSharingPro import XFileSharingPro, create_getInfo -class EasybytezCom(SimpleHoster): +class EasybytezCom(XFileSharingPro): __name__ = "EasybytezCom" __type__ = "hoster" - __pattern__ = r"http://(?:\w*\.)?easybytez.com/(\w{6,}).*" - __version__ = "0.06" + __pattern__ = r"http://(?:\w*\.)?easybytez.com/(\w+).*" + __version__ = "0.11" __description__ = """easybytez.com""" __author_name__ = ("zoidberg") __author_mail__ = ("zoidberg@mujmail.cz") - - # shares code with TurbouploadCom FILE_NAME_PATTERN = r'<input type="hidden" name="fname" value="(?P<N>[^"]+)"' FILE_SIZE_PATTERN = r'You have requested <font color="red">[^<]+</font> \((?P<S>[^<]+)\)</font>' - FILE_INFO_PATTERN = r'<tr><td align=right><b>Filename:</b></td><td nowrap>(?P<N>[^<]+)</td></tr>\s*.*?<small>\((?P<S>[^<]+)\)</small>' - FILE_OFFLINE_PATTERN = r'<h2>File Not Found</h2>' + FILE_INFO_PATTERN = r'<tr><td align=right><b>Filename:</b></td><td nowrap>(?P<N>[^<]+)</td></tr>\s*.*?<small>\((?P<S>[^<]+)\)</small>' + FILE_OFFLINE_PATTERN = r'<h1>File not available</h1>' - FORM_INPUT_PATTERN = r'<input[^>]* name="([^"]+)"[^>]*value="([^"]*)"' - WAIT_PATTERN = r'<span id="countdown_str">[^>]*>(\d+)</span> seconds</span>' DIRECT_LINK_PATTERN = r'(http://(\w+\.easybytez\.com|\d+\.\d+\.\d+\.\d+)/files/\d+/\w+/[^"<]+)' - - FORM_PATTERN = r'<form name=["\']?%s[^>]*action=["\']?([^"\' ]+)(.*?)</form>' OVR_DOWNLOAD_LINK_PATTERN = r'<h2>Download Link</h2>\s*<textarea[^>]*>([^<]+)' OVR_KILL_LINK_PATTERN = r'<h2>Delete Link</h2>\s*<textarea[^>]*>([^<]+)' - TEXTAREA_PATTERN = r"<textarea name='([^']+)'>([^<]+)</textarea>" - - HOSTER_URL = "www.easybytez.com" - - def process(self, pyfile): - if not re.match(self.__pattern__, self.pyfile.url): - if self.premium: - self.handleOverriden() - else: - self.fail("Only premium users can download from other hosters with %s" % self.HOSTER_URL) - else: - self.html = self.load(pyfile.url, cookies = False, decode = True) - self.file_info = self.getFileInfo() - - header = self.load(self.pyfile.url, just_header = True, cookies = True) - self.logDebug(header) - - if 'location' in header and re.match(self.DIRECT_LINK_PATTERN, header['location']): - self.downloadLink(header['location']) - elif self.premium: - self.handlePremium() - else: - self.handleFree() - def handleFree(self): - self.download(self.pyfile.url, post = self.getPostParameters(), ref = True, cookies = True) + HOSTER_NAME = "easybytez.com" + def setup(self): + self.resumeDownload = self.multiDL = self.premium + def handlePremium(self): - self.html = self.load(self.pyfile.url, post = self.getPostParameters(premium=True)) + self.html = self.load(self.pyfile.url, post = self.getPostParameters()) found = re.search(self.DIRECT_LINK_PATTERN, self.html) if not found: self.parseError('DIRECT LINK') - self.downloadLink(found.group(1)) - + self.startDownload(found.group(1)) + def handleOverriden(self): - self.html = self.load(self.HOSTER_URL) - action, form = re.search(self.FORM_PATTERN % "url", self.html, re.DOTALL).groups() - inputs = dict(re.findall(self.FORM_INPUT_PATTERN, form)) + self.html = self.load("http://www.%s/" % self.HOSTER_NAME) + action, inputs = self.parseHtmlForm('') upload_id = "%012d" % int(random()*10**12) - action += upload_id + "&js_on=1&utype=prem&upload_type=url" + action += upload_id + "&js_on=1&utype=prem&upload_type=url" inputs['tos'] = '1' inputs['url_mass'] = self.pyfile.url - inputs['up1oad_type'] = 'url' - + inputs['up1oad_type'] = 'url' + self.logDebug(action, inputs) + #wait for file to upload to easybytez.com + self.req.http.c.setopt(LOW_SPEED_TIME, 600) self.html = self.load(action, post = inputs) - - found = re.search(self.FORM_PATTERN % "F1", self.html, re.S | re.I) - if not found: - self.logDebug(self.html) - self.fail("upload failed") - action, form = found.groups() - - inputs = dict(re.findall(self.TEXTAREA_PATTERN, form)) - if not inputs: parseError('TEXTAREA') - self.logDebug(inputs) + + action, inputs = self.parseHtmlForm('F1') + if not inputs: self.parseError('TEXTAREA') + self.logDebug(inputs) if inputs['st'] == 'OK': self.html = self.load(action, post = inputs) + elif inputs['st'] == 'Can not leech file': + self.retry(max_tries=20, wait_time=180, reason=inputs['st']) else: - self.fail(inputs['st']) + self.fail(inputs['st']) + #get easybytez.com link for uploaded file found = re.search(self.OVR_DOWNLOAD_LINK_PATTERN, self.html) if not found: self.parseError('DIRECT LINK (OVR)') self.pyfile.url = found.group(1) self.retry() - - def downloadLink(self, link): - self.logDebug('DIRECT LINK: %s' % link) - self.download(link) - - def getPostParameters(self, premium=False): - inputs = dict(re.findall(self.FORM_INPUT_PATTERN, self.html)) - self.logDebug(inputs) - - if 'op' in inputs and inputs['op'] == 'download2': return inputs - - inputs['referer'] = self.pyfile.url - - if premium: - inputs['method_premium'] = "Premium Download" - if 'method_free' in inputs: del inputs['method_free'] - else: - inputs['method_free'] = "Free Download" - if 'method_premium' in inputs: del inputs['method_premium'] - - self.html = self.load(self.pyfile.url, post = inputs, ref = True, cookies = True) - inputs = dict(re.findall(self.FORM_INPUT_PATTERN, self.html)) - self.logDebug(inputs) - - if not premium: - found = re.search(self.WAIT_PATTERN, self.html) - self.setWait(int(found.group(1)) + 1 if found else 60) - self.wait() - - return inputs - - def urlParseFileName(self): - return html_unescape(urlparse(self.pyfile.url).path.split("/")[-1]) getInfo = create_getInfo(EasybytezCom)
\ No newline at end of file diff --git a/module/plugins/hoster/ExtabitCom.py b/module/plugins/hoster/ExtabitCom.py new file mode 100644 index 000000000..718423986 --- /dev/null +++ b/module/plugins/hoster/ExtabitCom.py @@ -0,0 +1,84 @@ +# -*- coding: utf-8 -*- +""" + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <http://www.gnu.org/licenses/>. + + @author: zoidberg +""" + +import re +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo +from module.plugins.ReCaptcha import ReCaptcha +from module.common.json_layer import json_loads + +class ExtabitCom(SimpleHoster): + __name__ = "ExtabitCom" + __type__ = "hoster" + __pattern__ = r"http://(\w+\.)*extabit\.com/(file|go)/(?P<ID>\w+)" + __version__ = "0.2" + __description__ = """Extabit.com""" + __author_name__ = ("zoidberg") + + FILE_NAME_PATTERN = r'<th>File:</th>\s*<td class="col-fileinfo">\s*<div title="(?P<N>[^"]+)">' + FILE_SIZE_PATTERN = r'<th>Size:</th>\s*<td class="col-fileinfo">(?P<S>[^<]+)</td>' + FILE_OFFLINE_PATTERN = r'<h1>File not found</h1>' + TEMP_OFFLINE_PATTERN = r">(File is temporary unavailable|No download mirror)<" + + DOWNLOAD_LINK_PATTERN = r'"(http://guest\d+\.extabit\.com/[a-z0-9]+/.*?)"' + + def handleFree(self): + if r">Only premium users can download this file" in self.html: + self.fail("Only premium users can download this file") + + m = re.search(r"Next free download from your ip will be available in <b>(\d+)\s*minutes", self.html) + if m: + self.setWait(int(m.group(1)) * 60, True) + self.wait() + elif "The daily downloads limit from your IP is exceeded" in self.html: + self.setWait(3600, True) + self.wait() + + self.logDebug("URL: " + self.req.http.lastEffectiveURL) + m = re.match(self.__pattern__, self.req.http.lastEffectiveURL) + fileID = m.group('ID') if m else self.file_info('ID') + + m = re.search(r'recaptcha/api/challenge\?k=(\w+)', self.html) + if m: + recaptcha = ReCaptcha(self) + captcha_key = m.group(1) + + for i in range(5): + get_data = {"type": "recaptcha"} + get_data["challenge"], get_data["capture"] = recaptcha.challenge(captcha_key) + response = json_loads(self.load("http://extabit.com/file/%s/" % fileID, get = get_data)) + if "ok" in response: + self.correctCaptcha() + break + else: + self.invalidCaptcha() + else: + self.fail("Invalid captcha") + else: + self.parseError('Captcha') + + if not "href" in response: self.parseError('JSON') + + self.html = self.load("http://extabit.com/file/%s%s" % (fileID, response['href'])) + m = re.search(self.DOWNLOAD_LINK_PATTERN, self.html) + if not m: + self.parseError('Download URL') + url = m.group(1) + self.logDebug("Download URL: " + url) + self.download(url) + +getInfo = create_getInfo(ExtabitCom)
\ No newline at end of file diff --git a/module/plugins/hoster/FastshareCz.py b/module/plugins/hoster/FastshareCz.py new file mode 100644 index 000000000..654a1abe8 --- /dev/null +++ b/module/plugins/hoster/FastshareCz.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +""" + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <http://www.gnu.org/licenses/>. + + @author: zoidberg +""" + +import re +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo + +class FastshareCz(SimpleHoster): + __name__ = "FastshareCz" + __type__ = "hoster" + __pattern__ = r"http://(?:\w*\.)?fastshare.cz/\d+/.+" + __version__ = "0.12" + __description__ = """FastShare.cz""" + __author_name__ = ("zoidberg") + + FILE_NAME_PATTERN = r'<h3><b><span style=color:black;>(?P<N>[^<]+)</b></h3>' + FILE_SIZE_PATTERN = r'<tr><td>Velikost: </td><td style=font-weight:bold>(?P<S>[^<]+)</td></tr>' + FILE_OFFLINE_PATTERN = r'<div id="content">\s*<div style=background-color:white' + SH_HTML_ENCODING = 'cp1250' + + FREE_URL_PATTERN = ur'<form method=post action=(/free/.*?)><b>Stáhnout FREE.*?<img src="([^"]*)">' + + def handleFree(self): + found = re.search(self.FREE_URL_PATTERN, self.html) + if not found: self.parseError("Free URL") + action, captcha_src = found.groups() + captcha = self.decryptCaptcha("http://www.fastshare.cz/" + captcha_src) + self.download("http://www.fastshare.cz/" + action, post = {"code": captcha, "submit": u"stáhnout"}) + + check = self.checkDownload({"paralell_dl": "<script>alert('Pres FREE muzete stahovat jen jeden soubor najednou.')"}) + self.logDebug(self.req.lastEffectiveURL, self.req.lastURL, self.req.code) + + if check == "paralell_dl": + self.setWait(600, True) + self.wait() + self.retry() + +getInfo = create_getInfo(FastshareCz)
\ No newline at end of file diff --git a/module/plugins/hoster/FilecloudIo.py b/module/plugins/hoster/FilecloudIo.py new file mode 100644 index 000000000..4a096e400 --- /dev/null +++ b/module/plugins/hoster/FilecloudIo.py @@ -0,0 +1,112 @@ +# -*- coding: utf-8 -*- +""" + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <http://www.gnu.org/licenses/>. + + @author: zoidberg +""" + +import re +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo, PluginParseError +from module.common.json_layer import json_loads +from module.plugins.ReCaptcha import ReCaptcha +from module.network.RequestFactory import getURL + +class FilecloudIo(SimpleHoster): + __name__ = "FilecloudIo" + __type__ = "hoster" + __pattern__ = r"http://(?:\w*\.)*(?:filecloud\.io|ifile\.it|mihd\.net)/(?P<ID>\w+).*" + __version__ = "0.01" + __description__ = """Filecloud.io (formerly Ifile.it) plugin - free account only""" + __author_name__ = ("zoidberg") + + FILE_SIZE_PATTERN = r'{var __ab1 = (?P<S>\d+);}' + FILE_NAME_PATTERN = r'id="aliasSpan">(?P<N>.*?) <' + FILE_OFFLINE_PATTERN = r'l10n.(FILES__DOESNT_EXIST|REMOVED)' + TEMP_OFFLINE_PATTERN = r'l10n.FILES__WARNING' + + UKEY_PATTERN = r"'ukey'\s*:'(\w+)'," + AB1_PATTERN = r"if\( __ab1 == '(\w+)' \)" + ERROR_MSG_PATTERN = r"var __error_msg\s*=\s*l10n\.(.*?);" + DOWNLOAD_LINK_PATTERN = r'"(http://s\d+.filecloud.io/%s/\d+/.*?)"' + RECAPTCHA_KEY_PATTERN = r"var __recaptcha_public\s*=\s*'([^']+)';" + RECAPTCHA_KEY = '6Lf5OdISAAAAAEZObLcx5Wlv4daMaASRov1ysDB1' + + def setup(self): + self.resumeDownload = self.multiDL = True + self.chunkLimit = 1 + + def handleFree(self): + data = {"ukey": self.file_info['ID']} + + found = re.search(self.AB1_PATTERN, self.html) + if not found: + raise PluginParseError("__AB1") + data["__ab1"] = found.group(1) + + if not self.account: + self.fail("User not logged in") + elif not self.account.logged_in: + recaptcha = ReCaptcha(self) + captcha_challenge, captcha_response = recaptcha.challenge(self.RECAPTCHA_KEY) + self.account.form_data = {"recaptcha_challenge_field" : captcha_challenge, + "recaptcha_response_field" : captcha_response} + self.account.relogin(self.user) + self.retry(max_tries = 2) + + json_url = "http://filecloud.io/download-request.json" + response = self.load(json_url, post = data) + self.logDebug(response) + response = json_loads(response) + + if "error" in response and response["error"]: + self.fail(response) + + self.logDebug(response) + if response["captcha"]: + recaptcha = ReCaptcha(self) + found = re.search(self.RECAPTCHA_KEY_PATTERN, self.html) + captcha_key = found.group(1) if found else self.RECAPTCHA_KEY + data["ctype"] = "recaptcha" + + for i in range(5): + data["recaptcha_challenge"], data["recaptcha_response"] = recaptcha.challenge(captcha_key) + + json_url = "http://filecloud.io/download-request.json" + response = self.load(json_url, post = data) + self.logDebug(response) + response = json_loads(response) + + if "retry" in response and response["retry"]: + self.invalidCaptcha() + else: + self.correctCaptcha() + break + else: + self.fail("Incorrect captcha") + + if response["dl"]: + self.html = self.load('http://filecloud.io/download.html') + found = re.search(self.DOWNLOAD_LINK_PATTERN % self.file_info['ID'], self.html) + if not found: + raise PluginParseError("Download URL") + download_url = found.group(1) + self.logDebug("Download URL: %s" % download_url) + + if "size" in self.file_info and self.file_info['size']: + self.check_data = {"size": int(self.file_info['size'])} + self.download(download_url) + else: + self.fail("Unexpected server response") + +getInfo = create_getInfo(FilecloudIo)
\ No newline at end of file diff --git a/module/plugins/hoster/FiledinoCom.py b/module/plugins/hoster/FiledinoCom.py new file mode 100644 index 000000000..6bdd01b51 --- /dev/null +++ b/module/plugins/hoster/FiledinoCom.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +from module.plugins.hoster.XFileSharingPro import XFileSharingPro, create_getInfo +import re + +class FiledinoCom(XFileSharingPro): + __name__ = "FiledinoCom" + __type__ = "hoster" + __pattern__ = r"http://(?:\w*\.)*(file(dino|fat).com)/\w{12}" + __version__ = "0.02" + __description__ = """FileDino / FileFat hoster plugin""" + __author_name__ = ("zoidberg") + __author_mail__ = ("zoidberg@mujmail.cz") + + FILE_SIZE_PATTERN = r'File Size : </(span|font)><(span|font)[^>]*>(?P<S>.+?)</(span|font)>' + DIRECT_LINK_PATTERN = r'http://www\.file(dino|fat)\.com/cgi-bin/dl\.cgi/' + + def setup(self): + self.HOSTER_NAME = re.search(self.__pattern__, self.pyfile.url).group(1) + self.multiDL = False + +getInfo = create_getInfo(FiledinoCom)
\ No newline at end of file diff --git a/module/plugins/hoster/FilefactoryCom.py b/module/plugins/hoster/FilefactoryCom.py index 37b2bb7ce..135dd90a1 100644 --- a/module/plugins/hoster/FilefactoryCom.py +++ b/module/plugins/hoster/FilefactoryCom.py @@ -1,122 +1,133 @@ # -*- coding: utf-8 -*- -from __future__ import with_statement - from module.network.RequestFactory import getURL from module.plugins.Hoster import Hoster from module.plugins.ReCaptcha import ReCaptcha +from module.utils import parseFileSize +from module.plugins.Plugin import chunks +from module.common.json_layer import json_loads import re -def getInfo(urls): - result = [] +def checkFile(plugin, urls): + file_info = [] + url_dict = {} for url in urls: - - # Get file info html - # @TODO: Force responses in english language so current patterns will be right - html = getURL(url) - if re.search(FilefactoryCom.FILE_OFFLINE_PATTERN, html): - result.append((url, 0, 1, url)) + url_dict[re.search(plugin.__pattern__, url).group('id')] = (url, 0, 0, url) + url_ids = url_dict.keys() + urls = map(lambda url_id: 'http://www.filefactory.com/file/' + url_id, url_ids) - # Name - name = re.search(FilefactoryCom.FILE_NAME_PATTERN, html).group('name') - m = re.search(FilefactoryCom.FILE_INFO_PATTERN, html) + html = getURL("http://www.filefactory.com/tool/links.php", post = {"func": "links", "links": "\n".join(urls)}, decode=True) - # Size - value = float(m.group('size')) - units = m.group('units') - pow = {'KB' : 1, 'MB' : 2, 'GB' : 3}[units] - size = int(value*1024**pow) + for m in re.finditer(plugin.LC_INFO_PATTERN, html): + if m.group('id') in url_ids: + url_dict[m.group('id')] = (m.group('name'), parseFileSize(m.group('size')), 2, url_dict[m.group('id')][3]) + + for m in re.finditer(plugin.LC_OFFLINE_PATTERN, html): + if m.group('id') in url_ids: + url_dict[m.group('id')] = (url_dict[m.group('id')][0], 0, 1, url_dict[m.group('id')][3]) - # Return info - result.append((name, size, 2, url)) - - yield result + file_info = url_dict.values() + return file_info + class FilefactoryCom(Hoster): __name__ = "FilefactoryCom" __type__ = "hoster" - __pattern__ = r"http://(www\.)?filefactory\.com/file/(?P<id>[a-zA-Z0-9]+)" # URLs given out are often longer but this is the requirement - __version__ = "0.3" + __pattern__ = r"http://(?:www\.)?filefactory\.com/file/(?P<id>[a-zA-Z0-9]+).*" # URLs given out are often longer but this is the requirement + __version__ = "0.34" __description__ = """Filefactory.Com File Download Hoster""" - __author_name__ = ("paulking") + __author_name__ = ("paulking", "zoidberg") + LC_INFO_PATTERN = r'<h1 class="name">(?P<name>[^<]+) \((?P<size>[0-9.]+ \w+)\)</h1>\s*<p>http://www.filefactory.com/file/(?P<id>\w+)/' + LC_OFFLINE_PATTERN = r'<p>http://www.filefactory.com/file/(?P<id>\w+)/</p>\s*<p class="errorResponse">' + FILE_OFFLINE_PATTERN = r'<title>File Not Found' FILE_NAME_PATTERN = r'<span class="last">(?P<name>.*?)</span>' FILE_INFO_PATTERN = r'<span>(?P<size>\d(\d|\.)*) (?P<units>..) file uploaded' - FILE_CHECK_PATTERN = r'check:\'(?P<check>.*?)\'' - CAPTCHA_KEY_PATTERN = r'Recaptcha.create\("(?P<recaptchakey>.*?)",' - WAIT_PATH_PATTERN = r'path:"(?P<path>.*?)"' + + FILE_CHECK_PATTERN = r'check:\s*\'(?P<check>.*?)\'' + CAPTCHA_KEY_PATTERN = r'Recaptcha.create\(\s*"(.*?)",' WAIT_PATTERN = r'id="startWait" value="(?P<wait>\d+)"' - FILE_URL_PATTERN = r'<a href="(?P<url>.*?)" id="downloadLinkTarget">' - + FILE_URL_PATTERN = r'<p[^>]*?id="downloadLinkTarget"[^>]*>\s*<a href="(?P<url>.*?)"' + def setup(self): - self.multiDL = False + self.multiDL = self.resumeDownloads = self.premium def process(self, pyfile): - - self.pyfile = pyfile + # Check file + pyfile.name, pyfile.size, status, self.url = checkFile(self, [pyfile.url])[0] + if status != 2: self.offline() + self.logDebug("File Name: %s Size: %d" % (pyfile.name, pyfile.size)) - # Force responses language to US English - self.req.cj.setCookie("filefactory.com", "ff_locale","") - - # Load main page - self.html = self.load(self.pyfile.url, ref=False, decode=True) - - # Check offline - if re.search(self.FILE_OFFLINE_PATTERN, self.html) is not None: - self.offline() + # Handle downloading + url = self.checkDirectDownload(pyfile.url) + if url: + self.download(url) + else: + self.html = self.load(pyfile.url, decode = True) + + if self.premium: + self.handlePremium() + else: + self.handleFree() + + def checkDirectDownload(self, url): + for i in range(5): + header = self.load(url, just_header = True) + if 'location' in header: + url = header['location'].strip() + if not url.startswith("http://"): + url = "http://www.filefactory.com" + url + self.logDebug('URL: ' + url) + elif 'content-disposition' in header: + return url - # File id - self.file_id = re.match(self.__pattern__, self.pyfile.url).group('id') - self.log.debug("%s: File id is [%s]" % (self.__name__, self.file_id)) - - # File name - self.pyfile.name = re.search(self.FILE_NAME_PATTERN, self.html).group('name') - - # Check Id - self.check = re.search(self.FILE_CHECK_PATTERN, self.html).group('check') - self.log.debug("%s: File check code is [%s]" % (self.__name__, self.check)) - - # Handle free downloading - self.handleFree() + return False def handleFree(self): - + if "Currently only Premium Members can download files larger than" in self.html: + self.fail("File too large for free download") + elif "All free download slots on this server are currently in use" in self.html: + self.retry(50, 900, "All free slots are busy") + + # Check Id + self.check = re.search(self.FILE_CHECK_PATTERN, self.html).group('check') + self.logDebug("File check code is [%s]" % self.check) + # Resolve captcha - self.log.debug("%s: File is captcha protected" % self.__name__) - id = re.search(self.CAPTCHA_KEY_PATTERN, self.html).group('recaptchakey') + found = re.search(self.CAPTCHA_KEY_PATTERN, self.html) + recaptcha_key = found.group(1) if found else "6LeN8roSAAAAAPdC1zy399Qei4b1BwmSBSsBN8zm" + recaptcha = ReCaptcha(self) + # Try up to 5 times - for i in range(5): - self.log.debug("%s: Resolving ReCaptcha with key [%s], round %d" % (self.__name__, id, i+1)) - recaptcha = ReCaptcha(self) - challenge, code = recaptcha.challenge(id) - response = self.load("http://www.filefactory.com/file/checkCaptcha.php", - post={"check" : self.check, "recaptcha_challenge_field" : challenge, "recaptcha_response_field" : code}) - captchavalid = self.handleCaptchaErrors(response) - if captchavalid: + for i in range(5): + challenge, code = recaptcha.challenge(recaptcha_key) + response = json_loads(self.load("http://www.filefactory.com/file/checkCaptcha.php", + post={"check" : self.check, "recaptcha_challenge_field" : challenge, "recaptcha_response_field" : code})) + if response['status'] == 'ok': + self.correctCaptcha() break - if not captchavalid: + else: + self.invalidCaptcha() + else: self.fail("No valid captcha after 5 attempts") - - # Get wait URL - waitpath = re.search(self.WAIT_PATH_PATTERN, response).group('path') - waiturl = "http://www.filefactory.com" + waitpath # This will take us to a wait screen - self.log.debug("%s: fetching wait with url [%s]" % (self.__name__, waiturl)) + waiturl = "http://www.filefactory.com" + response['path'] + self.logDebug("Fetching wait with url [%s]" % waiturl) waithtml = self.load(waiturl, decode=True) # Find the wait value and wait wait = int(re.search(self.WAIT_PATTERN, waithtml).group('wait')) - self.log.debug("%s: Waiting %d seconds." % (self.__name__, wait)) + self.logDebug("Waiting %d seconds." % wait) self.setWait(wait, True) self.wait() # Now get the real download url and retrieve the file url = re.search(self.FILE_URL_PATTERN,waithtml).group('url') # this may either download our file or forward us to an error page - self.log.debug("%s: download url %s" % (self.__name__, url)) + self.logDebug("Download URL: %s" % url) dl = self.download(url) check = self.checkDownload({"multiple": "You are currently downloading too many files at once.", @@ -124,17 +135,14 @@ class FilefactoryCom(Hoster): if check == "multiple": self.setWait(15*60) - self.log.debug("%s: Parallel downloads detected waiting 15 minutes" % self.__name__) + self.logDebug("Parallel downloads detected; waiting 15 minutes") self.wait() self.retry() elif check == "error": self.fail("Unknown error") - - def handleCaptchaErrors(self, response): - self.log.debug("%s: Result of captcha resolving [%s]" % (self.__name__, response)) - if 'status:"ok"' in response: - self.correctCaptcha() - return True + + def handlePremium(self): + self.fail('Please enable direct downloads') - self.log.debug("%s: Wrong captcha" % self.__name__) - self.invalidCaptcha() +def getInfo(urls): + for chunk in chunks(urls, 100): yield checkFile(FilefactoryCom, chunk) diff --git a/module/plugins/hoster/FilejungleCom.py b/module/plugins/hoster/FilejungleCom.py index c49cc8506..fd833eef2 100644 --- a/module/plugins/hoster/FilejungleCom.py +++ b/module/plugins/hoster/FilejungleCom.py @@ -16,70 +16,23 @@ @author: zoidberg """ -import re -from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo -from module.network.RequestFactory import getURL -from module.plugins.ReCaptcha import ReCaptcha +from module.plugins.hoster.FileserveCom import FileserveCom, checkFile +from module.plugins.Plugin import chunks -class FilejungleCom(SimpleHoster): +class FilejungleCom(FileserveCom): __name__ = "FilejungleCom" __type__ = "hoster" - __pattern__ = r"http://(?:www\.)?filejungle\.com/f/([^/]+).*" - __version__ = "0.25" + __pattern__ = r"http://(?:www\.)?filejungle\.com/f/(?P<id>[^/]+).*" + __version__ = "0.51" __description__ = """Filejungle.com plugin - free only""" __author_name__ = ("zoidberg") __author_mail__ = ("zoidberg@mujmail.cz") - - FILE_INFO_PATTERN = r'<div id="file_name">(?P<N>[^<]+) <span class="filename_normal">\((?P<S>[0-9.]+) (?P<U>[kKMG])i?B\)</span></div>' - FILE_OFFLINE_PATTERN = r'(This file is no longer available.</h1>|class="error_msg_title"> Invalid or Deleted File. </div>)' - RECAPTCHA_KEY_PATTERN = r"var reCAPTCHA_publickey='([^']+)'" - WAIT_TIME_PATTERN = r'<h1>Please wait for (\d+) seconds to download the next file\.</h1>' - - def handleFree(self): - file_id = re.search(self.__pattern__, self.pyfile.url).group(1) - url = "http://www.filejungle.com/f/%s" % file_id - self.logDebug("File ID: %s" % file_id) - - # Get captcha - found = re.search(self.RECAPTCHA_KEY_PATTERN, self.html) - if not found: self.fail("Captcha key not found") - captcha_key = found.group(1) - - json_response = self.load(self.pyfile.url, post = {"checkDownload" : "check"}, decode = True) - self.logDebug(json_response) - if r'"success":"showCaptcha"' in json_response: - recaptcha = ReCaptcha(self) - for i in range(5): - captcha_challenge, captcha_response = recaptcha.challenge(captcha_key) - self.logDebug("RECAPTCHA: %s : %s : %s" % (captcha_key, captcha_challenge, captcha_response)) - - json_response = self.load("http://www.filejungle.com/checkReCaptcha.php", post = { - "recaptcha_challenge_field" : captcha_challenge, - "recaptcha_response_field" : captcha_response, - "recaptcha_shortencode_field" : file_id - }, decode = True) - self.logDebug(json_response) - if r'{"success":1}' in json_response: - self.correctCaptcha() - break - else: - self.invalidCaptcha() - else: self.fail("Invalid captcha") - elif r'"fail":"timeLimit"' in json_response: - self.html = self.load(url, post = {"checkDownload" : "showError", "errorType" : "timeLimit"}) - found = re.search(self.WAIT_TIME_PATTERN, self.html) - self.retry(5, int(found.group(1)) if found else 1200, "Time limit reached") - else: - self.fail("Unknown server response") - - json_response = self.load(url, post = {"downloadLink" : "wait"}, decode = True) - self.logDebug(json_response[:30]) - found = re.search(r'"waitTime":(\d+)', json_response) - if not found: self.fail("Cannot get wait time") - self.setWait(int(found.group(1))) - self.wait() - - response = self.load(url, post = {"downloadLink" : "show"}) - self.download(url, post = {"download" : "normal"}) - -getInfo = create_getInfo(FilejungleCom) + + URLS = ['http://www.filejungle.com/f/', 'http://www.filejungle.com/check_links.php', 'http://www.filejungle.com/checkReCaptcha.php'] + LINKCHECK_TR = r'<li>\s*(<div class="col1">.*?)</li>' + LINKCHECK_TD = r'<div class="(?:col )?col\d">(?:<[^>]*>| )*([^<]*)' + + LONG_WAIT_PATTERN = r'<h1>Please wait for (\d+) (\w+)\s*to download the next file\.</h1>' + +def getInfo(urls): + for chunk in chunks(urls, 100): yield checkFile(FilejungleCom, chunk)
\ No newline at end of file diff --git a/module/plugins/hoster/FilepostCom.py b/module/plugins/hoster/FilepostCom.py index 834ad7199..bc47856e5 100644 --- a/module/plugins/hoster/FilepostCom.py +++ b/module/plugins/hoster/FilepostCom.py @@ -14,6 +14,11 @@ along with this program; if not, see <http://www.gnu.org/licenses/>. @author: zoidberg + + changelog: + 0.27 - 2012-08-12 - hgg + fix "global name 'js_answer' is not defined" bug + fix captcha bug #1 (failed on non-english "captcha wrong" errors) """ import re @@ -26,7 +31,7 @@ class FilepostCom(SimpleHoster): __name__ = "FilepostCom" __type__ = "hoster" __pattern__ = r"https?://(?:www\.)?(?:filepost\.com/files|fp.io)/([^/]+).*" - __version__ = "0.26" + __version__ = "0.27" __description__ = """Filepost.com plugin - free only""" __author_name__ = ("zoidberg") __author_mail__ = ("zoidberg@mujmail.cz") @@ -81,7 +86,7 @@ class FilepostCom(SimpleHoster): get_dict['JsHttpRequest'] = str(int(time()*10000)) + '-xml' if pokus: post_dict["recaptcha_challenge_field"], post_dict["recaptcha_response_field"] = recaptcha.challenge(captcha_key) - self.logDebug(u"RECAPTCHA: %s : %s : %s" % (captcha_key, post_dict["recaptcha_challenge_field"], post_dict["recaptcha_response_field"])) + self.logDebug(u"RECAPTCHA: %s : %s : %s" % (captcha_key, post_dict["recaptcha_challenge_field"], post_dict["recaptcha_response_field"])) download_url = self.getJsonResponse(get_dict, post_dict, 'link') if download_url: @@ -101,19 +106,30 @@ class FilepostCom(SimpleHoster): if not 'js' in json_response: self.parseError('JSON %s 1' % field) + # i changed js_answer to json_response['js'] since js_answer is nowhere set. + # i don't know the JSON-HTTP specs in detail, but the previous author + # accessed json_response['js']['error'] as well as js_answer['error']. + # see the two lines commented out with "# ~?". if 'error' in json_response['js']: if json_response['js']['error'] == 'download_delay': - self.retry(js_answer['params']['next_download']) + self.retry(json_response['js']['params']['next_download']) + # ~? self.retry(js_answer['params']['next_download']) elif 'Wrong file password' in json_response['js']['error']: return None elif 'You entered a wrong CAPTCHA code' in json_response['js']['error']: return None + elif 'CAPTCHA Code nicht korrekt' in json_response['js']['error']: + return None + elif 'CAPTCHA' in json_response['js']['error']: + self.logDebug('error response is unknown, but mentions CAPTCHA -> return None') + return None else: - self.fail(js_answer['error']) + self.fail(json_response['js']['error']) + # ~? self.fail(js_answer['error']) if not 'answer' in json_response['js'] or not field in json_response['js']['answer']: self.parseError('JSON %s 2' % field) return json_response['js']['answer'][field] -getInfo = create_getInfo(FilepostCom)
\ No newline at end of file +getInfo = create_getInfo(FilepostCom) diff --git a/module/plugins/hoster/FilerioCom.py b/module/plugins/hoster/FilerioCom.py new file mode 100644 index 000000000..3d983bedf --- /dev/null +++ b/module/plugins/hoster/FilerioCom.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +from module.plugins.hoster.XFileSharingPro import XFileSharingPro, create_getInfo + +class FilerioCom(XFileSharingPro): + __name__ = "FilerioCom" + __type__ = "hoster" + __pattern__ = r"http://(?:\w*\.)*file(rio|keen).com/\w{12}" + __version__ = "0.01" + __description__ = """FileRio.com hoster plugin""" + __author_name__ = ("zoidberg") + __author_mail__ = ("zoidberg@mujmail.cz") + + FILE_OFFLINE_PATTERN = '<b>"File Not Found"</b>|File has been removed due to Copyright Claim' + HOSTER_NAME = "filerio.com" + DIRECT_LINK_PATTERN = r'Download Link:.*?<a href="(.*?)"' + + def setup(self): + self.multiDL = False + +getInfo = create_getInfo(FilerioCom)
\ No newline at end of file diff --git a/module/plugins/hoster/FileserveCom.py b/module/plugins/hoster/FileserveCom.py index ce3836a48..04c297661 100644 --- a/module/plugins/hoster/FileserveCom.py +++ b/module/plugins/hoster/FileserveCom.py @@ -1,168 +1,211 @@ -# -*- coding: utf-8 -*-
-from __future__ import with_statement
-
-import re
-
-from module.plugins.Hoster import Hoster
-from module.plugins.ReCaptcha import ReCaptcha
-
-from module.common.json_layer import json_loads
-from module.network.RequestFactory import getURL
-from module.utils import parseFileSize
-
-
-def getInfo(urls):
- yield [(url, 0, 1, url) for url in urls]
-
-class FileserveCom(Hoster):
- __name__ = "FileserveCom"
- __type__ = "hoster"
- __pattern__ = r"http://(www\.)?fileserve\.com/file/[a-zA-Z0-9]+"
- __version__ = "0.44"
- __description__ = """Fileserve.Com File Download Hoster"""
- __author_name__ = ("jeix", "mkaay", "paul king")
- __author_mail__ = ("jeix@hasnomail.de", "mkaay@mkaay.de", "")
-
- FILE_ID_KEY = r"fileserve\.com/file/(?P<id>\w+)"
- FILE_CHECK_KEY = r"<td>http://www.fileserve\.com/file/(?P<id>\w+)</td>.*?<td>(?P<name>.*?)</td>.*?<td>(?P<units>.*?) (?P<scale>.B)</td>.*?<td>(?P<online>.*?)</td>"
- CAPTCHA_KEY_PATTERN = r"var reCAPTCHA_publickey='(?P<key>.*?)';"
- LONG_WAIT_PATTERN = r"You need to wait (\d+) seconds to start another download"
-
- def init(self):
- if not self.premium:
- self.multiDL = False
- self.resumeDownload = False
- self.chunkLimit = 1
-
- def process(self, pyfile):
- self.fail("Hoster not longer available")
-
- def checkFile(self):
- self.file_id = re.search(self.FILE_ID_KEY, self.pyfile.url).group("id")
- self.logDebug("file id is %s" % self.file_id)
-
- self.pyfile.url = "http://www.fileserve.com/file/" + self.file_id
-
- linkCheck = self.load("http://www.fileserve.com/link-checker.php",
- post={"urls": self.pyfile.url},
- ref=False, cookies=False if self.account else True, decode=True)
-
- linkMatch = re.search(self.FILE_CHECK_KEY, linkCheck.replace("\r\n", ""))
- if not linkMatch:
- self.logDebug("couldn't extract file status")
- self.offline()
-
- if linkMatch.group("online").find("Available"):
- self.logDebug("file is not available : %s" % linkMatch.group("online"))
- self.offline()
-
- self.pyfile.name = linkMatch.group("name")
-
-
- def handlePremium(self):
- # TODO: handle login timeouts
- self.download(self.pyfile.url)
-
- check = self.checkDownload({"login": '<form action="/login.php" method="POST">'})
-
- if check == "login":
- self.account.relogin(self.user)
- self.retry(reason=_("Not logged in."))
-
-
- def handleFree(self):
- self.html = self.load(self.pyfile.url)
- action = self.load(self.pyfile.url, post={"checkDownload": "check"}, decode=True)
- action = json_loads(action.replace(u"\ufeff", ""))
- self.logDebug("action is : %s" % action)
-
- if "fail" in action:
- if action["fail"] == "timeLimit":
- html = self.load(self.pyfile.url,
- post={"checkDownload": "showError",
- "errorType": "timeLimit"},
- decode=True)
- wait = re.search(self.LONG_WAIT_PATTERN, html)
- if wait:
- wait = int(wait.group(1))
- else:
- wait = 720
- self.setWait(wait, True)
- self.wait()
- self.retry()
-
- elif action["fail"] == "parallelDownload":
- self.logWarning(_("Parallel download error, now waiting 60s."))
- self.retry(wait_time=60, reason="parallelDownload")
-
- else:
- self.fail("Download check returned %s" % action["fail"])
-
- if action["success"] == "showCaptcha":
- self.doCaptcha()
- self.doTimmer()
- elif action["success"] == "showTimmer":
- self.doTimmer()
-
- # show download link
- response = self.load(self.pyfile.url, post={"downloadLink": "show"}, decode=True)
- self.logDebug("show downloadLink response : %s" % response)
- if not response.find("fail"):
- self.fail("Couldn't retrieve download url")
-
- # this may either download our file or forward us to an error page
- self.download(self.pyfile.url, post={"download": "normal"})
-
- check = self.checkDownload({"expired": "Your download link has expired",
- "wait": re.compile(self.LONG_WAIT_PATTERN),
- "limit": "Your daily download limit has been reached"})
-
- if check == "expired":
- self.logDebug("Download link was expired")
- self.retry()
- elif check == "wait":
- wait_time = 720
- if self.lastCheck is not None:
- wait_time = int(self.lastCheck.group(1))
- self.setWait(wait_time + 3, True)
- self.wait()
- self.retry()
- elif check == "limit":
- #download limited reached for today (not a exact time known)
-
- self.setWait(180 * 60, True) # wait 3 hours
- self.wait()
- self.retry(max_tries=0)
-
- self.thread.m.reconnecting.wait(3) # Ease issue with later downloads appearing to be in parallel
-
- def doTimmer(self):
- wait = self.load(self.pyfile.url,
- post={"downloadLink": "wait"},
- decode=True).replace(u"\ufeff", "") # remove UTF8 BOM
- self.logDebug("wait response : %s" % wait)
-
- if not wait.find("fail"):
- self.fail("Failed getting wait time")
-
- self.setWait(int(wait)) # remove UTF8 BOM
- self.wait()
-
- def doCaptcha(self):
- captcha_key = re.search(self.CAPTCHA_KEY_PATTERN, self.html).group("key")
- recaptcha = ReCaptcha(self)
-
- for i in range(5):
- challenge, code = recaptcha.challenge(captcha_key)
-
- response = json_loads(self.load("http://www.fileserve.com/checkReCaptcha.php",
- post={'recaptcha_challenge_field': challenge,
- 'recaptcha_response_field': code,
- 'recaptcha_shortencode_field': self.file_id}).replace(u"\ufeff", ""))
- self.logDebug("reCaptcha response : %s" % response)
- if not response["success"]:
- self.invalidCaptcha()
- else:
- self.correctCaptcha()
- break
-
+# -*- coding: utf-8 -*- +""" + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <http://www.gnu.org/licenses/>. +""" + +import re +from module.plugins.Hoster import Hoster +from module.network.RequestFactory import getURL +from module.plugins.ReCaptcha import ReCaptcha +from module.common.json_layer import json_loads +from module.utils import parseFileSize +from module.plugins.Plugin import chunks + +def checkFile(plugin, urls): + html = getURL(plugin.URLS[1], post = {"urls": "\n".join(urls)}, decode=True) + + file_info = [] + for li in re.finditer(plugin.LINKCHECK_TR, html, re.DOTALL): + try: + cols = re.findall(plugin.LINKCHECK_TD, li.group(1)) + if cols: + file_info.append(( + cols[1] if cols[1] != '--' else cols[0], + parseFileSize(cols[2]) if cols[2] != '--' else 0, + 2 if cols[3].startswith('Available') else 1, + cols[0])) + except Exception, e: + continue + + return file_info + +class FileserveCom(Hoster): + __name__ = "FileserveCom" + __type__ = "hoster" + __pattern__ = r"http://(?:www\.)?fileserve\.com/file/(?P<id>[^/]+).*" + __version__ = "0.51" + __description__ = """Fileserve.Com File Download Hoster""" + __author_name__ = ("jeix", "mkaay", "paul king", "zoidberg") + __author_mail__ = ("jeix@hasnomail.de", "mkaay@mkaay.de", "", "zoidberg@mujmail.cz") + + URLS = ['http://www.fileserve.com/file/', 'http://www.fileserve.com/link-checker.php', 'http://www.fileserve.com/checkReCaptcha.php'] + LINKCHECK_TR = r'<tr>\s*(<td>http://www.fileserve\.com/file/.*?)</tr>' + LINKCHECK_TD = r'<td>(?:<[^>]*>| )*([^<]*)' + + CAPTCHA_KEY_PATTERN = r"var reCAPTCHA_publickey='(?P<key>[^']+)'" + LONG_WAIT_PATTERN = r'<li class="title">You need to wait (\d+) (\w+) to start another download\.</li>' + LINK_EXPIRED_PATTERN = "Your download link has expired" + DAILY_LIMIT_PATTERN = "Your daily download limit has been reached" + NOT_LOGGED_IN_PATTERN = '<form (name="loginDialogBoxForm"|id="login_form")|<li><a href="/login.php">Login</a></li>' + + # shares code with FilejungleCom and UploadstationCom + + def setup(self): + self.resumeDownload = self.multiDL = True if self.premium else False + + self.file_id = re.search(self.__pattern__, self.pyfile.url).group('id') + self.url = "%s%s" % (self.URLS[0], self.file_id) + self.logDebug("File ID: %s URL: %s" % (self.file_id, self.url)) + + def process(self, pyfile): + pyfile.name, pyfile.size, status, self.url = checkFile(self, [self.url])[0] + if status != 2: self.offline() + self.logDebug("File Name: %s Size: %d" % (pyfile.name, pyfile.size)) + + if self.premium: + self.handlePremium() + else: + self.handleFree() + + def handleFree(self): + self.html = self.load(self.url) + action = self.load(self.url, post={"checkDownload": "check"}, decode=True) + action = json_loads(action) + self.logDebug(action) + + if "fail" in action: + if action["fail"] == "timeLimit": + self.html = self.load(self.url, + post={"checkDownload": "showError", + "errorType": "timeLimit"}, + decode=True) + + self.doLongWait(re.search(self.LONG_WAIT_PATTERN, self.html)) + + elif action["fail"] == "parallelDownload": + self.logWarning(_("Parallel download error, now waiting 60s.")) + self.retry(wait_time=60, reason="parallelDownload") + + else: + self.fail("Download check returned %s" % action["fail"]) + + elif "success" in action: + if action["success"] == "showCaptcha": + self.doCaptcha() + self.doTimmer() + elif action["success"] == "showTimmer": + self.doTimmer() + + else: + self.fail("Unknown server response") + + # show download link + response = self.load(self.url, post={"downloadLink": "show"}, decode=True) + self.logDebug("show downloadLink response : %s" % response) + if "fail" in response: + self.fail("Couldn't retrieve download url") + + # this may either download our file or forward us to an error page + self.download(self.url, post = {"download": "normal"}) + self.logDebug(self.req.http.lastEffectiveURL) + + check = self.checkDownload({"expired": self.LINK_EXPIRED_PATTERN, + "wait": re.compile(self.LONG_WAIT_PATTERN), + "limit": self.DAILY_LIMIT_PATTERN}) + + if check == "expired": + self.logDebug("Download link was expired") + self.retry() + elif check == "wait": + self.doLongWait(self.lastCheck) + elif check == "limit": + #download limited reached for today (not a exact time known) + self.setWait(180 * 60, True) # wait 3 hours + self.wait() + self.retry(max_tries=0) + + self.thread.m.reconnecting.wait(3) # Ease issue with later downloads appearing to be in parallel + + def doTimmer(self): + response = self.load(self.url, + post={"downloadLink": "wait"}, + decode=True) + self.logDebug("wait response : %s" % response[:80]) + + if "fail" in response: + self.fail("Failed getting wait time") + + if self.__name__ == "FilejungleCom": + found = re.search(r'"waitTime":(\d+)', response) + if not found: self.fail("Cannot get wait time") + wait_time = int(found.group(1)) + else: + wait_time = int(response) + 3 + + self.setWait(wait_time) + self.wait() + + def doCaptcha(self): + captcha_key = re.search(self.CAPTCHA_KEY_PATTERN, self.html).group("key") + recaptcha = ReCaptcha(self) + + for i in range(5): + challenge, code = recaptcha.challenge(captcha_key) + + response = json_loads(self.load(self.URLS[2], + post={'recaptcha_challenge_field': challenge, + 'recaptcha_response_field': code, + 'recaptcha_shortencode_field': self.file_id})) + self.logDebug("reCaptcha response : %s" % response) + if not response["success"]: + self.invalidCaptcha() + else: + self.correctCaptcha() + break + else: self.fail("Invalid captcha") + + def doLongWait(self, m): + wait_time = (int(m.group(1)) * {'seconds':1, 'minutes':60, 'hours':3600}[m.group(2)]) if m else 720 + self.setWait(wait_time, True) + self.wait() + self.retry() + + def handlePremium(self): + premium_url = None + if self.__name__ == "FileserveCom": + #try api download + response = self.load("http://app.fileserve.com/api/download/premium/", + post = {"username": self.user, + "password": self.account.getAccountData(self.user)["password"], + "shorten": self.file_id}, + decode = True) + if response: + response = json_loads(response) + if response['error_code'] == "302": premium_url = response['next'] + elif response['error_code'] in ["305", "500"]: self.tempOffline() + elif response['error_code'] in ["403", "605"]: self.resetAccount() + elif response['error_code'] in ["606", "607", "608"]: self.offline() + else: self.logError(response['error_code'], response['error_message']) + + self.download(premium_url or self.pyfile.url) + + if not premium_url: + check = self.checkDownload({"login": re.compile(self.NOT_LOGGED_IN_PATTERN)}) + + if check == "login": + self.account.relogin(self.user) + self.retry(reason=_("Not logged in.")) + +def getInfo(urls): + for chunk in chunks(urls, 100): yield checkFile(FileserveCom, chunk)
\ No newline at end of file diff --git a/module/plugins/hoster/FourSharedCom.py b/module/plugins/hoster/FourSharedCom.py index 2b27eed28..551706283 100644 --- a/module/plugins/hoster/FourSharedCom.py +++ b/module/plugins/hoster/FourSharedCom.py @@ -7,33 +7,45 @@ import re class FourSharedCom(SimpleHoster): __name__ = "FourSharedCom" __type__ = "hoster" - __pattern__ = r"http://[\w\.]*?4shared(-china)?\.com/(account/)?(download|get|file|document|photo|video|audio)/.+?/.*" - __version__ = "0.25" + __pattern__ = r"http://[\w\.]*?4shared(-china)?\.com/(account/)?(download|get|file|document|photo|video|audio|office)/.+?/.*" + __version__ = "0.28" __description__ = """4Shared Download Hoster""" __author_name__ = ("jeix", "zoidberg") __author_mail__ = ("jeix@hasnomail.de", "zoidberg@mujmail.cz") - FILE_NAME_PATTERN = '<meta name="title" content="(?P<N>[^"]+)" />' + FILE_NAME_PATTERN = r'<meta name="title" content="(?P<N>.+?)"' FILE_SIZE_PATTERN = '<span title="Size: (?P<S>[0-9,.]+) (?P<U>[kKMG])i?B">' FILE_OFFLINE_PATTERN = 'The file link that you requested is not valid\.|This file was deleted.' FILE_NAME_REPLACEMENTS = [(r"&#(\d+).", lambda m: unichr(int(m.group(1))))] + FILE_SIZE_REPLACEMENTS = [(",", "")] - DOWNLOAD_BUTTON_PATTERN = '<a href="([^"]+)"\s*class="dbtn' - DOWNLOAD_URL_PATTERN = r"<a class=\"linkShowD3\" href='([^']+)'>Download file now</a>" + DOWNLOAD_BUTTON_PATTERN = 'id="btnLink" href="(.*?)"' + FID_PATTERN = 'name="d3fid" value="(.*?)"' + DOWNLOAD_URL_PATTERN = r'name="d3link" value="(.*?)"' def handleFree(self): + if not self.account: + self.fail("User not logged in") + found = re.search(self.DOWNLOAD_BUTTON_PATTERN, self.html) if found: link = found.group(1) else: link = re.sub(r'/(download|get|file|document|photo|video|audio)/', r'/get/', self.pyfile.url) - + self.html = self.load(link) found = re.search(self.DOWNLOAD_URL_PATTERN, self.html) if not found: self.parseError('Download link') link = found.group(1) + try: + found = re.search(self.FID_PATTERN, self.html) + response = self.load('http://www.4shared.com/web/d2/getFreeDownloadLimitInfo?fileId=%s' % found.group(1)) + self.logDebug(response) + except: + pass + self.setWait(20) self.wait() self.download(link) diff --git a/module/plugins/hoster/FreakshareCom.py b/module/plugins/hoster/FreakshareCom.py index 869b8a99e..56e02cbdc 100644 --- a/module/plugins/hoster/FreakshareCom.py +++ b/module/plugins/hoster/FreakshareCom.py @@ -9,10 +9,10 @@ class FreakshareCom(Hoster): __name__ = "FreakshareCom"
__type__ = "hoster"
__pattern__ = r"http://(?:www\.)?freakshare\.(net|com)/files/\S*?/"
- __version__ = "0.33"
+ __version__ = "0.37"
__description__ = """Freakshare.com Download Hoster"""
- __author_name__ = ("sitacuisses","spoob","mkaay")
- __author_mail__ = ("sitacuisses@yahoo.de","spoob@pyload.org","mkaay@mkaay.de")
+ __author_name__ = ("sitacuisses","spoob","mkaay", "Toilal")
+ __author_mail__ = ("sitacuisses@yahoo.de","spoob@pyload.org","mkaay@mkaay.de", "toilal.dev@gmail.com")
def setup(self):
self.html = None
@@ -22,6 +22,7 @@ class FreakshareCom(Hoster): def process(self, pyfile):
self.pyfile = pyfile
+
pyfile.url = pyfile.url.replace("freakshare.net/","freakshare.com/")
if self.account:
@@ -36,10 +37,22 @@ class FreakshareCom(Hoster): self.download(self.pyfile.url, post=self.req_opts)
- check = self.checkDownload({"bad": "bad try"})
+ check = self.checkDownload({"bad": "bad try",
+ "paralell": "> Sorry, you cant download more then 1 files at time. <",
+ "empty": "Warning: Unknown: Filename cannot be empty",
+ "wrong_captcha": "Wrong Captcha!"})
+
if check == "bad":
self.fail("Bad Try.")
-
+ if check == "paralell":
+ self.setWait(300, True)
+ self.wait()
+ self.retry()
+ if check == "empty":
+ self.fail("File not downloadable")
+ if check == "wrong_captcha":
+ self.invalidCaptcha()
+ self.retry()
def prepare(self):
pyfile = self.pyfile
@@ -61,6 +74,7 @@ class FreakshareCom(Hoster): return True
def download_html(self):
+ self.load("http://freakshare.com/index.php", {"language": "EN"}); # Set english language in server session
self.html = self.load(self.pyfile.url)
def get_file_url(self):
@@ -105,16 +119,11 @@ class FreakshareCom(Hoster): if self.html is None:
self.download_html()
- if "Der Traffic f\xc3\xbcr heute ist verbraucht!" in self.html or "Your Traffic is used up for today" in self.html:
+ if "Your Traffic is used up for today" in self.html:
self.wantReconnect = True
return 24*3600
- if re.search(r"This file does not exist!", self.html) is not None:
- self.offline()
- timestring = re.search('\s*var\sdownloadWait\s=\s(\d*);', self.html)
- if timestring:
- return int(timestring.group(1)) + 1 #add 1 sec as tenths of seconds are cut off
- timestring = re.search('\s*var\stime\s=\s(\d*)[.0];', self.html)
+ timestring = re.search('\s*var\s(?:downloadWait|time)\s=\s(\d*)[.\d]*;', self.html)
if timestring:
return int(timestring.group(1)) + 1 #add 1 sec as tenths of seconds are cut off
else:
@@ -126,7 +135,7 @@ class FreakshareCom(Hoster): """
if self.html is None:
self.download_html()
- if re.search(r"Sorry, this Download doesnt exist anymore", self.html) is not None:
+ if re.search(r"This file does not exist!", self.html) is not None:
return False
else:
return True
@@ -134,10 +143,7 @@ class FreakshareCom(Hoster): def get_download_options(self):
re_envelope = re.search(r".*?value=\"Free\sDownload\".*?\n*?(.*?<.*?>\n*)*?\n*\s*?</form>", self.html).group(0) #get the whole request
to_sort = re.findall(r"<input\stype=\"hidden\"\svalue=\"(.*?)\"\sname=\"(.*?)\"\s\/>", re_envelope)
- request_options = []
-
- for item in to_sort: #Name value pairs are output reversed from regex, so we reorder them
- request_options.append((item[1], item[0]))
+ request_options = dict((n, v) for (v, n) in to_sort)
herewego = self.load(self.pyfile.url, None, request_options) # the actual download-Page
@@ -146,21 +152,16 @@ class FreakshareCom(Hoster): # fp.write(herewego)
to_sort = re.findall(r"<input\stype=\".*?\"\svalue=\"(\S*?)\".*?name=\"(\S*?)\"\s.*?\/>", herewego)
- request_options = []
+ request_options = dict((n, v) for (v, n) in to_sort)
# comment this in, when it doesnt work as well
#print "\n\n%s\n\n" % ";".join(["%s=%s" % x for x in to_sort])
-
- for item in to_sort: #Same as above
- request_options.append((item[1], item[0]))
challenge = re.search(r"http://api\.recaptcha\.net/challenge\?k=([0-9A-Za-z]+)", herewego)
if challenge:
re_captcha = ReCaptcha(self)
- challenge, result = re_captcha.challenge(challenge.group(1))
-
- request_options.append(("recaptcha_challenge_field", challenge))
- request_options.append(("recaptcha_response_field", result))
+ request_options["recaptcha_challenge_field"], request_options["recaptcha_response_field"] \
+ = re_captcha.challenge(challenge.group(1))
return request_options
diff --git a/module/plugins/hoster/FshareVn.py b/module/plugins/hoster/FshareVn.py index 5a8b00c17..977e97211 100644 --- a/module/plugins/hoster/FshareVn.py +++ b/module/plugins/hoster/FshareVn.py @@ -16,23 +16,27 @@ def getInfo(urls): yield file_info +def doubleDecode(m): + return m.group(1).decode('raw_unicode_escape') + class FshareVn(SimpleHoster): __name__ = "FshareVn" __type__ = "hoster" __pattern__ = r"http://(www\.)?fshare.vn/file/.*" - __version__ = "0.12" + __version__ = "0.13" __description__ = """FshareVn Download Hoster""" __author_name__ = ("zoidberg") __author_mail__ = ("zoidberg@mujmail.cz") - FILE_INFO_PATTERN = r'<p>(?P<N>[^<]+)<\\/p>\\r\\n\s*<p>(?P<S>[0-9,.]+)\s*(?P<U>[kKMG])i?B<\\/p>' + FILE_INFO_PATTERN = r'<p>(?P<N>[^<]+)<\\/p>[\\trn\s]*<p>(?P<S>[0-9,.]+)\s*(?P<U>[kKMG])i?B<\\/p>' FILE_OFFLINE_PATTERN = r'<div class=\\"f_left file_(enable|w)\\">' + FILE_NAME_REPLACEMENTS = [("(.*)", doubleDecode)] DOWNLOAD_URL_PATTERN = r"<a class=\"bt_down\" id=\"down\".*window.location='([^']+)'\">" FORM_PATTERN = r'<form action="" method="post" name="frm_download">(.*?)</form>' FORM_INPUT_PATTERN = r'<input[^>]* name="?([^" ]+)"? value="?([^" ]+)"?[^>]*>' VIP_URL_PATTERN = r'<form action="([^>]+)" method="get" name="frm_download">' - WAIT_PATTERN = u"Vui lòng chờ cho lượt download kế tiếp !" + WAIT_PATTERN = u"Vui lòng chờ lượt download kế tiếp" def process(self, pyfile): self.html = self.load('http://www.fshare.vn/check_link.php', post = { @@ -40,15 +44,17 @@ class FshareVn(SimpleHoster): "arrlinks": pyfile.url }, decode = True) self.getFileInfo() - if self.account and self.premium: - self.handlePremium() - else: - self.handleFree() + + url = self.handlePremium() if self.premium else self.handleFree() + self.download(url) + self.checkDownloadedFile() def handleFree(self): self.html = self.load(self.pyfile.url, decode = True) if self.WAIT_PATTERN in self.html: - self.retry(300, 20, "Try again later...") + self.retry(20, 300, "Try again later...") + + self.checkErrors() found = re.search(self.FORM_PATTERN, self.html, re.DOTALL) if not found: self.parseError('FORM') @@ -68,15 +74,18 @@ class FshareVn(SimpleHoster): self.setWait(int(found.group(1)) if found else 30) self.wait() - self.download(url) + return url def handlePremium(self): header = self.load(self.pyfile.url, just_header = True) if 'location' in header and header['location'].startswith('http://download'): self.logDebug('Direct download') - self.download(self.pyfile.url) + return self.pyfile.url else: self.html = self.load(self.pyfile.url) + + self.checkErrors() + found = re.search(self.VIP_URL_PATTERN, self.html) if not found: if self.retries >= 3: self.resetAccount() @@ -84,4 +93,17 @@ class FshareVn(SimpleHoster): self.retry(5, 1, 'VIP URL not found') url = found.group(1) self.logDebug('VIP URL: ' + url) - self.download(url)
\ No newline at end of file + return url + + def checkErrors(self): + if '/error.php?' in self.req.lastEffectiveURL: + self.offline() + + def checkDownloadedFile(self): + # check download + check = self.checkDownload({ + "not_found": ("<head><title>404 Not Found</title></head>") + }) + + if check == "not_found": + self.fail("File not found on server")
\ No newline at end of file diff --git a/module/plugins/hoster/GigapetaCom.py b/module/plugins/hoster/GigapetaCom.py new file mode 100644 index 000000000..28ba35abe --- /dev/null +++ b/module/plugins/hoster/GigapetaCom.py @@ -0,0 +1,73 @@ +# -*- coding: utf-8 -*- +""" + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <http://www.gnu.org/licenses/>. + + @author: zoidberg +""" + +import re +from random import randint +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo +from pycurl import FOLLOWLOCATION + +class GigapetaCom(SimpleHoster): + __name__ = "GigapetaCom" + __type__ = "hoster" + __pattern__ = r"http://(?:www\.)?gigapeta\.com/dl/\w+" + __version__ = "0.01" + __description__ = """GigaPeta.com plugin - free only""" + __author_name__ = ("zoidberg") + __author_mail__ = ("zoidberg@mujmail.cz") + + SH_COOKIES = [("http://gigapeta.com", "lang", "us")] + FILE_NAME_PATTERN = r'<img src=".*" alt="file" />-->\s*(?P<N>.*?)\s*</td>' + FILE_SIZE_PATTERN = r'<th>\s*Size\s*</th>\s*<td>\s*(?P<S>.*?)\s*</td>' + FILE_OFFLINE_PATTERN = r'<div id="page_error">' + + def handleFree(self): + captcha_key = str(randint(1,100000000)) + captcha_url = "http://gigapeta.com/img/captcha.gif?x=%s" % captcha_key + + self.req.http.c.setopt(FOLLOWLOCATION, 0) + + for i in range(5): + self.checkErrors() + + captcha = self.decryptCaptcha(captcha_url) + self.html = self.load(self.pyfile.url, post = { + "captcha_key": captcha_key, + "captcha": captcha, + "download": "Download"}) + + found = re.search(r"Location\s*:\s*(.*)", self.req.http.header, re.I) + if found: + download_url = found.group(1) + break + elif "Entered figures don`t coincide with the picture" in self.html: + self.invalidCaptcha() + else: + self.fail("No valid captcha code entered") + + self.req.http.c.setopt(FOLLOWLOCATION, 1) + self.logDebug("Download URL: %s" % download_url) + self.download(download_url) + + def checkErrors(self): + if "All threads for IP" in self.html: + self.logDebug("Your IP is already downloading a file - wait and retry") + self.setWait(300, True) + self.wait() + self.retry() + +getInfo = create_getInfo(GigapetaCom)
\ No newline at end of file diff --git a/module/plugins/hoster/HellshareCz.py b/module/plugins/hoster/HellshareCz.py index cc8341f8e..0add79ed9 100644 --- a/module/plugins/hoster/HellshareCz.py +++ b/module/plugins/hoster/HellshareCz.py @@ -26,7 +26,7 @@ class HellshareCz(SimpleHoster): __name__ = "HellshareCz" __type__ = "hoster" __pattern__ = r"(http://(?:.*\.)*hellshare\.(?:cz|com|sk|hu)/[^?]*/\d+).*" - __version__ = "0.76" + __version__ = "0.77" __description__ = """Hellshare.cz""" __author_name__ = ("zoidberg") @@ -46,18 +46,15 @@ class HellshareCz(SimpleHoster): self.chunkLimit = 1 def process(self, pyfile): - if self.account: - self.account.relogin(self.user) - pyfile.url = re.search(self.__pattern__, pyfile.url).group(1) self.html = self.load(pyfile.url, decode = True) self.getFileInfo() found = re.search(self.SHOW_WINDOW_PATTERN, self.html) if not found: self.parseError('SHOW WINDOW') - url = found.group(1) - self.logDebug("SHOW WINDOW: " + url) - self.html = self.load("http://download.hellshare.com" + url, decode=True) + self.url = "http://www.hellshare.com" + found.group(1) + self.logDebug("SHOW WINDOW: " + self.url) + self.html = self.load(self.url, decode=True) if self.account: self.handlePremium() diff --git a/module/plugins/hoster/HotfileCom.py b/module/plugins/hoster/HotfileCom.py index e618d0f4f..df652edcc 100644 --- a/module/plugins/hoster/HotfileCom.py +++ b/module/plugins/hoster/HotfileCom.py @@ -32,24 +32,26 @@ class HotfileCom(Hoster): __name__ = "HotfileCom" __type__ = "hoster" __pattern__ = r"http://(www.)?hotfile\.com/dl/\d+/[0-9a-zA-Z]+/" - __version__ = "0.32" + __version__ = "0.34" __description__ = """Hotfile.com Download Hoster""" - __author_name__ = ("sitacuisses","spoob","mkaay") - __author_mail__ = ("sitacuisses@yhoo.de","spoob@pyload.org","mkaay@mkaay.de") + __author_name__ = ("sitacuisses","spoob","mkaay","JoKoT3") + __author_mail__ = ("sitacuisses@yhoo.de","spoob@pyload.org","mkaay@mkaay.de","jokot3@gmail.com") FILE_OFFLINE_PATTERN = r'File is removed' def setup(self): self.html = [None, None] self.wantReconnect = False - self.multiDL = False self.htmlwithlink = None self.url = None - if self.account: + if self.premium: self.multiDL = True self.resumeDownload = True self.chunkLimit = -1 + else: + self.multiDL = False + self.chunkLimit = 1 def apiCall(self, method, post, login=False): if not self.account and login: @@ -73,7 +75,7 @@ class HotfileCom(Hoster): pyfile.name = self.apiData["name"] - if not self.account: + if not self.premium: self.downloadHTML() if self.FILE_OFFLINE_PATTERN in self.html[0]: @@ -127,14 +129,9 @@ class HotfileCom(Hoster): free_limit_pattern = re.compile(r"timerend=d\.getTime\(\)\+(\d+);") matches = free_limit_pattern.findall(self.html[0]) if matches: - for match in matches: - if int(match) in (60000,15000,0): - continue - else: - waittime = int(match)/1000 + 65 - if waittime > 300: - self.wantReconnect = True - return waittime - return 65 + wait_time = (sum([int(match) for match in matches])/1000) or 60 + if wait_time > 300: + self.wantReconnect = True + return wait_time + 1 else: - self.fail("Don't know how long to wait. Cannot proceed.") + self.fail("Don't know how long to wait. Cannot proceed.")
\ No newline at end of file diff --git a/module/plugins/hoster/IcyFilesCom.py b/module/plugins/hoster/IcyFilesCom.py new file mode 100644 index 000000000..3f966d936 --- /dev/null +++ b/module/plugins/hoster/IcyFilesCom.py @@ -0,0 +1,112 @@ +# -*- coding: utf-8 -*- +""" + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <http://www.gnu.org/licenses/>. + + @author: godofdream +""" + +import re +from module.plugins.Hoster import Hoster +from module.network.RequestFactory import getURL + +def getInfo(urls): + result = [] + for url in urls: + html = getURL(url, decode=True) + if re.search(IcyFilesCom.FILE_OFFLINE_PATTERN, html): + # File offline + result.append((url, 0, 1, url)) + else: + # Get file info + name = re.search(IcyFilesCom.FILE_NAME_PATTERN, html) + size = re.search(IcyFilesCom.SIZE_PATTERN, html) + if name is not None: + name = name.group(1) + size = (int(size.group(1)) * 1000000) + result.append((name, size, 2, url)) + yield result + + +class IcyFilesCom(Hoster): + __name__ = "IcyFilesCom" + __type__ = "hoster" + __pattern__ = r"http://(?:www\.)?icyfiles\.com/(.*)" + __version__ = "0.04" + __description__ = """IcyFiles.com plugin - free only""" + __author_name__ = ("godofdream") + __author_mail__ = ("soilfiction@gmail.com") + + FILE_NAME_PATTERN = r'<div id="file">(.*?)</div>' + SIZE_PATTERN = r'<li>(\d+) <span>Size/mb' + FILE_OFFLINE_PATTERN = r'The requested File cant be found' + WAIT_LONGER_PATTERN = r'All download tickets are in use\. please try it again in a few seconds' + WAIT_PATTERN = r'<div class="counter">(\d+)</div>' + TOOMUCH_PATTERN = r'Sorry dude, you have downloaded too much\. Please wait (\d+) seconds' + + + def setup(self): + self.multiDL = False + + def process(self, pyfile): + self.html = self.load(pyfile.url, decode=True) + # check if offline + if re.search(self.FILE_OFFLINE_PATTERN, self.html): + self.offline() + # All Downloadtickets in use + timmy = re.search(self.WAIT_LONGER_PATTERN, self.html) + if timmy: + self.logDebug("waitforfreeslot") + self.waitForFreeSlot() + # Wait the waittime + timmy = re.search(self.WAIT_PATTERN, self.html) + if timmy: + self.logDebug("waiting", timmy.group(1)) + self.setWait(int(timmy.group(1)) + 2, False) + self.wait() + # Downloaded to much + timmy = re.search(self.TOOMUCH_PATTERN, self.html) + if timmy: + self.logDebug("too much", timmy.group(1)) + self.setWait(int(timmy.group(1)), True) + self.wait() + # Find Name + found = re.search(self.FILE_NAME_PATTERN, self.html) + if found is None: + self.fail("Parse error (NAME)") + pyfile.name = found.group(1) + # Get the URL + url = pyfile.url + found = re.search(self.__pattern__, url) + if found is None: + self.fail("Parse error (URL)") + download_url = "http://icyfiles.com/download.php?key=" + found.group(1) + self.download(download_url) + # check download + check = self.checkDownload({ + "notfound": re.compile(r"^<head><title>404 Not Found</title>$"), + "skippedcountdown": re.compile(r"^Dont skip the countdown$"), + "waitforfreeslots": re.compile(self.WAIT_LONGER_PATTERN), + "downloadedtoomuch": re.compile(self.TOOMUCH_PATTERN) + }) + if check == "skippedcountdown": + self.fail("Countdown error") + elif check == "notfound": + self.fail("404 Not found") + elif check == "waitforfreeslots": + self.waitForFreeSlot() + elif check == "downloadedtoomuch": + self.retry() + + def waitForFreeSlot(self): + self.retry(60, 60, "Wait for free slot") diff --git a/module/plugins/hoster/IfileIt.py b/module/plugins/hoster/IfileIt.py index ec830f3b2..bf394f340 100644 --- a/module/plugins/hoster/IfileIt.py +++ b/module/plugins/hoster/IfileIt.py @@ -25,8 +25,8 @@ from module.network.RequestFactory import getURL class IfileIt(SimpleHoster): __name__ = "IfileIt" __type__ = "hoster" - __pattern__ = r"http://(?:\w*\.)*(?:ifile\.it|mihd\.net)/(\w+).*" - __version__ = "0.24" + __pattern__ = r"^unmatchable$" + __version__ = "0.27" __description__ = """Ifile.it""" __author_name__ = ("zoidberg") @@ -35,28 +35,29 @@ class IfileIt(SimpleHoster): DOWNLOAD_LINK_PATTERN = r'</span> If it doesn\'t, <a target="_blank" href="([^"]+)">' RECAPTCHA_KEY_PATTERN = r"var __recaptcha_public\s*=\s*'([^']+)';" FILE_INFO_PATTERN = r'<span style="cursor: default;[^>]*>\s*(?P<N>.*?)\s* \s*<strong>\s*(?P<S>[0-9.]+)\s*(?P<U>[kKMG])i?B\s*</strong>\s*</span>' - FILE_OFFLINE_PATTERN = r'$\("#errorPnl"\)\.empty\(\)\.append\( "no such file" \);' + FILE_OFFLINE_PATTERN = r'<span style="cursor: default;[^>]*>\s* \s*<strong>\s*</strong>\s*</span>' + TEMP_OFFLINE_PATTERN = r'<span class="msg_red">Downloading of this file is temporarily disabled</span>' def handleFree(self): ukey = re.search(self.__pattern__, self.pyfile.url).group(1) - json_url = 'http://ifile.it/download-request2.json?ukey=' + ukey - - json_response = json_loads(self.load(json_url)) + json_url = 'http://ifile.it/new_download-request.json' + post_data = {"ukey" : ukey, "ab": "0"} + + json_response = json_loads(self.load(json_url, post = post_data)) self.logDebug(json_response) + if json_response['status'] == 3: + self.offline() + if json_response["captcha"]: captcha_key = re.search(self.RECAPTCHA_KEY_PATTERN, self.html).group(1) recaptcha = ReCaptcha(self) + post_data["ctype"] = "recaptcha" for i in range(5): - captcha_challenge, captcha_response = recaptcha.challenge(captcha_key) - - json_response = json_loads(self.load(json_url, post={ - "ctype": "recaptcha", - "recaptcha_challenge": captcha_challenge, - "recaptcha_response": captcha_response - })) - + post_data["recaptcha_challenge"], post_data["recaptcha_response"] = recaptcha.challenge(captcha_key) + json_response = json_loads(self.load(json_url, post = post_data)) self.logDebug(json_response) + if json_response["retry"]: self.invalidCaptcha() else: @@ -65,11 +66,9 @@ class IfileIt(SimpleHoster): else: self.fail("Incorrect captcha") - # load twice - self.html = self.load(self.pyfile.url) - self.html = self.load(self.pyfile.url) - download_url = re.search(self.DOWNLOAD_LINK_PATTERN, self.html).group(1) + if not "ticket_url" in json_response: + self.parseError("Download URL") - self.download(download_url) + self.download(json_response["ticket_url"]) getInfo = create_getInfo(IfileIt)
\ No newline at end of file diff --git a/module/plugins/hoster/IfolderRu.py b/module/plugins/hoster/IfolderRu.py index 83b98ecc9..b84f77c5c 100644 --- a/module/plugins/hoster/IfolderRu.py +++ b/module/plugins/hoster/IfolderRu.py @@ -24,8 +24,8 @@ from module.network.RequestFactory import getURL class IfolderRu(SimpleHoster): __name__ = "IfolderRu" __type__ = "hoster" - __pattern__ = r"http://(?:\w*\.)?ifolder.ru/(\d+).*" - __version__ = "0.33" + __pattern__ = r"http://(?:[^.]*\.)?ifolder.ru/(\d+).*" + __version__ = "0.35" __description__ = """ifolder.ru""" __author_name__ = ("zoidberg") __author_mail__ = ("zoidberg@mujmail.cz") @@ -33,7 +33,7 @@ class IfolderRu(SimpleHoster): FILE_SIZE_REPLACEMENTS = [(u'Кб', 'KB'), (u'Мб', 'MB'), (u'Гб', 'GB')] FILE_NAME_PATTERN = ur'(?:<div><span>)?Название:(?:</span>)? <b>(?P<N>[^<]+)</b><(?:/div|br)>' FILE_SIZE_PATTERN = ur'(?:<div><span>)?Размер:(?:</span>)? <b>(?P<S>[^<]+)</b><(?:/div|br)>' - FILE_OFFLINE_PATTERN = ur'<p>Файл номер <b>[^<]*</b> не найден !!!</p>' + FILE_OFFLINE_PATTERN = ur'<p>Файл номер <b>[^<]*</b> (не найден|удален) !!!</p>' SESSION_ID_PATTERN = r'<a href=(http://ints.ifolder.ru/ints/sponsor/\?bi=\d*&session=([^&]+)&u=[^>]+)>' FORM1_PATTERN = r'<form method=post name="form1" ID="Form1" style="margin-bottom:200px">(.*?)</form>' diff --git a/module/plugins/hoster/JumbofilesCom.py b/module/plugins/hoster/JumbofilesCom.py new file mode 100644 index 000000000..9e8adb512 --- /dev/null +++ b/module/plugins/hoster/JumbofilesCom.py @@ -0,0 +1,31 @@ +# -*- coding: utf-8 -*- +import re +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo +from module.utils import html_unescape + +class JumbofilesCom(SimpleHoster): + __name__ = "JumbofilesCom" + __type__ = "hoster" + __pattern__ = r"http://(?:\w*\.)*jumbofiles.com/(\w{12}).*" + __version__ = "0.02" + __description__ = """JumboFiles.com hoster plugin""" + __author_name__ = ("godofdream") + __author_mail__ = ("soilfiction@gmail.com") + + FILE_INFO_PATTERN = '<TR><TD>(?P<N>[^<]+?)\s*<small>\((?P<S>[\d.]+)\s*(?P<U>[KMG][bB])\)</small></TD></TR>' + FILE_OFFLINE_PATTERN = 'Not Found or Deleted / Disabled due to inactivity or DMCA' + DIRECT_LINK_PATTERN = '<meta http-equiv="refresh" content="10;url=(.+)">' + + def setup(self): + self.resumeDownload = True + self.multiDL = True + + def handleFree(self): + ukey = re.search(self.__pattern__, self.pyfile.url).group(1) + post_data = {"id" : ukey, "op": "download3", "rand": ""} + html = self.load(self.pyfile.url, post = post_data, decode=True) + url = re.search(self.DIRECT_LINK_PATTERN, html).group(1) + self.logDebug("Download " + url) + self.download(url) + +getInfo = create_getInfo(JumbofilesCom) diff --git a/module/plugins/hoster/LetitbitNet.py b/module/plugins/hoster/LetitbitNet.py index 4ff2b9750..88e708bf5 100644 --- a/module/plugins/hoster/LetitbitNet.py +++ b/module/plugins/hoster/LetitbitNet.py @@ -19,12 +19,13 @@ import re from random import random from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo +from module.common.json_layer import json_loads class LetitbitNet(SimpleHoster): __name__ = "LetitbitNet" __type__ = "hoster" - __pattern__ = r"http://(?:\w*\.)*letitbit.net/download/.*" - __version__ = "0.13" + __pattern__ = r"http://(?:\w*\.)*(letitbit|shareflare).net/download/.*" + __version__ = "0.19" __description__ = """letitbit.net""" __author_name__ = ("zoidberg") __author_mail__ = ("zoidberg@mujmail.cz") @@ -32,8 +33,14 @@ class LetitbitNet(SimpleHoster): CHECK_URL_PATTERN = r"ajax_check_url\s*=\s*'((http://[^/]+)[^']+)';" SECONDS_PATTERN = r"seconds\s*=\s*(\d+);" - FILE_INFO_PATTERN = r'<h1[^>]*>File: <a[^>]*><span>(?P<N>[^<]+)</span></a>\s*\[<span>(?P<S>[^<]+)</span>]</h1>' - FILE_OFFLINE_PATTERN = r'<div id="download_content" class="hide-block">[^<]*<br>File not found<br /></div>' + FILE_INFO_PATTERN = r'<h1[^>]*>File:.*?<span>(?P<N>[^<]+)</span>.*?\[<span>(?P<S>[^<]+)</span>]</h1>' + FILE_OFFLINE_PATTERN = r'>File not found<' + + DOMAIN = "http://letitbit.net" + FILE_URL_REPLACEMENTS = [(r"(?<=http://)([^/]+)", "letitbit.net")] + + def setup(self): + self.resumeDownload = self.multiDL = True def handleFree(self): action, inputs = self.parseHtmlForm('id="ifree_form"') @@ -42,8 +49,9 @@ class LetitbitNet(SimpleHoster): #self.logDebug(action, inputs) inputs['desc'] = "" - self.html = self.load("http://letitbit.net" + action, post = inputs, cookies = True) - + self.html = self.load(self.DOMAIN + action, post = inputs, cookies = True) + + """ action, inputs = self.parseHtmlForm('id="d3_form"') if not action: self.parseError("page 2 / d3_form") #self.logDebug(action, inputs) @@ -59,23 +67,44 @@ class LetitbitNet(SimpleHoster): except Exception, e: self.logError(e) self.parseError("page 3 / js") - - response = self.load(ajax_check_url, post = inputs, cookies = True) - if response != '1': self.fail('Unknown response (ajax_check_url)') + """ + + found = re.search(self.SECONDS_PATTERN, self.html) + seconds = int(found.group(1)) if found else 60 + self.setWait(seconds+1) + self.wait() + + response = self.load("%s/ajax/download3.php" % self.DOMAIN, post = " ", cookies = True) + if response != '1': self.parseError('Unknown response - ajax_check_url') for i in range(5): - captcha = self.decryptCaptcha('%s/captcha_new.php?rand=%d' % (captcha_url, random() * 100000), cookies = True) - response = self.load(captcha_url + '/ajax/check_captcha.php', post = {"code": captcha}, cookies = True) + captcha = self.decryptCaptcha('%s/captcha_new.php?rand=%d' % (self.DOMAIN, random() * 100000), cookies = True) + response = self.load('%s/ajax/check_captcha.php' % self.DOMAIN, post = {"code": captcha}, cookies = True) self.logDebug(response) - if response.startswith('http://'): - download_url = response - self.correctCaptcha() + if not response: + self.invalidCaptcha() + elif response.startswith('['): + urls = json_loads(response) + break + elif response.startswith('http://'): + urls = [response] break else: - self.invalidCaptcha() + self.parseError("Unknown response - captcha check") + else: self.fail("No valid captcha solution received") - self.download(download_url) + self.correctCaptcha() + + for download_url in urls: + try: + self.logDebug("Download URL", download_url) + self.download(download_url) + break + except Exception, e: + self.logError(e) + else: + self.fail("Download did not finish correctly") getInfo = create_getInfo(LetitbitNet)
\ No newline at end of file diff --git a/module/plugins/hoster/LoadTo.py b/module/plugins/hoster/LoadTo.py index b1204cb2d..66bc6f407 100644 --- a/module/plugins/hoster/LoadTo.py +++ b/module/plugins/hoster/LoadTo.py @@ -33,7 +33,7 @@ def getInfo(urls): # Get file info name = re.search(LoadTo.FILE_NAME_PATTERN, html) size = re.search(LoadTo.SIZE_PATTERN, html) - if name is not None: + if name is not None and size is not None: name = name.group(1) size = size.group(1) result.append((name, size, 2, url)) @@ -42,14 +42,14 @@ def getInfo(urls): class LoadTo(Hoster): __name__ = "LoadTo" __type__ = "hoster" - __pattern__ = r"http://.*load.to/.*" - __version__ = "0.1" + __pattern__ = r"http://(www.*?\.)?load\.to/.{7,10}?/.*" + __version__ = "0.1002" __description__ = """load.to""" __author_name__ = ("halfman") __author_mail__ = ("Pulpan3@gmail.com") - FILE_NAME_PATTERN = r'<div class="toolarge"><h1>([^<]+)</h1></div>' - URL_PATTERN = r'<form method="post" action="([^"]+)"' + FILE_NAME_PATTERN = r'<div class="toolarge"><h1>(.+?)</h1></div>' + URL_PATTERN = r'<form method="post" action="(.+?)"' SIZE_PATTERN = r'<div class="download_table_right">(\d+) Bytes</div>' FILE_OFFLINE_PATTERN = r'Can\'t find file. Please check URL.<br />' WAIT_PATTERN = r'type="submit" value="Download \((\d+)\)"' @@ -64,11 +64,6 @@ class LoadTo(Hoster): if re.search(self.FILE_OFFLINE_PATTERN, self.html): self.offline() - timmy = re.search(self.WAIT_PATTERN, self.html) - if timmy: - self.setWait(timmy.group(1)) - self.wait() - found = re.search(self.FILE_NAME_PATTERN, self.html) if found is None: self.fail("Parse error (NAME)") @@ -78,5 +73,10 @@ class LoadTo(Hoster): if found is None: self.fail("Parse error (URL)") download_url = found.group(1) + + timmy = re.search(self.WAIT_PATTERN, self.html) + if timmy: + self.setWait(timmy.group(1)) + self.wait() - self.download(download_url)
\ No newline at end of file + self.download(download_url) diff --git a/module/plugins/hoster/MediafireCom.py b/module/plugins/hoster/MediafireCom.py index c1d6e3595..dce16118f 100644 --- a/module/plugins/hoster/MediafireCom.py +++ b/module/plugins/hoster/MediafireCom.py @@ -58,7 +58,7 @@ class MediafireCom(SimpleHoster): __name__ = "MediafireCom" __type__ = "hoster" __pattern__ = r"http://(\w*\.)*mediafire\.com/(file/|(download.php)?\?)(\w{11}|\w{15})($|/)" - __version__ = "0.74" + __version__ = "0.76" __description__ = """Mediafire.com plugin - free only""" __author_name__ = ("zoidberg") __author_mail__ = ("zoidberg@mujmail.cz") @@ -75,7 +75,7 @@ class MediafireCom(SimpleHoster): FILE_OFFLINE_PATTERN = r'class="error_msg_title"> Invalid or Deleted File. </div>' def setup(self): - self.multiDL = True + self.multiDL = False def process(self, pyfile): self.url, result = checkHTMLHeader(pyfile.url) @@ -83,15 +83,18 @@ class MediafireCom(SimpleHoster): if result == 0: self.html = self.load(self.url, decode = True) - self.checkCaptcha() + self.checkCaptcha() + self.multiDL = True self.getFileInfo() + if self.account: self.handlePremium() else: self.handleFree() elif result == 1: self.offline() - else: + else: + self.multiDL = True self.download(self.url, disposition = True) def handleFree(self): @@ -104,6 +107,7 @@ class MediafireCom(SimpleHoster): else: self.fail("No or incorrect password") + """ links = re.findall(self.DOWNLOAD_LINK_PATTERN, self.html) link_count = len(links) self.logDebug('LINKS ', links) @@ -131,6 +135,11 @@ class MediafireCom(SimpleHoster): else: zindex, download_url = links[0] + """ + found = re.search(r'kNO = "(http://.*?)";', self.html) + if not found: self.parseError("Download URL") + download_url = found.group(1) + self.logDebug("DOWNLOAD LINK:", download_url) self.download(download_url) diff --git a/module/plugins/hoster/NarodRu.py b/module/plugins/hoster/NarodRu.py new file mode 100644 index 000000000..335860de9 --- /dev/null +++ b/module/plugins/hoster/NarodRu.py @@ -0,0 +1,66 @@ +# -*- coding: utf-8 -*- +""" + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <http://www.gnu.org/licenses/>. + + @author: zoidberg +""" + +import re +from random import random +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo + +class NarodRu(SimpleHoster): + __name__ = "NarodRu" + __type__ = "hoster" + __pattern__ = r"http://(www\.)?narod(\.yandex)?\.ru/(disk|start/[0-9]+\.\w+-narod\.yandex\.ru)/(?P<ID>\d+)/.+" + __version__ = "0.1" + __description__ = """Narod.ru""" + __author_name__ = ("zoidberg") + + FILE_NAME_PATTERN = r'<dt class="name">(?:<[^<]*>)*(?P<N>[^<]+)</dt>' + FILE_SIZE_PATTERN = r'<dd class="size">(?P<S>\d[^<]*)</dd>' + FILE_OFFLINE_PATTERN = r'<title>404</title>|Файл удален с сервиса|Закончился срок хранения файла\.' + + FILE_SIZE_REPLACEMENTS = [(u'КБ', 'KB'), (u'МБ', 'MB'), (u'ГБ', 'GB')] + FILE_URL_REPLACEMENTS = [("narod.yandex.ru/", "narod.ru/"), (r"/start/[0-9]+\.\w+-narod\.yandex\.ru/([0-9]{6,15})/\w+/(\w+)", r"/disk/\1/\2")] + + CAPTCHA_PATTERN = r'<number url="(.*?)">(\w+)</number>' + DOWNLOAD_LINK_PATTERN = r'<a class="h-link" rel="yandex_bar" href="(.+?)">' + + def handleFree(self): + for i in range(5): + self.html = self.load('http://narod.ru/disk/getcapchaxml/?rnd=%d' % int(random() * 777)) + found = re.search(self.CAPTCHA_PATTERN, self.html) + if not found: self.parseError('Captcha') + post_data = {"action": "sendcapcha"} + captcha_url, post_data['key'] = found.groups() + post_data['rep'] = self.decryptCaptcha(captcha_url) + + self.html = self.load(self.pyfile.url, post = post_data, decode = True) + found = re.search(self.DOWNLOAD_LINK_PATTERN, self.html) + if found: + url = 'http://narod.ru' + found.group(1) + self.correctCaptcha() + break + elif u'<b class="error-msg"><strong>Ошиблись?</strong>' in self.html: + self.invalidCaptcha() + else: + self.parseError('Download link') + else: + self.fail("No valid captcha code entered") + + self.logDebug('Download link: ' + url) + self.download(url) + +getInfo = create_getInfo(NarodRu)
\ No newline at end of file diff --git a/module/plugins/hoster/NetloadIn.py b/module/plugins/hoster/NetloadIn.py index d768090e8..9310b5c34 100644 --- a/module/plugins/hoster/NetloadIn.py +++ b/module/plugins/hoster/NetloadIn.py @@ -24,7 +24,7 @@ def getInfo(urls): if match: ids = ids + match.group(1) +";" - api = getURL(apiurl+ids) + api = getURL(apiurl+ids, decode = True) if api is None or len(api) < 10: print "Netload prefetch: failed " @@ -53,14 +53,14 @@ class NetloadIn(Hoster): __name__ = "NetloadIn" __type__ = "hoster" __pattern__ = r"http://.*netload\.in/(?:datei(.*?)(?:\.htm|/)|index.php?id=10&file_id=)" - __version__ = "0.33" + __version__ = "0.40" __description__ = """Netload.in Download Hoster""" __author_name__ = ("spoob", "RaNaN", "Gregy") __author_mail__ = ("spoob@pyload.org", "ranan@pyload.org", "gregy@gregy.cz") def setup(self): self.multiDL = False - if self.account: + if self.premium: self.multiDL = True self.chunkLimit = -1 self.resumeDownload = True @@ -77,7 +77,7 @@ class NetloadIn(Hoster): if self.api_data and self.api_data["filename"]: self.pyfile.name = self.api_data["filename"] - if self.account: + if self.premium: self.log.debug("Netload: Use Premium Account") return True @@ -96,8 +96,8 @@ class NetloadIn(Hoster): self.api_data = False return - apiurl = "http://netload.in/share/fileinfos2.php" - src = self.load(apiurl, cookies=False, get={"file_id": match.group(1)}).strip() + apiurl = "http://api.netload.in/info.php" + src = self.load(apiurl, cookies=False, get={"file_id": match.group(1), "auth": "Zf9SnQh9WiReEsb18akjvQGqT0I830e8", "bz": "1", "md5": "1"}, decode = True).strip() if not src and n <= 3: sleep(0.2) self.download_api_data(n+1) @@ -105,7 +105,7 @@ class NetloadIn(Hoster): self.log.debug("Netload: APIDATA: "+src) self.api_data = {} - if src and src not in ("unknown file_data", "unknown_server_data"): + if src and src not in ("unknown file_data", "unknown_server_data", "No input file specified."): lines = src.split(";") self.api_data["exists"] = True self.api_data["fileid"] = lines[0] @@ -145,7 +145,11 @@ class NetloadIn(Hoster): self.offline() name = re.search(r'class="dl_first_filename">([^<]+)', page, re.MULTILINE) - self.pyfile.name = name.group(1).strip() + # the found filename is not truncated + if name: + name = name.group(1).strip() + if not name.endswith(".."): + self.pyfile.name = name captchawaited = False for i in range(10): @@ -160,11 +164,11 @@ class NetloadIn(Hoster): self.log.debug("Netload: try number %d " % i) - if re.search(r"(We will prepare your download..)", page) is not None: + if ">Your download is being prepared.<" in page: self.log.debug("Netload: We will prepare your download") self.final_wait(page) return True - if re.search(r"(We had a reqeust with the IP)", page) is not None: + if ">An access request has been made from IP address <" in page: wait = self.get_wait_time(page) if wait == 0: self.log.debug("Netload: Wait was 0 setting 30") @@ -211,7 +215,7 @@ class NetloadIn(Hoster): def get_file_url(self, page): try: - file_url_pattern = r"<a class=\"Orange_Link\" href=\"(http://.+)\".?>Click here" + file_url_pattern = r"<a class=\"Orange_Link\" href=\"(http://.+)\".?>Or click here" attempt = re.search(file_url_pattern, page) if attempt is not None: return attempt.group(1) @@ -232,12 +236,12 @@ class NetloadIn(Hoster): def proceed(self, url): self.log.debug("Netload: Downloading..") - self.download(url) + self.download(url, disposition=True) check = self.checkDownload({"empty": re.compile(r"^$"), "offline": re.compile("The file was deleted")}) if check == "empty": - self.log.info(_("Downloaded File was empty")) + self.logInfo(_("Downloaded File was empty")) self.retry() elif check == "offline": self.offline() diff --git a/module/plugins/hoster/OneFichierCom.py b/module/plugins/hoster/OneFichierCom.py index 16401891b..128942b75 100644 --- a/module/plugins/hoster/OneFichierCom.py +++ b/module/plugins/hoster/OneFichierCom.py @@ -6,49 +6,44 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class OneFichierCom(SimpleHoster): __name__ = "OneFichierCom" __type__ = "hoster" - __pattern__ = r"(http://\w+\.((1fichier|d(es)?fichiers|pjointe)\.(com|fr|net|org)|(cjoint|mesfichiers|piecejointe|oi)\.(org|net)|tenvoi\.(com|org|net)|dl4free\.com|alterupload\.com|megadl.fr))" - __version__ = "0.4" + __pattern__ = r"(http://(\w+)\.((1fichier|d(es)?fichiers|pjointe)\.(com|fr|net|org)|(cjoint|mesfichiers|piecejointe|oi)\.(org|net)|tenvoi\.(com|org|net)|dl4free\.com|alterupload\.com|megadl.fr))" + __version__ = "0.43" __description__ = """1fichier.com download hoster""" __author_name__ = ("fragonib", "the-razer", "zoidberg") __author_mail__ = ("fragonib[AT]yahoo[DOT]es", "daniel_ AT gmx DOT net", "zoidberg@mujmail.cz") - FILE_NAME_PATTERN = r'">File name :</th>[\t\r\n ]+<td>(?P<N>.*?)</td>' - FILE_SIZE_PATTERN = r'<th>File size :</th>\s+<td>(?P<S>[\d\.]*) (?P<U>\w+)</td>' + FILE_NAME_PATTERN = r'">File name :</th>\s*<td>(?P<N>[^<]+)</td>' + FILE_SIZE_PATTERN = r'<th>File size :</th>\s*<td>(?P<S>[^<]+)</td>' FILE_OFFLINE_PATTERN = r'The (requested)? file (could not be found|has been deleted)' FILE_URL_REPLACEMENTS = [(r'(http://[^/]*).*', r'\1/en/')] DOWNLOAD_LINK_PATTERN = r'<br/> <br/> <br/> \s+<a href="(?P<url>http://.*?)"' PASSWORD_PROTECTED_TOKEN = "protected by password" - WAITING_TOKEN = "Please wait a few seconds" + WAITING_TOKEN = "Please wait a few seconds" - def handleFree(self): + def process(self, pyfile): + found = re.search(self.__pattern__, pyfile.url) + file_id = found.group(2) + url = "http://%s.%s/en/" % (found.group(2), found.group(3)) + self.html = self.load(url, decode = True) + if self.WAITING_TOKEN in self.html: - self.waitAndRetry(60) + self.waitAndRetry(120) + + self.getFileInfo() + + url, inputs = self.parseHtmlForm('action="http://%s' % file_id) + if not url or not inputs: + self.parseError("Download link not found") # Check for protection - if self.isProtected(): - password = self.getPassword() - self.logDebug("Submitting password [%s]" % password) - self.download(url, post={"password" : password}) - else: - downloadLink = self.getDownloadLink() - self.download(downloadLink) + if "pass" in inputs: + inputs['pass'] = self.getPassword() + + self.download(url, post = inputs) # Check download self.checkDownloadedFile() - - def isProtected(self): - if self.PASSWORD_PROTECTED_TOKEN in self.html: - self.logDebug("Links are password protected") - return True - return False - - def getDownloadLink(self): - m = re.search(self.DOWNLOAD_LINK_PATTERN, self.html) - if m is not None: - url = m.group('url') - self.logDebug("Got file URL [%s]" % url) - return url def checkDownloadedFile(self): check = self.checkDownload({"wait": self.WAITING_TOKEN}) @@ -60,4 +55,4 @@ class OneFichierCom(SimpleHoster): self.wait() self.retry() -getInfo = create_getInfo(OneFichierCom)
\ No newline at end of file +getInfo = create_getInfo(OneFichierCom) diff --git a/module/plugins/hoster/OronCom.py b/module/plugins/hoster/OronCom.py index e659beee5..864b7e96a 100755 --- a/module/plugins/hoster/OronCom.py +++ b/module/plugins/hoster/OronCom.py @@ -16,7 +16,7 @@ def getInfo(urls): result.append((url, 0, 1, url)) continue - m = re.search(OronCom.FILE_INFO_PATTERN, html) + m = re.search(OronCom.FILE_INFO_PATTERN, html, re.MULTILINE) if m: name = m.group(1) size = parseFileSize(m.group(2), m.group(3)) @@ -31,11 +31,11 @@ def getInfo(urls): class OronCom(Hoster): __name__ = "OronCom" __type__ = "hoster" - __pattern__ = r"http://(?:www\.)?oron.com/(?!folder/)" - __version__ = "0.14" - __description__ = "File Hoster: Oron.com" + __pattern__ = r"http://(?:www.)?oron.com/(?!folder)\w+" + __version__ = "0.16" + __description__ = "Oron.com Hoster Plugin" __author_name__ = ("chrox", "DHMH") - __author_mail__ = ("chrox@pyload.org", "DHMH@pyload.org") + __author_mail__ = ("chrox@pyload.org", "webmaster@pcProfil.de") FILE_INFO_PATTERN = r'(?:Filename|Dateiname): <b class="f_arial f_14px">(.*?)</b>\s*<br>\s*(?:Größe|File size): ([0-9,\.]+) (Kb|Mb|Gb)' @@ -50,7 +50,8 @@ class OronCom(Hoster): #self.load("http://oron.com/?op=change_lang&lang=german") # already logged in, so the above line shouldn't be necessary self.html = self.load(self.pyfile.url, ref=False, decode=True).encode("utf-8").replace("\n", "") - if "File could not be found" in self.html or "Datei nicht gefunden" in self.html: + if "File could not be found" in self.html or "Datei nicht gefunden" in self.html or \ + "This file has been blocked for TOS violation." in self.html: self.offline() self.html = self.html.replace("\t", "") m = re.search(self.FILE_INFO_PATTERN, self.html) @@ -126,13 +127,13 @@ class OronCom(Hoster): self.logError("error in parsing site") def handlePremium(self): - self.account.getAccountInfo(True) - self.logDebug("Traffic left: %s" % self.account.formatTrafficleft()) - self.logDebug("File Size: %s" % self.pyfile.formatSize()) + info = self.account.getAccountInfo(self.user, True) + self.logDebug("Traffic left: %s" % info['trafficleft']) + self.logDebug("File Size: %d" % int(self.pyfile.size / 1024)) - if int(self.pyfile.size / 1024) > self.account.trafficleft: + if int(self.pyfile.size / 1024) > info["trafficleft"]: self.logInfo(_("Not enough traffic left")) - self.account.empty() + self.account.empty(self.user) self.fail(_("Traffic exceeded")) post_url = "http://oron.com/" + self.file_id @@ -144,4 +145,3 @@ class OronCom(Hoster): self.html = self.load(post_url, post=post_dict, ref=False, decode=True).encode("utf-8") link = re.search('href="(.*?)" class="atitle"', self.html).group(1) self.download(link) - diff --git a/module/plugins/hoster/PremiumizeMe.py b/module/plugins/hoster/PremiumizeMe.py new file mode 100644 index 000000000..4ae59d198 --- /dev/null +++ b/module/plugins/hoster/PremiumizeMe.py @@ -0,0 +1,50 @@ +from module.plugins.Hoster import Hoster
+
+from module.common.json_layer import json_loads
+
+class PremiumizeMe(Hoster):
+ __name__ = "PremiumizeMe"
+ __version__ = "0.11"
+ __type__ = "hoster"
+ __description__ = """Premiumize.Me hoster plugin"""
+
+ # Since we want to allow the user to specify the list of hoster to use we let MultiHoster.coreReady create the regex patterns for us using getHosters in our PremiumizeMe hook.
+ __pattern__ = None
+
+ __author_name__ = ("Florian Franzen")
+ __author_mail__ = ("FlorianFranzen@gmail.com")
+
+ def process(self, pyfile):
+ # Check account
+ if not self.account or not self.account.canUse():
+ self.logError(_("Please enter a valid premiumize.me account or deactivate this plugin"))
+ self.fail("No valid premiumize.me account provided")
+
+ # In some cases hostsers do not supply us with a filename at download, so we are going to set a fall back filename (e.g. for freakshare or xfileshare)
+ self.pyfile.name = self.pyfile.name.split('/').pop() # Remove everthing before last slash
+
+ # Correction for automatic assigned filename: Removing html at end if needed
+ suffix_to_remove = ["html", "htm", "php", "php3", "asp", "shtm", "shtml", "cfml", "cfm"]
+ temp = self.pyfile.name.split('.')
+ if temp.pop() in suffix_to_remove:
+ self.pyfile.name = ".".join(temp)
+
+ # Get account data
+ (user, data) = self.account.selectAccount()
+
+ # Get rewritten link using the premiumize.me api v1 (see https://secure.premiumize.me/?show=api)
+ answer = self.load("https://api.premiumize.me/pm-api/v1.php?method=directdownloadlink¶ms[login]=%s¶ms[pass]=%s¶ms[link]=%s" % (user, data['password'], self.pyfile.url))
+ data = json_loads(answer)
+
+ # Check status and decide what to do
+ status = data['status']
+ if status == 200:
+ self.download(data['result']['location'], disposition=True)
+ elif status == 400:
+ self.fail("Invalid link")
+ elif status == 404:
+ self.offline()
+ elif status >= 500:
+ self.tempOffline()
+ else:
+ self.fail(data['statusmessage'])
diff --git a/module/plugins/hoster/PutlockerCom.py b/module/plugins/hoster/PutlockerCom.py new file mode 100644 index 000000000..8cfcd4d9e --- /dev/null +++ b/module/plugins/hoster/PutlockerCom.py @@ -0,0 +1,126 @@ +# -*- coding: utf-8 -*- +""" + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <http://www.gnu.org/licenses/>. + + @author: jeix +""" + +import re +from module.plugins.Hoster import Hoster +from module.network.RequestFactory import getURL + +def getInfo(urls): + result = [] + + for url in urls: + + html = getURL(url) + if re.search(PutlockerCom.PATTERN_OFFLINE, html): + result.append((url, 0, 1, url)) + else: + name = re.search(PutlockerCom.PATTERN_FILENAME_1, html) + if name is None: + name = re.search(PutlockerCom.PATTERN_FILENAME_2, html) + if name is None: + result.append((url, 0, 1, url)) + continue + + name = name.group(1) + + # size = re.search(PutlockerCom.PATTERN_FILESIZE, html) + # if size is None: + # result.append((url, 0, 1, url)) + # continue + + # size = size.group(1) + + result.append((name, 0, 2, url)) + yield result + +class PutlockerCom(Hoster): + __name__ = "PutlockerCom" + __type__ = "hoster" + __pattern__ = r'http://(www\.)?putlocker\.com/(file|embed)/[A-Z0-9]+' + __version__ = "0.2" + __description__ = """Putlocker.Com""" + __author_name__ = ("jeix") + + PATTERN_OFFLINE = r"This file doesn't exist, or has been removed." + PATTERN_FILENAME_1 = "site-content.*?<h1>(.*?)<strong" + PATTERN_FILENAME_2 = "<title>(.*?) \|" + PATTERN_FILESIZE = "site-content.*?<h1>.*?<strong>\\((.*?)\\)" + + + def process(self, pyfile): + + self.pyfile = pyfile + self.html = self.load(pyfile.url, decode=True) + + if not self._checkOnline(): + self.offline() + + self.pyfile.name = self._getName() + + self.link = self._getLink() + if not self.link.startswith('http://'): + self.link = "http://www.putlocker.com" + self.link + self.download( self.link ) + + def _checkOnline(self): + if re.search(self.PATTERN_OFFLINE, self.html): + return False + else: + return True + + def _getName(self): + name = re.search(self.PATTERN_FILENAME_1, self.html) + if name is None: + name = re.search(self.PATTERN_FILENAME_2, self.html) + # if name is None: + # self.fail("%s: Plugin broken." % self.__name__) + + return name.group(1) + + def _getLink(self): + self.hash = re.search("<input type=\"hidden\" value=\"([a-z0-9]+)\" name=\"hash\">", self.html) + # if self.hash is None: + # self.fail("%s: Plugin broken." % self.__name__) + + self.param = "hash=" + self.hash.group(1) + "&confirm=Continue+as+Free+User" + self.html2 = self.load(self.pyfile.url, post=self.param) + if ">You have exceeded the daily stream limit for your country\\. You can wait until tomorrow" in self.html2 or "(>This content server has been temporarily disabled for upgrades|Try again soon\\. You can still download it below\\.<)" in self.html2: + self.waittime = 2 * 60 * 60 + self.retry(wait_time=self.waittime, reason="Waiting %s seconds" % self.waittime) + + self.link = re.search("<a href=\"/gopro\\.php\">Tired of ads and waiting\\? Go Pro\\!</a>[\t\n\rn ]+</div>[\t\n\rn ]+<a href=\"(/.*?)\"", self.html2) + if self.link is None: + self.link = re.search("\"(/get_file\\.php\\?download=[A-Z0-9]+\\&key=[a-z0-9]+)\"", self.html2) + + if self.link is None: + self.link = re.search("\"(/get_file\\.php\\?download=[A-Z0-9]+\\&key=[a-z0-9]+&original=1)\"", self.html2) + + if self.link is None: + self.link = re.search("playlist: \\'(/get_file\\.php\\?stream=[A-Za-z0-9=]+)\\'", self.html2) + if not self.link is None: + self.html3 = self.load("http://www.putlocker.com" + self.link.group(1)) + self.link = re.search("media:content url=\"(http://.*?)\"", self.html3) + if self.link is None: + self.link = re.search("\"(http://media\\-b\\d+\\.putlocker\\.com/download/\\d+/.*?)\"", self.html3) + + # if link is None: + # self.fail("%s: Plugin broken." % self.__name__) + + return self.link.group(1).replace("&", "&") + + diff --git a/module/plugins/hoster/RapidgatorNet.py b/module/plugins/hoster/RapidgatorNet.py new file mode 100644 index 000000000..678a3d707 --- /dev/null +++ b/module/plugins/hoster/RapidgatorNet.py @@ -0,0 +1,181 @@ +# -*- coding: utf-8 -*- +""" + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <http://www.gnu.org/licenses/>. + + @author: zoidberg +""" + +import re +from pycurl import HTTPHEADER +from random import random + +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo +from module.common.json_layer import json_loads +from module.plugins.ReCaptcha import ReCaptcha + +class AdsCaptcha(): + def __init__(self, plugin): + self.plugin = plugin + + def challenge(self, src): + js = self.plugin.req.load(src, cookies=True) + + try: + challenge = re.search("challenge: '(.*?)',", js).group(1) + server = re.search("server: '(.*?)',", js).group(1) + except: + self.plugin.fail("adscaptcha error") + result = self.result(server,challenge) + + return challenge, result + + def result(self, server, challenge): + return self.plugin.decryptCaptcha("%sChallenge.aspx" % server, get={"cid": challenge, "dummy": random()}, cookies=True, imgtype="jpg") + +class SolveMedia(): + def __init__(self,plugin): + self.plugin = plugin + + def challenge(self, src): + html = self.plugin.req.load("http://api.solvemedia.com/papi/challenge.script?k=%s" % src, cookies=True) + try: + ckey = re.search("ckey:.*?'(.*?)',",html).group(1) + html = self.plugin.req.load("http://api.solvemedia.com/papi/_challenge.js?k=%s" % ckey, cookies=True) + challenge = re.search('"chid".*?: "(.*?)"',html).group(1) + except: + self.plugin.fail("solvmedia error") + result = self.result(challenge) + + return challenge, result + + def result(self,challenge): + return self.plugin.decryptCaptcha("http://api.solvemedia.com/papi/media?c=%s" % challenge,imgtype="gif") + + +class RapidgatorNet(SimpleHoster): + __name__ = "RapidgatorNet" + __type__ = "hoster" + __pattern__ = r"http://(?:www\.)?(rapidgator.net)/file/(\d+)" + __version__ = "0.06" + __description__ = """rapidgator.net""" + __author_name__ = ("zoidberg","chrox") + + FILE_INFO_PATTERN = r'Downloading:(\s*<[^>]*>)*\s*(?P<N>.*?)(\s*<[^>]*>)*\s*File size:\s*<strong>(?P<S>.*?)</strong>' + FILE_OFFLINE_PATTERN = r'<title>File not found</title>' + + JSVARS_PATTERN = r"\s+var\s*(startTimerUrl|getDownloadUrl|captchaUrl|fid|secs)\s*=\s*'?(.*?)'?;" + DOWNLOAD_LINK_PATTERN = r"location.href = '(.*?)'" + RECAPTCHA_KEY_PATTERN = r'"http://api.recaptcha.net/challenge?k=(.*?)"' + ADSCAPTCHA_SRC_PATTERN = r'(http://api.adscaptcha.com/Get.aspx[^"\']*)' + SOLVEMEDIA_PATTERN = r'http:\/\/api\.solvemedia\.com\/papi\/challenge\.script\?k=(.*?)"' + + def handleFree(self): + if "You can download files up to 500 MB in free mode" in self.html \ + or "This file can be downloaded by premium only" in self.html: + self.fail("Premium account needed for download") + + self.checkWait() + + jsvars = dict(re.findall(self.JSVARS_PATTERN, self.html)) + self.logDebug(jsvars) + + self.req.http.lastURL = self.pyfile.url + self.req.http.c.setopt(HTTPHEADER, ["X-Requested-With: XMLHttpRequest"]) + + url = "http://rapidgator.net%s?fid=%s" % (jsvars.get('startTimerUrl', '/download/AjaxStartTimer'), jsvars["fid"]) + jsvars.update(self.getJsonResponse(url)) + + self.setWait(int(jsvars.get('secs', 30)) + 1, False) + self.wait() + + url = "http://rapidgator.net%s?sid=%s" % (jsvars.get('getDownloadUrl', '/download/AjaxGetDownload'), jsvars["sid"]) + jsvars.update(self.getJsonResponse(url)) + + self.req.http.lastURL = self.pyfile.url + self.req.http.c.setopt(HTTPHEADER, ["X-Requested-With:"]) + + url = "http://rapidgator.net%s" % jsvars.get('captchaUrl', '/download/captcha') + self.html = self.load(url) + found = re.search(self.ADSCAPTCHA_SRC_PATTERN, self.html) + if found: + captcha_key = found.group(1) + captcha = AdsCaptcha(self) + else: + found = re.search(self.RECAPTCHA_KEY_PATTERN, self.html) + if found: + captcha_key = found.group(1) + captcha = ReCaptcha(self) + + else: + found = re.search(self.SOLVEMEDIA_PATTERN, self.html) + if found: + captcha_key = found.group(1) + captcha = SolveMedia(self) + else: + self.parseError("Captcha:"+st) + if captcha.__class__.__name__ == "SolveMedia": + captcha_prov = "adcopy" + else: + captcha_prov = captcha.__class__.__name__.lower() + + for i in range(5): + self.checkWait() + captcha_challenge, captcha_response = captcha.challenge(captcha_key) + + self.html = self.load(url, post={ + "DownloadCaptchaForm[captcha]": "", + "adcopy_challenge": captcha_challenge, + "adcopy_response": captcha_response + }) + + if 'The verification code is incorrect' in self.html: + self.invalidCaptcha() + else: + self.correctCaptcha() + break + else: + self.fail("No valid captcha solution received") + + found = re.search(self.DOWNLOAD_LINK_PATTERN, self.html) + if not found: + self.parseError("download link") + download_url = found.group(1) + self.logDebug(download_url) + self.download(download_url) + + def checkWait(self): + found = re.search(r"(?:Delay between downloads must be not less than|Try again in)\s*(\d+)\s*(hour|min)", self.html) + if found: + wait_time = int(found.group(1)) * {"hour": 60, "min": 1}[found.group(2)] + else: + found = re.search(r"You have reached your (daily|hourly) downloads limit", self.html) + if found: + wait_time = 60 + else: + return + + self.logDebug("Waiting %d minutes" % wait_time) + self.setWait(wait_time * 60, True) + self.wait() + self.retry(max_tries = 24) + + def getJsonResponse(self, url): + response = self.load(url, decode = True) + if not response.startswith('{'): + self.retry() + self.logDebug(url, response) + return json_loads(response) + +getInfo = create_getInfo(RapidgatorNet) + diff --git a/module/plugins/hoster/RapidshareCom.py b/module/plugins/hoster/RapidshareCom.py index a4a72eb53..6aacd684e 100644 --- a/module/plugins/hoster/RapidshareCom.py +++ b/module/plugins/hoster/RapidshareCom.py @@ -50,7 +50,7 @@ class RapidshareCom(Hoster): __name__ = "RapidshareCom" __type__ = "hoster" __pattern__ = r"https?://[\w\.]*?rapidshare.com/(?:files/(?P<id>\d*?)/(?P<name>[^?]+)|#!download\|(?:\w+)\|(?P<id_new>\d+)\|(?P<name_new>[^|]+))" - __version__ = "1.37" + __version__ = "1.38" __description__ = """Rapidshare.com Download Hoster""" __config__ = [("server", "Cogent;Deutsche Telekom;Level(3);Level(3) #2;GlobalCrossing;Level(3) #3;Teleglobe;GlobalCrossing #2;TeliaSonera #2;Teleglobe #2;TeliaSonera #3;TeliaSonera", "Preferred Server", "None")] __author_name__ = ("spoob", "RaNaN", "mkaay") @@ -60,17 +60,14 @@ class RapidshareCom(Hoster): self.html = None self.no_download = True self.api_data = None - self.multiDL = False self.offset = 0 self.dl_dict = {} self.id = None self.name = None - - if self.account: - self.multiDL = True - self.chunkLimit = -1 - self.resumeDownload = True + + self.chunkLimit = -1 if self.premium else 1 + self.multiDL = self.resumeDownload = self.premium def process(self, pyfile): self.url = self.pyfile.url @@ -90,7 +87,7 @@ class RapidshareCom(Hoster): if self.api_data["status"] == "1": self.pyfile.name = self.get_file_name() - if self.account: + if self.premium: self.handlePremium() else: self.handleFree() @@ -225,5 +222,4 @@ class RapidshareCom(Hoster): def get_file_name(self): if self.api_data["filename"]: return self.api_data["filename"] - return self.url.split("/")[-1] - + return self.url.split("/")[-1]
\ No newline at end of file diff --git a/module/plugins/hoster/RarefileNet.py b/module/plugins/hoster/RarefileNet.py new file mode 100644 index 000000000..8339d40eb --- /dev/null +++ b/module/plugins/hoster/RarefileNet.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +import re +from module.plugins.hoster.XFileSharingPro import XFileSharingPro, create_getInfo +from module.utils import html_unescape + +class RarefileNet(XFileSharingPro): + __name__ = "RarefileNet" + __type__ = "hoster" + __pattern__ = r"http://(?:\w*\.)*rarefile.net/\w{12}" + __version__ = "0.01" + __description__ = """Rarefile.net hoster plugin""" + __author_name__ = ("zoidberg") + __author_mail__ = ("zoidberg@mujmail.cz") + + FILE_NAME_PATTERN = r'<td><font color="red">(?P<N>.*?)</font></td>' + FILE_SIZE_PATTERN = r'<td>Size : (?P<S>.+?) ' + + def handleCaptcha(self, inputs): + captcha_div = re.search(r'<b>Enter code.*?<div.*?>(.*?)</div>', self.html, re.S).group(1) + self.logDebug(captcha_div) + numerals = re.findall('<span.*?padding-left\s*:\s*(\d+).*?>(\d)</span>', html_unescape(captcha_div)) + inputs['code'] = "".join([a[1] for a in sorted(numerals, key = lambda num: int(num[0]))]) + self.logDebug("CAPTCHA", inputs['code'], numerals) + return 3 + +getInfo = create_getInfo(RarefileNet)
\ No newline at end of file diff --git a/module/plugins/hoster/RealdebridCom.py b/module/plugins/hoster/RealdebridCom.py index 46ac51c82..3c796232e 100644 --- a/module/plugins/hoster/RealdebridCom.py +++ b/module/plugins/hoster/RealdebridCom.py @@ -1,86 +1,88 @@ -#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-import re
-from time import time
-from urllib import quote, unquote
-from random import randrange
-
-from module.utils import encode, parseFileSize
-from module.common.json_layer import json_loads
-from module.plugins.Hoster import Hoster
-
-class RealdebridCom(Hoster):
- __version__ = "0.43"
- __pattern__ = r"https?://.*real-debrid\..*"
- __description__ = """Real-Debrid.com hoster plugin"""
- __config__ = [("https", "bool", _("Enable HTTPS"), False)]
-
- __author_name__ = ("Devirex, Hazzard")
- __author_mail__ = ("naibaf_11@yahoo.de")
-
- def getFilename(self, url):
- try:
- name = unquote(url.rsplit("/", 1)[1])
- except IndexError:
- name = "Unknown_Filename..."
- if name.endswith("..."): #incomplete filename, append random stuff
- name += "%s.tmp" % randrange(100,999)
- return name
-
- def init(self):
- self.tries = 0
- self.chunkLimit = 3
- self.resumeDownload = True
-
-
- def process(self, pyfile):
- if not self.account:
- self.logError(_("Please enter your Real-debrid account or deactivate this plugin"))
- self.fail("No Real-debrid account provided")
-
- self.log.debug("Real-Debrid: Old URL: %s" % pyfile.url)
- if re.match(self.__pattern__, pyfile.url):
- new_url = pyfile.url
- else:
- password = self.getPassword().splitlines()
- if not password: password = ""
- else: password = password[0]
-
- url = "http://real-debrid.com/ajax/unrestrict.php?lang=en&link=%s&password=%s&time=%s" % (quote(encode(pyfile.url), ""), password, int(time()*1000))
- page = self.load(url)
- data = json_loads(page)
-
- self.logDebug("Returned Data: %s" % data)
-
- if data["error"] != 0:
- if data["message"] == "Your file is unavailable on the hoster.":
- self.offline()
- else:
- self.logWarning(data["message"])
- self.tempOffline()
- else:
- self.pyfile.name = data["file_name"]
- self.pyfile.size = parseFileSize(data["file_size"])
- new_url = data['generated_links'].split('|')[-1]
-
- if self.getConfig("https"):
- new_url = new_url.replace("http://", "https://")
- else:
- new_url = new_url.replace("https://", "http://")
-
- self.log.debug("Real-Debrid: New URL: %s" % new_url)
-
- if pyfile.name.startswith("http") or pyfile.name.startswith("Unknown"):
- #only use when name wasnt already set
- pyfile.name = self.getFilename(new_url)
-
- self.download(new_url, disposition=True)
-
- check = self.checkDownload(
- {"error": "<title>An error occured while processing your request</title>"})
-
- if check == "error":
- #usual this download can safely be retried
- self.retry(reason="An error occured while generating link.", wait_time=60)
-
+#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import re +from time import time +from urllib import quote, unquote +from random import randrange + +from module.utils import parseFileSize, remove_chars +from module.common.json_layer import json_loads +from module.plugins.Hoster import Hoster + +class RealdebridCom(Hoster): + __name__ = "RealdebridCom" + __version__ = "0.49" + __type__ = "hoster" + + __pattern__ = r"https?://.*real-debrid\..*" + __description__ = """Real-Debrid.com hoster plugin""" + __author_name__ = ("Devirex, Hazzard") + __author_mail__ = ("naibaf_11@yahoo.de") + + def getFilename(self, url): + try: + name = unquote(url.rsplit("/", 1)[1]) + except IndexError: + name = "Unknown_Filename..." + if not name or name.endswith(".."): #incomplete filename, append random stuff + name += "%s.tmp" % randrange(100,999) + return name + + def init(self): + self.tries = 0 + self.chunkLimit = 3 + self.resumeDownload = True + + + def process(self, pyfile): + if not self.account: + self.logError(_("Please enter your Real-debrid account or deactivate this plugin")) + self.fail("No Real-debrid account provided") + + self.log.debug("Real-Debrid: Old URL: %s" % pyfile.url) + if re.match(self.__pattern__, pyfile.url): + new_url = pyfile.url + else: + password = self.getPassword().splitlines() + if not password: password = "" + else: password = password[0] + + url = "http://real-debrid.com/ajax/unrestrict.php?lang=en&link=%s&password=%s&time=%s" % (quote(pyfile.url, ""), password, int(time()*1000)) + page = self.load(url) + data = json_loads(page) + + self.logDebug("Returned Data: %s" % data) + + if data["error"] != 0: + if data["message"] == "Your file is unavailable on the hoster.": + self.offline() + else: + self.logWarning(data["message"]) + self.tempOffline() + else: + if self.pyfile.name is not None and self.pyfile.name.endswith('.tmp') and data["file_name"]: + self.pyfile.name = data["file_name"] + self.pyfile.size = parseFileSize(data["file_size"]) + new_url = data['generated_links'][0][-1] + + if self.getConfig("https"): + new_url = new_url.replace("http://", "https://") + else: + new_url = new_url.replace("https://", "http://") + + self.log.debug("Real-Debrid: New URL: %s" % new_url) + + if pyfile.name.startswith("http") or pyfile.name.startswith("Unknown") or pyfile.name.endswith('..'): + #only use when name wasnt already set + pyfile.name = self.getFilename(new_url) + + self.download(new_url, disposition=True) + + check = self.checkDownload( + {"error": "<title>An error occured while processing your request</title>"}) + + if check == "error": + #usual this download can safely be retried + self.retry(reason="An error occured while generating link.", wait_time=60) + diff --git a/module/plugins/hoster/RyushareCom.py b/module/plugins/hoster/RyushareCom.py new file mode 100644 index 000000000..b3d7bafc6 --- /dev/null +++ b/module/plugins/hoster/RyushareCom.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +from module.plugins.hoster.XFileSharingPro import XFileSharingPro, create_getInfo + +class RyushareCom(XFileSharingPro): + __name__ = "RyushareCom" + __type__ = "hoster" + __pattern__ = r"http://(?:\w*\.)*?ryushare.com/\w{12}" + __version__ = "0.02" + __description__ = """ryushare.com hoster plugin""" + __author_name__ = ("zoidberg") + __author_mail__ = ("zoidberg@mujmail.cz") + + HOSTER_NAME = "ryushare.com" + + def setup(self): + self.resumeDownload = self.multiDL = self.premium + +getInfo = create_getInfo(RyushareCom)
\ No newline at end of file diff --git a/module/plugins/hoster/Share4webCom.py b/module/plugins/hoster/Share4webCom.py new file mode 100644 index 000000000..ef9c2acf8 --- /dev/null +++ b/module/plugins/hoster/Share4webCom.py @@ -0,0 +1,16 @@ +# -*- coding: utf-8 -*- + +from module.plugins.hoster.UnibytesCom import UnibytesCom +from module.plugins.internal.SimpleHoster import create_getInfo + +class Share4webCom(UnibytesCom): + __name__ = "Share4webCom" + __type__ = "hoster" + __pattern__ = r"http://(www\.)?share4web\.com/get/\w+" + __version__ = "0.1" + __description__ = """Share4web.com""" + __author_name__ = ("zoidberg") + + DOMAIN = 'http://www.share4web.com' + +getInfo = create_getInfo(UnibytesCom)
\ No newline at end of file diff --git a/module/plugins/hoster/ShareRapidCom.py b/module/plugins/hoster/ShareRapidCom.py index b9ce61e18..4a25d4027 100644 --- a/module/plugins/hoster/ShareRapidCom.py +++ b/module/plugins/hoster/ShareRapidCom.py @@ -3,66 +3,102 @@ import re from pycurl import HTTPHEADER -from module.network.RequestFactory import getRequest +from module.network.RequestFactory import getRequest, getURL from module.network.HTTPRequest import BadHeader from module.plugins.internal.SimpleHoster import SimpleHoster, parseFileInfo +from module.common.json_layer import json_loads +def checkFile(url): + info = {"name" : url, "size" : 0, "status" : 3} + + response = getURL("http://share-rapid.com/checkfiles.php", post = {"files": url}, decode = True) + info = json_loads(response) + + if "error" in info: + if info['error'] == False: + info['name'] = info['filename'] + info['status'] = 2 + elif info['msg'] == "Not found": + info['status'] = 1 #offline + elif info['msg'] == "Service Unavailable": + info['status'] = 6 #temp.offline + + return info + def getInfo(urls): - file_info = [] for url in urls: - h = getRequest() - try: - h.c.setopt(HTTPHEADER, ["Accept: text/html"]) - html = h.load(url, cookies = True, decode = True) - file_info = parseFileInfo(ShareRapidCom, url, html) - finally: - h.close() - yield file_info + info = checkFile(url) + if "filename" in info: + yield info['name'], info['size'], info['status'], url + else: + file_info = (url, 0, 3, url) + h = getRequest() + try: + h.c.setopt(HTTPHEADER, ["Accept: text/html"]) + html = h.load(url, cookies = True, decode = True) + file_info = parseFileInfo(ShareRapidCom, url, html) + finally: + h.close() + yield file_info class ShareRapidCom(SimpleHoster): __name__ = "ShareRapidCom" __type__ = "hoster" - __pattern__ = r"http://(?:www\.)?((share(-?rapid\.(biz|com|cz|info|eu|net|org|pl|sk)|-(central|credit|free|net)\.cz|-ms\.net)|(s-?rapid|rapids)\.(cz|sk))|(e-stahuj|mediatack|premium-rapidshare|rapidshare-premium|qiuck)\.cz|kadzet\.com|stahuj-zdarma\.eu|strelci\.net|universal-share\.com)/(stahuj/.+)" - __version__ = "0.47" + __pattern__ = r"http://(?:www\.)?((share(-?rapid\.(biz|com|cz|info|eu|net|org|pl|sk)|-(central|credit|free|net)\.cz|-ms\.net)|(s-?rapid|rapids)\.(cz|sk))|(e-stahuj|mediatack|premium-rapidshare|rapidshare-premium|qiuck)\.cz|kadzet\.com|stahuj-zdarma\.eu|strelci\.net|universal-share\.com)/stahuj/(.+)" + __version__ = "0.50" __description__ = """Share-rapid.com plugin - premium only""" __author_name__ = ("MikyWoW", "zoidberg") __author_mail__ = ("MikyWoW@seznam.cz", "zoidberg@mujmail.cz") FILE_NAME_PATTERN = r'<h1[^>]*><span[^>]*>(?:<a[^>]*>)?(?P<N>[^<]+)' FILE_SIZE_PATTERN = r'<td class="i">Velikost:</td>\s*<td class="h"><strong>\s*(?P<S>[0-9.]+) (?P<U>[kKMG])i?B</strong></td>' + FILE_OFFLINE_PATTERN = ur'Nastala chyba 404|Soubor byl smazán' + DOWNLOAD_URL_PATTERN = r'<a href="([^"]+)" title="Stahnout">([^<]+)</a>' ERR_LOGIN_PATTERN = ur'<div class="error_div"><strong>Stahování je přístupné pouze přihlášeným uživatelům' ERR_CREDIT_PATTERN = ur'<div class="error_div"><strong>Stahování zdarma je možné jen přes náš' - FILE_OFFLINE_PATTERN = ur'Nastala chyba 404|Soubor byl smazán' def setup(self): self.chunkLimit = 1 self.resumeDownload = True def process(self, pyfile): - if not self.account: self.fail("User not logged in") - url = "http://share-rapid.com/" + re.search(self.__pattern__, pyfile.url).groups()[-1] - self.logDebug("URL: " + url) - + if not self.account: self.fail("User not logged in") + + self.info = checkFile(pyfile.url) + self.logDebug(self.info) + + pyfile.status = self.info['status'] + + if pyfile.status == 2: + pyfile.name = self.info['name'] + pyfile.size = self.info['size'] + elif pyfile.status == 1: + self.offline() + elif pyfile.status == 6: + self.tempOffline() + else: + self.fail("Unexpected file status") + + url = "http://share-rapid.com/stahuj/%s" % self.info['filepath'] try: self.html = self.load(url, decode=True) except BadHeader, e: self.account.relogin(self.user) self.retry(3, 0, str(e)) - - self.getFileInfo() found = re.search(self.DOWNLOAD_URL_PATTERN, self.html) if found is not None: - link, pyfile.name = found.groups() + link = found.group(1) self.logDebug("Premium link: %s" % link) + + self.check_data = {"size": pyfile.size} self.download(link) else: - self.logError("Download URL not found") if re.search(self.ERR_LOGIN_PATTERN, self.html): - self.relogin() + self.relogin(self.user) self.retry(3,0,"User login failed") elif re.search(self.ERR_CREDIT_PATTERN, self.html): self.fail("Not enough credit left") else: - self.fail("Download link not found")
\ No newline at end of file + self.fail("Download link not found")
\ No newline at end of file diff --git a/module/plugins/hoster/ShareonlineBiz.py b/module/plugins/hoster/ShareonlineBiz.py index 2d1fc8d85..b40cd51dd 100644 --- a/module/plugins/hoster/ShareonlineBiz.py +++ b/module/plugins/hoster/ShareonlineBiz.py @@ -5,10 +5,12 @@ import re from base64 import b64decode import hashlib import random -from time import sleep +from time import time, sleep -from module.plugins.Hoster import Hoster, chunks +from module.plugins.Hoster import Hoster from module.network.RequestFactory import getURL +from module.plugins.Plugin import chunks +from module.plugins.ReCaptcha import ReCaptcha as _ReCaptcha def getInfo(urls): api_url_base = "http://api.share-online.biz/linkcheck.php" @@ -32,14 +34,21 @@ def getInfo(urls): result.append((fields[2], int(fields[3]), status, chunk[i])) yield result +#suppress ocr plugin +class ReCaptcha(_ReCaptcha): + def result(self, server, challenge): + return self.plugin.decryptCaptcha("%simage"%server, get={"c":challenge}, cookies=True, forceUser=True, imgtype="jpg") + class ShareonlineBiz(Hoster): __name__ = "ShareonlineBiz" __type__ = "hoster" __pattern__ = r"http://[\w\.]*?(share\-online\.biz|egoshare\.com)/(download.php\?id\=|dl/)[\w]+" - __version__ = "0.22" + __version__ = "0.33" __description__ = """Shareonline.biz Download Hoster""" - __author_name__ = ("spoob", "mkaay") - __author_mail__ = ("spoob@pyload.org", "mkaay@mkaay.de") + __author_name__ = ("spoob", "mkaay", "zoidberg") + __author_mail__ = ("spoob@pyload.org", "mkaay@mkaay.de", "zoidberg@mujmail.cz") + + ERROR_INFO_PATTERN = r'<p class="b">Information:</p>\s*<div>\s*<strong>(.*?)</strong>' def setup(self): # range request not working? @@ -48,21 +57,29 @@ class ShareonlineBiz(Hoster): self.file_id = re.search(r"(id\=|/dl/)([a-zA-Z0-9]+)", self.pyfile.url).group(2) self.pyfile.url = "http://www.share-online.biz/dl/" + self.file_id - self.multiDL = False - self.chunkLimit = 1 - if self.premium: - self.multiDL = True - - def process(self, pyfile): - self.downloadAPIData() - pyfile.name = self.api_data["filename"] - pyfile.sync() + self.resumeDownload = self.multiDL = self.premium + #self.chunkLimit = 1 + self.check_data = None + + def process(self, pyfile): if self.premium: self.handleAPIPremium() - #self.handleWebsitePremium() + #web-download fallback removed - didn't work anyway else: self.handleFree() + + """ + check = self.checkDownload({"failure": re.compile(self.ERROR_INFO_PATTERN)}) + if check == "failure": + try: + self.retry(reason = self.lastCheck.group(1).decode("utf8")) + except: + self.retry(reason = "Unknown error") + """ + + if self.api_data: + self.check_data = {"size": int(self.api_data['size']), "md5": self.api_data['md5']} def downloadAPIData(self): api_url_base = "http://api.share-online.biz/linkcheck.php?md5=1" @@ -76,101 +93,98 @@ class ShareonlineBiz(Hoster): self.offline() self.api_data["filename"] = fields[2] self.api_data["size"] = fields[3] # in bytes - self.api_data["checksum"] = fields[4].strip().lower().replace("\n\n", "") # md5 + self.api_data["md5"] = fields[4].strip().lower().replace("\n\n", "") # md5 - def handleFree(self): - self.resumeDownload = False + def handleFree(self): + self.downloadAPIData() + self.pyfile.name = self.api_data["filename"] + self.pyfile.size = int(self.api_data["size"]) - self.html = self.load(self.pyfile.url) #refer, stuff - self.html = self.load("%s/free/" % self.pyfile.url, post={"dl_free":"1", "choice": "free"}) - if re.search(r"/failure/full/1", self.req.lastEffectiveURL): - self.setWait(120) - self.log.info("%s: no free slots, waiting 120 seconds" % self.__name__) - self.wait() - self.retry(max_tries=60) + self.html = self.load(self.pyfile.url, cookies = True) #refer, stuff + self.setWait(3) + self.wait() + + self.html = self.load("%s/free/" % self.pyfile.url, post={"dl_free":"1", "choice": "free"}, decode = True) + self.checkErrors() - if "Captcha number error or expired" in self.html: - captcha = self.decryptCaptcha("http://www.share-online.biz/captcha.php", get={"rand":"0.%s" % random.randint(10**15,10**16)}) + found = re.search(r'var wait=(\d+);', self.html) - self.log.debug("%s Captcha: %s" % (self.__name__, captcha)) - sleep(3) - - self.html = self.load(self.pyfile.url, post={"captchacode": captcha}) + recaptcha = ReCaptcha(self) + for i in range(5): + challenge, response = recaptcha.challenge("6LdatrsSAAAAAHZrB70txiV5p-8Iv8BtVxlTtjKX") + self.setWait(int(found.group(1)) if found else 30) + response = self.load("%s/free/captcha/%d" % (self.pyfile.url, int(time() * 1000)), post = { + 'dl_free': '1', + 'recaptcha_challenge_field': challenge, + 'recaptcha_response_field': response}) - if r"Der Download ist Ihnen zu langsam" not in self.html and r"The download is too slow for you" not in self.html: - self.fail("Plugin defect. Save dumps and report.") - - if "Kein weiterer Download-Thread möglich!" in self.html: #TODO corresponding translation - self.retry(wait_time=30, reason=_("Parallel download issue")) + if not response == '0': + break - m = re.search("var wait=(\d+);", self.html[1]) - wait_time = int(m.group(1)) if m else 30 - self.setWait(wait_time) - self.log.debug("%s: Waiting %d seconds." % (self.__name__, wait_time)) - self.wait() + else: self.fail("No valid captcha solution received") - file_url_pattern = r'var\sdl="(.*?)"' - download_url = b64decode(re.search(file_url_pattern, self.html).group(1)) + download_url = response.decode("base64") + self.logDebug(download_url) + if not download_url.startswith("http://"): + self.parseError("download url") + self.wait() self.download(download_url) - - check = self.checkDownload({"invalid" : "Dieses Download-Ticket ist ungültig!", - "error" : "Es ist ein unbekannter Fehler aufgetreten"}) - if check == "invalid": - self.retry(reason=_("Invalid download ticket")) - elif check == "error": - self.fail(reason=_("ShareOnline internal problems")) - - def handleAPIPremium(self): #should be working better - self.resumeDownload = True - - info = self.account.getUserAPI(self.req) - if info["dl"].lower() == "not_available": - self.fail("DL API error") - self.req.cj.setCookie("share-online.biz", "dl", info["dl"]) - - + def checkErrors(self): + found = re.search(r"/failure/(.*?)/1", self.req.lastEffectiveURL) + if found: + err = found.group(1) + found = re.search(self.ERROR_INFO_PATTERN, self.html) + msg = found.group(1) if found else "" + self.logError(err, msg or "Unknown error occurred") + + if err in ('freelimit', 'size', 'proxy'): + self.fail(msg or "Premium account needed") + if err in ('invalid'): + self.fail(msg or "File not available") + elif err in ('server'): + self.setWait(600, False) + elif err in ('expired'): + self.setWait(30, False) + else: + self.setWait(300, True) + + self.wait() + self.retry(max_tries=25, reason = msg) + + def handleAPIPremium(self): #should be working better + self.account.getAccountInfo(self.user, True) src = self.load("http://api.share-online.biz/account.php?username=%s&password=%s&act=download&lid=%s" % (self.user, self.account.accounts[self.user]["password"], self.file_id), post={}) - dlinfo = {} + self.api_data = dlinfo = {} for line in src.splitlines(): key, value = line.split(": ") dlinfo[key.lower()] = value - if not dlinfo["status"].lower() == "online": + self.logDebug(dlinfo) + if not dlinfo["status"] == "online": self.offline() + self.pyfile.name = dlinfo["name"] + self.pyfile.size = int(dlinfo["size"]) + dlLink = dlinfo["url"] - if dlLink.startswith("/_dl.php"): - self.log.debug("got invalid downloadlink, falling back") - self.handleWebsitePremium() + if dlLink == "server_under_maintenance": + self.tempoffline() else: self.download(dlLink) - def handleWebsitePremium(self): #seems to be buggy - self.resumeDownload = False - - self.html = self.load(self.pyfile.url) - if r"Die Nummer ist leider nicht richtig oder ausgelaufen!" in self.html: - self.retry() - - try: - download_url = re.search('loadfilelink\.decode\("(.*?)"\);', self.html, re.S).group(1) - except: - self.fail("Session issue") - - self.download(download_url) - def checksum(self, local_file): - if self.api_data and self.api_data["checksum"]: + if self.api_data and "md5" in self.api_data and self.api_data["md5"]: h = hashlib.md5() f = open(local_file, "rb") h.update(f.read()) f.close() hexd = h.hexdigest() - if hexd == self.api_data["checksum"]: + if hexd == self.api_data["md5"]: return True, 0 else: return False, 1 else: + self.logWarning("MD5 checksum missing") return True, 5 diff --git a/module/plugins/hoster/ShragleCom.py b/module/plugins/hoster/ShragleCom.py index 9ebf4917b..8fe05a2b9 100644 --- a/module/plugins/hoster/ShragleCom.py +++ b/module/plugins/hoster/ShragleCom.py @@ -2,84 +2,105 @@ # -*- coding: utf-8 -*- import re -import time +from pycurl import FOLLOWLOCATION from module.plugins.Hoster import Hoster +from module.plugins.internal.SimpleHoster import parseHtmlForm +from module.plugins.ReCaptcha import ReCaptcha +from module.network.RequestFactory import getURL + +API_KEY = "078e5ca290d728fd874121030efb4a0d" + +def parseFileInfo(self, url): + file_id = re.match(self.__pattern__, url).group('ID') + + data = getURL( + "http://www.cloudnator.com/api.php?key=%s&action=getStatus&fileID=%s" % (API_KEY, file_id), + decode = True + ).split() + + if len(data) == 4: + name, size, md5, status = data + size = int(size) + + if hasattr(self, "check_data"): + self.checkdata = {"size": size, "md5": md5} + + return name, size, 2 if status == "0" else 1, url + else: + return url, 0, 1, url + +def getInfo(urls): + for url in urls: + file_info = parseFileInfo(plugin, url) + yield file_info class ShragleCom(Hoster): __name__ = "ShragleCom" __type__ = "hoster" - __pattern__ = r"http://(?:www.)?shragle.com/files/" - __version__ = "0.1" - __description__ = """Shragle Download PLugin""" - __author_name__ = ("RaNaN") - __author_mail__ = ("RaNaN@pyload.org") + __pattern__ = r"http://(?:www.)?(cloudnator|shragle).com/files/(?P<ID>.*?)/" + __version__ = "0.20" + __description__ = """Cloudnator.com (Shragle.com) Download PLugin""" + __author_name__ = ("RaNaN", "zoidberg") + __author_mail__ = ("RaNaN@pyload.org", "zoidberg@mujmail.cz") def setup(self): self.html = None self.multiDL = False + self.check_data = None def process(self, pyfile): - self.pyfile = pyfile - - if not self.file_exists(): + #get file status and info + self.pyfile.name, self.pyfile.size, status = parseFileInfo(self, pyfile.url)[:3] + if status != 2: self.offline() - - self.pyfile.name = self.get_file_name() - self.setWait(self.get_waiting_time()) - self.wait() + self.handleFree() - self.proceed(self.get_file_url()) - - def get_waiting_time(self): - if self.html is None: - self.download_html() - - timestring = re.search('\s*var\sdownloadWait\s=\s(\d*);', self.html) - if timestring: - return int(timestring.group(1)) - else: - return 10 - - def download_html(self): + def handleFree(self): self.html = self.load(self.pyfile.url) - - def get_file_url(self): - """ returns the absolute downloadable filepath - """ - if self.html is None: - self.download_html() - - self.fileID = re.search(r'name="fileID"\svalue="(.*?)"', self.html).group(1) - self.dlSession = re.search(r'name="dlSession"\svalue="(.*?)"', self.html).group(1) - self.userID = re.search(r'name="userID"\svalue="(.*?)"', self.html).group(1) - self.password = re.search(r'name="password"\svalue="(.*?)"', self.html).group(1) - self.lang = re.search(r'name="lang"\svalue="(.*?)"', self.html).group(1) - return re.search(r'id="download"\saction="(.*?)"', self.html).group(1) - - def get_file_name(self): - if self.html is None: - self.download_html() - - #file_name_pattern = r'You want to download \xc2\xbb<strong>(.*?)</strong>\xc2\xab' - file_name_pattern = r'<h2 class="colorgrey center" style="overflow:hidden;width:1000px;"> (.*)<br /><span style="font-size:12px;font-weight:normal; width:100px;"> ([\d\.]*) MB</span></h2>' - res = re.search(file_name_pattern, self.html) - if res: - return res.group(1) - else: - self.fail("filename cant be extracted") - - def file_exists(self): - """ returns True or False - """ - if self.html is None: - self.download_html() - - if re.search(r"html", self.html) is None: - return False + + #get wait time + found = re.search('\s*var\sdownloadWait\s=\s(\d+);', self.html) + self.setWait(int(found.group(1)) if found else 30) + + #parse download form + action, inputs = parseHtmlForm('id="download', self.html) + + #solve captcha + found = re.search('recaptcha/api/(?:challenge|noscript)?k=(.+?)', self.html) + captcha_key = found.group(1) if found else "6LdEFb0SAAAAAAwM70vnYo2AkiVkCx-xmfniatHz" + + recaptcha = ReCaptcha(self) + + inputs['recaptcha_challenge_field'], inputs['recaptcha_response_field'] = recaptcha.challenge(captcha_key) + self.wait() + + #validate + self.req.http.c.setopt(FOLLOWLOCATION, 0) + self.html = self.load(action, post = inputs) + + found = re.search(r"Location\s*:\s*(\S*)", self.req.http.header, re.I) + if found: + self.correctCaptcha() + download_url = found.group(1) else: - return True - - def proceed(self, url): - self.download(url, post={'fileID': self.fileID, 'dlSession': self.dlSession, 'userID': self.userID, 'password': self.password, 'lang': self.lang}) + if "Sicherheitscode falsch" in self.html: + self.invalidCaptcha() + self.retry(max_tries = 5, reason = "Invalid captcha") + else: + self.fail("Invalid session") + + #download + self.req.http.c.setopt(FOLLOWLOCATION, 1) + self.download(download_url) + + check = self.checkDownload({ + "ip_blocked": re.compile(r'<div class="error".*IP.*loading') + }) + if check == "ip_blocked": + self.setWait(1800, True) + self.wait() + self.retry() + +
\ No newline at end of file diff --git a/module/plugins/hoster/StahnuTo.py b/module/plugins/hoster/StahnuTo.py index a78615dba..354a99b1a 100644 --- a/module/plugins/hoster/StahnuTo.py +++ b/module/plugins/hoster/StahnuTo.py @@ -32,29 +32,32 @@ def getInfo(urls): class StahnuTo(SimpleHoster): __name__ = "StahnuTo" __type__ = "hoster" - __pattern__ = r"http://(\w*\.)?stahnu.to/(files/get/|.*\?file=)([^/]+).*" - __version__ = "0.12" + __pattern__ = r"http://(?:\w*\.)?stahnu.to/(?:files/get/|.*\?file=)(?P<ID>[^/]+).*" + __version__ = "0.14" __description__ = """stahnu.to""" __author_name__ = ("zoidberg") - FILE_NAME_PATTERN = r"<div class='nadpis-01'><h2>(?<N>[^<]+)</h2></div>" - FILE_SIZE_PATTERN = r'<td>Velikost souboru<br /><span>(?<S>[^<]+)\s*(?<U>[kKMG])i?[Bb]</span></td>' + FILE_NAME_PATTERN = r"<td colspan='2'>Název souboru<br /><span>(?P<N>[^<]+)</span>" + FILE_SIZE_PATTERN = r'<td>Velikost souboru<br /><span>(?P<S>[^<]+)\s*(?P<U>[kKMG])i?[Bb]</span></td>' FILE_OFFLINE_PATTERN = r'<!-- Obsah - start -->\s*<!-- Obsah - end -->' - #FILE_OFFLINE_PATTERN = r'<h2 align="center">Tento soubor neexistuje nebo byl odstraněn! </h2>' - CAPTCHA_PATTERN = r'<img src="captcha/captcha.php" id="captcha" /></td>' def setup(self): self.multiDL = True def process(self, pyfile): + if not self.account: + self.fail("Please enter your stahnu.to account") + found = re.search(self.__pattern__, pyfile.url) - file_id = found.group(3) + file_id = found.group(1) - self.html = self.load("http://stahnu.to/?file=" + file_id, decode=True) + self.html = self.load("http://www.stahnu.to/getfile.php?file=%s" % file_id, decode=True) self.getFileInfo() + + if "K stažení souboru se musíte <strong>zdarma</strong> přihlásit!" in self.html: + self.account.relogin(self.user) + self.retry() - self.download("http://stahnu.to/files/gen/" + file_id, post={ - "file": file_id, - "user": "Anonym", - "commenttext": "" + self.download("http://www.stahnu.to/files/gen/" + file_id, post={ + "downloadbutton": u"STÁHNOUT" }) diff --git a/module/plugins/hoster/TurbobitNet.py b/module/plugins/hoster/TurbobitNet.py new file mode 100644 index 000000000..b3b01c92b --- /dev/null +++ b/module/plugins/hoster/TurbobitNet.py @@ -0,0 +1,169 @@ +# -*- coding: utf-8 -*- +""" + Copyright (C) 2012 pyLoad team + Copyright (C) 2012 JD-Team support@jdownloader.org + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <http://www.gnu.org/licenses/>. + + @author: zoidberg +""" + +import re +import random +from urllib import quote +from binascii import hexlify, unhexlify +from Crypto.Cipher import ARC4 + +from module.network.RequestFactory import getURL +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo, timestamp +from module.plugins.ReCaptcha import ReCaptcha + +from pycurl import HTTPHEADER + +class TurbobitNet(SimpleHoster): + __name__ = "TurbobitNet" + __type__ = "hoster" + __pattern__ = r"http://(?:\w*\.)?(turbobit.net|unextfiles.com)/(?:download/free/)?(?P<ID>\w+).*" + __version__ = "0.07" + __description__ = """Turbobit.net plugin""" + __author_name__ = ("zoidberg") + __author_mail__ = ("zoidberg@mujmail.cz") + + FILE_INFO_PATTERN = r"<span class='file-icon1[^>]*>(?P<N>[^<]+)</span>\s*\((?P<S>[^\)]+)\)\s*</h1>" #long filenames are shortened + FILE_NAME_PATTERN = r'<meta name="keywords" content="\s+(?P<N>[^,]+)' #full name but missing on page2 + FILE_OFFLINE_PATTERN = r'<h2>File Not Found</h2>|html\(\'File was not found' + FILE_URL_REPLACEMENTS = [(r"http://(?:\w*\.)?(turbobit.net|unextfiles.com)/(?:download/free/)?(?P<ID>\w+).*", "http://turbobit.net/\g<ID>.html")] + SH_COOKIES = [("turbobit.net", "user_lang", "en")] + + CAPTCHA_KEY_PATTERN = r'src="http://api\.recaptcha\.net/challenge\?k=([^"]+)"' + DOWNLOAD_URL_PATTERN = r'(?P<url>/download/redirect/[^"\']+)' + LIMIT_WAIT_PATTERN = r'<div id="time-limit-text">\s*.*?<span id=\'timeout\'>(\d+)</span>' + CAPTCHA_SRC_PATTERN = r'<img alt="Captcha" src="(.*?)"' + + def handleFree(self): + self.url = "http://turbobit.net/download/free/%s" % self.file_info['ID'] + self.html = self.load(self.url) + + rtUpdate = self.getRtUpdate() + + self.solveCaptcha() + self.req.http.c.setopt(HTTPHEADER, ["X-Requested-With: XMLHttpRequest"]) + self.url = self.getDownloadUrl(rtUpdate) + + self.wait() + self.html = self.load(self.url) + self.req.http.c.setopt(HTTPHEADER, ["X-Requested-With:"]) + self.downloadFile() + + def solveCaptcha(self): + for i in range(5): + found = re.search(self.LIMIT_WAIT_PATTERN, self.html) + if found: + wait_time = int(found.group(1)) + self.setWait(wait_time, wait_time > 60) + self.wait() + self.retry() + + action, inputs = self.parseHtmlForm("action='#'") + if not inputs: self.parseError("captcha form") + self.logDebug(inputs) + + if inputs['captcha_type'] == 'recaptcha': + recaptcha = ReCaptcha(self) + found = re.search(self.CAPTCHA_KEY_PATTERN, self.html) + captcha_key = found.group(1) if found else '6LcTGLoSAAAAAHCWY9TTIrQfjUlxu6kZlTYP50_c' + inputs['recaptcha_challenge_field'], inputs['recaptcha_response_field'] = recaptcha.challenge(captcha_key) + else: + found = re.search(self.CAPTCHA_SRC_PATTERN, self.html) + if not found: self.parseError('captcha') + captcha_url = found.group(1) + inputs['captcha_response'] = self.decryptCaptcha(captcha_url) + + self.logDebug(inputs) + self.html = self.load(self.url, post = inputs) + + if not "<div class='download-timer-header'>" in self.html: + self.invalidCaptcha() + else: + self.correctCaptcha() + break + else: self.fail("Invalid captcha") + + def getRtUpdate(self): + rtUpdate = self.getStorage("rtUpdate") + if not rtUpdate: + if self.getStorage("version") != self.__version__ or int(self.getStorage("timestamp", 0)) + 86400000 < timestamp(): + # that's right, we are even using jdownloader updates + rtUpdate = getURL("http://update0.jdownloader.org/pluginstuff/tbupdate.js") + rtUpdate = self.decrypt(rtUpdate.splitlines()[1]) + # but we still need to fix the syntax to work with other engines than rhino + rtUpdate = re.sub(r'for each\(var (\w+) in(\[[^\]]+\])\)\{',r'zza=\2;for(var zzi=0;zzi<zza.length;zzi++){\1=zza[zzi];',rtUpdate) + rtUpdate = re.sub(r"for\((\w+)=",r"for(var \1=", rtUpdate) + + self.logDebug("rtUpdate") + self.setStorage("rtUpdate", rtUpdate) + self.setStorage("timestamp", timestamp()) + self.setStorage("version", self.__version__) + else: + self.logError("Unable to download, wait for update...") + self.tempOffline() + + return rtUpdate + + def getDownloadUrl(self, rtUpdate): + self.req.http.lastURL = self.url + + found = re.search("(/\w+/timeout\.js\?\w+=)([^\"\'<>]+)", self.html) + url = "http://turbobit.net%s%s" % (found.groups() if found else ('/files/timeout.js?ver=', ''.join(random.choice('0123456789ABCDEF') for x in range(32)))) + fun = self.load(url) + + self.setWait(65, False) + + for b in [1,3]: + self.jscode = "var id = \'%s\';var b = %d;var inn = \'%s\';%sout" % (self.file_info['ID'], b, quote(fun), rtUpdate) + + try: + out = self.js.eval(self.jscode) + 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() + + def decrypt(self, data): + cipher = ARC4.new(hexlify('E\x15\xa1\x9e\xa3M\xa0\xc6\xa0\x84\xb6H\x83\xa8o\xa0')) + return unhexlify(cipher.encrypt(unhexlify(data))) + + def getLocalTimeString(): + lt = time.localtime() + tz = time.altzone if lt.tm_isdst else time.timezone + return "%s GMT%+03d%02d" % (time.strftime("%a %b %d %Y %H:%M:%S", lt), -tz // 3600, tz % 3600) + + def handlePremium(self): + self.logDebug("Premium download as user %s" % self.user) + self.downloadFile() + + def downloadFile(self): + found = re.search(self.DOWNLOAD_URL_PATTERN, self.html) + if not found: self.parseError("download link") + self.url = "http://turbobit.net" + found.group('url') + self.logDebug(self.url) + self.download(self.url) + +getInfo = create_getInfo(TurbobitNet)
\ No newline at end of file diff --git a/module/plugins/hoster/TwoSharedCom.py b/module/plugins/hoster/TwoSharedCom.py index 89c4b7781..8401e0cb0 100644 --- a/module/plugins/hoster/TwoSharedCom.py +++ b/module/plugins/hoster/TwoSharedCom.py @@ -8,15 +8,18 @@ class TwoSharedCom(SimpleHoster): __name__ = "TwoSharedCom" __type__ = "hoster" __pattern__ = r"http://[\w\.]*?2shared.com/(account/)?(download|get|file|document|photo|video|audio)/.*" - __version__ = "0.10" + __version__ = "0.11" __description__ = """2Shared Download Hoster""" __author_name__ = ("zoidberg") __author_mail__ = ("zoidberg@mujmail.cz") - FILE_NAME_PATTERN = r'<meta name="Description" content="(?P<N>.*) download free at 2shared' + FILE_NAME_PATTERN = r'<h1>(?P<N>.*)</h1>' FILE_SIZE_PATTERN = r'<span class="dtitle">File size:</span>\s*(?P<S>[0-9,.]+) (?P<U>[kKMG])i?B' FILE_OFFLINE_PATTERN = r'The file link that you requested is not valid\.|This file was deleted\.' DOWNLOAD_URL_PATTERN = r"window.location ='([^']+)';" + + def setup(self): + self.resumeDownload = self.multiDL = True def handleFree(self): found = re.search(self.DOWNLOAD_URL_PATTERN, self.html) diff --git a/module/plugins/hoster/UlozTo.py b/module/plugins/hoster/UlozTo.py index 6b699e39f..cf2f09311 100644 --- a/module/plugins/hoster/UlozTo.py +++ b/module/plugins/hoster/UlozTo.py @@ -21,116 +21,137 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo def convertDecimalPrefix(m): # decimal prefixes used in filesize and traffic - return ("%%.%df" % {'k':3,'M':6,'G':9}[m.group(2)] % float(m.group(1))).replace('.','') + return ("%%.%df" % {'k':3,'M':6,'G':9}[m.group(2)] % float(m.group(1))).replace('.','') class UlozTo(SimpleHoster): __name__ = "UlozTo" __type__ = "hoster" - __pattern__ = r"http://(\w*\.)?(uloz\.to|ulozto\.(cz|sk|net)|bagruj.cz|zachowajto.pl)/.*" - __version__ = "0.81" + __pattern__ = r"http://(\w*\.)?(uloz\.to|ulozto\.(cz|sk|net)|bagruj.cz|zachowajto.pl)/(?:live/)?(?P<id>\w+/[^/?]*)" + __version__ = "0.89" __description__ = """uloz.to""" __author_name__ = ("zoidberg") - FILE_NAME_PATTERN = r'<a share_url="[^&]*&t=(?P<N>[^"]+)"' - #FILE_NAME_PATTERN = r'<h2 class="nadpis" style="margin-left:196px;"><a href="[^"]+">(?P<N>[^<]+)</a></h2>' - FILE_SIZE_PATTERN = r'<div class="info_velikost" style="top:-55px;">\s*<div>[^<]*\s+(?P<S>[0-9.]+\s[kMG]B)\s*</div>\s*</div>' - FILE_SIZE_REPLACEMENTS = [('([0-9.]+)\s([kMG])B', convertDecimalPrefix)] - FILE_OFFLINE_PATTERN = r'http://www.uloz.to/(neexistujici|smazano|nenalezeno)' - - PASSWD_PATTERN = r'<input type="password" class="text" name="file_password" id="frmfilepasswordForm-file_password" />' - VIPLINK_PATTERN = r'<a href="[^"]*\?disclaimer=1" class="linkVip">' - FREE_URL_PATTERN = r'<form name="dwn" action="([^"]+)"' - PREMIUM_URL_PATTERN = r'<a onclick[^>]*href="([^"]+)[^>]*class="linkVip"' - CAPTCHA_PATTERN = r'<img style=".*src="([^"]+)" alt="Captcha" class="captcha"' - CAPTCHA_NB_PATTERN = r'<input class="captcha_nb" type="hidden" name="captcha_nb" value="([0-9]+)" >' + FILE_NAME_PATTERN = r'<a href="#download" class="jsShowDownload">(?P<N>[^<]+)</a>' + FILE_SIZE_PATTERN = r'<span id="fileSize">.*?(?P<S>[0-9.]+\s[kMG]B)</span>' + FILE_INFO_PATTERN = r'<p>File <strong>(?P<N>[^<]+)</strong> is password protected</p>' + FILE_OFFLINE_PATTERN = r'<title>404 - Page not found</title>|<h1 class="h1">File (has been deleted|was banned)</h1>' + FILE_SIZE_REPLACEMENTS = [('([0-9.]+)\s([kMG])B', convertDecimalPrefix)] + FILE_URL_REPLACEMENTS = [(r"(?<=http://)([^/]+)", "www.ulozto.net")] + + PASSWD_PATTERN = r'<div class="passwordProtectedFile">' + VIPLINK_PATTERN = r'<a href="[^"]*\?disclaimer=1" class="linkVip">' + FREE_URL_PATTERN = r'<div class="freeDownloadForm"><form action="([^"]+)"' + PREMIUM_URL_PATTERN = r'<div class="downloadForm"><form action="([^"]+)"' + + def setup(self): + self.multiDL = self.premium + self.resumeDownload = True def process(self, pyfile): - # check file online - header = self.load(pyfile.url, just_header=True) - if "location" in header: - self.logDebug('LOCATION: ' + header['location']) - if "utm_source=old" in header['location'] or re.search(self.FILE_OFFLINE_PATTERN, header['location']): - self.offline() - - self.html = self.load(pyfile.url, decode=True) - - # password protected links - passwords = self.getPassword().splitlines() + pyfile.url = re.sub(r"(?<=http://)([^/]+)", "www.ulozto.net", pyfile.url) + self.html = self.load(pyfile.url, decode = True, cookies = True) + + passwords = self.getPassword().splitlines() while self.PASSWD_PATTERN in self.html: if passwords: password = passwords.pop(0) self.logInfo("Password protected link, trying " + password) - self.html = self.load(pyfile.url, get = {"do": "filepasswordForm-submit"}, post={"file_password": password, "fpwdsend": 'Odeslat'}, cookies=True) + self.html = self.load(pyfile.url, get = {"do": "passwordProtectedForm-submit"}, + post={"password": password, "password_send": 'Send'}, cookies=True) else: self.fail("No or incorrect password") - - self.file_info = self.getFileInfo() - - # adult content + if re.search(self.VIPLINK_PATTERN, self.html): self.html = self.load(pyfile.url, get={"disclaimer": "1"}) - + + self.file_info = self.getFileInfo() + if self.premium and self.checkTrafficLeft(): self.handlePremium() - else: + else: self.handleFree() - def handleFree(self): - parsed_url = self.findDownloadURL(premium=False) + self.doCheckDownload() + def handleFree(self): + action, inputs = self.parseHtmlForm('id="frm-downloadDialog-freeDownloadForm"') + if not action or not inputs: + self.parseError("free download form") + # get and decrypt captcha - captcha = self.getStorage("captchaUser") - captcha_nb = self.getStorage("captchaNb") - captcha_url = "DUMMY" - - if not captcha or not captcha_nb: - found = re.search(self.CAPTCHA_PATTERN, self.html) - if not found: self.parseError("CAPTCHA") - captcha_url = found.group(1) - - found = re.search(self.CAPTCHA_NB_PATTERN, self.html) - if not found: self.parseError("CAPTCHA_NB") - captcha_nb = found.group(1) - - captcha = self.decryptCaptcha(captcha_url) + captcha_id_field = captcha_text_field = None + captcha_id = captcha_text = None - self.log.debug('CAPTCHA_URL:' + captcha_url + ' CAPTCHA:' + captcha + ' CAPTCHA_NB:' + captcha_nb) + for key in inputs.keys(): + found = re.match("captcha.*(id|text|value)", key) + if found: + if found.group(1) == "id": + captcha_id_field = key + else: + captcha_text_field = key + + if not captcha_id_field or not captcha_text_field: + self.parseError("CAPTCHA form changed") + + """ + captcha_id = self.getStorage("captcha_id") + captcha_text = self.getStorage("captcha_text") + + if not captcha_id or not captcha_text: + """ + captcha_id = inputs[captcha_id_field] + captcha_text = self.decryptCaptcha("http://img.uloz.to/captcha/%s.png" % captcha_id) - # download and check - self.download(parsed_url, post={"captcha_user": captcha, "captcha_nb": captcha_nb}, cookies=True) - self.doCheckDownload() + self.log.debug(' CAPTCHA ID:' + captcha_id + ' CAPTCHA TEXT:' + captcha_text) - self.setStorage("captchaUser", captcha) - self.setStorage("captchaNb", captcha_nb) - - def handlePremium(self): - parsed_url = self.findDownloadURL(premium=True) - self.download(parsed_url) - self.doCheckDownload() + """ + self.setStorage("captcha_id", captcha_id) + self.setStorage("captcha_text", captcha_text) + """ + self.multiDL = True + + inputs.update({captcha_id_field: captcha_id, captcha_text_field: captcha_text}) + self.download("http://www.ulozto.net" + action, post=inputs, cookies=True) + + def handlePremium(self): + self.download(self.pyfile.url + "?do=directDownload") + #parsed_url = self.findDownloadURL(premium=True) + #self.download(parsed_url, post={"download": "Download"}) + def findDownloadURL(self, premium=False): msg = "%s link" % ("Premium" if premium else "Free") found = re.search(self.PREMIUM_URL_PATTERN if premium else self.FREE_URL_PATTERN, self.html) if not found: self.parseError(msg) - parsed_url = found.group(1) + parsed_url = "http://www.ulozto.net" + found.group(1) self.logDebug("%s: %s" % (msg, parsed_url)) return parsed_url - + def doCheckDownload(self): check = self.checkDownload({ - "wrong_captcha": re.compile(self.CAPTCHA_PATTERN), + "wrong_captcha": re.compile(r'<ul class="error">\s*<li>Error rewriting the text.</li>'), "offline": re.compile(self.FILE_OFFLINE_PATTERN), - "passwd": self.PASSWD_PATTERN + "passwd": self.PASSWD_PATTERN, + "server_error": 'src="http://img.ulozto.cz/error403/vykricnik.jpg"', #paralell dl, server overload etc. + "not_found": "<title>Ulož.to</title>" }) if check == "wrong_captcha": - self.delStorage("captchaUser") - self.delStorage("captchaNb") + self.delStorage("captcha_id") + self.delStorage("captcha_text") self.invalidCaptcha() self.retry(reason="Wrong captcha code") elif check == "offline": self.offline() elif check == "passwd": self.fail("Wrong password") + elif check == "server_error": + self.logError("Server error, try downloading later") + self.multiDL = False + self.setWait(3600, True) + self.wait() + self.retry() + elif check == "not_found": + self.fail("Server error - file not downloadable") -getInfo = create_getInfo(UlozTo)
\ No newline at end of file +getInfo = create_getInfo(UlozTo)
\ No newline at end of file diff --git a/module/plugins/hoster/UnibytesCom.py b/module/plugins/hoster/UnibytesCom.py new file mode 100644 index 000000000..3c8552271 --- /dev/null +++ b/module/plugins/hoster/UnibytesCom.py @@ -0,0 +1,80 @@ +# -*- coding: utf-8 -*- +""" + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <http://www.gnu.org/licenses/>. + + @author: zoidberg +""" + +import re +from pycurl import FOLLOWLOCATION +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo + +class UnibytesCom(SimpleHoster): + __name__ = "UnibytesCom" + __type__ = "hoster" + __pattern__ = r"http://(www\.)?unibytes\.com/[a-zA-Z0-9-._ ]{11}B" + __version__ = "0.1" + __description__ = """UniBytes.com""" + __author_name__ = ("zoidberg") + + FILE_INFO_PATTERN = r'<span[^>]*?id="fileName"[^>]*>(?P<N>[^>]+)</span>\s*\((?P<S>\d.*?)\)' + DOMAIN = 'http://www.unibytes.com' + + WAIT_PATTERN = r'Wait for <span id="slowRest">(\d+)</span> sec' + DOWNLOAD_LINK_PATTERN = r'<a href="([^"]+)">Download</a>' + + def handleFree(self): + action, post_data = self.parseHtmlForm('id="startForm"') + self.req.http.c.setopt(FOLLOWLOCATION, 0) + + for i in range(8): + self.logDebug(action, post_data) + self.html = self.load(self.DOMAIN + action, post = post_data) + + found = re.search(r'location:\s*(\S+)', self.req.http.header, re.I) + if found: + url = found.group(1) + break + + if '>Somebody else is already downloading using your IP-address<' in self.html: + self.setWait(600, True) + self.wait() + self.retry() + + if post_data['step'] == 'last': + found = re.search(self.DOWNLOAD_LINK_PATTERN, self.html) + if found: + url = found.group(1) + self.correctCaptcha() + break + else: + self.invalidCaptcha() + + last_step = post_data['step'] + action, post_data = self.parseHtmlForm('id="stepForm"') + + if last_step == 'timer': + found = re.search(self.WAIT_PATTERN, self.html) + self.setWait(int(found.group(1)) if found else 60, False) + self.wait() + elif last_step in ('captcha', 'last'): + post_data['captcha'] = self.decryptCaptcha(self.DOMAIN + '/captcha.jpg') + else: + self.fail("No valid captcha code entered") + + self.logDebug('Download link: ' + url) + self.req.http.c.setopt(FOLLOWLOCATION, 1) + self.download(url) + +getInfo = create_getInfo(UnibytesCom)
\ No newline at end of file diff --git a/module/plugins/hoster/UploadStationCom.py b/module/plugins/hoster/UploadStationCom.py index fea5f4245..d24682e4d 100644 --- a/module/plugins/hoster/UploadStationCom.py +++ b/module/plugins/hoster/UploadStationCom.py @@ -1,141 +1,21 @@ # -*- coding: utf-8 -*-
-from __future__ import with_statement
+from module.plugins.hoster.FileserveCom import FileserveCom, checkFile
+from module.plugins.Plugin import chunks
-from module.network.RequestFactory import getURL
-from module.plugins.Hoster import Hoster
-from module.plugins.ReCaptcha import ReCaptcha
-
-import re
-
-def getInfo(urls):
- yield [(url, 0, 1, url) for url in urls]
-
-class UploadStationCom(Hoster):
+class UploadStationCom(FileserveCom):
__name__ = "UploadStationCom"
__type__ = "hoster"
- __pattern__ = r"http://(www\.)?uploadstation\.com/file/(?P<id>[A-Za-z0-9]+)"
- __version__ = "0.33"
+ __pattern__ = r"http://(?:www\.)?uploadstation\.com/file/(?P<id>[A-Za-z0-9]+)"
+ __version__ = "0.51"
__description__ = """UploadStation.Com File Download Hoster"""
- __author_name__ = ("fragonib")
- __author_mail__ = ("fragonib[AT]yahoo[DOT]es")
-
- FILE_OFFLINE_PATTERN = r'''<h1>File not available</h1>|<h1>File is not available</h1>'''
- FILE_TITLE_PATTERN = r'''<div class=\"download_item\">(.*?)</div>'''
- FILE_SIZE_PATTERN = r'''<div><span>File size: <b>(.*?) (KB|MB|GB)</b>'''
- CAPTCHA_PRESENT_TOKEN = '<div class="speedBox" id="showCaptcha" style="display:none;">'
- CAPTCHA_KEY_PATTERN = r"var reCAPTCHA_publickey='(.*?)';"
- CAPTCHA_WRONG_TOKEN = 'incorrect-captcha-sol'
- WAITING_PATTERN = r".*?(\d+).*?"
- TIME_LIMIT_TOKEN = '"fail":"timeLimit"'
- TIME_LIMIT_WAIT_PATTERN = r"You need to wait (\d+) seconds to download next file."
- DOWNLOAD_RESTRICTION_TOKEN = '"To remove download restriction, please choose your suitable plan as below</h1>"'
-
- def setup(self):
- self.multiDL = False
- self.fileId = ''
- self.html = ''
-
- def process(self, pyfile):
-
- self.fail("Hoster not longer available")
-
- # Get URL
- self.html = self.load(self.pyfile.url, ref=False, decode=True)
-
- # Is offline?
- m = re.search(UploadStationCom.FILE_OFFLINE_PATTERN, self.html)
- if m is not None:
- self.offline()
-
- # Id & Title
- self.fileId = re.search(self.__pattern__, self.pyfile.url).group('id')
- self.pyfile.name = re.search(UploadStationCom.FILE_TITLE_PATTERN, self.html).group(1)
-
- # Free account
- self.handleFree()
-
- def handleFree(self):
-
- # Not needed yet
- # pattern = r'''\"(/landing/.*?/download_captcha\.js)\"'''
- # jsPage = re.search(pattern, self.html).group(1)
- # self.jsPage = self.load("http://uploadstation.com" + jsPage)
-
- # Check download
- response = self.load(self.pyfile.url, post={"checkDownload" : "check"}, decode=True)
- self.logDebug("Checking download, response [%s]" % response.encode('ascii', 'ignore'))
- self.handleErrors(response)
-
- # We got a captcha?
- if UploadStationCom.CAPTCHA_PRESENT_TOKEN in self.html:
- id = re.search(UploadStationCom.CAPTCHA_KEY_PATTERN, self.html).group(1)
- self.logDebug("Resolving ReCaptcha with key [%s]" % id)
- recaptcha = ReCaptcha(self)
- challenge, code = recaptcha.challenge(id)
- response = self.load('http://www.uploadstation.com/checkReCaptcha.php',
- post={'recaptcha_challenge_field' : challenge,
- 'recaptcha_response_field' : code,
- 'recaptcha_shortencode_field' : self.fileId})
- self.logDebug("Result of captcha resolving [%s]" % response.encode('ascii', 'ignore'))
- self.handleCaptchaErrors(response)
-
- # Process waiting
- response = self.load(self.pyfile.url, post={"downloadLink" : "wait"})
- m = re.search(UploadStationCom.WAITING_PATTERN, response)
- if m is not None:
- wait = int(m.group(1))
- if wait == 404:
- self.logDebug("No wait time returned")
- self.fail("No wait time returned")
-
- self.logDebug("Waiting %d seconds." % wait)
- self.setWait(wait + 3)
- self.wait()
-
- # Show download link
- self.load(self.pyfile.url, post={"downloadLink" : "show"})
-
- # This may either download our file or forward us to an error page
- self.logDebug("Downloading file.")
- dl = self.download(self.pyfile.url, post={"download" : "normal"})
- self.handleDownloadedFile()
-
- def handleErrors(self, response):
-
- if UploadStationCom.TIME_LIMIT_TOKEN in response:
- wait = 300
- html = self.load(self.pyfile.url, post={"checkDownload" : "showError", "errorType" : "timeLimit"})
- m = re.search(UploadStationCom.TIME_LIMIT_WAIT_PATTERN, html)
- if m is not None:
- wait = int(m.group(1))
-
- self.logInfo("Time limit reached, waiting %d seconds." % wait)
- self.setWait(wait, True)
- self.wait()
- self.retry()
+ __author_name__ = ("fragonib", "zoidberg")
+ __author_mail__ = ("fragonib[AT]yahoo[DOT]es", "zoidberg@mujmail.cz")
- if UploadStationCom.DOWNLOAD_RESTRICTION_TOKEN in response:
- wait = 720
- self.logInfo("Free account time limit reached, waiting %d seconds." % wait)
- self.setWait(wait, True)
- self.wait()
- self.retry()
-
- def handleCaptchaErrors(self, response):
- if UploadStationCom.CAPTCHA_WRONG_TOKEN in response:
- self.logInfo("Invalid captcha response, retrying.")
- self.invalidCaptcha()
- self.retry()
- else:
- self.correctCaptcha()
-
- def handleDownloadedFile(self):
- check = self.checkDownload({"wait": re.compile(UploadStationCom.TIME_LIMIT_WAIT_PATTERN)})
- if check == "wait":
- wait = 720
- if self.lastCheck is not None:
- wait = int(self.lastCheck.group(1))
- self.logDebug("Failed, you need to wait %d seconds for another download." % wait)
- self.setWait(wait + 3, True)
- self.wait()
- self.retry()
+ URLS = ['http://www.uploadstation.com/file/', 'http://www.uploadstation.com/check-links.php', 'http://www.uploadstation.com/checkReCaptcha.php']
+ LINKCHECK_TR = r'<div class="details (?:white|grey)">(.*?)\t{9}</div>'
+ LINKCHECK_TD = r'<div class="(?:col )?col\d">(?:<[^>]*>| )*([^<]*)'
+
+ LONG_WAIT_PATTERN = r'<h1>You have to wait (\d+) (\w+) to download the next file\.</h1>'
+
+def getInfo(urls):
+ for chunk in chunks(urls, 100): yield checkFile(UploadStationCom, chunk)
\ No newline at end of file diff --git a/module/plugins/hoster/UploadedTo.py b/module/plugins/hoster/UploadedTo.py index 751dcda25..3cb1e71ff 100644 --- a/module/plugins/hoster/UploadedTo.py +++ b/module/plugins/hoster/UploadedTo.py @@ -10,19 +10,10 @@ from module.plugins.ReCaptcha import ReCaptcha key = "bGhGMkllZXByd2VEZnU5Y2NXbHhYVlZ5cEE1bkEzRUw=".decode('base64') -def correctDownloadLink(url): - url = re.sub("http://.*?/", "http://uploaded.to/",url, 1) - url = re.sub("\\.to/.*?id=", ".to/file/", url, 1) - - if "/file/" not in url: - url = url.replace("uploaded.to/", "uploaded.to/file/") - - parts = url.split("/") - return "/".join(parts[:min(5,len(parts))]) + "/" - def getID(url): - """ returns id of corrected url""" - return re.search(r"uploaded.to/file/([^/]+)", url).group(1) + """ returns id from file url""" + m = re.match(r"http://[\w\.-]*?(uploaded\.(to|net)(/file/|/?\?id=|.*?&id=)|ul\.to/)(?P<ID>\w+)", url) + return m.group('ID') def getAPIData(urls): post = {"apikey" : key} @@ -30,18 +21,17 @@ def getAPIData(urls): idMap = {} for i, url in enumerate(urls): - newUrl = correctDownloadLink(url) - id = getID(newUrl) + id = getID(url) post["id_%s" % i] = id idMap[id] = url - api = unicode(getURL("http://uploaded.to/api/filemultiple", post=post, decode=False), 'iso-8859-1') + api = unicode(getURL("http://uploaded.net/api/filemultiple", post=post, decode=False), 'iso-8859-1') result = {} if api: for line in api.splitlines(): - data = line.split(",") + data = line.split(",", 4) if data[1] in idMap: result[data[1]] = (data[0], data[2], data[4], data[3], idMap[data[1]]) @@ -82,11 +72,11 @@ def getInfo(urls): class UploadedTo(Hoster): __name__ = "UploadedTo" __type__ = "hoster" - __pattern__ = r"(http://[\w\.-]*?uploaded\.to/.*?(file/|\?id=|&id=)[\w]+/?)|(http://[\w\.]*?ul\.to/(\?id=|&id=)?[\w\-]+/.+)|(http://[\w\.]*?ul\.to/(\?id=|&id=)?[\w\-]+/?)" - __version__ = "0.53" - __description__ = """Uploaded.to Download Hoster""" - __author_name__ = ("spoob", "mkaay") - __author_mail__ = ("spoob@pyload.org", "mkaay@mkaay.de") + __pattern__ = r"http://[\w\.-]*?(uploaded\.(to|net)(/file/|/?\?id=|.*?&id=)|ul\.to/)\w+" + __version__ = "0.62" + __description__ = """Uploaded.net Download Hoster""" + __author_name__ = ("spoob", "mkaay", "zoidberg", "netpok") + __author_mail__ = ("spoob@pyload.org", "mkaay@mkaay.de", "zoidberg@mujmail.cz", "netpok@gmail.com") FILE_INFO_PATTERN = r'<a href="file/(?P<ID>\w+)" id="filename">(?P<N>[^<]+)</a> \s*<small[^>]*>(?P<S>[^<]+)</small>' FILE_OFFLINE_PATTERN = r'<small class="cL">Error: 404</small>' @@ -103,12 +93,12 @@ class UploadedTo(Hoster): self.multiDL = True self.resumeDownload = True - - self.pyfile.url = correctDownloadLink(self.pyfile.url) self.fileID = getID(self.pyfile.url) + self.pyfile.url = "http://uploaded.net/file/%s" % self.fileID def process(self, pyfile): - self.req.cj.setCookie("uploaded.to", "lang", "en") + self.req.cj.setCookie("uploaded.net", "lang", "en") # doesn't work anymore + self.load("http://uploaded.net/language/en") api = getAPIData([pyfile.url]) @@ -156,24 +146,42 @@ class UploadedTo(Hoster): self.resetAccount() self.fail(_("Traffic exceeded")) - self.download("http://uploaded.to/file/%s/ddl" % self.fileID) - + header = self.load("http://uploaded.net/file/%s" % self.fileID, just_header=True) + if "location" in header: + #Direct download + print "Direct Download: " + header['location'] + self.download(header['location']) + else: + #Indirect download + self.html = self.load("http://uploaded.net/file/%s" % self.fileID) + found = re.search(r'<div class="tfree".*\s*<form method="post" action="(.*?)"', self.html) + if not found: + self.fail("Download URL not found. Try to enable direct downloads.") + url = found.group(1) + print "Premium URL: " + url + self.download(url, post={}) def handleFree(self): self.html = self.load(self.pyfile.url, decode=True) + + if 'var free_enabled = false;' in self.html: + self.logError("Free-download capacities exhausted.") + self.retry(24, 300) - wait = re.search(r"Current waiting period: <span>(\d+)</span> seconds", self.html).group(1) - self.setWait(wait) + found = re.search(r"Current waiting period: <span>(\d+)</span> seconds", self.html) + if not found: + self.fail("File not downloadable for free users") + self.setWait(int(found.group(1))) - js = self.load("http://uploaded.to/js/download.js", decode=True) + js = self.load("http://uploaded.net/js/download.js", decode=True) challengeId = re.search(r'Recaptcha\.create\("([^"]+)', js) - url = "http://uploaded.to/io/ticket/captcha/%s" % self.fileID + url = "http://uploaded.net/io/ticket/captcha/%s" % self.fileID downloadURL = "" for i in range(5): - self.req.lastURL = str(self.url) + #self.req.lastURL = str(self.url) re_captcha = ReCaptcha(self) challenge, result = re_captcha.challenge(challengeId.group(1)) options = {"recaptcha_challenge_field" : challenge, "recaptcha_response_field": result} @@ -190,18 +198,24 @@ class UploadedTo(Hoster): self.retry() elif "limit-parallel" in result: self.fail("Cannot download in parallel") - elif "limit-dl" in result: - self.setWait(30 * 60, True) + elif "You have reached the max. number of possible free downloads for this hour" in result: # limit-dl + self.setWait(60 * 60, True) self.wait() self.retry() elif 'err:"captcha"' in result: + self.logError("ul.net captcha is disabled") self.invalidCaptcha() elif "type:'download'" in result: self.correctCaptcha() downloadURL = re.search("url:'([^']+)", result).group(1) break + else: + self.fail("Unknown error '%s'") + self.setWait(60 * 60, True) + self.wait() + self.retry() if not downloadURL: self.fail("No Download url retrieved/all captcha attempts failed") - self.download(downloadURL)
\ No newline at end of file + self.download(downloadURL) diff --git a/module/plugins/hoster/UploadheroCom.py b/module/plugins/hoster/UploadheroCom.py new file mode 100644 index 000000000..eb7b5fb23 --- /dev/null +++ b/module/plugins/hoster/UploadheroCom.py @@ -0,0 +1,84 @@ +# -*- coding: utf-8 -*- +""" + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <http://www.gnu.org/licenses/>. + + @author: zoidberg +""" + +import re +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo + +class UploadheroCom(SimpleHoster): + __name__ = "UploadheroCom" + __type__ = "hoster" + __pattern__ = r"http://(?:www\.)?uploadhero\.com/dl/\w+" + __version__ = "0.12" + __description__ = """UploadHero.com plugin""" + __author_name__ = ("mcmyst", "zoidberg") + __author_mail__ = ("mcmyst@hotmail.fr", "zoidberg@mujmail.cz") + + SH_COOKIES = [("http://uploadhero.com", "lang", "en")] + FILE_NAME_PATTERN = r'<div class="nom_de_fichier">(?P<N>.*?)</div>' + FILE_SIZE_PATTERN = r'Taille du fichier : </span><strong>(?P<S>.*?)</strong>' + FILE_OFFLINE_PATTERN = r'<p class="titre_dl_2">|<div class="raison"><strong>Le lien du fichier ci-dessus n\'existe plus.' + + DOWNLOAD_URL_PATTERN = r'<a href="([^"]+)" id="downloadnow"' + + IP_BLOCKED_PATTERN = r'href="(/lightbox_block_download.php\?min=.*?)"' + IP_WAIT_PATTERN = r'<span id="minutes">(\d+)</span>.*\s*<span id="seconds">(\d+)</span>' + + CAPTCHA_PATTERN = r'"(/captchadl\.php\?[a-z0-9]+)"' + FREE_URL_PATTERN = r'var magicomfg = \'<a href="(http://[^<>"]*?)"|"(http://storage\d+\.uploadhero\.com/\?d=[A-Za-z0-9]+/[^<>"/]+)"' + + def handleFree(self): + self.checkErrors() + + found = re.search(self.CAPTCHA_PATTERN, self.html) + if not found: self.parseError("Captcha URL") + captcha_url = "http://uploadhero.com" + found.group(1) + + for i in range(5): + captcha = self.decryptCaptcha(captcha_url) + self.html = self.load(self.pyfile.url, get = {"code": captcha}) + found = re.search(self.FREE_URL_PATTERN, self.html) + if found: + self.correctCaptcha() + download_url = found.group(1) or found.group(2) + break + else: + self.invalidCaptcha() + else: + self.fail("No valid captcha code entered") + + self.download(download_url) + + def handlePremium(self): + self.log.debug("%s: Use Premium Account" % self.__name__) + self.html = self.load(self.pyfile.url) + link = re.search(self.DOWNLOAD_URL_PATTERN, self.html).group(1) + self.log.debug("Downloading link : '%s'" % link) + self.download(link) + + def checkErrors(self): + found = re.search(self.IP_BLOCKED_PATTERN, self.html) + if found: + self.html = self.load("http://uploadhero.com%s" % found.group(1)) + + found = re.search(self.IP_WAIT_PATTERN, self.html) + wait_time = (int(found.group(1)) * 60 + int(found.group(2))) if found else 300 + self.setWait(wait_time, True) + self.wait() + self.retry() + +getInfo = create_getInfo(UploadheroCom)
\ No newline at end of file diff --git a/module/plugins/hoster/UploadingCom.py b/module/plugins/hoster/UploadingCom.py index 1278bfc01..4a157a787 100644 --- a/module/plugins/hoster/UploadingCom.py +++ b/module/plugins/hoster/UploadingCom.py @@ -18,20 +18,22 @@ """
import re
+from pycurl import HTTPHEADER
from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo, timestamp
+from module.common.json_layer import json_loads
class UploadingCom(SimpleHoster):
__name__ = "UploadingCom"
__type__ = "hoster"
- __pattern__ = r"http://(?:www\.)?uploading\.com/files/(?:get/)?[\w\d]+/?"
- __version__ = "0.30"
+ __pattern__ = r"http://(?:www\.)?uploading\.com/files/(?:get/)?(?P<ID>[\w\d]+)"
+ __version__ = "0.32"
__description__ = """Uploading.Com File Download Hoster"""
__author_name__ = ("jeix", "mkaay", "zoidberg")
__author_mail__ = ("jeix@hasnomail.de", "mkaay@mkaay.de", "zoidberg@mujmail.cz")
FILE_NAME_PATTERN = r'<title>Download (?P<N>.*?) for free on uploading.com</title>'
FILE_SIZE_PATTERN = r'<span>File size: (?P<S>.*?)</span>'
- FILE_OFFLINE_PATTERN = r'<h2 style=".*?">The requested file is not found</h2>'
+ FILE_OFFLINE_PATTERN = r'<h2.*?>The requested file is not found</h2>'
def process(self, pyfile):
# set lang to english
@@ -47,21 +49,20 @@ class UploadingCom(SimpleHoster): self.file_info = self.getFileInfo()
if self.premium:
- url = self.handlePremium()
+ self.handlePremium()
else:
- url = self.handleFree()
-
- self.download(url)
+ self.handleFree()
def handlePremium(self):
postData = {'action': 'get_link',
- 'code': re.search('code: "(.*?)",', self.html).group(1),
+ 'code': self.file_info['ID'],
'pass': 'undefined'}
self.html = self.load('http://uploading.com/files/get/?JsHttpRequest=%d-xml' % timestamp(), post=postData)
url = re.search(r'"link"\s*:\s*"(.*?)"', self.html)
if url:
- return url.group(1).replace("\\/", "/")
+ url = url.group(1).replace("\\/", "/")
+ self.download(url)
raise Exception("Plugin defect.")
@@ -72,39 +73,38 @@ class UploadingCom(SimpleHoster): self.logWarning(self.pyfile.error)
self.retry(max_tries=6, wait_time = 21600 if found.group(2) else 900, reason = self.pyfile.error)
- self.code = re.search(r'name="code" value="(.*?)"', self.html).group(1)
- self.fileid = re.search(r'name="file_id" value="(.*?)"', self.html).group(1)
-
- postData = {'action': 'second_page',
- 'code': self.code,
- 'file_id': self.fileid}
-
- self.html = self.load(self.pyfile.url, post=postData)
+ ajax_url = "http://uploading.com/files/get/?ajax"
+ self.req.http.c.setopt(HTTPHEADER, ["X-Requested-With: XMLHttpRequest"])
+ self.req.http.lastURL = self.pyfile.url
- wait_time = re.search(r'timead_counter">(\d+)<', self.html)
- if not wait_time:
- wait_time = re.search(r'start_timer\((\d+)\)', self.html)
-
- if wait_time:
- wait_time = int(wait_time.group(1))
+ response = json_loads(self.load(ajax_url, post = {'action': 'second_page', 'code': self.file_info['ID']}))
+ if 'answer' in response and 'wait_time' in response['answer']:
+ wait_time = int(response['answer']['wait_time'])
self.log.info("%s: Waiting %d seconds." % (self.__name__, wait_time))
self.setWait(wait_time)
self.wait()
+ else:
+ self.pluginParseError("AJAX/WAIT")
+ response = json_loads(self.load(ajax_url, post = {'action': 'get_link', 'code': self.file_info['ID'], 'pass': 'false'}))
+ if 'answer' in response and 'link' in response['answer']:
+ url = response['answer']['link']
+ else:
+ self.pluginParseError("AJAX/URL")
+
+ self.html = self.load(url)
+ found = re.search(r'<form id="file_form" action="(.*?)"', self.html)
+ if found:
+ url = found.group(1)
+ else:
+ self.pluginParseError("URL")
- postData = {'action': 'get_link',
- 'code': self.code,
- 'pass': 'undefined'}
-
- if r'var captcha_src' in self.html[1]:
- captcha_url = "http://uploading.com/general/captcha/download%s/?ts=%d" % (self.fileid, timestamp())
- postData['captcha_code'] = self.decryptCaptcha(captcha_url)
-
- self.html = self.load('http://uploading.com/files/get/?JsHttpRequest=%d-xml' % timestamp(), post=postData)
- url = re.search(r'"link"\s*:\s*"(.*?)"', self.html)
- if url:
- return url.group(1).replace("\\/", "/")
-
- raise Exception("Plugin defect.")
+ self.download(url)
+
+ check = self.checkDownload({"html" : re.compile("\A<!DOCTYPE html PUBLIC")})
+ if check == "html":
+ self.logWarning("Redirected to a HTML page, wait 10 minutes and retry")
+ self.setWait(600, True)
+ self.wait()
getInfo = create_getInfo(UploadingCom)
\ No newline at end of file diff --git a/module/plugins/hoster/WarserverCz.py b/module/plugins/hoster/WarserverCz.py new file mode 100644 index 000000000..423170319 --- /dev/null +++ b/module/plugins/hoster/WarserverCz.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +""" + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <http://www.gnu.org/licenses/>. + + @author: zoidberg +""" + +import re +from module.plugins.hoster.CoolshareCz import CoolshareCz +from module.plugins.internal.SimpleHoster import create_getInfo + +class WarserverCz(CoolshareCz): + __name__ = "WarserverCz" + __type__ = "hoster" + __pattern__ = r"http://(?:\w*\.)?warserver.cz/stahnout/(?P<ID>\d+)/.+" + __version__ = "0.11" + __description__ = """Warserver.cz""" + __author_name__ = ("zoidberg") + + FILE_NAME_PATTERN = r'<h1.*?>(?P<N>[^<]+)</h1>' + DOMAIN = "http://s01.warserver.cz" + +getInfo = create_getInfo(WarserverCz)
\ No newline at end of file diff --git a/module/plugins/hoster/WebshareCz.py b/module/plugins/hoster/WebshareCz.py new file mode 100644 index 000000000..b60fda7e4 --- /dev/null +++ b/module/plugins/hoster/WebshareCz.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +""" + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <http://www.gnu.org/licenses/>. + + @author: zoidberg +""" + +import re +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo +from module.network.HTTPRequest import BadHeader + +class WebshareCz(SimpleHoster): + __name__ = "WebshareCz" + __type__ = "hoster" + __pattern__ = r"http://(\w+\.)?webshare.cz/(stahnout/)?(?P<ID>\w{10})-.+" + __version__ = "0.11" + __description__ = """WebShare.cz""" + __author_name__ = ("zoidberg") + + FILE_NAME_PATTERN = r'<h3>Stahujete soubor: </h3>\s*<div class="textbox">(?P<N>[^<]+)</div>' + FILE_SIZE_PATTERN = r'<h3>Velikost souboru je: </h3>\s*<div class="textbox">(?P<S>[^<]+)</div>' + FILE_OFFLINE_PATTERN = r'<h3>Soubor ".*?" nebyl nalezen.</h3>' + + DOWNLOAD_LINK_PATTERN = r'id="download_link" href="(?P<url>.*?)"' + + def handleFree(self): + url_a = re.search(r"(var l.*)", self.html).group(1) + url_b = re.search(r"(var keyStr.*)", self.html).group(1) + url = self.js.eval("%s\n%s\ndec(l)" % (url_a, url_b)) + + self.logDebug('Download link: ' + url) + self.download(url) + +getInfo = create_getInfo(WebshareCz)
\ No newline at end of file diff --git a/module/plugins/hoster/WrzucTo.py b/module/plugins/hoster/WrzucTo.py new file mode 100644 index 000000000..4a5e89f22 --- /dev/null +++ b/module/plugins/hoster/WrzucTo.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- +""" + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <http://www.gnu.org/licenses/>. + + @author: zoidberg +""" + +import re +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo +from pycurl import HTTPHEADER + +class WrzucTo(SimpleHoster): + __name__ = "WrzucTo" + __type__ = "hoster" + __pattern__ = r"http://(?:\w+\.)*?wrzuc\.to/([a-zA-Z0-9]+(\.wt|\.html)|(\w+/?linki/[a-zA-Z0-9]+))" + __version__ = "0.01" + __description__ = """Wrzuc.to plugin - free only""" + __author_name__ = ("zoidberg") + __author_mail__ = ("zoidberg@mujmail.cz") + + SH_COOKIES = [("http://www.wrzuc.to", "language", "en")] + FILE_SIZE_PATTERN = r'class="info">\s*<tr>\s*<td>(?P<S>.*?)</td>' + FILE_NAME_PATTERN = r'id="file_info">\s*<strong>(?P<N>.*?)</strong>' + + def setup(self): + self.multiDL = True + + def handleFree(self): + data = dict(re.findall(r'(md5|file): "(.*?)"', self.html)) + if len(data) != 2: self.parseError('File ID') + + self.req.http.c.setopt(HTTPHEADER, ["X-Requested-With: XMLHttpRequest"]) + self.req.http.lastURL = self.pyfile.url + self.load("http://www.wrzuc.to/ajax/server/prepair", post = {"md5": data['md5']}) + + self.req.http.lastURL = self.pyfile.url + self.html = self.load("http://www.wrzuc.to/ajax/server/download_link", post = {"file": data['file']}) + + data.update(re.findall(r'"(download_link|server_id)":"(.*?)"', self.html)) + if len(data) != 4: self.parseError('Download URL') + + download_url = "http://%s.wrzuc.to/pobierz/%s" % (data['server_id'], data['download_link']) + self.logDebug("Download URL: %s" % download_url) + self.download(download_url) + +getInfo = create_getInfo(WrzucTo) + diff --git a/module/plugins/hoster/XFileSharingPro.py b/module/plugins/hoster/XFileSharingPro.py new file mode 100644 index 000000000..8e213e9bf --- /dev/null +++ b/module/plugins/hoster/XFileSharingPro.py @@ -0,0 +1,286 @@ +# -*- coding: utf-8 -*- +""" + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <http://www.gnu.org/licenses/>. + + @author: zoidberg +""" + +import re +from random import random +from urllib import unquote +from urlparse import urlparse +from pycurl import FOLLOWLOCATION, LOW_SPEED_TIME +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo, PluginParseError +from module.plugins.ReCaptcha import ReCaptcha +from module.utils import html_unescape + +class XFileSharingPro(SimpleHoster): + """ + Common base for XFileSharingPro hosters like EasybytezCom, CramitIn, FiledinoCom... + Some hosters may work straight away when added to __pattern__ + However, most of them will NOT work because they are either down or running a customized version + """ + __name__ = "XFileSharingPro" + __type__ = "hoster" + __pattern__ = r"^unmatchable$" + __version__ = "0.11" + __description__ = """XFileSharingPro common hoster base""" + __author_name__ = ("zoidberg") + __author_mail__ = ("zoidberg@mujmail.cz") + + FILE_NAME_PATTERN = r'<input type="hidden" name="fname" value="(?P<N>[^"]+)"' + FILE_SIZE_PATTERN = r'You have requested <font color="red">[^<]+</font> \((?P<S>[^<]+)\)</font>' + FILE_INFO_PATTERN = r'<tr><td align=right><b>Filename:</b></td><td nowrap>(?P<N>[^<]+)</td></tr>\s*.*?<small>\((?P<S>[^<]+)\)</small>' + FILE_OFFLINE_PATTERN = r'<(b|h2)>File Not Found</(b|h2)>' + + WAIT_PATTERN = r'<span id="countdown_str">.*?>(\d+)</span>' + LONG_WAIT_PATTERN = r'(?P<H>\d+(?=\s*hour))?.*?(?P<M>\d+(?=\s*minute))?.*?(?P<S>\d+(?=\s*second))?' + OVR_DOWNLOAD_LINK_PATTERN = r'<h2>Download Link</h2>\s*<textarea[^>]*>([^<]+)' + OVR_KILL_LINK_PATTERN = r'<h2>Delete Link</h2>\s*<textarea[^>]*>([^<]+)' + CAPTCHA_URL_PATTERN = r'(http://[^"\']+?/captchas?/[^"\']+)' + RECAPTCHA_URL_PATTERN = r'http://[^"\']+?recaptcha[^"\']+?\?k=([^"\']+)"' + CAPTCHA_DIV_PATTERN = r'<b>Enter code.*?<div.*?>(.*?)</div>' + ERROR_PATTERN = r'class=["\']err["\'][^>]*>(.*?)</' + + def setup(self): + self.__pattern__ = self.core.pluginManager.hosterPlugins[self.__name__]['pattern'] + self.multiDL = True + self.chunkLimit = 1 + + def process(self, pyfile): + if not hasattr(self, "HOSTER_NAME"): + self.HOSTER_NAME = re.search(self.__pattern__, self.pyfile.url).group(1) + if not hasattr(self, "DIRECT_LINK_PATTERN"): + self.DIRECT_LINK_PATTERN = r'(http://(\w+\.%s|\d+\.\d+\.\d+\.\d+)(:\d+/d/|/files/\d+/\w+/)[^"\'<]+)' % self.HOSTER_NAME + + self.captcha = self.errmsg = None + self.passwords = self.getPassword().splitlines() + + if not re.match(self.__pattern__, self.pyfile.url): + if self.premium: + self.handleOverriden() + else: + self.fail("Only premium users can download from other hosters with %s" % self.HOSTER_NAME) + else: + try: + self.html = self.load(pyfile.url, cookies = False, decode = True) + self.file_info = self.getFileInfo() + except PluginParseError: + self.file_info = None + + self.req.http.lastURL = self.pyfile.url + + self.req.http.c.setopt(FOLLOWLOCATION, 0) + self.html = self.load(self.pyfile.url, cookies = True, decode = True) + self.header = self.req.http.header + self.req.http.c.setopt(FOLLOWLOCATION, 1) + + self.location = None + found = re.search("Location\s*:\s*(.*)", self.header, re.I) + if found and re.match(self.DIRECT_LINK_PATTERN, found.group(1)): + self.location = found.group(1).strip() + + if not self.file_info: + pyfile.name = html_unescape(unquote(urlparse(self.location if self.location else pyfile.url).path.split("/")[-1])) + + if self.location: + self.startDownload(self.location) + elif self.premium: + self.handlePremium() + else: + self.handleFree() + + def handleFree(self): + url = self.getDownloadLink() + self.logDebug("Download URL: %s" % url) + self.startDownload(url) + + def getDownloadLink(self): + for i in range(5): + self.logDebug("Getting download link: #%d" % i) + data = self.getPostParameters() + + self.req.http.c.setopt(FOLLOWLOCATION, 0) + self.html = self.load(self.pyfile.url, post = data, ref = True, decode = True) + self.header = self.req.http.header + self.req.http.c.setopt(FOLLOWLOCATION, 1) + + found = re.search("Location\s*:\s*(.*)", self.header, re.I) + if found: + break + + found = re.search(self.DIRECT_LINK_PATTERN, self.html, re.S) + if found: + break + + else: + if captcha in self.err: + self.fail("No valid captcha code entered") + else: + self.fail("Download link not found") + + return found.group(1) + + def handlePremium(self): + self.html = self.load(self.pyfile.url, post = self.getPostParameters()) + found = re.search(self.DIRECT_LINK_PATTERN, self.html) + if not found: self.parseError('DIRECT LINK') + self.startDownload(found.group(1)) + + def handleOverriden(self): + #only tested with easybytez.com + self.html = self.load("http://www.%s/" % self.HOSTER_NAME) + action, inputs = self.parseHtmlForm('') + upload_id = "%012d" % int(random()*10**12) + action += upload_id + "&js_on=1&utype=prem&upload_type=url" + inputs['tos'] = '1' + inputs['url_mass'] = self.pyfile.url + inputs['up1oad_type'] = 'url' + + self.logDebug(self.HOSTER_NAME, action, inputs) + #wait for file to upload to easybytez.com + self.req.http.c.setopt(LOW_SPEED_TIME, 600) + self.html = self.load(action, post = inputs) + + action, inputs = self.parseHtmlForm('F1') + if not inputs: self.parseError('TEXTAREA') + self.logDebug(self.HOSTER_NAME, inputs) + if inputs['st'] == 'OK': + self.html = self.load(action, post = inputs) + elif inputs['st'] == 'Can not leech file': + self.retry(max_tries=20, wait_time=180, reason=inputs['st']) + else: + self.fail(inputs['st']) + + #get easybytez.com link for uploaded file + found = re.search(self.OVR_DOWNLOAD_LINK_PATTERN, self.html) + if not found: self.parseError('DIRECT LINK (OVR)') + self.pyfile.url = found.group(1) + self.retry() + + def startDownload(self, link): + if self.captcha: self.correctCaptcha() + self.logDebug('DIRECT LINK: %s' % link) + self.download(link) + + def checkErrors(self): + found = re.search(self.ERROR_PATTERN, self.html) + if found: + self.errmsg = found.group(1) + self.logWarning(re.sub(r"<.*?>"," ",self.errmsg)) + + if 'wait' in self.errmsg: + wait_time = sum([int(v) * {"hour": 3600, "minute": 60, "second": 1}[u] for v, u in re.findall('(\d+)\s*(hour|minute|second)?', self.errmsg)]) + self.setWait(wait_time, True) + self.wait() + elif 'limit' in self.errmsg: + self.setWait(3600, True) + self.wait() + self.retry(25) + elif 'captcha' in self.errmsg: + self.invalidCaptcha() + elif 'countdown' or 'Expired session' in self.errmsg: + self.retry(3) + elif 'maintenance' in self.errmsg: + self.tempOffline() + elif 'download files up to' in self.errmsg: + self.fail("File too large for free download") + elif 'requires premium' in self.errmsg: + self.fail("File can be downloaded by premium users only") + else: + self.fail(self.errmsg) + + else: + self.errmsg = None + + return self.errmsg + + def getPostParameters(self): + for i in range(3): + if not self.errmsg: self.checkErrors() + + action, inputs = self.parseHtmlForm('F1') + if not inputs: + action, inputs = self.parseHtmlForm("action=(''|\"\")") + if not inputs: + if self.errmsg: + self.retry() + else: + self.parseError("Form not found") + + self.logDebug(self.HOSTER_NAME, inputs) + + if 'op' in inputs and inputs['op'] in ('download2', 'download3'): + if "password" in inputs: + if self.passwords: + inputs['password'] = self.passwords.pop(0) + else: + self.fail("No or invalid passport") + + if not self.premium: + found = re.search(self.WAIT_PATTERN, self.html) + if found: + wait_time = int(found.group(1)) + 1 + self.setWait(wait_time, False) + else: + wait_time = 0 + + self.captcha = self.handleCaptcha(inputs) + + if wait_time: self.wait() + + self.errmsg = None + return inputs + + else: + inputs['referer'] = self.pyfile.url + + if self.premium: + inputs['method_premium'] = "Premium Download" + if 'method_free' in inputs: del inputs['method_free'] + else: + inputs['method_free'] = "Free Download" + if 'method_premium' in inputs: del inputs['method_premium'] + + self.html = self.load(self.pyfile.url, post = inputs, ref = True) + self.errmsg = None + + else: self.parseError('FORM: %s' % (inputs['op'] if 'op' in inputs else 'UNKNOWN')) + + def handleCaptcha(self, inputs): + found = re.search(self.RECAPTCHA_URL_PATTERN, self.html) + if found: + recaptcha_key = unquote(found.group(1)) + self.logDebug("RECAPTCHA KEY: %s" % recaptcha_key) + recaptcha = ReCaptcha(self) + inputs['recaptcha_challenge_field'], inputs['recaptcha_response_field'] = recaptcha.challenge(recaptcha_key) + return 1 + else: + found = re.search(self.CAPTCHA_URL_PATTERN, self.html) + if found: + captcha_url = found.group(1) + inputs['code'] = self.decryptCaptcha(captcha_url) + return 2 + else: + found = re.search(self.CAPTCHA_DIV_PATTERN, self.html, re.S) + if found: + captcha_div = found.group(1) + self.logDebug(captcha_div) + numerals = re.findall('<span.*?padding-left\s*:\s*(\d+).*?>(\d)</span>', html_unescape(captcha_div)) + inputs['code'] = "".join([a[1] for a in sorted(numerals, key = lambda num: int(num[0]))]) + self.logDebug("CAPTCHA", inputs['code'], numerals) + return 3 + return 0 + +getInfo = create_getInfo(XFileSharingPro)
\ No newline at end of file diff --git a/module/plugins/hoster/YibaishiwuCom.py b/module/plugins/hoster/YibaishiwuCom.py new file mode 100644 index 000000000..5926cc227 --- /dev/null +++ b/module/plugins/hoster/YibaishiwuCom.py @@ -0,0 +1,54 @@ +# -*- coding: utf-8 -*- +""" + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <http://www.gnu.org/licenses/>. + + @author: zoidberg +""" + +import re +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo +from module.common.json_layer import json_loads + +class YibaishiwuCom(SimpleHoster): + __name__ = "YibaishiwuCom" + __type__ = "hoster" + __pattern__ = r"http://(?:www\.)?(?:u\.)?115.com/file/(?P<ID>\w+)" + __version__ = "0.11" + __description__ = """115.com""" + __author_name__ = ("zoidberg") + + FILE_NAME_PATTERN = r"file_name: '(?P<N>[^']+)'" + FILE_SIZE_PATTERN = r"file_size: '(?P<S>[^']+)'" + FILE_OFFLINE_PATTERN = ur'<h3><i style="color:red;">哎呀!提取码不存在!不妨搜搜看吧!</i></h3>' + + AJAX_URL_PATTERN = r'(/\?ct=(pickcode|download)[^"\']+)' + + def handleFree(self): + found = re.search(self.AJAX_URL_PATTERN, self.html) + if not found: self.parseError("AJAX URL") + url = found.group(1) + self.logDebug(('FREEUSER' if found.group(2) == 'download' else 'GUEST') + ' URL', url) + + response = json_loads(self.load("http://115.com" + url, decode = False)) + for mirror in (response['urls'] if 'urls' in response else response['data'] if 'data' in response else []): + try: + url = mirror['url'].replace('\\','') + self.logDebug("Trying URL: " + url) + header = self.download(url) + break + except: + continue + else: self.fail('No working link found') + +getInfo = create_getInfo(YibaishiwuCom)
\ No newline at end of file diff --git a/module/plugins/hoster/ZeveraCom.py b/module/plugins/hoster/ZeveraCom.py index d1fa80802..8be725d2f 100644 --- a/module/plugins/hoster/ZeveraCom.py +++ b/module/plugins/hoster/ZeveraCom.py @@ -1,83 +1,108 @@ -#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-from module.plugins.Hoster import Hoster
-from module.utils import html_unescape
-from urllib import quote, unquote
-from time import sleep
-
-class ZeveraCom(Hoster):
- __name__ = "ZeveraCom"
- __version__ = "0.11"
- __type__ = "hoster"
- __pattern__ = r"http://zevera.com/.*"
- __description__ = """zevera.com hoster plugin"""
- __author_name__ = ("zoidberg")
- __author_mail__ = ("zoidberg@mujmail.cz")
-
- api_url = "http://zevera.com/API.ashx"
-
- def process(self, pyfile):
- if not self.account:
- self.logError(_("Please enter your zevera.com account or deactivate this plugin"))
- self.fail("No zevera.com account provided")
-
- self.logDebug("zevera.com: Old URL: %s" % pyfile.url)
-
- last_size = retries = 0
- olink = self.pyfile.url #quote(self.pyfile.url.encode('utf_8'))
-
- for i in range(100):
- self.retData = self.account.loadAPIRequest(self.req, cmd = 'download_request', olink = olink)
- self.checkAPIErrors(self.retData)
-
- if self.retData['FileInfo']['StatusID'] == 100:
- break
- elif self.retData['FileInfo']['StatusID'] == 99:
- self.fail('Failed to initialize download (99)')
- else:
- if self.retData['FileInfo']['Progress']['BytesReceived'] <= last_size:
- if retries >= 6:
- self.fail('Failed to initialize download (%d)' % self.retData['FileInfo']['StatusID'] )
- retries += 1
- else:
- retries = 0
-
- last_size = self.retData['FileInfo']['Progress']['BytesReceived']
-
- pyfile.progress = self.retData['FileInfo']['Progress']['Percentage']
-
- self.setWait(self.retData['Update_Wait'])
- self.wait()
-
- pyfile.progress = 0
- pyfile.name = self.crazyDecode(self.retData['FileInfo']['RealFileName'])
- pyfile.size = self.retData['FileInfo']['FileSizeInBytes']
-
- self.retData = self.account.loadAPIRequest(self.req, cmd = 'download_start', FileID = self.retData['FileInfo']['FileID'])
- self.checkAPIErrors(self.retData)
-
- self.download(self.api_url, get = {
- 'cmd': "open_stream",
- 'login': self.account.loginname,
- 'pass': self.account.password,
- 'FileID': self.retData['FileInfo']['FileID'],
- 'startBytes': 0
- }
- )
-
- def checkAPIErrors(self, retData):
- if not retData:
- self.fail('Unknown API response')
-
- if retData['ErrorCode']:
- self.logError(retData['ErrorCode'], retData['ErrorMessage'])
- self.fail('ERROR: ' + retData['ErrorMessage'])
-
- if self.pyfile.size / 1024000 > retData['AccountInfo']['AvailableTODAYTrafficForUseInMBytes']:
- self.logWarning("Not enough data left to download the file")
-
- def crazyDecode(self, ustring):
- # accepts decoded ie. unicode string - API response is double-quoted, double-utf8-encoded
- # no idea what the proper order of calling these functions would be :-/
- return html_unescape(unquote(unquote(ustring.replace('@DELIMITER@','#'))).encode('raw_unicode_escape').decode('utf-8'))
\ No newline at end of file +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +from module.plugins.Hoster import Hoster +from module.utils import html_unescape +from urllib import quote, unquote +from time import sleep + +class ZeveraCom(Hoster): + __name__ = "ZeveraCom" + __version__ = "0.20" + __type__ = "hoster" + __pattern__ = r"http://zevera.com/.*" + __description__ = """zevera.com hoster plugin""" + __author_name__ = ("zoidberg") + __author_mail__ = ("zoidberg@mujmail.cz") + + def setup(self): + self.resumeDownload = self.multiDL = True + self.chunkLimit = 1 + + def process(self, pyfile): + if not self.account: + self.logError(_("Please enter your zevera.com account or deactivate this plugin")) + self.fail("No zevera.com account provided") + + self.logDebug("zevera.com: Old URL: %s" % pyfile.url) + + if self.account.getAPIData(self.req, cmd = "checklink", olink = pyfile.url) != "Alive": + self.fail("Offline or not downloadable - contact Zevera support") + + header = self.account.getAPIData(self.req, just_header = True, cmd="generatedownloaddirect", olink = pyfile.url) + if not "location" in header: + self.fail("Unable to initialize download - contact Zevera support") + + self.download(header['location'], disposition = True) + + check = self.checkDownload({"error" : 'action="ErrorDownload.aspx'}) + if check == "error": + self.fail("Error response received - contact Zevera support") + + """ + # BitAPI not used - defunct, probably abandoned by Zevera + + api_url = "http://zevera.com/API.ashx" + + def process(self, pyfile): + if not self.account: + self.logError(_("Please enter your zevera.com account or deactivate this plugin")) + self.fail("No zevera.com account provided") + + self.logDebug("zevera.com: Old URL: %s" % pyfile.url) + + last_size = retries = 0 + olink = self.pyfile.url #quote(self.pyfile.url.encode('utf_8')) + + for i in range(100): + self.retData = self.account.loadAPIRequest(self.req, cmd = 'download_request', olink = olink) + self.checkAPIErrors(self.retData) + + if self.retData['FileInfo']['StatusID'] == 100: + break + elif self.retData['FileInfo']['StatusID'] == 99: + self.fail('Failed to initialize download (99)') + else: + if self.retData['FileInfo']['Progress']['BytesReceived'] <= last_size: + if retries >= 6: + self.fail('Failed to initialize download (%d)' % self.retData['FileInfo']['StatusID'] ) + retries += 1 + else: + retries = 0 + + last_size = self.retData['FileInfo']['Progress']['BytesReceived'] + + self.setWait(self.retData['Update_Wait']) + self.wait() + + pyfile.name = self.retData['FileInfo']['RealFileName'] + pyfile.size = self.retData['FileInfo']['FileSizeInBytes'] + + self.retData = self.account.loadAPIRequest(self.req, cmd = 'download_start', FileID = self.retData['FileInfo']['FileID']) + self.checkAPIErrors(self.retData) + + self.download(self.api_url, get = { + 'cmd': "open_stream", + 'login': self.account.loginname, + 'pass': self.account.password, + 'FileID': self.retData['FileInfo']['FileID'], + 'startBytes': 0 + } + ) + + def checkAPIErrors(self, retData): + if not retData: + self.fail('Unknown API response') + + if retData['ErrorCode']: + self.logError(retData['ErrorCode'], retData['ErrorMessage']) + #self.fail('ERROR: ' + retData['ErrorMessage']) + + if self.pyfile.size / 1024000 > retData['AccountInfo']['AvailableTODAYTrafficForUseInMBytes']: + self.logWarning("Not enough data left to download the file") + + def crazyDecode(self, ustring): + # accepts decoded ie. unicode string - API response is double-quoted, double-utf8-encoded + # no idea what the proper order of calling these functions would be :-/ + return html_unescape(unquote(unquote(ustring.replace('@DELIMITER@','#'))).encode('raw_unicode_escape').decode('utf-8')) + """
\ No newline at end of file diff --git a/module/plugins/hoster/ZippyshareCom.py b/module/plugins/hoster/ZippyshareCom.py index 5b32b4068..6b0b01003 100644 --- a/module/plugins/hoster/ZippyshareCom.py +++ b/module/plugins/hoster/ZippyshareCom.py @@ -1,51 +1,186 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -import re -from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo +import re, subprocess, tempfile, os +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo, timestamp +from module.plugins.ReCaptcha import ReCaptcha +from module.common.json_layer import json_loads class ZippyshareCom(SimpleHoster): __name__ = "ZippyshareCom" __type__ = "hoster" - __pattern__ = r"(http://www\d{0,2}\.zippyshare.com)/v(?:/|iew.jsp.*key=)(\d+)" - __version__ = "0.31" + __pattern__ = r"(?P<HOST>http://www\d{0,2}\.zippyshare.com)/v(?:/|iew.jsp.*key=)(?P<KEY>\d+)" + __version__ = "0.36" __description__ = """Zippyshare.com Download Hoster""" __author_name__ = ("spoob", "zoidberg") __author_mail__ = ("spoob@pyload.org", "zoidberg@mujmail.cz") + __config__ = [("swfdump_path", "string", "Path to swfdump", "")] FILE_NAME_PATTERN = r'>Name:</font>\s*<font [^>]*>(?P<N>[^<]+)</font><br />' FILE_SIZE_PATTERN = r'>Size:</font>\s*<font [^>]*>(?P<S>[0-9.,]+) (?P<U>[kKMG]+)i?B</font><br />' FILE_OFFLINE_PATTERN = r'>File does not exist on this server</div>' - DOWNLOAD_URL_PATTERN = r"document\.getElementById\('dlbutton'\).href = ([^;]+);" - SEED_PATTERN = r"seed: (\d*)" + DOWNLOAD_URL_PATTERN = r"<script type=\"text/javascript\">([^<]*?)document\.getElementById\('dlbutton'\).href = ([^;]+);" + SEED_PATTERN = r'swfobject.embedSWF\("([^"]+)".*?seed: (\d+)' + CAPTCHA_KEY_PATTERN = r'Recaptcha.create\("([^"]+)"' + CAPTCHA_SHORTENCODE_PATTERN = r"shortencode: '([^']+)'" + CAPTCHA_DOWNLOAD_PATTERN = r"document.location = '([^']+)'" + + LAST_KNOWN_VALUES = (9, 2374755) #time = (seed * multiply) % modulo def setup(self): self.html = None self.wantReconnect = False self.multiDL = True - def handleFree(self): + def handleFree(self): url = self.get_file_url() + if not url: self.fail("Download URL not found.") self.logDebug("Download URL %s" % url) self.download(url, cookies = True) + check = self.checkDownload({ + "swf_values": re.compile(self.SEED_PATTERN) + }) + + if check == "swf_values": + swf_sts = self.getStorage("swf_sts") + if not swf_sts: + self.setStorage("swf_sts", 2) + self.setStorage("swf_stamp", 0) + elif swf_sts == '1': + self.setStorage("swf_sts", 2) + + self.retry(max_tries = 1) + def get_file_url(self): """ returns the absolute downloadable filepath """ - file_host, file_key = re.search(self.__pattern__, self.pyfile.url).groups() + url = multiply = modulo = None - found = re.search(self.DOWNLOAD_URL_PATTERN, self.html) + found = re.search(self.DOWNLOAD_URL_PATTERN, self.html, re.S) if found: - url = self.js.eval(found.group(1)) + #Method #1: JS eval + url = self.js.eval("\n".join(found.groups())) else: + #Method #2: SWF eval seed_search = re.search(self.SEED_PATTERN, self.html) - if seed_search is None: self.parseError('SEED') + if seed_search: + swf_url, file_seed = seed_search.groups() + + swf_sts = self.getStorage("swf_sts") + swf_stamp = int(self.getStorage("swf_stamp") or 0) + swf_version = self.getStorage("version") + self.logDebug("SWF", swf_sts, swf_stamp, swf_version) + + if not swf_sts: + self.logDebug('Using default values') + multiply, modulo = self.LAST_KNOWN_VALUES + elif swf_sts == "1": + self.logDebug('Using stored values') + multiply = self.getStorage("multiply") + modulo = self.getStorage("modulo") + elif swf_sts == "2": + if swf_version < self.__version__: + self.logDebug('Reverting to default values') + self.setStorage("swf_sts", "") + self.setStorage("version", self.__version__) + multiply, modulo = self.LAST_KNOWN_VALUES + elif (swf_stamp + 3600000) < timestamp(): + swfdump = self.get_swfdump_path() + if swfdump: + multiply, modulo = self.get_swf_values(self.file_info['HOST'] + swf_url, swfdump) + else: + self.logWarning("Swfdump not found. Install swftools to bypass captcha.") + + if multiply and modulo: + self.logDebug("TIME = (%s * %s) %s" % (file_seed, multiply, modulo)) + url = "/download?key=%s&time=%d" % (self.file_info['KEY'], (int(file_seed) * int(multiply)) % int(modulo)) + + if not url: + #Method #3: Captcha + url = self.do_recaptcha() + + return self.file_info['HOST'] + url + + def get_swf_values(self, swf_url, swfdump): + self.logDebug('Parsing values from %s' % swf_url) + multiply = modulo = None + + fd, fpath = tempfile.mkstemp() + try: + swf_data = self.load(swf_url) + os.write(fd, swf_data) + + p = subprocess.Popen([swfdump, '-a', fpath], stdout=subprocess.PIPE, stderr=subprocess.PIPE) + out, err = p.communicate() + + if err: + self.logError(err) + else: + m_str = re.search(r'::break.*?{(.*?)}', out, re.S).group(1) + multiply = re.search(r'pushbyte (\d+)', m_str).group(1) + modulo = re.search(r'pushint (\d+)', m_str).group(1) + finally: + os.close(fd) + os.remove(fpath) + + if multiply and modulo: + self.setStorage("multiply", multiply) + self.setStorage("modulo", modulo) + self.setStorage("swf_sts", 1) + self.setStorage("version", self.__version__) + else: + self.logError("Parsing SWF failed: swfdump not installed or plugin out of date") + self.setStorage("swf_sts", 2) - file_seed = int(seed_search.group(1)) - time = str((file_seed * 24) % 6743256) - url = "/download?key=" + str(file_key) + "&time=" + str(time) + self.setStorage("swf_stamp", timestamp()) + + return multiply, modulo + + def get_swfdump_path(self): + # used for detecting if swfdump is installed + def is_exe(ppath): + return os.path.isfile(ppath) and os.access(ppath, os.X_OK) + + program = self.getConfig("swfdump_path") or "swfdump" + swfdump = None + ppath, pname = os.path.split(program) + if ppath: + if is_exe(program): + swfdump = program + else: + for ppath in os.environ["PATH"].split(os.pathsep): + exe_file = os.path.join(ppath, program) + if is_exe(exe_file): + swfdump = exe_file + + # return path to the executable or None if not found + return swfdump + + def do_recaptcha(self): + self.logDebug('Trying to solve captcha') + captcha_key = re.search(self.CAPTCHA_KEY_PATTERN, self.html).group(1) + shortencode = re.search(self.CAPTCHA_SHORTENCODE_PATTERN, self.html).group(1) + url = re.search(self.CAPTCHA_DOWNLOAD_PATTERN, self.html).group(1) + + recaptcha = ReCaptcha(self) + + for i in range(5): + challenge, code = recaptcha.challenge(captcha_key) + + response = json_loads(self.load(self.file_info['HOST'] + '/rest/captcha/test', + post={'challenge': challenge, + 'response': code, + 'shortencode': shortencode})) + self.logDebug("reCaptcha response : %s" % response) + if response == True: + self.correctCaptcha + break + else: + self.invalidCaptcha() + else: self.fail("Invalid captcha") - return file_host + url + return url getInfo = create_getInfo(ZippyshareCom)
\ No newline at end of file |