Handle unencodable file paths in config types.
If an user e.g. has a download-directory of ~/föö, but has LC_ALL=C set, we'll get an UnicodeEncodeError when trying to validate it. This is now handled properly by raising a ValidationError. Fixes #562.
This commit is contained in:
parent
330e03d382
commit
fb5fbd09da
@ -833,10 +833,14 @@ class File(BaseType):
|
|||||||
else:
|
else:
|
||||||
raise configexc.ValidationError(value, "may not be empty!")
|
raise configexc.ValidationError(value, "may not be empty!")
|
||||||
value = os.path.expanduser(value)
|
value = os.path.expanduser(value)
|
||||||
if not os.path.isfile(value):
|
try:
|
||||||
raise configexc.ValidationError(value, "must be a valid file!")
|
if not os.path.isfile(value):
|
||||||
if not os.path.isabs(value):
|
raise configexc.ValidationError(value, "must be a valid file!")
|
||||||
raise configexc.ValidationError(value, "must be an absolute path!")
|
if not os.path.isabs(value):
|
||||||
|
raise configexc.ValidationError(
|
||||||
|
value, "must be an absolute path!")
|
||||||
|
except UnicodeEncodeError as e:
|
||||||
|
raise configexc.ValidationError(value, e)
|
||||||
|
|
||||||
def transform(self, value):
|
def transform(self, value):
|
||||||
if not value:
|
if not value:
|
||||||
@ -858,11 +862,15 @@ class Directory(BaseType):
|
|||||||
raise configexc.ValidationError(value, "may not be empty!")
|
raise configexc.ValidationError(value, "may not be empty!")
|
||||||
value = os.path.expandvars(value)
|
value = os.path.expandvars(value)
|
||||||
value = os.path.expanduser(value)
|
value = os.path.expanduser(value)
|
||||||
if not os.path.isdir(value):
|
try:
|
||||||
raise configexc.ValidationError(value, "must be a valid "
|
if not os.path.isdir(value):
|
||||||
"directory!")
|
raise configexc.ValidationError(
|
||||||
if not os.path.isabs(value):
|
value, "must be a valid directory!")
|
||||||
raise configexc.ValidationError(value, "must be an absolute path!")
|
if not os.path.isabs(value):
|
||||||
|
raise configexc.ValidationError(
|
||||||
|
value, "must be an absolute path!")
|
||||||
|
except UnicodeEncodeError as e:
|
||||||
|
raise configexc.ValidationError(value, e)
|
||||||
|
|
||||||
def transform(self, value):
|
def transform(self, value):
|
||||||
if not value:
|
if not value:
|
||||||
@ -1179,18 +1187,21 @@ class UserStyleSheet(File):
|
|||||||
raise configexc.ValidationError(value, "may not be empty!")
|
raise configexc.ValidationError(value, "may not be empty!")
|
||||||
value = os.path.expandvars(value)
|
value = os.path.expandvars(value)
|
||||||
value = os.path.expanduser(value)
|
value = os.path.expanduser(value)
|
||||||
if not os.path.isabs(value):
|
try:
|
||||||
# probably a CSS, so we don't handle it as filename.
|
if not os.path.isabs(value):
|
||||||
# FIXME We just try if it is encodable, maybe we should validate
|
# probably a CSS, so we don't handle it as filename.
|
||||||
# CSS?
|
# FIXME We just try if it is encodable, maybe we should
|
||||||
# https://github.com/The-Compiler/qutebrowser/issues/115
|
# validate CSS?
|
||||||
try:
|
# https://github.com/The-Compiler/qutebrowser/issues/115
|
||||||
value.encode('utf-8')
|
try:
|
||||||
except UnicodeEncodeError as e:
|
value.encode('utf-8')
|
||||||
raise configexc.ValidationError(value, str(e))
|
except UnicodeEncodeError as e:
|
||||||
return
|
raise configexc.ValidationError(value, str(e))
|
||||||
elif not os.path.isfile(value):
|
return
|
||||||
raise configexc.ValidationError(value, "must be a valid file!")
|
elif not os.path.isfile(value):
|
||||||
|
raise configexc.ValidationError(value, "must be a valid file!")
|
||||||
|
except UnicodeEncodeError as e:
|
||||||
|
raise configexc.ValidationError(value, e)
|
||||||
|
|
||||||
def transform(self, value):
|
def transform(self, value):
|
||||||
path = os.path.expandvars(value)
|
path = os.path.expandvars(value)
|
||||||
|
@ -1374,6 +1374,13 @@ class FileTests(unittest.TestCase):
|
|||||||
self.t.validate('~/foobar')
|
self.t.validate('~/foobar')
|
||||||
os_path.expanduser.assert_called_once_with('~/foobar')
|
os_path.expanduser.assert_called_once_with('~/foobar')
|
||||||
|
|
||||||
|
def test_validate_invalid_encoding(self, os_path):
|
||||||
|
"""Test validate with an invalid encoding, e.g. LC_ALL=C."""
|
||||||
|
os_path.isfile.side_effect = helpers.unicode_encode_err
|
||||||
|
os_path.isabs.side_effect = helpers.unicode_encode_err
|
||||||
|
with self.assertRaises(configexc.ValidationError):
|
||||||
|
self.t.validate('foobar')
|
||||||
|
|
||||||
def test_transform(self, os_path):
|
def test_transform(self, os_path):
|
||||||
"""Test transform."""
|
"""Test transform."""
|
||||||
os_path.expanduser.side_effect = lambda x: x.replace('~', '/home/foo')
|
os_path.expanduser.side_effect = lambda x: x.replace('~', '/home/foo')
|
||||||
@ -1445,6 +1452,13 @@ class DirectoryTests(unittest.TestCase):
|
|||||||
self.t.validate('$BAR/foobar')
|
self.t.validate('$BAR/foobar')
|
||||||
os_path.expandvars.assert_called_once_with('$BAR/foobar')
|
os_path.expandvars.assert_called_once_with('$BAR/foobar')
|
||||||
|
|
||||||
|
def test_validate_invalid_encoding(self, os_path):
|
||||||
|
"""Test validate with an invalid encoding, e.g. LC_ALL=C."""
|
||||||
|
os_path.isdir.side_effect = helpers.unicode_encode_err
|
||||||
|
os_path.isabs.side_effect = helpers.unicode_encode_err
|
||||||
|
with self.assertRaises(configexc.ValidationError):
|
||||||
|
self.t.validate('foobar')
|
||||||
|
|
||||||
def test_transform(self, os_path):
|
def test_transform(self, os_path):
|
||||||
"""Test transform."""
|
"""Test transform."""
|
||||||
os_path.expandvars.side_effect = lambda x: x
|
os_path.expandvars.side_effect = lambda x: x
|
||||||
@ -1879,6 +1893,14 @@ class UserStyleSheetTests(unittest.TestCase):
|
|||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.t = configtypes.UserStyleSheet()
|
self.t = configtypes.UserStyleSheet()
|
||||||
|
|
||||||
|
@mock.patch('qutebrowser.config.configtypes.os.path', autospec=True)
|
||||||
|
def test_validate_invalid_encoding(self, os_path):
|
||||||
|
"""Test validate with an invalid encoding, e.g. LC_ALL=C."""
|
||||||
|
os_path.isfile.side_effect = helpers.unicode_encode_err
|
||||||
|
os_path.isabs.side_effect = helpers.unicode_encode_err
|
||||||
|
with self.assertRaises(configexc.ValidationError):
|
||||||
|
self.t.validate('foobar')
|
||||||
|
|
||||||
def test_transform_empty(self):
|
def test_transform_empty(self):
|
||||||
"""Test transform with an empty value."""
|
"""Test transform with an empty value."""
|
||||||
self.assertIsNone(self.t.transform(''))
|
self.assertIsNone(self.t.transform(''))
|
||||||
|
@ -29,6 +29,13 @@ from PyQt5.QtWebKitWidgets import QWebPage
|
|||||||
from PyQt5.QtNetwork import QNetworkAccessManager
|
from PyQt5.QtNetwork import QNetworkAccessManager
|
||||||
|
|
||||||
|
|
||||||
|
unicode_encode_err = UnicodeEncodeError('ascii', # codec
|
||||||
|
'', # object
|
||||||
|
0, # start
|
||||||
|
2, # end
|
||||||
|
'fake exception') # reason
|
||||||
|
|
||||||
|
|
||||||
@contextlib.contextmanager
|
@contextlib.contextmanager
|
||||||
def environ_set_temp(env):
|
def environ_set_temp(env):
|
||||||
"""Set temporary environment variables.
|
"""Set temporary environment variables.
|
||||||
|
Loading…
Reference in New Issue
Block a user