Always autoescape jinja environments unless overridden
We were only rendering .html files before, so the old _guess_autoescape function had the effect of always autoescaping .render() (from a file) but never autoescaping .from_string(). However, most places using .from_string() actually render (Qt-)HTML via jinja, so they should escape stuff! Now, we always autoescape, except when the caller uses the jinja.environment.no_autoescape() context manager, which places rendering stylesheets now do. This impacted: - Confirm quit texts (no HTML here) - config.py loading errors (where this was found because of an error containing - a <keybinding>) - Certificate error prompts (should be fine from what I can tell, as the only user-controllable output is the hostname, which cannot contain HTML)
This commit is contained in:
parent
337d57b940
commit
3179e8c7b9
@ -194,6 +194,7 @@ class CompletionItemDelegate(QStyledItemDelegate):
|
|||||||
color: {{ conf.colors.completion.match.fg }};
|
color: {{ conf.colors.completion.match.fg }};
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
|
with jinja.environment.no_autoescape():
|
||||||
template = jinja.environment.from_string(stylesheet)
|
template = jinja.environment.from_string(stylesheet)
|
||||||
self._doc.setDefaultStyleSheet(template.render(conf=config.val))
|
self._doc.setDefaultStyleSheet(template.render(conf=config.val))
|
||||||
|
|
||||||
|
@ -585,6 +585,7 @@ def _render_stylesheet(stylesheet):
|
|||||||
"""Render the given stylesheet jinja template."""
|
"""Render the given stylesheet jinja template."""
|
||||||
# Imported here to avoid a Python 3.4 circular import
|
# Imported here to avoid a Python 3.4 circular import
|
||||||
from qutebrowser.utils import jinja
|
from qutebrowser.utils import jinja
|
||||||
|
with jinja.environment.no_autoescape():
|
||||||
template = jinja.environment.from_string(stylesheet)
|
template = jinja.environment.from_string(stylesheet)
|
||||||
return template.render(conf=val)
|
return template.render(conf=val)
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
import os.path
|
import os.path
|
||||||
|
import contextlib
|
||||||
import traceback
|
import traceback
|
||||||
import mimetypes
|
import mimetypes
|
||||||
import html
|
import html
|
||||||
@ -82,21 +83,19 @@ class Environment(jinja2.Environment):
|
|||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__(loader=Loader('html'),
|
super().__init__(loader=Loader('html'),
|
||||||
autoescape=self._guess_autoescape,
|
autoescape=lambda _name: self._autoescape,
|
||||||
undefined=jinja2.StrictUndefined)
|
undefined=jinja2.StrictUndefined)
|
||||||
self.globals['resource_url'] = self._resource_url
|
self.globals['resource_url'] = self._resource_url
|
||||||
self.globals['file_url'] = urlutils.file_url
|
self.globals['file_url'] = urlutils.file_url
|
||||||
self.globals['data_url'] = self._data_url
|
self.globals['data_url'] = self._data_url
|
||||||
|
self._autoescape = True
|
||||||
|
|
||||||
def _guess_autoescape(self, template_name):
|
@contextlib.contextmanager
|
||||||
"""Turn auto-escape on/off based on the file type.
|
def no_autoescape(self):
|
||||||
|
"""Context manager to temporarily turn off autoescaping."""
|
||||||
Based on http://jinja.pocoo.org/docs/dev/api/#autoescaping
|
self._autoescape = False
|
||||||
"""
|
yield
|
||||||
if template_name is None or '.' not in template_name:
|
self._autoescape = True
|
||||||
return False
|
|
||||||
ext = template_name.rsplit('.', 1)[1]
|
|
||||||
return ext in ['html', 'htm', 'xml']
|
|
||||||
|
|
||||||
def _resource_url(self, path):
|
def _resource_url(self, path):
|
||||||
"""Load images from a relative path (to qutebrowser).
|
"""Load images from a relative path (to qutebrowser).
|
||||||
|
@ -146,14 +146,12 @@ def test_attribute_error():
|
|||||||
jinja.render('attributeerror.html', obj=object())
|
jinja.render('attributeerror.html', obj=object())
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize('name, expected', [
|
@pytest.mark.parametrize('escape', [True, False])
|
||||||
(None, False),
|
def test_autoescape(escape):
|
||||||
('foo', False),
|
if not escape:
|
||||||
('foo.html', True),
|
with jinja.environment.no_autoescape():
|
||||||
('foo.htm', True),
|
template = jinja.environment.from_string("{{ v }}")
|
||||||
('foo.xml', True),
|
assert template.render(v='<foo') == '<foo'
|
||||||
('blah/bar/foo.html', True),
|
|
||||||
('foo.bar.html', True),
|
template = jinja.environment.from_string("{{ v }}")
|
||||||
])
|
assert template.render(v='<foo') == '<foo'
|
||||||
def test_autoescape(name, expected):
|
|
||||||
assert jinja.environment._guess_autoescape(name) == expected
|
|
||||||
|
Loading…
Reference in New Issue
Block a user