1 | # -*- coding: utf-8 -*-
|
---|
2 | """
|
---|
3 | urlresolver XBMC Addon
|
---|
4 | Copyright (C) 2016 tknorris
|
---|
5 | Derived from Shani's LPro Code (https://github.com/Shani-08/ShaniXBMCWork2/blob/master/plugin.video.live.streamspro/unCaptcha.py)
|
---|
6 |
|
---|
7 | This program is free software: you can redistribute it and/or modify
|
---|
8 | it under the terms of the GNU General Public License as published by
|
---|
9 | the Free Software Foundation, either version 3 of the License, or
|
---|
10 | (at your option) any later version.
|
---|
11 |
|
---|
12 | This program is distributed in the hope that it will be useful,
|
---|
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
---|
15 | GNU General Public License for more details.
|
---|
16 |
|
---|
17 | You should have received a copy of the GNU General Public License
|
---|
18 | along with this program. If not, see <http://www.gnu.org/licenses/>.
|
---|
19 |
|
---|
20 | reusable captcha methods
|
---|
21 | """
|
---|
22 | import re
|
---|
23 | import urllib
|
---|
24 | import urllib2
|
---|
25 | import os
|
---|
26 | import xbmcgui
|
---|
27 | from urlresolver import common
|
---|
28 |
|
---|
29 | class cInputWindow(xbmcgui.WindowDialog):
|
---|
30 |
|
---|
31 | def __init__(self, *args, **kwargs):
|
---|
32 | bg_image = os.path.join(common.addon_path, 'resources', 'images', 'DialogBack2.png')
|
---|
33 | check_image = os.path.join(common.addon_path, 'resources', 'images', 'checked.png')
|
---|
34 | self.cancelled = False
|
---|
35 | self.chk = [0] * 9
|
---|
36 | self.chkbutton = [0] * 9
|
---|
37 | self.chkstate = [False] * 9
|
---|
38 |
|
---|
39 | imgX, imgY, imgw, imgh = 436, 210, 408, 300
|
---|
40 | ph, pw = imgh / 3, imgw / 3
|
---|
41 | x_gap = 70
|
---|
42 | y_gap = 70
|
---|
43 | button_gap = 40
|
---|
44 | button_h = 40
|
---|
45 | button_y = imgY + imgh + button_gap
|
---|
46 | middle = imgX + (imgw / 2)
|
---|
47 | win_x = imgX - x_gap
|
---|
48 | win_y = imgY - y_gap
|
---|
49 | win_h = imgh + 2 * y_gap + button_h + button_gap
|
---|
50 | win_w = imgw + 2 * x_gap
|
---|
51 |
|
---|
52 | ctrlBackgound = xbmcgui.ControlImage(win_x, win_y, win_w, win_h, bg_image)
|
---|
53 | self.addControl(ctrlBackgound)
|
---|
54 | self.msg = '[COLOR red]%s[/COLOR]' % (kwargs.get('msg'))
|
---|
55 | self.strActionInfo = xbmcgui.ControlLabel(imgX, imgY - 30, imgw, 20, self.msg, 'font13')
|
---|
56 | self.addControl(self.strActionInfo)
|
---|
57 | img = xbmcgui.ControlImage(imgX, imgY, imgw, imgh, kwargs.get('captcha'))
|
---|
58 | self.addControl(img)
|
---|
59 | self.iteration = kwargs.get('iteration')
|
---|
60 | self.strActionInfo = xbmcgui.ControlLabel(imgX, imgY + imgh, imgw, 20, 'Captcha Round: %s [I](2 Rounds is typical)[/I]' % (str(self.iteration)), 'font40')
|
---|
61 | self.addControl(self.strActionInfo)
|
---|
62 | self.cancelbutton = xbmcgui.ControlButton(middle - 110, button_y, 100, button_h, 'Cancel', alignment=2)
|
---|
63 | self.okbutton = xbmcgui.ControlButton(middle + 10, button_y, 100, button_h, 'OK', alignment=2)
|
---|
64 | self.addControl(self.okbutton)
|
---|
65 | self.addControl(self.cancelbutton)
|
---|
66 |
|
---|
67 | for i in xrange(9):
|
---|
68 | row = i / 3
|
---|
69 | col = i % 3
|
---|
70 | x_pos = imgX + (pw * col)
|
---|
71 | y_pos = imgY + (ph * row)
|
---|
72 | self.chk[i] = xbmcgui.ControlImage(x_pos, y_pos, pw, ph, check_image)
|
---|
73 | self.addControl(self.chk[i])
|
---|
74 | self.chk[i].setVisible(False)
|
---|
75 | self.chkbutton[i] = xbmcgui.ControlButton(x_pos, y_pos, pw, ph, str(i + 1), font='font1')
|
---|
76 | self.addControl(self.chkbutton[i])
|
---|
77 |
|
---|
78 | for i in xrange(9):
|
---|
79 | row_start = (i / 3) * 3
|
---|
80 | right = row_start + (i + 1) % 3
|
---|
81 | left = row_start + (i - 1) % 3
|
---|
82 | up = (i - 3) % 9
|
---|
83 | down = (i + 3) % 9
|
---|
84 | self.chkbutton[i].controlRight(self.chkbutton[right])
|
---|
85 | self.chkbutton[i].controlLeft(self.chkbutton[left])
|
---|
86 | if i <= 2:
|
---|
87 | self.chkbutton[i].controlUp(self.okbutton)
|
---|
88 | else:
|
---|
89 | self.chkbutton[i].controlUp(self.chkbutton[up])
|
---|
90 |
|
---|
91 | if i >= 6:
|
---|
92 | self.chkbutton[i].controlDown(self.okbutton)
|
---|
93 | else:
|
---|
94 | self.chkbutton[i].controlDown(self.chkbutton[down])
|
---|
95 |
|
---|
96 | self.okbutton.controlLeft(self.cancelbutton)
|
---|
97 | self.okbutton.controlRight(self.cancelbutton)
|
---|
98 | self.cancelbutton.controlLeft(self.okbutton)
|
---|
99 | self.cancelbutton.controlRight(self.okbutton)
|
---|
100 | self.okbutton.controlDown(self.chkbutton[2])
|
---|
101 | self.okbutton.controlUp(self.chkbutton[8])
|
---|
102 | self.cancelbutton.controlDown(self.chkbutton[0])
|
---|
103 | self.cancelbutton.controlUp(self.chkbutton[6])
|
---|
104 | self.setFocus(self.okbutton)
|
---|
105 |
|
---|
106 | def get(self):
|
---|
107 | self.doModal()
|
---|
108 | self.close()
|
---|
109 | if not self.cancelled:
|
---|
110 | return [i for i in xrange(9) if self.chkstate[i]]
|
---|
111 |
|
---|
112 | def onControl(self, control):
|
---|
113 | if control == self.okbutton and any(self.chkstate):
|
---|
114 | self.close()
|
---|
115 |
|
---|
116 | elif control == self.cancelbutton:
|
---|
117 | self.cancelled = True
|
---|
118 | self.close()
|
---|
119 | else:
|
---|
120 | label = control.getLabel()
|
---|
121 | if label.isnumeric():
|
---|
122 | index = int(label) - 1
|
---|
123 | self.chkstate[index] = not self.chkstate[index]
|
---|
124 | self.chk[index].setVisible(self.chkstate[index])
|
---|
125 |
|
---|
126 | def onAction(self, action):
|
---|
127 | if action == 10:
|
---|
128 | self.cancelled = True
|
---|
129 | self.close()
|
---|
130 |
|
---|
131 | class UnCaptchaReCaptcha:
|
---|
132 |
|
---|
133 | def processCaptcha(self, key, lang):
|
---|
134 | headers = {'Referer': 'https://www.google.com/recaptcha/api2/demo', 'Accept-Language': lang}
|
---|
135 | html = get_url('http://www.google.com/recaptcha/api/fallback?k=%s' % (key), headers=headers)
|
---|
136 | token = ''
|
---|
137 | iteration = 0
|
---|
138 | while True:
|
---|
139 | payload = re.findall('"(/recaptcha/api2/payload[^"]+)', html)
|
---|
140 | iteration += 1
|
---|
141 | message = re.findall('<label[^>]+class="fbc-imageselect-message-text"[^>]*>(.*?)</label>', html)
|
---|
142 | if not message:
|
---|
143 | message = re.findall('<div[^>]+class="fbc-imageselect-message-error">(.*?)</div>', html)
|
---|
144 | if not message:
|
---|
145 | token = re.findall('"this\.select\(\)">(.*?)</textarea>', html)[0]
|
---|
146 | if token:
|
---|
147 | common.log_utils.log_debug('Captcha Success: %s' % (token))
|
---|
148 | else:
|
---|
149 | common.log_utils.log_debug('Captcha Failed: %s')
|
---|
150 | break
|
---|
151 | else:
|
---|
152 | message = message[0]
|
---|
153 | payload = payload[0]
|
---|
154 |
|
---|
155 | cval = re.findall('name="c"\s+value="([^"]+)', html)[0]
|
---|
156 | captcha_imgurl = 'https://www.google.com%s' % (payload.replace('&', '&'))
|
---|
157 | message = re.sub('</?strong>', '', message)
|
---|
158 | oSolver = cInputWindow(captcha=captcha_imgurl, msg=message, iteration=iteration)
|
---|
159 | captcha_response = oSolver.get()
|
---|
160 | if not captcha_response:
|
---|
161 | break
|
---|
162 |
|
---|
163 | data = {'c': cval, 'response': captcha_response}
|
---|
164 | html = get_url("http://www.google.com/recaptcha/api/fallback?k=%s" % (key), data=data, headers=headers)
|
---|
165 | return token
|
---|
166 |
|
---|
167 | # TODO: Replace with common.Net() when urlencode is fixed in _fetch
|
---|
168 | def get_url(url, data=None, timeout=20, headers=None):
|
---|
169 | if headers is None: headers = {}
|
---|
170 | if data is None: data = {}
|
---|
171 | post_data = urllib.urlencode(data, doseq=True)
|
---|
172 | if 'User-Agent' not in headers:
|
---|
173 | headers['User-Agent'] = common.FF_USER_AGENT
|
---|
174 | common.log_utils.log_debug('URL: |%s| Data: |%s| Headers: |%s|' % (url, post_data, headers))
|
---|
175 |
|
---|
176 | req = urllib2.Request(url)
|
---|
177 | for key in headers:
|
---|
178 | req.add_header(key, headers[key])
|
---|
179 |
|
---|
180 | response = urllib2.urlopen(req, data=post_data, timeout=timeout)
|
---|
181 | result = response.read()
|
---|
182 | response.close()
|
---|
183 | return result
|
---|