diff options
author | Florian Bruhin <me@the-compiler.org> | 2020-04-20 18:01:38 +0200 |
---|---|---|
committer | Florian Bruhin <me@the-compiler.org> | 2020-04-20 18:01:38 +0200 |
commit | a36f14e2ee9f7921f59bfa7aa71b7f20394f0b3b (patch) | |
tree | 6f6c0e4b4b975a8aef31459b7101aff2d0d86d4c | |
parent | 728c84158f413a2e7515ebb97eb36cbbf4c2ec2e (diff) | |
parent | 3e331f6275ecec84aca23c9b58a3d67b654d2e2a (diff) | |
download | qutebrowser-a36f14e2ee9f7921f59bfa7aa71b7f20394f0b3b.tar.gz qutebrowser-a36f14e2ee9f7921f59bfa7aa71b7f20394f0b3b.zip |
Merge remote-tracking branch 'origin/pr/5314'
-rw-r--r-- | qutebrowser/config/configdata.yml | 16 | ||||
-rw-r--r-- | qutebrowser/config/configtypes.py | 14 | ||||
-rw-r--r-- | qutebrowser/utils/urlutils.py | 9 | ||||
-rw-r--r-- | tests/end2end/features/yankpaste.feature | 4 | ||||
-rw-r--r-- | tests/unit/config/test_configtypes.py | 1 | ||||
-rw-r--r-- | tests/unit/utils/test_urlutils.py | 25 |
6 files changed, 55 insertions, 14 deletions
diff --git a/qutebrowser/config/configdata.yml b/qutebrowser/config/configdata.yml index 0a44a9be3..effb2271c 100644 --- a/qutebrowser/config/configdata.yml +++ b/qutebrowser/config/configdata.yml @@ -1913,12 +1913,24 @@ url.searchengines: name: String forbidden: ' ' valtype: SearchEngineUrl - desc: >- + desc: | Search engines which can be used via the address bar. Maps a search engine name (such as `DEFAULT`, or `ddg`) to a URL with a `{}` placeholder. The placeholder will be replaced by the search term, use - `{{` and `}}` for literal `{`/`}` signs. + `{{` and `}}` for literal `{`/`}` braces. + + The following further placeholds are defined to configure how special + characters in the search terms are replaced by safe characters (called + 'quoting'): + + * `{}` and `{semiquoted}` quote everything except slashes; this is the most + sensible choice for almost all search engines (for the search term + `slash/and&` this placeholder expands to `slash/and%26amp`). + * `{quoted}` quotes all characters (for `slash/and&` this placeholder + expands to `slash%2Fand%26amp`). + * `{unquoted}` quotes nothing (for `slash/and&` this placeholder + expands to `slash/and&`). The search engine named `DEFAULT` is used when `url.auto_search` is turned on and something else than a URL was entered to be opened. Other search diff --git a/qutebrowser/config/configtypes.py b/qutebrowser/config/configtypes.py index befc43806..3d0f5c924 100644 --- a/qutebrowser/config/configtypes.py +++ b/qutebrowser/config/configtypes.py @@ -1760,22 +1760,22 @@ class SearchEngineUrl(BaseType): elif not value: return None - if not ('{}' in value or '{0}' in value): + if not re.search('{(|0|semiquoted|unquoted|quoted)}', value): raise configexc.ValidationError(value, "must contain \"{}\"") try: - value.format("") + format_keys = { + 'quoted': "", + 'unquoted': "", + 'semiquoted': "", + } + value.format("", **format_keys) except (KeyError, IndexError): raise configexc.ValidationError( value, "may not contain {...} (use {{ and }} for literal {/})") except ValueError as e: raise configexc.ValidationError(value, str(e)) - url = QUrl(value.replace('{}', 'foobar')) - if not url.isValid(): - raise configexc.ValidationError( - value, "invalid url, {}".format(url.errorString())) - return value diff --git a/qutebrowser/utils/urlutils.py b/qutebrowser/utils/urlutils.py index b0013c195..2df45bf12 100644 --- a/qutebrowser/utils/urlutils.py +++ b/qutebrowser/utils/urlutils.py @@ -116,8 +116,15 @@ def _get_search_url(txt: str) -> QUrl: engine = 'DEFAULT' if term: template = config.val.url.searchengines[engine] + semiquoted_term = urllib.parse.quote(term) quoted_term = urllib.parse.quote(term, safe='') - url = qurl_from_user_input(template.format(quoted_term)) + format_keys = { + 'unquoted': term, + 'quoted': quoted_term, + 'semiquoted': semiquoted_term, + } + evaluated = template.format(semiquoted_term, **format_keys) + url = qurl_from_user_input(evaluated) else: url = qurl_from_user_input(config.val.url.searchengines[engine]) url.setPath(None) # type: ignore diff --git a/tests/end2end/features/yankpaste.feature b/tests/end2end/features/yankpaste.feature index 46ef92a9c..16caac3a3 100644 --- a/tests/end2end/features/yankpaste.feature +++ b/tests/end2end/features/yankpaste.feature @@ -194,10 +194,10 @@ Feature: Yanking and pasting. http://qutebrowser.org should not open And I run :open -t {clipboard} - And I wait until data/hello.txt?q=this%20url%3A%0Ahttp%3A%2F%2Fqutebrowser.org%0Ashould%20not%20open is loaded + And I wait until data/hello.txt?q=this%20url%3A%0Ahttp%3A//qutebrowser.org%0Ashould%20not%20open is loaded Then the following tabs should be open: - about:blank - - data/hello.txt?q=this%20url%3A%0Ahttp%3A%2F%2Fqutebrowser.org%0Ashould%20not%20open (active) + - data/hello.txt?q=this%20url%3A%0Ahttp%3A//qutebrowser.org%0Ashould%20not%20open (active) Scenario: Pasting multiline whose first line looks like a URI When I set url.auto_search to naive diff --git a/tests/unit/config/test_configtypes.py b/tests/unit/config/test_configtypes.py index f949e1ca0..97cb4fbf0 100644 --- a/tests/unit/config/test_configtypes.py +++ b/tests/unit/config/test_configtypes.py @@ -2003,7 +2003,6 @@ class TestSearchEngineUrl: @pytest.mark.parametrize('val', [ 'foo', # no placeholder - ':{}', # invalid URL 'foo{bar}baz{}', # {bar} format string variable '{1}{}', # numbered format string variable '{{}', # invalid format syntax diff --git a/tests/unit/utils/test_urlutils.py b/tests/unit/utils/test_urlutils.py index 0c265917d..39a43479b 100644 --- a/tests/unit/utils/test_urlutils.py +++ b/tests/unit/utils/test_urlutils.py @@ -98,6 +98,8 @@ def init_config(config_stub): 'test': 'http://www.qutebrowser.org/?q={}', 'test-with-dash': 'http://www.example.org/?q={}', 'path-search': 'http://www.example.org/{}', + 'quoted-path': 'http://www.example.org/{quoted}', + 'unquoted': 'http://www.example.org/?{unquoted}', 'DEFAULT': 'http://www.example.com/?q={}', } @@ -286,8 +288,10 @@ def test_special_urls(url, special): ('blub testfoo', 'www.example.com', 'q=blub testfoo'), ('stripped ', 'www.example.com', 'q=stripped'), ('test-with-dash testfoo', 'www.example.org', 'q=testfoo'), - ('test/with/slashes', 'www.example.com', 'q=test%2Fwith%2Fslashes'), + ('test/with/slashes', 'www.example.com', 'q=test/with/slashes'), ('test path-search', 'www.qutebrowser.org', 'q=path-search'), + ('slash/and&', 'www.example.com', 'q=slash/and%26amp'), + ('unquoted one=1&two=2', 'www.example.org', 'one=1&two=2'), ]) def test_get_search_url(config_stub, url, host, query, open_base_url): """Test _get_search_url(). @@ -303,6 +307,25 @@ def test_get_search_url(config_stub, url, host, query, open_base_url): assert url.query() == query +@pytest.mark.parametrize('open_base_url', [True, False]) +@pytest.mark.parametrize('url, host, path', [ + ('path-search t/w/s', 'www.example.org', 't/w/s'), + ('quoted-path t/w/s', 'www.example.org', 't%2Fw%2Fs'), +]) +def test_get_search_url_for_path_search(config_stub, url, host, path, open_base_url): + """Test _get_search_url_for_path_search(). + + Args: + url: The "URL" to enter. + host: The expected search machine host. + path: The expected path on that host that is requested. + """ + config_stub.val.url.open_base_url = open_base_url + url = urlutils._get_search_url(url) + assert url.host() == host + assert url.path(options=QUrl.PrettyDecoded) == '/' + path + + @pytest.mark.parametrize('url, host', [ ('test', 'www.qutebrowser.org'), ('test-with-dash', 'www.example.org'), |