Replace unencodable chars in download filenames.

Fixes #427.
This commit is contained in:
Florian Bruhin 2015-01-03 17:50:59 +01:00
parent 450d1ab70d
commit 7dbbfedd3b
3 changed files with 40 additions and 1 deletions

View File

@ -21,6 +21,7 @@
import io
import os
import sys
import os.path
import shutil
import functools
@ -385,6 +386,10 @@ class DownloadItem(QObject):
"existing: {}, fileobj {}".format(
filename, self._filename, self.fileobj))
filename = os.path.expanduser(filename)
# Remove chars which can't be encoded in the filename encoding.
# See https://github.com/The-Compiler/qutebrowser/issues/427
encoding = sys.getfilesystemencoding()
filename = utils.force_encoding(filename, encoding)
if os.path.isabs(filename) and os.path.isdir(filename):
# We got an absolute directory from the user, so we save it under
# the default filename in that directory.
@ -639,7 +644,10 @@ class DownloadManager(QAbstractListModel):
return self.fetch_request(request, filename, fileobj, page,
auto_remove)
q = self._prepare_question()
q.default = urlutils.filename_from_url(request.url())
filename = urlutils.filename_from_url(request.url())
encoding = sys.getfilesystemencoding()
filename = utils.force_encoding(filename, encoding)
q.default = filename
message_bridge = objreg.get('message-bridge', scope='window',
window=self._win_id)
q.answered.connect(
@ -719,6 +727,9 @@ class DownloadManager(QAbstractListModel):
download.autoclose = False
else:
q = self._prepare_question()
encoding = sys.getfilesystemencoding()
suggested_filename = utils.force_encoding(suggested_filename,
encoding)
q.default = suggested_filename
q.answered.connect(download.set_filename)
q.cancelled.connect(download.cancel)

View File

@ -383,5 +383,25 @@ class RaisesTests(unittest.TestCase):
utils.raises(ValueError, self.do_raise)
class ForceEncodingTests(unittest.TestCase):
"""Test force_encoding."""
def test_fitting_ascii(self):
"""Test with a text fitting into ascii."""
text = 'hello world'
self.assertEqual(utils.force_encoding(text, 'ascii'), text)
def test_fitting_utf8(self):
"""Test with a text fitting into utf-8."""
text = 'hellö wörld'
self.assertEqual(utils.force_encoding(text, 'utf-8'), text)
def test_not_fitting_ascii(self):
"""Test with a text not fitting into ascii."""
text = 'hellö wörld'
self.assertEqual(utils.force_encoding(text, 'ascii'), 'hell? w?rld')
if __name__ == '__main__':
unittest.main()

View File

@ -542,3 +542,11 @@ def raises(exc, func, *args):
return True
else:
return False
def force_encoding(text, encoding):
"""Make sure a given text is encodable with the given encoding.
This replaces all chars not encodable with question marks.
"""
return text.encode(encoding, errors='replace').decode(encoding)