def get_proxy_url(url): proxies = getproxies() parsed = urlparse.urlparse(url) proxy_keys = [ parsed.scheme + '://' + parsed.netloc, parsed.scheme, 'all://' + parsed.netloc, 'all' ] # Set port if not defined explicitly in url. port = parsed.port if port is None and parsed.scheme == 'http': port = 80 elif port is None and parsed.scheme == 'https': port = 443 hostname = parsed.hostname is not None and parsed.hostname or '' # Determine if proxy should be used based on no_proxy entries. # Note this does not support no_proxy ip or cidr entries. if proxy_bypass("%s:%s" % (hostname, port)): return None for key in proxy_keys: if key in proxies: return proxies[key] return None
async def _do_connect(self, protocol_factory: IProtocolFactory) -> None: first_exception = None server_list = await self._resolve_server() for server in server_list: host = server.host port = server.port endpoint: IStreamClientEndpoint try: if self.https_proxy_endpoint and not proxy_bypass(host.decode()): logger.debug( "Connecting to %s:%i via %s", host.decode("ascii"), port, self.https_proxy_endpoint, ) connect_headers = Headers() # Determine whether we need to set Proxy-Authorization headers if self.https_proxy_creds: # Set a Proxy-Authorization header connect_headers.addRawHeader( b"Proxy-Authorization", self.https_proxy_creds.as_proxy_authorization_value(), ) endpoint = HTTPConnectProxyEndpoint( self._reactor, self.https_proxy_endpoint, host, port, headers=connect_headers, ) else: logger.debug("Connecting to %s:%i", host.decode("ascii"), port) # not using a proxy endpoint = HostnameEndpoint(self._reactor, host, port) if self._tls_options: endpoint = wrapClientTLS(self._tls_options, endpoint) result = await make_deferred_yieldable( endpoint.connect(protocol_factory) ) return result except Exception as e: logger.info( "Failed to connect to %s:%i: %s", host.decode("ascii"), port, e ) if not first_exception: first_exception = e # We return the first failure because that's probably the most interesting. if first_exception: raise first_exception # This shouldn't happen as we should always have at least one host/port # to try and if that doesn't work then we'll have an exception. raise Exception("Failed to resolve server %r" % (self._parsed_uri.netloc,))
def build_opener(apiurl, user, password, cookie_path, debuglevel=0, capath=None, cafile=None, headers=()): """build urllib opener for given name/password it creates * HTTPSHandler with proper ssl context * HTTPCookieProcessor with a link to cookiejar * HTTPBasicAuthHandler with user/password * proxyhandler which respects no_proxy variable """ handlers = list() if hasattr(ssl, "SSLContext"): #allow only sslv3 and tlsv1, but not sslv2 ctx = ssl.SSLContext(protocol=ssl.PROTOCOL_SSLv23) ctx.options |= ssl.OP_NO_SSLv2 ctx.verify_mode = ssl.CERT_REQUIRED ctx.set_default_verify_paths() if cafile or capath: if ctx.load_verify_locations(capath=capath, cafile=cafile) != -1: raise Exception("load_verify_locations failed for capath={}, cafile={}".format(capath, cafile)) #TODO: debuglevel httpshandler = HTTPSHandler(debuglevel=debuglevel, context=ctx, check_hostname=True) handlers.append(httpshandler) try: # TODO is this correct? cookie_file = os.path.expanduser(cookie_path) cookiejar = LWPCookieJar(cookie_file) cookiejar.load(ignore_discard=True) except (OSError, IOError, AttributeError): try: os.open(cookie_file, os.O_WRONLY | os.O_CREAT, mode=0o600) except: #TODO: log it cookiejar = CookieJar() handlers.append(HTTPCookieProcessor(cookiejar)) authhandler = HTTPBasicAuthHandler( HTTPPasswordMgrWithDefaultRealm()) authhandler.add_password(None, apiurl, bytes(user, "utf-8"), bytes(password, "ascii")) handlers.append(authhandler) # proxy handling if not proxy_bypass(apiurl): proxyhandler = ProxyHandler() else: proxyhandler = ProxyHandler({}) handlers.append(proxyhandler) opener = _build_opener(*handlers) from bslib import __version__ opener.addheaders = [("User-agent", "bslib/{}".format(__version__)), ] for h in headers: opener.addheaders(h) return opener
def get_env_proxy_for_url(url: URL) -> Tuple[URL, Optional[BasicAuth]]: """Get a permitted proxy for the given URL from the env.""" if url.host is not None and proxy_bypass(url.host): raise LookupError(f"Proxying is disallowed for `{url.host!r}`") proxies_in_env = proxies_from_env() try: proxy_info = proxies_in_env[url.scheme] except KeyError: raise LookupError(f"No proxies found for `{url!s}` in the env") else: return proxy_info.proxy, proxy_info.proxy_auth
def process_request(self, request, spider): if 'proxy' in request.meta: print('httpproxy.process_request') elif not self.proxies: return parsed = urlparse_cached(request) scheme = parsed.scheme if scheme in ('http', 'https') and proxy_bypass(parsed.hostname): return if scheme in self.proxies: self._set_proxy(request, scheme)
def _get_proxy_from_environ_or_os_config(url: str, hostname: str) -> Optional[str]: """ Returns: proxy url to use "" if no proxy should be used `None` if no config was found """ # Retrieve proxies from environ vars then (depending on platform) os configuration if proxy_bypass(hostname): return "" # no proxy should be used proxies = getproxies() proxy_type = "https" if url.startswith("https://") else "http" proxy_url = proxies.get(proxy_type) return proxy_url
def process_request(self, request, spider): creds, proxy_url = None, None if 'proxy' in request.meta: if request.meta['proxy'] is not None: creds, proxy_url = self._get_proxy(request.meta['proxy'], '') elif self.proxies: parsed = urlparse_cached(request) scheme = parsed.scheme if (( # 'no_proxy' is only supported by http schemes scheme not in ('http', 'https') or not proxy_bypass(parsed.hostname)) and scheme in self.proxies): creds, proxy_url = self.proxies[scheme] self._set_proxy_and_creds(request, proxy_url, creds)
def process_request(self, request: Request, spider): if 'proxy' in request.meta: if request.meta['proxy'] is None: return creds, proxy_url = self._get_proxy(request.meta['proxy'], '') request.meta['proxy'] = proxy_url if creds and not request.headers.get('Proxy-Authorization'): request.headers['Proxy-Authorization'] = b'Basic ' + creds return elif not self.proxies: return parsed = urlparse_cached(request) scheme = parsed.scheme if scheme in ('http', 'https') and proxy_bypass(parsed.hostname): return if scheme in self.proxies: self._set_proxy(request, scheme)
def process_request(self, request, spider): # ignore if proxy is already set if 'proxy' in request.meta: if request.meta['proxy'] is None: return # extract credentials if present creds, proxy_url = self._get_proxy(request.meta['proxy'], '') request.meta['proxy'] = proxy_url if creds and not request.headers.get('Proxy-Authorization'): request.headers['Proxy-Authorization'] = b'Basic ' + creds return elif not self.proxies: return parsed = urlparse_cached(request) scheme = parsed.scheme # 'no_proxy' is only supported by http schemes if scheme in ('http', 'https') and proxy_bypass(parsed.hostname): return if scheme in self.proxies: self._set_proxy(request, scheme)
def process_request(self, request, spider): # ignore if proxy is already set if "proxy" in request.meta: if request.meta["proxy"] is None: return # extract credentials if present creds, proxy_url = self._get_proxy(request.meta["proxy"], "") request.meta["proxy"] = proxy_url if creds and not request.headers.get("Proxy-Authorization"): request.headers["Proxy-Authorization"] = b"Basic " + creds return elif not self.proxies: return parsed = urlparse_cached(request) scheme = parsed.scheme # 'no_proxy' is only supported by http schemes if scheme in ("http", "https") and proxy_bypass(parsed.hostname): return if scheme in self.proxies: self._set_proxy(request, scheme)
def open_http(self, url, data=None): """Use HTTP protocol.""" from eventlib.green import httplib user_passwd = None proxy_passwd = None if isinstance(url, str): host, selector = splithost(url) if host: user_passwd, host = splituser(host) host = unquote(host) realhost = host else: host, selector = url # check whether the proxy contains authorization information proxy_passwd, host = splituser(host) # now we proceed with the url we want to obtain urltype, rest = splittype(selector) url = rest user_passwd = None if urltype.lower() != 'http': realhost = None else: realhost, rest = splithost(rest) if realhost: user_passwd, realhost = splituser(realhost) if user_passwd: selector = "%s://%s%s" % (urltype, realhost, rest) if proxy_bypass(realhost): host = realhost #print "proxy via http:", host, selector if not host: raise IOError('http error', 'no host given') if proxy_passwd: import base64 proxy_auth = base64.b64encode(proxy_passwd).strip() else: proxy_auth = None if user_passwd: import base64 auth = base64.b64encode(user_passwd).strip() else: auth = None h = httplib.HTTP(host) if data is not None: h.putrequest('POST', selector) h.putheader('Content-Type', 'application/x-www-form-urlencoded') h.putheader('Content-Length', '%d' % len(data)) else: h.putrequest('GET', selector) if proxy_auth: h.putheader('Proxy-Authorization', 'Basic %s' % proxy_auth) if auth: h.putheader('Authorization', 'Basic %s' % auth) if realhost: h.putheader('Host', realhost) for args in self.addheaders: h.putheader(*args) h.endheaders() if data is not None: h.send(data) errcode, errmsg, headers = h.getreply() if errcode == -1: # something went wrong with the HTTP status line raise IOError('http protocol error', 0, 'got a bad status line', None) fp = h.getfile() if errcode == 200: return addinfourl(fp, headers, "http:" + url) else: if data is None: return self.http_error(url, fp, errcode, errmsg, headers) else: return self.http_error(url, fp, errcode, errmsg, headers, data)
def _create_connection(self): """ 创建HTTP/HTTPS客户端连接。""" # :::::代理 # 添加系统环境代理 is_proxied_https_request = False actual_host = self.source.hostname actual_port = self.source.port proxies = self.source.proxies proxy = None if proxies: # 若设置了代理直接走代理,不需要旁路判断 if proxy_bypass(self.source.hostname): env_proxies = {} else: env_proxies = getproxies() for k, v in env_proxies.items(): proxies.setdefault(k, v) # 选择代理 proxy = proxies.get(self.source.protocol, None) if proxy is not None: if self.source.protocol == 'https': is_proxied_https_request = True scheme, netloc, path, params, query, fragment = urlparse( proxy, 'http') if not netloc: netloc, path = path, netloc proxy_url = urlunparse( (scheme, netloc, path, params, query, fragment)) parse = urlparse(proxy_url) actual_host = parse.hostname actual_port = parse.port # :::::建立连接 if self.source.protocol == 'http': conn_hdl = HTTPConnection else: conn_hdl = partial_func(HTTPSConnection, context=self.options.get( 'https_context', HTTPClient.HTTPS_CONTEXT)) conn = conn_hdl(host=actual_host, port=actual_port, timeout=self.options.get('timeout', HTTPClient.CONNECT_TIMEOUT)) # :::::构建请求头 request_range = None if self.partial: request_range = (self.progress.begin + self.progress.increment_go, self.progress.end) request_uri, headers = self._build_request_headers(request_range) if is_proxied_https_request: conn.set_tunnel(self.source.netloc) conn.connect() # 若非代理下request_uri使用path_query if not proxy: parse_uri = urlparse(request_uri) request_uri = parse_uri.path if parse_uri.query: request_uri += '?' + parse_uri.query conn.request('GET', request_uri, None, dict(headers)) return conn
def _build_opener(apiurl): from osc.core import __version__ global config if 'last_opener' not in _build_opener.__dict__: _build_opener.last_opener = (None, None) if apiurl == _build_opener.last_opener[0]: return _build_opener.last_opener[1] # respect no_proxy env variable if proxy_bypass(apiurl): # initialize with empty dict proxyhandler = ProxyHandler({}) else: # read proxies from env proxyhandler = ProxyHandler() # workaround for http://bugs.python.org/issue9639 authhandler_class = HTTPBasicAuthHandler if sys.version_info >= (2, 6, 6) and sys.version_info < (2, 7, 1) \ and not 'reset_retry_count' in dir(HTTPBasicAuthHandler): print('warning: your urllib2 version seems to be broken. ' \ 'Using a workaround for http://bugs.python.org/issue9639', file=sys.stderr) class OscHTTPBasicAuthHandler(HTTPBasicAuthHandler): def http_error_401(self, *args): response = HTTPBasicAuthHandler.http_error_401(self, *args) self.retried = 0 return response def http_error_404(self, *args): self.retried = 0 return None authhandler_class = OscHTTPBasicAuthHandler elif sys.version_info >= (2, 6, 6) and sys.version_info < (2, 7, 1): class OscHTTPBasicAuthHandler(HTTPBasicAuthHandler): def http_error_404(self, *args): self.reset_retry_count() return None authhandler_class = OscHTTPBasicAuthHandler elif sys.version_info >= (2, 6, 5) and sys.version_info < (2, 6, 6): # workaround for broken urllib2 in python 2.6.5: wrong credentials # lead to an infinite recursion class OscHTTPBasicAuthHandler(HTTPBasicAuthHandler): def retry_http_basic_auth(self, host, req, realm): # don't retry if auth failed if req.get_header(self.auth_header, None) is not None: return None return HTTPBasicAuthHandler.retry_http_basic_auth( self, host, req, realm) authhandler_class = OscHTTPBasicAuthHandler options = config['api_host_options'][apiurl] # with None as first argument, it will always use this username/password # combination for urls for which arg2 (apisrv) is a super-url authhandler = authhandler_class( \ HTTPPasswordMgrWithDefaultRealm()) authhandler.add_password(None, apiurl, options['user'], options['pass']) if options['sslcertck']: try: from . import oscssl from M2Crypto import m2urllib2 except ImportError as e: print(e) raise NoSecureSSLError( 'M2Crypto is needed to access %s in a secure way.\nPlease install python-m2crypto.' % apiurl) cafile = options.get('cafile', None) capath = options.get('capath', None) if not cafile and not capath: for i in ['/etc/pki/tls/cert.pem', '/etc/ssl/certs']: if os.path.isfile(i): cafile = i break elif os.path.isdir(i): capath = i break if not cafile and not capath: raise oscerr.OscIOError(None, 'No CA certificates found') ctx = oscssl.mySSLContext() if ctx.load_verify_locations(capath=capath, cafile=cafile) != 1: raise oscerr.OscIOError(None, 'No CA certificates found') opener = m2urllib2.build_opener( ctx, oscssl.myHTTPSHandler(ssl_context=ctx, appname='osc'), HTTPCookieProcessor(cookiejar), authhandler, proxyhandler) else: handlers = [HTTPCookieProcessor(cookiejar), authhandler, proxyhandler] try: # disable ssl cert check in python >= 2.7.9 ctx = ssl._create_unverified_context() handlers.append(HTTPSHandler(context=ctx)) except AttributeError: pass print( "WARNING: SSL certificate checks disabled. Connection is insecure!\n", file=sys.stderr) opener = build_opener(*handlers) opener.addheaders = [('User-agent', 'osc/%s' % __version__)] _build_opener.last_opener = (apiurl, opener) return opener
def build_opener(apiurl, user, password, cookie_path, debuglevel=0, capath=None, cafile=None, headers=()): """build urllib opener for given name/password it creates * HTTPSHandler with proper ssl context * HTTPCookieProcessor with a link to cookiejar * HTTPBasicAuthHandler with user/password * proxyhandler which respects no_proxy variable """ handlers = list() if hasattr(ssl, "SSLContext"): #allow only sslv3 and tlsv1, but not sslv2 ctx = ssl.SSLContext(protocol=ssl.PROTOCOL_SSLv23) ctx.options |= ssl.OP_NO_SSLv2 ctx.verify_mode = ssl.CERT_REQUIRED ctx.set_default_verify_paths() if cafile or capath: if ctx.load_verify_locations(capath=capath, cafile=cafile) != -1: raise Exception( "load_verify_locations failed for capath={}, cafile={}". format(capath, cafile)) #TODO: debuglevel httpshandler = HTTPSHandler(debuglevel=debuglevel, context=ctx, check_hostname=True) handlers.append(httpshandler) try: # TODO is this correct? cookie_file = os.path.expanduser(cookie_path) cookiejar = LWPCookieJar(cookie_file) cookiejar.load(ignore_discard=True) except (OSError, IOError, AttributeError): try: os.open(cookie_file, os.O_WRONLY | os.O_CREAT, mode=0o600) except: #TODO: log it cookiejar = CookieJar() handlers.append(HTTPCookieProcessor(cookiejar)) authhandler = HTTPBasicAuthHandler(HTTPPasswordMgrWithDefaultRealm()) authhandler.add_password(None, apiurl, bytes(user, "utf-8"), bytes(password, "ascii")) handlers.append(authhandler) # proxy handling if not proxy_bypass(apiurl): proxyhandler = ProxyHandler() else: proxyhandler = ProxyHandler({}) handlers.append(proxyhandler) opener = _build_opener(*handlers) from bslib import __version__ opener.addheaders = [ ("User-agent", "bslib/{}".format(__version__)), ] for h in headers: opener.addheaders(h) return opener
def _run(argv=None, exec=True) -> Optional[AnkiApp]: """Start AnkiQt application or reuse an existing instance if one exists. If the function is invoked with exec=False, the AnkiQt will not enter the main event loop - instead the application object will be returned. The 'exec' and 'argv' arguments will be useful for testing purposes. If no 'argv' is supplied then 'sys.argv' will be used. """ global mw global profiler if argv is None: argv = sys.argv # parse args opts, args = parseArgs(argv) if opts.version: print(f"Anki {appVersion}") return None elif opts.syncserver: from anki.syncserver import serve serve() return None if PROFILE_CODE: profiler = cProfile.Profile() profiler.enable() # default to specified/system language before getting user's preference so that we can localize some more strings lang = anki.lang.get_def_lang(opts.lang) anki.lang.set_lang(lang[1], locale_dir()) # profile manager pm = None try: pm = ProfileManager(opts.base) pmLoadResult = pm.setupMeta() except AnkiRestart as error: if error.exitcode: sys.exit(error.exitcode) return None except: # will handle below traceback.print_exc() pm = None if pm: # gl workarounds setupGL(pm) # apply user-provided scale factor os.environ["QT_SCALE_FACTOR"] = str(pm.uiScale()) # opt in to full hidpi support? if not os.environ.get("ANKI_NOHIGHDPI"): QCoreApplication.setAttribute(Qt.AA_EnableHighDpiScaling) os.environ["QT_ENABLE_HIGHDPI_SCALING"] = "1" os.environ["QT_SCALE_FACTOR_ROUNDING_POLICY"] = "PassThrough" # Opt into software rendering. Useful for buggy systems. if os.environ.get("ANKI_SOFTWAREOPENGL"): QCoreApplication.setAttribute(Qt.AA_UseSoftwareOpenGL) if ( isWin and (qtminor == 14 or (qtminor == 15 and qtpoint == 0)) and "QT_QPA_PLATFORM" not in os.environ ): os.environ["QT_QPA_PLATFORM"] = "windows:altgr" # create the app QCoreApplication.setApplicationName("Anki") QGuiApplication.setDesktopFileName("anki.desktop") app = AnkiApp(argv) if app.secondInstance(): # we've signaled the primary instance, so we should close return None if not pm: QMessageBox.critical( None, tr(TR.QT_MISC_ERROR), tr(TR.PROFILES_COULD_NOT_CREATE_DATA_FOLDER), ) return None # disable icons on mac; this must be done before window created if isMac: app.setAttribute(Qt.AA_DontShowIconsInMenus) # disable help button in title bar on qt versions that support it if isWin and qtminor >= 10: QApplication.setAttribute(Qt.AA_DisableWindowContextHelpButton) # proxy configured? from urllib.request import getproxies, proxy_bypass disable_proxies = False try: if "http" in getproxies(): # if it's not set up to bypass localhost, we'll # need to disable proxies in the webviews if not proxy_bypass("127.0.0.1"): disable_proxies = True except UnicodeDecodeError: # proxy_bypass can't handle unicode in hostnames; assume we need # to disable proxies disable_proxies = True if disable_proxies: print("webview proxy use disabled") proxy = QNetworkProxy() proxy.setType(QNetworkProxy.NoProxy) QNetworkProxy.setApplicationProxy(proxy) # we must have a usable temp dir try: tempfile.gettempdir() except: QMessageBox.critical( None, tr(TR.QT_MISC_ERROR), tr(TR.QT_MISC_NO_TEMP_FOLDER), ) return None if pmLoadResult.firstTime: pm.setDefaultLang(lang[0]) if pmLoadResult.loadError: QMessageBox.warning( None, tr(TR.PROFILES_PREFS_CORRUPT_TITLE), tr(TR.PROFILES_PREFS_FILE_IS_CORRUPT), ) if opts.profile: pm.openProfile(opts.profile) # i18n & backend backend = setupLangAndBackend(pm, app, opts.lang, pmLoadResult.firstTime) driver = pm.video_driver() if isLin and driver == VideoDriver.OpenGL: from aqt.utils import gfxDriverIsBroken if gfxDriverIsBroken(): pm.set_video_driver(driver.next()) QMessageBox.critical( None, tr(TR.QT_MISC_ERROR), tr(TR.QT_MISC_INCOMPATIBLE_VIDEO_DRIVER), ) sys.exit(1) # load the main window import aqt.main mw = aqt.main.AnkiQt(app, pm, backend, opts, args) if exec: app.exec() else: return app if PROFILE_CODE: write_profile_results() return None
def _build_opener(apiurl): from osc.core import __version__ global config class OscHTTPBasicAuthHandler(HTTPBasicAuthHandler, object): # python2: inherit from object in order to make it a new-style class # (HTTPBasicAuthHandler is not a new-style class) def _rewind_request(self, req): if hasattr(req.data, 'seek'): # if the request is issued again (this time with an # Authorization header), the file's offset has to be # repositioned to the beginning of the file (otherwise, # a 0-length body is sent which most likely does not match # the Content-Length header (if present)) req.data.seek(0) def retry_http_basic_auth(self, host, req, realm): self._rewind_request(req) return super(self.__class__, self).retry_http_basic_auth(host, req, realm) if 'last_opener' not in _build_opener.__dict__: _build_opener.last_opener = (None, None) if apiurl == _build_opener.last_opener[0]: return _build_opener.last_opener[1] # respect no_proxy env variable if proxy_bypass(apiurl): # initialize with empty dict proxyhandler = ProxyHandler({}) else: # read proxies from env proxyhandler = ProxyHandler() authhandler_class = OscHTTPBasicAuthHandler # workaround for http://bugs.python.org/issue9639 if sys.version_info >= (2, 6, 6) and sys.version_info < (2, 7, 9): class OscHTTPBasicAuthHandlerCompat(OscHTTPBasicAuthHandler): # The following two functions were backported from upstream 2.7. def http_error_auth_reqed(self, authreq, host, req, headers): authreq = headers.get(authreq, None) if authreq: mo = AbstractBasicAuthHandler.rx.search(authreq) if mo: scheme, quote, realm = mo.groups() if quote not in ['"', "'"]: warnings.warn("Basic Auth Realm was unquoted", UserWarning, 2) if scheme.lower() == 'basic': return self.retry_http_basic_auth(host, req, realm) def retry_http_basic_auth(self, host, req, realm): self._rewind_request(req) user, pw = self.passwd.find_user_password(realm, host) if pw is not None: raw = "%s:%s" % (user, pw) auth = 'Basic %s' % base64.b64encode(raw).strip() if req.get_header(self.auth_header, None) == auth: return None req.add_unredirected_header(self.auth_header, auth) return self.parent.open(req, timeout=req.timeout) else: return None authhandler_class = OscHTTPBasicAuthHandlerCompat options = config['api_host_options'][apiurl] # with None as first argument, it will always use this username/password # combination for urls for which arg2 (apisrv) is a super-url authhandler = authhandler_class( \ HTTPPasswordMgrWithDefaultRealm()) authhandler.add_password(None, apiurl, options['user'], options['pass']) if options['sslcertck']: try: from . import oscssl from M2Crypto import m2urllib2 except ImportError as e: print(e) raise NoSecureSSLError( 'M2Crypto is needed to access %s in a secure way.\nPlease install python-m2crypto.' % apiurl) cafile = options.get('cafile', None) capath = options.get('capath', None) if not cafile and not capath: for i in ['/etc/pki/tls/cert.pem', '/etc/ssl/certs']: if os.path.isfile(i): cafile = i break elif os.path.isdir(i): capath = i break if not cafile and not capath: raise oscerr.OscIOError( None, 'No CA certificates found. (You may want to install ca-certificates-mozilla package)' ) ctx = oscssl.mySSLContext() if ctx.load_verify_locations(capath=capath, cafile=cafile) != 1: raise oscerr.OscIOError( None, 'No CA certificates found. (You may want to install ca-certificates-mozilla package)' ) opener = m2urllib2.build_opener( ctx, oscssl.myHTTPSHandler(ssl_context=ctx, appname='osc'), HTTPCookieProcessor(cookiejar), authhandler, proxyhandler) else: handlers = [HTTPCookieProcessor(cookiejar), authhandler, proxyhandler] try: # disable ssl cert check in python >= 2.7.9 ctx = ssl._create_unverified_context() handlers.append(HTTPSHandler(context=ctx)) except AttributeError: pass print( "WARNING: SSL certificate checks disabled. Connection is insecure!\n", file=sys.stderr) opener = build_opener(*handlers) opener.addheaders = [('User-agent', 'osc/%s' % __version__)] _build_opener.last_opener = (apiurl, opener) return opener
def _build_opener(apiurl): from osc.core import __version__ global config if 'last_opener' not in _build_opener.__dict__: _build_opener.last_opener = (None, None) if apiurl == _build_opener.last_opener[0]: return _build_opener.last_opener[1] # respect no_proxy env variable if proxy_bypass(apiurl): # initialize with empty dict proxyhandler = ProxyHandler({}) else: # read proxies from env proxyhandler = ProxyHandler() # workaround for http://bugs.python.org/issue9639 authhandler_class = HTTPBasicAuthHandler if sys.version_info >= (2, 6, 6) and sys.version_info < (2, 7, 1) \ and not 'reset_retry_count' in dir(HTTPBasicAuthHandler): print('warning: your urllib2 version seems to be broken. ' \ 'Using a workaround for http://bugs.python.org/issue9639', file=sys.stderr) class OscHTTPBasicAuthHandler(HTTPBasicAuthHandler): def http_error_401(self, *args): response = HTTPBasicAuthHandler.http_error_401(self, *args) self.retried = 0 return response def http_error_404(self, *args): self.retried = 0 return None authhandler_class = OscHTTPBasicAuthHandler elif sys.version_info >= (2, 6, 6) and sys.version_info < (2, 7, 1): class OscHTTPBasicAuthHandler(HTTPBasicAuthHandler): def http_error_404(self, *args): self.reset_retry_count() return None authhandler_class = OscHTTPBasicAuthHandler elif sys.version_info >= (2, 6, 5) and sys.version_info < (2, 6, 6): # workaround for broken urllib2 in python 2.6.5: wrong credentials # lead to an infinite recursion class OscHTTPBasicAuthHandler(HTTPBasicAuthHandler): def retry_http_basic_auth(self, host, req, realm): # don't retry if auth failed if req.get_header(self.auth_header, None) is not None: return None return HTTPBasicAuthHandler.retry_http_basic_auth(self, host, req, realm) authhandler_class = OscHTTPBasicAuthHandler options = config['api_host_options'][apiurl] # with None as first argument, it will always use this username/password # combination for urls for which arg2 (apisrv) is a super-url authhandler = authhandler_class( \ HTTPPasswordMgrWithDefaultRealm()) authhandler.add_password(None, apiurl, options['user'], options['pass']) if options['sslcertck']: try: from . import oscssl from M2Crypto import m2urllib2 except ImportError as e: print(e) raise NoSecureSSLError('M2Crypto is needed to access %s in a secure way.\nPlease install python-m2crypto.' % apiurl) cafile = options.get('cafile', None) capath = options.get('capath', None) if not cafile and not capath: for i in ['/etc/pki/tls/cert.pem', '/etc/ssl/certs']: if os.path.isfile(i): cafile = i break elif os.path.isdir(i): capath = i break if not cafile and not capath: raise oscerr.OscIOError(None, 'No CA certificates found') ctx = oscssl.mySSLContext() if ctx.load_verify_locations(capath=capath, cafile=cafile) != 1: raise oscerr.OscIOError(None, 'No CA certificates found') opener = m2urllib2.build_opener(ctx, oscssl.myHTTPSHandler(ssl_context=ctx, appname='osc'), HTTPCookieProcessor(cookiejar), authhandler, proxyhandler) else: handlers = [HTTPCookieProcessor(cookiejar), authhandler, proxyhandler] try: # disable ssl cert check in python >= 2.7.9 ctx = ssl._create_unverified_context() handlers.append(HTTPSHandler(context=ctx)) except AttributeError: pass print("WARNING: SSL certificate checks disabled. Connection is insecure!\n", file=sys.stderr) opener = build_opener(*handlers) opener.addheaders = [('User-agent', 'osc/%s' % __version__)] _build_opener.last_opener = (apiurl, opener) return opener
def _run(argv=None, exec=True): """Start AnkiQt application or reuse an existing instance if one exists. If the function is invoked with exec=False, the AnkiQt will not enter the main event loop - instead the application object will be returned. The 'exec' and 'argv' arguments will be useful for testing purposes. If no 'argv' is supplied then 'sys.argv' will be used. """ global mw if argv is None: argv = sys.argv # parse args opts, args = parseArgs(argv) # profile manager from aqt.profiles import ProfileManager pm = ProfileManager(opts.base) # gl workarounds setupGL(pm) # opt in to full hidpi support? if not os.environ.get("ANKI_NOHIGHDPI"): QCoreApplication.setAttribute(Qt.AA_EnableHighDpiScaling) # Opt into software rendering. Useful for buggy systems. if os.environ.get("ANKI_SOFTWAREOPENGL"): QCoreApplication.setAttribute(Qt.AA_UseSoftwareOpenGL) # create the app QCoreApplication.setApplicationName("Anki") QGuiApplication.setDesktopFileName("anki.desktop") app = AnkiApp(argv) if app.secondInstance(): # we've signaled the primary instance, so we should close return # disable icons on mac; this must be done before window created if isMac: app.setAttribute(Qt.AA_DontShowIconsInMenus) # proxy configured? from urllib.request import proxy_bypass, getproxies if 'http' in getproxies(): # if it's not set up to bypass localhost, we'll # need to disable proxies in the webviews if not proxy_bypass("127.0.0.1"): print("webview proxy use disabled") proxy = QNetworkProxy() proxy.setType(QNetworkProxy.NoProxy) QNetworkProxy.setApplicationProxy(proxy) # we must have a usable temp dir try: tempfile.gettempdir() except: QMessageBox.critical( None, "Error", """\ No usable temporary folder found. Make sure C:\\temp exists or TEMP in your \ environment points to a valid, writable folder.""") return pm.setupMeta() if opts.profile: pm.openProfile(opts.profile) # i18n setupLang(pm, app, opts.lang) if isLin and pm.glMode() == "auto": from aqt.utils import gfxDriverIsBroken if gfxDriverIsBroken(): pm.nextGlMode() QMessageBox.critical( None, "Error", "Your video driver is incompatible. Please start Anki again, and Anki will switch to a slower, more compatible mode." ) sys.exit(1) # load the main window import aqt.main mw = aqt.main.AnkiQt(app, pm, opts, args) if exec: app.exec() else: return app
def _build_opener(apiurl): from osc.core import __version__ global config if 'last_opener' not in _build_opener.__dict__: _build_opener.last_opener = (None, None) if apiurl == _build_opener.last_opener[0]: return _build_opener.last_opener[1] # respect no_proxy env variable if proxy_bypass(apiurl): # initialize with empty dict proxyhandler = ProxyHandler({}) else: # read proxies from env proxyhandler = ProxyHandler() # workaround for http://bugs.python.org/issue9639 authhandler_class = HTTPBasicAuthHandler if sys.version_info >= (2, 6, 6) and sys.version_info < (2, 7, 9): class OscHTTPBasicAuthHandler(HTTPBasicAuthHandler): # The following two functions were backported from upstream 2.7. def http_error_auth_reqed(self, authreq, host, req, headers): authreq = headers.get(authreq, None) if authreq: mo = AbstractBasicAuthHandler.rx.search(authreq) if mo: scheme, quote, realm = mo.groups() if quote not in ['"', "'"]: warnings.warn("Basic Auth Realm was unquoted", UserWarning, 2) if scheme.lower() == 'basic': return self.retry_http_basic_auth(host, req, realm) def retry_http_basic_auth(self, host, req, realm): user, pw = self.passwd.find_user_password(realm, host) if pw is not None: raw = "%s:%s" % (user, pw) auth = 'Basic %s' % base64.b64encode(raw).strip() if req.get_header(self.auth_header, None) == auth: return None req.add_unredirected_header(self.auth_header, auth) return self.parent.open(req, timeout=req.timeout) else: return None authhandler_class = OscHTTPBasicAuthHandler options = config['api_host_options'][apiurl] # with None as first argument, it will always use this username/password # combination for urls for which arg2 (apisrv) is a super-url authhandler = authhandler_class( \ HTTPPasswordMgrWithDefaultRealm()) authhandler.add_password(None, apiurl, options['user'], options['pass']) if options['sslcertck']: try: from . import oscssl from M2Crypto import m2urllib2 except ImportError as e: print(e) raise NoSecureSSLError('M2Crypto is needed to access %s in a secure way.\nPlease install python-m2crypto.' % apiurl) cafile = options.get('cafile', None) capath = options.get('capath', None) if not cafile and not capath: for i in ['/etc/pki/tls/cert.pem', '/etc/ssl/certs']: if os.path.isfile(i): cafile = i break elif os.path.isdir(i): capath = i break if not cafile and not capath: raise oscerr.OscIOError(None, 'No CA certificates found. (You may want to install ca-certificates-mozilla package)') ctx = oscssl.mySSLContext() if ctx.load_verify_locations(capath=capath, cafile=cafile) != 1: raise oscerr.OscIOError(None, 'No CA certificates found. (You may want to install ca-certificates-mozilla package)') opener = m2urllib2.build_opener(ctx, oscssl.myHTTPSHandler(ssl_context=ctx, appname='osc'), HTTPCookieProcessor(cookiejar), authhandler, proxyhandler) else: handlers = [HTTPCookieProcessor(cookiejar), authhandler, proxyhandler] try: # disable ssl cert check in python >= 2.7.9 ctx = ssl._create_unverified_context() handlers.append(HTTPSHandler(context=ctx)) except AttributeError: pass print("WARNING: SSL certificate checks disabled. Connection is insecure!\n", file=sys.stderr) opener = build_opener(*handlers) opener.addheaders = [('User-agent', 'osc/%s' % __version__)] _build_opener.last_opener = (apiurl, opener) return opener
def _run(argv=None, exec=True): """Start AnkiQt application or reuse an existing instance if one exists. If the function is invoked with exec=False, the AnkiQt will not enter the main event loop - instead the application object will be returned. The 'exec' and 'argv' arguments will be useful for testing purposes. If no 'argv' is supplied then 'sys.argv' will be used. """ global mw if argv is None: argv = sys.argv # parse args opts, args = parseArgs(argv) # profile manager pm = ProfileManager(opts.base) pmLoadResult = pm.setupMeta() # gl workarounds setupGL(pm) # opt in to full hidpi support? if not os.environ.get("ANKI_NOHIGHDPI"): QCoreApplication.setAttribute(Qt.AA_EnableHighDpiScaling) os.environ["QT_ENABLE_HIGHDPI_SCALING"] = "1" os.environ["QT_SCALE_FACTOR_ROUNDING_POLICY"] = "PassThrough" # Opt into software rendering. Useful for buggy systems. if os.environ.get("ANKI_SOFTWAREOPENGL"): QCoreApplication.setAttribute(Qt.AA_UseSoftwareOpenGL) # apply user-provided scale factor os.environ["QT_SCALE_FACTOR"] = str(pm.uiScale()) # create the app QCoreApplication.setApplicationName("Anki") QGuiApplication.setDesktopFileName("anki.desktop") app = AnkiApp(argv) if app.secondInstance(): # we've signaled the primary instance, so we should close return # disable icons on mac; this must be done before window created if isMac: app.setAttribute(Qt.AA_DontShowIconsInMenus) # disable help button in title bar on qt versions that support it if isWin and qtminor >= 10: QApplication.setAttribute(Qt.AA_DisableWindowContextHelpButton) # proxy configured? from urllib.request import proxy_bypass, getproxies if "http" in getproxies(): # if it's not set up to bypass localhost, we'll # need to disable proxies in the webviews if not proxy_bypass("127.0.0.1"): print("webview proxy use disabled") proxy = QNetworkProxy() proxy.setType(QNetworkProxy.NoProxy) QNetworkProxy.setApplicationProxy(proxy) # we must have a usable temp dir try: tempfile.gettempdir() except: QMessageBox.critical( None, "Error", """\ No usable temporary folder found. Make sure C:\\temp exists or TEMP in your \ environment points to a valid, writable folder.""", ) return if pmLoadResult.loadError: QMessageBox.warning( None, "Preferences Corrupt", """\ Anki's prefs21.db file was corrupt and has been recreated. If you were using multiple \ profiles, please add them back using the same names to recover your cards.""", ) if opts.profile: pm.openProfile(opts.profile) # i18n setupLang(pm, app, opts.lang) if isLin and pm.glMode() == "auto": from aqt.utils import gfxDriverIsBroken if gfxDriverIsBroken(): pm.nextGlMode() QMessageBox.critical( None, "Error", "Your video driver is incompatible. Please start Anki again, and Anki will switch to a slower, more compatible mode.", ) sys.exit(1) # load the main window import aqt.main mw = aqt.main.AnkiQt(app, pm, opts, args) if exec: app.exec() else: return app
def _run(argv=None, exec=True): """Start AnkiQt application or reuse an existing instance if one exists. If the function is invoked with exec=False, the AnkiQt will not enter the main event loop - instead the application object will be returned. The 'exec' and 'argv' arguments will be useful for testing purposes. If no 'argv' is supplied then 'sys.argv' will be used. """ global mw if argv is None: argv = sys.argv # parse args opts, args = parseArgs(argv) opts.base = opts.base or "" opts.profile = opts.profile or "" # profile manager from aqt.profiles import ProfileManager pm = ProfileManager(opts.base) # gl workarounds setupGL(pm) # opt in to full hidpi support? if not os.environ.get("ANKI_NOHIGHDPI"): QCoreApplication.setAttribute(Qt.AA_EnableHighDpiScaling) # create the app app = AnkiApp(argv) QCoreApplication.setApplicationName("Anki") if app.secondInstance(): # we've signaled the primary instance, so we should close return # disable icons on mac; this must be done before window created if isMac: app.setAttribute(Qt.AA_DontShowIconsInMenus) # proxy configured? from urllib.request import proxy_bypass, getproxies if 'http' in getproxies(): # if it's not set up to bypass localhost, we'll # need to disable proxies in the webviews if not proxy_bypass("127.0.0.1"): print("webview proxy use disabled") proxy = QNetworkProxy() proxy.setType(QNetworkProxy.NoProxy) QNetworkProxy.setApplicationProxy(proxy) # we must have a usable temp dir try: tempfile.gettempdir() except: QMessageBox.critical( None, "Error", """\ No usable temporary folder found. Make sure C:\\temp exists or TEMP in your \ environment points to a valid, writable folder.""") return pm.setupMeta() if opts.profile: pm.openProfile(opts.profile) # i18n setupLang(pm, app, opts.lang) # remaining pm init pm.ensureProfile() # load the main window import aqt.main mw = aqt.main.AnkiQt(app, pm, opts, args) if exec: app.exec() else: return app
def _run(argv: Optional[list[str]] = None, exec: bool = True) -> Optional[AnkiApp]: """Start AnkiQt application or reuse an existing instance if one exists. If the function is invoked with exec=False, the AnkiQt will not enter the main event loop - instead the application object will be returned. The 'exec' and 'argv' arguments will be useful for testing purposes. If no 'argv' is supplied then 'sys.argv' will be used. """ global mw global profiler if argv is None: argv = sys.argv # parse args opts, args = parseArgs(argv) if opts.version: print(f"Anki {appVersion}") return None elif opts.syncserver: from anki.syncserver import serve serve() return None if PROFILE_CODE: profiler = cProfile.Profile() profiler.enable() if (getattr(sys, "frozen", False) and os.getenv("QT_QPA_PLATFORM") == "wayland" and not os.getenv("ANKI_WAYLAND")): # users need to opt in to wayland support, given the issues it has print("Wayland support is disabled by default due to bugs.") print("You can force it on with an env var: ANKI_WAYLAND=1") os.environ["QT_QPA_PLATFORM"] = "xcb" # default to specified/system language before getting user's preference so that we can localize some more strings lang = anki.lang.get_def_lang(opts.lang) anki.lang.set_lang(lang[1]) # profile manager pm = None try: pm = ProfileManager(opts.base) pmLoadResult = pm.setupMeta() except: # will handle below traceback.print_exc() pm = None if pm: # gl workarounds setupGL(pm) # apply user-provided scale factor os.environ["QT_SCALE_FACTOR"] = str(pm.uiScale()) # opt in to full hidpi support? if not os.environ.get("ANKI_NOHIGHDPI") and qtmajor == 5: QCoreApplication.setAttribute( Qt.ApplicationAttribute.AA_EnableHighDpiScaling) # type: ignore QCoreApplication.setAttribute( Qt.ApplicationAttribute.AA_UseHighDpiPixmaps) # type: ignore os.environ["QT_ENABLE_HIGHDPI_SCALING"] = "1" os.environ["QT_SCALE_FACTOR_ROUNDING_POLICY"] = "PassThrough" # Opt into software rendering. Useful for buggy systems. if os.environ.get("ANKI_SOFTWAREOPENGL"): QCoreApplication.setAttribute( Qt.ApplicationAttribute.AA_UseSoftwareOpenGL) if (isWin and qtmajor == 5 and (qtminor == 14 or (qtminor == 15 and qtpoint == 0)) and "QT_QPA_PLATFORM" not in os.environ): os.environ["QT_QPA_PLATFORM"] = "windows:altgr" # create the app QCoreApplication.setApplicationName("Anki") QGuiApplication.setDesktopFileName("anki.desktop") app = AnkiApp(argv) if app.secondInstance(): # we've signaled the primary instance, so we should close return None if not pm: QMessageBox.critical( None, tr.qt_misc_error(), tr.profiles_could_not_create_data_folder(), ) return None # disable icons on mac; this must be done before window created if isMac: app.setAttribute(Qt.ApplicationAttribute.AA_DontShowIconsInMenus) # disable help button in title bar on qt versions that support it if isWin and qtmajor == 5 and qtminor >= 10: QApplication.setAttribute( QApplication.Attribute. AA_DisableWindowContextHelpButton # type: ignore ) # proxy configured? from urllib.request import getproxies, proxy_bypass disable_proxies = False try: if "http" in getproxies(): # if it's not set up to bypass localhost, we'll # need to disable proxies in the webviews if not proxy_bypass("127.0.0.1"): disable_proxies = True except UnicodeDecodeError: # proxy_bypass can't handle unicode in hostnames; assume we need # to disable proxies disable_proxies = True if disable_proxies: print("webview proxy use disabled") proxy = QNetworkProxy() proxy.setType(QNetworkProxy.ProxyType.NoProxy) QNetworkProxy.setApplicationProxy(proxy) # we must have a usable temp dir try: tempfile.gettempdir() except: QMessageBox.critical( None, tr.qt_misc_error(), tr.qt_misc_no_temp_folder(), ) return None # make image resources available from aqt.utils import aqt_data_folder QDir.addSearchPath("icons", os.path.join(aqt_data_folder(), "qt", "icons")) if pmLoadResult.firstTime: pm.setDefaultLang(lang[0]) if pmLoadResult.loadError: QMessageBox.warning( None, tr.profiles_prefs_corrupt_title(), tr.profiles_prefs_file_is_corrupt(), ) if opts.profile: pm.openProfile(opts.profile) # i18n & backend backend = setupLangAndBackend(pm, app, opts.lang, pmLoadResult.firstTime) driver = pm.video_driver() if isLin and driver == VideoDriver.OpenGL: from aqt.utils import gfxDriverIsBroken if gfxDriverIsBroken(): pm.set_video_driver(driver.next()) QMessageBox.critical( None, tr.qt_misc_error(), tr.qt_misc_incompatible_video_driver(), ) sys.exit(1) # load the main window import aqt.main mw = aqt.main.AnkiQt(app, pm, backend, opts, args) if exec: app.exec() else: return app if PROFILE_CODE: write_profile_results() return None
def _build_opener(url): from osc.core import __version__ global config apiurl = urljoin(*parse_apisrv_url(None, url)) if "last_opener" not in _build_opener.__dict__: _build_opener.last_opener = (None, None) if apiurl == _build_opener.last_opener[0]: return _build_opener.last_opener[1] # respect no_proxy env variable if proxy_bypass(apiurl): # initialize with empty dict proxyhandler = ProxyHandler({}) else: # read proxies from env proxyhandler = ProxyHandler() # workaround for http://bugs.python.org/issue9639 authhandler_class = HTTPBasicAuthHandler if ( sys.version_info >= (2, 6, 6) and sys.version_info < (2, 7, 1) and not "reset_retry_count" in dir(HTTPBasicAuthHandler) ): print( "warning: your urllib2 version seems to be broken. " "Using a workaround for http://bugs.python.org/issue9639", file=sys.stderr, ) class OscHTTPBasicAuthHandler(HTTPBasicAuthHandler): def http_error_401(self, *args): response = HTTPBasicAuthHandler.http_error_401(self, *args) self.retried = 0 return response def http_error_404(self, *args): self.retried = 0 return None authhandler_class = OscHTTPBasicAuthHandler elif sys.version_info >= (2, 6, 6) and sys.version_info < (2, 7, 99): class OscHTTPBasicAuthHandler(HTTPBasicAuthHandler): def http_error_404(self, *args): self.reset_retry_count() return None authhandler_class = OscHTTPBasicAuthHandler elif sys.version_info >= (2, 6, 5) and sys.version_info < (2, 6, 6): # workaround for broken urllib2 in python 2.6.5: wrong credentials # lead to an infinite recursion class OscHTTPBasicAuthHandler(HTTPBasicAuthHandler): def retry_http_basic_auth(self, host, req, realm): # don't retry if auth failed if req.get_header(self.auth_header, None) is not None: return None return HTTPBasicAuthHandler.retry_http_basic_auth(self, host, req, realm) authhandler_class = OscHTTPBasicAuthHandler options = config["api_host_options"][apiurl] # with None as first argument, it will always use this username/password # combination for urls for which arg2 (apisrv) is a super-url authhandler = authhandler_class(HTTPPasswordMgrWithDefaultRealm()) authhandler.add_password(None, apiurl, options["user"], options["pass"]) if options["sslcertck"]: try: from . import oscssl from M2Crypto import m2urllib2 except ImportError as e: print(e) raise NoSecureSSLError( "M2Crypto is needed to access %s in a secure way.\nPlease install python-m2crypto." % apiurl ) cafile = options.get("cafile", None) capath = options.get("capath", None) if not cafile and not capath: for i in ["/etc/pki/tls/cert.pem", "/etc/ssl/certs"]: if os.path.isfile(i): cafile = i break elif os.path.isdir(i): capath = i break if not cafile and not capath: raise Exception("No CA certificates found") ctx = oscssl.mySSLContext() if ctx.load_verify_locations(capath=capath, cafile=cafile) != 1: raise Exception("No CA certificates found") opener = m2urllib2.build_opener( ctx, oscssl.myHTTPSHandler(ssl_context=ctx, appname="osc"), HTTPCookieProcessor(cookiejar), authhandler, proxyhandler, ) else: print("WARNING: SSL certificate checks disabled. Connection is insecure!\n", file=sys.stderr) opener = build_opener(HTTPCookieProcessor(cookiejar), authhandler, proxyhandler) opener.addheaders = [("User-agent", "osc/%s" % __version__)] _build_opener.last_opener = (apiurl, opener) return opener