📄 autoupdatebutler.py
字号:
parts = [app_name, str(available_version)] if available_version.is_beta(): parts.append('Beta') name = '-'.join(parts) name += '.' + ext return name def _calc_installer_dir(self): """Find a place to store the installer while it's being downloaded.""" temp_dir = get_temp_dir() return temp_dir def _get_available(self, url): """Get the available version from the version site. The command line option --new_version X.Y.Z overrides this method and returns 'X.Y.Z' instead.""" self.debug('_get_available() run#%d: hitting url %s' % (self.runs, url)) try: u = zurllib.urlopen(url) s = u.read() s = s.strip() except: raise BTFailure(_("Could not get latest version from %s")%url) try: # we're luck asserts are turned off in production. # this assert is false for 4.20.X #assert len(s) == 5 available_version = Version.from_str(s) except: raise BTFailure(_("Could not parse new version string from %s")%url) return available_version def _get_torrent(self, installer_url): """Get the .torrent file from the version site.""" torrentfile = None try: torrentfile = GetTorrent.get_url(installer_url) except GetTorrent.GetTorrentException, e: self.debug('_get_torrent() run#%d: failed to download torrent file %s: %s' % (self.runs, installer_url, unicode(e.args[0]))) pass return torrentfile def _get_signature(self, installer_url): """Get the signature (.sign) file from the version site, and unpickle the signature. The sign file is a signature of the .torrent file created with the auto-update tool in auto-update/sign_file.py.""" signature = None try: signfile = zurllib.urlopen(installer_url + '.sign') except: self.debug('_get_signature() run#%d: failed to download signfile %s.sign' % (self.runs, installer_url)) pass else: try: signature = pickle.load(signfile) except: self.debug('_get_signature() run#%d: failed to unpickle signfile %s' % (self.runs, signfile)) pass return signature def _check_signature(self, torrentfile, signature): """Check the torrent file's signature using the public key.""" public_key_file = open(os.path.join(doc_root, 'public.key'), 'rb') public_key = pickle.load(public_key_file) public_key_file.close() h = sha(torrentfile).digest() return public_key.verify(h, signature) def check_version(self): """Launch the actual version check code in a coroutine since it needs to make three (or four, in beta) http requests, one disk read, and one decryption.""" df = launch_coroutine(_wrap_task(self.rawserver.external_add_task), self._check_version) def errback(e): from traceback import format_exc self.debug('check_version() run #%d: '%self.runs + format_exc(e)) df.addErrback(errback) def _check_version(self): """Actually check for an auto-update: 1. Check the version number from the file on the version site. 2. Check the stable version number from the file on the version site. 3. Notify the user and stop if they are on an OS with no installer. 4. Get the torrent file from the version site. 5. Get the signature from the version site. 6. Check the signature against the torrent file using the public key. 7a. Start the torrent if it's not in the client. 7b. Restart the torrent if it's in the client but not running. 8. Put the infohash of the torrent into estate so the butler knows to butle it. 9. AutoUpdateButler.started() ensures that only the most recent auto-update torrent is running. 10. AutoUpdateButler.finished() indicates the new version is available, the UI polls for that value later. Whether an auto-update was found and started or not, requeue the call to check_version() to run a day later. This means that the version check runs at startup, and once a day. """ debug_prefix = '_check_version() run#%d: '%self.runs self.debug(debug_prefix + 'starting') url = self.version_site + self.current_version.name() df = ThreadedDeferred(_wrap_task(self.rawserver.external_add_task), self._get_available, url, daemon=True) yield df try: available_version = df.getResult() except BTFailure, e: self.debug(debug_prefix + 'failed to load %s' % url) self._restart() return if available_version.is_beta(): if available_version[1] != self.current_version[1]: available_version = self.current_version if self.current_version.is_beta(): stable_url = self.version_site + 'stable' df = ThreadedDeferred(_wrap_task(self.rawserver.external_add_task), self._get_available, stable_url) yield df try: available_stable_version = df.getResult() except BTFailure, e: self.debug(debug_prefix + 'failed to load %s' % url) self._restart() return if available_stable_version > available_version: available_version = available_stable_version self.debug(debug_prefix + 'got %s' % str(available_version)) if available_version <= self.current_version: self.debug(debug_prefix + 'not updating old version %s' % str(available_version)) self._restart() return if not self._can_install(): self.debug(debug_prefix + 'cannot install on this os') self.available_version = available_version self._restart() return installer_name = self._calc_installer_name(available_version) installer_url = self.version_site + installer_name + '.torrent' fs_name = encode_for_filesystem(installer_name.decode('ascii'))[0] installer_path = os.path.join(self.installer_dir, fs_name) df = ThreadedDeferred(_wrap_task(self.rawserver.external_add_task), self._get_torrent, installer_url) yield df torrentfile = df.getResult() df = ThreadedDeferred(_wrap_task(self.rawserver.external_add_task), self._get_signature, installer_url) yield df signature = df.getResult() if torrentfile and signature: df = ThreadedDeferred(_wrap_task(self.rawserver.external_add_task), self._check_signature, torrentfile, signature) yield df checked = df.getResult() if checked: self.debug(debug_prefix + 'signature verified successfully.') b = bdecode(torrentfile) metainfo = ConvertedMetainfo(b) infohash = metainfo.infohash self.available_version = available_version self.multitorrent.remove_auto_updates_except(infohash) try: df = self.multitorrent.create_torrent(metainfo, installer_path, installer_path, hidden=True, is_auto_update=True) yield df df.getResult() except TorrentAlreadyRunning: self.debug(debug_prefix + 'found auto-update torrent already running') except TorrentAlreadyInQueue: self.debug(debug_prefix + 'found auto-update torrent queued') else: self.debug(debug_prefix + 'starting auto-update download') self.debug(debug_prefix + 'adding to estate '+infohash.short()) self.estate.add(infohash) else: self.debug(debug_prefix + 'torrent file signature failed to verify.') pass else: self.debug(debug_prefix + 'couldn\'t get both torrentfile %s and signature %s' % (str(type(torrentfile)), str(type(signature)))) self._restart() def _restart(self): """Run the auto-update check once a day, or every ten seconds in debug mode.""" self.runs += 1 self.rawserver.external_add_task(self.delay, self.check_version)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -