Add a new qutebrowser.utils.http module
This commit is contained in:
parent
50604de24d
commit
be2604cacd
@ -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))
|
||||
|
@ -17,13 +17,13 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with qutebrowser. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""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__':
|
60
qutebrowser/utils/http.py
Normal file
60
qutebrowser/utils/http.py
Normal file
@ -0,0 +1,60 @@
|
||||
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
|
||||
|
||||
# Copyright 2014 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
|
||||
#
|
||||
# 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""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)
|
@ -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.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user