summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Bruhin <me@the-compiler.org>2021-03-19 12:48:05 +0100
committerFlorian Bruhin <me@the-compiler.org>2021-03-19 17:59:47 +0100
commit046148fa8fac770b4e1816af4b9342f17bc361d4 (patch)
tree718b33ba51cb9cafd64c64dfe2cb93acad71731b
parent2f3ae984d04261d1df735f8688fb8d5e6013675f (diff)
downloadqutebrowser-046148fa8fac770b4e1816af4b9342f17bc361d4.tar.gz
qutebrowser-046148fa8fac770b4e1816af4b9342f17bc361d4.zip
Improve certificate error formatting
-rw-r--r--qutebrowser/browser/shared.py2
-rw-r--r--qutebrowser/browser/webkit/certificateerror.py17
-rw-r--r--qutebrowser/utils/usertypes.py4
-rw-r--r--tests/unit/browser/webkit/test_certificateerror.py73
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: &lt;&gt;</p>'],
+ ),
+ (
+ [
+ FakeError('Escaping test 1: <>'),
+ FakeError('Escaping test 2: <>'),
+ ],
+ [
+ '<ul>',
+ '<li>Escaping test 1: &lt;&gt;</li>',
+ '<li>Escaping test 2: &lt;&gt;</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