1 | """ |
---|
2 | urlresolver XBMC Addon |
---|
3 | Copyright (C) 2014 tknorris |
---|
4 | |
---|
5 | This program is free software: you can redistribute it and/or modify |
---|
6 | it under the terms of the GNU General Public License as published by |
---|
7 | the Free Software Foundation, either version 3 of the License, or |
---|
8 | (at your option) any later version. |
---|
9 | |
---|
10 | This program is distributed in the hope that it will be useful, |
---|
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
13 | GNU General Public License for more details. |
---|
14 | |
---|
15 | You should have received a copy of the GNU General Public License |
---|
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. |
---|
17 | |
---|
18 | reusable captcha methods |
---|
19 | """ |
---|
20 | from urlresolver import common |
---|
21 | import re |
---|
22 | import xbmcgui |
---|
23 | import xbmc |
---|
24 | import os |
---|
25 | import recaptcha_v2 |
---|
26 | import helpers |
---|
27 | |
---|
28 | net = common.Net() |
---|
29 | IMG_FILE = 'captcha_img.gif' |
---|
30 | |
---|
31 | def get_response(img): |
---|
32 | try: |
---|
33 | img = xbmcgui.ControlImage(450, 0, 400, 130, img) |
---|
34 | wdlg = xbmcgui.WindowDialog() |
---|
35 | wdlg.addControl(img) |
---|
36 | wdlg.show() |
---|
37 | xbmc.sleep(3000) |
---|
38 | kb = xbmc.Keyboard('', 'Type the letters in the image', False) |
---|
39 | kb.doModal() |
---|
40 | if (kb.isConfirmed()): |
---|
41 | solution = kb.getText() |
---|
42 | if solution == '': |
---|
43 | raise Exception('You must enter text in the image to access video') |
---|
44 | else: |
---|
45 | return solution |
---|
46 | else: |
---|
47 | raise Exception('Captcha Error') |
---|
48 | finally: |
---|
49 | wdlg.close() |
---|
50 | |
---|
51 | def do_captcha(html): |
---|
52 | solvemedia = re.search('<iframe[^>]+src="((?:https?:)?//api.solvemedia.com[^"]+)', html) |
---|
53 | recaptcha = re.search('<script\s+type="text/javascript"\s+src="(http://www.google.com[^"]+)', html) |
---|
54 | recaptcha_v2 = re.search('data-sitekey="([^"]+)', html) |
---|
55 | xfilecaptcha = re.search('<img\s+src="([^"]+/captchas/[^"]+)', html) |
---|
56 | |
---|
57 | if solvemedia: |
---|
58 | return do_solvemedia_captcha(solvemedia.group(1)) |
---|
59 | elif recaptcha: |
---|
60 | return do_recaptcha(recaptcha.group(1)) |
---|
61 | elif recaptcha_v2: |
---|
62 | return do_recaptcha_v2(recaptcha_v2.group(1)) |
---|
63 | elif xfilecaptcha: |
---|
64 | return do_xfilecaptcha(xfilecaptcha.group(1)) |
---|
65 | else: |
---|
66 | captcha = re.compile("left:(\d+)px;padding-top:\d+px;'>&#(.+?);<").findall(html) |
---|
67 | result = sorted(captcha, key=lambda ltr: int(ltr[0])) |
---|
68 | solution = ''.join(str(int(num[1]) - 48) for num in result) |
---|
69 | if solution: |
---|
70 | return {'code': solution} |
---|
71 | else: |
---|
72 | return {} |
---|
73 | |
---|
74 | def do_solvemedia_captcha(captcha_url): |
---|
75 | common.log_utils.log_debug('SolveMedia Captcha: %s' % (captcha_url)) |
---|
76 | if captcha_url.startswith('//'): captcha_url = 'http:' + captcha_url |
---|
77 | html = net.http_GET(captcha_url).content |
---|
78 | data = { |
---|
79 | 'adcopy_challenge': '' # set to blank just in case not found; avoids exception on return |
---|
80 | } |
---|
81 | data.update(helpers.get_hidden(html)) |
---|
82 | captcha_img = os.path.join(common.profile_path, IMG_FILE) |
---|
83 | try: os.remove(captcha_img) |
---|
84 | except: pass |
---|
85 | |
---|
86 | # Check for alternate puzzle type - stored in a div |
---|
87 | alt_frame = re.search('<div><iframe src="(/papi/media[^"]+)', html) |
---|
88 | if alt_frame: |
---|
89 | html = net.http_GET("http://api.solvemedia.com%s" % alt_frame.group(1)).content |
---|
90 | alt_puzzle = re.search('<div\s+id="typein">\s*<img\s+src="data:image/png;base64,([^"]+)', html, re.DOTALL) |
---|
91 | if alt_puzzle: |
---|
92 | open(captcha_img, 'wb').write(alt_puzzle.group(1).decode('base64')) |
---|
93 | else: |
---|
94 | open(captcha_img, 'wb').write(net.http_GET("http://api.solvemedia.com%s" % re.search('<img src="(/papi/media[^"]+)"', html).group(1)).content) |
---|
95 | |
---|
96 | solution = get_response(captcha_img) |
---|
97 | data['adcopy_response'] = solution |
---|
98 | html = net.http_POST('http://api.solvemedia.com/papi/verify.noscript', data) |
---|
99 | return {'adcopy_challenge': data['adcopy_challenge'], 'adcopy_response': 'manual_challenge'} |
---|
100 | |
---|
101 | def do_recaptcha(captcha_url): |
---|
102 | common.log_utils.log_debug('Google ReCaptcha: %s' % (captcha_url)) |
---|
103 | if captcha_url.startswith('//'): captcha_url = 'http:' + captcha_url |
---|
104 | personal_nid = common.get_setting('personal_nid') |
---|
105 | if personal_nid: |
---|
106 | headers = {'Cookie': 'NID=' + personal_nid} |
---|
107 | else: |
---|
108 | headers = {} |
---|
109 | html = net.http_GET(captcha_url, headers=headers).content |
---|
110 | part = re.search("challenge \: \\'(.+?)\\'", html) |
---|
111 | captcha_img = 'http://www.google.com/recaptcha/api/image?c=' + part.group(1) |
---|
112 | solution = get_response(captcha_img) |
---|
113 | return {'recaptcha_challenge_field': part.group(1), 'recaptcha_response_field': solution} |
---|
114 | |
---|
115 | def do_recaptcha_v2(sitekey): |
---|
116 | token = recaptcha_v2.UnCaptchaReCaptcha().processCaptcha(sitekey, lang='en') |
---|
117 | if token: |
---|
118 | return {'g-recaptcha-response': token} |
---|
119 | |
---|
120 | return {} |
---|
121 | def do_xfilecaptcha(captcha_url): |
---|
122 | common.log_utils.log_debug('XFileLoad ReCaptcha: %s' % (captcha_url)) |
---|
123 | if captcha_url.startswith('//'): captcha_url = 'http:' + captcha_url |
---|
124 | solution = get_response(captcha_url) |
---|
125 | return {'code': solution} |
---|