diff options
author | Florian Bruhin <me@the-compiler.org> | 2021-03-19 12:48:05 +0100 |
---|---|---|
committer | Florian Bruhin <me@the-compiler.org> | 2021-03-19 17:59:47 +0100 |
commit | 046148fa8fac770b4e1816af4b9342f17bc361d4 (patch) | |
tree | 718b33ba51cb9cafd64c64dfe2cb93acad71731b | |
parent | 2f3ae984d04261d1df735f8688fb8d5e6013675f (diff) | |
download | qutebrowser-046148fa8fac770b4e1816af4b9342f17bc361d4.tar.gz qutebrowser-046148fa8fac770b4e1816af4b9342f17bc361d4.zip |
Improve certificate error formatting
-rw-r--r-- | qutebrowser/browser/shared.py | 2 | ||||
-rw-r--r-- | qutebrowser/browser/webkit/certificateerror.py | 17 | ||||
-rw-r--r-- | qutebrowser/utils/usertypes.py | 4 | ||||
-rw-r--r-- | tests/unit/browser/webkit/test_certificateerror.py | 73 |
4 files changed, 93 insertions, 3 deletions
diff --git a/qutebrowser/browser/shared.py b/qutebrowser/browser/shared.py index 7e2b6dc2a..532ccb91b 100644 --- a/qutebrowser/browser/shared.py +++ b/qutebrowser/browser/shared.py @@ -179,7 +179,7 @@ def ignore_certificate_error( err_template = jinja.environment.from_string(""" <p>Error while loading <b>{{url.toDisplayString()}}</b>:</p> - <p>{{error|replace('\n', '<br>')|safe}}</p> + {{error.html()|safe}} """.strip()) msg = err_template.render(url=url, error=error) diff --git a/qutebrowser/browser/webkit/certificateerror.py b/qutebrowser/browser/webkit/certificateerror.py index 68c0de775..09237dae9 100644 --- a/qutebrowser/browser/webkit/certificateerror.py +++ b/qutebrowser/browser/webkit/certificateerror.py @@ -23,7 +23,7 @@ from typing import Sequence from PyQt5.QtNetwork import QSslError -from qutebrowser.utils import usertypes, utils, debug +from qutebrowser.utils import usertypes, utils, debug, jinja class CertificateErrorWrapper(usertypes.AbstractCertificateErrorWrapper): @@ -34,7 +34,7 @@ class CertificateErrorWrapper(usertypes.AbstractCertificateErrorWrapper): self._errors = tuple(errors) # needs to be hashable def __str__(self) -> str: - return '\n'.join('- ' + err.errorString() for err in self._errors) + return '\n'.join(err.errorString() for err in self._errors) def __repr__(self) -> str: return utils.get_repr( @@ -52,3 +52,16 @@ class CertificateErrorWrapper(usertypes.AbstractCertificateErrorWrapper): def is_overridable(self) -> bool: return True + + def html(self): + if len(self._errors) == 1: + return super().html() + + template = jinja.environment.from_string(""" + <ul> + {% for err in errors %} + <li>{{err.errorString()}}</li> + {% endfor %} + </ul> + """.strip()) + return template.render(errors=self._errors) diff --git a/qutebrowser/utils/usertypes.py b/qutebrowser/utils/usertypes.py index dd2535e26..4408ce6cb 100644 --- a/qutebrowser/utils/usertypes.py +++ b/qutebrowser/utils/usertypes.py @@ -19,6 +19,7 @@ """Custom useful data types.""" +import html import operator import enum import dataclasses @@ -492,6 +493,9 @@ class AbstractCertificateErrorWrapper: def is_overridable(self) -> bool: raise NotImplementedError + def html(self) -> str: + return f'<p>{html.escape(str(self))}</p>' + @dataclasses.dataclass class NavigationRequest: diff --git a/tests/unit/browser/webkit/test_certificateerror.py b/tests/unit/browser/webkit/test_certificateerror.py new file mode 100644 index 000000000..e615854ca --- /dev/null +++ b/tests/unit/browser/webkit/test_certificateerror.py @@ -0,0 +1,73 @@ +# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et: + +# Copyright 2021 Florian Bruhin (The Compiler) <mail@qutebrowser.org> +# +# This file is part of qutebrowser. +# +# qutebrowser is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# qutebrowser is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with qutebrowser. If not, see <https://www.gnu.org/licenses/>. + +import pytest +from PyQt5.QtNetwork import QSslError + +from qutebrowser.browser.webkit import certificateerror + + +class FakeError: + + def __init__(self, msg): + self.msg = msg + + def errorString(self): + return self.msg + + +@pytest.mark.parametrize('errors, expected', [ + ( + [QSslError(QSslError.UnableToGetIssuerCertificate)], + ['<p>The issuer certificate could not be found</p>'], + ), + ( + [ + QSslError(QSslError.UnableToGetIssuerCertificate), + QSslError(QSslError.UnableToDecryptCertificateSignature), + ], + [ + '<ul>', + '<li>The issuer certificate could not be found</li>', + '<li>The certificate signature could not be decrypted</li>', + '</ul>', + ], + ), + + ( + [FakeError('Escaping test: <>')], + ['<p>Escaping test: <></p>'], + ), + ( + [ + FakeError('Escaping test 1: <>'), + FakeError('Escaping test 2: <>'), + ], + [ + '<ul>', + '<li>Escaping test 1: <></li>', + '<li>Escaping test 2: <></li>', + '</ul>', + ], + ), +]) +def test_html(errors, expected): + wrapper = certificateerror.CertificateErrorWrapper(errors) + lines = [line.strip() for line in wrapper.html().splitlines() if line.strip()] + assert lines == expected |