def load_auth(self, username): auth_file = os.path.join(Config.get_tmp_path(username), 'auth.json') if os.path.exists(auth_file): if time.time() - os.stat(auth_file).st_mtime < DELTA: with open(auth_file) as fh: c, tokens = json.load(fh) cookie = RequestCookie(c) return cookie, tokens return None, None
def load_auth(self, username): auth_file = Config.check_auth_file(username) # 如果缓存授权信息没过期, 就直接读取它. if auth_file: if time.time() - os.stat(auth_file).st_mtime < DELTA: with open(auth_file) as fh: c, tokens = json.load(fh) cookie = RequestCookie(c) return cookie, tokens return None, None
def urlopen(url, headers={}, data=None, retries=RETRIES, timeout=TIMEOUT, cookie=RequestCookie()): '''打开一个http连接, 并返回Request. headers 是一个dict. 默认提供了一些项目, 比如User-Agent, Referer等, 就 不需要重复加入了. 这个函数只能用于http请求, 不可以用于下载大文件. 如果服务器支持gzip压缩的话, 就会使用gzip对数据进行压缩, 然后在本地自动 解压. req.data 里面放着的是最终的http数据内容, 通常都是UTF-8编码的文本. ''' headers_merged = default_headers.copy() for key in headers.keys(): headers_merged[key] = headers[key] redirectHandler = myRedirctHandler(cookie) opener = urllib.request.build_opener(ForbiddenHandler, redirectHandler) opener.addheaders = [(k, v) for k, v in headers_merged.items()] for i in range(retries): try: req = opener.open(url, data=data, timeout=timeout) encoding = req.headers.get('Content-encoding') req.data = req.read() if encoding == 'gzip': req.data = gzip.decompress(req.data) elif encoding == 'deflate': req.data = zlib.decompress(req.data, -zlib.MAX_WBITS) return req except OSError as e: logger.error(traceback.format_exc()) except: logger.error(traceback.format_exc()) return None
def signin(self): def on_get_bdstoken(bdstoken, error=None): if error or not bdstoken: logger.error('SigninDialog.on_get_bdstoken: %s, %s' % (bdstoken, error)) self.signin_failed(_('Failed to get bdstoken!')) else: nonlocal tokens tokens['bdstoken'] = bdstoken self.update_profile(username, password, cookie, tokens, dump=True) def on_post_login(info, error=None): if error or not info: logger.error('SigninDialog.on_post_login: %s, %s' % (info, error)) self.signin_failed(_('Login failed, please try again')) else: errno, query = info if errno == 0: cookie.load_list(query) self.signin_button.set_label(_('Get bdstoken...')) gutil.async_call(auth.get_bdstoken, cookie, callback=on_get_bdstoken) # 257: 需要输入验证码 elif errno == 257: nonlocal verifycode nonlocal codeString vcodetype = query['vcodetype'] codeString = query['codeString'] dialog = SigninVcodeDialog(self, username, cookie, tokens['token'], codeString, vcodetype) response = dialog.run() verifycode = dialog.get_vcode() codeString = dialog.codeString dialog.destroy() self.signin_button.set_label(_('Get bdstoken...')) gutil.async_call(auth.post_login, cookie, tokens, username, password_enc, rsakey, verifycode, codeString, callback=on_post_login) # 密码错误 elif errno == 4: logger.error('SigninDialog.on_post_login: %s, %s' % (info, error)) self.signin_failed(_('Password error, please try again')) # 验证码错误 elif errno == 6: self.signin_failed( _('Verfication code error, please try again')) # 需要短信验证 elif errno == 400031: logger.error('SigninDialog.on_post_login: %s, %s' % (info, error)) self.signin_failed( _('Does not support SMS/Email verification!')) # 登录失败,请在弹出的窗口操作,或重新登录 elif errno == 120021: logger.error('SigninDialog.on_post_login: %s, %s' % (info, error)) self.signin_failed(_('NET:登录失败,请在弹出的窗口操作,或重新登录')) elif errno == 120019: logger.error('SigninDialog.on_post_login: %s, %s' % (info, error)) self.signin_failed( _('NET:近期登录次数过多, 请先通过 passport.baidu.com 解除锁定')) elif errno == 500010: logger.error('SigninDialog.on_post_login: %s, %s' % (info, error)) self.signin_failed(_('NET:登录过于频繁,请24小时后再试')) elif errno == 400031: logger.error('SigninDialog.on_post_login: %s, %s' % (info, error)) self.signin_failed(_('NET:账号异常,请在当前网络环境下在百度网页端正常登录一次')) else: logger.error('SigninDialog.on_post_login: %s, %s' % (info, error)) self.signin_failed(_('Unknown error, please try again')) def on_get_public_key(info, error=None): if not info or error: logger.error('SigninDialog.on_get_public_key: %s, %s' % (info, error)) self.signin_failed( _('Failed to request public key, please try again')) else: pubkey = info['pubkey'] nonlocal rsakey rsakey = info['key'] nonlocal password_enc password_enc = util.RSA_encrypt(pubkey, password) gutil.async_call(auth.post_login, cookie, tokens, username, password_enc, rsakey, verifycode, codeString, callback=on_post_login) def on_check_login(info, error=None): if not info or error: logger.error('SigninDialog.on_check_login: %s, %s' % (info, error)) self.signin_failed( _('Failed to check login, please try again')) else: ubi_cookie, status = info cookie.load_list(ubi_cookie) nonlocal codeString nonlocal verifycode codeString = status['data']['codeString'] vcodetype = status['data']['vcodetype'] if codeString: dialog = SigninVcodeDialog(self, username, cookie, tokens, codeString, vcodetype) response = dialog.run() verifycode = dialog.get_vcode() codeString = dialog.codeString dialog.destroy() '''中文验证码长度为2,英文验证码长度为4''' if not verifycode or (len(verifycode) != 4 and len(verifycode) != 2): self.signin_failed( _('Please input verification code!')) return else: gutil.async_call(auth.get_public_key, cookie, tokens, callback=on_get_public_key) else: gutil.async_call(auth.get_public_key, cookie, tokens, callback=on_get_public_key) def on_get_UBI(ubi_cookie, error=None): if error or not ubi_cookie: logger.error('SigninDialog.on_getUBI: %s, %s' % (ubi_cookie, error)) self.signin_failed(_('Failed to get UBI, please try again.')) else: cookie.load_list(ubi_cookie) self.signin_button.set_label(_('Check login')) gutil.async_call(auth.check_login, cookie, tokens, username, callback=on_check_login) def on_get_token(info, error=None): if error or not info: logger.error('SigninDialog.on_get_token: %s, %s' % (info, error)) self.signin_failed(_('Failed to get token, please try again.')) else: nonlocal tokens hosupport, token = info cookie.load_list(hosupport) cookie.load('cflag=65535%3A1; PANWEB=1;') tokens['token'] = token self.signin_button.set_label(_('Get UBI...')) gutil.async_call(auth.get_UBI, cookie, tokens, callback=on_get_UBI) def on_get_BAIDUID(uid_cookie, error=None): if error or not uid_cookie: logger.error('SigninDialog.on_get_BAIDUID: %s, %s' % (uid_cookie, error)) self.signin_failed( _('Failed to get BAIDUID cookie, please try again.')) else: cookie.load_list(uid_cookie) self.signin_button.set_label(_('Get TOKEN...')) gutil.async_call(auth.get_token, cookie, callback=on_get_token) username = self.username_combo.get_child().get_text() password = self.password_entry.get_text() # 使用本地的缓存token, 有效期是三天 if not self.password_changed and self.signin_check.get_active(): cookie, tokens = self.load_auth(username) if cookie and tokens: self.update_profile(username, password, cookie, tokens) return cookie = RequestCookie() tokens = {} verifycode = '' codeString = '' password_enc = '' rsakey = '' self.signin_button.set_label(_('Get BAIDUID...')) gutil.async_call(auth.get_BAIDUID, callback=on_get_BAIDUID)
def signin(self): def on_get_bdstoken(bdstokens, error=None): if error or not bdstokens: self.signin_failed(_('Error: Failed to get bdstokens!')) else: nonlocal tokens for token in bdstokens: tokens[token] = bdstokens[token] self.update_profile(username, password, cookie, tokens, dump=True) def on_get_bduss(result, error=None): status, info = result if status == 4: self.signin_failed( _('Please check username and password are correct!')) elif status == 0: cookie.load_list(info) self.signin_button.set_label(_('Get bdstoken...')) gutil.async_call(auth.get_bdstoken, cookie, callback=on_get_bdstoken) elif status == 257: vcodetype, codeString = info dialog = SigninVcodeDialog(self, username, cookie, tokens['token'], codeString, vcodetype) dialog.run() vcode = dialog.get_vcode() dialog.destroy() if not vcode or len(vcode) != 4: self.signin_failed(_('Please input verification code!')) return self.signin_button.set_label(_('Get bduss...')) gutil.async_call(auth.get_bduss, cookie, tokens['token'], username, password, vcode, codeString, callback=on_get_bduss) else: self.signin_failed( _('Unknown err_no {0}, please try again!').format(status)) def on_check_login(status, error=None): if error or not status: self.signin_failed( _('Failed to get check login, please try again.')) elif len(status['data']['codeString']): codeString = status['data']['codeString'] vcodetype = status['data']['vcodetype'] dialog = SigninVcodeDialog(self, username, cookie, tokens['token'], codeString, vcodetype) dialog.run() vcode = dialog.get_vcode() dialog.destroy() if not vcode or len(vcode) != 4: self.signin_failed(_('Please input verification code!')) return self.signin_button.set_label(_('Get bduss...')) gutil.async_call(auth.get_bduss, cookie, tokens['token'], username, password, vcode, codeString, callback=on_get_bduss) else: self.signin_button.set_label(_('Get bduss...')) gutil.async_call(auth.get_bduss, cookie, tokens['token'], username, password, callback=on_get_bduss) def on_get_UBI(ubi_cookie, error=None): if error or not ubi_cookie: self.signin_failed( _('Failed to get UBI cookie, please try again.')) else: cookie.load_list(ubi_cookie) self.signin_button.set_label(_('Get token...')) gutil.async_call(auth.check_login, cookie, tokens['token'], username, callback=on_check_login) def on_get_token(token, error=None): if error or not token: self.signin_failed( _('Failed to get tokens, please try again.')) else: nonlocal tokens tokens['token'] = token self.signin_button.set_label(_('Get UBI...')) gutil.async_call(auth.get_UBI, cookie, token, callback=on_get_UBI) def on_get_BAIDUID(uid_cookie, error=None): if error or not uid_cookie: self.signin_failed( _('Failed to get BAIDUID cookie, please try agin.')) else: cookie.load_list(uid_cookie) self.signin_button.set_label(_('Get BAIDUID...')) gutil.async_call(auth.get_token, cookie, callback=on_get_token) username = self.username_combo.get_child().get_text() password = self.password_entry.get_text() # 使用本地的缓存token, 有效期是三天 if self.signin_check.get_active(): cookie, tokens = self.load_auth(username) if cookie and tokens: self.update_profile(username, password, cookie, tokens) return cookie = RequestCookie() tokens = {} cookie.load('cflag=65535%3A1; PANWEB=1;') self.signin_button.set_label(_('Get cookie...')) gutil.async_call(auth.get_BAIDUID, callback=on_get_BAIDUID)
def signin(self): def on_get_bdstoken(bdstokens, error=None): if error or not bdstokens: self.signin_failed( _('Error: Failed to get bdstokens!')) else: nonlocal tokens for token in bdstokens: tokens[token] = bdstokens[token] self.update_profile( username, password, cookie, tokens, dump=True) def on_get_bduss(result, error=None): status, info = result if status == 4: self.signin_failed( _('Please check username and password are correct!')) elif status == 0: cookie.load_list(info) self.signin_button.set_label(_('Get bdstoken...')) gutil.async_call( auth.get_bdstoken, cookie, callback=on_get_bdstoken) elif status == 257: vcodetype, codeString = info dialog = SigninVcodeDialog( self, username, cookie, tokens['token'], codeString, vcodetype) dialog.run() vcode = dialog.get_vcode() dialog.destroy() if not vcode or len(vcode) != 4: self.signin_failed( _('Please input verification code!')) return self.signin_button.set_label(_('Get bduss...')) gutil.async_call( auth.get_bduss, cookie, tokens['token'], username, password, vcode, codeString, callback=on_get_bduss) else: self.signin_failed( _('Unknown err_no {0}, please try again!').format( status)) def on_check_login(status, error=None): if error or not status: self.signin_failed( _('Failed to get check login, please try again.')) elif len(status['data']['codeString']): codeString = status['data']['codeString'] vcodetype = status['data']['vcodetype'] dialog = SigninVcodeDialog( self, username, cookie, tokens['token'], codeString, vcodetype) dialog.run() vcode = dialog.get_vcode() dialog.destroy() if not vcode or len(vcode) != 4: self.signin_failed( _('Please input verification code!')) return self.signin_button.set_label(_('Get bduss...')) gutil.async_call( auth.get_bduss, cookie, tokens['token'], username, password, vcode, codeString, callback=on_get_bduss) else: self.signin_button.set_label(_('Get bduss...')) gutil.async_call( auth.get_bduss, cookie, tokens['token'], username, password, callback=on_get_bduss) def on_get_UBI(ubi_cookie, error=None): if error or not ubi_cookie: self.signin_failed( _('Failed to get UBI cookie, please try again.')) else: cookie.load_list(ubi_cookie) self.signin_button.set_label(_('Get token...')) gutil.async_call( auth.check_login, cookie, tokens['token'], username, callback=on_check_login) def on_get_token(token, error=None): if error or not token: self.signin_failed( _('Failed to get tokens, please try again.')) else: nonlocal tokens tokens['token'] = token self.signin_button.set_label(_('Get UBI...')) gutil.async_call( auth.get_UBI, cookie, token, callback=on_get_UBI) def on_get_BAIDUID(uid_cookie, error=None): if error or not uid_cookie: self.signin_failed( _('Failed to get BAIDUID cookie, please try agin.')) else: cookie.load_list(uid_cookie) self.signin_button.set_label(_('Get BAIDUID...')) gutil.async_call( auth.get_token, cookie, callback=on_get_token) username = self.username_combo.get_child().get_text() password = self.password_entry.get_text() # 使用本地的缓存token, 有效期是三天 if self.signin_check.get_active(): cookie, tokens = self.load_auth(username) if cookie and tokens: self.update_profile(username, password, cookie, tokens) return cookie = RequestCookie() tokens = {} cookie.load('cflag=65535%3A1; PANWEB=1;') self.signin_button.set_label(_('Get cookie...')) gutil.async_call( auth.get_BAIDUID, callback=on_get_BAIDUID)
def signin(self): def on_get_bdstoken(bdstoken, error=None): if error or not bdstoken: logger.error('SigninDialog.on_get_bdstoken: %s, %s' % (bdstoken, error)) self.signin_failed(_('Failed to get bdstoken!')) else: nonlocal tokens tokens['bdstoken'] = bdstoken self.update_profile(username, password, cookie, tokens, dump=True) def on_post_login(info, error=None): if error or not info: logger.error('SigninDialog.on_post_login: %s, %s' % (info, error)) self.signin_failed(_('Login failed, please try again')) else: errno, query = info if errno == 0: cookie.load_list(query) self.signin_button.set_label(_('Get bdstoken...')) gutil.async_call(auth.get_bdstoken, cookie, callback=on_get_bdstoken) # 257: 需要输入验证码 elif errno == 257: nonlocal verifycode nonlocal codeString vcodetype = query['vcodetype'] codeString = query['codeString'] dialog = SigninVcodeDialog(self, username, cookie, tokens['token'], codeString, vcodetype) response = dialog.run() verifycode = dialog.get_vcode() codeString = dialog.codeString dialog.destroy() if not verifycode or len(verifycode) != 4: self.signin_failed( _('Please input verification code!')) return else: self.signin_button.set_label(_('Get bdstoken...')) gutil.async_call(auth.post_login, cookie, tokens, username, password_enc, rsakey, verifycode, codeString, callback=on_post_login) # 密码错误 elif errno == 4: logger.error('SigninDialog.on_post_login: %s, %s' % (info, error)) self.signin_failed(_('Password error, please try again')) # 验证码错误 elif errno == 6: self.signin_failed( _('Verfication code error, please try again')) # 需要短信验证 elif errno == 400031: logger.error('SigninDialog.on_post_login: %s, %s' % (info, error)) self.signin_failed( _('Does not support SMS/Email verification!')) else: logger.error('SigninDialog.on_post_login: %s, %s' % (info, error)) self.signin_failed(_('Unknown error, please try again')) def on_get_public_key(info, error=None): if not info or error: logger.error('SigninDialog.on_get_public_key: %s, %s' % (info, error)) self.signin_failed( _('Failed to request public key, please try again')) else: pubkey = info['pubkey'] nonlocal rsakey rsakey = info['key'] nonlocal password_enc password_enc = util.RSA_encrypt(pubkey, password) gutil.async_call(auth.post_login, cookie, tokens, username, password_enc, rsakey, verifycode, codeString, callback=on_post_login) def on_check_login(info, error=None): if not info or error: logger.error('SigninDialog.on_check_login: %s, %s' % (info, error)) self.signin_failed( _('Failed to check login, please try again')) else: ubi_cookie, status = info cookie.load_list(ubi_cookie) nonlocal codeString nonlocal verifycode codeString = status['data']['codeString'] vcodetype = status['data']['vcodetype'] if codeString: dialog = SigninVcodeDialog(self, username, cookie, tokens, codeString, vcodetype) response = dialog.run() verifycode = dialog.get_vcode() codeString = dialog.codeString dialog.destroy() if not verifycode or len(verifycode) != 4: self.signin_failed( _('Please input verification code!')) return else: gutil.async_call(auth.get_public_key, cookie, tokens, callback=on_get_public_key) else: gutil.async_call(auth.get_public_key, cookie, tokens, callback=on_get_public_key) def on_get_UBI(ubi_cookie, error=None): if error or not ubi_cookie: logger.error('SigninDialog.on_getUBI: %s, %s' % (ubi_cookie, error)) self.signin_failed(_('Failed to get UBI, please try again.')) else: cookie.load_list(ubi_cookie) self.signin_button.set_label(_('Check login')) gutil.async_call(auth.check_login, cookie, tokens, username, callback=on_check_login) def on_get_token(info, error=None): if error or not info: logger.error('SigninDialog.on_get_token: %s, %s' % (info, error)) self.signin_failed(_('Failed to get token, please try again.')) else: nonlocal tokens hosupport, token = info cookie.load_list(hosupport) cookie.load('cflag=65535%3A1; PANWEB=1;') tokens['token'] = token self.signin_button.set_label(_('Get UBI...')) gutil.async_call(auth.get_UBI, cookie, tokens, callback=on_get_UBI) def on_get_BAIDUID(uid_cookie, error=None): if error or not uid_cookie: logger.error('SigninDialog.on_get_BAIDUID: %s, %s' % (uid_cookie, error)) self.signin_failed( _('Failed to get BAIDUID cookie, please try agin.')) else: cookie.load_list(uid_cookie) self.signin_button.set_label(_('Get TOKEN...')) gutil.async_call(auth.get_token, cookie, callback=on_get_token) username = "******" password = "******" # 使用本地的缓存token, 有效期是三天 cookie = RequestCookie() tokens = {} verifycode = '' codeString = '' password_enc = '' rsakey = '' self.signin_button.set_label(_('Get BAIDUID...')) gutil.async_call(auth.get_BAIDUID, callback=on_get_BAIDUID)
def signin(self): def on_get_bdstoken(bdstoken, error=None): if error or not bdstoken: print('Error in on_get_bdstoken():', bdstoken, error) print('Please check your username and passowrd') self.signin_failed( _('Error: Failed to get bdstokens!')) else: nonlocal tokens tokens['bdstoken'] = bdstoken self.update_profile( username, password, cookie, tokens, dump=True) def on_wap_signin(cookie_str, error): if not cookie_str or error: print('Error in on_wap_signin():', cookie_str, error) self.signin_failed( _('Failed to signin, please try again.')) else: cookie.load_list(cookie_str) self.signin_button.set_label(_('Get bdstoken...')) gutil.async_call(auth.get_bdstoken, cookie, callback=on_get_bdstoken) def on_get_wap_passport(info, error=None): if error or not info: print('Error occurs in on_get_wap_passport:', info, error) self.signin_failed( _('Failed to get WAP page, please try again.')) cookie_str, _form = info if not cookie_str or not _form: print('Error occurs in on_get_wap_passport:', info, error) self.signin_failed( _('Failed to get WAP page, please try again.')) else: nonlocal form form = _form form['username'] = username form['password'] = password cookie.load_list(cookie_str) if len(form.get('vcodestr', '')): dialog = SigninVcodeDialog(self, cookie, form) dialog.run() dialog.destroy() if len(form.get('verifycode', '')) != 4: print('verifycode length is not 4!') return self.signin_button.set_label(_('Signin...')) gutil.async_call(auth.wap_signin, cookie, form, callback=on_wap_signin) def on_get_token(token, error=None): if error or not token: print('Error in get token():', token, error) self.signin_failed( _('Failed to get tokens, please try again.')) else: nonlocal tokens tokens['token'] = token self.signin_button.set_label(_('Get WAP page...')) gutil.async_call( auth.get_wap_passport, callback=on_get_wap_passport) def on_get_BAIDUID(uid_cookie, error=None): if error or not uid_cookie: print('Error in get BAIDUID():', uid_cookie, error) self.signin_failed( _('Failed to get BAIDUID cookie, please try agin.')) else: cookie.load_list(uid_cookie) self.signin_button.set_label(_('Get TOKEN...')) gutil.async_call( auth.get_token, cookie, callback=on_get_token) username = self.username_combo.get_child().get_text() password = self.password_entry.get_text() # 使用本地的缓存token, 有效期是三天 if not self.password_changed and self.signin_check.get_active(): cookie, tokens = self.load_auth(username) if cookie and tokens: self.update_profile(username, password, cookie, tokens) return cookie = RequestCookie() cookie.load('cflag=65535%3A1; PANWEB=1;') tokens = {} form = {} self.signin_button.set_label(_('Get BAIDUID...')) gutil.async_call( auth.get_BAIDUID, callback=on_get_BAIDUID)
def signin(self, auto_signin = True): self.profile = None self.screen.nodelay(0) self.screen.addstr(2, 2, "Baidu Yun Login") self.screen.addstr(4, 2, "Please input your ID and Password") self.screen.addstr(6, 2, "Press Any Key to continue ... ") self.screen.refresh() self.screen.getch() curses.echo() win = curses.newwin(height, width, begin_y, begin_x); win.border(0) win.addstr(2, 2, "UserName:"******"Cookie is valid. Press any key to continue."); win.refresh() win.getch() return True win.addstr(4, 2, "Password: (Won't be shown)") win.refresh() curses.noecho() password = win.getstr(5, 2, 20).decode(encoding='utf-8') curses.echo() self.cookie = RequestCookie() self.tokens = {} verifycode = '' codeString = '' password_enc = '' rsakey = '' win.addstr(7, 2, "Get BaiduID..."); win.refresh() uid_cookie = auth.get_BAIDUID() if not uid_cookie: win.addstr(8, 2, " Get BaiduID failed, press any key to exit") win.refresh() win.getch() return False self.cookie.load_list(uid_cookie) win.addstr(8, 2, "Get token..."); win.refresh() info = auth.get_token(self.cookie) if not info: win.addstr(9, 2, " Get Token failed, press any key to exit") win.refresh() win.getch() return False hosupport, token = info self.cookie.load_list(hosupport) self.cookie.load('cflag=65535%3A1; PANWEB=1;') self.tokens['token'] = token win.addstr(9, 2, "Get UBI..."); win.refresh() ubi_cookie = auth.get_UBI(self.cookie, self.tokens) self.cookie.load_list(ubi_cookie) win.addstr(10, 2, "Check login..."); win.refresh() ubi_cookie, status = auth.check_login(self.cookie, self.tokens, username) self.cookie.load_list(ubi_cookie) codeString = status['data']['codeString'] vcodetype = status['data']['vcodetype'] if codeString: win.addstr(11, 2, "Vcode is needed but not supported") win.addstr(12, 2, "Press any key to quit") win.refresh() win.getch() return False win.addstr(11, 2, "Get public key..."); win.refresh() info = auth.get_public_key(self.cookie,self.tokens) pubkey = info['pubkey'] rsakey = info['key'] password_enc = util.RSA_encrypt(pubkey, password) win.addstr(12, 2, "login..."); win.refresh() info = auth.post_login(self.cookie, self.tokens, username, password_enc, rsakey) errno, query = info if errno == 0: self.cookie.load_list(query) win.addstr(13, 2, "Get bds_token ...") win.refresh() bdstoken = auth.get_bdstoken(self.cookie) self.tokens['bdstoken'] = bdstoken win.addstr(14, 2, "Login finished, press any key to continue") win.refresh() win.getch() elif errno == 257: win.addstr(13, 2, "need vcode, but not supported") win.addstr(14, 2, "Press any key to quit") win.refresh() win.getch() return False elif errno == 4: win.addstr(13, 2, "invalid password!") win.addstr(14, 2, "Press any key to quit") win.refresh() win.getch() return False else: win.addstr(13, 2, "Something is wrong") win.addstr(14, 2, "Press any key to quit") win.refresh() win.getch() return False self.dump_auth(self.username, self.cookie, self.tokens) return True
class Cli: profile = None tokens = None screen = None cookie = None files = None path = '/' page_num = 1 username = '' item_pos = 0 has_next = True block_size = 128 * 1024 def __init__(self): self.filewatcher = None self.screen = curses.initscr() curses.cbreak() curses.start_color() self.screen.border(0) #self.screen.start_color() # auto_signin mode is not supported now def signin(self, auto_signin = True): self.profile = None self.screen.nodelay(0) self.screen.addstr(2, 2, "Baidu Yun Login") self.screen.addstr(4, 2, "Please input your ID and Password") self.screen.addstr(6, 2, "Press Any Key to continue ... ") self.screen.refresh() self.screen.getch() curses.echo() win = curses.newwin(height, width, begin_y, begin_x); win.border(0) win.addstr(2, 2, "UserName:"******"Cookie is valid. Press any key to continue."); win.refresh() win.getch() return True win.addstr(4, 2, "Password: (Won't be shown)") win.refresh() curses.noecho() password = win.getstr(5, 2, 20).decode(encoding='utf-8') curses.echo() self.cookie = RequestCookie() self.tokens = {} verifycode = '' codeString = '' password_enc = '' rsakey = '' win.addstr(7, 2, "Get BaiduID..."); win.refresh() uid_cookie = auth.get_BAIDUID() if not uid_cookie: win.addstr(8, 2, " Get BaiduID failed, press any key to exit") win.refresh() win.getch() return False self.cookie.load_list(uid_cookie) win.addstr(8, 2, "Get token..."); win.refresh() info = auth.get_token(self.cookie) if not info: win.addstr(9, 2, " Get Token failed, press any key to exit") win.refresh() win.getch() return False hosupport, token = info self.cookie.load_list(hosupport) self.cookie.load('cflag=65535%3A1; PANWEB=1;') self.tokens['token'] = token win.addstr(9, 2, "Get UBI..."); win.refresh() ubi_cookie = auth.get_UBI(self.cookie, self.tokens) self.cookie.load_list(ubi_cookie) win.addstr(10, 2, "Check login..."); win.refresh() ubi_cookie, status = auth.check_login(self.cookie, self.tokens, username) self.cookie.load_list(ubi_cookie) codeString = status['data']['codeString'] vcodetype = status['data']['vcodetype'] if codeString: win.addstr(11, 2, "Vcode is needed but not supported") win.addstr(12, 2, "Press any key to quit") win.refresh() win.getch() return False win.addstr(11, 2, "Get public key..."); win.refresh() info = auth.get_public_key(self.cookie,self.tokens) pubkey = info['pubkey'] rsakey = info['key'] password_enc = util.RSA_encrypt(pubkey, password) win.addstr(12, 2, "login..."); win.refresh() info = auth.post_login(self.cookie, self.tokens, username, password_enc, rsakey) errno, query = info if errno == 0: self.cookie.load_list(query) win.addstr(13, 2, "Get bds_token ...") win.refresh() bdstoken = auth.get_bdstoken(self.cookie) self.tokens['bdstoken'] = bdstoken win.addstr(14, 2, "Login finished, press any key to continue") win.refresh() win.getch() elif errno == 257: win.addstr(13, 2, "need vcode, but not supported") win.addstr(14, 2, "Press any key to quit") win.refresh() win.getch() return False elif errno == 4: win.addstr(13, 2, "invalid password!") win.addstr(14, 2, "Press any key to quit") win.refresh() win.getch() return False else: win.addstr(13, 2, "Something is wrong") win.addstr(14, 2, "Press any key to quit") win.refresh() win.getch() return False self.dump_auth(self.username, self.cookie, self.tokens) return True #------------------------------------------------- # user info area #------------------------------------------------- # | file info # | area # file list | # | # | # | #------------------------------------------------ # operation area #------------------------------------------------ def cloud_driver(self): self.item_pos = 0 self.path = '/' self.page_num = 1 self.has_next = True curses.curs_set(0) self.screen.keypad(True) curses.noecho() info, filel, filei, o = self.initialize_window() self.draw_info(info) self.draw_nav(o) self.draw_file(filel, filei ) self.screen.nodelay(1) while True: c = self.screen.getch() if c == curses.KEY_UP: self.up() self.draw_current_list(filel, filei) elif c == curses.KEY_DOWN: self.down() self.draw_current_list(filel, filei) elif c == curses.KEY_RIGHT: self.enter_dir() self.draw_file(filel, filei) self.draw_info(info) elif c == curses.KEY_LEFT: self.back_dir() self.draw_file(filel, filei) self.draw_info(info) elif c == 27 or c == ord('Q') or c == ord('q'): break elif c == 10: self.download(o) elif c == ord('>'): self.next_page() self.draw_file(filel, filei) self.draw_info(info) elif c == ord('<'): self.prev_page() self.draw_file(filel, filei) self.draw_info(info) elif c == ord('R') or c == ord('r'): info.clear() o.clear() filel.clear() filei.clear() info.border(0) o.border(0) filel.border(0) filei.border(0) self.draw_info(info) self.draw_nav(o) self.draw_file(filel, filei) else: pass def next_page(self): self.files = None self.item_pos = 0 if not self.has_next: self.page_num += 1 def prev_page(self): self.files = None self.item_pos = 0 if self.page_num > 1: self.page_num -= 1 def up(self): if self.files and self.item_pos > 0: self.item_pos -= 1 def down(self): if self.files and self.item_pos < len(self.files) - 1: self.item_pos += 1 def download(self, o): if self.files and self.files[self.item_pos] and not self.files[self.item_pos]['isdir']: self.screen.nodelay(1) end_size = self.files[self.item_pos]['size'] path = self.files[self.item_pos]['path'] o.clear() o.border(0) curses.echo() o.addstr(1, 2, "DownloadPath: (Default: ~/)") o.refresh() download_path = o.getstr(2, 2, 40).decode(encoding='utf-8') if download_path == "": download_path = expanduser("~") else: download_path = expanduser(download_path) filepath, tmp_filepath , conf_filepath = get_tmp_filepath(download_path, path[1:]) if not os.path.exists(os.path.dirname(tmp_filepath)): os.makedirs(os.path.dirname(tmp_filepath), exist_ok=True) o.clear() o.border(0) o.refresh() if os.path.exists(filepath): o.clear() o.border(0) o.addstr(1, 2, "File Already Exists.") o.addstr(2, 2, "Press Any Key to Continue") o.refresh() self.screen.getch() return o.addstr(1, 2, "Getting Download links...") o.refresh() url = pcs.get_download_link(self.cookie, self.tokens, path) if not url: o.clear() o.border(0) o.addstr(1, 2, "Failed to get url") o.addstr(2, 2, "Press ESC to abort") o.refresh() self.screen.getch() return o.addstr(2, 2, "Prepare file...") o.refresh() if os.path.exists(conf_filepath) and os.path.exists(tmp_filepath): with open(conf_filepath) as conf_fh: status = json.load(conf_fh) file_exists = True fh = open(tmp_filepath, 'rb+') else: req = net.urlopen_simple(url) if not req: o.clear() o.border(0) o.addstr(1, 2, "Failed to request") o.addstr(2, 2, "Press ESC to abort") o.refresh() self.screen.getch() return content_length = req.getheader('Content-Length') if not content_length: match = re.search('\sContent-Length:\s*(\d+)', str(req.headers)) if not match: o.clear() o.border(0) o.addstr(1, 2, "Failed to match content-length") o.addstr(2, 2, "Press ESC to abort") o.refresh() self.screen.getch() return content_length = match.group(1) size = int(content_length) if size == 0: open(filepath, 'a').close() o.clear() o.border(0) o.addstr(1, 2, "File already downloaded") o.addstr(2, 2, "Press ESC to abort") o.refresh() self.screen.getch() return file_exists = False fh = open(tmp_filepath, 'wb') try: fh.truncate(size) except (OSError, IOError): o.clear() o.border(0) o.addstr(1, 2, "Disk error (disk is full?)") o.addstr(2, 2, "Press ESC to abort") o.refresh() self.screen.getch() return start_size = 0 if file_exists: start_size, end_size, received = status offset = start_size count = 0 while offset < end_size: status = [offset, end_size, 0] count += 1 o.clear() o.border(0) c = self.screen.getch() if c == 27: with open(conf_filepath, 'w') as fh: json.dump(status, fh) break o.addstr(1, 2, "Downloading: {0} ... ".format(path)) o.refresh() req = self.get_req(url, offset, end_size) if not req: o.addstr(2, 2, "Network error{0}, retry after 3s.".format(count)) o.addstr(3, 2, "Press ESC to abort.") o.refresh() time.sleep(3) continue else: try: block = req.read(self.block_size) except: o.addstr(2, 2, "Can not Read block, retry.".format(offset, end_size)) time.sleep(1) continue o.addstr(2, 2, "Process: {0} / {1}".format(offset, end_size)) fh.seek(offset) fh.write(block) offset += len(block) o.addstr(3, 2, "Press ESC to abort") o.refresh() def enter_dir(self): if self.files[self.item_pos] and self.files[self.item_pos]['isdir']: self.path = self.files[self.item_pos]['path'] self.files = None self.item_pos = 0 def back_dir(self): self.files = None self.item_pos = 0 if not self.path == '/' or not self.path == '': self.path = os.path.dirname(self.path) def draw_current_list(self, filel, filei): filel.clear() filei.clear() filel.border(0) filei.border(0) if self.files: index = 0 start_pos = self.item_pos if len(self.files) - self.item_pos < 26: start_pos = max(len(self.files) - 26, 0) for pindex in range(start_pos, len(self.files)): pfile = self.files[pindex] path = os.path.basename(pfile['path'])[:50] size = pfile.get('size', 0) if pfile['isdir']: human_size = '--' path = path + "/" else: human_size = util.get_human_size(pfile['size'])[0] if pindex == self.item_pos: filel.addstr(index + 1, 2, "> " + path, curses.COLOR_RED) else: filel.addstr(index + 1, 2, path) filei.addstr(index + 1, 2, human_size) index += 1 if index > 26: filel.addstr(index + 1, 2, "More {0} files...".format(len(self.files) - index + 1)) break filel.refresh() filei.refresh() def draw_file(self, filel, filei): filel.clear() filei.clear() filel.border(0) filei.border(0) if not self.cookie or not self.tokens: filel.refresh() filei.refresh() return content = pcs.list_dir(self.cookie, self.tokens, self.path, self.page_num) if not content: filel.addstr(2,2, "Network Error - content empty") elif content.get('errno', -1) != 0: filel.addstr(2,2, "Network Error - error") elif content['list']: # process here self.files = content['list'] self.draw_current_list(filel, filei) else: filel.addstr(2,2, "Already last page") self.has_next = False filel.refresh() filei.refresh() def initialize_window(self): self.screen.refresh() info_x, info_y, info_w, info_h = 0, 0, 90, 4 info = curses.newwin(info_h, info_w, info_y, info_x) info.border(0) file_y, file_x, file_w, file_h = 4, 0, 60, 30 filel = curses.newwin(file_h, file_w, file_y, file_x) filel.border(0) filei_y, filei_x, filei_w, filei_h = 4, 61, 30, 30 filei = curses.newwin(filei_h, filei_w, filei_y, filei_x) filei.border(0) o_y, o_x, o_w, o_h = 34, 0, 90, 5 o = curses.newwin(o_h, o_w, o_y, o_x) o.border(0) return info, filel, filei, o def draw_info(self, info): if not self.cookie or not self.tokens: info.addstr(1,2, 'User: {0}, Cookie and Tokens are not available'.format(self.username)) info.addstr(2,2, 'Try restarting application to fix'.format(self.path, self.page_num)) info.refresh() return quota_info = pcs.get_quota(self.cookie, self.tokens) used = quota_info['used'] total = quota_info['total'] used_size = util.get_human_size(used)[0] total_size = util.get_human_size(total)[0] info.addstr(1,2, 'User: {2}, Quota: {0} / {1}'.format(used_size, total_size, self.username)) info.addstr(2,2, 'Path: {0}, Page: {1}'.format(self.path, self.page_num)) info.refresh() def draw_nav(self, o): o.addstr(1, 2, "Up/Down - Select File, Left/Right - Change Directory, Enter - Download") o.addstr(2, 2, "Esc/Q - Quit, R - Refresh, F - Find, Delete - Not supported.") o.addstr(3, 2, "< - previous page, > - next page") o.refresh() def run(self, argv): if not self.profile: if not self.signin(True): return self.cloud_driver() curses.endwin() def load_auth(self, username): auth_file = os.path.join(Config.get_tmp_path(username), 'auth.json') if os.path.exists(auth_file): if time.time() - os.stat(auth_file).st_mtime < DELTA: with open(auth_file) as fh: c, tokens = json.load(fh) cookie = RequestCookie(c) return cookie, tokens return None, None def dump_auth(self, username, cookie, tokens): auth_file = os.path.join(Config.get_tmp_path(username), 'auth.json') with open(auth_file, 'w') as fh: json.dump([str(cookie), tokens], fh) def get_req(self, url, start_size, end_size): opener = request.build_opener() content_range = 'bytes={0}-{1}'.format(start_size, end_size) opener.addheaders = [ ('Range', content_range), ('User-Agent', const.USER_AGENT), ('Referer', const.PAN_REFERER), ] for i in range(RETRIES): try: return opener.open(url, timeout = 8) except: return None else: return None
def signin(self): def on_get_bdstoken(bdstoken, error=None): if error or not bdstoken: print('Error in get bdstoken:', bdstoken, error) print('Please check your username and passowrd') self.signin_failed(_('Error: Failed to get bdstokens!')) else: nonlocal tokens tokens['bdstoken'] = bdstoken self.update_profile(username, password, cookie, tokens, dump=True) def on_wap_signin(cookie_str, error): if not cookie_str or error: print('Error in on_wap_signin():', cookie_str, error) self.signin_failed(_('Failed to signin, please try again.')) else: cookie.load_list(cookie_str) self.signin_button.set_label(_('Get bdstoken...')) gutil.async_call(auth.get_bdstoken, cookie, callback=on_get_bdstoken) def on_get_wap_passport(info, error=None): if error or not info: print('Error occurs in on_get_wap_passport:', info, error) self.signin_failed( _('Failed to get WAP page, please try again.')) cookie_str, _form = info if not cookie_str or not _form: print('Error occurs in on_get_wap_passport:', info, error) self.signin_failed( _('Failed to get WAP page, please try again.')) else: nonlocal form form = _form form['username'] = username form['password'] = password cookie.load_list(cookie_str) if len(form.get('vcodestr', '')): dialog = SigninVcodeDialog(self, cookie, form) dialog.run() dialog.destroy() if len(form.get('verifycode', '')) != 4: print('verifycode length is not 4!') return self.signin_button.set_label(_('Signin...')) gutil.async_call(auth.wap_signin, cookie, form, callback=on_wap_signin) def on_get_token(token, error=None): if error or not token: print('Error in get token():', token, error) self.signin_failed( _('Failed to get tokens, please try again.')) else: nonlocal tokens tokens['token'] = token self.signin_button.set_label(_('Get WAP page...')) gutil.async_call(auth.get_wap_passport, callback=on_get_wap_passport) def on_get_BAIDUID(uid_cookie, error=None): if error or not uid_cookie: print('Error in get BAIDUID():', uid_cookie, error) self.signin_failed( _('Failed to get BAIDUID cookie, please try agin.')) else: cookie.load_list(uid_cookie) self.signin_button.set_label(_('Get TOKEN...')) gutil.async_call(auth.get_token, cookie, callback=on_get_token) username = self.username_combo.get_child().get_text() password = self.password_entry.get_text() # 使用本地的缓存token, 有效期是三天 if not self.password_changed and self.signin_check.get_active(): cookie, tokens = self.load_auth(username) if cookie and tokens: self.update_profile(username, password, cookie, tokens) return cookie = RequestCookie() cookie.load('cflag=65535%3A1; PANWEB=1;') tokens = {} form = {} self.signin_button.set_label(_('Get BAIDUID...')) gutil.async_call(auth.get_BAIDUID, callback=on_get_BAIDUID)
def signin(self, auto_signin=True): self.profile = None self.screen.nodelay(0) self.screen.addstr(2, 2, "Baidu Yun Login") self.screen.addstr(4, 2, "Please input your ID and Password") self.screen.addstr(6, 2, "Press Any Key to continue ... ") self.screen.refresh() self.screen.getch() curses.echo() win = curses.newwin(height, width, begin_y, begin_x) win.border(0) win.addstr(2, 2, "UserName:"******"Cookie is valid. Press any key to continue.") win.refresh() win.getch() return True win.addstr(4, 2, "Password: (Won't be shown)") win.refresh() curses.noecho() password = win.getstr(5, 2, 20).decode(encoding='utf-8') curses.echo() self.cookie = RequestCookie() self.tokens = {} verifycode = '' codeString = '' password_enc = '' rsakey = '' win.addstr(7, 2, "Get BaiduID...") win.refresh() uid_cookie = auth.get_BAIDUID() if not uid_cookie: win.addstr(8, 2, " Get BaiduID failed, press any key to exit") win.refresh() win.getch() return False self.cookie.load_list(uid_cookie) win.addstr(8, 2, "Get token...") win.refresh() info = auth.get_token(self.cookie) if not info: win.addstr(9, 2, " Get Token failed, press any key to exit") win.refresh() win.getch() return False hosupport, token = info self.cookie.load_list(hosupport) self.cookie.load('cflag=65535%3A1; PANWEB=1;') self.tokens['token'] = token win.addstr(9, 2, "Get UBI...") win.refresh() ubi_cookie = auth.get_UBI(self.cookie, self.tokens) self.cookie.load_list(ubi_cookie) win.addstr(10, 2, "Check login...") win.refresh() ubi_cookie, status = auth.check_login(self.cookie, self.tokens, username) self.cookie.load_list(ubi_cookie) codeString = status['data']['codeString'] vcodetype = status['data']['vcodetype'] if codeString: win.addstr(11, 2, "Vcode is needed but not supported") win.addstr(12, 2, "Press any key to quit") win.refresh() win.getch() return False win.addstr(11, 2, "Get public key...") win.refresh() info = auth.get_public_key(self.cookie, self.tokens) pubkey = info['pubkey'] rsakey = info['key'] password_enc = util.RSA_encrypt(pubkey, password) win.addstr(12, 2, "login...") win.refresh() info = auth.post_login(self.cookie, self.tokens, username, password_enc, rsakey) errno, query = info if errno == 0: self.cookie.load_list(query) win.addstr(13, 2, "Get bds_token ...") win.refresh() bdstoken = auth.get_bdstoken(self.cookie) self.tokens['bdstoken'] = bdstoken win.addstr(14, 2, "Login finished, press any key to continue") win.refresh() win.getch() elif errno == 257: win.addstr(13, 2, "need vcode, but not supported") win.addstr(14, 2, "Press any key to quit") win.refresh() win.getch() return False elif errno == 4: win.addstr(13, 2, "invalid password!") win.addstr(14, 2, "Press any key to quit") win.refresh() win.getch() return False else: win.addstr(13, 2, "Something is wrong") win.addstr(14, 2, "Press any key to quit") win.refresh() win.getch() return False self.dump_auth(self.username, self.cookie, self.tokens) return True
class Cli: profile = None tokens = None screen = None cookie = None files = None path = '/' page_num = 1 username = '' item_pos = 0 has_next = True block_size = 128 * 1024 def __init__(self): self.filewatcher = None self.screen = curses.initscr() curses.cbreak() curses.start_color() self.screen.border(0) #self.screen.start_color() # auto_signin mode is not supported now def signin(self, auto_signin=True): self.profile = None self.screen.nodelay(0) self.screen.addstr(2, 2, "Baidu Yun Login") self.screen.addstr(4, 2, "Please input your ID and Password") self.screen.addstr(6, 2, "Press Any Key to continue ... ") self.screen.refresh() self.screen.getch() curses.echo() win = curses.newwin(height, width, begin_y, begin_x) win.border(0) win.addstr(2, 2, "UserName:"******"Cookie is valid. Press any key to continue.") win.refresh() win.getch() return True win.addstr(4, 2, "Password: (Won't be shown)") win.refresh() curses.noecho() password = win.getstr(5, 2, 20).decode(encoding='utf-8') curses.echo() self.cookie = RequestCookie() self.tokens = {} verifycode = '' codeString = '' password_enc = '' rsakey = '' win.addstr(7, 2, "Get BaiduID...") win.refresh() uid_cookie = auth.get_BAIDUID() if not uid_cookie: win.addstr(8, 2, " Get BaiduID failed, press any key to exit") win.refresh() win.getch() return False self.cookie.load_list(uid_cookie) win.addstr(8, 2, "Get token...") win.refresh() info = auth.get_token(self.cookie) if not info: win.addstr(9, 2, " Get Token failed, press any key to exit") win.refresh() win.getch() return False hosupport, token = info self.cookie.load_list(hosupport) self.cookie.load('cflag=65535%3A1; PANWEB=1;') self.tokens['token'] = token win.addstr(9, 2, "Get UBI...") win.refresh() ubi_cookie = auth.get_UBI(self.cookie, self.tokens) self.cookie.load_list(ubi_cookie) win.addstr(10, 2, "Check login...") win.refresh() ubi_cookie, status = auth.check_login(self.cookie, self.tokens, username) self.cookie.load_list(ubi_cookie) codeString = status['data']['codeString'] vcodetype = status['data']['vcodetype'] if codeString: win.addstr(11, 2, "Vcode is needed but not supported") win.addstr(12, 2, "Press any key to quit") win.refresh() win.getch() return False win.addstr(11, 2, "Get public key...") win.refresh() info = auth.get_public_key(self.cookie, self.tokens) pubkey = info['pubkey'] rsakey = info['key'] password_enc = util.RSA_encrypt(pubkey, password) win.addstr(12, 2, "login...") win.refresh() info = auth.post_login(self.cookie, self.tokens, username, password_enc, rsakey) errno, query = info if errno == 0: self.cookie.load_list(query) win.addstr(13, 2, "Get bds_token ...") win.refresh() bdstoken = auth.get_bdstoken(self.cookie) self.tokens['bdstoken'] = bdstoken win.addstr(14, 2, "Login finished, press any key to continue") win.refresh() win.getch() elif errno == 257: win.addstr(13, 2, "need vcode, but not supported") win.addstr(14, 2, "Press any key to quit") win.refresh() win.getch() return False elif errno == 4: win.addstr(13, 2, "invalid password!") win.addstr(14, 2, "Press any key to quit") win.refresh() win.getch() return False else: win.addstr(13, 2, "Something is wrong") win.addstr(14, 2, "Press any key to quit") win.refresh() win.getch() return False self.dump_auth(self.username, self.cookie, self.tokens) return True #------------------------------------------------- # user info area #------------------------------------------------- # | file info # | area # file list | # | # | # | #------------------------------------------------ # operation area #------------------------------------------------ def cloud_driver(self): self.item_pos = 0 self.path = '/' self.page_num = 1 self.has_next = True curses.curs_set(0) self.screen.keypad(True) curses.noecho() info, filel, filei, o = self.initialize_window() self.draw_info(info) self.draw_nav(o) self.draw_file(filel, filei) self.screen.nodelay(1) while True: c = self.screen.getch() if c == curses.KEY_UP: self.up() self.draw_current_list(filel, filei) elif c == curses.KEY_DOWN: self.down() self.draw_current_list(filel, filei) elif c == curses.KEY_RIGHT: self.enter_dir() self.draw_file(filel, filei) self.draw_info(info) elif c == curses.KEY_LEFT: self.back_dir() self.draw_file(filel, filei) self.draw_info(info) elif c == 27 or c == ord('Q') or c == ord('q'): break elif c == 10: self.download(o) elif c == ord('>'): self.next_page() self.draw_file(filel, filei) self.draw_info(info) elif c == ord('<'): self.prev_page() self.draw_file(filel, filei) self.draw_info(info) elif c == ord('R') or c == ord('r'): info.clear() o.clear() filel.clear() filei.clear() info.border(0) o.border(0) filel.border(0) filei.border(0) self.draw_info(info) self.draw_nav(o) self.draw_file(filel, filei) else: pass def next_page(self): self.files = None self.item_pos = 0 if not self.has_next: self.page_num += 1 def prev_page(self): self.files = None self.item_pos = 0 if self.page_num > 1: self.page_num -= 1 def up(self): if self.files and self.item_pos > 0: self.item_pos -= 1 def down(self): if self.files and self.item_pos < len(self.files) - 1: self.item_pos += 1 def download(self, o): if self.files and self.files[ self.item_pos] and not self.files[self.item_pos]['isdir']: self.screen.nodelay(1) end_size = self.files[self.item_pos]['size'] path = self.files[self.item_pos]['path'] o.clear() o.border(0) curses.echo() o.addstr(1, 2, "DownloadPath: (Default: ~/)") o.refresh() download_path = o.getstr(2, 2, 40).decode(encoding='utf-8') if download_path == "": download_path = expanduser("~") else: download_path = expanduser(download_path) filepath, tmp_filepath, conf_filepath = get_tmp_filepath( download_path, path[1:]) if not os.path.exists(os.path.dirname(tmp_filepath)): os.makedirs(os.path.dirname(tmp_filepath), exist_ok=True) o.clear() o.border(0) o.refresh() if os.path.exists(filepath): o.clear() o.border(0) o.addstr(1, 2, "File Already Exists.") o.addstr(2, 2, "Press Any Key to Continue") o.refresh() self.screen.getch() return o.addstr(1, 2, "Getting Download links...") o.refresh() url = pcs.get_download_link(self.cookie, self.tokens, path) if not url: o.clear() o.border(0) o.addstr(1, 2, "Failed to get url") o.addstr(2, 2, "Press ESC to abort") o.refresh() self.screen.getch() return o.addstr(2, 2, "Prepare file...") o.refresh() if os.path.exists(conf_filepath) and os.path.exists(tmp_filepath): with open(conf_filepath) as conf_fh: status = json.load(conf_fh) file_exists = True fh = open(tmp_filepath, 'rb+') else: req = net.urlopen_simple(url) if not req: o.clear() o.border(0) o.addstr(1, 2, "Failed to request") o.addstr(2, 2, "Press ESC to abort") o.refresh() self.screen.getch() return content_length = req.getheader('Content-Length') if not content_length: match = re.search('\sContent-Length:\s*(\d+)', str(req.headers)) if not match: o.clear() o.border(0) o.addstr(1, 2, "Failed to match content-length") o.addstr(2, 2, "Press ESC to abort") o.refresh() self.screen.getch() return content_length = match.group(1) size = int(content_length) if size == 0: open(filepath, 'a').close() o.clear() o.border(0) o.addstr(1, 2, "File already downloaded") o.addstr(2, 2, "Press ESC to abort") o.refresh() self.screen.getch() return file_exists = False fh = open(tmp_filepath, 'wb') try: fh.truncate(size) except (OSError, IOError): o.clear() o.border(0) o.addstr(1, 2, "Disk error (disk is full?)") o.addstr(2, 2, "Press ESC to abort") o.refresh() self.screen.getch() return start_size = 0 if file_exists: start_size, end_size, received = status offset = start_size count = 0 while offset < end_size: status = [offset, end_size, 0] count += 1 o.clear() o.border(0) c = self.screen.getch() if c == 27: with open(conf_filepath, 'w') as fh: json.dump(status, fh) break o.addstr(1, 2, "Downloading: {0} ... ".format(path)) o.refresh() req = self.get_req(url, offset, end_size) if not req: o.addstr(2, 2, "Network error{0}, retry after 3s.".format(count)) o.addstr(3, 2, "Press ESC to abort.") o.refresh() time.sleep(3) continue else: try: block = req.read(self.block_size) except: o.addstr( 2, 2, "Can not Read block, retry.".format( offset, end_size)) time.sleep(1) continue o.addstr(2, 2, "Process: {0} / {1}".format(offset, end_size)) fh.seek(offset) fh.write(block) offset += len(block) o.addstr(3, 2, "Press ESC to abort") o.refresh() def enter_dir(self): if self.files[self.item_pos] and self.files[self.item_pos]['isdir']: self.path = self.files[self.item_pos]['path'] self.files = None self.item_pos = 0 def back_dir(self): self.files = None self.item_pos = 0 if not self.path == '/' or not self.path == '': self.path = os.path.dirname(self.path) def draw_current_list(self, filel, filei): filel.clear() filei.clear() filel.border(0) filei.border(0) if self.files: index = 0 start_pos = self.item_pos if len(self.files) - self.item_pos < 26: start_pos = max(len(self.files) - 26, 0) for pindex in range(start_pos, len(self.files)): pfile = self.files[pindex] path = os.path.basename(pfile['path'])[:50] size = pfile.get('size', 0) if pfile['isdir']: human_size = '--' path = path + "/" else: human_size = util.get_human_size(pfile['size'])[0] if pindex == self.item_pos: filel.addstr(index + 1, 2, "> " + path, curses.COLOR_RED) else: filel.addstr(index + 1, 2, path) filei.addstr(index + 1, 2, human_size) index += 1 if index > 26: filel.addstr( index + 1, 2, "More {0} files...".format( len(self.files) - index + 1)) break filel.refresh() filei.refresh() def draw_file(self, filel, filei): filel.clear() filei.clear() filel.border(0) filei.border(0) if not self.cookie or not self.tokens: filel.refresh() filei.refresh() return content = pcs.list_dir(self.cookie, self.tokens, self.path, self.page_num) if not content: filel.addstr(2, 2, "Network Error - content empty") elif content.get('errno', -1) != 0: filel.addstr(2, 2, "Network Error - error") elif content['list']: # process here self.files = content['list'] self.draw_current_list(filel, filei) else: filel.addstr(2, 2, "Already last page") self.has_next = False filel.refresh() filei.refresh() def initialize_window(self): self.screen.refresh() info_x, info_y, info_w, info_h = 0, 0, 90, 4 info = curses.newwin(info_h, info_w, info_y, info_x) info.border(0) file_y, file_x, file_w, file_h = 4, 0, 60, 30 filel = curses.newwin(file_h, file_w, file_y, file_x) filel.border(0) filei_y, filei_x, filei_w, filei_h = 4, 61, 30, 30 filei = curses.newwin(filei_h, filei_w, filei_y, filei_x) filei.border(0) o_y, o_x, o_w, o_h = 34, 0, 90, 5 o = curses.newwin(o_h, o_w, o_y, o_x) o.border(0) return info, filel, filei, o def draw_info(self, info): if not self.cookie or not self.tokens: info.addstr( 1, 2, 'User: {0}, Cookie and Tokens are not available'.format( self.username)) info.addstr( 2, 2, 'Try restarting application to fix'.format( self.path, self.page_num)) info.refresh() return quota_info = pcs.get_quota(self.cookie, self.tokens) used = quota_info['used'] total = quota_info['total'] used_size = util.get_human_size(used)[0] total_size = util.get_human_size(total)[0] info.addstr( 1, 2, 'User: {2}, Quota: {0} / {1}'.format(used_size, total_size, self.username)) info.addstr(2, 2, 'Path: {0}, Page: {1}'.format(self.path, self.page_num)) info.refresh() def draw_nav(self, o): o.addstr( 1, 2, "Up/Down - Select File, Left/Right - Change Directory, Enter - Download" ) o.addstr( 2, 2, "Esc/Q - Quit, R - Refresh, F - Find, Delete - Not supported.") o.addstr(3, 2, "< - previous page, > - next page") o.refresh() def run(self, argv): if not self.profile: if not self.signin(True): return self.cloud_driver() curses.endwin() def load_auth(self, username): auth_file = os.path.join(Config.get_tmp_path(username), 'auth.json') if os.path.exists(auth_file): if time.time() - os.stat(auth_file).st_mtime < DELTA: with open(auth_file) as fh: c, tokens = json.load(fh) cookie = RequestCookie(c) return cookie, tokens return None, None def dump_auth(self, username, cookie, tokens): auth_file = os.path.join(Config.get_tmp_path(username), 'auth.json') with open(auth_file, 'w') as fh: json.dump([str(cookie), tokens], fh) def get_req(self, url, start_size, end_size): opener = request.build_opener() content_range = 'bytes={0}-{1}'.format(start_size, end_size) opener.addheaders = [ ('Range', content_range), ('User-Agent', const.USER_AGENT), ('Referer', const.PAN_REFERER), ] for i in range(RETRIES): try: return opener.open(url, timeout=8) except: return None else: return None
def __init__(self, cookies=RequestCookie()): self.cookies = cookies
def signin(self): def on_get_bdstoken(bdstoken, error=None): if error or not bdstoken: logger.error('SigninDialog.on_get_bdstoken: %s, %s' % (bdstoken, error)) self.signin_failed(_('Failed to get bdstoken!')) else: nonlocal tokens tokens['bdstoken'] = bdstoken self.update_profile(username, password, cookie, tokens, dump=True) def on_get_auth_cookie(info, error=None): if error or not info: logger.error('SigninDialog.on_get_auth_cookie: %s, %s' % (info, error)) self.signin_failed( _('Fail to get auth cookie, please try again')) else: cookie.load_list(info) self.signin_button.set_label(_('Get bdstoken...')) gutil.async_call(auth.get_bdstoken, cookie, callback=on_get_bdstoken) def on_post_login(info, error=None): if error or not info: logger.error('SigninDialog.on_post_login: %s, %s' % (info, error)) self.signin_failed(_('Login failed, please try again')) else: errno, query = info if errno == 0: cookie.load_list(query) self.signin_button.set_label(_('Get auth cookie...')) gutil.async_call(auth.get_auth_cookie, cookie, callback=on_get_auth_cookie) # 257: 需要输入验证码 elif errno == 257: nonlocal verifycode nonlocal codeString vcodetype = query['vcodetype'] codeString = query['codeString'] dialog = SigninVcodeDialog(self, username, cookie, tokens, codeString, vcodetype) response = dialog.run() verifycode = dialog.get_vcode() codeString = dialog.codeString dialog.destroy() if not (verifycode or len(verifycode) == 2 or len(verifycode) == 4): self.signin_failed( _('Please input verification code!')) return else: self.signin_button.set_label(_('Get bdstoken...')) gutil.async_call(auth.post_login, cookie, tokens, username, password_enc, rsakey, verifycode, codeString, callback=on_post_login) # 密码错误 elif errno == 4: logger.error('SigninDialog.on_post_login: %s, %s' % (info, error)) self.signin_failed(_('Password error, please try again')) # 验证码错误 elif errno == 6: self.signin_failed( _('Verfication code error, please try again')) # 需要手机号验证 elif errno == 18: self.signin_failed(_('Real name verification required!')) # 需要安全验证 elif errno == 120021: self.signin_failed(_('Security verification required!')) # 需要短信验证 elif errno == 400031: logger.error('SigninDialog.on_post_login: %s, %s' % (info, error)) self.signin_failed( _('Does not support SMS/Email verification!')) else: logger.error('SigninDialog.on_post_login: %s, %s' % (info, error)) self.signin_failed(_('Unknown error, please try again')) def on_get_public_key(info, error=None): if not info or error: logger.error('SigninDialog.on_get_public_key: %s, %s' % (info, error)) self.signin_failed( _('Failed to request public key, please try again')) else: pubkey = info['pubkey'] nonlocal rsakey rsakey = info['key'] nonlocal password_enc password_enc = util.RSA_encrypt(pubkey, password) gutil.async_call(auth.post_login, cookie, tokens, username, password_enc, rsakey, verifycode, codeString, dv, callback=on_post_login) def on_check_login(info, error=None): if not info or error: logger.error('SigninDialog.on_check_login: %s, %s' % (info, error)) self.signin_failed( _('Failed to check login, please try again')) else: ubi_cookie, status = info cookie.load_list(ubi_cookie) nonlocal codeString nonlocal verifycode codeString = status['data']['codeString'] vcodetype = status['data']['vcodetype'] if codeString: dialog = SigninVcodeDialog(self, username, cookie, tokens, codeString, vcodetype) response = dialog.run() verifycode = dialog.get_vcode() codeString = dialog.codeString dialog.destroy() if not (verifycode or len(verifycode) == 2 or len(verifycode) == 4): self.signin_failed( _('Please input verification code!')) return else: gutil.async_call(auth.get_public_key, cookie, tokens, callback=on_get_public_key) else: gutil.async_call(auth.get_public_key, cookie, tokens, callback=on_get_public_key) def on_get_UBI(ubi_cookie, error=None): if error or not ubi_cookie: logger.error('SigninDialog.on_getUBI: %s, %s' % (ubi_cookie, error)) self.signin_failed(_('Failed to get UBI, please try again.')) else: cookie.load_list(ubi_cookie) self.signin_button.set_label(_('Check login')) gutil.async_call(auth.check_login, cookie, tokens, username, dv, callback=on_check_login) def on_get_token(info, error=None): if error or not info: logger.error('SigninDialog.on_get_token: %s, %s' % (info, error)) self.signin_failed(_('Failed to get token, please try again.')) else: nonlocal tokens hosupport, token = info cookie.load_list(hosupport) cookie.load('cflag=15%3A3; PANWEB=1;') tokens['token'] = token self.signin_button.set_label(_('Get UBI...')) gutil.async_call(auth.get_UBI, cookie, tokens, callback=on_get_UBI) def on_get_BAIDUID(uid_cookie, error=None): if error or not uid_cookie: logger.error('SigninDialog.on_get_BAIDUID: %s, %s' % (uid_cookie, error)) self.signin_failed( _('Failed to get BAIDUID cookie, please try again.')) else: cookie.load_list(uid_cookie) self.signin_button.set_label(_('Get TOKEN...')) gutil.async_call(auth.get_token, cookie, callback=on_get_token) username = self.username_combo.get_child().get_text() password = self.password_entry.get_text() # 判断是否使用缓存授权信息 if self.cache_login: cookie, tokens = self.load_auth(username) if cookie and tokens: self.update_profile(username, password, cookie, tokens) return cookie = RequestCookie() tokens = {} dv = DV.get_new_dv() verifycode = '' codeString = '' password_enc = '' rsakey = '' self.signin_button.set_label(_('Get BAIDUID...')) gutil.async_call(auth.get_BAIDUID, callback=on_get_BAIDUID)
def signin(self): def on_get_bdstoken(bdstoken, error=None): if error or not bdstoken: logger.error('SigninDialog.on_get_bdstoken: %s, %s' % (bdstoken, error)) self.signin_failed(_('Failed to get bdstoken!')) else: nonlocal tokens tokens['bdstoken'] = bdstoken self.update_profile(username, password, cookie, tokens, dump=True) def on_post_login(info, error=None): if error or not info: logger.error('SigninDialog.on_post_login: %s, %s' % (info, error)) self.signin_failed( _('Login failed, please try again')) else: errno, bduss = info # 257: 需要输入验证码 if errno == 257: nonlocal verifycode nonlocal codeString vcodetype, codeString = bduss dialog = SigninVcodeDialog(self, username, cookie, tokens['token'], codeString, vcodetype) response = dialog.run() verifycode = dialog.get_vcode() codeString = dialog.codeString dialog.destroy() if not verifycode or len(verifycode) != 4: self.signin_failed(_('Please input verification code!')) return else: self.signin_button.set_label(_('Get bdstoken...')) gutil.async_call(auth.post_login, cookie, tokens['token'], username, password_enc, rsakey, verifycode, codeString, callback=on_post_login) # 密码错误 elif errno == 4: logger.error('SigninDialog.on_post_login: %s, %s' % (info, error)) self.signin_failed(_('Password error, please try again')) # 验证码错误 elif errno == 6: self.signin_failed( _('Verfication code error, please try again')) elif errno == 0: cookie.load_list(bduss) self.signin_button.set_label(_('Get bdstoken...')) gutil.async_call(auth.get_bdstoken, cookie, callback=on_get_bdstoken) else: logger.error('SigninDialog.on_post_login: %s, %s' % (info, error)) self.signin_failed(_('Unknown error, please try again')) def on_get_public_key(info, error=None): if not info or error: logger.error('SigninDialog.on_get_public_key: %s, %s' % (info, error)) self.signin_failed( _('Failed to request public key, please try again')) else: pubkey = info['pubkey'] nonlocal rsakey rsakey = info['key'] nonlocal password_enc password_enc = util.RSA_encrypt(pubkey, password) gutil.async_call(auth.post_login, cookie, tokens['token'], username, password_enc, rsakey, verifycode, codeString, callback=on_post_login) def on_check_login(info, error=None): if not info or error: logger.error('SigninDialog.on_check_login: %s, %s' % (info, error)) self.signin_failed(_('Failed to check login, please try again')) else: ubi_cookie, status = info cookie.load_list(ubi_cookie) nonlocal codeString nonlocal verifycode codeString = status['data']['codeString'] vcodetype = status['data']['vcodetype'] if codeString: dialog = SigninVcodeDialog(self, username, cookie, tokens['token'], codeString, vcodetype) response = dialog.run() verifycode = dialog.get_vcode() codeString = dialog.codeString dialog.destroy() if not verifycode or len(verifycode) != 4: self.signin_failed(_('Please input verification code!')) return else: gutil.async_call(auth.get_public_key, cookie, tokens['token'], callback=on_get_public_key) else: gutil.async_call(auth.get_public_key, cookie, tokens['token'], callback=on_get_public_key) def on_get_UBI(ubi_cookie, error=None): if error or not ubi_cookie: logger.error('SigninDialog.on_getUBI: %s, %s' % (ubi_cookie, error)) self.signin_failed(_('Failed to get UBI, please try again.')) else: cookie.load_list(ubi_cookie) self.signin_button.set_label(_('Check login')) gutil.async_call(auth.check_login, cookie, tokens['token'], username, callback=on_check_login) def on_get_token(info, error=None): if error or not info: logger.error('SigninDialog.on_get_token: %s, %s' % (info, error)) self.signin_failed(_('Failed to get token, please try again.')) else: nonlocal tokens hosupport, token = info cookie.load_list(hosupport) tokens['token'] = token self.signin_button.set_label(_('Get UBI...')) gutil.async_call(auth.get_UBI, cookie, token, callback=on_get_UBI) def on_get_BAIDUID(uid_cookie, error=None): if error or not uid_cookie: logger.error('SigninDialog.on_get_BAIDUID: %s, %s' % (uid_cookie, error)) self.signin_failed( _('Failed to get BAIDUID cookie, please try agin.')) else: cookie.load_list(uid_cookie) self.signin_button.set_label(_('Get TOKEN...')) gutil.async_call(auth.get_token, cookie, callback=on_get_token) username = self.username_combo.get_child().get_text() password = self.password_entry.get_text() # 使用本地的缓存token, 有效期是三天 if not self.password_changed and self.signin_check.get_active(): cookie, tokens = self.load_auth(username) if cookie and tokens: self.update_profile(username, password, cookie, tokens) return cookie = RequestCookie() cookie.load('cflag=65535%3A1; PANWEB=1;') tokens = {} verifycode = '' codeString = '' password_enc = '' rsakey = '' self.signin_button.set_label(_('Get BAIDUID...')) gutil.async_call(auth.get_BAIDUID, callback=on_get_BAIDUID)