%PDF- %PDF-
| Direktori : /usr/lib/calibre/calibre/utils/ |
| Current File : //usr/lib/calibre/calibre/utils/browser.py |
#!/usr/bin/env python3
# License: GPLv3 Copyright: 2010, Kovid Goyal <kovid at kovidgoyal.net>
import copy
import ssl
from mechanize import Browser as B, HTTPSHandler
from polyglot import http_client
from polyglot.http_cookie import CookieJar
class ModernHTTPSHandler(HTTPSHandler):
ssl_context = None
def https_open(self, req):
if self.client_cert_manager is not None:
key_file, cert_file = self.client_cert_manager.find_key_cert(
req.get_full_url())
if cert_file:
self.ssl_context.load_cert_chain(cert_file, key_file)
def conn_factory(hostport, **kw):
kw['context'] = self.ssl_context
return http_client.HTTPSConnection(hostport, **kw)
return self.do_open(conn_factory, req)
class Browser(B):
'''
A cloneable mechanize browser. Useful for multithreading. The idea is that
each thread has a browser clone. Every clone uses the same thread safe
cookie jar. All clones share the same browser configuration.
Also adds support for fine-tuning SSL verification via an SSL context object.
'''
handler_classes = B.handler_classes.copy()
handler_classes['https'] = ModernHTTPSHandler
def __init__(self, *args, **kwargs):
self._clone_actions = {}
sc = kwargs.pop('ssl_context', None)
if sc is None:
sc = ssl.create_default_context() if kwargs.pop('verify_ssl', True) else ssl._create_unverified_context(cert_reqs=ssl.CERT_NONE)
B.__init__(self, *args, **kwargs)
self.set_cookiejar(CookieJar())
self._ua_handlers['https'].ssl_context = sc
@property
def https_handler(self):
return self._ua_handlers['https']
def set_current_header(self, header, value=None):
found = False
q = header.lower()
remove = []
for i, (k, v) in enumerate(tuple(self.addheaders)):
if k.lower() == q:
if value:
self.addheaders[i] = (header, value)
found = True
else:
remove.append(i)
if not found:
self.addheaders.append((header, value))
if remove:
for i in reversed(remove):
del self.addheaders[i]
def current_user_agent(self):
for k, v in self.addheaders:
if k.lower() == 'user-agent':
return v
def set_user_agent(self, newval):
self.set_current_header('User-agent', newval)
def set_handle_refresh(self, *args, **kwargs):
B.set_handle_refresh(self, *args, **kwargs)
self._clone_actions['set_handle_refresh'] = ('set_handle_refresh',
args, kwargs)
def set_cookiejar(self, *args, **kwargs):
B.set_cookiejar(self, *args, **kwargs)
self._clone_actions['set_cookiejar'] = ('set_cookiejar', args, kwargs)
def set_cookie(self, name, value, domain, path='/'):
return self.set_simple_cookie(name, value, domain, path=path)
@property
def cookiejar(self):
return self._clone_actions['set_cookiejar'][1][0]
def set_handle_redirect(self, *args, **kwargs):
B.set_handle_redirect(self, *args, **kwargs)
self._clone_actions['set_handle_redirect'] = ('set_handle_redirect',
args, kwargs)
def set_handle_equiv(self, *args, **kwargs):
B.set_handle_equiv(self, *args, **kwargs)
self._clone_actions['set_handle_equiv'] = ('set_handle_equiv',
args, kwargs)
def set_handle_gzip(self, *args, **kwargs):
B.set_handle_gzip(self, *args, **kwargs)
self._clone_actions['set_handle_gzip'] = ('set_handle_gzip',
args, kwargs)
def set_debug_redirects(self, *args, **kwargs):
B.set_debug_redirects(self, *args, **kwargs)
self._clone_actions['set_debug_redirects'] = ('set_debug_redirects',
args, kwargs)
def set_debug_responses(self, *args, **kwargs):
B.set_debug_responses(self, *args, **kwargs)
self._clone_actions['set_debug_responses'] = ('set_debug_responses',
args, kwargs)
def set_debug_http(self, *args, **kwargs):
B.set_debug_http(self, *args, **kwargs)
self._clone_actions['set_debug_http'] = ('set_debug_http',
args, kwargs)
def set_handle_robots(self, *args, **kwargs):
B.set_handle_robots(self, *args, **kwargs)
self._clone_actions['set_handle_robots'] = ('set_handle_robots',
args, kwargs)
def set_proxies(self, *args, **kwargs):
B.set_proxies(self, *args, **kwargs)
self._clone_actions['set_proxies'] = ('set_proxies', args, kwargs)
def add_password(self, *args, **kwargs):
B.add_password(self, *args, **kwargs)
self._clone_actions['add_password'] = ('add_password', args, kwargs)
def add_proxy_password(self, *args, **kwargs):
B.add_proxy_password(self, *args, **kwargs)
self._clone_actions['add_proxy_password'] = ('add_proxy_password', args, kwargs)
def clone_browser(self):
clone = self.__class__()
clone.https_handler.ssl_context = self.https_handler.ssl_context
clone.addheaders = copy.deepcopy(self.addheaders)
for func, args, kwargs in self._clone_actions.values():
func = getattr(clone, func)
func(*args, **kwargs)
return clone
if __name__ == '__main__':
from calibre import browser
from pprint import pprint
orig = browser()
clone = orig.clone_browser()
pprint(orig._ua_handlers)
pprint(clone._ua_handlers)
assert orig._ua_handlers.keys() == clone._ua_handlers.keys()
assert orig._ua_handlers['_cookies'].cookiejar is \
clone._ua_handlers['_cookies'].cookiejar
assert orig.addheaders == clone.addheaders