Beispiel #1
0
    def get_request(self,
                    request,
                    *,
                    target=None,
                    suggested_fn=None,
                    **kwargs):
        """Start a download with a QNetworkRequest.

        Args:
            request: The QNetworkRequest to download.
            target: Where to save the download as downloads.DownloadTarget.
            **kwargs: Passed to _fetch_request.

        Return:
            The created DownloadItem.
        """
        # WORKAROUND for Qt corrupting data loaded from cache:
        # https://bugreports.qt.io/browse/QTBUG-42757
        request.setAttribute(QNetworkRequest.CacheLoadControlAttribute,
                             QNetworkRequest.AlwaysNetwork)

        if suggested_fn is not None:
            pass
        elif request.url().scheme().lower() != 'data':
            suggested_fn = urlutils.filename_from_url(request.url())
        else:
            # We might be downloading a binary blob embedded on a page or even
            # generated dynamically via javascript. We try to figure out a more
            # sensible name than the base64 content of the data.
            origin = request.originatingObject()
            try:
                origin_url = origin.url()
            except AttributeError:
                # Raised either if origin is None or some object that doesn't
                # have its own url. We're probably fine with a default fallback
                # then.
                suggested_fn = 'binary blob'
            else:
                # Use the originating URL as a base for the filename (works
                # e.g. for pdf.js).
                suggested_fn = urlutils.filename_from_url(origin_url)

        if suggested_fn is None:
            suggested_fn = 'qutebrowser-download'

        return self._fetch_request(request,
                                   target=target,
                                   suggested_filename=suggested_fn,
                                   **kwargs)
Beispiel #2
0
    def get_request(self, request, page=None, fileobj=None, filename=None):
        """Start a download with a QNetworkRequest.

        Args:
            request: The QNetworkRequest to download.
            page: The QWebPage to use.
            fileobj: The file object to write the answer to.
            filename: A path to write the data to.

        Return:
            If the download could start immediately, (fileobj/filename given),
            the created DownloadItem.

            If not, None.
        """
        if fileobj is not None and filename is not None:
            raise TypeError("Only one of fileobj/filename may be given!")
        # WORKAROUND for Qt corrupting data loaded from cache:
        # https://bugreports.qt-project.org/browse/QTBUG-42757
        request.setAttribute(QNetworkRequest.CacheLoadControlAttribute,
                             QNetworkRequest.AlwaysNetwork)
        if fileobj is not None or filename is not None:
            return self.fetch_request(request, filename, fileobj, page)
        q = self._prepare_question()
        q.default = urlutils.filename_from_url(request.url())
        message_bridge = objreg.get('message-bridge', scope='window',
                                    window=self._win_id)
        q.answered.connect(
            lambda fn: self.fetch_request(request, filename=fn, page=page))
        message_bridge.ask(q, blocking=False)
        return None
Beispiel #3
0
    def get_request(self, request, page=None, fileobj=None, filename=None):
        """Start a download with a QNetworkRequest.

        Args:
            request: The QNetworkRequest to download.
            page: The QWebPage to use.
            fileobj: The file object to write the answer to.
            filename: A path to write the data to.

        Return:
            If the download could start immediately, (fileobj/filename given),
            the created DownloadItem.

            If not, None.
        """
        if fileobj is not None and filename is not None:
            raise TypeError("Only one of fileobj/filename may be given!")
        # WORKAROUND for Qt corrupting data loaded from cache:
        # https://bugreports.qt-project.org/browse/QTBUG-42757
        request.setAttribute(QNetworkRequest.CacheLoadControlAttribute,
                             QNetworkRequest.AlwaysNetwork)
        if fileobj is not None or filename is not None:
            return self.fetch_request(request, filename, fileobj, page)
        q = self._prepare_question()
        q.default = urlutils.filename_from_url(request.url())
        message_bridge = objreg.get('message-bridge', scope='window',
                                    window=self._win_id)
        q.answered.connect(
            lambda fn: self.fetch_request(request, filename=fn, page=page))
        message_bridge.ask(q, blocking=False)
        return None
Beispiel #4
0
    def get_request(self,
                    request,
                    *,
                    fileobj=None,
                    filename=None,
                    prompt_download_directory=None,
                    **kwargs):
        """Start a download with a QNetworkRequest.

        Args:
            request: The QNetworkRequest to download.
            fileobj: The file object to write the answer to.
            filename: A path to write the data to.
            prompt_download_directory: Whether to prompt for the download dir
                                       or automatically download. If None, the
                                       config is used.
            **kwargs: Passed to fetch_request.

        Return:
            If the download could start immediately, (fileobj/filename given),
            the created DownloadItem.

            If not, None.
        """
        if fileobj is not None and filename is not None:
            raise TypeError("Only one of fileobj/filename may be given!")
        # WORKAROUND for Qt corrupting data loaded from cache:
        # https://bugreports.qt.io/browse/QTBUG-42757
        request.setAttribute(QNetworkRequest.CacheLoadControlAttribute,
                             QNetworkRequest.AlwaysNetwork)
        suggested_fn = urlutils.filename_from_url(request.url())

        if prompt_download_directory is None:
            prompt_download_directory = config.get(
                'storage', 'prompt-download-directory')
        if not prompt_download_directory and not fileobj:
            filename = config.get('storage', 'download-directory')

        if fileobj is not None or filename is not None:
            return self.fetch_request(request,
                                      fileobj=fileobj,
                                      filename=filename,
                                      suggested_filename=suggested_fn,
                                      **kwargs)
        if suggested_fn is None:
            suggested_fn = 'qutebrowser-download'
        else:
            encoding = sys.getfilesystemencoding()
            suggested_fn = utils.force_encoding(suggested_fn, encoding)
        q = self._prepare_question()
        q.default = _path_suggestion(suggested_fn)
        message_bridge = objreg.get('message-bridge',
                                    scope='window',
                                    window=self._win_id)
        q.answered.connect(lambda fn: self.fetch_request(
            request, filename=fn, suggested_filename=suggested_fn, **kwargs))
        message_bridge.ask(q, blocking=False)
        return None
    def handle_download(self, qt_item):
        """Start a download coming from a QWebEngineProfile."""
        qt_filename = os.path.basename(qt_item.path())  # FIXME use 5.14 API
        mime_type = qt_item.mimeType()
        url = qt_item.url()

        # WORKAROUND for https://bugreports.qt.io/browse/QTBUG-90355
        if version.qtwebengine_versions().webengine >= utils.VersionNumber(
                5, 15, 3):
            needs_workaround = False
        elif url.scheme().lower() == 'data':
            if '/' in url.path().split(',')[-1]:  # e.g. a slash in base64
                wrong_filename = url.path().split('/')[-1]
            else:
                wrong_filename = mime_type.split('/')[1]

            needs_workaround = qt_filename == wrong_filename
        else:
            needs_workaround = False

        if needs_workaround:
            suggested_filename = urlutils.filename_from_url(
                url, fallback='qutebrowser-download')
        else:
            suggested_filename = _strip_suffix(qt_filename)

        use_pdfjs = pdfjs.should_use_pdfjs(mime_type, url)

        download = DownloadItem(qt_item, manager=self)
        self._init_item(download,
                        auto_remove=use_pdfjs,
                        suggested_filename=suggested_filename)

        if self._mhtml_target is not None:
            download.set_target(self._mhtml_target)
            self._mhtml_target = None
            return
        if use_pdfjs:
            download.set_target(downloads.PDFJSDownloadTarget())
            return

        filename = downloads.immediate_download_path()
        if filename is not None:
            # User doesn't want to be asked, so just use the download_dir
            target = downloads.FileDownloadTarget(filename)
            download.set_target(target)
            return

        if download.cancel_for_origin():
            return

        # Ask the user for a filename - needs to be blocking!
        question = downloads.get_filename_question(
            suggested_filename=suggested_filename,
            url=qt_item.url(),
            parent=self)
        self._init_filename_question(question, download)
        message.global_bridge.ask(question, blocking=True)
    def get_request(self, request, *, target=None,
                    suggested_fn=None, **kwargs):
        """Start a download with a QNetworkRequest.

        Args:
            request: The QNetworkRequest to download.
            target: Where to save the download as downloads.DownloadTarget.
            **kwargs: Passed to _fetch_request.

        Return:
            The created DownloadItem.
        """
        # WORKAROUND for Qt corrupting data loaded from cache:
        # https://bugreports.qt.io/browse/QTBUG-42757
        request.setAttribute(QNetworkRequest.CacheLoadControlAttribute,
                             QNetworkRequest.AlwaysNetwork)

        if suggested_fn is not None:
            pass
        elif request.url().scheme().lower() != 'data':
            suggested_fn = urlutils.filename_from_url(request.url())
        else:
            # We might be downloading a binary blob embedded on a page or even
            # generated dynamically via javascript. We try to figure out a more
            # sensible name than the base64 content of the data.
            origin = request.originatingObject()
            try:
                origin_url = origin.url()
            except AttributeError:
                # Raised either if origin is None or some object that doesn't
                # have its own url. We're probably fine with a default fallback
                # then.
                suggested_fn = 'binary blob'
            else:
                # Use the originating URL as a base for the filename (works
                # e.g. for pdf.js).
                suggested_fn = urlutils.filename_from_url(origin_url)

        if suggested_fn is None:
            suggested_fn = 'qutebrowser-download'

        return self._fetch_request(request,
                                   target=target,
                                   suggested_filename=suggested_fn,
                                   **kwargs)
    def get_request(self, request, *, fileobj=None, filename=None,
                    prompt_download_directory=None, **kwargs):
        """Start a download with a QNetworkRequest.

        Args:
            request: The QNetworkRequest to download.
            fileobj: The file object to write the answer to.
            filename: A path to write the data to.
            prompt_download_directory: Whether to prompt for the download dir
                                       or automatically download. If None, the
                                       config is used.
            **kwargs: Passed to fetch_request.

        Return:
            If the download could start immediately, (fileobj/filename given),
            the created DownloadItem.

            If not, None.
        """
        if fileobj is not None and filename is not None:
            raise TypeError("Only one of fileobj/filename may be given!")
        # WORKAROUND for Qt corrupting data loaded from cache:
        # https://bugreports.qt.io/browse/QTBUG-42757
        request.setAttribute(QNetworkRequest.CacheLoadControlAttribute,
                             QNetworkRequest.AlwaysNetwork)
        suggested_fn = urlutils.filename_from_url(request.url())

        if prompt_download_directory is None:
            prompt_download_directory = config.get(
                'storage', 'prompt-download-directory')
        if not prompt_download_directory and not fileobj:
            filename = config.get('storage', 'download-directory')

        if fileobj is not None or filename is not None:
            return self.fetch_request(request,
                                      fileobj=fileobj,
                                      filename=filename,
                                      suggested_filename=suggested_fn,
                                      **kwargs)
        if suggested_fn is None:
            suggested_fn = 'qutebrowser-download'
        else:
            encoding = sys.getfilesystemencoding()
            suggested_fn = utils.force_encoding(suggested_fn, encoding)
        q = self._prepare_question()
        q.default = _path_suggestion(suggested_fn)
        message_bridge = objreg.get('message-bridge', scope='window',
                                    window=self._win_id)
        q.answered.connect(
            lambda fn: self.fetch_request(request,
                                          filename=fn,
                                          suggested_filename=suggested_fn,
                                          **kwargs))
        message_bridge.ask(q, blocking=False)
        return None
Beispiel #8
0
    def get_request(self,
                    request,
                    *,
                    fileobj=None,
                    filename=None,
                    prompt_download_directory=None,
                    **kwargs):
        """Start a download with a QNetworkRequest.

        Args:
            request: The QNetworkRequest to download.
            fileobj: The file object to write the answer to.
            filename: A path to write the data to.
            prompt_download_directory: Whether to prompt for the download dir
                                       or automatically download. If None, the
                                       config is used.
            **kwargs: Passed to fetch_request.

        Return:
            If the download could start immediately, (fileobj/filename given),
            the created DownloadItem.

            If not, None.
        """
        if fileobj is not None and filename is not None:
            raise TypeError("Only one of fileobj/filename may be given!")
        # WORKAROUND for Qt corrupting data loaded from cache:
        # https://bugreports.qt.io/browse/QTBUG-42757
        request.setAttribute(QNetworkRequest.CacheLoadControlAttribute,
                             QNetworkRequest.AlwaysNetwork)

        suggested_fn = urlutils.filename_from_url(request.url())
        if suggested_fn is None:
            suggested_fn = 'qutebrowser-download'

        # We won't need a question if a filename or fileobj is already given
        if fileobj is None and filename is None:
            filename, q = ask_for_filename(
                suggested_fn,
                self._win_id,
                parent=self,
                prompt_download_directory=prompt_download_directory)

        if fileobj is not None or filename is not None:
            return self.fetch_request(request,
                                      fileobj=fileobj,
                                      filename=filename,
                                      suggested_filename=suggested_fn,
                                      **kwargs)
        q.answered.connect(lambda fn: self.fetch_request(
            request, filename=fn, suggested_filename=suggested_fn, **kwargs))
        self._postprocess_question(q)
        q.ask()
        return None
Beispiel #9
0
    def get_request(self, request, *, fileobj=None, filename=None,
                    prompt_download_directory=None, **kwargs):
        """Start a download with a QNetworkRequest.

        Args:
            request: The QNetworkRequest to download.
            fileobj: The file object to write the answer to.
            filename: A path to write the data to.
            prompt_download_directory: Whether to prompt for the download dir
                                       or automatically download. If None, the
                                       config is used.
            **kwargs: Passed to fetch_request.

        Return:
            If the download could start immediately, (fileobj/filename given),
            the created DownloadItem.

            If not, None.
        """
        if fileobj is not None and filename is not None:
            raise TypeError("Only one of fileobj/filename may be given!")
        # WORKAROUND for Qt corrupting data loaded from cache:
        # https://bugreports.qt.io/browse/QTBUG-42757
        request.setAttribute(QNetworkRequest.CacheLoadControlAttribute,
                             QNetworkRequest.AlwaysNetwork)

        suggested_fn = urlutils.filename_from_url(request.url())
        if suggested_fn is None:
            suggested_fn = 'qutebrowser-download'

        # We won't need a question if a filename or fileobj is already given
        if fileobj is None and filename is None:
            filename, q = ask_for_filename(
                suggested_fn, self._win_id, parent=self,
                prompt_download_directory=prompt_download_directory
            )

        if fileobj is not None or filename is not None:
            return self.fetch_request(request,
                                      fileobj=fileobj,
                                      filename=filename,
                                      suggested_filename=suggested_fn,
                                      **kwargs)
        q.answered.connect(
            lambda fn: self.fetch_request(request,
                                          filename=fn,
                                          suggested_filename=suggested_fn,
                                          **kwargs))
        self._postprocess_question(q)
        q.ask()
        return None
Beispiel #10
0
    def _get_suggested_filename(self, request):
        """Get the suggested filename for the given request."""
        filename_url = request.url()
        if request.url().scheme().lower() == 'data':
            # We might be downloading a binary blob embedded on a page or even
            # generated dynamically via javascript. If we happen to know where it's
            # coming from, we can try to figure out a more sensible name than the base64
            # content of the data.
            origin = request.originatingObject()
            try:
                filename_url = origin.url()
            except AttributeError:
                # Raised either if origin is None or some object that doesn't
                # have its own url. We're probably fine with a default fallback
                # based on the data URL then.
                pass

        return urlutils.filename_from_url(filename_url,
                                          fallback='qutebrowser-download')
Beispiel #11
0
    def get_request(self, request, page=None, fileobj=None, filename=None,
                    auto_remove=False):
        """Start a download with a QNetworkRequest.

        Args:
            request: The QNetworkRequest to download.
            page: The QWebPage to use.
            fileobj: The file object to write the answer to.
            filename: A path to write the data to.
            auto_remove: Whether to remove the download even if
                         ui -> remove-finished-downloads is set to false.

        Return:
            If the download could start immediately, (fileobj/filename given),
            the created DownloadItem.

            If not, None.
        """
        if fileobj is not None and filename is not None:
            raise TypeError("Only one of fileobj/filename may be given!")
        # WORKAROUND for Qt corrupting data loaded from cache:
        # https://bugreports.qt-project.org/browse/QTBUG-42757
        request.setAttribute(QNetworkRequest.CacheLoadControlAttribute,
                             QNetworkRequest.AlwaysNetwork)
        suggested_fn = urlutils.filename_from_url(request.url())
        if fileobj is not None or filename is not None:
            return self.fetch_request(request, page, fileobj, filename,
                                      auto_remove, suggested_fn)
        if suggested_fn is None:
            suggested_fn = 'qutebrowser-download'
        else:
            encoding = sys.getfilesystemencoding()
            suggested_fn = utils.force_encoding(suggested_fn, encoding)
        q = self._prepare_question()
        q.default = _path_suggestion(suggested_fn)
        message_bridge = objreg.get('message-bridge', scope='window',
                                    window=self._win_id)
        q.answered.connect(
            lambda fn: self.fetch_request(request, page, filename=fn,
                                          auto_remove=auto_remove,
                                          suggested_filename=suggested_fn))
        message_bridge.ask(q, blocking=False)
        return None
Beispiel #12
0
    def handle_download(self, qt_item):
        """Start a download coming from a QWebEngineProfile."""
        if qt_item.url().scheme().lower() == 'data':
            # WORKAROUND for an unknown QtWebEngine bug (?) which gives us base64 data
            # as filename.
            suggested_filename = urlutils.filename_from_url(
                qt_item.url(), fallback='qutebrowser-download')
        else:
            suggested_filename = _get_suggested_filename(qt_item.path())

        use_pdfjs = pdfjs.should_use_pdfjs(qt_item.mimeType(), qt_item.url())

        download = DownloadItem(qt_item, manager=self)
        self._init_item(download, auto_remove=use_pdfjs,
                        suggested_filename=suggested_filename)

        if self._mhtml_target is not None:
            download.set_target(self._mhtml_target)
            self._mhtml_target = None
            return
        if use_pdfjs:
            download.set_target(downloads.PDFJSDownloadTarget())
            return

        filename = downloads.immediate_download_path()
        if filename is not None:
            # User doesn't want to be asked, so just use the download_dir
            target = downloads.FileDownloadTarget(filename)
            download.set_target(target)
            return

        # Ask the user for a filename - needs to be blocking!
        question = downloads.get_filename_question(
            suggested_filename=suggested_filename, url=qt_item.url(),
            parent=self)
        self._init_filename_question(question, download)

        message.global_bridge.ask(question, blocking=True)
Beispiel #13
0
 def test_invalid_url(self):
     """Test with an invalid QUrl."""
     assert urlutils.filename_from_url(QUrl()) is None
Beispiel #14
0
 def test_url_host(self):
     """Test with an URL with no path."""
     url = QUrl('http://qutebrowser.org/')
     self.assertEqual(urlutils.filename_from_url(url),
                      'qutebrowser.org.html')
Beispiel #15
0
 def test_invalid_url(self):
     """Test with an invalid QUrl."""
     self.assertEqual(urlutils.filename_from_url(QUrl()), None)
Beispiel #16
0
 def test_url_host(self):
     """Test with an URL with no path."""
     url = QUrl('http://qutebrowser.org/')
     self.assertEqual(urlutils.filename_from_url(url),
                      'qutebrowser.org.html')
Beispiel #17
0
 def test_invalid_url(self):
     """Test with an invalid QUrl."""
     self.assertEqual(urlutils.filename_from_url(QUrl()), None)
Beispiel #18
0
def test_filename_from_url_fallback(qurl):
    assert urlutils.filename_from_url(qurl, fallback='fallback') == 'fallback'
Beispiel #19
0
def test_filename_from_url(qurl, output):
    assert urlutils.filename_from_url(qurl) == output
Beispiel #20
0
    def get_request(self, request, *, fileobj=None, filename=None,
                    prompt_download_directory=None, **kwargs):
        """Start a download with a QNetworkRequest.

        Args:
            request: The QNetworkRequest to download.
            fileobj: The file object to write the answer to.
            filename: A path to write the data to.
            prompt_download_directory: Whether to prompt for the download dir
                                       or automatically download. If None, the
                                       config is used.
            **kwargs: Passed to fetch_request.

        Return:
            If the download could start immediately, (fileobj/filename given),
            the created DownloadItem.

            If not, None.
        """
        if fileobj is not None and filename is not None:
            raise TypeError("Only one of fileobj/filename may be given!")
        # WORKAROUND for Qt corrupting data loaded from cache:
        # https://bugreports.qt.io/browse/QTBUG-42757
        request.setAttribute(QNetworkRequest.CacheLoadControlAttribute,
                             QNetworkRequest.AlwaysNetwork)

        if request.url().scheme().lower() != 'data':
            suggested_fn = urlutils.filename_from_url(request.url())
        else:
            # We might be downloading a binary blob embedded on a page or even
            # generated dynamically via javascript. We try to figure out a more
            # sensible name than the base64 content of the data.
            origin = request.originatingObject()
            try:
                origin_url = origin.url()
            except AttributeError:
                # Raised either if origin is None or some object that doesn't
                # have its own url. We're probably fine with a default fallback
                # then.
                suggested_fn = 'binary blob'
            else:
                # Use the originating URL as a base for the filename (works
                # e.g. for pdf.js).
                suggested_fn = urlutils.filename_from_url(origin_url)

        if suggested_fn is None:
            suggested_fn = 'qutebrowser-download'

        # We won't need a question if a filename or fileobj is already given
        if fileobj is None and filename is None:
            filename, q = ask_for_filename(
                suggested_fn, self._win_id, parent=self,
                prompt_download_directory=prompt_download_directory
            )

        if fileobj is not None or filename is not None:
            return self.fetch_request(request,
                                      fileobj=fileobj,
                                      filename=filename,
                                      suggested_filename=suggested_fn,
                                      **kwargs)
        q.answered.connect(
            lambda fn: self.fetch_request(request,
                                          filename=fn,
                                          suggested_filename=suggested_fn,
                                          **kwargs))
        self._postprocess_question(q)
        q.ask()
        return None
Beispiel #21
0
    def get_request(self, request, *, fileobj=None, filename=None,
                    prompt_download_directory=None, **kwargs):
        """Start a download with a QNetworkRequest.

        Args:
            request: The QNetworkRequest to download.
            fileobj: The file object to write the answer to.
            filename: A path to write the data to.
            prompt_download_directory: Whether to prompt for the download dir
                                       or automatically download. If None, the
                                       config is used.
            **kwargs: Passed to fetch_request.

        Return:
            If the download could start immediately, (fileobj/filename given),
            the created DownloadItem.

            If not, None.
        """
        if fileobj is not None and filename is not None:
            raise TypeError("Only one of fileobj/filename may be given!")
        # WORKAROUND for Qt corrupting data loaded from cache:
        # https://bugreports.qt.io/browse/QTBUG-42757
        request.setAttribute(QNetworkRequest.CacheLoadControlAttribute,
                             QNetworkRequest.AlwaysNetwork)

        if request.url().scheme().lower() != 'data':
            suggested_fn = urlutils.filename_from_url(request.url())
        else:
            # We might be downloading a binary blob embedded on a page or even
            # generated dynamically via javascript. We try to figure out a more
            # sensible name than the base64 content of the data.
            origin = request.originatingObject()
            try:
                origin_url = origin.url()
            except AttributeError:
                # Raised either if origin is None or some object that doesn't
                # have its own url. We're probably fine with a default fallback
                # then.
                suggested_fn = 'binary blob'
            else:
                # Use the originating URL as a base for the filename (works
                # e.g. for pdf.js).
                suggested_fn = urlutils.filename_from_url(origin_url)

        if suggested_fn is None:
            suggested_fn = 'qutebrowser-download'

        # We won't need a question if a filename or fileobj is already given
        if fileobj is None and filename is None:
            filename, q = ask_for_filename(
                suggested_fn, self._win_id, parent=self,
                prompt_download_directory=prompt_download_directory
            )

        if fileobj is not None or filename is not None:
            return self.fetch_request(request,
                                      fileobj=fileobj,
                                      filename=filename,
                                      suggested_filename=suggested_fn,
                                      **kwargs)
        q.answered.connect(
            lambda fn: self.fetch_request(request,
                                          filename=fn,
                                          suggested_filename=suggested_fn,
                                          **kwargs))
        self._postprocess_question(q)
        q.ask()
        return None
def test_filename_from_url(qurl, output):
    assert urlutils.filename_from_url(qurl) == output
Beispiel #23
0
 def test_url_path(self):
     """Test with an URL with path."""
     url = QUrl('http://qutebrowser.org/test.html')
     assert urlutils.filename_from_url(url) == 'test.html'