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')
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
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
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())
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()
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