diff --git a/qutebrowser/config/configdata.py b/qutebrowser/config/configdata.py index da3025319..dace0772a 100644 --- a/qutebrowser/config/configdata.py +++ b/qutebrowser/config/configdata.py @@ -56,7 +56,7 @@ class Option: @attr.s class Migrations: - """Nigrated options in configdata.yml. + """Migrated options in configdata.yml. Attributes: renamed: A dict mapping old option names to new names. diff --git a/qutebrowser/utils/urlmatch.py b/qutebrowser/utils/urlmatch.py index 5d9afc13e..02db96e33 100644 --- a/qutebrowser/utils/urlmatch.py +++ b/qutebrowser/utils/urlmatch.py @@ -29,6 +29,8 @@ import ipaddress import fnmatch import urllib.parse +from PyQt5.QtCore import QUrl + from qutebrowser.utils import utils, qtutils @@ -177,6 +179,15 @@ class UrlPattern: assert self._host is None return + if parsed.netloc.startswith('['): + # Using QUrl parsing to minimize ipv6 addresses + url = QUrl() + url.setHost(parsed.hostname) + if not url.isValid(): + raise ParseError(url.errorString()) + self._host = url.host() + return + # FIXME what about multiple dots? host_parts = parsed.hostname.rstrip('.').split('.') if host_parts[0] == '*': diff --git a/tests/unit/utils/test_urlmatch.py b/tests/unit/utils/test_urlmatch.py index dcd703790..b77588469 100644 --- a/tests/unit/utils/test_urlmatch.py +++ b/tests/unit/utils/test_urlmatch.py @@ -84,6 +84,19 @@ from qutebrowser.utils import urlmatch # Additional tests ("http://[", "Invalid IPv6 URL"), + ("http://[fc2e:bb88::edac]:", "Invalid port: Port is empty"), + ("http://[fc2e::bb88::edac]", 'Invalid IPv6 address; source was "fc2e::bb88::edac"; host = ""'), + ("http://[fc2e:0e35:bb88::edac:fc2e:0e35:bb88:edac]", 'Invalid IPv6 address; source was "fc2e:0e35:bb88::edac:fc2e:0e35:bb88:edac"; host = ""'), + ("http://[fc2e:0e35:bb88:af:edac:fc2e:0e35:bb88:edac]", 'Invalid IPv6 address; source was "fc2e:0e35:bb88:af:edac:fc2e:0e35:bb88:edac"; host = ""'), + ("http://[127.0.0.1:fc2e::bb88:edac]", 'Invalid IPv6 address; source was "127.0.0.1:fc2e::bb88:edac'), + ("http://[]:20", "Pattern without host"), + ("http://[fc2e::bb88", "Invalid IPv6 URL"), + ("http://[[fc2e::bb88:edac]", """Expected ']' to match '[' in hostname; source was "[fc2e::bb88:edac"; host = """""), + pytest.param("http://[fc2e::bb88:edac]]", "Invalid IPv6 URL", marks=pytest.mark.xfail(reason="https://bugs.python.org/issue34360")), + ("http://[fc2e:bb88:edac]", 'Invalid IPv6 address; source was "fc2e:bb88:edac"; host = ""'), + ("http://[fc2e:bb88:edac::z]", 'Invalid IPv6 address; source was "fc2e:bb88:edac::z"; host = ""'), + ("http://[fc2e:bb88:edac::2]:2a2", "Invalid port: invalid literal for int() with base 10: '2a2'"), + ]) def test_invalid_patterns(pattern, error): with pytest.raises(urlmatch.ParseError, match=re.escape(error)): @@ -154,10 +167,16 @@ class TestMatchAllPagesForGivenScheme: @pytest.mark.parametrize('url, expected', [ ("http://google.com", True), + ("http://google.com:80", True), + ("http://google.com.", True), ("http://yahoo.com", True), ("http://google.com/foo", True), ("https://google.com", False), ("http://74.125.127.100/search", True), + ("http://[fc2e:0e35:bb88::edac]", True), + ("http://[fc2e:e35:bb88::edac]", True), + ("http://[fc2e:e35:bb88::127.0.0.1]", True), + ("http://[::1]/bar", True), ]) def test_urls(self, up, url, expected): assert up.matches(QUrl(url)) == expected @@ -238,6 +257,10 @@ class TestMatchIpAddresses: @pytest.mark.parametrize('pattern, host, match_subdomains', [ ("http://127.0.0.1/*", "127.0.0.1", False), ("http://*.0.0.1/*", "0.0.1", True), + ("http://[::1]/*", "::1", False), + ("http://[0::1]/*", "::1", False), + ("http://[::01]/*", "::1", False), + ("http://[0:0:0:0:20::1]/*", "::20:0:0:1", False), ]) def test_attrs(self, pattern, host, match_subdomains): up = urlmatch.UrlPattern(pattern)