def handler(request): """Scheme handler for qute:// URLs. Args: request: QNetworkRequest to answer to. Return: A QNetworkReply. """ try: mimetype, data = qutescheme.data_for_url(request.url()) except qutescheme.NoHandlerFound: errorstr = "No handler found for {}!".format( request.url().toDisplayString()) return networkreply.ErrorNetworkReply( request, errorstr, QNetworkReply.ContentNotFoundError) except qutescheme.QuteSchemeOSError as e: return networkreply.ErrorNetworkReply( request, str(e), QNetworkReply.ContentNotFoundError) except qutescheme.QuteSchemeError as e: return networkreply.ErrorNetworkReply(request, e.errorstring, e.error) except qutescheme.Redirect as e: qtutils.ensure_valid(e.url) return networkreply.RedirectNetworkReply(e.url) return networkreply.FixedDataNetworkReply(request, data, mimetype)
def createRequest(self, _op, request, _outgoing_data): """Create a new request. Args: request: const QNetworkRequest & req _op: Operation op _outgoing_data: QIODevice * outgoingData Return: A QNetworkReply. """ try: mimetype, data = qutescheme.data_for_url(request.url()) except qutescheme.NoHandlerFound: errorstr = "No handler found for {}!".format( request.url().toDisplayString()) return networkreply.ErrorNetworkReply( request, errorstr, QNetworkReply.ContentNotFoundError, self.parent()) except qutescheme.QuteSchemeOSError as e: return networkreply.ErrorNetworkReply( request, str(e), QNetworkReply.ContentNotFoundError, self.parent()) except qutescheme.QuteSchemeError as e: return networkreply.ErrorNetworkReply(request, e.errorstring, e.error, self.parent()) except qutescheme.Redirect as e: qtutils.ensure_valid(e.url) return networkreply.RedirectNetworkReply(e.url, self.parent()) return networkreply.FixedDataNetworkReply(request, data, mimetype, self.parent())
def createRequest(self, op, req, outgoing_data): """Return a new QNetworkReply object. Args: op: Operation op req: const QNetworkRequest & req outgoing_data: QIODevice * outgoingData Return: A QNetworkReply. """ if proxymod.application_factory is not None: proxy_error = proxymod.application_factory.get_error() if proxy_error is not None: return networkreply.ErrorNetworkReply( req, proxy_error, QNetworkReply.UnknownProxyError, self) if not req.url().isValid(): log.network.debug("Ignoring invalid requested URL: {}".format( req.url().errorString())) return networkreply.ErrorNetworkReply( req, "Invalid request URL", QNetworkReply.HostNotFoundError, self) for header, value in shared.custom_headers(url=req.url()): req.setRawHeader(header, value) tab = self._get_tab() current_url = QUrl() if tab is not None: try: current_url = tab.url() except RuntimeError: # We could be in the middle of the webpage shutdown here. pass request = interceptors.Request(first_party_url=current_url, request_url=req.url()) interceptors.run(request) if request.is_blocked: return networkreply.ErrorNetworkReply( req, HOSTBLOCK_ERROR_STRING, QNetworkReply.ContentAccessDenied, self) if 'log-requests' in objects.debug_flags: operation = debug.qenum_key(QNetworkAccessManager, op) operation = operation.replace('Operation', '').upper() log.network.debug("{} {}, first-party {}".format( operation, req.url().toDisplayString(), current_url.toDisplayString())) scheme = req.url().scheme() if scheme in self._scheme_handlers: result = self._scheme_handlers[scheme](req, op, current_url) if result is not None: result.setParent(self) return result self.set_referer(req, current_url) return super().createRequest(op, req, outgoing_data)
def createRequest(self, op, req, outgoing_data): """Return a new QNetworkReply object. Args: op: Operation op req: const QNetworkRequest & req outgoing_data: QIODevice * outgoingData Return: A QNetworkReply. """ proxy_factory = objreg.get('proxy-factory', None) if proxy_factory is not None: proxy_error = proxy_factory.get_error() if proxy_error is not None: return networkreply.ErrorNetworkReply( req, proxy_error, QNetworkReply.UnknownProxyError, self) scheme = req.url().scheme() if scheme in self._scheme_handlers: result = self._scheme_handlers[scheme](req) if result is not None: result.setParent(self) return result for header, value in shared.custom_headers(): req.setRawHeader(header, value) host_blocker = objreg.get('host-blocker') if host_blocker.is_blocked(req.url()): log.webview.info("Request to {} blocked by host blocker.".format( req.url().host())) return networkreply.ErrorNetworkReply( req, HOSTBLOCK_ERROR_STRING, QNetworkReply.ContentAccessDenied, self) # There are some scenarios where we can't figure out current_url: # - There's a generic NetworkManager, e.g. for downloads # - The download was in a tab which is now closed. current_url = QUrl() if self._tab_id is not None: assert self._win_id is not None try: tab = objreg.get('tab', scope='tab', window=self._win_id, tab=self._tab_id) current_url = tab.url() except (KeyError, RuntimeError): # https://github.com/qutebrowser/qutebrowser/issues/889 # Catching RuntimeError because we could be in the middle of # the webpage shutdown here. current_url = QUrl() self.set_referer(req, current_url) return super().createRequest(op, req, outgoing_data)
def handler(request, operation, current_url): """Scheme handler for qute:// URLs. Args: request: QNetworkRequest to answer to. operation: The HTTP operation being done. current_url: The page we're on currently. Return: A QNetworkReply. """ if operation != QNetworkAccessManager.GetOperation: return networkreply.ErrorNetworkReply( request, "Unsupported request type", QNetworkReply.ContentOperationNotPermittedError) url = request.url() if ((url.scheme(), url.host(), url.path()) == ('qute', 'settings', '/set')): if current_url != QUrl('qute://settings/'): log.network.warning("Blocking malicious request from {} to {}" .format(current_url.toDisplayString(), url.toDisplayString())) return networkreply.ErrorNetworkReply( request, "Invalid qute://settings request", QNetworkReply.ContentAccessDenied) try: mimetype, data = qutescheme.data_for_url(url) except qutescheme.Error as e: errors = { qutescheme.NotFoundError: QNetworkReply.ContentNotFoundError, qutescheme.UrlInvalidError: QNetworkReply.ContentOperationNotPermittedError, qutescheme.RequestDeniedError: QNetworkReply.ContentAccessDenied, qutescheme.SchemeOSError: QNetworkReply.ContentNotFoundError, qutescheme.Error: QNetworkReply.InternalServerError, } exctype = type(e) log.misc.error("{} while handling qute://* URL".format( exctype.__name__)) return networkreply.ErrorNetworkReply(request, str(e), errors[exctype]) except qutescheme.Redirect as e: qtutils.ensure_valid(e.url) return networkreply.RedirectNetworkReply(e.url) return networkreply.FixedDataNetworkReply(request, data, mimetype)
def handler(request, operation, current_url): """Scheme handler for qute:// URLs. Args: request: QNetworkRequest to answer to. operation: The HTTP operation being done. current_url: The page we're on currently. Return: A QNetworkReply. """ if operation != QNetworkAccessManager.GetOperation: return networkreply.ErrorNetworkReply( request, "Unsupported request type", QNetworkReply.ContentOperationNotPermittedError) url = request.url() if ((url.scheme(), url.host(), url.path()) == ('qute', 'settings', '/set')): if current_url != QUrl('qute://settings/'): log.webview.warning( "Blocking malicious request from {} to {}".format( current_url.toDisplayString(), url.toDisplayString())) return networkreply.ErrorNetworkReply( request, "Invalid qute://settings request", QNetworkReply.ContentAccessDenied) try: mimetype, data = qutescheme.data_for_url(url) except qutescheme.NoHandlerFound: errorstr = "No handler found for {}!".format(url.toDisplayString()) return networkreply.ErrorNetworkReply( request, errorstr, QNetworkReply.ContentNotFoundError) except qutescheme.QuteSchemeOSError as e: return networkreply.ErrorNetworkReply( request, str(e), QNetworkReply.ContentNotFoundError) except qutescheme.QuteSchemeError as e: return networkreply.ErrorNetworkReply(request, e.errorstring, e.error) except qutescheme.Redirect as e: qtutils.ensure_valid(e.url) return networkreply.RedirectNetworkReply(e.url) return networkreply.FixedDataNetworkReply(request, data, mimetype)
def createRequest(self, _op, request, _outgoing_data): """Create a new request. Args: request: const QNetworkRequest & req _op: Operation op _outgoing_data: QIODevice * outgoingData Return: A QNetworkReply. """ path = request.url().path() host = request.url().host() # An url like "qute:foo" is split as "scheme:path", not "scheme:host". log.misc.debug("url: {}, path: {}, host {}".format( request.url().toDisplayString(), path, host)) try: handler = HANDLERS[path] except KeyError: try: handler = HANDLERS[host] except KeyError: errorstr = "No handler found for {}!".format( request.url().toDisplayString()) return networkreply.ErrorNetworkReply( request, errorstr, QNetworkReply.ContentNotFoundError, self.parent()) try: data = handler(self._win_id, request) except OSError as e: return networkreply.ErrorNetworkReply( request, str(e), QNetworkReply.ContentNotFoundError, self.parent()) except QuteSchemeError as e: return networkreply.ErrorNetworkReply(request, e.errorstring, e.error, self.parent()) mimetype, _encoding = mimetypes.guess_type(request.url().fileName()) if mimetype is None: mimetype = 'text/html' return networkreply.FixedDataNetworkReply(request, data, mimetype, self.parent())
def test_error_network_reply(qtbot, req): reply = networkreply.ErrorNetworkReply(req, "This is an error", QNetworkReply.UnknownNetworkError) with qtbot.waitSignals([reply.error, reply.finished], order='strict'): pass reply.abort() # shouldn't do anything assert reply.request() == req assert reply.url() == req.url() assert reply.openMode() == QIODevice.ReadOnly assert reply.isFinished() assert not reply.isRunning() assert reply.bytesAvailable() == 0 assert reply.readData(1) == b'' assert reply.error() == QNetworkReply.UnknownNetworkError assert reply.errorString() == "This is an error"
def createRequest(self, op, req, outgoing_data): """Return a new QNetworkReply object. Args: op: Operation op req: const QNetworkRequest & req outgoing_data: QIODevice * outgoingData Return: A QNetworkReply. """ proxy_factory = objreg.get('proxy-factory', None) if proxy_factory is not None: proxy_error = proxy_factory.get_error() if proxy_error is not None: return networkreply.ErrorNetworkReply( req, proxy_error, QNetworkReply.UnknownProxyError, self) scheme = req.url().scheme() if scheme in self._scheme_handlers: result = self._scheme_handlers[scheme].createRequest( op, req, outgoing_data) if result is not None: return result for header, value in shared.custom_headers(): req.setRawHeader(header, value) host_blocker = objreg.get('host-blocker') if host_blocker.is_blocked(req.url()): log.webview.info("Request to {} blocked by host blocker.".format( req.url().host())) return networkreply.ErrorNetworkReply( req, HOSTBLOCK_ERROR_STRING, QNetworkReply.ContentAccessDenied, self) # There are some scenarios where we can't figure out current_url: # - There's a generic NetworkManager, e.g. for downloads # - The download was in a tab which is now closed. current_url = QUrl() if self._tab_id is not None: try: tab = objreg.get('tab', scope='tab', window=self._win_id, tab=self._tab_id) current_url = tab.url() except (KeyError, RuntimeError, TypeError): # https://github.com/qutebrowser/qutebrowser/issues/889 # Catching RuntimeError and TypeError because we could be in # the middle of the webpage shutdown here. current_url = QUrl() self.set_referer(req, current_url) if PYQT_VERSION < 0x050301: # WORKAROUND (remove this when we bump the requirements to 5.3.1) # # If we don't disable our message handler, we get a freeze if a # warning is printed due to a PyQt bug, e.g. when clicking a # currency on http://ch.mouser.com/localsites/ # # See http://www.riverbankcomputing.com/pipermail/pyqt/2014-June/034420.html with log.disable_qt_msghandler(): reply = super().createRequest(op, req, outgoing_data) else: reply = super().createRequest(op, req, outgoing_data) return reply
def createRequest(self, op, req, outgoing_data): """Return a new QNetworkReply object. Extend QNetworkAccessManager::createRequest to save requests in self._requests and handle custom schemes. Args: op: Operation op req: const QNetworkRequest & req outgoing_data: QIODevice * outgoingData Return: A QNetworkReply. """ scheme = req.url().scheme() if scheme in self._scheme_handlers: result = self._scheme_handlers[scheme].createRequest( op, req, outgoing_data) if result is not None: return result host_blocker = objreg.get('host-blocker') if (op == QNetworkAccessManager.GetOperation and host_blocker.is_blocked(req.url())): log.webview.info("Request to {} blocked by host blocker.".format( req.url().host())) return networkreply.ErrorNetworkReply( req, HOSTBLOCK_ERROR_STRING, QNetworkReply.ContentAccessDenied, self) if config.get('network', 'do-not-track'): dnt = '1'.encode('ascii') else: dnt = '0'.encode('ascii') req.setRawHeader('DNT'.encode('ascii'), dnt) req.setRawHeader('X-Do-Not-Track'.encode('ascii'), dnt) # Load custom headers custom_headers = config.get('network', 'custom-headers') if custom_headers is not None: for header, value in custom_headers.items(): req.setRawHeader(header.encode('ascii'), value.encode('ascii')) # There are some scenarios where we can't figure out current_url: # - There's a generic NetworkManager, e.g. for downloads # - The download was in a tab which is now closed. current_url = QUrl() if self._tab_id is not None: try: tab = objreg.get('tab', scope='tab', window=self._win_id, tab=self._tab_id) current_url = tab.url() except (KeyError, RuntimeError, TypeError): # https://github.com/The-Compiler/qutebrowser/issues/889 # Catching RuntimeError and TypeError because we could be in # the middle of the webpage shutdown here. current_url = QUrl() self.set_referer(req, current_url) accept_language = config.get('network', 'accept-language') if accept_language is not None: req.setRawHeader('Accept-Language'.encode('ascii'), accept_language.encode('ascii')) if PYQT_VERSION < 0x050301: # WORKAROUND (remove this when we bump the requirements to 5.3.1) # # If we don't disable our message handler, we get a freeze if a # warning is printed due to a PyQt bug, e.g. when clicking a # currency on http://ch.mouser.com/localsites/ # # See http://www.riverbankcomputing.com/pipermail/pyqt/2014-June/034420.html with log.disable_qt_msghandler(): reply = super().createRequest(op, req, outgoing_data) else: reply = super().createRequest(op, req, outgoing_data) self._requests.append(reply) reply.destroyed.connect(self._requests.remove) return reply
def createRequest(self, op, req, outgoing_data): """Return a new QNetworkReply object. Args: op: Operation op req: const QNetworkRequest & req outgoing_data: QIODevice * outgoingData Return: A QNetworkReply. """ if proxymod.application_factory is not None: proxy_error = proxymod.application_factory.get_error() if proxy_error is not None: return networkreply.ErrorNetworkReply( req, proxy_error, QNetworkReply.UnknownProxyError, self) for header, value in shared.custom_headers(url=req.url()): req.setRawHeader(header, value) # There are some scenarios where we can't figure out current_url: # - There's a generic NetworkManager, e.g. for downloads # - The download was in a tab which is now closed. current_url = QUrl() if self._tab_id is not None: assert self._win_id is not None try: tab = objreg.get('tab', scope='tab', window=self._win_id, tab=self._tab_id) current_url = tab.url() except (KeyError, RuntimeError): # https://github.com/qutebrowser/qutebrowser/issues/889 # Catching RuntimeError because we could be in the middle of # the webpage shutdown here. current_url = QUrl() request = interceptors.Request(first_party_url=current_url, request_url=req.url()) interceptors.run(request) if request.is_blocked: return networkreply.ErrorNetworkReply( req, HOSTBLOCK_ERROR_STRING, QNetworkReply.ContentAccessDenied, self) if 'log-requests' in objects.debug_flags: operation = debug.qenum_key(QNetworkAccessManager, op) operation = operation.replace('Operation', '').upper() log.webview.debug("{} {}, first-party {}".format( operation, req.url().toDisplayString(), current_url.toDisplayString())) scheme = req.url().scheme() if scheme in self._scheme_handlers: result = self._scheme_handlers[scheme](req, op, current_url) if result is not None: result.setParent(self) return result self.set_referer(req, current_url) return super().createRequest(op, req, outgoing_data)