Parse Content-Disposition header properly

This commit is contained in:
Florian Bruhin 2014-06-18 22:51:26 +02:00
parent d18f02cc7a
commit 6e59b0ab3a
2 changed files with 32 additions and 11 deletions

View File

@ -30,7 +30,7 @@ import qutebrowser.utils.message as message
from qutebrowser.utils.log import downloads as logger from qutebrowser.utils.log import downloads as logger
from qutebrowser.utils.usertypes import PromptMode, Question, Timer from qutebrowser.utils.usertypes import PromptMode, Question, Timer
from qutebrowser.utils.misc import (interpolate_color, format_seconds, from qutebrowser.utils.misc import (interpolate_color, format_seconds,
format_size) format_size, get_http_header)
class DownloadItem(QObject): class DownloadItem(QObject):
@ -321,18 +321,10 @@ class DownloadManager(QObject):
Args: Args:
reply: The QNetworkReply to get a filename for. reply: The QNetworkReply to get a filename for.
""" """
filename = None
# First check if the Content-Disposition header has a filename # First check if the Content-Disposition header has a filename
# attribute. # attribute.
if reply.hasRawHeader('Content-Disposition'): from qutebrowser.utils.debug import set_trace; set_trace()
header = reply.rawHeader('Content-Disposition') filename = get_http_header(reply, 'Content-Disposition', 'filename')
data = header.split(':', maxsplit=1)[1].strip()
for pair in data.split(';'):
if '=' in pair:
key, value = pair.split('=')
if key == 'filename':
filename = value.strip('"')
break
# Then try to get filename from url # Then try to get filename from url
if not filename: if not filename:
filename = reply.url().path() filename = reply.url().path()

View File

@ -26,6 +26,8 @@ import os
import re import re
import sys import sys
import shlex import shlex
import email
import email.policy
import os.path import os.path
import operator import operator
import urllib.request import urllib.request
@ -393,6 +395,33 @@ def check_print_compat():
return not (os.name == 'nt' and qt_version_check('5.3.0', operator.lt)) return not (os.name == 'nt' and qt_version_check('5.3.0', operator.lt))
def get_http_header(reply, headername, param=None):
"""Get a parameter from a HTTP header.
Note we use the email value to get a HTTP header, because they're both MIME
headers and email supports that.
Args:
reply: The QNetworkReply to get the header from.
headername: The name of the header.
param: The name of the param to get, or None to get the whole contents.
Return:
The data as a string, or None if the data wasn't found.
FIXME add tests
"""
if not reply.hasRawHeader(headername):
return None
header = (headername.encode('ascii') + b': ' +
bytes(reply.rawHeader(headername)))
msg = email.message_from_bytes(header, policy=email.policy.HTTP)
if param is not None:
return msg.get_param(param, header=headername)
else:
return msg.get(headername, None)
class EventLoop(QEventLoop): class EventLoop(QEventLoop):
"""A thin wrapper around QEventLoop. """A thin wrapper around QEventLoop.