diff options
Diffstat (limited to 'pyload/plugins/hoster/DlFreeFr.py')
-rw-r--r-- | pyload/plugins/hoster/DlFreeFr.py | 212 |
1 files changed, 212 insertions, 0 deletions
diff --git a/pyload/plugins/hoster/DlFreeFr.py b/pyload/plugins/hoster/DlFreeFr.py new file mode 100644 index 000000000..4440c5370 --- /dev/null +++ b/pyload/plugins/hoster/DlFreeFr.py @@ -0,0 +1,212 @@ +# -*- coding: utf-8 -*- + +import pycurl +import re + +from pyload.utils import json_loads +from pyload.network.Browser import Browser +from pyload.network.CookieJar import CookieJar +from pyload.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo, replace_patterns + + +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 and 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 AdYouLike: + """ + Class to support adyoulike captcha service + """ + 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 + m = re.search(self.ADYOULIKE_INPUT_PATTERN, html) + if m: + adyoulike_data_string = m.group(1) + else: + self.plugin.fail("Can't read AdYouLike input data") + + # {"adyoulike":{"key":"P~zQ~O0zV0WTiAzC-iw0navWQpCLoYEP"}, + # "all":{"element_id":"ayl_private_cap_92300","lang":"fr","env":"prod"}} + ayl_data = json_loads(adyoulike_data_string) + + 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}) + + m = re.search(self.ADYOULIKE_CHALLENGE_PATTERN, res) + challenge_string = None + if m: + challenge_string = m.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'] + m = re.search(u".*«(.*)».*", instructions_visual) + if m: + response = m.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" + __version__ = "0.25" + + __pattern__ = r'http://(?:www\.)?dl\.free\.fr/([a-zA-Z0-9]+|getfile\.pl\?file=/[a-zA-Z0-9]+)' + + __description__ = """Dl.free.fr hoster plugin""" + __authors__ = [("the-razer", "daniel_ AT gmx DOT net"), + ("zoidberg", "zoidberg@mujmail.cz"), + ("Toilal", "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' + OFFLINE_PATTERN = r"Erreur 404 - Document non trouv|Fichier inexistant|Le fichier demandé n'a pas été trouvé" + + + def setup(self): + self.multiDL = self.resumeDownload = True + self.limitDL = 5 + self.chunkLimit = 1 + + + def init(self): + factory = self.core.requestFactory + self.req = CustomBrowser(factory.bucket, factory.getOptions()) + + + def process(self, pyfile): + 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 "set-cookie" in headers and "location" in headers: + m = re.search("(.*?)=(.*?); path=(.*?); domain=(.*?)", headers.get("set-cookie")) + cj = CookieJar(__name__) + if m: + cj.setCookie(m.group(4), m.group(1), m.group(2), m.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) |