diff options
Diffstat (limited to 'module/plugins/internal/CaptchaService.py')
-rw-r--r-- | module/plugins/internal/CaptchaService.py | 233 |
1 files changed, 176 insertions, 57 deletions
diff --git a/module/plugins/internal/CaptchaService.py b/module/plugins/internal/CaptchaService.py index b429fd6e0..c6e83fe7d 100644 --- a/module/plugins/internal/CaptchaService.py +++ b/module/plugins/internal/CaptchaService.py @@ -1,24 +1,24 @@ # -*- coding: utf-8 -*- import re +import time -from base64 import urlsafe_b64encode -from random import random +from base64 import b64encode +from random import random, randint +from urlparse import urljoin, urlparse from module.common.json_layer import json_loads class CaptchaService: __name__ = "CaptchaService" - __version__ = "0.16" + __version__ = "0.20" __description__ = """Base captcha service plugin""" __license__ = "GPLv3" __authors__ = [("pyLoad Team", "admin@pyload.org")] - KEY_PATTERN = None - key = None #: last key detected @@ -27,25 +27,10 @@ class CaptchaService: def detect_key(self, html=None): - if not html: - if hasattr(self.plugin, "html") and self.plugin.html: - html = self.plugin.html - else: - errmsg = _("%s html not found") % self.__name__ - self.plugin.fail(errmsg) #@TODO: replace all plugin.fail(errmsg) with plugin.error(errmsg) in 0.4.10 - raise TypeError(errmsg) - - m = re.search(self.KEY_PATTERN, html) - if m: - self.key = m.group(1).strip() - self.plugin.logDebug("%s key: %s" % (self.__name__, self.key)) - return self.key - else: - self.plugin.logDebug("%s key not found" % self.__name__) - return None + raise NotImplementedError - def challenge(self, key=None): + def challenge(self, key=None, html=None): raise NotImplementedError @@ -55,15 +40,17 @@ class CaptchaService: class ReCaptcha(CaptchaService): __name__ = "ReCaptcha" - __version__ = "0.09" + __version__ = "0.11" __description__ = """ReCaptcha captcha service plugin""" __license__ = "GPLv3" - __authors__ = [("pyLoad Team", "admin@pyload.org")] + __authors__ = [("pyLoad Team", "admin@pyload.org"), + ("Walter Purcaro", "vuolter@gmail.com"), + ("zapp-brannigan", "fuerst.reinje@web.de")] - KEY_PATTERN = r'(?:class="g-recaptcha"\s+data-sitekey="|recaptcha(?:/api|\.net)/(?:challenge|noscript)\?k=)([\w-]+)' - KEY_AJAX_PATTERN = r'Recaptcha\.create\s*\(\s*["\']([\w-]+)' + KEY_V2_PATTERN = r'(?:data-sitekey=["\']|["\']sitekey["\']:\s*["\'])([\w-]+)' + KEY_V1_PATTERN = r'(?:recaptcha(?:/api|\.net)/(?:challenge|noscript)\?k=|Recaptcha\.create\s*\(\s*["\'])([\w-]+)' def detect_key(self, html=None): @@ -75,7 +62,7 @@ class ReCaptcha(CaptchaService): self.plugin.fail(errmsg) raise TypeError(errmsg) - m = re.search(self.KEY_PATTERN, html) or re.search(self.KEY_AJAX_PATTERN, html) + m = re.search(self.KEY_V2_PATTERN, html) or re.search(self.KEY_V1_PATTERN, html) if m: self.key = m.group(1).strip() self.plugin.logDebug("ReCaptcha key: %s" % self.key) @@ -85,9 +72,24 @@ class ReCaptcha(CaptchaService): return None - def challenge(self, key=None, userverify=False): + def challenge(self, key=None, html=None, version=None): + if not html: + if hasattr(self.plugin, "html") and self.plugin.html: + html = self.plugin.html + else: + errmsg = _("ReCaptcha html not found") + self.plugin.fail(errmsg) + raise TypeError(errmsg) + + challenge = "challenge_v%s" % (version if version in (1, 2) else + 2 if re.search(self.KEY_V2_PATTERN, html) else 1) + + return getattr(self, challenge)(key, html) + + + def challenge_v1(self, key=None, html=None): if not key: - if self.detect_key(): + if self.detect_key(html): key = self.key else: errmsg = _("ReCaptcha key not found") @@ -106,22 +108,7 @@ class ReCaptcha(CaptchaService): self.plugin.logDebug("ReCaptcha challenge: %s" % challenge) - response = challenge, self.result(server, challenge) - - return self.userverify(*response) if userverify else response - - - def userverify(self, challenge, result): - response = self.plugin.req.load("https://www.google.com/recaptcha/api2/userverify", - post={'c' : challenge, - 'response': urlsafe_b64encode('{"response":"%s"}' % result)}) - try: - return re.search(r'"uvresp","(.+?)"', response).group(1) - - except AttributeError: - errmsg = _("ReCaptcha userverify response not found") - self.plugin.fail(errmsg) - raise AttributeError(errmsg) + return self.result(server, challenge), challenge def result(self, server, challenge): @@ -136,9 +123,122 @@ class ReCaptcha(CaptchaService): return result + def _collectApiInfo(self): + html = self.plugin.req.load("http://www.google.com/recaptcha/api.js") + a = re.search(r'po.src = \'(.*?)\';', html).group(1) + vers = a.split("/")[5] + + self.plugin.logDebug("ReCaptcha API version: %s" %vers) + + language = a.split("__")[1].split(".")[0] + + self.plugin.logDebug("ReCaptcha API language: %s" % language) + + html = self.plugin.req.load("https://apis.google.com/js/api.js") + b = re.search(r'"h":"(.*?)","', html).group(1) + jsh = b.decode('unicode-escape') + + self.plugin.logDebug("ReCaptcha API jsh-string: %s" % jsh) + + return vers, language, jsh + + + def _prepareTimeAndRpc(self): + self.plugin.req.load("http://www.google.com/recaptcha/api2/demo") + + millis = int(round(time.time() * 1000)) + + self.plugin.logDebug("ReCaptcha time: %s" % millis) + + rand = randint(1, 99999999) + a = "0.%s" % str(rand * 2147483647) + rpc = int(100000000 * float(a)) + + self.plugin.logDebug("ReCaptcha rpc-token: %s" % rpc) + + return millis, rpc + + + def challenge_v2(self, key=None, html=None): + if not key: + if self.detect_key(html): + key = self.key + else: + errmsg = _("ReCaptcha key not found") + self.plugin.fail(errmsg) + raise TypeError(errmsg) + + try: + parent = urljoin("http://", urlparse(self.plugin.pyfile.url).netloc) + + except Exception: + parent = "" + + botguardstring = "!A" + vers, language, jsh = self._collectApiInfo() + millis, rpc = self._prepareTimeAndRpc() + + html = self.plugin.req.load("https://www.google.com/recaptcha/api2/anchor", + get={'k' : key, + 'hl' : language, + 'v' : vers, + 'usegapi' : "1", + 'jsh' : "%s#id=IO_%s" % (jsh, millis), + 'parent' : parent, + 'pfname' : "", + 'rpctoken': rpc}) + + token1 = re.search(r'id="recaptcha-token" value="(.*?)">', html) + self.plugin.logDebug("ReCaptcha token #1: %s" % token1.group(1)) + + html = self.plugin.req.load("https://www.google.com/recaptcha/api2/frame", + get={'c' : token1.group(1), + 'hl' : language, + 'v' : vers, + 'bg' : botguardstring, + 'usegapi': "1", + 'jsh' : jsh}).decode('unicode-escape') + + token2 = re.search(r'"finput","(.*?)",', html) + self.plugin.logDebug("ReCaptcha token #2: %s" % token2.group(1)) + + token3 = re.search(r'."asconf".\s.\s,"(.*?)".', html) + self.plugin.logDebug("ReCaptcha token #3: %s" % token3.group(1)) + + html = self.plugin.req.load("https://www.google.com/recaptcha/api2/reload", + post={'c' : token2.group(1), + 'reason': "fi", + 'fbg' : token3.group(1)}) + + token4 = re.search(r'"rresp","(.*?)",', html) + self.plugin.logDebug("ReCaptcha token #4: %s" % token4.group(1)) + + millis_captcha_loading = int(round(time.time() * 1000)) + captcha_response = self.plugin.decryptCaptcha("https://www.google.com/recaptcha/api2/payload", + get={'c':token4.group(1)}, forceUser=True) + response = b64encode('{"response":"%s"}' % captcha_response) + + self.plugin.logDebug("ReCaptcha result: %s" % response) + + timeToSolve = int(round(time.time() * 1000)) - millis_captcha_loading + timeToSolveMore = timeToSolve + int(float("0." + str(randint(1, 99999999))) * 500) + + html = self.plugin.req.load("https://www.google.com/recaptcha/api2/userverify", + post={'c' : token4.group(1), + 'response': response, + 't' : timeToSolve, + 'ct' : timeToSolveMore, + 'bg' : botguardstring}) + + token5 = re.search(r'"uvresp","(.*?)",', html) + self.plugin.logDebug("ReCaptcha token #5: %s" % token5.group(1)) + + return token5.group(1), None + + class AdsCaptcha(CaptchaService): __name__ = "AdsCaptcha" - __version__ = "0.06" + __version__ = "0.07" __description__ = """AdsCaptcha captcha service plugin""" __license__ = "GPLv3" @@ -169,9 +269,9 @@ class AdsCaptcha(CaptchaService): return None - def challenge(self, key=None): + def challenge(self, key=None, html=None): if not key: - if self.detect_key(): + if self.detect_key(html): key = self.key else: errmsg = _("AdsCaptcha key not found") @@ -192,7 +292,7 @@ class AdsCaptcha(CaptchaService): self.plugin.logDebug("AdsCaptcha challenge: %s" % challenge) - return challenge, self.result(server, challenge) + return self.result(server, challenge), challenge def result(self, server, challenge): @@ -208,7 +308,7 @@ class AdsCaptcha(CaptchaService): class SolveMedia(CaptchaService): __name__ = "SolveMedia" - __version__ = "0.06" + __version__ = "0.08" __description__ = """SolveMedia captcha service plugin""" __license__ = "GPLv3" @@ -218,9 +318,28 @@ class SolveMedia(CaptchaService): KEY_PATTERN = r'api\.solvemedia\.com/papi/challenge\.(?:no)?script\?k=(.+?)["\']' - def challenge(self, key=None): + def detect_key(self, html=None): + if not html: + if hasattr(self.plugin, "html") and self.plugin.html: + html = self.plugin.html + else: + errmsg = _("SolveMedia html not found") + self.plugin.fail(errmsg) + raise TypeError(errmsg) + + m = re.search(self.KEY_PATTERN, html) + if m: + self.key = m.group(1).strip() + self.plugin.logDebug("SolveMedia key: %s" % self.key) + return self.key + else: + self.plugin.logDebug("SolveMedia key not found") + return None + + + def challenge(self, key=None, html=None): if not key: - if self.detect_key(): + if self.detect_key(html): key = self.key else: errmsg = _("SolveMedia key not found") @@ -240,7 +359,7 @@ class SolveMedia(CaptchaService): self.plugin.logDebug("SolveMedia challenge: %s" % challenge) - return challenge, self.result(server, challenge) + return self.result(server, challenge), challenge def result(self, server, challenge): @@ -253,7 +372,7 @@ class SolveMedia(CaptchaService): class AdYouLike(CaptchaService): __name__ = "AdYouLike" - __version__ = "0.02" + __version__ = "0.04" __description__ = """AdYouLike captcha service plugin""" __license__ = "GPLv3" @@ -284,9 +403,9 @@ class AdYouLike(CaptchaService): return None - def challenge(self, key=None): + def challenge(self, key=None, html=None): if not key: - if self.detect_key(): + if self.detect_key(html): key = self.key else: errmsg = _("AdYouLike key not found") @@ -313,7 +432,7 @@ class AdYouLike(CaptchaService): self.plugin.logDebug("AdYouLike challenge: %s" % challenge) - return self.result(ayl, challenge) + return self.result(ayl, challenge), challenge def result(self, server, challenge): |