diff --git a/qutebrowser/browser/downloads.py b/qutebrowser/browser/downloads.py
index 7132f6932..9af04661b 100644
--- a/qutebrowser/browser/downloads.py
+++ b/qutebrowser/browser/downloads.py
@@ -31,6 +31,7 @@ import qutebrowser.config.config as config
import qutebrowser.utils.message as message
import qutebrowser.commands.utils as cmdutils
import qutebrowser.utils.misc as utils
+from qutebrowser.utils.http import parse_content_disposition
from qutebrowser.utils.log import downloads as logger
from qutebrowser.utils.log import fix_rfc2622
from qutebrowser.utils.usertypes import PromptMode, Question, Timer
@@ -375,7 +376,7 @@ class DownloadManager(QObject):
Args:
reply: The QNetworkReply to download.
"""
- _inline, suggested_filename = utils.parse_content_disposition(reply)
+ _inline, suggested_filename = parse_content_disposition(reply)
logger.debug("fetch: {} -> {}".format(reply.url(), suggested_filename))
download = DownloadItem(reply, self)
download.finished.connect(partial(self.on_finished, download))
diff --git a/qutebrowser/test/utils/test_misc_content_disposition.py b/qutebrowser/test/utils/http/test_content_disposition.py
similarity index 98%
rename from qutebrowser/test/utils/test_misc_content_disposition.py
rename to qutebrowser/test/utils/http/test_content_disposition.py
index 2ee793f7b..08c705ef9 100644
--- a/qutebrowser/test/utils/test_misc_content_disposition.py
+++ b/qutebrowser/test/utils/http/test_content_disposition.py
@@ -17,13 +17,13 @@
# You should have received a copy of the GNU General Public License
# along with qutebrowser. If not, see .
-"""Tests for qutebrowser.utils.misc.parse_content_disposition."""
+"""Tests for qutebrowser.utils.http.parse_content_disposition."""
import os
import unittest
from unittest.mock import Mock
-import qutebrowser.utils.misc as utils
+import qutebrowser.utils.http as httputils
from qutebrowser.test.stubs import FakeNetworkReply
@@ -40,7 +40,7 @@ class AttachmentTestCase(unittest.TestCase):
def _check_filename(self, header, filename):
"""Check if the passed header has the given filename."""
reply = FakeNetworkReply(header)
- cd_inline, cd_filename = utils.parse_content_disposition(reply)
+ cd_inline, cd_filename = httputils.parse_content_disposition(reply)
self.assertIsNotNone(cd_filename)
self.assertEqual(cd_filename, filename)
self.assertFalse(cd_inline)
@@ -48,14 +48,14 @@ class AttachmentTestCase(unittest.TestCase):
def _check_ignored(self, header):
"""Check if the passed header is ignored."""
reply = FakeNetworkReply(header)
- cd_inline, cd_filename = utils.parse_content_disposition(reply)
+ cd_inline, cd_filename = httputils.parse_content_disposition(reply)
self.assertEqual(cd_filename, DEFAULT_NAME)
self.assertTrue(cd_inline)
def _check_unnamed(self, header):
"""Check if the passed header results in an unnamed attachment."""
reply = FakeNetworkReply(header)
- cd_inline, cd_filename = utils.parse_content_disposition(reply)
+ cd_inline, cd_filename = httputils.parse_content_disposition(reply)
self.assertEqual(cd_filename, DEFAULT_NAME)
self.assertFalse(cd_inline)
@@ -70,14 +70,14 @@ class InlineTests(unittest.TestCase):
def _check_filename(self, header, filename):
"""Check if the passed header has the given filename."""
reply = FakeNetworkReply(header)
- cd_inline, cd_filename = utils.parse_content_disposition(reply)
+ cd_inline, cd_filename = httputils.parse_content_disposition(reply)
self.assertEqual(cd_filename, filename)
self.assertTrue(cd_inline)
def _check_ignored(self, header):
"""Check if the passed header is ignored."""
reply = FakeNetworkReply(header)
- cd_inline, cd_filename = utils.parse_content_disposition(reply)
+ cd_inline, cd_filename = httputils.parse_content_disposition(reply)
self.assertEqual(cd_filename, DEFAULT_NAME)
self.assertTrue(cd_inline)
@@ -135,7 +135,7 @@ class AttachmentTests(AttachmentTestCase):
UA should offer to download the resource.
"""
reply = FakeNetworkReply('attachment')
- cd_inline, cd_filename = utils.parse_content_disposition(reply)
+ cd_inline, cd_filename = httputils.parse_content_disposition(reply)
self.assertFalse(cd_inline)
self.assertEqual(cd_filename, DEFAULT_NAME)
@@ -894,8 +894,8 @@ class OurTests(AttachmentTestCase):
def setUpModule():
- """Mock out logging in utils."""
- utils.log = Mock()
+ """Mock out logging in httputils."""
+ httputils.logger = Mock()
if __name__ == '__main__':
diff --git a/qutebrowser/utils/http.py b/qutebrowser/utils/http.py
new file mode 100644
index 000000000..a5683cd4e
--- /dev/null
+++ b/qutebrowser/utils/http.py
@@ -0,0 +1,60 @@
+# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
+
+# Copyright 2014 Florian Bruhin (The Compiler)
+#
+# This file is part of qutebrowser.
+#
+# qutebrowser is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# qutebrowser is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with qutebrowser. If not, see .
+
+"""Other utilities which don't fit anywhere else. """
+
+
+import os.path
+import rfc6266
+from qutebrowser.utils.log import misc as logger
+
+
+def parse_content_disposition(reply):
+ """Parse a content_disposition header.
+
+ Args:
+ reply: The QNetworkReply to get a filename for.
+
+ Return:
+ A (is_inline, filename) tuple.
+ """
+ is_inline = True
+ filename = None
+ # First check if the Content-Disposition header has a filename
+ # attribute.
+ if reply.hasRawHeader('Content-Disposition'):
+ # We use the unsafe variant of the filename as we sanitize it via
+ # os.path.basename later.
+ try:
+ content_disposition = rfc6266.parse_headers(
+ bytes(reply.rawHeader('Content-Disposition')), relaxed=True)
+ filename = content_disposition.filename_unsafe
+ except UnicodeDecodeError as e:
+ logger.warning("Error while getting filename: {}: {}".format(
+ e.__class__.__name__, e))
+ filename = None
+ else:
+ is_inline = content_disposition.is_inline
+ # Then try to get filename from url
+ if not filename:
+ filename = reply.url().path()
+ # If that fails as well, use a fallback
+ if not filename:
+ filename = 'qutebrowser-download'
+ return is_inline, os.path.basename(filename)
diff --git a/qutebrowser/utils/misc.py b/qutebrowser/utils/misc.py
index 76361beb2..887b25c7b 100644
--- a/qutebrowser/utils/misc.py
+++ b/qutebrowser/utils/misc.py
@@ -28,13 +28,11 @@ from urllib.parse import urljoin, urlencode
from collections import OrderedDict
from functools import reduce
-import rfc6266
from PyQt5.QtCore import QCoreApplication, QStandardPaths, Qt
from PyQt5.QtGui import QKeySequence, QColor
from pkg_resources import resource_string
import qutebrowser
-import qutebrowser.utils.log as log
from qutebrowser.utils.qt import qt_version_check, qt_ensure_valid
@@ -304,41 +302,6 @@ def format_size(size, base=1024, suffix=''):
return '{:.02f}{}{}'.format(size, prefixes[-1], suffix)
-def parse_content_disposition(reply):
- """Parse a content_disposition header.
-
- Args:
- reply: The QNetworkReply to get a filename for.
-
- Return:
- A (is_inline, filename) tuple.
- """
- is_inline = True
- filename = None
- # First check if the Content-Disposition header has a filename
- # attribute.
- if reply.hasRawHeader('Content-Disposition'):
- # We use the unsafe variant of the filename as we sanitize it via
- # os.path.basename later.
- try:
- content_disposition = rfc6266.parse_headers(
- bytes(reply.rawHeader('Content-Disposition')), relaxed=True)
- filename = content_disposition.filename_unsafe
- except UnicodeDecodeError as e:
- log.misc.warning("Error while getting filename: {}: {}".format(
- e.__class__.__name__, e))
- filename = None
- else:
- is_inline = content_disposition.is_inline
- # Then try to get filename from url
- if not filename:
- filename = reply.url().path()
- # If that fails as well, use a fallback
- if not filename:
- filename = 'qutebrowser-download'
- return is_inline, os.path.basename(filename)
-
-
def key_to_string(key):
"""Convert a Qt::Key member to a meaningful name.