Handle wrong image/jpg mimetype in unsupportedContent slot.

This commit is contained in:
Florian Bruhin 2014-08-12 21:08:13 +02:00
parent 01ec30cda3
commit dd2ed78f40
3 changed files with 39 additions and 10 deletions

View File

@ -19,6 +19,8 @@
"""The main browser widgets.""" """The main browser widgets."""
from functools import partial
import sip import sip
from PyQt5.QtCore import pyqtSignal, pyqtSlot, PYQT_VERSION, Qt from PyQt5.QtCore import pyqtSignal, pyqtSlot, PYQT_VERSION, Qt
from PyQt5.QtNetwork import QNetworkReply from PyQt5.QtNetwork import QNetworkReply
@ -29,6 +31,7 @@ from PyQt5.QtWebKitWidgets import QWebPage
import qutebrowser.utils.message as message import qutebrowser.utils.message as message
import qutebrowser.config.config as config import qutebrowser.config.config as config
import qutebrowser.utils.log as log import qutebrowser.utils.log as log
import qutebrowser.utils.http as http
from qutebrowser.network.networkmanager import NetworkManager from qutebrowser.network.networkmanager import NetworkManager
from qutebrowser.utils.misc import read_file from qutebrowser.utils.misc import read_file
from qutebrowser.utils.qt import check_print_compat from qutebrowser.utils.qt import check_print_compat
@ -63,6 +66,7 @@ class BrowserPage(QWebPage):
self.setForwardUnsupportedContent(True) self.setForwardUnsupportedContent(True)
self.printRequested.connect(self.on_print_requested) self.printRequested.connect(self.on_print_requested)
self.downloadRequested.connect(self.on_download_requested) self.downloadRequested.connect(self.on_download_requested)
self.unsupportedContent.connect(self.on_unsupported_content)
self._view = view self._view = view
if PYQT_VERSION > 0x050300: if PYQT_VERSION > 0x050300:
@ -147,6 +151,11 @@ class BrowserPage(QWebPage):
suggested_file) suggested_file)
return True return True
def display_content(self, reply, mimetype):
"""Display a QNetworkReply with an explicitely set mimetype."""
self.mainFrame().setContent(reply.readAll(), mimetype, reply.url())
reply.deleteLater()
def on_print_requested(self, frame): def on_print_requested(self, frame):
"""Handle printing when requested via javascript.""" """Handle printing when requested via javascript."""
if not check_print_compat(): if not check_print_compat():
@ -168,6 +177,36 @@ class BrowserPage(QWebPage):
reply = self.networkAccessManager().get(request) reply = self.networkAccessManager().get(request)
self.start_download.emit(reply) self.start_download.emit(reply)
@pyqtSlot('QNetworkReply')
def on_unsupported_content(self, reply):
"""Handle an unsupportedContent signal.
Most likely this will mean we need to download the reply, but we
correct for some common errors the server do.
At some point we might want to implement the MIME Sniffing standard
here: http://mimesniff.spec.whatwg.org/
"""
inline, _suggested_filename = http.parse_content_disposition(reply)
if not inline:
# Content-Disposition: attachment -> force download
self.start_download.emit(reply)
return
mimetype, _rest = http.parse_content_type(reply)
if mimetype == 'image/jpg':
# Some servers (e.g. the LinkedIn CDN) send a non-standard
# image/jpg (instead of image/jpeg, defined in RFC 1341 section
# 7.5). If this is the case, we force displaying with a corrected
# mimetype.
if reply.isFinished():
self.display_content(reply, 'image/jpeg')
else:
reply.finished.connect(
partial(self.display_content, reply, 'image/jpeg'))
else:
# Unknown mimetype, so download anyways.
self.start_download.emit(reply)
def userAgentForUrl(self, url): def userAgentForUrl(self, url):
"""Override QWebPage::userAgentForUrl to customize the user agent.""" """Override QWebPage::userAgentForUrl to customize the user agent."""
ua = config.get('network', 'user-agent') ua = config.get('network', 'user-agent')

View File

@ -19,8 +19,6 @@
"""Our own QNetworkAccessManager.""" """Our own QNetworkAccessManager."""
from functools import partial
from PyQt5.QtCore import pyqtSlot, PYQT_VERSION, QCoreApplication from PyQt5.QtCore import pyqtSlot, PYQT_VERSION, QCoreApplication
from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkReply from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkReply
@ -37,7 +35,6 @@ import qutebrowser.utils.log as log
from qutebrowser.network.qutescheme import QuteSchemeHandler from qutebrowser.network.qutescheme import QuteSchemeHandler
from qutebrowser.network.schemehandler import ErrorNetworkReply from qutebrowser.network.schemehandler import ErrorNetworkReply
from qutebrowser.utils.usertypes import PromptMode from qutebrowser.utils.usertypes import PromptMode
from qutebrowser.utils.http import change_content_type
class NetworkManager(QNetworkAccessManager): class NetworkManager(QNetworkAccessManager):
@ -162,10 +159,4 @@ class NetworkManager(QNetworkAccessManager):
reply = super().createRequest(op, req, outgoing_data) reply = super().createRequest(op, req, outgoing_data)
self._requests.append(reply) self._requests.append(reply)
reply.destroyed.connect(lambda obj: self._requests.remove(obj)) reply.destroyed.connect(lambda obj: self._requests.remove(obj))
# Some servers (e.g. the LinkedIn CDN) send a non-standard image/jpg
# header for jpg images. We change this to image/jpeg (defined in RFC
# 1341 section 7.5: https://tools.ietf.org/html/rfc1341) so QtWebKit
# displays this instead of downloading it.
reply.metaDataChanged.connect(
partial(change_content_type, reply, {'image/jpg': 'image/jpeg'}))
return reply return reply

View File

@ -166,7 +166,6 @@ class TabbedBrowser(TabWidget):
tab.hintmanager.openurl.connect(self.openurl) tab.hintmanager.openurl.connect(self.openurl)
self.cur_load_started.connect(self.on_cur_load_started) self.cur_load_started.connect(self.on_cur_load_started)
# downloads # downloads
page.unsupportedContent.connect(self.start_download)
page.start_download.connect(self.start_download) page.start_download.connect(self.start_download)
# misc # misc
tab.titleChanged.connect(partial(self.on_title_changed, tab)) tab.titleChanged.connect(partial(self.on_title_changed, tab))