예제 #1
0
    def _switch_to_main_window(self, reason):
        if self.mainwindow.systray_icon:
            self.mainwindow.systray_icon.set_tooltip(reason)
            self.mainwindow.systray_icon.set_blinking(True)

            # Wait for the user to click the icon, then continue
            yield self.mainwindow.systray_icon_blocker
            yield tasks.TimeoutBlocker(0.5, 'Delay')
예제 #2
0
	def confirm_import_feed(self, pending, valid_sigs):
		if self.mainwindow.systray_icon:
			self.mainwindow.systray_icon.set_tooltip(_('Need to confirm a new GPG key'))
			self.mainwindow.systray_icon.set_blinking(True)

			# Wait for the user to click the icon, then continue
			yield self.mainwindow.systray_icon_blocker
			yield tasks.TimeoutBlocker(0.5, 'Delay')

		from zeroinstall.gtkui import trust_box
		box = trust_box.TrustBox(pending, valid_sigs, parent = self.mainwindow.window)
		box.show()
		yield box.closed
예제 #3
0
        def wait_for_downloads(primary):
            # Download just the upstream feed, unless it takes too long...
            timeout = tasks.TimeoutBlocker(5, 'Mirror timeout')  # 5 seconds

            yield primary, timeout
            tasks.check(timeout)

            try:
                tasks.check(primary)
                if primary.happened:
                    return  # OK, primary succeeded!
                # OK, maybe it's just being slow...
                info(
                    "Feed download from %s is taking a long time. Trying mirror too...",
                    feed_url)
                primary_ex = None
            except NoTrustedKeys, ex:
                raise  # Don't bother trying the mirror if we have a trust problem
예제 #4
0
    def testInputBlocker(self):
        r, w = os.pipe()
        b = tasks.InputBlocker(r, "waiting for input")
        t = tasks.TimeoutBlocker(0.01, "timeout")

        @tasks. async
        def run():
            yield b, t
            assert t.happened
            assert not b.happened

            os.write(w, b"!")

            yield b
            assert b.happened

            os.close(r)
            os.close(w)

        tasks.wait_for_blocker(run())
예제 #5
0
    def confirm_keys(self, pending):
        """We don't trust any of the signatures yet. Collect information about them and add the keys to the
		trusted list, possibly after confirming with the user (via config.handler).
		Updates the L{trust} database, and then calls L{trust.TrustDB.notify}.
		@param pending: an object holding details of the updated feed
		@type pending: L{PendingFeed}
		@return: A blocker that triggers when the user has chosen, or None if already done.
		@rtype: None | L{Blocker}
		@since: 0.53"""

        assert pending.sigs

        from zeroinstall.injector import gpg
        valid_sigs = [s for s in pending.sigs if isinstance(s, gpg.ValidSig)]
        if not valid_sigs:

            def format_sig(sig):
                msg = str(sig)
                if sig.messages:
                    msg += "\nMessages from GPG:\n" + sig.messages
                return msg

            raise SafeException(
                _('No valid signatures found on "%(url)s". Signatures:%(signatures)s'
                  ) % {
                      'url':
                      pending.url,
                      'signatures':
                      ''.join(['\n- ' + format_sig(s) for s in pending.sigs])
                  })

        # Start downloading information about the keys...
        fetcher = self.config.fetcher
        kfs = {}
        for sig in valid_sigs:
            kfs[sig] = fetcher.fetch_key_info(sig.fingerprint)

        # Wait up to KEY_INFO_TIMEOUT seconds for key information to arrive. Avoids having the dialog
        # box update while the user is looking at it, and may allow it to be skipped completely in some
        # cases.
        timeout = tasks.TimeoutBlocker(KEY_INFO_TIMEOUT, "key info timeout")
        while True:
            key_info_blockers = [
                sig_info.blocker for sig_info in kfs.values()
                if sig_info.blocker is not None
            ]
            if not key_info_blockers:
                break
            logger.info("Waiting for response from key-info server: %s",
                        key_info_blockers)
            yield [timeout] + key_info_blockers
            if timeout.happened:
                logger.info("Timeout waiting for key info response")
                break

        # If we're already confirming something else, wait for that to finish...
        while self._current_confirm is not None:
            logger.info("Waiting for previous key confirmations to finish")
            yield self._current_confirm

        domain = domain_from_url(pending.url)

        if self.config.auto_approve_keys:
            existing_feed = self.config.iface_cache.get_feed(pending.url)
            if not existing_feed:
                changes = False
                trust_db._dry_run = self.config.handler.dry_run
                for sig, kf in kfs.items():
                    for key_info in kf.info:
                        if key_info.getAttribute("vote") == "good":
                            logger.info(
                                _("Automatically approving key for new feed %s based on response from key info server"
                                  ), pending.url)
                            trust_db.trust_key(sig.fingerprint, domain)
                            changes = True
                if changes:
                    trust_db.notify()

        # Check whether we still need to confirm. The user may have
        # already approved one of the keys while dealing with another
        # feed, or we may have just auto-approved it.
        for sig in kfs:
            is_trusted = trust_db.is_trusted(sig.fingerprint, domain)
            if is_trusted:
                return

        # Take the lock and confirm this feed
        self._current_confirm = lock = tasks.Blocker('confirm key lock')
        try:
            done = self.config.handler.confirm_import_feed(pending, kfs)
            if done is not None:
                yield done
                tasks.check(done)
        finally:
            self._current_confirm = None
            lock.trigger()
예제 #6
0
        def wait_for_downloads(primary):
            # Download just the upstream feed, unless it takes too long...
            timeout = tasks.TimeoutBlocker(5, 'Mirror timeout')  # 5 seconds

            yield primary, timeout
            tasks.check(timeout)

            try:
                tasks.check(primary)
                if primary.happened:
                    return  # OK, primary succeeded!
                # OK, maybe it's just being slow...
                info("Feed download from %s is taking a long time.", feed_url)
                primary_ex = None
            except NoTrustedKeys as ex:
                raise  # Don't bother trying the mirror if we have a trust problem
            except ReplayAttack as ex:
                raise  # Don't bother trying the mirror if we have a replay attack
            except DownloadAborted as ex:
                raise  # Don't bother trying the mirror if the user cancelled
            except SafeException as ex:
                # Primary failed
                primary = None
                primary_ex = ex
                warn(_("Feed download from %(url)s failed: %(exception)s"), {
                    'url': feed_url,
                    'exception': ex
                })

            # Start downloading from mirror...
            mirror = self._download_and_import_feed(feed_url,
                                                    force,
                                                    use_mirror=True)

            # Wait until both mirror and primary tasks are complete...
            while True:
                blockers = filter(None, [primary, mirror])
                if not blockers:
                    break
                yield blockers

                if primary:
                    try:
                        tasks.check(primary)
                        if primary.happened:
                            primary = None
                            # No point carrying on with the mirror once the primary has succeeded
                            if mirror:
                                info(
                                    _("Primary feed download succeeded; aborting mirror download for %s"
                                      ) % feed_url)
                                mirror.dl.abort()
                    except SafeException as ex:
                        primary = None
                        primary_ex = ex
                        info(
                            _("Feed download from %(url)s failed; still trying mirror: %(exception)s"
                              ), {
                                  'url': feed_url,
                                  'exception': ex
                              })

                if mirror:
                    try:
                        tasks.check(mirror)
                        if mirror.happened:
                            mirror = None
                            if primary_ex:
                                # We already warned; no need to raise an exception too,
                                # as the mirror download succeeded.
                                primary_ex = None
                    except ReplayAttack as ex:
                        info(
                            _("Version from mirror is older than cached version; ignoring it: %s"
                              ), ex)
                        mirror = None
                        primary_ex = None
                    except SafeException as ex:
                        info(_("Mirror download failed: %s"), ex)
                        mirror = None

            if primary_ex:
                raise primary_ex