diff options
Diffstat (limited to 'pyload/plugins/hoster')
133 files changed, 11162 insertions, 0 deletions
diff --git a/pyload/plugins/hoster/ARD.py b/pyload/plugins/hoster/ARD.py new file mode 100644 index 000000000..cda783091 --- /dev/null +++ b/pyload/plugins/hoster/ARD.py @@ -0,0 +1,80 @@ + +import subprocess +import re +import os.path +import os + +from module.utils import save_join, save_path +from module.plugins.Hoster import Hoster + +# Requires rtmpdump +# by Roland Beermann + +class RTMP: +    # TODO: Port to some RTMP-library like rtmpy or similar +    # TODO?: Integrate properly into the API of pyLoad + +    command = "rtmpdump" + +    @classmethod +    def download_rtmp_stream(cls, url, output_file, playpath=None): +        opts = [ +            "-r", url, +            "-o", output_file, +        ] +        if playpath: +            opts.append("--playpath") +            opts.append(playpath) + +        cls._invoke_rtmpdump(opts) + +    @classmethod +    def _invoke_rtmpdump(cls, opts): +        args = [ +            cls.command +        ] +        args.extend(opts) + +        return subprocess.check_call(args) + +class ARD(Hoster): +    __name__ = "ARD Mediathek" +    __version__ = "0.11" +    __pattern__ = r"http://www\.ardmediathek\.de/.*" +    __config__ = [] + +    def process(self, pyfile): +        site = self.load(pyfile.url) + +        avail_videos = re.findall(r"""mediaCollection.addMediaStream\(0, ([0-9]*), "([^\"]*)", "([^\"]*)", "[^\"]*"\);""", site) +        avail_videos.sort(key=lambda videodesc: int(videodesc[0]), reverse=True) # The higher the number, the better the quality + +        quality, url, playpath = avail_videos[0] + +        pyfile.name = re.search(r"<h1>([^<]*)</h1>", site).group(1) + +        if url.startswith("http"): +            # Best quality is available over HTTP. Very rare. +            self.download(url) +        else: +            pyfile.setStatus("downloading") + +            download_folder = self.config['general']['download_folder'] + +            location = save_join(download_folder, pyfile.package().folder) + +            if not os.path.exists(location): +                os.makedirs(location, int(self.core.config["permission"]["folder"], 8)) + +                if self.core.config["permission"]["change_dl"] and os.name != "nt": +                    try: +                        uid = getpwnam(self.config["permission"]["user"])[2] +                        gid = getgrnam(self.config["permission"]["group"])[2] + +                        chown(location, uid, gid) +                    except Exception, e: +                        self.logWarning(_("Setting User and Group failed: %s") % str(e)) + +            output_file = save_join(location, save_path(pyfile.name)) + os.path.splitext(playpath)[1] + +            RTMP.download_rtmp_stream(url, playpath=playpath, output_file=output_file) diff --git a/pyload/plugins/hoster/AlldebridCom.py b/pyload/plugins/hoster/AlldebridCom.py new file mode 100644 index 000000000..cdb5ccc08 --- /dev/null +++ b/pyload/plugins/hoster/AlldebridCom.py @@ -0,0 +1,84 @@ +# -*- coding: utf-8 -*- + +import re +from urllib import unquote +from random import randrange +from module.plugins.Hoster import Hoster +from module.common.json_layer import json_loads +from module.utils import parseFileSize + + +class AlldebridCom(Hoster): +    __name__ = "AlldebridCom" +    __version__ = "0.33" +    __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 %s account or deactivate this plugin") % "AllDebrid") +            self.fail("No AllDebrid account provided") + +        self.logDebug("AllDebrid: Old URL: %s" % pyfile.url) +        if re.match(self.__pattern__, pyfile.url): +            new_url = pyfile.url +        else: +            password = self.getPassword().splitlines() +            password = "" if not password else 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.logDebug("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.logDebug("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) +        elif check == "empty": +            self.retry(reason="Downloaded File was empty.", wait_time=60) diff --git a/pyload/plugins/hoster/BasePlugin.py b/pyload/plugins/hoster/BasePlugin.py new file mode 100644 index 000000000..552e7bc73 --- /dev/null +++ b/pyload/plugins/hoster/BasePlugin.py @@ -0,0 +1,104 @@ +#!/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, remove_chars + +class BasePlugin(Hoster): +    __name__ = "BasePlugin" +    __type__ = "hoster" +    __pattern__ = r"^unmatchable$" +    __version__ = "0.17" +    __description__ = """Base Plugin when any other didn't match""" +    __author_name__ = ("RaNaN") +    __author_mail__ = ("RaNaN@pyload.org") + +    def setup(self): +        self.chunkLimit = -1 +        self.resumeDownload = True + +    def process(self, pyfile): +        """main function""" + +        #debug part, for api exerciser +        if pyfile.url.startswith("DEBUG_API"): +            self.multiDL = False +            return + +        #TODO: remove debug +        if pyfile.url.lower().startswith("debug"): +            self.decryptCaptcha("http://forum.pyload.org/lib/tpl/pyload/images/pyload-logo-edited3.5-new-font-small.png", imgtype="png") +            self.download("http://download.pyload.org/random100.bin") +            return +# +#        if pyfile.url == "79": +#            self.core.api.addPackage("test", [str(i) for i in range(80)], 1) +# +#        return +        if pyfile.url.startswith("http"): + +            try: +                self.downloadFile(pyfile) +            except BadHeader, e: +                if e.code in (401, 403): +                    self.logDebug("Auth required") + +                    account = self.core.accountManager.getAccountPlugin('Http') +                    servers = [ x['login'] for x in account.getAllAccounts() ] +                    server = urlparse(pyfile.url).netloc + +                    if server in servers: +                        self.logDebug("Logging on to %s" % server) +                        self.req.addAuth(account.accounts[server]["password"]) +                    else: +                        for pwd in pyfile.package().password.splitlines(): +                            if ":" in pwd: +                                self.req.addAuth(pwd.strip()) +                                break +                        else: +                            self.fail(_("Authorization required (username:password)")) + +                    self.downloadFile(pyfile) +                else: +                    raise + +        else: +            self.fail("No Plugin matched and not a downloadable url.") + + +    def downloadFile(self, pyfile): +        url = pyfile.url + +        for i in range(5): +            header = self.load(url, just_header = True) + +            # self.load does not raise a BadHeader on 404 responses, do it here +            if header.has_key('code') and header['code'] == 404: +                raise BadHeader(404) + +            if 'location' in header: +                self.logDebug("Location: " + header['location']) +                url = unquote(header['location']) +            else: +                break + +        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) diff --git a/pyload/plugins/hoster/BayfilesCom.py b/pyload/plugins/hoster/BayfilesCom.py new file mode 100644 index 000000000..8473468ba --- /dev/null +++ b/pyload/plugins/hoster/BayfilesCom.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.common.json_layer import json_loads +from time import time + +class BayfilesCom(SimpleHoster): +    __name__ = "BayfilesCom" +    __type__ = "hoster" +    __pattern__ = r"http://(?:www\.)?bayfiles\.com/file/\w+/\w+/.*" +    __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>|<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: +            self.setWait(int(found.group(1)) * 60) +            self.wait() +            self.retry() +         +        # Get download token +        found = re.search(self.VARS_PATTERN, self.html) +        if not found: self.parseError('VARS') +        vfid, delay = found.groups() +         +        response = json_loads(self.load('http://bayfiles.com/ajax_download', get = { +            "_": time() * 1000, +            "action": "startTimer", +            "vfid": vfid}, decode = True)) +         +        if not "token" in response or not response['token']:  +            self.fail('No token')     +         +        self.setWait(int(delay)) +        self.wait() +         +        self.html = self.load('http://bayfiles.com/ajax_download', get = { +            "token": response['token'], +            "action": "getLink", +            "vfid": vfid}) + +        # Get final link and download         +        found = re.search(self.LINK_PATTERN, self.html) +        if not found: self.parseError("Free link") +        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) diff --git a/pyload/plugins/hoster/BezvadataCz.py b/pyload/plugins/hoster/BezvadataCz.py new file mode 100644 index 000000000..49299d463 --- /dev/null +++ b/pyload/plugins/hoster/BezvadataCz.py @@ -0,0 +1,94 @@ +# -*- 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 BezvadataCz(SimpleHoster): +    __name__ = "BezvadataCz" +    __type__ = "hoster" +    __pattern__ = r"http://(\w*\.)*bezvadata.cz/stahnout/.*" +    __version__ = "0.24" +    __description__ = """BezvaData.cz""" +    __author_name__ = ("zoidberg") +    __author_mail__ = ("zoidberg@mujmail.cz") + +    FILE_NAME_PATTERN = r'<p><b>Soubor: (?P<N>[^<]+)</b></p>' +    FILE_SIZE_PATTERN = r'<li><strong>Velikost:</strong> (?P<S>[^<]+)</li>' +    FILE_OFFLINE_PATTERN = r'<title>BezvaData \| Soubor nenalezen</title>' + +    def setup(self): +        self.multiDL = self.resumeDownload = True + +    def handleFree(self): +        #download button +        found = re.search(r'<a class="stahnoutSoubor".*?href="(.*?)"', self.html) +        if not found: self.parseError("page1 URL") +        url = "http://bezvadata.cz%s" % found.group(1) + +        #captcha form +        self.html = self.load(url) +        self.checkErrors() +        for i in range(5): +            action, inputs = self.parseHtmlForm('frm-stahnoutFreeForm') +            if not inputs: self.parseError("FreeForm") + +            found = re.search(r'<img src="data:image/png;base64,(.*?)"', self.html) +            if not found: self.parseError("captcha img") + +            #captcha image is contained in html page as base64encoded data but decryptCaptcha() expects image url +            self.load, proper_load = self.loadcaptcha, self.load +            try: +                inputs['captcha'] = self.decryptCaptcha(found.group(1), imgtype='png') +            finally: +                self.load = proper_load + +            if '<img src="data:image/png;base64' in self.html: +                self.invalidCaptcha() +            else: +                self.correctCaptcha() +                break +        else: +            self.fail("No valid captcha code entered") + +        #download url +        self.html = self.load("http://bezvadata.cz%s" % action, post=inputs) +        self.checkErrors() +        found = re.search(r'<a class="stahnoutSoubor2" href="(.*?)">', self.html) +        if not found: self.parseError("page2 URL") +        url = "http://bezvadata.cz%s" % found.group(1) +        self.logDebug("DL URL %s" % url) + +        #countdown +        found = re.search(r'id="countdown">(\d\d):(\d\d)<', self.html) +        wait_time = (int(found.group(1)) * 60 + int(found.group(2)) + 1) if found else 120 +        self.setWait(wait_time, False) +        self.wait() + +        self.download(url) + +    def checkErrors(self): +        if 'images/button-download-disable.png' in self.html: +            self.longWait(300, 24) #parallel dl limit +        elif '<div class="infobox' in self.html: +            self.tempOffline() + +    def loadcaptcha(self, data, *args, **kwargs): +        return data.decode("base64") + +getInfo = create_getInfo(BezvadataCz) diff --git a/pyload/plugins/hoster/BillionuploadsCom.py b/pyload/plugins/hoster/BillionuploadsCom.py new file mode 100644 index 000000000..5b053d547 --- /dev/null +++ b/pyload/plugins/hoster/BillionuploadsCom.py @@ -0,0 +1,17 @@ +# -*- coding: utf-8 -*- +from module.plugins.hoster.XFileSharingPro import XFileSharingPro, create_getInfo + +class BillionuploadsCom(XFileSharingPro): +    __name__ = "BillionuploadsCom" +    __type__ = "hoster" +    __pattern__ = r"http://(?:\w*\.)*?billionuploads.com/\w{12}" +    __version__ = "0.01" +    __description__ = """billionuploads.com hoster plugin""" +    __author_name__ = ("zoidberg") +    __author_mail__ = ("zoidberg@mujmail.cz") + +    FILE_NAME_PATTERN = r'<b>Filename:</b>(?P<N>.*?)<br>' +    FILE_SIZE_PATTERN = r'<b>Size:</b>(?P<S>.*?)<br>' +    HOSTER_NAME = "billionuploads.com" + +getInfo = create_getInfo(BillionuploadsCom) diff --git a/pyload/plugins/hoster/BitshareCom.py b/pyload/plugins/hoster/BitshareCom.py new file mode 100644 index 000000000..5e117ff45 --- /dev/null +++ b/pyload/plugins/hoster/BitshareCom.py @@ -0,0 +1,147 @@ +# -*- coding: utf-8 -*- +from __future__ import with_statement + +import re + +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo +from module.plugins.internal.CaptchaService import ReCaptcha + + +class BitshareCom(SimpleHoster): +    __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.48" +    __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_NAME_PATTERN = r'Download:</td>\s*<td><input type="text" value="http://bitshare\.com/files/\w+/(?P<N>[^"]+)\.html"' +    FILE_SIZE_PATTERN = r'- (?P<S>[\d.]+) (?P<U>\w+)</h1>' +    FILE_AJAXID_PATTERN = r'var ajaxdl = "(.*?)";' +    CAPTCHA_KEY_PATTERN = r"http://api\.recaptcha\.net/challenge\?k=(.*?) " +    TRAFFIC_USED_UP = r"Your Traffic is used up for today. Upgrade to premium to continue!" + +    def setup(self): +        self.multiDL = self.premium +        self.chunkLimit = 1 + +    def process(self, pyfile): +        if self.premium: +            self.account.relogin(self.user) +     +        self.pyfile = pyfile +         +        # File id +        m = re.match(self.__pattern__, self.pyfile.url) +        self.file_id = max(m.group('id1'), m.group('id2'))  +        self.logDebug("File id is [%s]" % self.file_id) + +        # Load main page +        self.req.cj.setCookie(self.HOSTER_DOMAIN, "language_selection", "EN") +        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() + +        # Check Traffic used up +        if re.search(BitshareCom.TRAFFIC_USED_UP, self.html) is not None: +            self.logInfo("Your Traffic is used up for today. Wait 1800 seconds or reconnect!") +            self.logDebug("Waiting %d seconds." % 1800) +            self.setWait(1800, True) +            self.wantReconnect = True +            self.wait() +            self.retry() + +        # File name +        m = re.search(BitshareCom.__pattern__, self.pyfile.url) +        name1 = m.group('name') if m is not None else None +        m = re.search(BitshareCom.FILE_INFO_PATTERN, self.html) +        name2 = m.group('name') if m is not None else None +        self.pyfile.name = max(name1, name2) + +        # 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) + +         +    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", +                            post={"request" : "generateID", "ajaxid" : self.ajaxid}) +        self.handleErrors(response, ':') +        parts = response.split(":") +        filetype = parts[0] +        wait = int(parts[1]) +        captcha = int(parts[2]) +        self.logDebug("Download info [type: '%s', waiting: %d, captcha: %d]" % (filetype, wait, captcha)) + +        # Waiting +        if wait > 0: +            self.logDebug("Waiting %d seconds." % 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: +            self.logDebug("File is captcha protected") +            id = re.search(BitshareCom.CAPTCHA_KEY_PATTERN, self.html).group(1) +            # Try up to 3 times +            for i in range(3): +                self.logDebug("Resolving ReCaptcha with key [%s], round %d" % (id, i+1)) +                recaptcha = ReCaptcha(self) +                challenge, code = recaptcha.challenge(id) +                response = self.load("http://bitshare.com/files-ajax/" + self.file_id + "/request.html", +                                post={"request" : "validateCaptcha", "ajaxid" : self.ajaxid, "recaptcha_challenge_field" : challenge, "recaptcha_response_field" : code}) +                if self.handleCaptchaErrors(response): +                    break + + +        # Get download URL +        self.logDebug("Getting download url") +        response = self.load("http://bitshare.com/files-ajax/" + self.file_id + "/request.html", +                    post={"request" : "getDownloadURL", "ajaxid" : self.ajaxid}) +        self.handleErrors(response, '#') +        url = response.split("#")[-1]     +         +        return url +                  +    def handleErrors(self, response, separator): +        self.logDebug("Checking response [%s]" % response) +        if "ERROR:Session timed out" in response: +            self.retry() +        elif "ERROR" in response: +            msg = response.split(separator)[-1] +            self.fail(msg) + +    def handleCaptchaErrors(self, response): +        self.logDebug("Result of captcha resolving [%s]" % response) +        if "SUCCESS" in response: +            self.correctCaptcha() +            return True +        elif "ERROR:SESSION ERROR" in response: +            self.retry() +        self.logDebug("Wrong captcha") +        self.invalidCaptcha() + +getInfo = create_getInfo(BitshareCom) diff --git a/pyload/plugins/hoster/BoltsharingCom.py b/pyload/plugins/hoster/BoltsharingCom.py new file mode 100644 index 000000000..2f42c8b23 --- /dev/null +++ b/pyload/plugins/hoster/BoltsharingCom.py @@ -0,0 +1,15 @@ +# -*- coding: utf-8 -*- +from module.plugins.hoster.XFileSharingPro import XFileSharingPro, create_getInfo + +class BoltsharingCom(XFileSharingPro): +    __name__ = "BoltsharingCom" +    __type__ = "hoster" +    __pattern__ = r"http://(?:\w*\.)*?boltsharing.com/\w{12}" +    __version__ = "0.01" +    __description__ = """Boltsharing.com hoster plugin""" +    __author_name__ = ("zoidberg") +    __author_mail__ = ("zoidberg@mujmail.cz") + +    HOSTER_NAME = "boltsharing.com" + +getInfo = create_getInfo(BoltsharingCom) diff --git a/pyload/plugins/hoster/CatShareNet.py b/pyload/plugins/hoster/CatShareNet.py new file mode 100644 index 000000000..3289ef72c --- /dev/null +++ b/pyload/plugins/hoster/CatShareNet.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +import re +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo +from module.plugins.internal.CaptchaService import ReCaptcha + + +class CatShareNet(SimpleHoster): +    __name__ = "CatShareNet" +    __type__ = "hoster" +    __pattern__ = r"http://(www\.)?catshare.net/\w{16}.*" +    __version__ = "0.01" +    __description__ = """CatShare.net Download Hoster""" +    __author_name__ = ("z00nx") +    __author_mail__ = ("z00nx0@gmail.com") + +    FILE_INFO_PATTERN = r'<h3 class="pull-left"[^>]+>(?P<N>.*)</h3>\s+<h3 class="pull-right"[^>]+>(?P<S>.*)</h3>' +    FILE_OFFLINE_PATTERN = r'Podany plik zosta' +    SECONDS_PATTERN = 'var\s+count\s+=\s+(\d+);' +    RECAPTCHA_KEY = "6Lfln9kSAAAAANZ9JtHSOgxUPB9qfDFeLUI_QMEy" + +    def handleFree(self): +        found = re.search(self.SECONDS_PATTERN, self.html) +        seconds = int(found.group(1)) +        self.logDebug("Seconds found", seconds) +        self.setWait(seconds + 1) +        self.wait() +        recaptcha = ReCaptcha(self) +        challenge, code = recaptcha.challenge(self.RECAPTCHA_KEY) +        post_data = {"recaptcha_challenge_field": challenge, "recaptcha_response_field": code} +        self.download(self.pyfile.url, post=post_data) +        check = self.checkDownload({"html": re.compile("\A<!DOCTYPE html PUBLIC")}) +        if check == "html": +            self.logDebug("Wrong captcha entered") +            self.invalidCaptcha() +            self.retry() + +getInfo = create_getInfo(CatShareNet) diff --git a/pyload/plugins/hoster/ChipDe.py b/pyload/plugins/hoster/ChipDe.py new file mode 100644 index 000000000..fcb84a300 --- /dev/null +++ b/pyload/plugins/hoster/ChipDe.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import re +from module.plugins.Crypter import Crypter + +class ChipDe(Crypter): +	__name__ = "ChipDe" +	__type__ = "container" +	__pattern__ = r"http://(?:www\.)?chip.de/video/.*\.html" +	__version__ = "0.1" +	__description__ = """Chip.de Container Plugin""" +	__author_name__ = ('4Christopher') +	__author_mail__ = ('4Christopher@gmx.de') + +	def decrypt(self, pyfile): +		self.html = self.load(pyfile.url) +		try: +			url = re.search(r'"(http://video.chip.de/\d+?/.*)"', self.html).group(1) +			self.logDebug('The file URL is %s' % url) +		except: +			self.fail('Failed to find the URL') + +		self.packages.append((self.pyfile.package().name, [ url ], self.pyfile.package().folder)) diff --git a/pyload/plugins/hoster/CloudzerNet.py b/pyload/plugins/hoster/CloudzerNet.py new file mode 100644 index 000000000..6c02203ca --- /dev/null +++ b/pyload/plugins/hoster/CloudzerNet.py @@ -0,0 +1,72 @@ +# -*- coding: utf-8 -*- +import re +from module.plugins.internal.SimpleHoster import SimpleHoster +from module.common.json_layer import json_loads +from module.plugins.internal.CaptchaService import ReCaptcha +from module.network.RequestFactory import getURL +from module.utils import parseFileSize + + +def getInfo(urls): +    for url in urls: +        header = getURL(url, just_header=True) +        if 'Location: http://cloudzer.net/404' in header: +            file_info = (url, 0, 1, url) +        else: +            if url.endswith('/'): +                api_data = getURL(url + 'status') +            else: +                api_data = getURL(url + '/status') +            name, size = api_data.splitlines() +            size = parseFileSize(size) +            file_info = (name, size, 2, url) +        yield file_info + + +class CloudzerNet(SimpleHoster): +    __name__ = "CloudzerNet" +    __type__ = "hoster" +    __pattern__ = r"http://(www\.)?(cloudzer\.net/file/|clz\.to/(file/)?)(?P<ID>\w+).*" +    __version__ = "0.03" +    __description__ = """Cloudzer.net hoster plugin""" +    __author_name__ = ("gs", "z00nx", "stickell") +    __author_mail__ = ("I-_-I-_-I@web.de", "z00nx0@gmail.com", "l.stickell@yahoo.it") + +    FILE_SIZE_PATTERN = '<span class="size">(?P<S>[^<]+)</span>' +    WAIT_PATTERN = '<meta name="wait" content="(\d+)">' +    FILE_OFFLINE_PATTERN = r'Please check the URL for typing errors, respectively' +    CAPTCHA_KEY = '6Lcqz78SAAAAAPgsTYF3UlGf2QFQCNuPMenuyHF3' + +    def handleFree(self): +        found = re.search(self.WAIT_PATTERN, self.html) +        seconds = int(found.group(1)) +        self.logDebug("Found wait", seconds) +        self.setWait(seconds + 1) +        self.wait() +        response = self.load('http://cloudzer.net/io/ticket/slot/%s' % self.file_info['ID'], post=' ', cookies=True) +        self.logDebug("Download slot request response", response) +        response = json_loads(response) +        if response["succ"] is not True: +            self.fail("Unable to get a download slot") + +        recaptcha = ReCaptcha(self) +        challenge, response = recaptcha.challenge(self.CAPTCHA_KEY) +        post_data = {"recaptcha_challenge_field": challenge, "recaptcha_response_field": response} +        response = json_loads(self.load('http://cloudzer.net/io/ticket/captcha/%s' % self.file_info['ID'], post=post_data, cookies=True)) +        self.logDebug("Captcha check response", response) +        self.logDebug("First check") + +        if "err" in response: +            if response["err"] == "captcha": +                self.logDebug("Wrong captcha") +                self.invalidCaptcha() +                self.retry() +            elif "Sie haben die max" in response["err"] or "You have reached the max" in response["err"]: +                self.logDebug("Download limit reached, waiting an hour") +                self.setWait(3600, True) +                self.wait() +        if "type" in response: +            if response["type"] == "download": +                url = response["url"] +                self.logDebug("Download link", url) +                self.download(url, disposition=True) diff --git a/pyload/plugins/hoster/CramitIn.py b/pyload/plugins/hoster/CramitIn.py new file mode 100644 index 000000000..171fba0ff --- /dev/null +++ b/pyload/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.04" +    __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.resumeDownload = self.multiDL = self.premium  + +getInfo = create_getInfo(CramitIn)
\ No newline at end of file diff --git a/pyload/plugins/hoster/CrockoCom.py b/pyload/plugins/hoster/CrockoCom.py new file mode 100644 index 000000000..f075d073b --- /dev/null +++ b/pyload/plugins/hoster/CrockoCom.py @@ -0,0 +1,71 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo +from module.plugins.internal.CaptchaService import ReCaptcha +import re + +class CrockoCom(SimpleHoster): +    __name__ = "CrockoCom" +    __type__ = "hoster" +    __pattern__ = r"http://(www\.)?(crocko|easy-share).com/.*" +    __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_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+)';") +    CAPTCHA_KEY_PATTERN = re.compile(r'Recaptcha.create\("([^"]+)"') +     +    FORM_PATTERN = r'<form  method="post" action="([^"]+)">(.*?)</form>' +    FORM_INPUT_PATTERN = r'<input[^>]* name="?([^" ]+)"? value="?([^" ]+)"?[^>]*>' +     +    FILE_NAME_REPLACEMENTS = [(r'<[^>]*>', '')] + +    def handleFree(self): +        if "You need Premium membership to download this file." in self.html: +            self.fail("You need Premium membership to download this file.") +     +        url = False                +        for i in range(5): +            found = re.search(self.CAPTCHA_URL_PATTERN, self.html) +            if found:  +                url, wait_time = 'http://crocko.com' + found.group(1), found.group(2) +                self.setWait(wait_time) +                self.wait() +                self.html = self.load(url) +            else:      +                break  +                 +        found = re.search(self.CAPTCHA_KEY_PATTERN, self.html) +        if not found: self.parseError('Captcha KEY') +        captcha_key = found.group(1) +         +        found = re.search(self.FORM_PATTERN, self.html, re.DOTALL) +        if not found: self.parseError('ACTION') +        action, form = found.groups() +        inputs = dict(re.findall(self.FORM_INPUT_PATTERN, form)) +         +        recaptcha = ReCaptcha(self) +         +        for i in range(5): +            inputs['recaptcha_challenge_field'], inputs['recaptcha_response_field'] = recaptcha.challenge(captcha_key) +            self.download(action, post = inputs) +             +            check = self.checkDownload({ +                "captcha_err": self.CAPTCHA_KEY_PATTERN +                }) + +            if check == "captcha_err": +                self.invalidCaptcha() +            else: +                break +        else: +            self.fail('No valid captcha solution received') + +getInfo = create_getInfo(CrockoCom) +            
\ No newline at end of file diff --git a/pyload/plugins/hoster/CyberlockerCh.py b/pyload/plugins/hoster/CyberlockerCh.py new file mode 100644 index 000000000..57dd26787 --- /dev/null +++ b/pyload/plugins/hoster/CyberlockerCh.py @@ -0,0 +1,15 @@ +# -*- coding: utf-8 -*- +from module.plugins.hoster.XFileSharingPro import XFileSharingPro, create_getInfo + +class CyberlockerCh(XFileSharingPro): +    __name__ = "CyberlockerCh" +    __type__ = "hoster" +    __pattern__ = r"http://(www\.)?cyberlocker\.ch/\w{12}" +    __version__ = "0.01" +    __description__ = """Cyberlocker.ch hoster plugin""" +    __author_name__ = ("stickell") +    __author_mail__ = ("l.stickell@yahoo.it") + +    HOSTER_NAME = "cyberlocker.ch" + +getInfo = create_getInfo(CyberlockerCh) diff --git a/pyload/plugins/hoster/CzshareCom.py b/pyload/plugins/hoster/CzshareCom.py new file mode 100644 index 000000000..347427586 --- /dev/null +++ b/pyload/plugins/hoster/CzshareCom.py @@ -0,0 +1,160 @@ +# -*- 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 +""" + +# Test links (random.bin): +# http://czshare.com/5278880/random.bin + +import re +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo, PluginParseError +from module.utils import parseFileSize + +class CzshareCom(SimpleHoster): +    __name__ = "CzshareCom" +    __type__ = "hoster" +    __pattern__ = r"http://(\w*\.)*czshare\.(com|cz)/(\d+/|download.php\?).*" +    __version__ = "0.93" +    __description__ = """CZshare.com""" +    __author_name__ = ("zoidberg") + +    FILE_NAME_PATTERN = r'<div class="tab" id="parameters">\s*<p>\s*Cel. n.zev: <a href=[^>]*>(?P<N>[^<]+)</a>' +    FILE_SIZE_PATTERN = r'<div class="tab" id="category">(?:\s*<p>[^\n]*</p>)*\s*Velikost:\s*(?P<S>[0-9., ]+)(?P<U>[kKMG])i?B\s*</div>' +    FILE_OFFLINE_PATTERN = r'<div class="header clearfix">\s*<h2 class="red">' +     +    FILE_SIZE_REPLACEMENTS = [(' ', '')] +    FILE_URL_REPLACEMENTS = [(r'http://[^/]*/download.php\?.*?id=(\w+).*', r'http://czshare.com/\1/x/')] +    SH_CHECK_TRAFFIC = True + +    FREE_URL_PATTERN = r'<a href="([^"]+)" class="page-download">[^>]*alt="([^"]+)" /></a>' +    FREE_FORM_PATTERN = r'<form action="download.php" method="post">\s*<img src="captcha.php" id="captcha" />(.*?)</form>' +    PREMIUM_FORM_PATTERN = r'<form action="/profi_down.php" method="post">(.*?)</form>' +    FORM_INPUT_PATTERN = r'<input[^>]* name="([^"]+)" value="([^"]+)"[^>]*/>' +    MULTIDL_PATTERN = r"<p><font color='red'>Z[^<]*PROFI.</font></p>" +    USER_CREDIT_PATTERN = r'<div class="credit">\s*kredit: <strong>([0-9., ]+)([kKMG]i?B)</strong>\s*</div><!-- .credit -->' + +    def setup(self): +        self.multiDL = self.resumeDownload = True if self.premium else False +        self.chunkLimit = 1 + +    def checkTrafficLeft(self): +        # check if user logged in +        found = re.search(self.USER_CREDIT_PATTERN, self.html) +        if not found: +            self.account.relogin(self.user) +            self.html = self.load(self.pyfile.url, cookies=True, decode=True) +            found = re.search(self.USER_CREDIT_PATTERN, self.html) +            if not found: return False + +        # check user credit +        try: +            credit = parseFileSize(found.group(1).replace(' ',''), found.group(2)) +            self.logInfo("Premium download for %i KiB of Credit" % (self.pyfile.size / 1024)) +            self.logInfo("User %s has %i KiB left" % (self.user, credit / 1024)) +            if credit < self.pyfile.size: +                self.logInfo("Not enough credit to download file %s" % self.pyfile.name) +                return False +        except Exception, e: +            # let's continue and see what happens... +            self.logError('Parse error (CREDIT): %s' % e) +         +        return True  +     +    def handlePremium(self):         +        # parse download link +        try: +            form = re.search(self.PREMIUM_FORM_PATTERN, self.html, re.DOTALL).group(1) +            inputs = dict(re.findall(self.FORM_INPUT_PATTERN, form)) +        except Exception, e: +            self.logError("Parse error (FORM): %s" % e) +            self.resetAccount() + +        # download the file, destination is determined by pyLoad +        self.download("http://czshare.com/profi_down.php", post=inputs, disposition=True) +        self.checkDownloadedFile() + +    def handleFree(self): +        # get free url +        found = re.search(self.FREE_URL_PATTERN, self.html) +        if found is None: +            raise PluginParseError('Free URL') +        parsed_url = "http://czshare.com" + found.group(1) +        self.logDebug("PARSED_URL:" + parsed_url) + +        # get download ticket and parse html +        self.html = self.load(parsed_url, cookies=True, decode=True) +        if re.search(self.MULTIDL_PATTERN, self.html): +            self.longWait(300, 12) + +        try: +            form = re.search(self.FREE_FORM_PATTERN, self.html, re.DOTALL).group(1) +            inputs = dict(re.findall(self.FORM_INPUT_PATTERN, form)) +            self.pyfile.size = int(inputs['size']) +        except Exception, e: +            self.logError(e) +            raise PluginParseError('Form') + +        # get and decrypt captcha         +        captcha_url = 'http://czshare.com/captcha.php' +        for i in range(5): +            inputs['captchastring2'] = self.decryptCaptcha(captcha_url) +            self.html = self.load(parsed_url, cookies=True, post=inputs, decode=True) +            if u"<li>Zadaný ověřovací kód nesouhlasí!</li>" in self.html: +                self.invalidCaptcha() +            elif re.search(self.MULTIDL_PATTERN, self.html): +                self.longWait(300, 12) +            else: +                self.correctCaptcha() +                break +        else: +            self.fail("No valid captcha code entered") +         +        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.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) +        self.checkDownloadedFile() + +    def checkDownloadedFile(self): +        # check download +        check = self.checkDownload({ +            "tempoffline": re.compile(r"^Soubor je do.*asn.* nedostupn.*$"), +            "credit": re.compile(r"^Nem.*te dostate.*n.* kredit.$"), +            "multi_dl": re.compile(self.MULTIDL_PATTERN), +            "captcha_err": "<li>Zadaný ověřovací kód nesouhlasí!</li>" +            }) + +        if check == "tempoffline": +            self.fail("File not available - try later") +        if check == "credit": +            self.resetAccount() +        elif check == "multi_dl": +            self.longWait(300, 12) +        elif check == "captcha_err": +            self.invalidCaptcha() +            self.retry() +         +getInfo = create_getInfo(CzshareCom) diff --git a/pyload/plugins/hoster/DailymotionCom.py b/pyload/plugins/hoster/DailymotionCom.py new file mode 100644 index 000000000..1b411393d --- /dev/null +++ b/pyload/plugins/hoster/DailymotionCom.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import re +from urllib import unquote +from module.plugins.Hoster import Hoster + +class DailymotionCom(Hoster): +    __name__ = 'DailymotionCom' +    __type__ = 'hoster' +    __pattern__ = r'http://www.dailymotion.com/.*' +    __version__ = '0.1' +    __description__ = """Dailymotion Video Download Hoster""" +    __author_name__ = ("Peekayy") +    __author_mail__ = ("peekayy.dev@gmail.com") + +    def process(self, pyfile): +        html = self.load(pyfile.url, decode=True) + +        for pattern in (r'name="title" content="Dailymotion \\-(.*?)\\- ein Film', +                        r'class="title" title="(.*?)"', +                        r'<span class="title foreground" title="(.*?)">', +                        r'"(?:vs_videotitle|videoTitle|dm_title|ss_mediaTitle)": "(.*?)"'): +            filename = re.search(pattern, html) +            if filename is not None: break +        else: +            self.fail("Unable to find file name") + +        pyfile.name = filename.group(1)+'.mp4' +        self.logDebug('Filename='+pyfile.name) +        allLinksInfo = re.search(r'"sequence":"(.*?)"', html) +        self.logDebug(allLinksInfo.groups()) +        allLinksInfo = unquote(allLinksInfo.group(1)) + +        for quality in ('hd720URL', 'hqURL', 'sdURL', 'ldURL', ''): +            dlLink = self.getQuality(quality, allLinksInfo) +            if dlLink is not None: break +        else: +            self.fail(r'Unable to find video URL') + +        self.logDebug(dlLink) +        self.download(dlLink) + +    def getQuality(self, quality, data): +        link = re.search('"' + quality + '":"(http:[^<>"\']+)"', data) +        if link is not None: +            return link.group(1).replace('\\','')
\ No newline at end of file diff --git a/pyload/plugins/hoster/DataHu.py b/pyload/plugins/hoster/DataHu.py new file mode 100644 index 000000000..7abd93d1f --- /dev/null +++ b/pyload/plugins/hoster/DataHu.py @@ -0,0 +1,53 @@ +# -*- coding: utf-8 -*- + +############################################################################ +# This program is free software: you can redistribute it and/or modify     # +# it under the terms of the GNU Affero 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 Affero General Public License for more details.                      # +#                                                                          # +# You should have received a copy of the GNU Affero General Public License # +# along with this program.  If not, see <http://www.gnu.org/licenses/>.    # +############################################################################ + +# Test links (random.bin): +# http://data.hu/get/6381232/random.bin + +import re + +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo + + +class DataHu(SimpleHoster): +    __name__ = "DataHu" +    __type__ = "hoster" +    __pattern__ = r"http://(www\.)?data.hu/get/\w+" +    __version__ = "0.01" +    __description__ = """Data.hu Download Hoster""" +    __author_name__ = ("crash", "stickell") +    __author_mail__ = ("l.stickell@yahoo.it") + +    FILE_INFO_PATTERN = ur'<title>(?P<N>.*) \((?P<S>[^)]+)\) let\xf6lt\xe9se</title>' +    FILE_OFFLINE_PATTERN = ur'Az adott f\xe1jl nem l\xe9tezik' +    DIRECT_LINK_PATTERN = r'<div class="download_box_button"><a href="([^"]+)">' + +    def handleFree(self): +        self.resumeDownload = True +        self.html = self.load(self.pyfile.url, decode=True) + +        m = re.search(self.DIRECT_LINK_PATTERN, self.html) +        if m: +            url = m.group(1) +            self.logDebug('Direct link: ' + url) +        else: +            self.parseError('Unable to get direct link') + +        self.download(url, disposition=True) + + +getInfo = create_getInfo(DataHu) diff --git a/pyload/plugins/hoster/DataportCz.py b/pyload/plugins/hoster/DataportCz.py new file mode 100644 index 000000000..3dc581bf1 --- /dev/null +++ b/pyload/plugins/hoster/DataportCz.py @@ -0,0 +1,68 @@ +# -*- 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 pycurl import FOLLOWLOCATION +     +class DataportCz(SimpleHoster): +    __name__ = "DataportCz" +    __type__ = "hoster" +    __pattern__ = r"http://(?:.*?\.)?dataport.cz/file/(.*)" +    __version__ = "0.37" +    __description__ = """Dataport.cz plugin - free only""" +    __author_name__ = ("zoidberg") + +    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>' +    FILE_URL_REPLACEMENTS = [(__pattern__, r'http://www.dataport.cz/file/\1')] +     +    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://www.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/pyload/plugins/hoster/DateiTo.py b/pyload/plugins/hoster/DateiTo.py new file mode 100644 index 000000000..061881e4b --- /dev/null +++ b/pyload/plugins/hoster/DateiTo.py @@ -0,0 +1,94 @@ +# -*- 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.internal.CaptchaService import ReCaptcha + +class DateiTo(SimpleHoster): +    __name__ = "DateiTo" +    __type__ = "hoster" +    __pattern__ = r"http://(?:www\.)?datei\.to/datei/(?P<ID>\w+)\.html" +    __version__ = "0.02" +    __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: +            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.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/pyload/plugins/hoster/DdlstorageCom.py b/pyload/plugins/hoster/DdlstorageCom.py new file mode 100644 index 000000000..5eaebf1d1 --- /dev/null +++ b/pyload/plugins/hoster/DdlstorageCom.py @@ -0,0 +1,19 @@ +# -*- 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.07" +    __description__ = """DDLStorage.com hoster plugin""" +    __author_name__ = ("zoidberg", "stickell") +    __author_mail__ = ("zoidberg@mujmail.cz", "l.stickell@yahoo.it") + +    FILE_INFO_PATTERN = r'<p class="sub_title"[^>]*>(?P<N>.+) \((?P<S>[^)]+)\)</p>' +    HOSTER_NAME = "ddlstorage.com" + + +getInfo = create_getInfo(DdlstorageCom)
\ No newline at end of file diff --git a/pyload/plugins/hoster/DebridItaliaCom.py b/pyload/plugins/hoster/DebridItaliaCom.py new file mode 100644 index 000000000..1c2f4246b --- /dev/null +++ b/pyload/plugins/hoster/DebridItaliaCom.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 Affero 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 Affero General Public License for more details.                      # +#                                                                          # +# You should have received a copy of the GNU Affero General Public License # +# along with this program.  If not, see <http://www.gnu.org/licenses/>.    # +############################################################################ + +import re + +from module.plugins.Hoster import Hoster + + +class DebridItaliaCom(Hoster): +    __name__ = "DebridItaliaCom" +    __version__ = "0.04" +    __type__ = "hoster" +    __pattern__ = r"https?://.*debriditalia\.com" +    __description__ = """Debriditalia.com hoster plugin""" +    __author_name__ = ("stickell") +    __author_mail__ = ("l.stickell@yahoo.it") + +    def init(self): +        self.chunkLimit = -1 +        self.resumeDownload = True + +    def process(self, pyfile): +        if not self.account: +            self.logError(_("Please enter your %s account or deactivate this plugin") % "DebridItalia") +            self.fail("No DebridItalia account provided") + +        self.logDebug("Old URL: %s" % pyfile.url) +        if re.match(self.__pattern__, pyfile.url): +            new_url = pyfile.url +        else: +            url = "http://debriditalia.com/linkgen2.php?xjxfun=convertiLink&xjxargs[]=S<![CDATA[%s]]>" % pyfile.url +            page = self.load(url) +            self.logDebug("XML data: %s" % page) + +            if 'File not available' in page: +                self.fail('File not available') +            else: +                new_url = re.search(r'<a href="(?:[^"]+)">(?P<direct>[^<]+)</a>', page).group('direct') + +        self.logDebug("New URL: %s" % new_url) + +        self.download(new_url, disposition=True) + +        check = self.checkDownload({"empty": re.compile(r"^$")}) + +        if check == "empty": +            self.retry(5, 120, 'Empty file downloaded') diff --git a/pyload/plugins/hoster/DepositfilesCom.py b/pyload/plugins/hoster/DepositfilesCom.py new file mode 100644 index 000000000..ee5fdf6af --- /dev/null +++ b/pyload/plugins/hoster/DepositfilesCom.py @@ -0,0 +1,112 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import re +from urllib import unquote +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo +from module.network.RequestFactory import getURL +from module.plugins.internal.CaptchaService import ReCaptcha + +class DepositfilesCom(SimpleHoster): +    __name__ = "DepositfilesCom" +    __type__ = "hoster" +    __pattern__ = r"http://[\w\.]*?(depositfiles\.com|dfiles\.eu)(/\w{1,3})?/files/[\w]+" +    __version__ = "0.44" +    __description__ = """Depositfiles.com Download Hoster""" +    __author_name__ = ("spoob", "zoidberg") +    __author_mail__ = ("spoob@pyload.org", "zoidberg@mujmail.cz") + +    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>' +    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 id="downloader_file_form" action="(http://.+?\.(dfiles\.eu|depositfiles\.com)/.+?)" method="post"' + +    def setup(self): +        self.multiDL = False +        self.resumeDownload = self.premium + +    def handleFree(self): +        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: +            self.logInfo("DepositFiles.com: The file is being checked. Waiting 1 minute.") +            self.setWait(61) +            self.wait() +            self.retry() + +        wait = re.search(r'html_download_api-limit_interval\">(\d+)</span>', self.html) +        if wait: +            wait_time = int(wait.group(1)) +            self.logInfo( "%s: Traffic used up. Waiting %d seconds." % (self.__name__, wait_time) ) +            self.setWait(wait_time) +            self.wantReconnect = True +            self.wait() +            self.retry() + +        wait = re.search(r'>Try in (\d+) minutes or use GOLD account', self.html) +        if wait: +            wait_time = int(wait.group(1)) +            self.logInfo( "%s: All free slots occupied. Waiting %d minutes." % (self.__name__, wait_time) ) +            self.setWait(wait_time * 60, False) + +        wait = re.search(r'Please wait (\d+) sec', self.html) +        if wait: +            self.setWait(int(wait.group(1))) + +        found = re.search(r"var fid = '(\w+)';", self.html) +        if not found: self.retry(wait_time=5) +        params = {'fid' : found.group(1)} +        self.logDebug ("FID: %s" % params['fid']) + +        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) + +        self.wait() +        recaptcha = ReCaptcha(self) + +        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: self.parseError('Captcha key') +                if 'response' in params: self.invalidCaptcha() +                params['challenge'], params['response'] = recaptcha.challenge(captcha_key) +                self.logDebug(params) +                continue + +            found = re.search(self.DOWNLOAD_LINK_PATTERN, self.html) +            if found: +                if 'response' in params: self.correctCaptcha() +                link = unquote(found.group(1)) +                self.logDebug ("LINK: %s" % link) +                break +            else: +                self.parseError('Download link') +        else: +            self.fail('No valid captcha response received') + +        try: +            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.multiDL = True +        self.download(link, disposition = True) + +getInfo = create_getInfo(DepositfilesCom) diff --git a/pyload/plugins/hoster/DlFreeFr.py b/pyload/plugins/hoster/DlFreeFr.py new file mode 100644 index 000000000..67c2d6c17 --- /dev/null +++ b/pyload/plugins/hoster/DlFreeFr.py @@ -0,0 +1,183 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import re +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.24" +    __description__ = """dl.free.fr download hoster""" +    __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])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'    +                     +    def setup(self): +        self.limitDL = 5 +        self.resumeDownload = True +        self.chunkLimit = 1         + +    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) +         +        self.html = None +        if headers.get('code') == 302: +            valid_url = headers.get('location') +            headers = self.load(valid_url, just_header = True) +         +        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) +                         +        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)    diff --git a/pyload/plugins/hoster/EasybytezCom.py b/pyload/plugins/hoster/EasybytezCom.py new file mode 100644 index 000000000..98691a641 --- /dev/null +++ b/pyload/plugins/hoster/EasybytezCom.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 +""" + +from module.plugins.hoster.XFileSharingPro import XFileSharingPro, create_getInfo + + +class EasybytezCom(XFileSharingPro): +    __name__ = "EasybytezCom" +    __type__ = "hoster" +    __pattern__ = r"http://(?:\w*\.)?easybytez.com/(\w+).*" +    __version__ = "0.17" +    __description__ = """easybytez.com""" +    __author_name__ = ("zoidberg", "stickell") +    __author_mail__ = ("zoidberg@mujmail.cz", "l.stickell@yahoo.it") + +    FILE_INFO_PATTERN = r'<span class="name">(?P<N>.+)</span><br>\s*<span class="size">(?P<S>[^<]+)</span>' +    FILE_OFFLINE_PATTERN = r'<h1>File not available</h1>' + +    DIRECT_LINK_PATTERN = r'(http://(\w+\.(easyload|easybytez|zingload)\.(com|to)|\d+\.\d+\.\d+\.\d+)/files/\d+/\w+/[^"<]+)' +    OVR_DOWNLOAD_LINK_PATTERN = r'<h2>Download Link</h2>\s*<textarea[^>]*>([^<]+)' +    OVR_KILL_LINK_PATTERN = r'<h2>Delete Link</h2>\s*<textarea[^>]*>([^<]+)' +    ERROR_PATTERN = r'(?:class=["\']err["\'][^>]*>|<Center><b>)(.*?)</' + +    HOSTER_NAME = "easybytez.com" + +    def setup(self): +        self.resumeDownload = self.multiDL = self.premium + + +getInfo = create_getInfo(EasybytezCom) diff --git a/pyload/plugins/hoster/EdiskCz.py b/pyload/plugins/hoster/EdiskCz.py new file mode 100644 index 000000000..a253be0d9 --- /dev/null +++ b/pyload/plugins/hoster/EdiskCz.py @@ -0,0 +1,62 @@ +# -*- 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 EdiskCz(SimpleHoster): +    __name__ = "EdiskCz" +    __type__ = "hoster" +    __pattern__ = r"http://(\w*\.)?edisk.(cz|sk|eu)/(stahni|sk/stahni|en/download)/.*" +    __version__ = "0.21" +    __description__ = """Edisk.cz""" +    __author_name__ = ("zoidberg") + +    URL_PATTERN = r'<form name = "formular" action = "([^"]+)" method = "post">' +    FILE_INFO_PATTERN = r'<span class="fl" title="(?P<N>[^"]+)">\s*.*?\((?P<S>[0-9.]*) (?P<U>[kKMG])i?B\)</h1></span>' +    ACTION_PATTERN = r'/en/download/(\d+/.*\.html)' +    DLLINK_PATTERN = r'http://.*edisk.cz.*\.html' +    FILE_OFFLINE_PATTERN = r'<h3>This file does not exist due to one of the following:</h3><ul><li>' + +    def setup(self): +        self.multiDL = False + +    def process(self, pyfile): +        url = re.sub("/(stahni|sk/stahni)/", "/en/download/", pyfile.url) + +        self.logDebug('URL:' + url) + +        found = re.search(self.ACTION_PATTERN, url) +        if found is None: self.parseError("ACTION") +        action = found.group(1) + +        self.html = self.load(url, decode=True) +        self.getFileInfo() + +        self.html = self.load(re.sub("/en/download/", "/en/download-slow/", url)) + +        url = self.load(re.sub("/en/download/", "/x-download/", url), post={ +            "action": action +        }) + +        if not re.match(self.DLLINK_PATTERN, url): +            self.fail("Unexpected server response") + +        self.download(url) + +getInfo = create_getInfo(EdiskCz)        
\ No newline at end of file diff --git a/pyload/plugins/hoster/EgoFilesCom.py b/pyload/plugins/hoster/EgoFilesCom.py new file mode 100644 index 000000000..274286cf1 --- /dev/null +++ b/pyload/plugins/hoster/EgoFilesCom.py @@ -0,0 +1,103 @@ +# -*- coding: utf-8 -*- + +############################################################################ +# This program is free software: you can redistribute it and/or modify     # +# it under the terms of the GNU Affero 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 Affero General Public License for more details.                      # +#                                                                          # +# You should have received a copy of the GNU Affero General Public License # +# along with this program.  If not, see <http://www.gnu.org/licenses/>.    # +############################################################################ + +# Test link (random.bin): +# http://egofiles.com/mOZfMI1WLZ6HBkGG/random.bin + +import re + +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo +from module.plugins.internal.CaptchaService import ReCaptcha + + +class EgoFilesCom(SimpleHoster): +    __name__ = "EgoFilesCom" +    __type__ = "hoster" +    __pattern__ = r"https?://(www\.)?egofiles.com/(\w+)" +    __version__ = "0.13" +    __description__ = """Egofiles.com Download Hoster""" +    __author_name__ = ("stickell") +    __author_mail__ = ("l.stickell@yahoo.it") + +    FILE_INFO_PATTERN = r'<div class="down-file">\s+(?P<N>[^\t]+)\s+<div class="file-properties">\s+(File size|Rozmiar): (?P<S>[\w.]+) (?P<U>\w+) \|' +    FILE_OFFLINE_PATTERN = r'(File size|Rozmiar): 0 KB' +    WAIT_TIME_PATTERN = r'For next free download you have to wait <strong>((?P<m>\d*)m)? ?((?P<s>\d+)s)?</strong>' +    DIRECT_LINK_PATTERN = r'<a href="(?P<link>[^"]+)">Download ></a>' +    RECAPTCHA_KEY = '6LeXatQSAAAAAHezcjXyWAni-4t302TeYe7_gfvX' + +    def init(self): +        self.file_info = {} +        # Set English language +        self.load("https://egofiles.com/ajax/lang.php?lang=en", just_header=True) + +    def process(self, pyfile): +        if self.premium and (not self.SH_CHECK_TRAFFIC or self.checkTrafficLeft()): +            self.handlePremium() +        else: +            self.handleFree() + +    def handleFree(self): +        self.html = self.load(self.pyfile.url, decode=True) +        self.getFileInfo() + +        # Wait time between free downloads +        if 'For next free download you have to wait' in self.html: +            m = re.search(self.WAIT_TIME_PATTERN, self.html).groupdict('0') +            waittime = int(m['m']) * 60 + int(m['s']) +            self.setWait(waittime, True) +            self.wait() + +        downloadURL = '' +        recaptcha = ReCaptcha(self) +        for i in xrange(5): +            challenge, response = recaptcha.challenge(self.RECAPTCHA_KEY) +            post_data = {'recaptcha_challenge_field': challenge, +                         'recaptcha_response_field': response} +            self.html = self.load(self.pyfile.url, post=post_data, decode=True) +            m = re.search(self.DIRECT_LINK_PATTERN, self.html) +            if not m: +                self.logInfo('Wrong captcha') +                self.invalidCaptcha() +            elif hasattr(m, 'group'): +                downloadURL = m.group('link') +                self.correctCaptcha() +                break +            else: +                self.fail('Unknown error - Plugin may be out of date') + +        if not downloadURL: +            self.fail("No Download url retrieved/all captcha attempts failed") + +        self.download(downloadURL, disposition=True) + +    def handlePremium(self): +        header = self.load(self.pyfile.url, just_header=True) +        if header.has_key('location'): +            self.logDebug('DIRECT LINK from header: ' + header['location']) +            self.download(header['location']) +        else: +            self.html = self.load(self.pyfile.url, decode=True) +            self.getFileInfo() +            m = re.search(r'<a href="(?P<link>[^"]+)">Download ></a>', self.html) +            if not m: +                self.parseError('Unable to detect direct download url') +            else: +                self.logDebug('DIRECT URL from html: ' + m.group('link')) +                self.download(m.group('link'), disposition=True) + + +getInfo = create_getInfo(EgoFilesCom) diff --git a/pyload/plugins/hoster/EuroshareEu.py b/pyload/plugins/hoster/EuroshareEu.py new file mode 100644 index 000000000..5224dfd9f --- /dev/null +++ b/pyload/plugins/hoster/EuroshareEu.py @@ -0,0 +1,74 @@ +# -*- 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 EuroshareEu(SimpleHoster): +    __name__ = "EuroshareEu" +    __type__ = "hoster" +    __pattern__ = r"http://(\w*\.)?euroshare.(eu|sk|cz|hu|pl)/file/.*" +    __version__ = "0.25" +    __description__ = """Euroshare.eu""" +    __author_name__ = ("zoidberg") + +    FILE_INFO_PATTERN = r'<span style="float: left;"><strong>(?P<N>.+?)</strong> \((?P<S>.+?)\)</span>' +    FILE_OFFLINE_PATTERN = ur'<h2>S.bor sa nena.iel</h2>|Požadovaná stránka neexistuje!' + +    FREE_URL_PATTERN = r'<a href="(/file/\d+/[^/]*/download/)"><div class="downloadButton"' +    ERR_PARDL_PATTERN = r'<h2>Prebieha s.ahovanie</h2>|<p>Naraz je z jednej IP adresy mo.n. s.ahova. iba jeden s.bor' +    ERR_NOT_LOGGED_IN_PATTERN = r'href="/customer-zone/login/"' + +    FILE_URL_REPLACEMENTS = [(r"(http://[^/]*\.)(sk|cz|hu|pl)/", r"\1eu/")] + +    def setup(self): +        self.multiDL = self.resumeDownload = self.premium +        self.req.setOption("timeout", 120) + +    def handlePremium(self): +        if self.ERR_NOT_LOGGED_IN_PATTERN in self.html: +            self.account.relogin(self.user) +            self.retry(reason="User not logged in") + +        self.download(self.pyfile.url.rstrip('/') + "/download/") + +        check = self.checkDownload({"login": re.compile(self.ERR_NOT_LOGGED_IN_PATTERN), +                                    "json": re.compile(r'\{"status":"error".*?"message":"(.*?)"') +                                   }) +        if check == "login" or (check == "json" and self.lastCheck.group(1) == "Access token expired"): +            self.account.relogin(self.user) +            self.retry(reason="Access token expired") +        elif check == "json": +            self.fail(self.lastCheck.group(1)) + +    def handleFree(self): +        if re.search(self.ERR_PARDL_PATTERN, self.html) is not None: +            self.longWait(300, 12) + +        found = re.search(self.FREE_URL_PATTERN, self.html) +        if found is None: +            self.parseError("Parse error (URL)") +        parsed_url = "http://euroshare.eu%s" % found.group(1) +        self.logDebug("URL", parsed_url) +        self.download(parsed_url, disposition=True) + +        check = self.checkDownload({"multi_dl": re.compile(self.ERR_PARDL_PATTERN)}) +        if check == "multi_dl": +            self.longWait(300, 12) + +getInfo = create_getInfo(EuroshareEu)
\ No newline at end of file diff --git a/pyload/plugins/hoster/ExtabitCom.py b/pyload/plugins/hoster/ExtabitCom.py new file mode 100644 index 000000000..41a43fab5 --- /dev/null +++ b/pyload/plugins/hoster/ExtabitCom.py @@ -0,0 +1,87 @@ +# -*- 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.internal.CaptchaService 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|fid)/(?P<ID>\w+)" +    __version__ = "0.3" +    __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) diff --git a/pyload/plugins/hoster/FastshareCz.py b/pyload/plugins/hoster/FastshareCz.py new file mode 100644 index 000000000..1dbf9fe8f --- /dev/null +++ b/pyload/plugins/hoster/FastshareCz.py @@ -0,0 +1,96 @@ +# -*- 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 +""" + +# Test links (random.bin): +# http://www.fastshare.cz/2141189/random.bin + +import re +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo, replace_patterns + + +class FastshareCz(SimpleHoster): +    __name__ = "FastshareCz" +    __type__ = "hoster" +    __pattern__ = r"http://(?:\w*\.)?fastshare.cz/\d+/.+" +    __version__ = "0.15" +    __description__ = """FastShare.cz""" +    __author_name__ = ("zoidberg", "stickell") + +    FILE_INFO_PATTERN = r'<h1 class="dwp">(?P<N>[^<]+)</h1>\s*<div class="fileinfo">\s*(?:Velikost|Size)\s*: (?P<S>[^,]+),' +    FILE_OFFLINE_PATTERN = ur'<td align=center>Tento soubor byl smazán' +    FILE_URL_REPLACEMENTS = [('#.*','')] + +    FREE_URL_PATTERN = ur'<form method=post action=(/free/.*?)><b>Stáhnout FREE.*?<img src="([^"]*)">' +    PREMIUM_URL_PATTERN = r'(http://data\d+\.fastshare\.cz/download\.php\?id=\d+\&[^\s\"\'<>]+)' +    NOT_ENOUGH_CREDIC_PATTERN = "Nem.te dostate.n. kredit pro sta.en. tohoto souboru" + +    def process(self, pyfile): +        pyfile.url = replace_patterns(pyfile.url, self.FILE_URL_REPLACEMENTS) +        self.req.setOption("timeout", 120) +        if self.premium and (not self.SH_CHECK_TRAFFIC or self.checkTrafficLeft()): +            self.handlePremium() +        else: +            self.html = self.load(pyfile.url, decode = not self.SH_BROKEN_ENCODING, cookies = self.SH_COOKIES) +            self.getFileInfo() +            self.handleFree() + +    def handleFree(self): +        if u">100% FREE slotů je plných.<" in self.html: +            self.setWait(60, False) +            self.wait() +            self.retry(120, "No free slots") + +        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": "<title>FastShare.cz</title>|<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(6, "Paralell download") + +    def handlePremium(self): +        header = self.load(self.pyfile.url, just_header=True) +        if 'location' in header: +            url = header['location'] +        else: +            self.html = self.load(self.pyfile.url) +            self.getFileInfo() +            if self.NOT_ENOUGH_CREDIC_PATTERN in self.html: +                self.logWarning('Not enough traffic left') +                self.resetAccount() + +            found = re.search(self.PREMIUM_URL_PATTERN, self.html) +            if not found: self.parseError("Premium URL") +            url = found.group(1) + +        self.logDebug("PREMIUM URL: %s" % url) +        self.download(url) + +        check = self.checkDownload({"credit": re.compile(self.NOT_ENOUGH_CREDIC_PATTERN)}) +        if check == "credit": +            self.resetAccount() + +getInfo = create_getInfo(FastshareCz)
\ No newline at end of file diff --git a/pyload/plugins/hoster/FileApeCom.py b/pyload/plugins/hoster/FileApeCom.py new file mode 100644 index 000000000..f5182a788 --- /dev/null +++ b/pyload/plugins/hoster/FileApeCom.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import re + +from module.plugins.Hoster import Hoster + +class FileApeCom(Hoster): +    __name__ = "FileApeCom" +    __type__ = "hoster" +    __pattern__ = r"http://(www\.)?fileape\.com/(index\.php\?act=download\&id=|dl/)\w+" +    __version__ = "0.11" +    __description__ = """FileApe Download Hoster""" +    __author_name__ = ("espes") + +    def setup(self): +        self.multiDL = False +        self.html = None + +    def process(self, pyfile): +        self.pyfile = pyfile + +        self.html = self.load(self.pyfile.url) +         +        if "This file is either temporarily unavailable or does not exist" in self.html: +            self.offline() +         +        self.html = self.load(self.pyfile.url+"&g=1") +         +        continueMatch = re.search(r"window\.location = '(http://.*?)'", self.html) +        if not continueMatch: +            continueMatch = re.search(r"'(http://fileape\.com/\?act=download&t=[A-Za-z0-9_-]+)'", self.html) +        if continueMatch: +            continuePage = continueMatch.group(1) +        else: +            self.fail("Plugin Defect")  +         +        wait = 60 +        waitMatch = re.search("id=\"waitnumber\" style=\"font-size:2em; text-align:center; width:33px; height:33px;\">(\\d+)</span>", self.html) +        if waitMatch: +            wait = int(waitMatch.group(1)) +        self.setWait(wait+3) +        self.wait() +         +        self.html = self.load(continuePage) +        linkMatch = \ +            re.search(r"<div style=\"text-align:center; font-size: 30px;\"><a href=\"(http://.*?)\"", self.html) +        if not linkMatch: +            linkMatch = re.search(r"\"(http://tx\d+\.fileape\.com/[a-z]+/.*?)\"", self.html) +        if linkMatch: +            link = linkMatch.group(1) +        else: +            self.fail("Plugin Defect") +         +        pyfile.name = link.rpartition('/')[2] +         +        self.download(link) +         +        check = self.checkDownload({"exp": "Download ticket expired"}) +        if check == "exp": +            self.logInfo("Ticket expired, retrying...") +            self.retry()
\ No newline at end of file diff --git a/pyload/plugins/hoster/FilebeerInfo.py b/pyload/plugins/hoster/FilebeerInfo.py new file mode 100644 index 000000000..216ecfbca --- /dev/null +++ b/pyload/plugins/hoster/FilebeerInfo.py @@ -0,0 +1,15 @@ +# -*- coding: utf-8 -*- +from module.plugins.internal.DeadHoster import DeadHoster, create_getInfo + + +class FilebeerInfo(DeadHoster): +    __name__ = "FilebeerInfo" +    __type__ = "hoster" +    __pattern__ = r"http://(?:www\.)?filebeer\.info/(?!\d*~f)(?P<ID>\w+).*" +    __version__ = "0.03" +    __description__ = """Filebeer.info plugin""" +    __author_name__ = ("zoidberg") +    __author_mail__ = ("zoidberg@mujmail.cz") + + +getInfo = create_getInfo(FilebeerInfo)
\ No newline at end of file diff --git a/pyload/plugins/hoster/FilecloudIo.py b/pyload/plugins/hoster/FilecloudIo.py new file mode 100644 index 000000000..71af3e9dd --- /dev/null +++ b/pyload/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.internal.CaptchaService 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/pyload/plugins/hoster/FilefactoryCom.py b/pyload/plugins/hoster/FilefactoryCom.py new file mode 100644 index 000000000..fdde1f9d7 --- /dev/null +++ b/pyload/plugins/hoster/FilefactoryCom.py @@ -0,0 +1,133 @@ +# -*- coding: utf-8 -*- + +############################################################################ +# This program is free software: you can redistribute it and/or modify     # +# it under the terms of the GNU Affero 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 Affero General Public License for more details.                      # +#                                                                          # +# You should have received a copy of the GNU Affero General Public License # +# along with this program.  If not, see <http://www.gnu.org/licenses/>.    # +############################################################################ + +# Test links (random.bin): +# http://www.filefactory.com/file/ymxkmdud2o3/n/random.bin + +import re + +from module.plugins.internal.SimpleHoster import SimpleHoster +from module.network.RequestFactory import getURL +from module.utils import parseFileSize + + +def getInfo(urls): +    file_info = list() +    list_ids = dict() + +    # Create a dict id:url. Will be used to retrieve original url +    for url in urls: +        m = re.search(FilefactoryCom.__pattern__, url) +        list_ids[m.group('id')] = url + +    # WARN: There could be a limit of urls for request +    post_data = {'func': 'links', 'links': '\n'.join(urls)} +    rep = getURL('http://www.filefactory.com/tool/links.php', post=post_data, decode=True) + +    # Online links +    for m in re.finditer( +            r'innerText">\s*<h1 class="name">(?P<N>.+) \((?P<S>[\w.]+) (?P<U>\w+)\)</h1>\s*<p>http://www.filefactory.com/file/(?P<ID>\w+).*</p>\s*<p class="hidden size">', +            rep): +        file_info.append((m.group('N'), parseFileSize(m.group('S'), m.group('U')), 2, list_ids[m.group('ID')])) + +    # Offline links +    for m in re.finditer( +            r'innerText">\s*<h1>(http://www.filefactory.com/file/(?P<ID>\w+)/)</h1>\s*<p>\1</p>\s*<p class="errorResponse">Error: file not found</p>', +            rep): +        file_info.append((list_ids[m.group('ID')], 0, 1, list_ids[m.group('ID')])) + +    return file_info + + +class FilefactoryCom(SimpleHoster): +    __name__ = "FilefactoryCom" +    __type__ = "hoster" +    __pattern__ = r"https?://(?:www\.)?filefactory\.com/file/(?P<id>[a-zA-Z0-9]+)" +    __version__ = "0.41" +    __description__ = """Filefactory.Com File Download Hoster""" +    __author_name__ = ("stickell") +    __author_mail__ = ("l.stickell@yahoo.it") + +    DIRECT_LINK_PATTERN = r'<section id="downloadLink">\s*<p class="textAlignCenter">\s*<a href="([^"]+)">[^<]+</a>\s*</p>\s*</section>' + +    def process(self, pyfile): +        if not re.match(self.__pattern__ + r'/n/.+', pyfile.url):  # Not in standard format +            header = self.load(pyfile.url, just_header=True) +            if 'location' in header: +                self.pyfile.url = 'http://www.filefactory.com' + header['location'] + +        if self.premium and (not self.SH_CHECK_TRAFFIC or self.checkTrafficLeft()): +            self.handlePremium() +        else: +            self.handleFree() + +    def handleFree(self): +        self.html = self.load(self.pyfile.url, decode=True) +        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") + +        # Load the page that contains the direct link +        url = re.search(r"document\.location\.host \+\s*'(.+)';", self.html) +        if not url: +            self.parseError('Unable to detect free link') +        url = 'http://www.filefactory.com' + url.group(1) +        self.html = self.load(url, decode=True) + +        # Free downloads wait time +        waittime = re.search(r'id="startWait" value="(\d+)"', self.html) +        if not waittime: +            self.parseError('Unable to detect wait time') +        self.setWait(int(waittime.group(1))) +        self.wait() + +        # Parse the direct link and download it +        direct = re.search(r'data-href-direct="(.*)" class="button', self.html) +        if not direct: +            self.parseError('Unable to detect free direct link') +        direct = direct.group(1) +        self.logDebug('DIRECT LINK: ' + direct) +        self.download(direct, disposition=True) + +        check = self.checkDownload({"multiple": "You are currently downloading too many files at once.", +                                    "error": '<div id="errorMessage">'}) + +        if check == "multiple": +            self.logDebug("Parallel downloads detected; waiting 15 minutes") +            self.retry(wait_time=15 * 60, reason='Parallel downloads') +        elif check == "error": +            self.fail("Unknown error") + +    def handlePremium(self): +        header = self.load(self.pyfile.url, just_header=True) +        if 'location' in header: +            url = header['location'].strip() +            if not url.startswith("http://"): +                url = "http://www.filefactory.com" + url +        elif 'content-disposition' in header: +            url = self.pyfile.url +        else: +            html = self.load(self.pyfile.url) +            found = re.search(self.DIRECT_LINK_PATTERN, html) +            if found: +                url = found.group(1) +            else: +                self.parseError('Unable to detect premium direct link') + +        self.logDebug('DIRECT PREMIUM LINK: ' + url) +        self.download(url, disposition=True) diff --git a/pyload/plugins/hoster/FilejungleCom.py b/pyload/plugins/hoster/FilejungleCom.py new file mode 100644 index 000000000..fd833eef2 --- /dev/null +++ b/pyload/plugins/hoster/FilejungleCom.py @@ -0,0 +1,38 @@ +# -*- 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 +""" + +from module.plugins.hoster.FileserveCom import FileserveCom, checkFile +from module.plugins.Plugin import chunks + +class FilejungleCom(FileserveCom): +    __name__ = "FilejungleCom" +    __type__ = "hoster" +    __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") +     +    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/pyload/plugins/hoster/FilepostCom.py b/pyload/plugins/hoster/FilepostCom.py new file mode 100644 index 000000000..8e9df3f17 --- /dev/null +++ b/pyload/plugins/hoster/FilepostCom.py @@ -0,0 +1,135 @@ +# -*- 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 + +    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 +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo +from module.plugins.internal.CaptchaService import ReCaptcha +from module.common.json_layer import json_loads +from time import time + +class FilepostCom(SimpleHoster): +    __name__ = "FilepostCom" +    __type__ = "hoster" +    __pattern__ = r"https?://(?:www\.)?(?:filepost\.com/files|fp.io)/([^/]+).*" +    __version__ = "0.27" +    __description__ = """Filepost.com plugin - free only""" +    __author_name__ = ("zoidberg") +    __author_mail__ = ("zoidberg@mujmail.cz") + +    FILE_INFO_PATTERN = r'<input type="text" id="url" value=\'<a href[^>]*>(?P<N>[^>]+?) - (?P<S>[0-9\.]+ [kKMG]i?B)</a>\' class="inp_text"/>' +    #FILE_INFO_PATTERN = r'<h1>(?P<N>[^<]+)</h1>\s*<div class="ul">\s*<ul>\s*<li><span>Size:</span> (?P<S>[0-9.]+) (?P<U>[kKMG])i?B</li>' +    FILE_OFFLINE_PATTERN = r'class="error_msg_title"> Invalid or Deleted File. </div>|<div class="file_info file_info_deleted">' +    RECAPTCHA_KEY_PATTERN = r"Captcha.init\({\s*key:\s*'([^']+)'" +    FLP_TOKEN_PATTERN = r"set_store_options\({token: '([^']+)'" + +    def handleFree(self): +        # Find token and captcha key +        file_id = re.search(self.__pattern__, self.pyfile.url).group(1) + +        found = re.search(self.FLP_TOKEN_PATTERN, self.html) +        if not found: self.parseError("Token") +        flp_token = found.group(1) + +        found = re.search(self.RECAPTCHA_KEY_PATTERN, self.html) +        if not found: self.parseError("Captcha key") +        captcha_key = found.group(1) + +        # Get wait time +        get_dict = {'SID' : self.req.cj.getCookie('SID'), 'JsHttpRequest' : str(int(time()*10000)) + '-xml'} +        post_dict = {'action' : 'set_download', 'token' : flp_token, 'code' : file_id}                     +        wait_time = int(self.getJsonResponse(get_dict, post_dict, 'wait_time'))      + +        if wait_time > 0: +            self.setWait(wait_time) +            self.wait()                                +         +        post_dict = {"token" : flp_token, "code" : file_id, "file_pass" : ''} +         +        if 'var is_pass_exists = true;' in self.html: +            # Solve password             +            for file_pass in self.getPassword().splitlines(): +                get_dict['JsHttpRequest'] = str(int(time()*10000)) + '-xml'            +                post_dict['file_pass'] = file_pass +                self.logInfo("Password protected link, trying " + file_pass)                 +                                     +                download_url = self.getJsonResponse(get_dict, post_dict, 'link')                +                if download_url:  +                    break +                       +            else: self.fail("No or incorrect password")          +         +        else: +            # Solve recaptcha +            recaptcha = ReCaptcha(self) +             +            for pokus in range(5): +                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"])) +                  +                download_url = self.getJsonResponse(get_dict, post_dict, 'link') +                if download_url: +                    if pokus: self.correctCaptcha() +                    break +                elif pokus: +                    self.invalidCaptcha() +                                 +            else: self.fail("Invalid captcha") +         +        # Download +        self.download(download_url)        +     +    def getJsonResponse(self, get_dict, post_dict, field):      +        json_response = json_loads(self.load('https://filepost.com/files/get/', get = get_dict, post = post_dict)) +        self.logDebug(json_response) +         +        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(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(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) diff --git a/pyload/plugins/hoster/FilerNet.py b/pyload/plugins/hoster/FilerNet.py new file mode 100644 index 000000000..8e8cee526 --- /dev/null +++ b/pyload/plugins/hoster/FilerNet.py @@ -0,0 +1,119 @@ +# -*- coding: utf-8 -*- + +############################################################################ +# This program is free software: you can redistribute it and/or modify     # +# it under the terms of the GNU Affero 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 Affero General Public License for more details.                      # +#                                                                          # +# You should have received a copy of the GNU Affero General Public License # +# along with this program.  If not, see <http://www.gnu.org/licenses/>.    # +############################################################################ + +# Test links (random.bin): +# http://filer.net/get/ivgf5ztw53et3ogd +# http://filer.net/get/hgo14gzcng3scbvv + +import pycurl +import re + +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo +from module.plugins.internal.CaptchaService import ReCaptcha + + +class FilerNet(SimpleHoster): +    __name__ = "FilerNet" +    __type__ = "hoster" +    __pattern__ = r"https?://(www\.)?filer\.net/get/(\w+)" +    __version__ = "0.02" +    __description__ = """Filer.net Download Hoster""" +    __author_name__ = ("stickell") +    __author_mail__ = ("l.stickell@yahoo.it") + +    FILE_INFO_PATTERN = r'<h1 class="page-header">Free Download (?P<N>\S+) <small>(?P<S>[\w.]+) (?P<U>\w+)</small></h1>' +    FILE_OFFLINE_PATTERN = r'Nicht gefunden' +    RECAPTCHA_KEY = '6LcFctISAAAAAAgaeHgyqhNecGJJRnxV1m_vAz3V' +    DIRECT_LINK_PATTERN = r'href="([^"]+)">Get download</a>' + +    def process(self, pyfile): +        if self.premium and (not self.SH_CHECK_TRAFFIC or self.checkTrafficLeft()): +            self.handlePremium() +        else: +            self.handleFree() + +    def handleFree(self): +        self.req.setOption("timeout", 120) +        self.html = self.load(self.pyfile.url, decode=not self.SH_BROKEN_ENCODING, cookies=self.SH_COOKIES) + +        # Wait between downloads +        m = re.search(r'musst du <span id="time">(\d+)</span> Sekunden warten', self.html) +        if m: +            waittime = int(m.group(1)) +            self.retry(3, waittime, 'Wait between free downloads') + +        self.getFileInfo() + +        self.html = self.load(self.pyfile.url, decode=True) + +        inputs = self.parseHtmlForm(input_names='token')[1] +        if 'token' not in inputs: +            self.parseError('Unable to detect token') +        token = inputs['token'] +        self.logDebug('Token: ' + token) + +        self.html = self.load(self.pyfile.url, post={'token': token}, decode=True) + +        inputs = self.parseHtmlForm(input_names='hash')[1] +        if 'hash' not in inputs: +            self.parseError('Unable to detect hash') +        hash_data = inputs['hash'] +        self.logDebug('Hash: ' + hash_data) + +        downloadURL = '' +        recaptcha = ReCaptcha(self) +        for i in xrange(5): +            challenge, response = recaptcha.challenge(self.RECAPTCHA_KEY) +            post_data = {'recaptcha_challenge_field': challenge, +                         'recaptcha_response_field': response, +                         'hash': hash_data} + +            # Workaround for 0.4.9 just_header issue. In 0.5 clean the code using just_header +            self.req.http.c.setopt(pycurl.FOLLOWLOCATION, 0) +            self.load(self.pyfile.url, post=post_data) +            self.req.http.c.setopt(pycurl.FOLLOWLOCATION, 1) + +            if 'location' in self.req.http.header: +                location = re.search(r'location: (\S+)', self.req.http.header).group(1) +                downloadURL = 'http://filer.net' + location +                self.correctCaptcha() +                break +            else: +                self.logInfo('Wrong captcha') +                self.invalidCaptcha() + +        if not downloadURL: +            self.fail("No Download url retrieved/all captcha attempts failed") + +        self.download(downloadURL, disposition=True) + +    def handlePremium(self): +        header = self.load(self.pyfile.url, just_header=True) +        if 'location' in header:  # Direct Download ON +            dl = self.pyfile.url +        else:  # Direct Download OFF +            html = self.load(self.pyfile.url) +            m = re.search(self.DIRECT_LINK_PATTERN, html) +            if not m: +                self.parseError("Unable to detect direct link, try to enable 'Direct download' in your user settings") +            dl = 'http://filer.net' + m.group(1) + +        self.logDebug('Direct link: ' + dl) +        self.download(dl, disposition=True) + + +getInfo = create_getInfo(FilerNet) diff --git a/pyload/plugins/hoster/FilerioCom.py b/pyload/plugins/hoster/FilerioCom.py new file mode 100644 index 000000000..7be0fa4f6 --- /dev/null +++ b/pyload/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*\.)*(filerio\.(in|com)|filekeen\.com)/\w{12}" +    __version__ = "0.02"                              +    __description__ = """FileRio.in 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.in" +    FILE_URL_REPLACEMENTS = [(r'http://.*?/','http://filerio.in/')] +     +    def setup(self): +        self.resumeDownload = self.multiDL = self.premium  + +getInfo = create_getInfo(FilerioCom)
\ No newline at end of file diff --git a/pyload/plugins/hoster/FilesMailRu.py b/pyload/plugins/hoster/FilesMailRu.py new file mode 100644 index 000000000..c7232f5dd --- /dev/null +++ b/pyload/plugins/hoster/FilesMailRu.py @@ -0,0 +1,99 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import re +from module.plugins.Hoster import Hoster, chunks +from module.network.RequestFactory import getURL + +def getInfo(urls): +    result = [] +    for chunk in chunks(urls, 10): +        for url in chunk: +            src = getURL(url) +            if r'<div class="errorMessage mb10">' in src: +                result.append((url, 0, 1, url)) +            elif r'Page cannot be displayed' in src: +                result.append((url, 0, 1, url)) +            else: +                try: +                    url_pattern = '<a href="(.+?)" onclick="return Act\(this\, \'dlink\'\, event\)">(.+?)</a>' +                    file_name = re.search(url_pattern, src).group(0).split(', event)">')[1].split('</a>')[0] +                    result.append((file_name, 0, 2, url)) +                except: +                    pass + + +        # status 1=OFFLINE, 2=OK, 3=UNKNOWN +        # result.append((#name,#size,#status,#url)) +        yield result + +class FilesMailRu(Hoster): +    __name__ = "FilesMailRu" +    __type__ = "hoster" +    __pattern__ = r"http://files\.mail\.ru/.*" +    __version__ = "0.31" +    __description__ = """Files.Mail.Ru One-Klick Hoster""" +    __author_name__ = ("oZiRiz") +    __author_mail__ = ("ich@oziriz.de") + +     +    def setup(self): +        if not self.account: +            self.multiDL = False +            self.chunkLimit = 1 + +    def process(self, pyfile): +        self.html = self.load(pyfile.url) +        self.url_pattern = '<a href="(.+?)" onclick="return Act\(this\, \'dlink\'\, event\)">(.+?)</a>' +         +        #marks the file as "offline" when the pattern was found on the html-page''' +        if r'<div class="errorMessage mb10">' in self.html: +            self.offline() +         +        elif r'Page cannot be displayed' in self.html: +            self.offline() +         +        #the filename that will be showed in the list (e.g. test.part1.rar)''' +        pyfile.name = self.getFileName() +         +        #prepare and download''' +        if not self.account: +            self.prepare() +            self.download(self.getFileUrl()) +            self.myPostProcess() +        else: +            self.download(self.getFileUrl()) +            self.myPostProcess() + +    def prepare(self): +        '''You have to wait some seconds. Otherwise you will get a 40Byte HTML Page instead of the file you expected''' +        self.setWait(10) +        self.wait() +        return True +         +    def getFileUrl(self): +        '''gives you the URL to the file. Extracted from the Files.mail.ru HTML-page stored in self.html''' +        file_url = re.search(self.url_pattern, self.html).group(0).split('<a href="')[1].split('" onclick="return Act')[0] +        return file_url + + +    def getFileName(self): +        '''gives you the Name for each file. Also extracted from the HTML-Page''' +        file_name = re.search(self.url_pattern, self.html).group(0).split(', event)">')[1].split('</a>')[0] +        return file_name +         +    def myPostProcess(self): +        # searches the file for HTMl-Code. Sometimes the Redirect  +        # doesn't work (maybe a curl Problem) and you get only a small  +        # HTML file and the Download is marked as "finished" +        # then the download will be restarted. It's only bad for these +        # who want download a HTML-File (it's one in a million ;-) ) +        #  +        # The maximum UploadSize allowed on files.mail.ru at the moment is 100MB +        # so i set it to check every download because sometimes there are downloads +        # that contain the HTML-Text and 60MB ZEROs after that in a xyzfile.part1.rar file +        # (Loading 100MB in to ram is not an option) +        check = self.checkDownload({"html": "<meta name="}, read_size=50000) +        if check == "html": +            self.logInfo(_("There was HTML Code in the Downloaded File(%s)...redirect error? The Download will be restarted." % self.pyfile.name)) +            self.retry() diff --git a/pyload/plugins/hoster/FileserveCom.py b/pyload/plugins/hoster/FileserveCom.py new file mode 100644 index 000000000..c6f414b0e --- /dev/null +++ b/pyload/plugins/hoster/FileserveCom.py @@ -0,0 +1,211 @@ +# -*- 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.internal.CaptchaService 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/pyload/plugins/hoster/FileshareInUa.py b/pyload/plugins/hoster/FileshareInUa.py new file mode 100644 index 000000000..9700b2d0a --- /dev/null +++ b/pyload/plugins/hoster/FileshareInUa.py @@ -0,0 +1,78 @@ +from urllib import urlencode +import re +from module.plugins.Hoster import Hoster +from module.network.RequestFactory import getURL +from module.utils import parseFileSize + +class FileshareInUa(Hoster): +    __name__ = "FileshareInUa" +    __type__ = "hoster" +    __pattern__ = r"http://(?:\w*\.)*?fileshare.in.ua/[A-Za-z0-9]+" +    __version__ = "0.01" +    __description__ = """fileshare.in.ua hoster plugin""" +    __author_name__ = ("fwannmacher") +    __author_mail__ = ("felipe@warhammerproject.com") +     +    HOSTER_NAME = "fileshare.in.ua" +    PATTERN_FILENAME = r'<h3 class="b-filename">(.*?)</h3>' +    PATTERN_FILESIZE = r'<b class="b-filesize">(.*?)</b>' +    PATTERN_OFFLINE = "This file doesn't exist, or has been removed." +     +    def setup(self): +        self.resumeDownload = True +        self.multiDL = True + +    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://fileshare.in.ua" + 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, self.html) +        if name is None: +            self.fail("%s: Plugin broken." % self.__name__) + +        return name.group(1) +         +    def _getLink(self):  +        return re.search("<a href=\"(/get/.+)\" class=\"b-button m-blue m-big\" >", self.html).group(1) + +def getInfo(urls): +    result = [] +     +    for url in urls:  +        html = getURL(url) +         +        if re.search(FileshareInUa.PATTERN_OFFLINE, html): +            result.append((url, 0, 1, url)) +        else: +            name = re.search(FileshareInUa.PATTERN_FILENAME, html) +             +            if name is None: +                result.append((url, 0, 1, url)) +                continue +                 +            name = name.group(1) +            size = re.search(FileshareInUa.PATTERN_FILESIZE, html) +            size = parseFileSize(size.group(1))  +             +            result.append((name, size, 3, url)) + +    yield result diff --git a/pyload/plugins/hoster/FilezyNet.py b/pyload/plugins/hoster/FilezyNet.py new file mode 100644 index 000000000..7c5729c2d --- /dev/null +++ b/pyload/plugins/hoster/FilezyNet.py @@ -0,0 +1,33 @@ +# -*- coding: utf-8 -*- +import re +from module.plugins.hoster.XFileSharingPro import XFileSharingPro, create_getInfo + +class FilezyNet(XFileSharingPro): +    __name__ = "FilezyNet" +    __type__ = "hoster" +    __version__ = "0.1" +    __pattern__ = r"http://filezy.net/.*/.*.html" +    __description__ = """filezy.net hoster plugin""" + +    HOSTER_NAME = "filezy.net" + +    FILE_SIZE_PATTERN = r'<span class="plansize">(?P<S>[0-9.]+) (?P<U>[kKMG])i?B</span>' +    WAIT_PATTERN = r'<div id="countdown_str" class="seconds">\n<!--Wait--> <span id=".*?">(\d+)</span>' +    DOWNLOAD_JS_PATTERN = r"<script type='text/javascript'>eval(.*)" + +    def setup(self): +        self.resumeDownload = True +        self.multiDL = self.premium + +    def getDownloadLink(self): +        self.logDebug("Getting download link") + +        data = self.getPostParameters() +        self.html = self.load(self.pyfile.url, post = data, ref = True, decode = True) + +        obfuscated_js = re.search(self.DOWNLOAD_JS_PATTERN, self.html) +        dl_file_now = self.js.eval(obfuscated_js.group(1)) +        link = re.search(self.DIRECT_LINK_PATTERN, dl_file_now) +        return link.group(1) + +getInfo = create_getInfo(FilezyNet) diff --git a/pyload/plugins/hoster/FlyFilesNet.py b/pyload/plugins/hoster/FlyFilesNet.py new file mode 100644 index 000000000..0ffb76191 --- /dev/null +++ b/pyload/plugins/hoster/FlyFilesNet.py @@ -0,0 +1,41 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import re +import urllib + +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo +from module.network.RequestFactory import getURL + +class FlyFilesNet(SimpleHoster): +    __name__ = "FlyFilesNet" +    __version__ = "0.1" +    __type__ = "hoster" +    __pattern__ = r'http://flyfiles\.net/.*' + +    SESSION_PATTERN = r'flyfiles\.net/(.*)/.*' +    FILE_NAME_PATTERN = r'flyfiles\.net/.*/(.*)' + +    def process(self, pyfile): + +        pyfile.name = re.search(self.FILE_NAME_PATTERN, pyfile.url).group(1) +        pyfile.name = urllib.unquote_plus(pyfile.name) + +        session = re.search(self.SESSION_PATTERN, pyfile.url).group(1) + +        url = "http://flyfiles.net" + +        # get download URL +        parsed_url = getURL(url, post={"getDownLink": session}, cookies=True) +        self.logDebug("Parsed URL: %s" % parsed_url) + +        if parsed_url == '#downlink|' or parsed_url == "#downlink|#": +            self.logWarning("Could not get the download URL. Please wait 10 minutes.") +            self.setWait(600, True) # wait 10 minutes +            self.wait() +            self.retry() + +        download_url = parsed_url.replace('#downlink|','') + +        self.logDebug("Download URL: %s" % download_url) +        self.download(download_url) diff --git a/pyload/plugins/hoster/FourSharedCom.py b/pyload/plugins/hoster/FourSharedCom.py new file mode 100644 index 000000000..518ae2ae6 --- /dev/null +++ b/pyload/plugins/hoster/FourSharedCom.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo +import re + +class FourSharedCom(SimpleHoster): +    __name__ = "FourSharedCom" +    __type__ = "hoster" +    __pattern__ = r"https?://(www\.)?4shared(\-china)?\.com/(account/)?(download|get|file|document|photo|video|audio|mp3|office|rar|zip|archive|music)/.+?/.*" +    __version__ = "0.29" +    __description__ = """4Shared Download Hoster""" +    __author_name__ = ("jeix", "zoidberg") +    __author_mail__ = ("jeix@hasnomail.de", "zoidberg@mujmail.cz") + +    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 = '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) + +getInfo = create_getInfo(FourSharedCom)            
\ No newline at end of file diff --git a/pyload/plugins/hoster/FreakshareCom.py b/pyload/plugins/hoster/FreakshareCom.py new file mode 100644 index 000000000..156f697c3 --- /dev/null +++ b/pyload/plugins/hoster/FreakshareCom.py @@ -0,0 +1,167 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import re +from module.plugins.Hoster import Hoster +from module.plugins.internal.CaptchaService import ReCaptcha + +class FreakshareCom(Hoster): +    __name__ = "FreakshareCom" +    __type__ = "hoster" +    __pattern__ = r"http://(?:www\.)?freakshare\.(net|com)/files/\S*?/" +    __version__ = "0.37" +    __description__ = """Freakshare.com Download Hoster""" +    __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 +        self.wantReconnect = False +        self.multiDL = False +        self.req_opts = [] + +    def process(self, pyfile): +        self.pyfile = pyfile +         +        pyfile.url = pyfile.url.replace("freakshare.net/","freakshare.com/") + +        if self.account: +            self.html = self.load(pyfile.url, cookies=False) +            pyfile.name = self.get_file_name() +            self.download(pyfile.url) + +        else: +            self.prepare() +            self.get_file_url() + +            self.download(self.pyfile.url, post=self.req_opts) + + +            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 + +        self.wantReconnect = False +         +        self.download_html() + +        if not self.file_exists(): +            self.offline() +             +        self.setWait( self.get_waiting_time() ) + +        pyfile.name = self.get_file_name() +        pyfile.size = self.get_file_size() +             +        self.wait() + +        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): +        """ returns the absolute downloadable filepath +        """ +        if self.html is None: +            self.download_html() +        if not self.wantReconnect: +            self.req_opts = self.get_download_options() # get the Post options for the Request +            #file_url = self.pyfile.url +            #return file_url +        else: +            self.offline() + +    def get_file_name(self): +        if self.html is None: +            self.download_html() +        if not self.wantReconnect: +            file_name = re.search(r"<h1\sclass=\"box_heading\"\sstyle=\"text-align:center;\">([^ ]+)", self.html) +            if file_name is not None: +                file_name = file_name.group(1) +            else: +                file_name = self.pyfile.url +            return file_name +        else: +            return self.pyfile.url +     +    def get_file_size(self): +        size = 0 +        if self.html is None: +            self.download_html() +        if not self.wantReconnect: +            file_size_check = re.search(r"<h1\sclass=\"box_heading\"\sstyle=\"text-align:center;\">[^ ]+ - ([^ ]+) (\w\w)yte", self.html) +            if file_size_check is not None: +                units = float(file_size_check.group(1).replace(",", "")) +                pow = {'KB': 1, 'MB': 2, 'GB': 3}[file_size_check.group(2)] +                size = int(units * 1024 ** pow) + +        return size +     +    def get_waiting_time(self): +        if self.html is None: +            self.download_html() + +        if "Your Traffic is used up for today" in self.html: +            self.wantReconnect = True +            return 24*3600 + +        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: +            return 60 + + +    def file_exists(self): +        """ returns True or False +        """ +        if self.html is None: +            self.download_html() +        if re.search(r"This file does not exist!", self.html) is not None: +            return False +        else: +            return True + +    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 = dict((n, v) for (v, n) in to_sort) +             +        herewego = self.load(self.pyfile.url, None, request_options) # the actual download-Page +         +        # comment this in, when it doesnt work +        # with open("DUMP__FS_.HTML", "w") as fp: +            # fp.write(herewego) +         +        to_sort = re.findall(r"<input\stype=\".*?\"\svalue=\"(\S*?)\".*?name=\"(\S*?)\"\s.*?\/>", herewego) +        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]) + +        challenge = re.search(r"http://api\.recaptcha\.net/challenge\?k=([0-9A-Za-z]+)", herewego) + +        if challenge: +            re_captcha = ReCaptcha(self) +            request_options["recaptcha_challenge_field"], request_options["recaptcha_response_field"] \ +                = re_captcha.challenge(challenge.group(1)) + +        return request_options diff --git a/pyload/plugins/hoster/FreevideoCz.py b/pyload/plugins/hoster/FreevideoCz.py new file mode 100644 index 000000000..19eb77470 --- /dev/null +++ b/pyload/plugins/hoster/FreevideoCz.py @@ -0,0 +1,64 @@ +# -*- 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 import Hoster +from module.network.RequestFactory import getURL + +def getInfo(urls): +    result = [] + +    for url in urls: + +        html = getURL(url) +        if re.search(FreevideoCz.FILE_OFFLINE_PATTERN, html): +            # File offline +            result.append((url, 0, 1, url)) +        else: +            result.append((url, 0, 2, url)) +    yield result + +class FreevideoCz(Hoster): +    __name__ = "FreevideoCz" +    __type__ = "hoster" +    __pattern__ = r"http://www.freevideo.cz/vase-videa/(.*)\.html" +    __version__ = "0.2" +    __description__ = """freevideo.cz""" +    __author_name__ = ("zoidberg") + +    URL_PATTERN = r'clip: {\s*url: "([^"]+)"' +    FILE_OFFLINE_PATTERN = r'<h2 class="red-corner-full">Str.nka nebyla nalezena</h2>' + +    def setup(self): +        self.multiDL = True +        self.resumeDownload = True + +    def process(self, pyfile): + +        self.html = self.load(pyfile.url, decode=True) + +        if re.search(self.FILE_OFFLINE_PATTERN, self.html): +            self.offline() + +        found = re.search(self.URL_PATTERN, self.html) +        if found is None: self.fail("Parse error (URL)") +        download_url = found.group(1) + +        pyfile.name = re.search(self.__pattern__, pyfile.url).group(1) + ".mp4" + +        self.download(download_url) diff --git a/pyload/plugins/hoster/FshareVn.py b/pyload/plugins/hoster/FshareVn.py new file mode 100644 index 000000000..926781b40 --- /dev/null +++ b/pyload/plugins/hoster/FshareVn.py @@ -0,0 +1,111 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +from module.plugins.internal.SimpleHoster import SimpleHoster, parseFileInfo +from module.network.RequestFactory import getURL +import re +from time import strptime, mktime, gmtime + +def getInfo(urls): +    for url in urls: +        html = getURL('http://www.fshare.vn/check_link.php', post = { +            "action" : "check_link", +            "arrlinks" : url +            }, decode = True) + +        file_info = parseFileInfo(FshareVn, url, html) + +        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.16" +    __description__ = """FshareVn Download Hoster""" +    __author_name__ = ("zoidberg") +    __author_mail__ = ("zoidberg@mujmail.cz") + +    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_w\\"|<\\/p>\\t\\t\\t\\t\\r\\n\\t\\t<p><\\/p>\\t\\t\\r\\n\\t\\t<p>0 KB<\\/p>' +    FILE_NAME_REPLACEMENTS = [("(.*)", doubleDecode)] +    DOWNLOAD_URL_PATTERN = r'action="(http://download.*?)[#"]' +    VIP_URL_PATTERN = r'<form action="([^>]+)" method="get" name="frm_download">' +    WAIT_PATTERN = ur'Lượt tải xuống kế tiếp là:\s*(.*?)\s*<' + +    def process(self, pyfile): +        self.html = self.load('http://www.fshare.vn/check_link.php', post = { +            "action": "check_link", +            "arrlinks": pyfile.url +            }, decode = True) +        self.getFileInfo() + +        if self.premium: +            self.handlePremium() +        else: +            self.handleFree() +        self.checkDownloadedFile() + +    def handleFree(self): +        self.html = self.load(self.pyfile.url, decode = True) + +        self.checkErrors() + +        action, inputs = self.parseHtmlForm('frm_download') +        self.url = self.pyfile.url + action + +        if not inputs: self.parseError('FORM') +        elif 'link_file_pwd_dl' in inputs: +            for password in self.getPassword().splitlines(): +                self.logInfo('Password protected link, trying "%s"' % password) +                inputs['link_file_pwd_dl'] = password +                self.html = self.load(self.url, post=inputs, decode=True) +                if not 'name="link_file_pwd_dl"' in self.html: +                    break +            else: +                self.fail("No or incorrect password") +        else: +            self.html = self.load(self.url, post=inputs, decode=True) + +        self.checkErrors() + +        found = re.search(r'var count = (\d+)', self.html) +        self.setWait(int(found.group(1)) if found else 30) + +        found = re.search(self.DOWNLOAD_URL_PATTERN, self.html) +        if not found: self.parseError('FREE DL URL') +        self.url = found.group(1) +        self.logDebug("FREE DL URL: %s" % self.url) + +        self.wait() +        self.download(self.url) + +    def handlePremium(self): +        self.download(self.pyfile.url) + +    def checkErrors(self): +        if '/error.php?' in self.req.lastEffectiveURL or u"Liên kết bạn chọn không tồn" in self.html: +            self.offline() + +        found = re.search(self.WAIT_PATTERN, self.html) +        if found: +            self.logInfo("Wait until %s ICT" % found.group(1)) +            wait_until = mktime(strptime(found.group(1), "%d/%m/%Y %H:%M")) +            self.setWait(wait_until - mktime(gmtime()) - 7 * 3600, True) +            self.wait() +            self.retry() +        elif '<ul class="message-error">' in self.html: +            self.logError("Unknown error occured or wait time not parsed") +            self.retry(30, 120, "Unknown error") + +    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") diff --git a/pyload/plugins/hoster/Ftp.py b/pyload/plugins/hoster/Ftp.py new file mode 100644 index 000000000..c68f3b237 --- /dev/null +++ b/pyload/plugins/hoster/Ftp.py @@ -0,0 +1,91 @@ +# -*- 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 +    @author: mkaay +""" +from urlparse import urlparse, urljoin +from urllib import quote, unquote +import pycurl, re + +from module.plugins.Hoster import Hoster +from module.network.HTTPRequest import BadHeader + +class Ftp(Hoster): +    __name__ = "Ftp" +    __version__ = "0.41" +    __pattern__ = r'(ftps?|sftp)://(.*?:.*?@)?.*?/.*' # ftp://user:password@ftp.server.org/path/to/file +    __type__ = "hoster" +    __description__ = """A Plugin that allows you to download from an from an ftp directory""" +    __author_name__ = ("jeix", "mkaay", "zoidberg") +    __author_mail__ = ("jeix@hasnomail.com", "mkaay@mkaay.de", "zoidberg@mujmail.cz") +     +    def setup(self): +        self.chunkLimit = -1 +        self.resumeDownload = True    +     +    def process(self, pyfile): +        parsed_url = urlparse(pyfile.url) +        netloc = parsed_url.netloc +         +        pyfile.name = parsed_url.path.rpartition('/')[2] +        try: +            pyfile.name = unquote(str(pyfile.name)).decode('utf8') +        except: +            pass         +         +        if not "@" in netloc: +            servers = [ x['login'] for x in self.account.getAllAccounts() ] if self.account else []                              +                 +            if netloc in servers: +                self.logDebug("Logging on to %s" % netloc)                 +                self.req.addAuth(self.account.accounts[netloc]["password"]) +            else: +                for pwd in pyfile.package().password.splitlines():  +                    if ":" in pwd: +                        self.req.addAuth(pwd.strip()) +                        break                             +         +        self.req.http.c.setopt(pycurl.NOBODY, 1) +         +        try: +            response = self.load(pyfile.url) +        except pycurl.error, e: +            self.fail("Error %d: %s" % e.args) +         +        self.req.http.c.setopt(pycurl.NOBODY, 0)         +        self.logDebug(self.req.http.header) +         +        found = re.search(r"Content-Length:\s*(\d+)", response) +        if found: +            pyfile.size = int(found.group(1))                  +            self.download(pyfile.url) +        else: +            #Naive ftp directory listing           +            if re.search(r'^25\d.*?"', self.req.http.header, re.M):             +                pyfile.url = pyfile.url.rstrip('/') +                pkgname = "/".join((pyfile.package().name,urlparse(pyfile.url).path.rpartition('/')[2])) +                pyfile.url += '/' +                self.req.http.c.setopt(48, 1) # CURLOPT_DIRLISTONLY +                response = self.load(pyfile.url, decode = False) +                links = [ pyfile.url + quote(x) for x in response.splitlines() ] +                self.logDebug("LINKS", links) +                self.core.api.addPackage(pkgname, links, 1) +                #self.core.files.addLinks(links, pyfile.package().id) +            else: +                self.fail("Unexpected server response") +             +        
\ No newline at end of file diff --git a/pyload/plugins/hoster/GamefrontCom.py b/pyload/plugins/hoster/GamefrontCom.py new file mode 100644 index 000000000..34fda09d2 --- /dev/null +++ b/pyload/plugins/hoster/GamefrontCom.py @@ -0,0 +1,80 @@ +import re +from module.plugins.Hoster import Hoster +from module.network.RequestFactory import getURL +from module.utils import parseFileSize + +class GamefrontCom(Hoster): +    __name__ = "GamefrontCom" +    __type__ = "hoster" +    __pattern__ = r"http://(?:\w*\.)*?gamefront.com/files/[A-Za-z0-9]+" +    __version__ = "0.02" +    __description__ = """gamefront.com hoster plugin""" +    __author_name__ = ("fwannmacher") +    __author_mail__ = ("felipe@warhammerproject.com") +     +    HOSTER_NAME = "gamefront.com" +    PATTERN_FILENAME = r'<title>(.*?) | Game Front' +    PATTERN_FILESIZE = r'<dt>File Size:</dt>[\n\s]*<dd>(.*?)</dd>' +    PATTERN_OFFLINE = "This file doesn't exist, or has been removed." +     +    def setup(self): +        self.resumeDownload = True +        self.multiDL = False + +    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.gamefront.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, self.html) +        if name is None: +            self.fail("%s: Plugin broken." % self.__name__) + +        return name.group(1) +         +    def _getLink(self):  +        self.html2 = self.load("http://www.gamefront.com/" + re.search("(files/service/thankyou\\?id=[A-Za-z0-9]+)", self.html).group(1)) +        self.link = re.search("<a href=\"(http://media[0-9]+\.gamefront.com/.*)\">click here</a>", self.html2) + +        return self.link.group(1).replace("&", "&") + +def getInfo(urls): +    result = [] +     +    for url in urls:  +        html = getURL(url) +         +        if re.search(GamefrontCom.PATTERN_OFFLINE, html): +            result.append((url, 0, 1, url)) +        else: +            name = re.search(GamefrontCom.PATTERN_FILENAME, html) +             +            if name is None: +                result.append((url, 0, 1, url)) +                continue +                 +            name = name.group(1) +            size = re.search(GamefrontCom.PATTERN_FILESIZE, html) +            size = parseFileSize(size.group(1))  +             +            result.append((name, size, 3, url)) + +    yield result
\ No newline at end of file diff --git a/pyload/plugins/hoster/GigapetaCom.py b/pyload/plugins/hoster/GigapetaCom.py new file mode 100644 index 000000000..28ba35abe --- /dev/null +++ b/pyload/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/pyload/plugins/hoster/HellshareCz.py b/pyload/plugins/hoster/HellshareCz.py new file mode 100644 index 000000000..aa494e34e --- /dev/null +++ b/pyload/plugins/hoster/HellshareCz.py @@ -0,0 +1,56 @@ +# -*- 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 math import ceil +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo + + +class HellshareCz(SimpleHoster): +    __name__ = "HellshareCz" +    __type__ = "hoster" +    __pattern__ = r"(http://(?:.*\.)*hellshare\.(?:cz|com|sk|hu|pl)/[^?]*/\d+).*" +    __version__ = "0.82" +    __description__ = """Hellshare.cz - premium only""" +    __author_name__ = ("zoidberg") + +    FILE_NAME_PATTERN = r'<h1 id="filename"[^>]*>(?P<N>[^<]+)</h1>' +    FILE_SIZE_PATTERN = r'<strong id="FileSize_master">(?P<S>[0-9.]*) (?P<U>[kKMG])i?B</strong>' +    FILE_OFFLINE_PATTERN = r'<h1>File not found.</h1>' +    SHOW_WINDOW_PATTERN = r'<a href="([^?]+/(\d+)/\?do=(fileDownloadButton|relatedFileDownloadButton-\2)-showDownloadWindow)"' + +    def setup(self): +        self.resumeDownload = self.multiDL = True if self.account else False +        self.chunkLimit = 1 + +    def process(self, pyfile): +        if not self.account: self.fail("User not logged in") +        pyfile.url = re.search(self.__pattern__, pyfile.url).group(1) +        self.html = self.load(pyfile.url, decode = True) +        self.getFileInfo() +        if not self.checkTrafficLeft(): +            self.fail("Not enough traffic left for user %s." % self.user) + +        found = re.search(self.SHOW_WINDOW_PATTERN, self.html) +        if not found: self.parseError('SHOW WINDOW') +        self.url = "http://www.hellshare.com" + found.group(1) +        self.logDebug("DOWNLOAD URL: " + self.url) + +        self.download(self.url) + +getInfo = create_getInfo(HellshareCz) diff --git a/pyload/plugins/hoster/HellspyCz.py b/pyload/plugins/hoster/HellspyCz.py new file mode 100644 index 000000000..9858c82b7 --- /dev/null +++ b/pyload/plugins/hoster/HellspyCz.py @@ -0,0 +1,70 @@ +# -*- 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 HellspyCz(SimpleHoster): +    __name__ = "HellspyCz" +    __type__ = "hoster" +    __pattern__ = r"http://(?:\w*\.)*(?:hellspy\.(?:cz|com|sk|hu|pl)|sciagaj.pl)(/\S+/\d+)/?.*" +    __version__ = "0.27" +    __description__ = """HellSpy.cz""" +    __author_name__ = ("zoidberg") +    __author_mail__ = ("zoidberg@mujmail.cz") + +    FILE_SIZE_PATTERN = r'<span class="filesize right">(?P<S>[0-9.]+)\s*<span>(?P<U>[kKMG])i?B' +    FILE_NAME_PATTERN = r'<h1 title="(?P<N>.*?)"' +    FILE_OFFLINE_PATTERN = r'<h2>(404 - Page|File) not found</h2>' +    FILE_URL_REPLACEMENTS = [(__pattern__, r"http://www.hellspy.com\1")] +     +    CREDIT_LEFT_PATTERN = r'<strong>Credits: </strong>\s*(\d+)' +    DOWNLOAD_AGAIN_PATTERN = r'<a id="button-download-start"[^>]*title="You can download the file without deducting your credit.">' +    DOWNLOAD_URL_PATTERN = r"launchFullDownload\('([^']+)'" + +    def setup(self): +        self.resumeDownload = self.multiDL = True +        self.chunkLimit = 1 + +    def handleFree(self): +        self.fail("Only premium users can download from HellSpy.cz") + +    def handlePremium(self):         +        # set PHPSESSID cookie +        cj = self.account.getAccountCookies(self.user) +        cj.setCookie(".hellspy.com", "PHPSESSID", self.account.phpsessid) +        self.logDebug("PHPSESSID: " + cj.getCookie("PHPSESSID")) + +        info = self.account.getAccountInfo(self.user, True) +        self.logInfo("User %s has %i credits left" % (self.user, info["trafficleft"]/1024)) + +        if self.pyfile.size / 1024 > info["trafficleft"]: +            self.logWarning("Not enough credit left to download file") + +        # get premium download URL and download +        self.html = self.load(self.pyfile.url + "?download=1") +        found = re.search(self.DOWNLOAD_URL_PATTERN, self.html) +        if not found: self.parseError("Download URL") +        url = found.group(1) +        self.logDebug("Download URL: " + url) +        self.download(url) + +        info = self.account.getAccountInfo(self.user, True) +        self.logInfo("User %s has %i credits left" % (self.user, info["trafficleft"]/1024)) +         +getInfo = create_getInfo(HellspyCz)
\ No newline at end of file diff --git a/pyload/plugins/hoster/HotfileCom.py b/pyload/plugins/hoster/HotfileCom.py new file mode 100644 index 000000000..2dfe6ec88 --- /dev/null +++ b/pyload/plugins/hoster/HotfileCom.py @@ -0,0 +1,137 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import re +from module.plugins.Hoster import Hoster +from module.plugins.internal.CaptchaService import ReCaptcha + +from module.network.RequestFactory import getURL +from module.utils import chunks + +def getInfo(urls): +    api_url_base = "http://api.hotfile.com/" +     +    for chunk in chunks(urls, 90): +        api_param_file = {"action":"checklinks","links": ",".join(chunk),"fields":"id,status,name,size"} #api only supports old style links +        src = getURL(api_url_base, post=api_param_file, decode=True) +        result = [] +        for i, res in enumerate(src.split("\n")): +            if not res: +                continue +            fields = res.split(",") +             +            if fields[1] in ("1", "2"): +                status = 2 +            else: +                status = 1 +                 +            result.append((fields[2], int(fields[3]), status, chunk[i])) +        yield result + +class HotfileCom(Hoster): +    __name__ = "HotfileCom" +    __type__ = "hoster" +    __pattern__ = r"https?://(www.)?hotfile\.com/dl/\d+/[0-9a-zA-Z]+/" +    __version__ = "0.36" +    __description__ = """Hotfile.com Download Hoster""" +    __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.htmlwithlink = None +        self.url = None +         +        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: +            return +        elif self.account and login: +            return self.account.apiCall(method, post, self.user) +        post.update({"action": method}) +        return self.load("http://api.hotfile.com/", post=post, decode=True) +         +    def process(self, pyfile): +        self.wantReconnect = False +         +        args = {"links":self.pyfile.url, "fields":"id,status,name,size,sha1"} +        resp = self.apiCall("checklinks", args) +        self.api_data = {} +        for k, v in zip(args["fields"].split(","), resp.strip().split(",")): +            self.api_data[k] = v +         +        if self.api_data["status"] == "0": +            self.offline() + +        pyfile.name = self.api_data["name"] +         +        if not self.premium: +            self.downloadHTML() + +            if self.FILE_OFFLINE_PATTERN in self.html[0]: +                self.offline() + +            self.setWait(self.getWaitTime()) +            self.wait() +             +            self.freeDownload() +        else: +            dl = self.account.apiCall("getdirectdownloadlink", {"link":self.pyfile.url}, self.user) +            #dl = unquote(dl).strip()  <- Made problems +            dl = dl.strip() +            self.download(dl) + +    def downloadHTML(self): +        self.html[0] = self.load(self.pyfile.url, get={"lang":"en"}) + +    def freeDownload(self): +         +        form_content = re.search(r"<form style=.*(\n<.*>\s*)*?[\n\t]?<tr>", self.html[0]) +        if form_content is None: +            print self.html[0] +            self.fail("Form not found in HTML. Can not proceed.") + +        form_content = form_content.group(0) +        form_posts = dict(re.findall(r"<input\stype=hidden\sname=(\S*)\svalue=(\S*)>", form_content)) +         +        self.html[1] = self.load(self.pyfile.url, post=form_posts) + +        challenge = re.search(r"http://api\.recaptcha\.net/challenge\?k=([0-9A-Za-z]+)", self.html[1]) +         +        if challenge: +            re_captcha = ReCaptcha(self) +            challenge, result = re_captcha.challenge(challenge.group(1)) +             +            url = re.search(r'<form action="(/dl/[^"]+)', self.html[1] ) +                         +            self.html[1] = self.load("http://hotfile.com"+url.group(1), post={"action": "checkcaptcha", +                                             "recaptcha_challenge_field" : challenge, +                                             "recaptcha_response_field": result}) +             +            if "Wrong Code. Please try again." in self.html[1]: +                self.freeDownload() +                return +         +        file_url = re.search(r'a href="(http://hotfile\.com/get/\S*)"', self.html[1]).group(1) +        self.download(file_url) +           +    def getWaitTime(self): +        free_limit_pattern = re.compile(r"timerend=d\.getTime\(\)\+(\d+);") +        matches = free_limit_pattern.findall(self.html[0]) +        if matches: +            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.")
\ No newline at end of file diff --git a/pyload/plugins/hoster/HundredEightyUploadCom.py b/pyload/plugins/hoster/HundredEightyUploadCom.py new file mode 100644 index 000000000..d8b744359 --- /dev/null +++ b/pyload/plugins/hoster/HundredEightyUploadCom.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- + +############################################################################ +# This program is free software: you can redistribute it and/or modify     # +# it under the terms of the GNU Affero 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 Affero General Public License for more details.                      # +#                                                                          # +# You should have received a copy of the GNU Affero General Public License # +# along with this program.  If not, see <http://www.gnu.org/licenses/>.    # +############################################################################ + +from module.plugins.hoster.XFileSharingPro import XFileSharingPro, create_getInfo + + +class HundredEightyUploadCom(XFileSharingPro): +    __name__ = "HundredEightyUploadCom" +    __type__ = "hoster" +    __pattern__ = r"http://(?:\w*\.)?180upload\.com/(\w+).*" +    __version__ = "0.01" +    __description__ = """180upload.com hoster plugin""" +    __author_name__ = ("stickell") +    __author_mail__ = ("l.stickell@yahoo.it") + +    FILE_NAME_PATTERN = r'Filename:</b></td><td nowrap>(?P<N>.+)</td></tr>-->' +    FILE_SIZE_PATTERN = r'Size:</b></td><td>(?P<S>[\d.]+) (?P<U>[A-Z]+)\s*<small>' + +    HOSTER_NAME = "180upload.com" + + +getInfo = create_getInfo(HundredEightyUploadCom) diff --git a/pyload/plugins/hoster/IFileWs.py b/pyload/plugins/hoster/IFileWs.py new file mode 100644 index 000000000..160fe641c --- /dev/null +++ b/pyload/plugins/hoster/IFileWs.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +from module.plugins.hoster.XFileSharingPro import XFileSharingPro, create_getInfo + + +class IFileWs(XFileSharingPro): +    __name__ = "IFileWs" +    __type__ = "hoster" +    __pattern__ = r"http://(www\.)?ifile\.ws/\w+(/.+)?" +    __version__ = "0.01" +    __description__ = """Ifile.ws hoster plugin""" +    __author_name__ = ("z00nx") +    __author_mail__ = ("z00nx0@gmail.com") + +    FILE_INFO_PATTERN = '<h1\s+style="display:inline;">(?P<N>[^<]+)</h1>\s+\[(?P<S>[^]]+)\]' +    FILE_OFFLINE_PATTERN = 'File Not Found|The file was removed by administrator' +    HOSTER_NAME = "ifile.ws" +    LONG_WAIT_PATTERN = "(?P<M>\d(?=\s+minutes)).*(?P<S>\d+(?=\s+seconds))" + + +getInfo = create_getInfo(IFileWs) diff --git a/pyload/plugins/hoster/IcyFilesCom.py b/pyload/plugins/hoster/IcyFilesCom.py new file mode 100644 index 000000000..34737e560 --- /dev/null +++ b/pyload/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.05" +    __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/pyload/plugins/hoster/IfileIt.py b/pyload/plugins/hoster/IfileIt.py new file mode 100644 index 000000000..02bcbfd40 --- /dev/null +++ b/pyload/plugins/hoster/IfileIt.py @@ -0,0 +1,74 @@ +# -*- 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 +from module.plugins.internal.CaptchaService import ReCaptcha +from module.network.RequestFactory import getURL + +class IfileIt(SimpleHoster): +    __name__ = "IfileIt" +    __type__ = "hoster" +    __pattern__ = r"^unmatchable$" +    __version__ = "0.27" +    __description__ = """Ifile.it""" +    __author_name__ = ("zoidberg") + +    #EVAL_PATTERN = r'(eval\(function\(p,a,c,k,e,d\).*)' +    #DEC_PATTERN = r"requestBtn_clickEvent[^}]*url:\s*([^,]+)" +    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'<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/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): +                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: +                    self.correctCaptcha() +                    break +            else: +                self.fail("Incorrect captcha") + +        if not "ticket_url" in json_response: +            self.parseError("Download URL") + +        self.download(json_response["ticket_url"]) + +getInfo = create_getInfo(IfileIt)
\ No newline at end of file diff --git a/pyload/plugins/hoster/IfolderRu.py b/pyload/plugins/hoster/IfolderRu.py new file mode 100644 index 000000000..6accbc524 --- /dev/null +++ b/pyload/plugins/hoster/IfolderRu.py @@ -0,0 +1,90 @@ +# -*- 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 urllib import quote +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo +from module.network.RequestFactory import getURL + +class IfolderRu(SimpleHoster): +    __name__ = "IfolderRu" +    __type__ = "hoster" +    __pattern__ = r"http://(?:[^.]*\.)?(?:ifolder\.ru|rusfolder\.(?:com|net|ru))/(?:files/)?(?P<ID>\d+).*" +    __version__ = "0.37" +    __description__ = """rusfolder.com / ifolder.ru""" +    __author_name__ = ("zoidberg") +    __author_mail__ = ("zoidberg@mujmail.cz") + +    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>' +     +    SESSION_ID_PATTERN = r'<a href=(http://ints.(?:rusfolder.com|ifolder.ru)/ints/sponsor/\?bi=\d*&session=([^&]+)&u=[^>]+)>' +    INTS_SESSION_PATTERN = r'\(\'ints_session\'\);\s*if\(tag\)\{tag.value = "([^"]+)";\}' +    HIDDEN_INPUT_PATTERN = r"var v = .*?name='([^']+)' value='1'" +    DOWNLOAD_LINK_PATTERN = r'<a id="download_file_href" href="([^"]+)"' +    WRONG_CAPTCHA_PATTERN = ur'<font color=Red>неверный код,<br>введите еще раз</font><br>' + +    def setup(self): +        self.resumeDownload = self.multiDL = True if self.account else False +        self.chunkLimit = 1 + +    def process(self, pyfile): +        file_id = re.search(self.__pattern__, pyfile.url).group('ID') +        self.html = self.load("http://rusfolder.com/%s" % file_id, cookies=True, decode=True) +        self.getFileInfo() + +        url = re.search('<a href="(http://ints\..*?=)"', self.html).group(1) +        self.html = self.load(url, cookies=True, decode=True) +         +        url, session_id = re.search(self.SESSION_ID_PATTERN, self.html).groups() +        self.html = self.load(url, cookies=True, decode=True) + +        url = "http://ints.rusfolder.com/ints/frame/?session=%s" % session_id +        self.html = self.load(url, cookies=True) + +        self.setWait(31, False) +        self.wait() + +        captcha_url = "http://ints.rusfolder.com/random/images/?session=%s" % session_id +        for i in range(5): +            self.html = self.load(url, cookies=True) +            action, inputs = self.parseHtmlForm('ID="Form1"') +            inputs['ints_session'] = re.search(self.INTS_SESSION_PATTERN, self.html).group(1) +            inputs[re.search(self.HIDDEN_INPUT_PATTERN, self.html).group(1)] = '1' +            inputs['confirmed_number'] = self.decryptCaptcha(captcha_url, cookies = True) +            inputs['action'] = '1' +            self.logDebug(inputs) + +            self.html = self.load(url, decode = True, cookies = True, post = inputs) +            if self.WRONG_CAPTCHA_PATTERN in self.html: +                self.invalidCaptcha() +            else: +                break; +        else: +            self.fail("Invalid captcha") + +        #self.html = self.load("http://rusfolder.com/%s?ints_code=%s" % (file_id, session_id), decode=True, cookies = True) + +        download_url = re.search(self.DOWNLOAD_LINK_PATTERN, self.html).group(1) +        self.correctCaptcha() +        self.logDebug("Download URL: %s" % download_url) +        self.download(download_url) + +getInfo = create_getInfo(IfolderRu)
\ No newline at end of file diff --git a/pyload/plugins/hoster/JumbofilesCom.py b/pyload/plugins/hoster/JumbofilesCom.py new file mode 100644 index 000000000..9e8adb512 --- /dev/null +++ b/pyload/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/pyload/plugins/hoster/LetitbitNet.py b/pyload/plugins/hoster/LetitbitNet.py new file mode 100644 index 000000000..f5e2313ae --- /dev/null +++ b/pyload/plugins/hoster/LetitbitNet.py @@ -0,0 +1,125 @@ +# -*- 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 +from module.plugins.internal.CaptchaService import ReCaptcha + + +class LetitbitNet(SimpleHoster): +    __name__ = "LetitbitNet" +    __type__ = "hoster" +    __pattern__ = r"http://(?:\w*\.)*(letitbit|shareflare).net/download/.*" +    __version__ = "0.20" +    __description__ = """letitbit.net""" +    __author_name__ = ("zoidberg", "z00nx") +    __author_mail__ = ("zoidberg@mujmail.cz", "z00nx0@gmail.com") + +    CHECK_URL_PATTERN = r"ajax_check_url\s*=\s*'((http://[^/]+)[^']+)';" +    SECONDS_PATTERN = r"seconds\s*=\s*(\d+);" +    CAPTCHA_CONTROL_FIELD = r"recaptcha_control_field\s=\s'(?P<value>[^']+)'" +    FILE_INFO_PATTERN = r'<span[^>]*>File:.*?<span[^>]*>(?P<N>[^&]+).*</span>.*?\[(?P<S>[^\]]+)\]</span>' +    FILE_OFFLINE_PATTERN = r'>File not found<' + +    DOMAIN = "http://letitbit.net" +    FILE_URL_REPLACEMENTS = [(r"(?<=http://)([^/]+)", "letitbit.net")] +    RECAPTCHA_KEY = "6Lc9zdMSAAAAAF-7s2wuQ-036pLRbM0p8dDaQdAM" + +    def setup(self): +        self.resumeDownload = True +        #TODO confirm that resume works + +    def handleFree(self): +        action, inputs = self.parseHtmlForm('id="ifree_form"') +        if not action: +            self.parseError("page 1 / ifree_form") +        self.pyfile.size = float(inputs['sssize']) +        self.logDebug(action, inputs) +        inputs['desc'] = "" + +        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) + +        self.html = self.load(action, post = inputs, cookies = True) + +        try: +            ajax_check_url, captcha_url = re.search(self.CHECK_URL_PATTERN, self.html).groups() +            found = re.search(self.SECONDS_PATTERN, self.html) +            seconds = int(found.group(1)) if found else 60 +            self.setWait(seconds+1) +            self.wait() +        except Exception, e: +            self.logError(e) +            self.parseError("page 3 / js") +        """ + +        found = re.search(self.SECONDS_PATTERN, self.html) +        seconds = int(found.group(1)) if found else 60 +        self.logDebug("Seconds found", seconds) +        found = re.search(self.CAPTCHA_CONTROL_FIELD, self.html) +        recaptcha_control_field = found.group(1) +        self.logDebug("ReCaptcha control field found", recaptcha_control_field) +        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') +        self.logDebug(response) + +        recaptcha = ReCaptcha(self) +        challenge, response = recaptcha.challenge(self.RECAPTCHA_KEY) +        post_data = {"recaptcha_challenge_field": challenge, "recaptcha_response_field": response, "recaptcha_control_field": recaptcha_control_field} +        self.logDebug("Post data to send", post_data) +        response = self.load('%s/ajax/check_recaptcha.php' % self.DOMAIN, post=post_data, cookies=True) +        self.logDebug(response) +        if not response: +            self.invalidCaptcha() +        if response == "error_free_download_blocked": +            self.logInfo("Daily limit reached, waiting 24 hours") +            self.setWait(24 * 60 * 60) +            self.wait() +        if response == "error_wrong_captcha": +            self.logInfo("Wrong Captcha") +            self.invalidCaptcha() +            self.retry() +        elif response.startswith('['): +            urls = json_loads(response) +        elif response.startswith('http://'): +            urls = [response] +        else: +            self.parseError("Unknown response - captcha check") + +        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) diff --git a/pyload/plugins/hoster/LoadTo.py b/pyload/plugins/hoster/LoadTo.py new file mode 100644 index 000000000..0f99c272a --- /dev/null +++ b/pyload/plugins/hoster/LoadTo.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: halfman +""" + +# Test links (random.bin): +# http://www.load.to/dNsmgXRk4/random.bin +# http://www.load.to/edbNTxcUb/random100.bin + +import re +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo + + +class LoadTo(SimpleHoster): +    __name__ = "LoadTo" +    __type__ = "hoster" +    __pattern__ = r"http://(?:www\.)?load\.to/\w+" +    __version__ = "0.12" +    __description__ = """Load.to hoster plugin""" +    __author_name__ = ("halfman", "stickell") +    __author_mail__ = ("Pulpan3@gmail.com", "l.stickell@yahoo.it") + +    FILE_INFO_PATTERN = r'<a [^>]+>(?P<N>.+)</a></h3>\s*Size: (?P<S>\d+) Bytes' +    URL_PATTERN = r'<form method="post" action="(.+?)"' +    FILE_OFFLINE_PATTERN = r'Can\'t find file. Please check URL.<br />' +    WAIT_PATTERN = r'type="submit" value="Download \((\d+)\)"' + +    def setup(self): +        self.multiDL = False + +    def process(self, pyfile): + +        self.html = self.load(pyfile.url, decode=True) + +        found = re.search(self.URL_PATTERN, self.html) +        if not found: +            self.parseError('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, disposition=True) + + +getInfo = create_getInfo(LoadTo) diff --git a/pyload/plugins/hoster/LuckyShareNet.py b/pyload/plugins/hoster/LuckyShareNet.py new file mode 100644 index 000000000..08e44d9f6 --- /dev/null +++ b/pyload/plugins/hoster/LuckyShareNet.py @@ -0,0 +1,72 @@ +# -*- coding: utf-8 -*- + +import re +from module.lib.bottle import json_loads + +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo +from module.plugins.internal.CaptchaService import ReCaptcha + + +class LuckyShareNet(SimpleHoster): +    __name__ = "LuckyShareNet" +    __type__ = "hoster" +    __pattern__ = r"https?://(www\.)?luckyshare.net/(?P<ID>\d{10,})" +    __version__ = "0.02" +    __description__ = """LuckyShare.net Download Hoster""" +    __author_name__ = ("stickell") +    __author_mail__ = ("l.stickell@yahoo.it") + +    FILE_INFO_PATTERN = r"<h1 class='file_name'>(?P<N>\S+)</h1>\s*<span class='file_size'>Filesize: (?P<S>[\d.]+)(?P<U>\w+)</span>" +    FILE_OFFLINE_PATTERN = 'There is no such file available' +    RECAPTCHA_KEY = '6LdivsgSAAAAANWh-d7rPE1mus4yVWuSQIJKIYNw' + +    def parseJson(self, rep): +        if 'AJAX Error' in rep: +            html = self.load(self.pyfile.url, decode=True) +            m = re.search(r"waitingtime = (\d+);", html) +            if m: +                waittime = int(m.group(1)) +                self.logDebug('You have to wait %d seconds between free downloads' % waittime) +                self.retry(wait_time=waittime) +            else: +                self.parseError('Unable to detect wait time between free downloads') +        elif 'Hash expired' in rep: +            self.retry(reason='Hash expired') +        return json_loads(rep) + +    # TODO: There should be a filesize limit for free downloads +    # TODO: Some files could not be downloaded in free mode +    def handleFree(self): +        file_id = re.search(self.__pattern__, self.pyfile.url).group('ID') +        self.logDebug('File ID: ' + file_id) +        rep = self.load(r"http://luckyshare.net/download/request/type/time/file/" + file_id, decode=True) +        self.logDebug('JSON: ' + rep) +        json = self.parseJson(rep) + +        self.setWait(int(json['time'])) +        self.wait() + +        recaptcha = ReCaptcha(self) +        for i in xrange(5): +            challenge, response = recaptcha.challenge(self.RECAPTCHA_KEY) +            rep = self.load(r"http://luckyshare.net/download/verify/challenge/%s/response/%s/hash/%s" % +                            (challenge, response, json['hash']), decode=True) +            self.logDebug('JSON: ' + rep) +            if 'link' in rep: +                json.update(self.parseJson(rep)) +                self.correctCaptcha() +                break +            elif 'Verification failed' in rep: +                self.logInfo('Wrong captcha') +                self.invalidCaptcha() +            else: +                self.parseError('Unable to get downlaod link') + +        if not json['link']: +            self.fail("No Download url retrieved/all captcha attempts failed") + +        self.logDebug('Direct URL: ' + json['link']) +        self.download(json['link']) + + +getInfo = create_getInfo(LuckyShareNet) diff --git a/pyload/plugins/hoster/MediafireCom.py b/pyload/plugins/hoster/MediafireCom.py new file mode 100644 index 000000000..1e856c41d --- /dev/null +++ b/pyload/plugins/hoster/MediafireCom.py @@ -0,0 +1,135 @@ +# -*- 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, parseFileInfo +from module.plugins.internal.CaptchaService import SolveMedia +from module.network.RequestFactory import getURL + + +def replace_eval(js_expr): +    return js_expr.replace(r'eval("', '').replace(r"\'", r"'").replace(r'\"', r'"') + + +def checkHTMLHeader(url): +    try: +        for i in range(3): +            header = getURL(url, just_header=True) +            for line in header.splitlines(): +                line = line.lower() +                if 'location' in line: +                    url = line.split(':', 1)[1].strip() +                    if 'error.php?errno=320' in url: +                        return url, 1 +                    if not url.startswith('http://'): url = 'http://www.mediafire.com' + url +                    break +                elif 'content-disposition' in line: +                    return url, 2 +            else: +                break +    except: +        return url, 3 + +    return url, 0 + + +def getInfo(urls): +    for url in urls: +        location, status = checkHTMLHeader(url) +        if status: +            file_info = (url, 0, status, url) +        else: +            file_info = parseFileInfo(MediafireCom, url, getURL(url, decode=True)) +        yield file_info + + +class MediafireCom(SimpleHoster): +    __name__ = "MediafireCom" +    __type__ = "hoster" +    __pattern__ = r"http://(?:\w*\.)*mediafire\.com/(file/|(view/?|download.php)?\?)(\w{11}|\w{15})($|/)" +    __version__ = "0.79" +    __description__ = """Mediafire.com plugin - free only""" +    __author_name__ = ("zoidberg", "stickell") +    __author_mail__ = ("zoidberg@mujmail.cz", "l.stickell@yahoo.it") + +    DOWNLOAD_LINK_PATTERN = r'<div class="download_link"[^>]*(?:z-index:(?P<zindex>\d+))?[^>]*>\s*<a href="(?P<href>http://[^"]+)"' +    JS_KEY_PATTERN = r"DoShow\('mfpromo1'\);[^{]*{((\w+)='';.*?)eval\(\2\);" +    JS_ZMODULO_PATTERN = r"\('z-index'\)\) \% (\d+)\)\);" +    SOLVEMEDIA_PATTERN = r'http://api\.solvemedia\.com/papi/challenge\.noscript\?k=([^"]+)' +    PAGE1_ACTION_PATTERN = r'<link rel="canonical" href="([^"]+)"/>' +    PASSWORD_PATTERN = r'<form name="form_password"' + +    FILE_NAME_PATTERN = r'<META NAME="description" CONTENT="(?P<N>[^"]+)"/>' +    FILE_INFO_PATTERN = r"oFileSharePopup\.ald\('(?P<ID>[^']*)','(?P<N>[^']*)','(?P<S>[^']*)','','(?P<sha256>[^']*)'\)" +    FILE_OFFLINE_PATTERN = r'class="error_msg_title"> Invalid or Deleted File. </div>' + +    def setup(self): +        self.multiDL = False + +    def process(self, pyfile): +        pyfile.url = re.sub(r'/view/?\?', '/?', pyfile.url) + +        self.url, result = checkHTMLHeader(pyfile.url) +        self.logDebug('Location (%d): %s' % (result, self.url)) + +        if result == 0: +            self.html = self.load(self.url, decode=True) +            self.checkCaptcha() +            self.multiDL = True +            self.check_data = self.getFileInfo() + +            if self.account: +                self.handlePremium() +            else: +                self.handleFree() +        elif result == 1: +            self.offline() +        else: +            self.multiDL = True +            self.download(self.url, disposition=True) + +    def handleFree(self): +        passwords = self.getPassword().splitlines() +        while self.PASSWORD_PATTERN in self.html: +            if len(passwords): +                password = passwords.pop(0) +                self.logInfo("Password protected link, trying " + password) +                self.html = self.load(self.url, post={"downloadp": password}) +            else: +                self.fail("No or incorrect password") + +        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) + +    def checkCaptcha(self): +        for i in xrange(5): +            found = re.search(self.SOLVEMEDIA_PATTERN, self.html) +            if found: +                captcha_key = found.group(1) +                solvemedia = SolveMedia(self) +                captcha_challenge, captcha_response = solvemedia.challenge(captcha_key) +                self.html = self.load(self.url, post={"adcopy_challenge": captcha_challenge, +                                                      "adcopy_response": captcha_response}, decode=True) +            else: +                break +        else: +            self.fail("No valid recaptcha solution received") diff --git a/pyload/plugins/hoster/MegaNz.py b/pyload/plugins/hoster/MegaNz.py new file mode 100644 index 000000000..e5be4eeb7 --- /dev/null +++ b/pyload/plugins/hoster/MegaNz.py @@ -0,0 +1,125 @@ +# -*- coding: utf-8 -*- + +import re +import random +from array import array +from os import remove +from base64 import standard_b64decode + +from Crypto.Cipher import AES +from Crypto.Util import Counter + +from module.common.json_layer import json +from module.plugins.Hoster import Hoster + +#def getInfo(urls): +#    pass + +class MegaNz(Hoster): +    __name__ = "MegaNz" +    __type__ = "hoster" +    __pattern__ = r"https?://([a-z0-9]+\.)?mega\.co\.nz/#!([a-zA-Z0-9!_\-]+)" +    __version__ = "0.12" +    __description__ = """mega.co.nz hoster plugin""" +    __author_name__ = ("RaNaN", ) +    __author_mail__ = ("ranan@pyload.org", ) + +    API_URL = "https://g.api.mega.co.nz/cs?id=%d" +    FILE_SUFFIX = ".crypted" + +    def b64_decode(self, data): +        data = data.replace("-", "+").replace("_", "/") +        return standard_b64decode(data + '=' * (-len(data) % 4)) + +    def getCipherKey(self, key): +        """ Construct the cipher key from the given data """ +        a = array("I", key) +        key_array = array("I", [a[0] ^ a[4], a[1] ^ a[5], a[2] ^ a[6], a[3] ^ a[7]]) +        return key_array + +    def callApi(self, **kwargs): +        """ Dispatch a call to the api, see https://mega.co.nz/#developers """ +        # generate a session id, no idea where to obtain elsewhere +        uid = random.randint(10 << 9, 10 ** 10) + +        resp = self.load(self.API_URL % uid, post=json.dumps([kwargs])) +        self.logDebug("Api Response: " + resp) +        return json.loads(resp) + +    def decryptAttr(self, data, key): + +        cbc = AES.new(self.getCipherKey(key), AES.MODE_CBC, "\0" * 16) +        attr = cbc.decrypt(self.b64_decode(data)) +        self.logDebug("Decrypted Attr: " + attr) +        if not attr.startswith("MEGA"): +            self.fail(_("Decryption failed")) + +        # Data is padded, 0-bytes must be stripped +        return json.loads(attr.replace("MEGA", "").rstrip("\0").strip()) + +    def decryptFile(self, key): +        """  Decrypts the file at lastDownload` """ + +        # upper 64 bit of counter start +        n = key[16:24] + +        # convert counter to long and shift bytes +        ctr = Counter.new(128, initial_value=long(n.encode("hex"),16) << 64) +        cipher = AES.new(self.getCipherKey(key), AES.MODE_CTR, counter=ctr) + +        self.pyfile.setStatus("decrypting") +        f = open(self.lastDownload, "rb") +        df = open(self.lastDownload.rsplit(self.FILE_SUFFIX)[0], "wb") + +        # TODO: calculate CBC-MAC for checksum + +        size = 2 ** 15 # buffer size, 32k +        while True: +            buf = f.read(size) +            if not buf: break + +            df.write(cipher.decrypt(buf)) + +        f.close() +        df.close() +        remove(self.lastDownload) + +    def process(self, pyfile): + +        key = None + +        # match is guaranteed because plugin was chosen to handle url +        node = re.search(self.__pattern__, pyfile.url).group(2) +        if "!" in node: +            node, key = node.split("!") + +        self.logDebug("File id: %s | Key: %s" % (node, key)) + +        if not key: +            self.fail(_("No file key provided in the URL")) + +        # g is for requesting a download url +        # this is similar to the calls in the mega js app, documentation is very bad +        dl = self.callApi(a="g", g=1, p=node, ssl=1)[0] + +        if "e" in dl: +            e = dl["e"] +            # ETEMPUNAVAIL (-18): Resource temporarily not available, please try again later +            if e == -18: +                self.retry() +            else: +                self.fail(_("Error code:") + e) + +        # TODO: map other error codes, e.g +        # EACCESS (-11): Access violation (e.g., trying to write to a read-only share) + +        key = self.b64_decode(key) +        attr = self.decryptAttr(dl["at"], key) + +        pyfile.name = attr["n"] + self.FILE_SUFFIX + +        self.download(dl["g"]) +        self.decryptFile(key) + +        # Everything is finished and final name can be set +        pyfile.name = attr["n"] diff --git a/pyload/plugins/hoster/MegacrypterCom.py b/pyload/plugins/hoster/MegacrypterCom.py new file mode 100644 index 000000000..9f012e5be --- /dev/null +++ b/pyload/plugins/hoster/MegacrypterCom.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- +import re + +from module.common.json_layer import json +from module.plugins.hoster.MegaNz import MegaNz + + +class MegacrypterCom(MegaNz): +    __name__ = "MegacrypterCom" +    __type__ = "hoster" +    __pattern__ = r"(https?://[a-z0-9]{0,10}\.?megacrypter\.com/[a-zA-Z0-9!_\-]+)" +    __version__ = "0.1" +    __description__ = """megacrypter plugin, based and inherits from RaNaN's MegaNz plugin""" +    __author_name__ = ("GonzaloSR", ) +    __author_mail__ = ("gonzalo@gonzalosr.com", ) + +    API_URL = "http://megacrypter.com/api" +    FILE_SUFFIX = ".crypted" + +    +    def callApi(self, **kwargs): +        """ Dispatch a call to the api, see megacrypter.com/api_doc """ +        self.logDebug("JSON request: " + json.dumps(kwargs)) +        resp = self.load(self.API_URL, post=json.dumps(kwargs)) +        self.logDebug("API Response: " + resp) +        return json.loads(resp) + +    +    def process(self, pyfile): + +        key = None + +        # match is guaranteed because plugin was chosen to handle url +        node = re.search(self.__pattern__, pyfile.url).group(1) + + +        # get Mega.co.nz link info +        info = self.callApi(link=node, m="info") +         +        # get crypted file URL +        dl = self.callApi(link=node, m="dl") + + +        # TODO: map error codes, implement password protection +        # if info["pass"] == true: +        #    crypted_file_key, md5_file_key = info["key"].split("#") + + +        key = self.b64_decode(info["key"]) + +        pyfile.name = info["name"] + self.FILE_SUFFIX + +        self.download(dl["url"]) +        self.decryptFile(key) + +        # Everything is finished and final name can be set +        pyfile.name = info["name"] + + diff --git a/pyload/plugins/hoster/MegasharesCom.py b/pyload/plugins/hoster/MegasharesCom.py new file mode 100644 index 000000000..3fac633bc --- /dev/null +++ b/pyload/plugins/hoster/MegasharesCom.py @@ -0,0 +1,108 @@ +# -*- 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 time import time +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo + +class MegasharesCom(SimpleHoster): +    __name__ = "MegasharesCom" +    __type__ = "hoster" +    __pattern__ = r"http://(\w+\.)?megashares.com/.*" +    __version__ = "0.21" +    __description__ = """megashares.com plugin - free only""" +    __author_name__ = ("zoidberg") +    __author_mail__ = ("zoidberg@mujmail.cz") + +    FILE_NAME_PATTERN = '<h1 class="black xxl"[^>]*title="(?P<N>[^"]+)">' +    FILE_SIZE_PATTERN = '<strong><span class="black">Filesize:</span></strong> (?P<S>[0-9.]+) (?P<U>[kKMG])i?B<br />' +    DOWNLOAD_URL_PATTERN = '<div id="show_download_button_%d"[^>]*>\s*<a href="([^"]+)">' +    PASSPORT_LEFT_PATTERN = 'Your Download Passport is: <[^>]*>(\w+).*\s*You have\s*<[^>]*>\s*([0-9.]+) ([kKMG]i?B)' +    PASSPORT_RENEW_PATTERN = 'Your download passport will renew in\s*<strong>(\d+)</strong>:<strong>(\d+)</strong>:<strong>(\d+)</strong>' +    REACTIVATE_NUM_PATTERN = r'<input[^>]*id="random_num" value="(\d+)" />' +    REACTIVATE_PASSPORT_PATTERN = r'<input[^>]*id="passport_num" value="(\w+)" />' +    REQUEST_URI_PATTERN = r'var request_uri = "([^"]+)";' +    NO_SLOTS_PATTERN = r'<dd class="red">All download slots for this link are currently filled' +    FILE_OFFLINE_PATTERN = r'<dd class="red">(Invalid Link Request|Link has been deleted)' + +    def setup(self): +        self.resumeDownload = True +        self.multiDL = True if self.premium else False +        +    def handlePremium(self): +        self.handleDownload(True) + +    def handleFree(self): +        self.html = self.load(self.pyfile.url, decode=True) +         +        if self.NO_SLOTS_PATTERN in self.html: +            self.retry(wait_time = 300) +         +        self.getFileInfo() +        #if self.pyfile.size > 576716800: self.fail("This file is too large for free download") + +        # Reactivate passport if needed +        found = re.search(self.REACTIVATE_PASSPORT_PATTERN, self.html) +        if found: +            passport_num = found.group(1) +            request_uri = re.search(self.REQUEST_URI_PATTERN, self.html).group(1) + +            for i in range(5): +                random_num = re.search(self.REACTIVATE_NUM_PATTERN, self.html).group(1) + +                verifyinput = self.decryptCaptcha("http://megashares.com/index.php?secgfx=gfx&random_num=%s" % random_num) +                self.logInfo("Reactivating passport %s: %s %s" % (passport_num, random_num, verifyinput)) + +                url = "http://d01.megashares.com%s&rs=check_passport_renewal" % request_uri + \ +                    "&rsargs[]=%s&rsargs[]=%s&rsargs[]=%s" % (verifyinput, random_num, passport_num) + \ +                    "&rsargs[]=replace_sec_pprenewal&rsrnd=%s" % str(int(time()*1000)) +                self.logDebug(url) +                response = self.load(url) + +                if 'Thank you for reactivating your passport.' in response: +                    self.correctCaptcha() +                    self.retry(0) +                else: +                    self.invalidCaptcha() +            else: self.fail("Failed to reactivate passport") + +        # Check traffic left on passport +        found = re.search(self.PASSPORT_LEFT_PATTERN, self.html) +        if not found: self.fail('Passport not found') +        self.logInfo("Download passport: %s" % found.group(1)) +        data_left = float(found.group(2)) * 1024 ** {'KB': 1, 'MB': 2, 'GB': 3}[found.group(3)] +        self.logInfo("Data left: %s %s (%d MB needed)" % (found.group(2), found.group(3), self.pyfile.size / 1048576)) +         +        if not data_left: +            found = re.search(self.PASSPORT_RENEW_PATTERN, self.html) +            renew = (found.group(1) + 60 * (found.group(2) + 60 * found.group(3))) if found else 600 +            self.retry(renew, 15, "Unable to get passport") +             +        self.handleDownload(False) +     +    def handleDownload(self, premium = False):  +        # Find download link; +        found = re.search(self.DOWNLOAD_URL_PATTERN % (1 if premium else 2), self.html) +        msg = '%s download URL' % ('Premium' if premium else 'Free') +        if not found: self.parseError(msg) +         +        download_url = found.group(1) +        self.logDebug("%s: %s" % (msg, download_url)) +        self.download(download_url) + +getInfo = create_getInfo(MegasharesCom)
\ No newline at end of file diff --git a/pyload/plugins/hoster/MovReelCom.py b/pyload/plugins/hoster/MovReelCom.py new file mode 100644 index 000000000..6f5f1d3f1 --- /dev/null +++ b/pyload/plugins/hoster/MovReelCom.py @@ -0,0 +1,106 @@ +# -*- coding: utf-8 -*- +import re +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo +from module.utils import html_unescape +from module.network.RequestFactory import getURL + +class MovReelCom(SimpleHoster): +  __name__ = "MovReelCom" +  __type__ = "hoster" +  __pattern__ = r"http://movreel.com/.*" +  __version__ = "1.00" +  __description__ = """MovReel.com hoster plugin""" +  __author_name__ = ("JorisV83") +  __author_mail__ = ("jorisv83-pyload@yahoo.com") +   +  FILE_INFO_PATTERN = r'You have requested <font color="red">http://movreel.com/.*/(?P<N>.+?)</font>.*\((?P<S>[\d.]+) (?P<U>..)\)</font>' +  FILE_OFFLINE_PATTERN = r'<b>File Not Found</b>' +   +  def setup(self): +    self.resumeDownload = True +    self.multiDL = False +     +  def handleFree(self): +     +    # Define search patterns +    op_pattern = '<input type="hidden" name="op" value="(.*)">' +    id_pattern = '<input type="hidden" name="id" value="(.*)">' +    fn_pattern = '<input type="hidden" name="fname" value="(.*)">' +    re_pattern = '<input type="hidden" name="referer" value="(.*)">' +    ul_pattern = '<input type="hidden" name="usr_login" value="(.*)">' +    rand_pattern = '<input type="hidden" name="rand" value="(.*)">' +    link_pattern = "var file_link = '(.*)';" +    downlimit_pattern = '<br><p class="err">You have reached the download-limit: .*</p>' +     +    # Get HTML source +    self.logDebug("Getting first HTML source") +    html = self.load(self.pyfile.url) +    self.logDebug(" > Done") +     +    op_val = re.search(op_pattern, html).group(1) +    id_val = re.search(id_pattern, html).group(1) +    fn_val = re.search(fn_pattern, html).group(1) +    re_val = re.search(re_pattern, html).group(1) +    ul_val = re.search(ul_pattern, html).group(1) +     +    # Debug values +    self.logDebug(" > Op " + op_val) +    self.logDebug(" > Id " + id_val) +    self.logDebug(" > Fname " + fn_val) +    self.logDebug(" > Referer " + re_val) +    self.logDebug(" > User Login " + ul_val) +     +    # Create post data +    post_data = {"op" : op_val, "usr_login" : ul_val, "id" : id_val, "fname" : fn_val, "referer" : re_val, "method_free" : "+Free+Download"} +     +    # Post and get new HTML source +    self.logDebug("Getting second HTML source") +    html = self.load(self.pyfile.url, post = post_data, decode=True) +    self.logDebug(" > Done") +     +    # Check download limit +    if re.search(downlimit_pattern, html) is not None: +      self.retry(3, 7200, "Download limit reached, wait 2h")  +     +    # Retrieve data +    if re.search(op_pattern, html) is not None: +      op_val = re.search(op_pattern, html).group(1) +    else: +      self.retry(3, 10, "Second html: no op found!!") +     +    if re.search(id_pattern, html) is not None: +      id_val = re.search(id_pattern, html).group(1) +    else: +      self.retry(3, 10, "Second html: no id found!!")    	 +    	 +    if re.search(rand_pattern, html) is not None: +      rand_val = re.search(rand_pattern, html).group(1) +    else: +      self.retry(3, 10, "Second html: no rand found!!") +       +    re_val = self.pyfile.url +     +    # Debug values +    self.logDebug(" > Op " + op_val) +    self.logDebug(" > Id " + id_val) +    self.logDebug(" > Rand " + rand_val) +    self.logDebug(" > Referer " + re_val) +     +    # Create post data +    post_data = {"op" : op_val, "id" : id_val, "rand" : rand_val, "referer" : re_val, "method_free" : "+Free+Download", "method_premium" : "", "down_direct" : "1"} +     +    # Post and get new HTML source +    self.logDebug("Getting third HTML source") +    html = self.load(self.pyfile.url, post = post_data, decode=True) +    self.logDebug(" > Done") +     +    # Get link value +    if re.search(link_pattern, html) is not None: +      link_val = re.search(link_pattern, html).group(1) +      self.logDebug(" > Link " + link_val) +      self.download(link_val) +    else: +      self.logDebug("No link found!!") +      self.retry(3, 10, "No link found!!") +       +getInfo = create_getInfo(MovReelCom)
\ No newline at end of file diff --git a/pyload/plugins/hoster/MultiDebridCom.py b/pyload/plugins/hoster/MultiDebridCom.py new file mode 100644 index 000000000..7280504cb --- /dev/null +++ b/pyload/plugins/hoster/MultiDebridCom.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- + +############################################################################ +# This program is free software: you can redistribute it and/or modify     # +# it under the terms of the GNU Affero 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 Affero General Public License for more details.                      # +#                                                                          # +# You should have received a copy of the GNU Affero 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.common.json_layer import json_loads + + +class MultiDebridCom(Hoster): +    __name__ = "MultiDebridCom" +    __version__ = "0.02" +    __type__ = "hoster" +    __pattern__ = r"http://\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/dl/" +    __description__ = """Multi-debrid.com hoster plugin""" +    __author_name__ = ("stickell") +    __author_mail__ = ("l.stickell@yahoo.it") + +    def init(self): +        self.chunkLimit = -1 +        self.resumeDownload = True + +    def process(self, pyfile): +        if not self.account: +            self.logError(_("Please enter your %s account or deactivate this plugin") % "Multi-debrid.com") +            self.fail("No Multi-debrid.com account provided") + +        self.logDebug("Original URL: %s" % pyfile.url) +        if re.match(self.__pattern__, pyfile.url): +            new_url = pyfile.url +        else: +            page = self.req.load('http://multi-debrid.com/api.php', +                                 get={'user': self.user, 'pass': self.account.getAccountData(self.user)['password'], +                                      'link': pyfile.url}) +            self.logDebug("JSON data: " + page) +            page = json_loads(page) +            if page['status'] != 'ok': +                self.fail('Unable to unrestrict link') +            new_url = page['link'] + +        self.logDebug("Unrestricted URL: " + new_url) + +        self.download(new_url, disposition=True) diff --git a/pyload/plugins/hoster/MultishareCz.py b/pyload/plugins/hoster/MultishareCz.py new file mode 100644 index 000000000..af7aa94cf --- /dev/null +++ b/pyload/plugins/hoster/MultishareCz.py @@ -0,0 +1,76 @@ +# -*- 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 MultishareCz(SimpleHoster): +    __name__ = "MultishareCz" +    __type__ = "hoster" +    __pattern__ = r"http://(?:\w*\.)?multishare.cz/stahnout/(?P<ID>\d+).*" +    __version__ = "0.40" +    __description__ = """MultiShare.cz""" +    __author_name__ = ("zoidberg") + +    FILE_INFO_PATTERN = ur'(?:<li>Název|Soubor): <strong>(?P<N>[^<]+)</strong><(?:/li><li|br)>Velikost: <strong>(?P<S>[^<]+)</strong>' +    FILE_OFFLINE_PATTERN = ur'<h1>Stáhnout soubor</h1><p><strong>Požadovaný soubor neexistuje.</strong></p>' +    FILE_SIZE_REPLACEMENTS = [(' ', '')] +     +    def process(self, pyfile): +        msurl = re.match(self.__pattern__, pyfile.url) +        if msurl: +            self.fileID = msurl.group('ID')         +            self.html = self.load(pyfile.url, decode = True)        +            self.getFileInfo() +                     +            if self.premium: +                self.handlePremium() +            else: +                self.handleFree()          +        else:      +            self.handleOverriden()            + +    def handleFree(self): +        self.download("http://www.multishare.cz/html/download_free.php?ID=%s" % self.fileID) +         +    def handlePremium(self): +        if not self.checkTrafficLeft(): +            self.logWarning("Not enough credit left to download file") +            self.resetAccount()  +                 +        self.download("http://www.multishare.cz/html/download_premium.php?ID=%s" % self.fileID) +        self.checkTrafficLeft() +     +    def handleOverriden(self): +        if not self.premium:  +            self.fail("Only premium users can download from other hosters") +         +        self.html = self.load('http://www.multishare.cz/html/mms_ajax.php', post = {"link": self.pyfile.url}, decode = True)         +        self.getFileInfo()        +         +        if not self.checkTrafficLeft(): +            self.fail("Not enough credit left to download file") +         +        url = "http://dl%d.mms.multishare.cz/html/mms_process.php" % round(random()*10000*random())     +        params = {"u_ID" : self.acc_info["u_ID"], "u_hash" : self.acc_info["u_hash"], "link" : self.pyfile.url} +        self.logDebug(url, params) +        self.download(url, get = params) +        self.checkTrafficLeft() + +getInfo = create_getInfo(MultishareCz)
\ No newline at end of file diff --git a/pyload/plugins/hoster/MyvideoDe.py b/pyload/plugins/hoster/MyvideoDe.py new file mode 100644 index 000000000..f2d2082a7 --- /dev/null +++ b/pyload/plugins/hoster/MyvideoDe.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- + +import re +from module.plugins.Hoster import Hoster +from module.unescape import unescape + +class MyvideoDe(Hoster): +    __name__ = "MyvideoDe" +    __type__ = "hoster" +    __pattern__ = r"http://(www\.)?myvideo.de/watch/" +    __version__ = "0.9" +    __description__ = """Myvideo.de Video Download Hoster""" +    __author_name__ = ("spoob") +    __author_mail__ = ("spoob@pyload.org") +         +    def setup(self): +        self.html = None +         +    def process(self, pyfile): +        self.pyfile = pyfile +        self.download_html() +        pyfile.name = self.get_file_name() +        self.download(self.get_file_url()) + +    def download_html(self): +        self.html = self.load(self.pyfile.url) + +    def get_file_url(self): +        videoId = re.search(r"addVariable\('_videoid','(.*)'\);p.addParam\('quality'", self.html).group(1) +        videoServer = re.search("rel='image_src' href='(.*)thumbs/.*' />", self.html).group(1) +        file_url = videoServer + videoId + ".flv" +        return file_url + +    def get_file_name(self): +        file_name_pattern = r"<h1 class='globalHd'>(.*)</h1>" +        return unescape(re.search(file_name_pattern, self.html).group(1).replace("/", "") + '.flv') + +    def file_exists(self): +        self.download_html() +        self.load(str(self.pyfile.url), cookies=False, just_header=True) +        if self.req.lastEffectiveURL == "http://www.myvideo.de/": +            return False +        return True diff --git a/pyload/plugins/hoster/NarodRu.py b/pyload/plugins/hoster/NarodRu.py new file mode 100644 index 000000000..335860de9 --- /dev/null +++ b/pyload/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/pyload/plugins/hoster/NetloadIn.py b/pyload/plugins/hoster/NetloadIn.py new file mode 100644 index 000000000..c59080158 --- /dev/null +++ b/pyload/plugins/hoster/NetloadIn.py @@ -0,0 +1,252 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import re +from time import sleep, time + + +from module.utils import chunks +from module.plugins.Hoster import Hoster +from module.network.RequestFactory import getURL + +def getInfo(urls): + ##  returns list of tuples (name, size (in bytes), status (see FileDatabase), url) + + +    apiurl = "http://api.netload.in/info.php?auth=Zf9SnQh9WiReEsb18akjvQGqT0I830e8&bz=1&md5=1&file_id=" +    id_regex = re.compile(NetloadIn.__pattern__) +    urls_per_query = 80 + +    for chunk in chunks(urls, urls_per_query): +        ids = "" +        for url in chunk: +            match = id_regex.search(url) +            if match: +                ids = ids + match.group(1) +";" + +        api = getURL(apiurl+ids, decode = True) + +        if api is None or len(api) < 10: +            print "Netload prefetch: failed " +            return +        if api.find("unknown_auth") >= 0: +            print "Netload prefetch: Outdated auth code " +            return + +        result = [] + +        for i, r in enumerate(api.splitlines()): +            try: +                tmp = r.split(";") +                try: +                    size = int(tmp[2]) +                except: +                    size = 0 +                result.append( (tmp[1], size, 2 if tmp[3] == "online" else 1, chunk[i] ) ) +            except: +                print "Netload prefetch: Error while processing response: " +                print r + +        yield result + +class NetloadIn(Hoster): +    __name__ = "NetloadIn" +    __type__ = "hoster" +    __pattern__ = r"https?://.*netload\.in/(?:datei(.*?)(?:\.htm|/)|index.php?id=10&file_id=)" +    __version__ = "0.43" +    __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.premium: +            self.multiDL = True +            self.chunkLimit = -1 +            self.resumeDownload = True + +    def process(self, pyfile): +        self.url = pyfile.url +        self.prepare() +        self.pyfile.setStatus("downloading") +        self.proceed(self.url) + +    def prepare(self): +        self.download_api_data() + +        if self.api_data and self.api_data["filename"]: +            self.pyfile.name = self.api_data["filename"] + +        if self.premium: +            self.logDebug("Netload: Use Premium Account") +            return True + +        if self.download_html(): +            return True +        else: +            self.fail("Failed") +            return False +             +    def download_api_data(self, n=0): +        url = self.url +        id_regex = re.compile(self.__pattern__) +        match = id_regex.search(url) + +        if match: +            #normalize url +            self.url = 'http://www.netload.in/datei%s.htm' % match.group(1) +            self.logDebug("URL: %s" % self.url) +        else: +            self.api_data = False +            return + +        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) +            return  + +        self.logDebug("Netload: APIDATA: "+src) +        self.api_data = {} +        if src and ";" in 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] +            self.api_data["filename"] = lines[1] +            self.api_data["size"] = lines[2] +            self.api_data["status"] = lines[3] +            if self.api_data["status"] == "online": +                self.api_data["checksum"] = lines[4].strip() +            else: +                self.api_data = False  #check manually since api data is useless sometimes + +            if lines[0] == lines[1] and lines[2] == "0": #useless api data +                self.api_data = False +        else: +            self.api_data = False +             +    def final_wait(self, page): +        wait_time = self.get_wait_time(page) +        self.setWait(wait_time) +        self.logDebug("Netload: final wait %d seconds" % wait_time) +        self.wait() +        self.url = self.get_file_url(page) + +    def download_html(self): +        self.logDebug("Netload: Entering download_html") +        page = self.load(self.url, decode=True) +        t = time() + 30 +         +        if "/share/templates/download_hddcrash.tpl" in page: +            self.logError("Netload HDD Crash") +            self.fail(_("File temporarily not available")) +         +        if not self.api_data: +            self.logDebug("API Data may be useless, get details from html page") + +            if "* The file was deleted" in page: +                self.offline() + +            name = re.search(r'class="dl_first_filename">([^<]+)', page, re.MULTILINE) +            # 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): + +            if not page: +                page = self.load(self.url) +                t = time() + 30 +             +            if "/share/templates/download_hddcrash.tpl" in page: +                self.logError("Netload HDD Crash") +                self.fail(_("File temporarily not available")) +             +            self.logDebug("Netload: try number %d " % i) + +            if ">Your download is being prepared.<" in page: +                self.logDebug("Netload: We will prepare your download") +                self.final_wait(page) +                return True +            if ">An access request has been made from IP address <" in page: +                wait = self.get_wait_time(page) +                if wait == 0: +                    self.logDebug("Netload: Wait was 0 setting 30") +                    wait = 30 +                self.logInfo(_("Netload: waiting between downloads %d s." % wait)) +                self.wantReconnect = True +                self.setWait(wait) +                self.wait() + +                return self.download_html() + +             +            self.logDebug("Netload: Trying to find captcha") + +            try: +                url_captcha_html = "http://netload.in/" + re.search('(index.php\?id=10&.*&captcha=1)', page).group(1).replace("amp;", "") +            except: +                page = None +                continue + +            try: +                page = self.load(url_captcha_html, cookies=True) +                captcha_url = "http://netload.in/" + re.search('(share/includes/captcha.php\?t=\d*)', page).group(1) +            except: +                self.logDebug("Netload: Could not find captcha, try again from beginning") +                captchawaited = False +                continue + +            file_id = re.search('<input name="file_id" type="hidden" value="(.*)" />', page).group(1) +            if not captchawaited: +                wait = self.get_wait_time(page) +                if i == 0: self.pyfile.waitUntil = time() # don't wait contrary to time on web site +                else: self.pyfile.waitUntil = t +                self.logInfo(_("Netload: waiting for captcha %d s.") % (self.pyfile.waitUntil - time())) +                #self.setWait(wait) +                self.wait() +                captchawaited = True + +            captcha = self.decryptCaptcha(captcha_url) +            page = self.load("http://netload.in/index.php?id=10", post={"file_id": file_id, "captcha_check": captcha}, cookies=True) + +        return False +         + +    def get_file_url(self, page): +        try: +            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) +            else: +                self.logDebug("Netload: Backup try for final link") +                file_url_pattern = r"<a href=\"(.+)\" class=\"Orange_Link\">Click here" +                attempt = re.search(file_url_pattern, page) +                return "http://netload.in/"+attempt.group(1) +        except: +            self.logDebug("Netload: Getting final link failed") +            return None + +    def get_wait_time(self, page): +        wait_seconds = int(re.search(r"countdown\((.+),'change\(\)'\)", page).group(1)) / 100 +        return wait_seconds +         + +    def proceed(self, url): +        self.logDebug("Netload: Downloading..") + +        self.download(url, disposition=True) + +        check = self.checkDownload({"empty": re.compile(r"^$"), "offline": re.compile("The file was deleted")}) + +        if check == "empty": +            self.logInfo(_("Downloaded File was empty")) +            self.retry() +        elif check == "offline": +            self.offline() + diff --git a/pyload/plugins/hoster/NovafileCom.py b/pyload/plugins/hoster/NovafileCom.py new file mode 100644 index 000000000..dfd18761c --- /dev/null +++ b/pyload/plugins/hoster/NovafileCom.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +from module.plugins.hoster.XFileSharingPro import XFileSharingPro, create_getInfo + +class NovafileCom(XFileSharingPro): +    __name__ = "NovafileCom" +    __type__ = "hoster" +    __pattern__ = r"http://(?:\w*\.)*novafile\.com/\w{12}" +    __version__ = "0.01" +    __description__ = """novafile.com hoster plugin""" +    __author_name__ = ("zoidberg") +    __author_mail__ = ("zoidberg@mujmail.cz") +        +    FILE_SIZE_PATTERN = r'<div class="size">(?P<S>.+?)</div>' +    #FILE_OFFLINE_PATTERN = '<b>"File Not Found"</b>|File has been removed due to Copyright Claim' +    FORM_PATTERN = r'name="F\d+"' +    ERROR_PATTERN = r'class="alert[^"]*alert-separate"[^>]*>\s*(?:<p>)?(.*?)\s*</' +    DIRECT_LINK_PATTERN = r'<a href="(http://s\d+\.novafile\.com/.*?)" class="btn btn-green">Download File</a>' +     +    HOSTER_NAME = "novafile.com"    +     +    def setup(self): +        self.multiDL = False  + +getInfo = create_getInfo(NovafileCom)
\ No newline at end of file diff --git a/pyload/plugins/hoster/NowDownloadEu.py b/pyload/plugins/hoster/NowDownloadEu.py new file mode 100644 index 000000000..126ca3d89 --- /dev/null +++ b/pyload/plugins/hoster/NowDownloadEu.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 +from module.utils import fixup + +class NowDownloadEu(SimpleHoster): +    __name__ = "NowDownloadEu" +    __type__ = "hoster" +    __pattern__ = r"http://(www\.)?nowdownload\.(eu|co)/dl/(?P<ID>[a-z0-9]+)" +    __version__ = "0.02" +    __description__ = """NowDownloadEu""" +    __author_name__ = ("godofdream") +    FILE_INFO_PATTERN = r'Downloading</span> <br> (?P<N>.*) (?P<S>[0-9,.]+) (?P<U>[kKMG])i?B </h4>' +    FILE_OFFLINE_PATTERN = r'(This file does not exist!)' +    FILE_TOKEN_PATTERN = r'"(/api/token\.php\?token=[a-z0-9]+)"' +    FILE_CONTINUE_PATTERN = r'"(/dl2/[a-z0-9]+/[a-z0-9]+)"' +    FILE_WAIT_PATTERN = r'\.countdown\(\{until: \+(\d+),' +    FILE_DOWNLOAD_LINK = r'"(http://f\d+\.nowdownload\.eu/dl/[a-z0-9]+/[a-z0-9]+/[^<>"]*?)"' + +    FILE_NAME_REPLACEMENTS = [("&#?\w+;", fixup), (r'<[^>]*>', '')] + +    def setup(self): +        self.wantReconnect = False +        self.multiDL = True +        self.chunkLimit = -1 +        self.resumeDownload = True + +    def handleFree(self): +        tokenlink = re.search(self.FILE_TOKEN_PATTERN, self.html) +        continuelink = re.search(self.FILE_CONTINUE_PATTERN, self.html) +        if (not tokenlink) or (not continuelink): self.fail('Plugin out of Date') + +        wait = 60 +        found = re.search(self.FILE_WAIT_PATTERN, self.html) +        if found: wait = int(found.group(1)) + +        self.html = self.load("http://www.nowdownload.eu" + str(tokenlink.group(1))) +        self.setWait(wait) +        self.wait()  + +        self.html = self.load("http://www.nowdownload.eu" + str(continuelink.group(1))) + +        url = re.search(self.FILE_DOWNLOAD_LINK, self.html) +        if not url: self.fail('Download Link not Found (Plugin out of Date?)') +        self.logDebug('Download link: ' + str(url.group(1))) +        self.download(str(url.group(1)))         + +getInfo = create_getInfo(NowDownloadEu) diff --git a/pyload/plugins/hoster/OneFichierCom.py b/pyload/plugins/hoster/OneFichierCom.py new file mode 100644 index 000000000..c7c3384e9 --- /dev/null +++ b/pyload/plugins/hoster/OneFichierCom.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- + +import re +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.47" +    __description__ = """1fichier.com download hoster""" +    __author_name__ = ("fragonib", "the-razer", "zoidberg","imclem") +    __author_mail__ = ("fragonib[AT]yahoo[DOT]es", "daniel_ AT gmx DOT net", "zoidberg@mujmail.cz","imclem on github") +     +    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_PATTERN = "Warning ! Without premium status, you can download only one file at a time and you must wait up to (\d+) minutes between each downloads." +    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) +         +        found = re.search(self.WAITING_PATTERN, self.html) +        if found: +            self.waitAndRetry(int(found.group(1)) * 60) +         +        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 "pass" in inputs: +            inputs['pass'] = self.getPassword() +             +        self.download(url, post = inputs) +         +        # Check download  +        self.checkDownloadedFile() +             +    def checkDownloadedFile(self): +        check = self.checkDownload({"wait": self.WAITING_PATTERN}) +        if check == "wait": +            self.waitAndRetry(int(self.lastcheck.group(1)) * 60) +     +    def waitAndRetry(self, wait_time): +        self.setWait(wait_time, True) +        self.wait() +        self.retry() +         +getInfo = create_getInfo(OneFichierCom)    diff --git a/pyload/plugins/hoster/PornhostCom.py b/pyload/plugins/hoster/PornhostCom.py new file mode 100644 index 000000000..ef7961d81 --- /dev/null +++ b/pyload/plugins/hoster/PornhostCom.py @@ -0,0 +1,76 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import re +from module.plugins.Hoster import Hoster + +class PornhostCom(Hoster): +    __name__ = "PornhostCom" +    __type__ = "hoster" +    __pattern__ = r'http://[\w\.]*?pornhost\.com/([0-9]+/[0-9]+\.html|[0-9]+)' +    __version__ = "0.2" +    __description__ = """Pornhost.com Download Hoster""" +    __author_name__ = ("jeix") +    __author_mail__ = ("jeix@hasnomail.de") +         +    def process(self, pyfile): +        self.download_html() +        if not self.file_exists(): +            self.offline() +             +        pyfile.name = self.get_file_name() +        self.download(self.get_file_url()) +         + +    ###   old interface +    def download_html(self): +        url = self.pyfile.url +        self.html = self.load(url) + +    def get_file_url(self): +        """ returns the absolute downloadable filepath +        """ +        if self.html is None: +            self.download_html() + +        file_url = re.search(r'download this file</label>.*?<a href="(.*?)"', self.html) +        if not file_url:  +            file_url = re.search(r'"(http://dl[0-9]+\.pornhost\.com/files/.*?/.*?/.*?/.*?/.*?/.*?\..*?)"', self.html) +            if not file_url: +                file_url = re.search(r'width: 894px; height: 675px">.*?<img src="(.*?)"', self.html) +                if not file_url: +                    file_url = re.search(r'"http://file[0-9]+\.pornhost\.com/[0-9]+/.*?"', self.html) # TODO: fix this one since it doesn't match + +        file_url = file_url.group(1).strip() +                     +        return file_url +     +    def get_file_name(self): +        if self.html is None: +            self.download_html() +             +        name = re.search(r'<title>pornhost\.com - free file hosting with a twist - gallery(.*?)</title>', self.html) +        if not name: +            name = re.search(r'id="url" value="http://www\.pornhost\.com/(.*?)/"', self.html) +            if not name: +                name = re.search(r'<title>pornhost\.com - free file hosting with a twist -(.*?)</title>', self.html) +                if not name: +                    name = re.search(r'"http://file[0-9]+\.pornhost\.com/.*?/(.*?)"', self.html) +        +        name = name.group(1).strip() + ".flv" +         +        return name + +    def file_exists(self): +        """ returns True or False +        """ +        if self.html is None: +            self.download_html() +         +        if re.search(r'gallery not found', self.html) is not None \ +        or re.search(r'You will be redirected to', self.html) is not None: +            return False +        else: +            return True +             +             diff --git a/pyload/plugins/hoster/PornhubCom.py b/pyload/plugins/hoster/PornhubCom.py new file mode 100644 index 000000000..c431004d8 --- /dev/null +++ b/pyload/plugins/hoster/PornhubCom.py @@ -0,0 +1,83 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import re +from module.plugins.Hoster import Hoster + +class PornhubCom(Hoster): +    __name__ = "PornhubCom" +    __type__ = "hoster" +    __pattern__ = r'http://[\w\.]*?pornhub\.com/view_video\.php\?viewkey=[\w\d]+' +    __version__ = "0.5" +    __description__ = """Pornhub.com Download Hoster""" +    __author_name__ = ("jeix") +    __author_mail__ = ("jeix@hasnomail.de") +         +    def process(self, pyfile): +        self.download_html() +        if not self.file_exists(): +            self.offline() +             +        pyfile.name = self.get_file_name() +        self.download(self.get_file_url()) +         +    def download_html(self): +        url = self.pyfile.url +        self.html = self.load(url) + +    def get_file_url(self): +        """ returns the absolute downloadable filepath +        """ +        if self.html is None: +            self.download_html() + +        url = "http://www.pornhub.com//gateway.php" +        video_id = self.pyfile.url.split('=')[-1] +        # thanks to jD team for this one  v +        post_data = "\x00\x03\x00\x00\x00\x01\x00\x0c\x70\x6c\x61\x79\x65\x72\x43\x6f\x6e\x66\x69\x67\x00\x02\x2f\x31\x00\x00\x00\x44\x0a\x00\x00\x00\x03\x02\x00" +        post_data += chr(len(video_id)) +        post_data += video_id +        post_data += "\x02\x00\x02\x2d\x31\x02\x00\x20" +        post_data += "add299463d4410c6d1b1c418868225f7" +         +        content = self.req.load(url, post=str(post_data)) +         +        new_content = "" +        for x in content: +            if ord(x) < 32 or ord(x) > 176: +                new_content += '#' +            else: +                new_content += x +                 +        content = new_content +         +        file_url = re.search(r'flv_url.*(http.*?)##post_roll', content).group(1) + +        return file_url +     +    def get_file_name(self): +        if self.html is None: +            self.download_html() +         +        match = re.search(r'<title[^>]+>([^<]+) - ', self.html) +        if match: +            name = match.group(1) +        else: +            matches = re.findall('<h1>(.*?)</h1>', self.html) +            if len(matches) > 1: +                name = matches[1] +            else: +                name = matches[0] +         +        return name + '.flv' + +    def file_exists(self): +        """ returns True or False +        """ +        if self.html is None: +            self.download_html() +         +        if re.search(r'This video is no longer in our database or is in conversion', self.html) is not None: +            return False +        else: +            return True diff --git a/pyload/plugins/hoster/Premium4Me.py b/pyload/plugins/hoster/Premium4Me.py new file mode 100644 index 000000000..0bdb22bd7 --- /dev/null +++ b/pyload/plugins/hoster/Premium4Me.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +from urllib import quote +from os.path import exists +from os import remove + +from pyload.plugins.Hoster import Hoster +from pyload.utils.fs import fs_encode + +class Premium4Me(Hoster): +    __name__ = "Premium4Me" +    __version__ = "0.08" +    __type__ = "hoster" + +    __pattern__ = r"http://premium.to/.*" +    __description__ = """Premium.to hoster plugin""" +    __author_name__ = ("RaNaN", "zoidberg", "stickell") +    __author_mail__ = ("RaNaN@pyload.org", "zoidberg@mujmail.cz", "l.stickell@yahoo.it") + +    def setup(self): +        self.resumeDownload = True +        self.chunkLimit = 1 + +    def process(self, pyfile): +        if not self.account: +            self.logError(_("Please enter your %s account or deactivate this plugin") % "premium.to") +            self.fail("No premium.to account provided") + +        self.logDebug("premium.to: Old URL: %s" % pyfile.url) + +        tra = self.getTraffic() + +        #raise timeout to 2min +        self.req.setOption("timeout", 120) + +        self.download( +            "http://premium.to/api/getfile.php?authcode=%s&link=%s" % (self.account.authcode, quote(pyfile.url, "")), +            disposition=True) + +        check = self.checkDownload({"nopremium": "No premium account available"}) + +        if check == "nopremium": +            self.retry(60, 300, 'No premium account available') + +        err = '' +        if self.req.http.code == '420': +            # Custom error code send - fail +            lastDownload = fs_encode(self.lastDownload) + +            if exists(lastDownload): +                f = open(lastDownload, "rb") +                err = f.read(256).strip() +                f.close() +                remove(lastDownload) +            else: +                err = 'File does not exist' + +        trb = self.getTraffic() +        self.logInfo("Filesize: %d, Traffic used %d, traffic left %d" % (pyfile.size, tra - trb, trb)) + +        if err: self.fail(err) + +    def getTraffic(self): +        try: +            traffic = int(self.load("http://premium.to/api/traffic.php?authcode=%s" % self.account.authcode)) +        except: +            traffic = 0 +        return traffic        diff --git a/pyload/plugins/hoster/PremiumizeMe.py b/pyload/plugins/hoster/PremiumizeMe.py new file mode 100644 index 000000000..7f332e58b --- /dev/null +++ b/pyload/plugins/hoster/PremiumizeMe.py @@ -0,0 +1,47 @@ +from pyload.plugins.Hoster import Hoster +from pyload.utils import json_loads + +class PremiumizeMe(Hoster): +    __name__ = "PremiumizeMe" +    __version__ = "0.12" +    __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.isUsable(): +            self.logError(_("Please enter your %s account or deactivate this plugin") % "premiumize.me") +            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 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" % (self.account.loginname, self.account.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/pyload/plugins/hoster/PutlockerCom.py b/pyload/plugins/hoster/PutlockerCom.py new file mode 100644 index 000000000..b2016472d --- /dev/null +++ b/pyload/plugins/hoster/PutlockerCom.py @@ -0,0 +1,78 @@ +# -*- 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 +""" + +# http://www.putlocker.com/file/83C174C844583CF7 + +import re + +from module.plugins.internal.SimpleHoster import SimpleHoster + + +class PutlockerCom(SimpleHoster): +    __name__ = "PutlockerCom" +    __type__ = "hoster" +    __pattern__ = r'http://(www\.)?putlocker\.com/(file|embed)/[A-Z0-9]+' +    __version__ = "0.25" +    __description__ = """Putlocker.Com""" +    __author_name__ = ("jeix", "stickell") +    __author_mail__ = ("l.stickell@yahoo.it") + +    FILE_OFFLINE_PATTERN = r"This file doesn't exist, or has been removed." +    FILE_INFO_PATTERN = r'site-content">\s*<h1>(?P<N>.+)<strong>\( (?P<S>[^)]+) \)</strong></h1>' + +    def handleFree(self): +        self.pyfile.url = re.sub(r'http://putlocker\.com', r'http://www.putlocker.com', self.pyfile.url) + +        self.html = self.load(self.pyfile.url, decode=True) + +        link = self._getLink() +        if not link.startswith('http://'): +            link = "http://www.putlocker.com" + link +        self.download(link, disposition=True) + +    def _getLink(self): +        hash_data = re.search(r'<input type="hidden" value="([a-z0-9]+)" name="hash">', self.html) +        if not hash_data: +            self.parseError('Unable to detect hash') + +        post_data = {"hash": hash_data.group(1), "confirm": "Continue+as+Free+User"} +        self.html = self.load(self.pyfile.url, post=post_data) +        if ">You have exceeded the daily stream limit for your country\\. You can wait until tomorrow" in self.html or \ +                        "(>This content server has been temporarily disabled for upgrades|Try again soon\\. You can still download it below\\.<)" in self.html: +            self.retry(wait_time=2 * 60 * 60, reason="Download limit exceeded or server disabled") + +        patterns = (r'(/get_file\.php\?id=[A-Z0-9]+&key=[A-Za-z0-9=]+&original=1)', +                    r"(/get_file\.php\?download=[A-Z0-9]+&key=[a-z0-9]+)", +                    r"(/get_file\.php\?download=[A-Z0-9]+&key=[a-z0-9]+&original=1)", +                    r'<a href="/gopro\.php">Tired of ads and waiting\? Go Pro!</a>[\t\n\rn ]+</div>[\t\n\rn ]+<a href="(/.*?)"') +        for pattern in patterns: +            link = re.search(pattern, self.html) +            if link: +                break +        else: +            link = re.search(r"playlist: '(/get_file\.php\?stream=[A-Za-z0-9=]+)'", self.html) +            if link: +                self.html = self.load("http://www.putlocker.com" + link.group(1)) +                link = re.search(r'media:content url="(http://.*?)"', self.html) +                if not link: +                    link = re.search("\"(http://media\\-b\\d+\\.putlocker\\.com/download/\\d+/.*?)\"", self.html) +            else: +                self.parseError('Unable to detect a download link') + +        return link.group(1).replace("&", "&") diff --git a/pyload/plugins/hoster/QuickshareCz.py b/pyload/plugins/hoster/QuickshareCz.py new file mode 100644 index 000000000..4932c4702 --- /dev/null +++ b/pyload/plugins/hoster/QuickshareCz.py @@ -0,0 +1,99 @@ +# -*- coding: utf-8 -*- +""" +    This program is free software; you can redistribute it and/or modify +    it under the terms of the GNU General Public License as published by +    the Free Software Foundation; either version 3 of the License, +    or (at your option) any later version. + +    This program is distributed in the hope that it will be useful, +    but WITHOUT ANY WARRANTY; without even the implied warranty of +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +    See the GNU General Public License for more details. + +    You should have received a copy of the GNU General Public License +    along with this program; if not, see <http://www.gnu.org/licenses/>. + +    @author: zoidberg +""" + +import re +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo +from pycurl import FOLLOWLOCATION + +class QuickshareCz(SimpleHoster): +    __name__ = "QuickshareCz" +    __type__ = "hoster" +    __pattern__ = r"http://.*quickshare.cz/stahnout-soubor/.*" +    __version__ = "0.54" +    __description__ = """Quickshare.cz""" +    __author_name__ = ("zoidberg") + +    FILE_NAME_PATTERN = r'<th width="145px">Název:</th>\s*<td style="word-wrap:break-word;">(?P<N>[^<]+)</td>' +    FILE_SIZE_PATTERN = r'<th>Velikost:</th>\s*<td>(?P<S>[0-9.]+) (?P<U>[kKMG])i?B</td>' +    FILE_OFFLINE_PATTERN = r'<script type="text/javascript">location.href=\'/chyba\';</script>' + +    def process(self, pyfile): +        self.html = self.load(pyfile.url, decode = True) +        self.getFileInfo() +         +        # parse js variables +        self.jsvars = dict((x, y.strip("'")) for x,y in re.findall(r"var (\w+) = ([0-9.]+|'[^']*')", self.html)) +        self.logDebug(self.jsvars)         +        pyfile.name = self.jsvars['ID3'] +         +        # determine download type - free or premium +        if self.premium: +            if 'UU_prihlasen' in self.jsvars: +                if self.jsvars['UU_prihlasen'] == '0': +                    self.logWarning('User not logged in') +                    self.relogin(self.user) +                    self.retry() +                elif float(self.jsvars['UU_kredit']) < float(self.jsvars['kredit_odecet']): +                    self.logWarning('Not enough credit left') +                    self.premium = False +                 +        if self.premium: +            self.handlePremium() +        else: +            self.handleFree() +             +        check = self.checkDownload({"err": re.compile(r"\AChyba!")}, max_size=100) +        if check == "err": +            self.fail("File not found or plugin defect") +                    +    def handleFree(self):                +        # get download url +        download_url = '%s/download.php' % self.jsvars['server'] +        data = dict((x, self.jsvars[x]) for x in self.jsvars if x in ('ID1', 'ID2', 'ID3', 'ID4')) +        self.logDebug("FREE URL1:" + download_url, data) +                +        self.req.http.c.setopt(FOLLOWLOCATION, 0)         +        self.load(download_url, post=data) +        self.header = self.req.http.header         +        self.req.http.c.setopt(FOLLOWLOCATION, 1) +         +        found = re.search("Location\s*:\s*(.*)", self.header, re.I) +        if not found: self.fail('File not found') +        download_url = found.group(1)                         +        self.logDebug("FREE URL2:" + download_url) +         +        # check errors +        found = re.search(r'/chyba/(\d+)', download_url) +        if found: +            if found.group(1) == '1': +                self.retry(max_tries=60, wait_time=120, reason="This IP is already downloading") +            elif found.group(1) == '2': +                self.retry(max_tries=60, wait_time=60, reason="No free slots available") +            else: +                self.fail('Error %d' % found.group(1)) + +        # download file +        self.download(download_url)    +     +    def handlePremium(self): +        download_url = '%s/download_premium.php' % self.jsvars['server'] +        data = dict((x, self.jsvars[x]) for x in self.jsvars if x in ('ID1', 'ID2', 'ID4', 'ID5')) +        self.logDebug("PREMIUM URL:" + download_url, data) +        self.download(download_url, get=data) + +getInfo = create_getInfo(QuickshareCz) diff --git a/pyload/plugins/hoster/RapidgatorNet.py b/pyload/plugins/hoster/RapidgatorNet.py new file mode 100644 index 000000000..3c4611446 --- /dev/null +++ b/pyload/plugins/hoster/RapidgatorNet.py @@ -0,0 +1,196 @@ +# -*- 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 module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo +from module.plugins.internal.CaptchaService import ReCaptcha, SolveMedia, AdsCaptcha +from module.common.json_layer import json_loads +from module.network.HTTPRequest import BadHeader + + +class RapidgatorNet(SimpleHoster): +    __name__ = "RapidgatorNet" +    __type__ = "hoster" +    __pattern__ = r"http://(?:www\.)?(rapidgator.net)/file/(\w+)" +    __version__ = "0.18" +    __description__ = """rapidgator.net""" +    __author_name__ = ("zoidberg", "chrox", "stickell") + +    API_URL = 'http://rapidgator.net/api/file' + +    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"return '(http[^']+)';\s*}\s*}\s*}?\);" +    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 setup(self): +        self.resumeDownload = False +        self.multiDL = False +        self.sid = None +        self.chunkLimit = 1 +        self.req.setOption("timeout", 120) + +    def process(self, pyfile): +        if self.account: +            self.sid = self.account.getAccountData(self.user).get('SID', None) + +        if self.sid: +            self.handlePremium() +        else: +            self.handleFree() + +    def getAPIResponse(self, cmd): +        try: +            json = self.load('%s/%s' % (self.API_URL, cmd), +                             get={'sid': self.sid, +                                  'url': self.pyfile.url}, decode=True) +            self.logDebug('API:%s' % cmd, json, "SID: %s" % self.sid) +            json = json_loads(json) +            status = json['response_status'] +            msg = json['response_details'] +        except BadHeader, e: +            self.logError('API:%s' % cmd, e, "SID: %s" % self.sid) +            status = e.code +            msg = e + +        if status == 200: +            return json['response'] +        elif status == 423: +            self.account.empty(self.user) +            self.retry() +        else: +            self.account.relogin(self.user) +            self.retry(wait_time=60) + +    def handlePremium(self): +        #self.logDebug("ACCOUNT_DATA", self.account.getAccountData(self.user)) +        self.api_data = self.getAPIResponse('info') +        self.api_data['md5'] = self.api_data['hash'] +        self.pyfile.name = self.api_data['filename'] +        self.pyfile.size = self.api_data['size'] +        url = self.getAPIResponse('download')['url'] +        self.multiDL = True +        self.download(url) + +    def handleFree(self): +        self.html = self.load(self.pyfile.url, decode=True) +        self.getFileInfo() + +        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") + +        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/pyload/plugins/hoster/RapidshareCom.py b/pyload/plugins/hoster/RapidshareCom.py new file mode 100644 index 000000000..150dd425d --- /dev/null +++ b/pyload/plugins/hoster/RapidshareCom.py @@ -0,0 +1,225 @@ + +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# v1.36 +# * fixed call checkfiles subroutine +# v1.35 +# * fixed rs-urls in handleFree(..) and freeWait(..) +# * removed getInfo(..) function as it was not used anywhere (in this file) +# * removed some (old?) comment blocks + +import re + +from module.network.RequestFactory import getURL +from module.plugins.Hoster import Hoster + +def getInfo(urls): +    ids = "" +    names = "" + +    p = re.compile(RapidshareCom.__pattern__) + +    for url in urls: +        r = p.search(url) +        if r.group("name"): +            ids+= ","+r.group("id") +            names+= ","+r.group("name") +        elif r.group("name_new"): +            ids+= ","+r.group("id_new") +            names+= ","+r.group("name_new") +     +    url = "http://api.rapidshare.com/cgi-bin/rsapi.cgi?sub=checkfiles&files=%s&filenames=%s" % (ids[1:], names[1:]) +     +    api = getURL(url) +    result = [] +    i = 0 +    for res in api.split(): +        tmp = res.split(",") +        if tmp[4] in ("0", "4", "5"): status = 1 +        elif tmp[4] == "1": status = 2 +        else: status = 3 +         +        result.append( (tmp[1], tmp[2], status, urls[i]) ) +        i += 1 +         +    yield result + + +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.39" +    __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") +    __author_mail__ = ("spoob@pyload.org", "ranan@pyload.org", "mkaay@mkaay.de") + +    def setup(self): +        self.html = None +        self.no_download = True +        self.api_data = None +        self.offset = 0 +        self.dl_dict = {} + +        self.id = None +        self.name = None +           +        self.chunkLimit = -1 if self.premium else 1             +        self.multiDL = self.resumeDownload = self.premium + +    def process(self, pyfile): +        self.url = self.pyfile.url         +        self.prepare() +          +    def prepare(self): +        m = re.search(self.__pattern__, self.url) + +        if m.group("name"): +            self.id = m.group("id") +            self.name = m.group("name") +        else: +            self.id = m.group("id_new") +            self.name = m.group("name_new") + +        self.download_api_data() +        if self.api_data["status"] == "1": +            self.pyfile.name = self.get_file_name() + +            if self.premium: +                self.handlePremium() +            else: +                self.handleFree() + +        elif self.api_data["status"] == "2": +            self.logInfo(_("Rapidshare: Traffic Share (direct download)")) +            self.pyfile.name = self.get_file_name() + +            self.download(self.pyfile.url, get={"directstart":1}) +         +        elif self.api_data["status"] in ("0","4","5"): +            self.offline() +        elif self.api_data["status"] == "3": +            self.tempOffline() +        else: +            self.fail("Unknown response code.") + +    def handleFree(self): + +        while self.no_download: +            self.dl_dict = self.freeWait() + +        #tmp = "#!download|%(server)s|%(id)s|%(name)s|%(size)s" +        download = "http://%(host)s/cgi-bin/rsapi.cgi?sub=download&editparentlocation=0&bin=1&fileid=%(id)s&filename=%(name)s&dlauth=%(auth)s" % self.dl_dict + +        self.logDebug("RS API Request: %s" % download) +        self.download(download, ref=False) + +        check = self.checkDownload({"ip" : "You need RapidPro to download more files from your IP address", +                                    "auth" : "Download auth invalid"}) +        if check == "ip": +            self.setWait(60) +            self.logInfo(_("Already downloading from this ip address, waiting 60 seconds")) +            self.wait() +            self.handleFree() +        elif check == "auth": +            self.logInfo(_("Invalid Auth Code, download will be restarted")) +            self.offset += 5 +            self.handleFree() + +    def handlePremium(self): +        info = self.account.getAccountInfo(self.user, True) +        self.logDebug("%s: Use Premium Account" % self.__name__) +        url = self.api_data["mirror"] +        self.download(url, get={"directstart":1}) + + +    def download_api_data(self, force=False): +        """ +        http://images.rapidshare.com/apidoc.txt +        """ +        if self.api_data and not force: +            return +        api_url_base = "http://api.rapidshare.com/cgi-bin/rsapi.cgi" +        api_param_file = {"sub": "checkfiles", "incmd5": "1", "files": self.id, "filenames": self.name} +        src = self.load(api_url_base, cookies=False, get=api_param_file).strip() +        self.logDebug("RS INFO API: %s" % src) +        if src.startswith("ERROR"): +            return +        fields = src.split(",") +        """ +        status codes: +            0=File not found +            1=File OK (Anonymous downloading) +            3=Server down +            4=File marked as illegal +            5=Anonymous file locked, because it has more than 10 downloads already +            50+n=File OK (TrafficShare direct download type "n" without any logging.) +            100+n=File OK (TrafficShare direct download type "n" with logging. Read our privacy policy to see what is logged.) +        """ +        self.api_data = {"fileid": fields[0], "filename": fields[1], "size": int(fields[2]), "serverid": fields[3], +                         "status": fields[4], "shorthost": fields[5], "checksum": fields[6].strip().lower()} + +        if int(self.api_data["status"]) > 100: +            self.api_data["status"] = str(int(self.api_data["status"]) - 100) +        elif int(self.api_data["status"]) > 50: +            self.api_data["status"] = str(int(self.api_data["status"]) - 50) + +        self.api_data["mirror"] = "http://rs%(serverid)s%(shorthost)s.rapidshare.com/files/%(fileid)s/%(filename)s" % self.api_data + +    def freeWait(self): +        """downloads html with the important information +        """ +        self.no_download = True + +        id = self.id +        name = self.name + +        prepare = "https://api.rapidshare.com/cgi-bin/rsapi.cgi?sub=download&fileid=%(id)s&filename=%(name)s&try=1&cbf=RSAPIDispatcher&cbid=1" % {"name": name, "id" : id} + +        self.logDebug("RS API Request: %s" % prepare) +        result = self.load(prepare, ref=False) +        self.logDebug("RS API Result: %s" % result) + +        between_wait = re.search("You need to wait (\d+) seconds", result) + +        if "You need RapidPro to download more files from your IP address" in result: +            self.setWait(60) +            self.logInfo(_("Already downloading from this ip address, waiting 60 seconds")) +            self.wait() +        elif "Too many users downloading from this server right now" in result or "All free download slots are full" in result: +            self.setWait(120) +            self.logInfo(_("RapidShareCom: No free slots")) +            self.wait() +        elif "This file is too big to download it for free" in result: +            self.fail(_("You need a premium account for this file")) +        elif "Filename invalid." in result: +            self.fail(_("Filename reported invalid")) +        elif between_wait: +            self.setWait(int(between_wait.group(1))) +            self.wantReconnect = True +            self.wait() +        else: +            self.no_download = False + +            tmp, info = result.split(":") +            data = info.split(",") + +            dl_dict = {"id": id, +                        "name": name, +                        "host": data[0], +                        "auth": data[1], +                        "server": self.api_data["serverid"], +                        "size": self.api_data["size"] +            } +            self.setWait(int(data[2])+2+self.offset) +            self.wait() + +            return dl_dict + + +    def get_file_name(self): +        if self.api_data["filename"]: +            return self.api_data["filename"] +        return self.url.split("/")[-1]
\ No newline at end of file diff --git a/pyload/plugins/hoster/RarefileNet.py b/pyload/plugins/hoster/RarefileNet.py new file mode 100644 index 000000000..a0f5930b5 --- /dev/null +++ b/pyload/plugins/hoster/RarefileNet.py @@ -0,0 +1,34 @@ +# -*- 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.03" +    __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>.+?) ' +    DIRECT_LINK_PATTERN = r'<a href="(?P<link>[^"]+)">(?P=link)</a>' +    HOSTER_NAME = "rarefile.net" + +    def setup(self): +        self.resumeDownload = self.multiDL = self.premium + +    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) diff --git a/pyload/plugins/hoster/RealdebridCom.py b/pyload/plugins/hoster/RealdebridCom.py new file mode 100644 index 000000000..73baff5b3 --- /dev/null +++ b/pyload/plugins/hoster/RealdebridCom.py @@ -0,0 +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 parseFileSize, remove_chars +from module.common.json_layer import json_loads +from module.plugins.Hoster import Hoster + +class RealdebridCom(Hoster): +    __name__ = "RealdebridCom" +    __version__ = "0.51" +    __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 %s account or deactivate this plugin") % "Real-debrid") +            self.fail("No Real-debrid account provided") + +        self.logDebug("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.logDebug("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/pyload/plugins/hoster/RedtubeCom.py b/pyload/plugins/hoster/RedtubeCom.py new file mode 100644 index 000000000..c2083e679 --- /dev/null +++ b/pyload/plugins/hoster/RedtubeCom.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import re +from module.plugins.Hoster import Hoster +from module.unescape import unescape + +class RedtubeCom(Hoster): +    __name__ = "RedtubeCom" +    __type__ = "hoster" +    __pattern__ = r'http://[\w\.]*?redtube\.com/\d+' +    __version__ = "0.2" +    __description__ = """Redtube.com Download Hoster""" +    __author_name__ = ("jeix") +    __author_mail__ = ("jeix@hasnomail.de") +         +    def process(self, pyfile): +        self.download_html() +        if not self.file_exists(): +            self.offline() +             +        pyfile.name = self.get_file_name() +        self.download(self.get_file_url()) +         +    def download_html(self): +        url = self.pyfile.url +        self.html = self.load(url) + +    def get_file_url(self): +        """ returns the absolute downloadable filepath +        """ +        if self.html is None: +            self.download_html() + +        file_url = unescape(re.search(r'hashlink=(http.*?)"', self.html).group(1)) + +        return file_url +     +    def get_file_name(self): +        if self.html is None: +            self.download_html() +             +        name = re.search('<title>(.*?)- RedTube - Free Porn Videos</title>', self.html).group(1).strip() + ".flv"         +        return name + +    def file_exists(self): +        """ returns True or False +        """ +        if self.html is None: +            self.download_html() +         +        if re.search(r'This video has been removed.', self.html) is not None: +            return False +        else: +            return True +             diff --git a/pyload/plugins/hoster/RehostTo.py b/pyload/plugins/hoster/RehostTo.py new file mode 100644 index 000000000..7d1b1c3ea --- /dev/null +++ b/pyload/plugins/hoster/RehostTo.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +from urllib import quote, unquote +from module.plugins.Hoster import Hoster + +class RehostTo(Hoster): +    __name__ = "RehostTo" +    __version__ = "0.13" +    __type__ = "hoster" +    __pattern__ = r"https?://.*rehost.to\..*" +    __description__ = """rehost.com hoster plugin""" +    __author_name__ = ("RaNaN") +    __author_mail__ = ("RaNaN@pyload.org") + +    def getFilename(self, url): +        return unquote(url.rsplit("/", 1)[1]) + +    def setup(self): +        self.chunkLimit = 1 +        self.resumeDownload = True + +    def process(self, pyfile): +        if not self.account: +            self.logError(_("Please enter your %s account or deactivate this plugin") % "rehost.to") +            self.fail("No rehost.to account provided") + +        data = self.account.getAccountInfo(self.user) +        long_ses = data["long_ses"] + +        self.logDebug("Rehost.to: Old URL: %s" % pyfile.url) +        new_url = "http://rehost.to/process_download.php?user=cookie&pass=%s&dl=%s" % (long_ses, quote(pyfile.url, "")) + +        #raise timeout to 2min +        self.req.setOption("timeout", 120) + +        self.download(new_url, disposition=True)
\ No newline at end of file diff --git a/pyload/plugins/hoster/ReloadCc.py b/pyload/plugins/hoster/ReloadCc.py new file mode 100644 index 000000000..b39c2812c --- /dev/null +++ b/pyload/plugins/hoster/ReloadCc.py @@ -0,0 +1,103 @@ +from module.plugins.Hoster    import Hoster + +from module.common.json_layer import json_loads + +from module.network.HTTPRequest import BadHeader + +class ReloadCc(Hoster): +    __name__ = "ReloadCc" +    __version__ = "0.5" +    __type__ = "hoster" +    __description__ = """Reload.Cc 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 ReloadCc hook. +    __pattern__ = None + +    __author_name__ = ("Reload Team") +    __author_mail__ = ("hello@reload.cc") + +    def process(self, pyfile): +        # Check account +        if not self.account or not self.account.canUse(): +            self.logError(_("Please enter your %s account or deactivate this plugin") % "reload.cc") +            self.fail("No valid reload.cc 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() + +        query_params = dict( +            via='pyload', +            v=1, +            user=user, +            uri=self.pyfile.url +        ) + +        try: +            query_params.update(dict(hash=self.account.infos[user]['pwdhash'])) +        except Exception: +            query_params.update(dict(pwd=data['password'])) + +        try: +            answer = self.load("http://api.reload.cc/dl", get=query_params) +        except BadHeader, e: +            if e.code == 400: +                self.fail("The URI is not supported by Reload.cc.") +            elif e.code == 401: +                self.fail("Wrong username or password") +            elif e.code == 402: +                self.fail("Your account is inactive. A payment is required for downloading!") +            elif e.code == 403: +                self.fail("Your account is disabled. Please contact the Reload.cc support!") +            elif e.code == 409: +                self.logWarning("The hoster seems to be a limited hoster and you've used your daily traffic for this hoster: %s" % self.pyfile.url) +                # Wait for 6 hours and retry up to 4 times => one day +                self.retry(max_retries=4, wait_time=(3600 * 6), reason="Limited hoster traffic limit exceeded") +            elif e.code == 429: +                self.retry(max_retries=5, wait_time=120, reason="Too many concurrent connections") # Too many connections, wait 2 minutes and try again +            elif e.code == 503: +                self.retry(wait_time=600, reason="Reload.cc is currently in maintenance mode! Please check again later.") # Retry in 10 minutes +            else: +                self.fail("Internal error within Reload.cc. Please contact the Reload.cc support for further information.") +            return + +        data = json_loads(answer) + +        # Check status and decide what to do +        status = data.get('status', None) +        if status == "ok": +            conn_limit = data.get('msg', 0) +            # API says these connections are limited +            # Make sure this limit is used - the download will fail if not +            if conn_limit > 0: +                try: +                    self.limitDL = int(conn_limit) +                except ValueError: +                    self.limitDL = 1 +            else: +                self.limitDL = 0 + +            try: +                self.download(data['link'], disposition=True) +            except BadHeader, e: +                if e.code == 404: +                    self.fail("File Not Found") +                elif e.code == 412: +                    self.fail("File access password is wrong") +                elif e.code == 417: +                    self.fail("Password required for file access") +                elif e.code == 429: +                    self.retry(max_retries=5, wait_time=120, reason="Too many concurrent connections") # Too many connections, wait 2 minutes and try again +                else: +                    self.fail("Internal error within Reload.cc. Please contact the Reload.cc support for further information.") +                return +        else: +            self.fail("Internal error within Reload.cc. Please contact the Reload.cc support for further information.") diff --git a/pyload/plugins/hoster/RyushareCom.py b/pyload/plugins/hoster/RyushareCom.py new file mode 100644 index 000000000..7bfe4e8fe --- /dev/null +++ b/pyload/plugins/hoster/RyushareCom.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +from module.plugins.hoster.XFileSharingPro import XFileSharingPro, create_getInfo +import re + + +class RyushareCom(XFileSharingPro): +    __name__ = "RyushareCom" +    __type__ = "hoster" +    __pattern__ = r"http://(?:\w*\.)*?ryushare.com/\w{11,}" +    __version__ = "0.11" +    __description__ = """ryushare.com hoster plugin""" +    __author_name__ = ("zoidberg", "stickell") +    __author_mail__ = ("zoidberg@mujmail.cz", "l.stickell@yahoo.it") + +    HOSTER_NAME = "ryushare.com" + +    WAIT_PATTERN = r'(?:You have to|Please) wait (?:(?P<min>\d+) minutes, )?(?:<span id="[^"]+">)?(?P<sec>\d+)(?:</span>)? seconds' +    DIRECT_LINK_PATTERN = r'<a href="([^"]+)">Click here to download</a>' + +    def setup(self): +        self.resumeDownload = self.multiDL = True +        if not self.premium: +            self.limitDL = 2 +        # Up to 3 chunks allowed in free downloads. Unknown for premium +        self.chunkLimit = 3 + +    def getDownloadLink(self): +        self.html = self.load(self.pyfile.url) +        action, inputs = self.parseHtmlForm(input_names={"op": re.compile("^download")}) +        if inputs.has_key('method_premium'): +            del inputs['method_premium'] + +        self.html = self.load(self.pyfile.url, post = inputs) +        action, inputs = self.parseHtmlForm('F1') + +        for i in xrange(10): +            self.logInfo('Attempt to detect direct link #%d' % i) + +            # Wait +            if 'You have reached the download-limit!!!' in self.html: +                self.setWait(3600, True) +            else: +                m = re.search(self.WAIT_PATTERN, self.html).groupdict('0') +                waittime = int(m['min']) * 60 + int(m['sec']) +                self.setWait(waittime) +            self.wait() + +            self.html = self.load(self.pyfile.url, post = inputs) +            if 'Click here to download' in self.html: +                m = re.search(self.DIRECT_LINK_PATTERN, self.html) +                return m.group(1) + +        self.parseError('No direct link within 10 retries') + +getInfo = create_getInfo(RyushareCom) diff --git a/pyload/plugins/hoster/SecureUploadEu.py b/pyload/plugins/hoster/SecureUploadEu.py new file mode 100644 index 000000000..b9a900d96 --- /dev/null +++ b/pyload/plugins/hoster/SecureUploadEu.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +from module.plugins.hoster.XFileSharingPro import XFileSharingPro, create_getInfo + + +class SecureUploadEu(XFileSharingPro): +    __name__ = "SecureUploadEu" +    __type__ = "hoster" +    __pattern__ = r"http://(www\.)?secureupload\.eu/(\w){12}(/\w+)" +    __version__ = "0.01" +    __description__ = """SecureUpload.eu hoster plugin""" +    __author_name__ = ("z00nx") +    __author_mail__ = ("z00nx0@gmail.com") + +    HOSTER_NAME = "secureupload.eu" +    FILE_INFO_PATTERN = '<h3>Downloading (?P<N>[^<]+) \((?P<S>[^<]+)\)</h3>' +    FILE_OFFLINE_PATTERN = 'The file was removed|File Not Found' + +getInfo = create_getInfo(SecureUploadEu) diff --git a/pyload/plugins/hoster/SendmywayCom.py b/pyload/plugins/hoster/SendmywayCom.py new file mode 100644 index 000000000..fcbac850a --- /dev/null +++ b/pyload/plugins/hoster/SendmywayCom.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +from module.plugins.hoster.XFileSharingPro import XFileSharingPro, create_getInfo + + +class SendmywayCom(XFileSharingPro): +    __name__ = "SendmywayCom" +    __type__ = "hoster" +    __pattern__ = r"http://(?:\w*\.)*?sendmyway.com/\w{12}" +    __version__ = "0.01" +    __description__ = """SendMyWay hoster plugin""" +    __author_name__ = ("zoidberg") +    __author_mail__ = ("zoidberg@mujmail.cz") + +    FILE_NAME_PATTERN = r'<p class="file-name" ><.*?>\s*(?P<N>.+)' +    FILE_SIZE_PATTERN = r'<small>\((?P<S>\d+) bytes\)</small>' +    HOSTER_NAME = "sendmyway.com" + +getInfo = create_getInfo(SendmywayCom) diff --git a/pyload/plugins/hoster/SendspaceCom.py b/pyload/plugins/hoster/SendspaceCom.py new file mode 100644 index 000000000..22abaff56 --- /dev/null +++ b/pyload/plugins/hoster/SendspaceCom.py @@ -0,0 +1,67 @@ +# -*- 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 SendspaceCom(SimpleHoster): +    __name__ = "SendspaceCom" +    __type__ = "hoster" +    __pattern__ = r"http://(www\.)?sendspace.com/file/.*" +    __version__ = "0.13" +    __description__ = """sendspace.com plugin - free only""" +    __author_name__ = ("zoidberg") + +    DOWNLOAD_URL_PATTERN = r'<a id="download_button" href="([^"]+)"' +    FILE_NAME_PATTERN = r'<h2 class="bgray">\s*<(?:b|strong)>(?P<N>[^<]+)</' +    FILE_SIZE_PATTERN = r'<div class="file_description reverse margin_center">\s*<b>File Size:</b>\s*(?P<S>[0-9.]+)(?P<U>[kKMG])i?B\s*</div>' +    FILE_OFFLINE_PATTERN = r'<div class="msg error" style="cursor: default">Sorry, the file you requested is not available.</div>' +    CAPTCHA_PATTERN = r'<td><img src="(/captchas/captcha.php?captcha=([^"]+))"></td>' +    USER_CAPTCHA_PATTERN = r'<td><img src="/captchas/captcha.php?user=([^"]+))"></td>' +         +    def handleFree(self): +        params = {} +        for i in range(3): +            found = re.search(self.DOWNLOAD_URL_PATTERN, self.html) +            if found: +                if params.has_key('captcha_hash'): self.correctCaptcha() +                download_url = found.group(1) +                break + +            found = re.search(self.CAPTCHA_PATTERN, self.html) +            if found: +                if params.has_key('captcha_hash'): self.invalidCaptcha() +                captcha_url1 = "http://www.sendspace.com/" + found.group(1) +                found = re.search(self.USER_CAPTCHA_PATTERN, self.html) +                captcha_url2 = "http://www.sendspace.com/" + found.group(1) +                params = {'captcha_hash' : found.group(2), +                          'captcha_submit': 'Verify', +                          'captcha_answer': self.decryptCaptcha(captcha_url1) + " " + self.decryptCaptcha(captcha_url2) +                         } +            else: +                params = {'download': "Regular Download"} + +            self.logDebug(params) +            self.html = self.load(self.pyfile.url, post = params) +        else: +            self.fail("Download link not found") + +        self.logDebug("Download URL: %s" % download_url) +        self.download(download_url) + +create_getInfo(SendspaceCom)
\ No newline at end of file diff --git a/pyload/plugins/hoster/Share4webCom.py b/pyload/plugins/hoster/Share4webCom.py new file mode 100644 index 000000000..ef9c2acf8 --- /dev/null +++ b/pyload/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/pyload/plugins/hoster/Share76Com.py b/pyload/plugins/hoster/Share76Com.py new file mode 100644 index 000000000..db850cb73 --- /dev/null +++ b/pyload/plugins/hoster/Share76Com.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +from module.plugins.hoster.XFileSharingPro import XFileSharingPro, create_getInfo + +class Share76Com(XFileSharingPro): +    __name__ = "Share76Com" +    __type__ = "hoster" +    __pattern__ = r"http://(?:\w*\.)*?share76.com/\w{12}" +    __version__ = "0.03" +    __description__ = """share76.com hoster plugin""" +    __author_name__ = ("me") + +    FILE_INFO_PATTERN = r'<h2>\s*File:\s*<font[^>]*>(?P<N>[^>]+)</font>\s*\[<font[^>]*>(?P<S>[0-9.]+) (?P<U>[kKMG])i?B</font>\]</h2>' +    HOSTER_NAME = "share76.com" + +    def setup(self): +        self.resumeDownload = self.multiDL = self.premium +        self.chunkLimit = 1 + +getInfo = create_getInfo(Share76Com) diff --git a/pyload/plugins/hoster/ShareFilesCo.py b/pyload/plugins/hoster/ShareFilesCo.py new file mode 100644 index 000000000..ee44b0a1f --- /dev/null +++ b/pyload/plugins/hoster/ShareFilesCo.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +from module.plugins.hoster.XFileSharingPro import XFileSharingPro, create_getInfo +import re + +class ShareFilesCo(XFileSharingPro): +    __name__ = "ShareFilesCo" +    __type__ = "hoster" +    __pattern__ = r"http://(www\.)?sharefiles\.co/\w{12}" +    __version__ = "0.01" +    __description__ = """Sharefiles.co hoster plugin""" +    __author_name__ = ("stickell") +    __author_mail__ = ("l.stickell@yahoo.it") + +    HOSTER_NAME = "sharefiles.co" + +    def startDownload(self, link): +        link = link.strip() +        if link.startswith('http://adf.ly'): +            link = re.sub('http://adf.ly/\d+/', '', link) +        if self.captcha: self.correctCaptcha() +        self.logDebug('DIRECT LINK: %s' % link) +        self.download(link) + +getInfo = create_getInfo(ShareFilesCo) diff --git a/pyload/plugins/hoster/ShareRapidCom.py b/pyload/plugins/hoster/ShareRapidCom.py new file mode 100644 index 000000000..5a08fed1f --- /dev/null +++ b/pyload/plugins/hoster/ShareRapidCom.py @@ -0,0 +1,104 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import re +from pycurl import HTTPHEADER +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):     +    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): +    for url in urls: +        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/(\w+)" +    __version__ = "0.52" +    __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_URL_REPLACEMENTS = [(__pattern__, r'http://share-rapid.com/stahuj/\1')] + +    def setup(self): +        self.chunkLimit = 1 +        self.resumeDownload = True + +    def process(self, pyfile): +        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)) + +        found = re.search(self.DOWNLOAD_URL_PATTERN, self.html) +        if found is not None: +            link = found.group(1)             +            self.logDebug("Premium link: %s" % link) +             +            self.check_data = {"size": pyfile.size} +            self.download(link) +        else: +            if re.search(self.ERR_LOGIN_PATTERN, self.html): +                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")            diff --git a/pyload/plugins/hoster/SharebeesCom.py b/pyload/plugins/hoster/SharebeesCom.py new file mode 100644 index 000000000..f5bacc5b0 --- /dev/null +++ b/pyload/plugins/hoster/SharebeesCom.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +from module.plugins.hoster.XFileSharingPro import XFileSharingPro, create_getInfo + + +class SharebeesCom(XFileSharingPro): +    __name__ = "SharebeesCom" +    __type__ = "hoster" +    __pattern__ = r"http://(?:\w*\.)*?sharebees.com/\w{12}" +    __version__ = "0.01" +    __description__ = """ShareBees hoster plugin""" +    __author_name__ = ("zoidberg") +    __author_mail__ = ("zoidberg@mujmail.cz") + +    FILE_NAME_PATTERN = r'<p class="file-name" ><.*?>\s*(?P<N>.+)' +    FILE_SIZE_PATTERN = r'<small>\((?P<S>\d+) bytes\)</small>' +    FORM_PATTERN = 'F1' +    HOSTER_NAME = "sharebees.com" + +getInfo = create_getInfo(SharebeesCom) diff --git a/pyload/plugins/hoster/ShareonlineBiz.py b/pyload/plugins/hoster/ShareonlineBiz.py new file mode 100644 index 000000000..8a4bcfba8 --- /dev/null +++ b/pyload/plugins/hoster/ShareonlineBiz.py @@ -0,0 +1,203 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import re +from base64 import b64decode +import hashlib +import random +from time import time, sleep + +from module.plugins.Hoster import Hoster +from module.network.RequestFactory import getURL +from module.plugins.Plugin import chunks +from module.plugins.internal.CaptchaService import ReCaptcha as _ReCaptcha +     +def getInfo(urls): +    api_url_base = "http://api.share-online.biz/linkcheck.php" +     +    for chunk in chunks(urls, 90): +        api_param_file = {"links": "\n".join(x.replace("http://www.share-online.biz/dl/","").rstrip("/") for x in chunk)} #api only supports old style links +        src = getURL(api_url_base, post=api_param_file, decode=True) +        result = [] +        for i, res in enumerate(src.split("\n")): +            if not res: +                continue +            fields = res.split(";") +             +            if fields[1] == "OK": +                status = 2 +            elif fields[1] in ("DELETED", "NOT FOUND"): +                status = 1 +            else: +                status = 3 +                 +            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.36" +    __description__ = """Shareonline.biz Download Hoster""" +    __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? +        #  api supports resume, only one chunk +        #  website isn't supporting resuming in first place +        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.resumeDownload = self.premium +        self.multiDL = False +        #self.chunkLimit = 1 +         +        self.check_data = None + +    def process(self, pyfile):        +        if self.premium: +            self.handleAPIPremium() +            #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" +        api_param_file = {"links": self.pyfile.url.replace("http://www.share-online.biz/dl/","")} #api only supports old style links +        src = self.load(api_url_base, cookies=False, post=api_param_file, decode=True) +         +        fields = src.split(";") +        self.api_data = {"fileid": fields[0], +                         "status": fields[1]} +        if not self.api_data["status"] == "OK": +            self.offline() +        self.api_data["filename"] = fields[2] +        self.api_data["size"] = fields[3] # in bytes +        self.api_data["md5"] = fields[4].strip().lower().replace("\n\n", "") # md5 + +    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, 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() +             +        found = re.search(r'var wait=(\d+);', self.html)                     +                 +        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 not response == '0': +                break + +        else: self.fail("No valid captcha solution received") +         +        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 download +        check = self.checkDownload({ +            "cookie": re.compile(r'<div id="dl_failure"'), +            "fail": re.compile(r"<title>Share-Online") +            }) +        if check == "cookie": +            self.retry(5, 60, "Cookie failure") +        elif check == "fail": +            self.retry(5, 300, "Download failed") +     +    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": self.user, "password": self.account.accounts[self.user]["password"], "act": "download", "lid": self.file_id}) + +        self.api_data = dlinfo = {} +        for line in src.splitlines(): +            key, value = line.split(": ") +            dlinfo[key.lower()] = value +         +        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 == "server_under_maintenance": +            self.tempoffline() +        else: +            self.multiDL = True +            self.download(dlLink) +     +    def checksum(self, local_file): +        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["md5"]: +                return True, 0 +            else: +                return False, 1 +        else: +            self.logWarning("MD5 checksum missing") +            return True, 5 diff --git a/pyload/plugins/hoster/ShareplaceCom.py b/pyload/plugins/hoster/ShareplaceCom.py new file mode 100644 index 000000000..c55f6703a --- /dev/null +++ b/pyload/plugins/hoster/ShareplaceCom.py @@ -0,0 +1,84 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import re +import urllib +from module.plugins.Hoster import Hoster + +class ShareplaceCom(Hoster): +    __name__ = "ShareplaceCom" +    __type__ = "hoster" +    __pattern__ = r"(http://)?(www\.)?shareplace\.(com|org)/\?[a-zA-Z0-9]+" +    __version__ = "0.11" +    __description__ = """Shareplace.com Download Hoster""" +    __author_name__ = ("ACCakut, based on YourfilesTo by jeix and skydancer") +    __author_mail__ = ("none") + +    def setup(self): +        self.html = None +        self.multiDL = True + +    def process(self,pyfile): +        self.pyfile = pyfile +        self.prepare() +        self.download(self.get_file_url()) +     +    def prepare(self): +        if not self.file_exists(): +            self.offline() + +        self.pyfile.name = self.get_file_name() +         +        wait_time = self.get_waiting_time() +        self.setWait(wait_time) +        self.logDebug("%s: Waiting %d seconds." % (self.__name__,wait_time)) +        self.wait() + +    def get_waiting_time(self): +        if self.html is None: +            self.download_html() +             +        #var zzipitime = 15; +        m = re.search(r'var zzipitime = (\d+);', self.html) +        if m: +            sec = int(m.group(1)) +        else: +            sec = 0 +             +        return sec +         +    def download_html(self): +        url = re.sub("shareplace.com\/\?", "shareplace.com//index1.php/?a=", self.pyfile.url) +        self.html = self.load(url, decode=True) + +    def get_file_url(self): +        """ returns the absolute downloadable filepath +        """ +        url = re.search(r"var beer = '(.*?)';", self.html) +        if url: +            url = url.group(1) +            url = urllib.unquote(url.replace("http://http:/", "").replace("vvvvvvvvv", "").replace("lllllllll", "").replace("teletubbies", "")) +            self.logDebug("URL: %s" % url) +            return url +        else: +            self.fail("absolute filepath could not be found. offline? ") +        +    def get_file_name(self): +        if self.html is None: +            self.download_html() + +        return re.search("<title>\s*(.*?)\s*</title>", self.html).group(1) + +    def file_exists(self): +        """ returns True or False +        """ +        if self.html is None: +            self.download_html() +             +        if re.search(r"HTTP Status 404", self.html) is not None: +            return False +        else: +            return True + +         + diff --git a/pyload/plugins/hoster/ShragleCom.py b/pyload/plugins/hoster/ShragleCom.py new file mode 100644 index 000000000..f21ad213d --- /dev/null +++ b/pyload/plugins/hoster/ShragleCom.py @@ -0,0 +1,106 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import re +from pycurl import FOLLOWLOCATION + +from module.plugins.Hoster import Hoster +from module.plugins.internal.SimpleHoster import parseHtmlForm +from module.plugins.internal.CaptchaService 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(ShragleCom, url) +        yield file_info         + +class ShragleCom(Hoster): +    __name__ = "ShragleCom" +    __type__ = "hoster" +    __pattern__ = r"http://(?:www.)?(cloudnator|shragle).com/files/(?P<ID>.*?)/" +    __version__ = "0.21" +    __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): +        #get file status and info +        self.pyfile.name, self.pyfile.size, status = parseFileInfo(self, pyfile.url)[:3] +        if status != 2:      +            self.offline() +         +        self.handleFree() +         +    def handleFree(self): +        self.html = self.load(self.pyfile.url) +         +        #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: +            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() +             +             diff --git a/pyload/plugins/hoster/SpeedLoadOrg.py b/pyload/plugins/hoster/SpeedLoadOrg.py new file mode 100644 index 000000000..32e7baf13 --- /dev/null +++ b/pyload/plugins/hoster/SpeedLoadOrg.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +from module.plugins.hoster.XFileSharingPro import XFileSharingPro, create_getInfo + +class SpeedLoadOrg(XFileSharingPro): +    __name__ = "SpeedLoadOrg" +    __type__ = "hoster" +    __pattern__ = r"http://(www\.)?speedload\.org/(?P<ID>\w+)" +    __version__ = "1.01" +    __description__ = """Speedload.org hoster plugin""" +    __author_name__ = ("stickell") +    __author_mail__ = ("l.stickell@yahoo.it") + +    FILE_NAME_PATTERN = r'Filename:</b></td><td nowrap>(?P<N>[^<]+)</td></tr>' +    FILE_SIZE_PATTERN = r'Size:</b></td><td>[\w. ]+<small>\((?P<S>\d+) bytes\)</small>' + +    HOSTER_NAME = "speedload.org" + +    def handlePremium(self): +        self.download(self.pyfile.url, post = self.getPostParameters()) + +getInfo = create_getInfo(SpeedLoadOrg) diff --git a/pyload/plugins/hoster/SpeedfileCz.py b/pyload/plugins/hoster/SpeedfileCz.py new file mode 100644 index 000000000..bfd316dfa --- /dev/null +++ b/pyload/plugins/hoster/SpeedfileCz.py @@ -0,0 +1,65 @@ +# -*- 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 SpeedfileCz(SimpleHoster): +    __name__ = "SpeedFileCz" +    __type__ = "hoster" +    __pattern__ = r"http://speedfile.cz/.*" +    __version__ = "0.31" +    __description__ = """speedfile.cz""" +    __author_name__ = ("zoidberg") + +    FILE_NAME_PATTERN = r'<meta property="og:title" content="(?P<N>[^"]+)" />' +    FILE_SIZE_PATTERN = r'<strong><big>(?P<S>[0-9.]+) (?P<U>[kKMG])i?B' +    URL_PATTERN = r'<a id="request" class="caps" href="([^"]+)" rel="nofollow">' +    FILE_OFFLINE_PATTERN = r'<title>Speedfile \| 404' +    WAIT_PATTERN = r'"requestedAt":(\d+),"allowedAt":(\d+),"adUri"' + +    def setup(self): +        self.multiDL = False + +    def process(self, pyfile): +        self.html = self.load(pyfile.url, decode=True) + +        if re.search(self.FILE_OFFLINE_PATTERN, self.html): +            self.offline() + +        found = re.search(self.FILE_NAME_PATTERN, self.html) +        if found is None: +            self.fail("Parse error (NAME)") +        pyfile.name = found.group(1) + +        found = re.search(self.URL_PATTERN, self.html) +        if found is None: +            self.fail("Parse error (URL)") +        download_url = "http://speedfile.cz/" + found.group(1) + +        self.html = self.load(download_url) +        self.logDebug(self.html) +        found = re.search(self.WAIT_PATTERN, self.html) +        if found is None: +            self.fail("Parse error (WAIT)") +        self.setWait(int(found.group(2)) - int(found.group(1))) +        self.wait() + +        self.download(download_url)            + +create_getInfo(SpeedfileCz)
\ No newline at end of file diff --git a/pyload/plugins/hoster/StreamCz.py b/pyload/plugins/hoster/StreamCz.py new file mode 100644 index 000000000..ca1033502 --- /dev/null +++ b/pyload/plugins/hoster/StreamCz.py @@ -0,0 +1,76 @@ +# -*- 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 import Hoster +from module.network.RequestFactory import getURL + +def getInfo(urls): +    result = [] +     +    for url in urls: +         +        html = getURL(url) +        if re.search(StreamCz.FILE_OFFLINE_PATTERN, html): +            # File offline +            result.append((url, 0, 1, url)) +        else: +            result.append((url, 0, 2, url))         +    yield result +     +class StreamCz(Hoster): +    __name__ = "StreamCz" +    __type__ = "hoster" +    __pattern__ = r"http://www.stream.cz/[^/]+/\d+.*" +    __version__ = "0.1" +    __description__ = """stream.cz""" +    __author_name__ = ("zoidberg") +    +    FILE_OFFLINE_PATTERN = r'<h1 class="commonTitle">Str.nku nebylo mo.n. nal.zt \(404\)</h1>' +    FILE_NAME_PATTERN = r'<link rel="video_src" href="http://www.stream.cz/\w+/(\d+)-([^"]+)" />' +    CDN_PATTERN = r'<param name="flashvars" value="[^"]*&id=(?P<ID>\d+)(?:&cdnLQ=(?P<cdnLQ>\d*))?(?:&cdnHQ=(?P<cdnHQ>\d*))?(?:&cdnHD=(?P<cdnHD>\d*))?&' + +    def setup(self): +        self.multiDL = True +        self.resumeDownload = True + +    def process(self, pyfile):      +         +        self.html = self.load(pyfile.url, decode=True) +         +        if re.search(self.FILE_OFFLINE_PATTERN, self.html):  +            self.offline() +         +        found = re.search(self.CDN_PATTERN, self.html) +        if found is None: self.fail("Parse error (CDN)") +        cdn = found.groupdict() +        self.logDebug(cdn) +        for cdnkey in ("cdnHD", "cdnHQ", "cdnLQ"): +            if cdn.has_key(cdnkey) and cdn[cdnkey] > '':  +                cdnid = cdn[cdnkey] +                break +        else:        +            self.fail("Stream URL not found") +             +        found = re.search(self.FILE_NAME_PATTERN, self.html) +        if found is None: self.fail("Parse error (NAME)") +        pyfile.name = "%s-%s.%s.mp4" % (found.group(2), found.group(1), cdnkey[-2:]) +              +        download_url = "http://cdn-dispatcher.stream.cz/?id=" + cdnid +        self.logInfo("STREAM (%s): %s" % (cdnkey[-2:], download_url)) +        self.download(download_url)          diff --git a/pyload/plugins/hoster/StreamcloudEu.py b/pyload/plugins/hoster/StreamcloudEu.py new file mode 100644 index 000000000..73c0465f8 --- /dev/null +++ b/pyload/plugins/hoster/StreamcloudEu.py @@ -0,0 +1,111 @@ +# -*- coding: utf-8 -*- +from module.plugins.hoster.XFileSharingPro import XFileSharingPro, create_getInfo +from module.network.HTTPRequest import HTTPRequest +from time import sleep +import re + +class StreamcloudEu(XFileSharingPro): +    __name__ = "StreamcloudEu" +    __type__ = "hoster" +    __pattern__ = r"http://(www\.)?streamcloud\.eu/\S+" +    __version__ = "0.02" +    __description__ = """Streamcloud.eu hoster plugin""" +    __author_name__ = ("seoester") +    __author_mail__ = ("seoester@googlemail.com") + +    HOSTER_NAME = "streamcloud.eu" +    DIRECT_LINK_PATTERN = r'file: "(http://(stor|cdn)\d+\.streamcloud.eu:?\d*/.*/video\.mp4)",' + +    def setup(self): +        super(StreamcloudEu, self).setup() +        self.multiDL = True + +    def getDownloadLink(self): +        found = re.search(self.DIRECT_LINK_PATTERN, self.html, re.S) +        if found: +            return found.group(1) + +        for i in range(5): +            self.logDebug("Getting download link: #%d" % i) +            data = self.getPostParameters() +            httpRequest = HTTPRequest(options=self.req.options) +            httpRequest.cj = self.req.cj +            sleep(10) +            self.html = httpRequest.load(self.pyfile.url, post = data, referer=False, cookies=True, decode = True) +            self.header = httpRequest.header + +            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 self.errmsg and 'captcha' in self.errmsg: +                self.fail("No valid captcha code entered") +            else: +                self.fail("Download link not found") + +        return found.group(1) + +    def getPostParameters(self): +        for i in range(3): +            if not self.errmsg: self.checkErrors() + +            if hasattr(self,"FORM_PATTERN"): +                action, inputs = self.parseHtmlForm(self.FORM_PATTERN) +            else: +                action, inputs = self.parseHtmlForm(input_names={"op": re.compile("^download")}) + +            if not inputs: +                action, inputs = self.parseHtmlForm('F1') +                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 ('download1', '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 +                self.logDebug("getPostParameters {0}".format(i)) +                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 = False) +                self.errmsg = None + +        else: self.parseError('FORM: %s' % (inputs['op'] if 'op' in inputs else 'UNKNOWN')) + + +getInfo = create_getInfo(StreamcloudEu) diff --git a/pyload/plugins/hoster/TurbobitNet.py b/pyload/plugins/hoster/TurbobitNet.py new file mode 100644 index 000000000..4e7eb81c2 --- /dev/null +++ b/pyload/plugins/hoster/TurbobitNet.py @@ -0,0 +1,170 @@ +# -*- 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 +import time + +from module.network.RequestFactory import getURL +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo, timestamp +from module.plugins.internal.CaptchaService 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.09" +    __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(self): +        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) diff --git a/pyload/plugins/hoster/TurbouploadCom.py b/pyload/plugins/hoster/TurbouploadCom.py new file mode 100644 index 000000000..6e81c6319 --- /dev/null +++ b/pyload/plugins/hoster/TurbouploadCom.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.DeadHoster import DeadHoster as EasybytezCom, create_getInfo +#from module.plugins.internal.SimpleHoster import create_getInfo +#from module.plugins.hoster.EasybytezCom import EasybytezCom + +class TurbouploadCom(EasybytezCom): +    __name__ = "TurbouploadCom" +    __type__ = "hoster" +    __pattern__ = r"http://(?:\w*\.)?turboupload.com/(\w+).*" +    __version__ = "0.02" +    __description__ = """turboupload.com""" +    __author_name__ = ("zoidberg") +    __author_mail__ = ("zoidberg@mujmail.cz") +     +    # shares code with EasybytezCom +     +    DIRECT_LINK_PATTERN = r'<a href="(http://turboupload.com/files/[^"]+)">\1</a>' + +    def handleFree(self): +        self.html = self.load(self.pyfile.url, post = self.getPostParameters(), ref = True, cookies = True) +        found = re.search(self.DIRECT_LINK_PATTERN, self.html) +        if not found: self.parseError('Download Link') +        url = found.group(1) +        self.logDebug('URL: ' + url) +        self.download(url) + +getInfo = create_getInfo(TurbouploadCom)
\ No newline at end of file diff --git a/pyload/plugins/hoster/TusfilesNet.py b/pyload/plugins/hoster/TusfilesNet.py new file mode 100644 index 000000000..517df8561 --- /dev/null +++ b/pyload/plugins/hoster/TusfilesNet.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +from module.plugins.hoster.XFileSharingPro import XFileSharingPro, create_getInfo + +class TusfilesNet(XFileSharingPro): +    __name__ = "TusfilesNet" +    __type__ = "hoster" +    __pattern__ = r"http://(www\.)?tusfiles\.net/\w{12}" +    __version__ = "0.01" +    __description__ = """Tusfiles.net hoster plugin""" +    __author_name__ = ("stickell") +    __author_mail__ = ("l.stickell@yahoo.it") + +    FILE_INFO_PATTERN = r'<li>(?P<N>[^<]+)</li>\s+<li><b>Size:</b> <small>(?P<S>[\d.]+) (?P<U>\w+)</small></li>' +    FILE_OFFLINE_PATTERN = r'The file you were looking for could not be found' + +    HOSTER_NAME = "tusfiles.net" + +getInfo = create_getInfo(TusfilesNet) diff --git a/pyload/plugins/hoster/TwoSharedCom.py b/pyload/plugins/hoster/TwoSharedCom.py new file mode 100644 index 000000000..8401e0cb0 --- /dev/null +++ b/pyload/plugins/hoster/TwoSharedCom.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo +import re + +class TwoSharedCom(SimpleHoster): +    __name__ = "TwoSharedCom" +    __type__ = "hoster" +    __pattern__ = r"http://[\w\.]*?2shared.com/(account/)?(download|get|file|document|photo|video|audio)/.*" +    __version__ = "0.11" +    __description__ = """2Shared Download Hoster""" +    __author_name__ = ("zoidberg") +    __author_mail__ = ("zoidberg@mujmail.cz") + +    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) +        if not found: self.parseError('Download link') +        link = found.group(1) +        self.logDebug("Download URL %s" % link) +         +        self.download(link) + +getInfo = create_getInfo(TwoSharedCom) +            
\ No newline at end of file diff --git a/pyload/plugins/hoster/UlozTo.py b/pyload/plugins/hoster/UlozTo.py new file mode 100644 index 000000000..1c3891eb1 --- /dev/null +++ b/pyload/plugins/hoster/UlozTo.py @@ -0,0 +1,156 @@ +# -*- 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 + +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('.','') + +class UlozTo(SimpleHoster): +    __name__ = "UlozTo" +    __type__ = "hoster" +    __pattern__ = r"http://(\w*\.)?(uloz\.to|ulozto\.(cz|sk|net)|bagruj.cz|zachowajto.pl)/(?:live/)?(?P<id>\w+/[^/?]*)" +    __version__ = "0.93" +    __description__ = """uloz.to""" +    __author_name__ = ("zoidberg") + +    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): +        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": "passwordProtectedForm-submit"}, +                    post={"password": password, "password_send": 'Send'}, cookies=True) +            else: +                self.fail("No or incorrect password") + +        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: +            self.handleFree() +             +        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_id_field = captcha_text_field = None +         +        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) + +        self.logDebug(' CAPTCHA ID:' + captcha_id + ' CAPTCHA TEXT:' + captcha_text) +         +        """ +        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, disposition=True) + +    def handlePremium(self): +        self.download(self.pyfile.url + "?do=directDownload", disposition=True) +        #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 = "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(r'<ul class="error">\s*<li>Error rewriting the text.</li>'), +            "offline": re.compile(self.FILE_OFFLINE_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("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) diff --git a/pyload/plugins/hoster/UloziskoSk.py b/pyload/plugins/hoster/UloziskoSk.py new file mode 100644 index 000000000..c607e7a5b --- /dev/null +++ b/pyload/plugins/hoster/UloziskoSk.py @@ -0,0 +1,75 @@ +# -*- 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 + +class UloziskoSk(SimpleHoster): +    __name__ = "UloziskoSk" +    __type__ = "hoster" +    __pattern__ = r"http://(\w*\.)?ulozisko.sk/.*" +    __version__ = "0.23" +    __description__ = """Ulozisko.sk""" +    __author_name__ = ("zoidberg") + +    URL_PATTERN = r'<form name = "formular" action = "([^"]+)" method = "post">' +    ID_PATTERN = r'<input type = "hidden" name = "id" value = "([^"]+)" />' +    FILE_NAME_PATTERN = r'<div class="down1">(?P<N>[^<]+)</div>' +    FILE_SIZE_PATTERN = ur'Veľkosť súboru: <strong>(?P<S>[0-9.]+) (?P<U>[kKMG])i?B</strong><br />' +    CAPTCHA_PATTERN = r'<img src="(/obrazky/obrazky.php\?fid=[^"]+)" alt="" />' +    FILE_OFFLINE_PATTERN = ur'<span class = "red">Zadaný súbor neexistuje z jedného z nasledujúcich dôvodov:</span>' +    IMG_PATTERN = ur'<strong>PRE ZVÄČŠENIE KLIKNITE NA OBRÁZOK</strong><br /><a href = "([^"]+)">' + +    def process(self, pyfile): +        self.html = self.load(pyfile.url, decode=True) +        self.getFileInfo() +         +        found = re.search(self.IMG_PATTERN, self.html) +        if found: +            url = "http://ulozisko.sk" + found.group(1) +            self.download(url) +        else: +            self.handleFree() + +    def handleFree(self): +        found = re.search(self.URL_PATTERN, self.html) +        if found is None: raise PluginParseError('URL') +        parsed_url = 'http://www.ulozisko.sk' + found.group(1) + +        found = re.search(self.ID_PATTERN, self.html) +        if found is None: raise PluginParseError('ID') +        id = found.group(1) + +        self.logDebug('URL:' + parsed_url + ' ID:' + id) + +        found = re.search(self.CAPTCHA_PATTERN, self.html) +        if found is None: raise PluginParseError('CAPTCHA') +        captcha_url = 'http://www.ulozisko.sk' + found.group(1) + +        captcha = self.decryptCaptcha(captcha_url, cookies=True) + +        self.logDebug('CAPTCHA_URL:' + captcha_url + ' CAPTCHA:' + captcha) + +        self.download(parsed_url, post={ +            "antispam": captcha, +            "id": id, +            "name": self.pyfile.name, +            "but": "++++STIAHNI+S%DABOR++++" +        }) + +getInfo = create_getInfo(UloziskoSk) diff --git a/pyload/plugins/hoster/UnibytesCom.py b/pyload/plugins/hoster/UnibytesCom.py new file mode 100644 index 000000000..3c8552271 --- /dev/null +++ b/pyload/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/pyload/plugins/hoster/UploadStationCom.py b/pyload/plugins/hoster/UploadStationCom.py new file mode 100644 index 000000000..96dc7b577 --- /dev/null +++ b/pyload/plugins/hoster/UploadStationCom.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +from module.plugins.hoster.FileserveCom import FileserveCom, checkFile +from module.plugins.Plugin import chunks + +class UploadStationCom(FileserveCom): +    __name__ = "UploadStationCom" +    __type__ = "hoster" +    __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", "zoidberg") +    __author_mail__ = ("fragonib[AT]yahoo[DOT]es", "zoidberg@mujmail.cz") +             +    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/pyload/plugins/hoster/UploadedTo.py b/pyload/plugins/hoster/UploadedTo.py new file mode 100644 index 000000000..f38336773 --- /dev/null +++ b/pyload/plugins/hoster/UploadedTo.py @@ -0,0 +1,239 @@ +# -*- coding: utf-8 -*- + +# Test links (random.bin): +# http://ul.to/044yug9o +# http://ul.to/gzfhd0xs + +import re +from time import sleep + +from module.utils import html_unescape, parseFileSize + +from module.plugins.Hoster import Hoster +from module.network.RequestFactory import getURL +from module.plugins.Plugin import chunks +from module.plugins.internal.CaptchaService import ReCaptcha + +key = "bGhGMkllZXByd2VEZnU5Y2NXbHhYVlZ5cEE1bkEzRUw=".decode('base64') + + +def getID(url): +    """ returns id from file url""" +    m = re.match(UploadedTo.__pattern__, url) +    return m.group('ID') + + +def getAPIData(urls): +    post = {"apikey": key} + +    idMap = {} + +    for i, url in enumerate(urls): +        id = getID(url) +        post["id_%s" % i] = id +        idMap[id] = url + +    for i in xrange(5): +        api = unicode(getURL("http://uploaded.net/api/filemultiple", post=post, decode=False), 'iso-8859-1') +        if api != "can't find request": +            break +        else: +            sleep(3) + +    result = {} + +    if api: +        for line in api.splitlines(): +            data = line.split(",", 4) +            if data[1] in idMap: +                result[data[1]] = (data[0], data[2], data[4], data[3], idMap[data[1]]) + +    return result + + +def parseFileInfo(self, url='', html=''): +    if not html and hasattr(self, "html"): html = self.html +    name, size, status, found, fileid = url, 0, 3, None, None + +    if re.search(self.FILE_OFFLINE_PATTERN, html): +        # File offline +        status = 1 +    else: +        found = re.search(self.FILE_INFO_PATTERN, html) +        if found: +            name, fileid = html_unescape(found.group('N')), found.group('ID') +            size = parseFileSize(found.group('S')) +            status = 2 + +    return name, size, status, fileid + + +def getInfo(urls): +    for chunk in chunks(urls, 80): +        result = [] + +        api = getAPIData(chunk) + +        for data in api.itervalues(): +            if data[0] == "online": +                result.append((html_unescape(data[2]), data[1], 2, data[4])) + +            elif data[0] == "offline": +                result.append((data[4], 0, 1, data[4])) + +        yield result + + +class UploadedTo(Hoster): +    __name__ = "UploadedTo" +    __type__ = "hoster" +    __pattern__ = r"https?://[\w\.-]*?(uploaded\.(to|net)|ul\.to)(/file/|/?\?id=|.*?&id=|/)(?P<ID>\w+)" +    __version__ = "0.71" +    __description__ = """Uploaded.net Download Hoster""" +    __author_name__ = ("spoob", "mkaay", "zoidberg", "netpok", "stickell") +    __author_mail__ = ("spoob@pyload.org", "mkaay@mkaay.de", "zoidberg@mujmail.cz", "netpok@gmail.com", "l.stickell@yahoo.it") + +    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>' +    DL_LIMIT_PATTERN = "You have reached the max. number of possible free downloads for this hour" + +    def setup(self): +        self.html = None +        self.multiDL = False +        self.resumeDownload = False +        self.url = False +        self.chunkLimit = 1  # critical problems with more chunks +        if self.account: +            self.premium = self.account.getAccountInfo(self.user)["premium"] +            if self.premium: +                self.multiDL = True +                self.resumeDownload = True + +        self.fileID = getID(self.pyfile.url) +        self.pyfile.url = "http://uploaded.net/file/%s" % self.fileID + +    def process(self, pyfile): +        self.load("http://uploaded.net/language/en", just_header=True) + +        api = getAPIData([pyfile.url]) + +        # TODO: fallback to parse from site, because api sometimes delivers wrong status codes + +        if not api: +            self.logWarning("No response for API call") + +            self.html = unicode(self.load(pyfile.url, decode=False), 'iso-8859-1') +            name, size, status, self.fileID = parseFileInfo(self) +            self.logDebug(name, size, status, self.fileID) +            if status == 1: +                self.offline() +            elif status == 2: +                pyfile.name, pyfile.size = name, size +            else: +                self.fail('Parse error - file info') +        elif api == 'Access denied': +            self.fail(_("API key invalid")) + +        else: +            if self.fileID not in api: +                self.offline() + +            self.data = api[self.fileID] +            if self.data[0] != "online": +                self.offline() + +            pyfile.name = html_unescape(self.data[2]) + +        # self.pyfile.name = self.get_file_name() + +        if self.premium: +            self.handlePremium() +        else: +            self.handleFree() + + +    def handlePremium(self): +        info = self.account.getAccountInfo(self.user, True) +        self.logDebug("%(name)s: Use Premium Account (%(left)sGB left)" % {"name": self.__name__, +                                                                            "left": info["trafficleft"] / 1024 / 1024}) +        if int(self.data[1]) / 1024 > info["trafficleft"]: +            self.logInfo(_("%s: Not enough traffic left" % self.__name__)) +            self.account.empty(self.user) +            self.resetAccount() +            self.fail(_("Traffic exceeded")) + +        header = self.load("http://uploaded.net/file/%s" % self.fileID, just_header=True) +        if "location" in header: +            #Direct download +            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) + +        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.net/js/download.js", decode=True) + +        challengeId = re.search(r'Recaptcha\.create\("([^"]+)', js) + +        url = "http://uploaded.net/io/ticket/captcha/%s" % self.fileID +        downloadURL = "" + +        for i in range(5): +            #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} +            self.wait() + +            result = self.load(url, post=options) +            self.logDebug("result: %s" % result) + +            if "limit-size" in result: +                self.fail("File too big for free download") +            elif "limit-slot" in result:  # Temporary restriction so just wait a bit +                self.setWait(30 * 60, True) +                self.wait() +                self.retry() +            elif "limit-parallel" in result: +                self.fail("Cannot download in parallel") +            elif self.DL_LIMIT_PATTERN in result:  # limit-dl +                self.setWait(3 * 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'") + +        if not downloadURL: +            self.fail("No Download url retrieved/all captcha attempts failed") + +        self.download(downloadURL, disposition=True) +        check = self.checkDownload({"limit-dl": self.DL_LIMIT_PATTERN}) +        if check == "limit-dl": +            self.setWait(3 * 60 * 60, True) +            self.wait() +            self.retry() diff --git a/pyload/plugins/hoster/UploadheroCom.py b/pyload/plugins/hoster/UploadheroCom.py new file mode 100644 index 000000000..65d6cc4e9 --- /dev/null +++ b/pyload/plugins/hoster/UploadheroCom.py @@ -0,0 +1,87 @@ +# -*- 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 +""" + +# Test link (random.bin): +# http://uploadhero.co/dl/wQBRAVSM + +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.14" +    __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.logDebug("%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.logDebug("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) diff --git a/pyload/plugins/hoster/UploadingCom.py b/pyload/plugins/hoster/UploadingCom.py new file mode 100644 index 000000000..a98c3bf71 --- /dev/null +++ b/pyload/plugins/hoster/UploadingCom.py @@ -0,0 +1,110 @@ +#!/usr/bin/env python +# -*- 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 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/)?(?P<ID>[\w\d]+)" +    __version__ = "0.33" +    __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.*?>The requested file is not found</h2>' +         +    def process(self, pyfile): +        # set lang to english +        self.req.cj.setCookie("uploading.com", "lang", "1") +        self.req.cj.setCookie("uploading.com", "language", "1") +        self.req.cj.setCookie("uploading.com", "setlang", "en") +        self.req.cj.setCookie("uploading.com", "_lang", "en") +         +        if not "/get/" in self.pyfile.url: +            self.pyfile.url = self.pyfile.url.replace("/files", "/files/get") +         +        self.html = self.load(pyfile.url, decode = True) +        self.file_info = self.getFileInfo() +         +        if self.premium: +            self.handlePremium() +        else: +            self.handleFree()                    +     +    def handlePremium(self): +        postData = {'action': 'get_link', +                    '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: +            url = url.group(1).replace("\\/", "/") +            self.download(url) +         +        raise Exception("Plugin defect.") +     +    def handleFree(self): +        found = re.search('<h2>((Daily )?Download Limit)</h2>', self.html) +        if found: +            self.pyfile.error = found.group(1) +            self.logWarning(self.pyfile.error) +            self.retry(max_tries=6, wait_time = 21600 if found.group(2) else 900, reason = self.pyfile.error)   +         +        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 +         +        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.logInfo("%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") +         +        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/pyload/plugins/hoster/UptoboxCom.py b/pyload/plugins/hoster/UptoboxCom.py new file mode 100644 index 000000000..60a93c1e5 --- /dev/null +++ b/pyload/plugins/hoster/UptoboxCom.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +from module.plugins.hoster.XFileSharingPro import XFileSharingPro, create_getInfo + +class UptoboxCom(XFileSharingPro): +    __name__ = "UptoboxCom" +    __type__ = "hoster" +    __pattern__ = r"http://(?:\w*\.)*?uptobox.com/\w{12}" +    __version__ = "0.06" +    __description__ = """Uptobox.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>' +    FILE_OFFLINE_PATTERN = r'<center>File Not Found</center>' +    HOSTER_NAME = "uptobox.com" +    +    def setup(self): +        self.resumeDownload = self.multiDL = self.premium         +        self.chunkLimit = 1 + +getInfo = create_getInfo(UptoboxCom)
\ No newline at end of file diff --git a/pyload/plugins/hoster/VeehdCom.py b/pyload/plugins/hoster/VeehdCom.py new file mode 100644 index 000000000..4486eb84a --- /dev/null +++ b/pyload/plugins/hoster/VeehdCom.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +import re +from module.plugins.Hoster import Hoster + +class VeehdCom(Hoster): +    __name__ = 'VeehdCom' +    __type__ = 'hoster' +    __pattern__ = r'http://veehd\.com/video/\d+_\S+' +    __config__ = [ +        ('filename_spaces', 'bool', "Allow spaces in filename", 'False'), +        ('replacement_char', 'str', "Filename replacement character", '_'), +    ] +    __version__ = '0.22' +    __description__ = """Veehd.com Download Hoster""" +    __author_name__ = ('cat') +    __author_mail__ = ('cat@pyload') +     +    def _debug(self, msg): +        self.logDebug('[%s] %s' % (self.__name__, msg)) +     +    def setup(self): +        self.html = None +        self.multiDL = True +        self.req.canContinue = True + +    def process(self, pyfile): +        self.download_html() +        if not self.file_exists(): +            self.offline() +             +        pyfile.name = self.get_file_name() +        self.download(self.get_file_url()) +         +    def download_html(self): +        url = self.pyfile.url +        self._debug("Requesting page: %s" % (repr(url),)) +        self.html = self.load(url) +         +    def file_exists(self): +        if self.html is None: +            self.download_html() +         +        if '<title>Veehd</title>' in self.html: +            return False +        return True +         +    def get_file_name(self): +        if self.html is None: +            self.download_html() +             +        match = re.search(r'<title[^>]*>([^<]+) on Veehd</title>', self.html) +        if not match: +            self.fail("video title not found") +        name = match.group(1) +         +        # replace unwanted characters in filename +        if self.getConfig('filename_spaces'): +            pattern = '[^0-9A-Za-z\.\ ]+' +        else: +            pattern = '[^0-9A-Za-z\.]+' +             +        name = re.sub(pattern, self.getConfig('replacement_char'), +            name) +        return name + '.avi' + +    def get_file_url(self): +        """ returns the absolute downloadable filepath +          """ +        if self.html is None: +            self.download_html() + +        match = re.search(r'<embed type="video/divx" ' +            r'src="(http://([^/]*\.)?veehd\.com/dl/[^"]+)"', +            self.html) +        if not match: +            self.fail("embedded video url not found") +        file_url = match.group(1) + +        return file_url diff --git a/pyload/plugins/hoster/WarserverCz.py b/pyload/plugins/hoster/WarserverCz.py new file mode 100644 index 000000000..b256f8d1b --- /dev/null +++ b/pyload/plugins/hoster/WarserverCz.py @@ -0,0 +1,70 @@ +# -*- 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 +""" + +#similar to coolshare.cz (down) + +import re +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo +from module.network.HTTPRequest import BadHeader +from module.utils import html_unescape + +class WarserverCz(SimpleHoster): +    __name__ = "WarserverCz" +    __type__ = "hoster" +    __pattern__ = r"http://(?:\w*\.)?warserver.cz/stahnout/(?P<ID>\d+)/.+" +    __version__ = "0.12" +    __description__ = """Warserver.cz""" +    __author_name__ = ("zoidberg") +     +    FILE_NAME_PATTERN = r'<h1.*?>(?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" +     +    DOMAIN = "http://s01.warserver.cz"            +               +    def handleFree(self): +        try:       +            self.download("%s/dwn-free.php?fid=%s" % (self.DOMAIN, self.file_info['ID']))     +        except BadHeader, e: +            self.logError(e) +            if e.code == 403: +                self.longWait(60,60) +            else: raise +        self.checkDownloadedFile() +         +    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) +        self.checkDownloadedFile()   +         +    def checkDownloadedFile(self): +        check = self.checkDownload({ +            "offline": ">404 Not Found<" +            }) + +        if check == "offline": +            self.offline()      + +getInfo = create_getInfo(WarserverCz)
\ No newline at end of file diff --git a/pyload/plugins/hoster/WebshareCz.py b/pyload/plugins/hoster/WebshareCz.py new file mode 100644 index 000000000..195e65a93 --- /dev/null +++ b/pyload/plugins/hoster/WebshareCz.py @@ -0,0 +1,48 @@ +# -*- 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.12" +    __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 setup(self): +        self.multiDL = True + +    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/pyload/plugins/hoster/WrzucTo.py b/pyload/plugins/hoster/WrzucTo.py new file mode 100644 index 000000000..4a5e89f22 --- /dev/null +++ b/pyload/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/pyload/plugins/hoster/WuploadCom.py b/pyload/plugins/hoster/WuploadCom.py new file mode 100644 index 000000000..3dab1b1bb --- /dev/null +++ b/pyload/plugins/hoster/WuploadCom.py @@ -0,0 +1,241 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import re +import string +from urllib import unquote + +from module.plugins.Hoster import Hoster +from module.plugins.internal.CaptchaService import ReCaptcha +from module.plugins.Plugin import chunks + +from module.network.RequestFactory import getURL +from module.common.json_layer import json_loads + + +def getInfo(urls): +    for chunk in chunks(urls, 20): +        result = [] +        ids = dict() +        for url in chunk: +            id = getId(url) +            if id: +                ids[id] = url +            else: +                result.append((None, 0, 1, url)) + +        if len(ids) > 0: +            check_url = "http://api.wupload.com/link?method=getInfo&format=json&ids=" + ",".join(ids.keys()) +            response = json_loads(getURL(check_url).decode("utf8", "ignore")) +            for item in response["FSApi_Link"]["getInfo"]["response"]["links"]: +                if item["status"] != "AVAILABLE": +                    result.append((None, 0, 1, ids[str(item["id"])])) +                else: +                    result.append((unquote(item["filename"]), item["size"], 2, ids[str(item["id"])])) +        yield result + + +def getId(url): +    match = re.search(WuploadCom.FILE_ID_PATTERN, url) +    if match: +        return string.replace(match.group("id"), "/", "-") +    else: +        return None + + +class WuploadCom(Hoster): +    __name__ = "WuploadCom" +    __type__ = "hoster" +    __pattern__ = r"http://[\w\.]*?wupload\..*?/file/(([a-z][0-9]+/)?[0-9]+)(/.*)?" +    __version__ = "0.21" +    __description__ = """Wupload com""" +    __author_name__ = ("jeix", "paulking") +    __author_mail__ = ("jeix@hasnomail.de", "") + +    API_ADDRESS = "http://api.wupload.com" +    URL_DOMAIN_PATTERN = r'(?P<prefix>.*?)(?P<domain>.wupload\..+?)(?P<suffix>/.*)' +    FILE_ID_PATTERN = r'/file/(?P<id>([a-z][0-9]+/)?[0-9]+)(/.*)?' +    FILE_LINK_PATTERN = r'<p><a href="(http://.+?\.wupload\..+?)"><span>Download Now' +    WAIT_TIME_PATTERN = r'countDownDelay = (?P<wait>\d+)' +    WAIT_TM_PATTERN = r"name='tm' value='(.*?)' />" +    WAIT_TM_HASH_PATTERN = r"name='tm_hash' value='(.*?)' />" +    CAPTCHA_TYPE1_PATTERN = r'Recaptcha.create\("(.*?)",' +    CAPTCHA_TYPE2_PATTERN = r'id="recaptcha_image"><img style="display: block;" src="(.+)image?c=(.+?)"' + +    def init(self): +        if self.account: +            self.premium = self.account.getAccountInfo(self.user)["premium"] +        if not self.premium: +            self.chunkLimit = 1 +            self.multiDL = False + +    def process(self, pyfile): +        self.pyfile = pyfile + +        self.pyfile.url = self.checkFile(self.pyfile.url) + +        if self.premium: +            self.downloadPremium() +        else: +            self.downloadFree() + +    def checkFile(self, url): +        id = getId(url) +        self.logDebug("file id is %s" % id) +        if id: +            # Use the api to check the current status of the file and fixup data +            check_url = self.API_ADDRESS + "/link?method=getInfo&format=json&ids=%s" % id +            result = json_loads(self.load(check_url, decode=True)) +            item = result["FSApi_Link"]["getInfo"]["response"]["links"][0] +            self.logDebug("api check returns %s" % item) + +            if item["status"] != "AVAILABLE": +                self.offline() +            if item["is_password_protected"] != 0: +                self.fail("This file is password protected") + +            # ignored this check due to false api information +            #if item["is_premium_only"] != 0 and not self.premium: +            #    self.fail("need premium account for file") + +            self.pyfile.name = unquote(item["filename"]) + +            # Fix the url and resolve the domain to the correct regional variation +            url = item["url"] +            urlparts = re.search(self.URL_DOMAIN_PATTERN, url) +            if urlparts: +                url = urlparts.group("prefix") + self.getDomain() + urlparts.group("suffix") +                self.logDebug("localised url is %s" % url) +            return url +        else: +            self.fail("Invalid URL") + +    def getDomain(self): +        result = json_loads( +            self.load(self.API_ADDRESS + "/utility?method=getWuploadDomainForCurrentIp&format=json", decode=True)) +        self.logDebug("%s: response to get domain %s" % (self.__name__, result)) +        return result["FSApi_Utility"]["getWuploadDomainForCurrentIp"]["response"] + +    def downloadPremium(self): +        self.logDebug("Premium download") + +        api = self.API_ADDRESS + "/link?method=getDownloadLink&u=%%s&p=%%s&ids=%s" % getId(self.pyfile.url) + +        result = json_loads(self.load(api % (self.user, self.account.getAccountData(self.user)["password"]))) +        links = result["FSApi_Link"]["getDownloadLink"]["response"]["links"] + +        #wupload seems to return list and no dicts +        if type(links) == dict: +            info = links.values()[0] +        else: +            info = links[0] + +        if "status" in info and info["status"] == "NOT_AVAILABLE": +            self.tempOffline() + +        self.download(info["url"]) + +    def downloadFree(self): +        self.logDebug("Free download") +        # Get initial page +        self.html = self.load(self.pyfile.url) +        url = self.pyfile.url + "?start=1" +        self.html = self.load(url) +        self.handleErrors() + +        finalUrl = re.search(self.FILE_LINK_PATTERN, self.html) + +        if not finalUrl: +            self.doWait(url) + +            chall = re.search(self.CAPTCHA_TYPE1_PATTERN, self.html) +            chall2 = re.search(self.CAPTCHA_TYPE2_PATTERN, self.html) +            if chall or chall2: +                for i in range(5): +                    re_captcha = ReCaptcha(self) +                    if chall: +                        self.logDebug("Captcha type1") +                        challenge, result = re_captcha.challenge(chall.group(1)) +                    else: +                        self.logDebug("Captcha type2") +                        server = chall2.group(1) +                        challenge = chall2.group(2) +                        result = re_captcha.result(server, challenge) + +                    postData = {"recaptcha_challenge_field": challenge, +                                "recaptcha_response_field": result} + +                    self.html = self.load(url, post=postData) +                    self.handleErrors() +                    chall = re.search(self.CAPTCHA_TYPE1_PATTERN, self.html) +                    chall2 = re.search(self.CAPTCHA_TYPE2_PATTERN, self.html) + +                    if chall or chall2: +                        self.invalidCaptcha() +                    else: +                        self.correctCaptcha() +                        break + +            finalUrl = re.search(self.FILE_LINK_PATTERN, self.html) + +        if not finalUrl: +            self.fail("Couldn't find free download link") + +        self.logDebug("got download url %s" % finalUrl.group(1)) +        self.download(finalUrl.group(1)) + +    def doWait(self, url): +        # If the current page requires us to wait then wait and move to the next page as required + +        # There maybe more than one wait period. The extended wait if download limits have been exceeded (in which case we try reconnect) +        # and the short wait before every download. Visually these are the same, the difference is that one includes a code to allow +        # progress to the next page + +        waitSearch = re.search(self.WAIT_TIME_PATTERN, self.html) +        while waitSearch: +            wait = int(waitSearch.group("wait")) +            if wait > 300: +                self.wantReconnect = True + +            self.setWait(wait) +            self.logDebug("Waiting %d seconds." % wait) +            self.wait() + +            tm = re.search(self.WAIT_TM_PATTERN, self.html) +            tm_hash = re.search(self.WAIT_TM_HASH_PATTERN, self.html) + +            if tm and tm_hash: +                tm = tm.group(1) +                tm_hash = tm_hash.group(1) +                self.html = self.load(url, post={"tm": tm, "tm_hash": tm_hash}) +                self.handleErrors() +                break +            else: +                self.html = self.load(url) +                self.handleErrors() +                waitSearch = re.search(self.WAIT_TIME_PATTERN, self.html) + +    def handleErrors(self): +        if "This file is available for premium users only." in self.html: +            self.fail("need premium account for file") + +        if "The file that you're trying to download is larger than" in self.html: +            self.fail("need premium account for file") + +        if "Free users may only download 1 file at a time" in self.html: +            self.fail("only 1 file at a time for free users") + +        if "Free user can not download files" in self.html: +            self.fail("need premium account for file") + +        if "Download session in progress" in self.html: +            self.fail("already downloading") + +        if "This file is password protected" in self.html: +            self.fail("This file is password protected") + +        if "An Error Occurred" in self.html: +            self.fail("A server error occured.") + +        if "This file was deleted" in self.html: +            self.offline() diff --git a/pyload/plugins/hoster/X7To.py b/pyload/plugins/hoster/X7To.py new file mode 100644 index 000000000..965d84543 --- /dev/null +++ b/pyload/plugins/hoster/X7To.py @@ -0,0 +1,93 @@ +# -*- coding: utf-8 -*- +import re + +from module.plugins.Hoster import Hoster + +from module.network.RequestFactory import getURL + +def getInfo(urls): +    yield [(url, 0, 1, url) for url in urls] + + +class X7To(Hoster): +    __name__ = "X7To" +    __type__ = "hoster" +    __pattern__ = r"http://(?:www.)?x7.to/" +    __version__ = "0.3" +    __description__ = """X7.To File Download Hoster""" +    __author_name__ = ("ernieb") +    __author_mail__ = ("ernieb") +     +    FILE_INFO_PATTERN=r'<meta name="description" content="Download: (.*?) \(([0-9,.]+) (KB|MB|GB)\)' + +    def init(self): +        if self.premium: +            self.multiDL = False +            self.resumeDownload = False +            self.chunkLimit = 1 +        else: +            self.multiDL = False + +        self.file_id = re.search(r"http://x7.to/([a-zA-Z0-9]+)", self.pyfile.url).group(1) +        self.logDebug("file id is %s" % self.file_id) +        self.pyfile.url = "http://x7.to/" + self.file_id + +    def process(self, pyfile): +        self.fail("Hoster not longer available") + +    def handlePremium(self): +        # check if over limit first +        overLimit = re.search(r'<a onClick="cUser.buyTraffic\(\)" id="DL">', self.html) +        if overLimit: +            self.logDebug("over limit, falling back to free") +            self.handleFree() +        else: +            realurl = re.search(r'<a href="(http://stor.*?)" id="DL">', self.html) +            if realurl: +                realurl = realurl.group(1) +                self.logDebug("premium url found %s" % realurl) +            else: +                self.logDebug("premium link not found") +            self.download(realurl) + +    def handleFree(self): +        # find file id +        file_id = re.search(r"var dlID = '(.*?)'", self.html) +        if not file_id: +            self.fail("Free download id not found") + +        file_url = "http://x7.to/james/ticket/dl/" + file_id.group(1) +        self.logDebug("download id %s" % file_id.group(1)) + +        self.html = self.load(file_url, ref=False, decode=True) + +        # deal with errors +        if "limit-dl" in self.html: +            self.logDebug("Limit reached ... waiting") +            self.setWait(900,True) +            self.wait() +            self.retry() + +        if "limit-parallel" in self.html: +            self.fail("Cannot download in parallel") + +        # no waiting required, go to download +        waitCheck = re.search(r"wait:(\d*),", self.html) +        if waitCheck: +            waitCheck = int(waitCheck.group(1)) +            self.setWait(waitCheck) +            self.wait() + +        urlCheck = re.search(r"url:'(.*?)'", self.html) +        url = None +        if urlCheck: +            url = urlCheck.group(1) +            self.logDebug("free url found %s" % url) + +        if url: +            try: +                self.download(url) +            except: +                self.logDebug("downloading url failed: %s" % url) +        else: +            self.fail("Free download url found") diff --git a/pyload/plugins/hoster/XFileSharingPro.py b/pyload/plugins/hoster/XFileSharingPro.py new file mode 100644 index 000000000..d5a32dd16 --- /dev/null +++ b/pyload/plugins/hoster/XFileSharingPro.py @@ -0,0 +1,318 @@ +# -*- 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.internal.CaptchaService import ReCaptcha, SolveMedia +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.18" +    __description__ = """XFileSharingPro common hoster base""" +    __author_name__ = ("zoidberg", "stickell") +    __author_mail__ = ("zoidberg@mujmail.cz", "l.stickell@yahoo.it") + +    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|h[1-6])>File Not Found</(b|h[1-6])>' + +    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>' +    SOLVEMEDIA_PATTERN = r'http:\/\/api\.solvemedia\.com\/papi\/challenge\.script\?k=(.*?)"' +    ERROR_PATTERN = r'class=["\']err["\'][^>]*>(.*?)</' + +    def setup(self): +        if self.__name__ == "XFileSharingPro": +            self.__pattern__ = self.core.pluginManager.hosterPlugins[self.__name__]['pattern'] +            self.multiDL = True +        else: +            self.resumeDownload = self.multiDL = self.premium + +        self.chunkLimit = 1 + +    def process(self, pyfile): +        self.prepare() + +        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.location = self.getDirectDownloadLink() + +            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 prepare(self): +        """ Initialize important variables """ +        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://([^/]*?%s|\d+\.\d+\.\d+\.\d+)(:\d+/d/|/files/\d+/\w+/)[^"\'<]+)' % self.HOSTER_NAME + +        self.captcha = self.errmsg = None +        self.passwords = self.getPassword().splitlines() + +    def getDirectDownloadLink(self): +        """ Get download link for premium users with direct download enabled """ +        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) + +        location = None +        found = re.search("Location\s*:\s*(.*)", self.header, re.I) +        if found and re.match(self.DIRECT_LINK_PATTERN, found.group(1)): +            location = found.group(1).strip() + +        return location + +    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 self.errmsg and 'captcha' in self.errmsg: +                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) +        header = self.load(self.pyfile.url, just_header=True) +        if 'location' in header:  # Direct link +            self.startDownload(self.pyfile.url) +        else: +            self.retry() + +    def startDownload(self, link): +        link = link.strip() +        if self.captcha: self.correctCaptcha() +        self.logDebug('DIRECT LINK: %s' % link) +        self.download(link, disposition=True) + +    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 'captcha' in self.errmsg: +                self.invalidCaptcha() +            elif 'premium' in self.errmsg and 'require' in self.errmsg: +                self.fail("File can be downloaded by premium users only") +            elif 'limit' in self.errmsg: +                self.setWait(3600, True) +                self.wait() +                self.retry(25) +            elif 'countdown' in self.errmsg 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") +            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() + +            if hasattr(self,"FORM_PATTERN"): +                action, inputs = self.parseHtmlForm(self.FORM_PATTERN) +            else: +                action, inputs = self.parseHtmlForm(input_names={"op": re.compile("^download")}) + +            if not inputs: +                action, inputs = self.parseHtmlForm('F1') +                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 +                else: +                    found = re.search(self.SOLVEMEDIA_PATTERN, self.html) +                    if found: +                        captcha_key = found.group(1) +                        captcha = SolveMedia(self) +                        inputs['adcopy_challenge'], inputs['adcopy_response'] = captcha.challenge(captcha_key) +                        return 4 +        return 0 + +getInfo = create_getInfo(XFileSharingPro) diff --git a/pyload/plugins/hoster/XHamsterCom.py b/pyload/plugins/hoster/XHamsterCom.py new file mode 100644 index 000000000..866c5da45 --- /dev/null +++ b/pyload/plugins/hoster/XHamsterCom.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import re +from module.plugins.Hoster import Hoster +from urllib import unquote +from module.common.json_layer import json_loads + +def clean_json(json_expr): +    json_expr = re.sub('[\n\r]', '', json_expr) +    json_expr = re.sub(' +', '', json_expr) +    json_expr = re.sub('\'','"', json_expr) + +    return json_expr +     +class XHamsterCom(Hoster): +    __name__ = "XHamsterCom" +    __type__ = "hoster" +    __pattern__ = r"http://(www\.)?xhamster\.com/movies/.+" +    __version__ = "0.11" +    __config__ = [("type", ".mp4;.flv", "Preferred type", ".mp4")] +    __description__ = """XHamster.com Video Download Hoster""" + +    def setup(self): +        self.html = None +         +    def process(self, pyfile): +        self.pyfile = pyfile +         +        if not self.file_exists(): +            self.offline() + +        if self.getConfig("type"): +            self.desired_fmt = self.getConfig("type")     +            +        self.pyfile.name = self.get_file_name() + self.desired_fmt +        self.download(self.get_file_url()) + +    def download_html(self): +        url = self.pyfile.url +        self.html = self.load(url) + +    def get_file_url(self): +        """ returns the absolute downloadable filepath +        """ +        if self.html is None: +            self.download_html() +                          +        flashvar_pattern = re.compile('flashvars = ({.*?});', re.DOTALL) +        json_flashvar=flashvar_pattern.search(self.html) + +        if json_flashvar is None: +            self.fail("Parse error (flashvars)") + +        j = clean_json(json_flashvar.group(1)) +        flashvars = json_loads(j) +         +        if flashvars["srv"]: +            srv_url  =  flashvars["srv"] + '/' +        else: +            self.fail("Parse error (srv_url)") +             +        if flashvars["url_mode"]: +            url_mode  =  flashvars["url_mode"] +        else: +            self.fail("Parse error (url_mode)") +         + +        if self.desired_fmt == ".mp4": +            file_url = re.search(r"<a href=\"" + srv_url + "(.+?)\"", self.html) +            if file_url is None: +                self.fail("Parse error (file_url)") +            file_url=file_url.group(1) +            long_url = srv_url + file_url +            self.logDebug(_("long_url: %s") % long_url) +        else: +            if flashvars["file"]: +                file_url = unquote(flashvars["file"]) +            else: +                self.fail("Parse error (file_url)") + +            if url_mode=='3': +                long_url = file_url +                self.logDebug(_("long_url: %s") % long_url) +            else:     +                long_url = srv_url + "key=" + file_url +                self.logDebug(_("long_url: %s") % long_url) +                 +        return long_url +   + +    def get_file_name(self): +        if self.html is None: +            self.download_html() + +        file_name_pattern = r"<title>(.*?) - xHamster\.com</title>" +        file_name = re.search(file_name_pattern, self.html) +        if file_name is None: +            file_name_pattern = r"<h1 >(.*)</h1>" +            file_name = re.search(file_name_pattern, self.html) +            if file_name is None: +                file_name_pattern = r"http://[www.]+xhamster\.com/movies/.*/(.*?)\.html?" +                file_name = re.search(file_name_pattern, self.pyfile.url) +                if file_name is None: +                    file_name_pattern = r"<div id=\"element_str_id\" style=\"display:none;\">(.*)</div>" +                    file_name = re.search(file_name_pattern, self.html) +                    if file_name is None: +                        return "Unknown" + +        return file_name.group(1) + +    def file_exists(self): +        """ returns True or False +        """ +        if self.html is None: +            self.download_html() +        if re.search(r"(.*Video not found.*)", self.html) is not None: +            return False +        else: +            return True diff --git a/pyload/plugins/hoster/XVideosCom.py b/pyload/plugins/hoster/XVideosCom.py new file mode 100644 index 000000000..b7f3f7b58 --- /dev/null +++ b/pyload/plugins/hoster/XVideosCom.py @@ -0,0 +1,19 @@ + +import re +import urllib + +from module.plugins.Hoster import Hoster + +class XVideosCom(Hoster): +    __name__ = "XVideos.com" +    __version__ = "0.1" +    __pattern__ = r"http://www\.xvideos\.com/video([0-9]+)/.*" +    __config__ = [] + +    def process(self, pyfile): +        site = self.load(pyfile.url) +        pyfile.name = "%s (%s).flv" %( +            re.search(r"<h2>([^<]+)<span", site).group(1), +            re.search(self.__pattern__, pyfile.url).group(1), +        ) +        self.download(urllib.unquote(re.search(r"flv_url=([^&]+)&", site).group(1))) diff --git a/pyload/plugins/hoster/Xdcc.py b/pyload/plugins/hoster/Xdcc.py new file mode 100644 index 000000000..d0630bd29 --- /dev/null +++ b/pyload/plugins/hoster/Xdcc.py @@ -0,0 +1,229 @@ +# -*- 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 +""" + +from os.path import join +from os.path import exists +from os import makedirs +import re +import sys +import time +import socket, struct +from select import select +from module.utils import save_join + +from module.plugins.Hoster import Hoster + + +class Xdcc(Hoster): +    __name__ = "Xdcc" +    __version__ = "0.32" +    __pattern__ = r'xdcc://.*?(/#?.*?)?/.*?/#?\d+/?' # xdcc://irc.Abjects.net/#channel/[XDCC]|Shit/#0004/ +    __type__ = "hoster" +    __config__ = [ +                    ("nick", "str", "Nickname", "pyload"), +                    ("ident", "str", "Ident", "pyloadident"), +                    ("realname", "str", "Realname", "pyloadreal") +                 ] +    __description__ = """A Plugin that allows you to download from an IRC XDCC bot""" +    __author_name__ = ("jeix") +    __author_mail__ = ("jeix@hasnomail.com") +     +    def setup(self): +        self.debug   = 0  #0,1,2 +        self.timeout = 30 +        self.multiDL = False +         +         +     +    def process(self, pyfile): +        # change request type +        self.req = pyfile.m.core.requestFactory.getRequest(self.__name__, type="XDCC") +     +        self.pyfile = pyfile +        for i in range(0,3): +            try: +                nmn = self.doDownload(pyfile.url) +                self.logDebug("%s: Download of %s finished." % (self.__name__, nmn)) +                return +            except socket.error, e: +                if hasattr(e, "errno"): +                    errno = e.errno +                else: +                    errno = e.args[0] +                     +                if errno in (10054,): +                    self.logDebug("XDCC: Server blocked our ip, retry in 5 min") +                    self.setWait(300) +                    self.wait() +                    continue                     + +                self.fail("Failed due to socket errors. Code: %d" % errno) +                 +        self.fail("Server blocked our ip, retry again later manually") + + +    def doDownload(self, url): +        self.pyfile.setStatus("waiting") # real link + +        download_folder = self.config['general']['download_folder'] +        location = join(download_folder, self.pyfile.package().folder.decode(sys.getfilesystemencoding())) +        if not exists(location):  +            makedirs(location) +             +        m = re.search(r'xdcc://(.*?)/#?(.*?)/(.*?)/#?(\d+)/?', url) +        server = m.group(1) +        chan   = m.group(2) +        bot    = m.group(3) +        pack   = m.group(4) +        nick   = self.getConfig('nick') +        ident  = self.getConfig('ident') +        real   = self.getConfig('realname') +         +        temp = server.split(':') +        ln = len(temp) +        if ln == 2: +            host, port = temp +        elif ln == 1: +            host, port = temp[0], 6667 +        else: +            self.fail("Invalid hostname for IRC Server (%s)" % server) +         +         +        ####################### +        # CONNECT TO IRC AND IDLE FOR REAL LINK +        dl_time = time.time() +         +        sock = socket.socket() +        sock.connect((host, int(port))) +        if nick == "pyload": +            nick = "pyload-%d" % (time.time() % 1000) # last 3 digits +        sock.send("NICK %s\r\n" % nick) +        sock.send("USER %s %s bla :%s\r\n" % (ident, host, real)) +        time.sleep(3) +        sock.send("JOIN #%s\r\n" % chan) +        sock.send("PRIVMSG %s :xdcc send #%s\r\n" % (bot, pack)) +         +        # IRC recv loop +        readbuffer = "" +        done = False +        retry = None +        m = None +        while True: + +            # done is set if we got our real link +            if done: +                break +         +            if retry: +                if time.time() > retry: +                    retry = None +                    dl_time = time.time() +                    sock.send("PRIVMSG %s :xdcc send #%s\r\n" % (bot, pack)) + +            else: +                if (dl_time + self.timeout) < time.time(): # todo: add in config +                    sock.send("QUIT :byebye\r\n") +                    sock.close() +                    self.fail("XDCC Bot did not answer") + + +            fdset = select([sock], [], [], 0) +            if sock not in fdset[0]: +                continue +                 +            readbuffer += sock.recv(1024) +            temp = readbuffer.split("\n") +            readbuffer = temp.pop() + +            for line in temp: +                if self.debug is 2: print "*> " + unicode(line, errors='ignore') +                line  = line.rstrip() +                first = line.split() + +                if first[0] == "PING": +                    sock.send("PONG %s\r\n" % first[1]) +                     +                if first[0] == "ERROR": +                    self.fail("IRC-Error: %s" % line) +                     +                msg = line.split(None, 3) +                if len(msg) != 4: +                    continue +                     +                msg = { \ +                    "origin":msg[0][1:], \ +                    "action":msg[1], \ +                    "target":msg[2], \ +                    "text"  :msg[3][1:] \ +                } + + +                if nick == msg["target"][0:len(nick)] and "PRIVMSG" == msg["action"]: +                    if msg["text"] == "\x01VERSION\x01": +                        self.logDebug("XDCC: Sending CTCP VERSION.") +                        sock.send("NOTICE %s :%s\r\n" % (msg['origin'], "pyLoad! IRC Interface")) +                    elif msg["text"] == "\x01TIME\x01": +                        self.logDebug("Sending CTCP TIME.") +                        sock.send("NOTICE %s :%d\r\n" % (msg['origin'], time.time())) +                    elif msg["text"] == "\x01LAG\x01": +                        pass # don't know how to answer +                 +                if not (bot == msg["origin"][0:len(bot)]  +                    and nick == msg["target"][0:len(nick)]  +                    and msg["action"] in ("PRIVMSG", "NOTICE")): +                    continue +                     +                if self.debug is 1: +                    print "%s: %s" % (msg["origin"], msg["text"]) +                     +                if "You already requested that pack" in msg["text"]: +                    retry = time.time() + 300 +                     +                if "you must be on a known channel to request a pack" in msg["text"]: +                    self.fail("Wrong channel") +             +                m = re.match('\x01DCC SEND (.*?) (\d+) (\d+)(?: (\d+))?\x01', msg["text"]) +                if m: +                    done = True +                 +        # get connection data +        ip       = socket.inet_ntoa(struct.pack('L', socket.ntohl(int(m.group(2))))) +        port     = int(m.group(3))         +        packname = m.group(1) +         +        if len(m.groups()) > 3: +            self.req.filesize = int(m.group(4)) +             +        self.pyfile.name = packname +        filename = save_join(location, packname) +        self.logInfo("XDCC: Downloading %s from %s:%d" % (packname, ip, port)) + +        self.pyfile.setStatus("downloading") +        newname = self.req.download(ip, port, filename, sock, self.pyfile.setProgress) +        if newname and newname != filename: +            self.logInfo("%(name)s saved as %(newname)s" % {"name": self.pyfile.name, "newname": newname}) +            filename = newname +         +        # kill IRC socket +        # sock.send("QUIT :byebye\r\n") +        sock.close() + +        self.lastDownload = filename +        return self.lastDownload +         diff --git a/pyload/plugins/hoster/YibaishiwuCom.py b/pyload/plugins/hoster/YibaishiwuCom.py new file mode 100644 index 000000000..901225944 --- /dev/null +++ b/pyload/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.12" +    __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) +                self.download(url) +                break +            except: +                continue +        else: self.fail('No working link found') + +getInfo = create_getInfo(YibaishiwuCom) diff --git a/pyload/plugins/hoster/YoupornCom.py b/pyload/plugins/hoster/YoupornCom.py new file mode 100644 index 000000000..b17a4ef80 --- /dev/null +++ b/pyload/plugins/hoster/YoupornCom.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import re +from module.plugins.Hoster import Hoster + +class YoupornCom(Hoster): +    __name__ = "YoupornCom" +    __type__ = "hoster" +    __pattern__ = r"http://(www\.)?youporn\.com/watch/.+" +    __version__ = "0.2" +    __description__ = """Youporn.com Video Download Hoster""" +    __author_name__ = ("willnix") +    __author_mail__ = ("willnix@pyload.org") + +    def setup(self): +        self.html = None +         +    def process(self, pyfile): +        self.pyfile = pyfile +         +        if not self.file_exists(): +            self.offline() +             +        self.pyfile.name = self.get_file_name() +        self.download(self.get_file_url()) + +    def download_html(self): +        url = self.pyfile.url +        self.html = self.load(url, post={"user_choice":"Enter"}, cookies=False) + +    def get_file_url(self): +        """ returns the absolute downloadable filepath +        """ +        if self.html is None: +            self.download_html() + +        file_url = re.search(r'(http://download\.youporn\.com/download/\d+\?save=1)">', self.html).group(1) +        return file_url + +    def get_file_name(self): +        if self.html is None: +            self.download_html() + +        file_name_pattern = r"<title>(.*) - Free Porn Videos - YouPorn</title>" +        return re.search(file_name_pattern, self.html).group(1).replace("&", "&").replace("/","") + '.flv' + +    def file_exists(self): +        """ returns True or False +        """ +        if self.html is None: +            self.download_html() +        if re.search(r"(.*invalid video_id.*)", self.html) is not None: +            return False +        else: +            return True diff --git a/pyload/plugins/hoster/YourfilesTo.py b/pyload/plugins/hoster/YourfilesTo.py new file mode 100644 index 000000000..4a192b32a --- /dev/null +++ b/pyload/plugins/hoster/YourfilesTo.py @@ -0,0 +1,83 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import re +import urllib +from module.plugins.Hoster import Hoster + +class YourfilesTo(Hoster): +    __name__ = "YourfilesTo" +    __type__ = "hoster" +    __pattern__ = r"(http://)?(www\.)?yourfiles\.(to|biz)/\?d=[a-zA-Z0-9]+" +    __version__ = "0.21" +    __description__ = """Youfiles.to Download Hoster""" +    __author_name__ = ("jeix", "skydancer") +    __author_mail__ = ("jeix@hasnomail.de", "skydancer@hasnomail.de") + +    def setup(self): +        self.html = None +        self.multiDL = True + +    def process(self,pyfile): +        self.pyfile = pyfile +        self.prepare() +        self.download(self.get_file_url()) +     +    def prepare(self): +        if not self.file_exists(): +            self.offline() + +        self.pyfile.name = self.get_file_name() +         +        wait_time = self.get_waiting_time() +        self.setWait(wait_time) +        self.logDebug("%s: Waiting %d seconds." % (self.__name__,wait_time)) +        self.wait() + +    def get_waiting_time(self): +        if self.html is None: +            self.download_html() +             +        #var zzipitime = 15; +        m = re.search(r'var zzipitime = (\d+);', self.html) +        if m: +            sec = int(m.group(1)) +        else: +            sec = 0 +             +        return sec +         +    def download_html(self): +        url = self.pyfile.url +        self.html = self.load(url) + +    def get_file_url(self): +        """ returns the absolute downloadable filepath +        """ +        url = re.search(r"var bla = '(.*?)';", self.html) +        if url: +            url = url.group(1) +            url = urllib.unquote(url.replace("http://http:/http://", "http://").replace("dumdidum", "")) +            return url +        else: +            self.fail("absolute filepath could not be found. offline? ") +        +    def get_file_name(self): +        if self.html is None: +            self.download_html() + +        return re.search("<title>(.*)</title>", self.html).group(1) + +    def file_exists(self): +        """ returns True or False +        """ +        if self.html is None: +            self.download_html() +             +        if re.search(r"HTTP Status 404", self.html) is not None: +            return False +        else: +            return True + +         + diff --git a/pyload/plugins/hoster/YoutubeCom.py b/pyload/plugins/hoster/YoutubeCom.py new file mode 100644 index 000000000..129b948bf --- /dev/null +++ b/pyload/plugins/hoster/YoutubeCom.py @@ -0,0 +1,164 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import re +import subprocess +import os +import os.path +from urllib import unquote + +from module.utils import html_unescape +from module.plugins.Hoster import Hoster + +def which(program): +    """Works exactly like the unix command which + +    Courtesy of http://stackoverflow.com/a/377028/675646""" +    def is_exe(fpath): +        return os.path.isfile(fpath) and os.access(fpath, os.X_OK) + +    fpath, fname = os.path.split(program) +    if fpath: +        if is_exe(program): +            return program +    else: +        for path in os.environ["PATH"].split(os.pathsep): +            path = path.strip('"') +            exe_file = os.path.join(path, program) +            if is_exe(exe_file): +                return exe_file + +    return None + +class YoutubeCom(Hoster): +    __name__ = "YoutubeCom" +    __type__ = "hoster" +    __pattern__ = r"https?://(?:[^/]*?)youtube\.com/watch.*?[?&]v=.*" +    __version__ = "0.34" +    __config__ = [("quality", "sd;hd;fullhd;240p;360p;480p;720p;1080p;3072p", "Quality Setting", "hd"), +        ("fmt", "int", "FMT/ITAG Number (5-102, 0 for auto)", 0), +        (".mp4", "bool", "Allow .mp4", True), +        (".flv", "bool", "Allow .flv", True), +        (".webm", "bool", "Allow .webm", False), +        (".3gp", "bool", "Allow .3gp", False), +        ("3d", "bool", "Prefer 3D", False)] +    __description__ = """Youtube.com Video Download Hoster""" +    __author_name__ = ("spoob", "zoidberg") +    __author_mail__ = ("spoob@pyload.org", "zoidberg@mujmail.cz") + +    # name, width, height, quality ranking, 3D +    formats = {5: (".flv", 400, 240, 1, False), +                6: (".flv", 640, 400, 4, False), +               17: (".3gp", 176, 144, 0, False), +               18: (".mp4", 480, 360, 2, False), +               22: (".mp4", 1280, 720, 8, False), +               43: (".webm", 640, 360, 3, False), +               34: (".flv", 640, 360, 4, False), +               35: (".flv", 854, 480, 6, False), +                36: (".3gp", 400, 240, 1, False), +               37: (".mp4", 1920, 1080, 9, False), +               38: (".mp4", 4096, 3072, 10, False), +               44: (".webm", 854, 480, 5, False), +               45: (".webm", 1280, 720, 7, False), +                46: (".webm", 1920, 1080, 9, False), +                82: (".mp4", 640, 360, 3, True), +                83: (".mp4", 400, 240, 1, True), +                84: (".mp4", 1280, 720, 8, True), +                85: (".mp4", 1920, 1080, 9, True), +                100: (".webm", 640, 360, 3, True), +                101: (".webm", 640, 360, 4, True), +                102: (".webm", 1280, 720, 8, True) +               } + +    def setup(self): +        self.resumeDownload = self.multiDL = True + +    def process(self, pyfile): +        html = self.load(pyfile.url, decode=True) + +        if re.search(r'<div id="player-unavailable" class="\s*player-width player-height\s*">', html): +            self.offline() + +        if "We have been receiving a large volume of requests from your network." in html: +            self.tempOffline() + +        #get config +        use3d = self.getConfig("3d") +        if use3d: +            quality = {"sd":82,"hd":84,"fullhd":85,"240p":83,"360p":82,"480p":82,"720p":84,"1080p":85,"3072p":85} +        else: +            quality = {"sd":18,"hd":22,"fullhd":37,"240p":5,"360p":18,"480p":35,"720p":22,"1080p":37,"3072p":38} +        desired_fmt = self.getConfig("fmt") +        if desired_fmt and desired_fmt not in self.formats: +            self.logWarning("FMT %d unknown - using default." % desired_fmt) +            desired_fmt = 0 +        if not desired_fmt: +            desired_fmt = quality.get(self.getConfig("quality"), 18) + +        #parse available streams +        streams = re.search(r'"url_encoded_fmt_stream_map": "(.*?)",', html).group(1) +        streams = [x.split('\u0026') for x in streams.split(',')] +        streams = [dict((y.split('=',1)) for y in x) for x in streams] +        streams = [(int(x['itag']), "%s&signature=%s" % (unquote(x['url']), x['sig'])) for x in streams] +        #self.logDebug("Found links: %s" % streams) +        self.logDebug("AVAILABLE STREAMS: %s" % [x[0] for x in streams]) + +        #build dictionary of supported itags (3D/2D) +        allowed = lambda x: self.getConfig(self.formats[x][0]) +        streams = [x for x in streams if x[0] in self.formats and allowed(x[0])] +        if not streams: +            self.fail("No available stream meets your preferences") +        fmt_dict = dict([x for x in streams if self.formats[x[0]][4] == use3d] or streams) + +        self.logDebug("DESIRED STREAM: ITAG:%d (%s) %sfound, %sallowed" % +                          (desired_fmt, +                           "%s %dx%d Q:%d 3D:%s" % self.formats[desired_fmt], +                           "" if desired_fmt in fmt_dict else "NOT ", +                           "" if allowed(desired_fmt) else "NOT ") +                      ) + +        #return fmt nearest to quality index +        if desired_fmt in fmt_dict and allowed(desired_fmt): +            fmt = desired_fmt +        else: +            sel = lambda x: self.formats[x][3] #select quality index +            comp = lambda x, y: abs(sel(x) - sel(y)) + +            self.logDebug("Choosing nearest fmt: %s" % [(x, allowed(x), comp(x, desired_fmt)) for x in fmt_dict.keys()]) +            fmt = reduce(lambda x, y: x if comp(x, desired_fmt) <= comp(y, desired_fmt) and +                                       sel(x) > sel(y) else y, fmt_dict.keys()) + +        self.logDebug("Chosen fmt: %s" % fmt) +        url = fmt_dict[fmt] +        self.logDebug("URL: %s" % url) + +        #set file name +        file_suffix = self.formats[fmt][0] if fmt in self.formats else ".flv" +        file_name_pattern = '<meta name="title" content="(.+?)">' +        name = re.search(file_name_pattern, html).group(1).replace("/", "") +        pyfile.name = html_unescape(name) + +        time = re.search(r"t=((\d+)m)?(\d+)s", pyfile.url) +        ffmpeg = which("ffmpeg") +        if ffmpeg and time: +            m, s = time.groups()[1:] +            if not m: +                m = "0" + +            pyfile.name += " (starting at %s:%s)" % (m, s) +        pyfile.name += file_suffix + +        filename = self.download(url) + +        if ffmpeg and time: +            inputfile = filename + "_" +            os.rename(filename, inputfile) + +            subprocess.call([ +                ffmpeg, +                "-ss", "00:%s:%s" % (m, s), +                "-i", inputfile, +                "-vcodec", "copy", +                "-acodec", "copy", +                filename]) +            os.remove(inputfile) diff --git a/pyload/plugins/hoster/ZDF.py b/pyload/plugins/hoster/ZDF.py new file mode 100644 index 000000000..ea45f4fd8 --- /dev/null +++ b/pyload/plugins/hoster/ZDF.py @@ -0,0 +1,46 @@ + +import re +from xml.etree.ElementTree import fromstring + +from module.plugins.Hoster import Hoster + +XML_API = "http://www.zdf.de/ZDFmediathek/xmlservice/web/beitragsDetails?id=%i" + +class ZDF(Hoster): +    # Based on zdfm by Roland Beermann +    # http://github.com/enkore/zdfm/ +    __name__ = "ZDF Mediathek" +    __version__ = "0.7" +    __pattern__ = r"http://www\.zdf\.de/ZDFmediathek/[^0-9]*([0-9]+)[^0-9]*" +    __config__ = [] + +    @staticmethod +    def video_key(video): +        return ( +            int(video.findtext("videoBitrate", "0")), +            any(f.text == "progressive" for f in video.iter("facet")), +        ) + +    @staticmethod +    def video_valid(video): +        return (video.findtext("url").startswith("http") and video.findtext("url").endswith(".mp4")) + +    @staticmethod +    def get_id(url): +        return int(re.search(r"[^0-9]*([0-9]+)[^0-9]*", url).group(1)) + +    def process(self, pyfile): +        xml = fromstring(self.load(XML_API % self.get_id(pyfile.url))) + +        status = xml.findtext("./status/statuscode") +        if status != "ok": +            self.fail("Error retrieving manifest.") + +        video = xml.find("video") +        title = video.findtext("information/title") + +        pyfile.name = title +         +        target_url = sorted((v for v in video.iter("formitaet") if self.video_valid(v)), key=self.video_key)[-1].findtext("url") + +        self.download(target_url) diff --git a/pyload/plugins/hoster/ZeveraCom.py b/pyload/plugins/hoster/ZeveraCom.py new file mode 100644 index 000000000..92f9e4dcd --- /dev/null +++ b/pyload/plugins/hoster/ZeveraCom.py @@ -0,0 +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.21" +    __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 %s account or deactivate this plugin") % "zevera.com") +            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/pyload/plugins/hoster/ZippyshareCom.py b/pyload/plugins/hoster/ZippyshareCom.py new file mode 100644 index 000000000..e130be24c --- /dev/null +++ b/pyload/plugins/hoster/ZippyshareCom.py @@ -0,0 +1,192 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import re, subprocess, tempfile, os +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo, timestamp +from module.plugins.internal.CaptchaService import ReCaptcha +from module.common.json_layer import json_loads + +class ZippyshareCom(SimpleHoster): +    __name__ = "ZippyshareCom" +    __type__ = "hoster" +    __pattern__ = r"(?P<HOST>http://www\d{0,2}\.zippyshare.com)/v(?:/|iew.jsp.*key=)(?P<KEY>\d+)" +    __version__ = "0.38" +    __description__ = """Zippyshare.com Download Hoster""" +    __author_name__ = ("spoob", "zoidberg", "stickell") +    __author_mail__ = ("spoob@pyload.org", "zoidberg@mujmail.cz", "l.stickell@yahoo.it") +    __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_INFO_PATTERN = r'document\.getElementById\(\'dlbutton\'\)\.href = "[^;]*/(?P<N>[^"]+)";' +    FILE_OFFLINE_PATTERN = r'>File does not exist on this server</div>' + +    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):  +        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 +        """ +        url = multiply = modulo = None + +        found = re.search(self.DOWNLOAD_URL_PATTERN, self.html, re.S) +        if found: +            #Method #1: JS eval +            js = "\n".join(found.groups()) +            regex = r"document.getElementById\(\\*'dlbutton\\*'\).omg" +            omg = re.search(regex + r" = ([^;]+);", js).group(1) +            js = re.sub(regex + r" = ([^;]+);", '', js) +            js = re.sub(regex, omg, js) +            url = self.js.eval(js) +        else: +            #Method #2: SWF eval +            seed_search = re.search(self.SEED_PATTERN, self.html) +            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) +             +        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 url                + +getInfo = create_getInfo(ZippyshareCom)
\ No newline at end of file diff --git a/pyload/plugins/hoster/__init__.py b/pyload/plugins/hoster/__init__.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/pyload/plugins/hoster/__init__.py  | 
