Esempio n. 1
0
class TestDownloadTarget:

    def test_filename(self):
        target = downloads.FileDownloadTarget("/foo/bar")
        assert target.filename == "/foo/bar"

    def test_fileobj(self):
        fobj = object()
        target = downloads.FileObjDownloadTarget(fobj)
        assert target.fileobj is fobj

    def test_openfile(self):
        target = downloads.OpenFileDownloadTarget()
        assert target.cmdline is None

    def test_openfile_custom_command(self):
        target = downloads.OpenFileDownloadTarget('echo')
        assert target.cmdline == 'echo'

    @pytest.mark.parametrize('obj', [
        downloads.FileDownloadTarget('foobar'),
        downloads.FileObjDownloadTarget(None),
        downloads.OpenFileDownloadTarget(),
    ])
    def test_class_hierarchy(self, obj):
        assert isinstance(obj, downloads._DownloadTarget)
Esempio n. 2
0
    def _get_required_scripts(self, script, force=False):
        required_dls = [(url, self._required_url_to_file_path(url))
                        for url in script.requires]
        if not force:
            required_dls = [(url, path) for (url, path) in required_dls
                            if not os.path.exists(path)]
        if not required_dls:
            # All the required files exist already
            self._add_script_with_requires(script, quiet=True)
            return

        download_manager = objreg.get('qtnetwork-download-manager')

        for url, target_path in required_dls:
            target = downloads.FileDownloadTarget(target_path,
                                                  force_overwrite=True)
            download = download_manager.get(QUrl(url),
                                            target=target,
                                            auto_remove=True)
            download.requested_url = url
            self._in_progress_dls.append(download)
            if download.successful:
                self._on_required_download_finished(script, download)
            else:
                download.finished.connect(
                    functools.partial(self._on_required_download_finished,
                                      script, download))
Esempio n. 3
0
    def handle_download(self, qt_item):
        """Start a download coming from a QWebEngineProfile."""
        suggested_filename = _get_suggested_filename(qt_item.path())
        use_pdfjs = pdfjs.should_use_pdfjs(qt_item.mimeType(), qt_item.url())

        download = DownloadItem(qt_item)
        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)
Esempio n. 4
0
    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)
Esempio n. 5
0
    def fetch(self,
              reply,
              *,
              target=None,
              auto_remove=False,
              suggested_filename=None,
              prompt_download_directory=None):
        """Download a QNetworkReply to disk.

        Args:
            reply: The QNetworkReply to download.
            target: Where to save the download as downloads.DownloadTarget.
            auto_remove: Whether to remove the download even if
                         downloads.remove_finished is set to -1.
            suggested_filename: The filename to use for the file.
            prompt_download_directory: Whether to prompt for a location to
                                       download the file to.

        Return:
            The created DownloadItem.
        """
        if not suggested_filename:
            try:
                suggested_filename = target.suggested_filename()
            except downloads.NoFilenameError:
                _, suggested_filename = http.parse_content_disposition(reply)
        log.downloads.debug("fetch: {} -> {}".format(reply.url(),
                                                     suggested_filename))
        download = DownloadItem(reply, manager=self)
        self._init_item(download, auto_remove, suggested_filename)

        if download.cancel_for_origin():
            return download

        if target is not None:
            download.set_target(target)
            return download

        # Neither filename nor fileobj were given

        filename = downloads.immediate_download_path(prompt_download_directory)
        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 download

        # Ask the user for a filename
        question = downloads.get_filename_question(
            suggested_filename=suggested_filename,
            url=reply.url(),
            parent=self)
        self._init_filename_question(question, download)
        message.global_bridge.ask(question, blocking=False)

        return download
Esempio n. 6
0
def start_download_checked(target, tab):
    """First check if dest is already a file, then start the download.

    Args:
        target: The DownloadTarget where the resulting file should be saved.
        tab: Specify the tab whose page should be loaded.
    """
    if not isinstance(target, downloads.FileDownloadTarget):
        _start_download(target, tab)
        return
    # The default name is 'page title.mhtml'
    title = tab.title()
    default_name = utils.sanitize_filename(title + '.mhtml')

    # Remove characters which cannot be expressed in the file system encoding
    encoding = sys.getfilesystemencoding()
    default_name = utils.force_encoding(default_name, encoding)
    dest = utils.force_encoding(target.filename, encoding)

    dest = os.path.expanduser(dest)

    # See if we already have an absolute path
    path = downloads.create_full_filename(default_name, dest)
    if path is None:
        # We still only have a relative path, prepend download_dir and
        # try again.
        path = downloads.create_full_filename(
            default_name, os.path.join(downloads.download_dir(), dest))
    downloads.last_used_directory = os.path.dirname(path)

    # Avoid downloading files if we can't save the output anyway...
    # Yes, this is prone to race conditions, but we're checking again before
    # saving the file anyway.
    if not os.path.isdir(os.path.dirname(path)):
        folder = os.path.dirname(path)
        message.error("Directory {} does not exist.".format(folder))
        return

    target = downloads.FileDownloadTarget(path)
    if not os.path.isfile(path):
        _start_download(target, tab=tab)
        return

    q = usertypes.Question()
    q.mode = usertypes.PromptMode.yesno
    q.title = "Overwrite existing file?"
    q.text = "<b>{}</b> already exists. Overwrite?".format(
        html.escape(path))
    q.completed.connect(q.deleteLater)
    q.answered_yes.connect(functools.partial(
        _start_download, target, tab=tab))
    message.global_bridge.ask(q, blocking=False)
Esempio n. 7
0
def test_sanitized_filenames(raw, expected, config_stub, download_tmpdir,
                             monkeypatch):
    manager = downloads.AbstractDownloadManager()
    target = downloads.FileDownloadTarget(str(download_tmpdir))
    item = downloads.AbstractDownloadItem()

    # Don't try to start a timer outside of a QThread
    manager._update_timer.isActive = lambda: True

    # Abstract methods
    item._ensure_can_set_filename = lambda *args: True
    item._after_set_filename = lambda *args: True

    manager._init_item(item, True, raw)
    item.set_target(target)
    assert item._filename.endswith(expected)
Esempio n. 8
0
    def get_mhtml(self, tab, target):
        """Download the given tab as mhtml to the given DownloadTarget."""
        assert tab.backend == usertypes.Backend.QtWebKit
        from qutebrowser.browser.webkit import mhtml

        if target is not None:
            mhtml.start_download_checked(target, tab=tab)
            return

        suggested_fn = utils.sanitize_filename(tab.title() + ".mhtml")

        filename = downloads.immediate_download_path()
        if filename is not None:
            target = downloads.FileDownloadTarget(filename)
            mhtml.start_download_checked(target, tab=tab)
        else:
            question = downloads.get_filename_question(
                suggested_filename=suggested_fn, url=tab.url(), parent=tab)
            question.answered.connect(
                functools.partial(mhtml.start_download_checked, tab=tab))
            message.global_bridge.ask(question, blocking=False)
Esempio n. 9
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)
Esempio n. 10
0
 def accept(self, value=None, save=False):
     done = super().accept(value, save)
     answer = self.question.answer
     if answer is not None:
         self.question.answer = downloads.FileDownloadTarget(answer)
     return done
Esempio n. 11
0
 def test_filename(self):
     target = downloads.FileDownloadTarget("/foo/bar")
     assert target.filename == "/foo/bar"
Esempio n. 12
0
 def accept(self, value=None):
     text = value if value is not None else self._lineedit.text()
     self.question.answer = downloads.FileDownloadTarget(text)
     return True