Example #1
0
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)
Example #5
0
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)
Example #7
0
    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())
Example #8
0
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"
Example #9
0
    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
Example #10
0
    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
Example #11
0
    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)