home *** CD-ROM | disk | FTP | other *** search
Wrap
# Source Generated with Decompyle++ # File: in.pyo (Python 2.6) import logging log = logging.getLogger('d_updater') import sys import traceback import io import time import wx import gui import hashlib import path import syck import config import stdpaths import hooks import peak.util.addons as addons import lxml.objectify as objectify import util import util.net as net import util.callbacks as callbacks import common import common.asynchttp as asynchttp import file_integrity import downloader if config.platform == 'win': import winhelpers as helpers elif config.platform == 'mac': import machelpers as helpers def rm_emptydirs(dir): for d in dir.dirs(): rm_emptydirs(d) if not dir.files() or dir.dirs(): try: dir.rmdir() except Exception: pass except: None<EXCEPTION MATCH>Exception None<EXCEPTION MATCH>Exception class UpdateChecker(object): def __init__(self, release_type = None): self.remote_manifest_path = None if not release_type: pass self.release_type = self.get_release_type() self.callback = None def update(self, callback = None): self.callback = callback self.get_manifest_path() update = callbacks.callsback(update) def manifest_path_error(self, e): log.info('Error getting manifest path: %r', e) self._error(e) def manifest_request_error(self, e): log.error('Error retrieving manifest file: %r', e) self._error(e) def manifest_check_error(self, e): log.error('Error checking manifest integrity: %r', e) self._error(e) def update_check_complete(self, needs_update, manifest_data): log.info('Update check complete. Need update? %r', needs_update) self._success(needs_update, self.remote_manifest_path, manifest_data) def _error(self, e): cb = self.callback self.callback = None if cb is not None: cb.error(e) def _success(self, *a): cb = self.callback self.callback = None if cb is not None: cb.success(*a) def check_manifest_integrity(self, req, resp): headers = resp.headers rmtime = headers.get('x-amz-meta-mtime', None) if rmtime is None: rmtime = headers.get('last-modified', None) if rmtime is not None: rmtime = net.http_date_to_timestamp(rmtime) if rmtime is not None: try: rmtime = int(rmtime) except (TypeError, ValueError): rmtime = None except: None<EXCEPTION MATCH>(TypeError, ValueError) None<EXCEPTION MATCH>(TypeError, ValueError) prog_dir = util.program_dir() self.local_manifest_path = path.path(prog_dir) / path.path(self.remote_manifest_path).splitpath()[-1] needs_update = True if self.local_manifest_path.isfile(): lmtime = int(self.local_manifest_path.mtime) else: lmtime = 0 if sys.opts.force_update or lmtime != rmtime: log.info('MTime mismatch or sys.opts.force_update is True. Downloading manifest. (local=%r, remote=%r)', lmtime, rmtime) downloader.httpopen(self.remote_manifest_path, success = self.got_manifest_response, error = self.manifest_request_error) else: log.info('Local MTime matches remote. Not downloading manifest. (local=%r, remote=%r)', lmtime, rmtime) self.update_check_complete(False, None) def got_manifest_response(self, req, resp): if self.local_manifest_path.isfile(): local_manifest_digest = self.local_manifest_path.read_md5() else: local_manifest_digest = None log.info('Got manifest response. Comparing hashes.') manifest_data = resp.read() remote_manifest_digest = hashlib.md5(manifest_data).digest() needs_update = local_manifest_digest != remote_manifest_digest if sys.opts.force_update: needs_update = True if not needs_update: manifest_data = None self.update_check_complete(needs_update, manifest_data) def get_release_type(self): return get_client_tag() def get_manifest_path(self): program_dir = util.program_dir() local_info_file = program_dir / 'update.yaml' if local_info_file.isfile(): try: local_info = open(local_info_file, 'rb') except Exception: pass self.got_updateyaml(fobj = local_info) return None local_info_file.isfile() log.info('Manifest path not found in %r. checking web for update.yaml', local_info_file) asynchttp.httpopen('http://s3.amazonaws.com/update.digsby.com/update.yaml?%s' % int(time.time()), success = self.got_updateyaml, error = self.manifest_path_error) def got_updateyaml(self, req = None, fobj = None): try: data = fobj.read() except Exception: e = None return self.manifest_path_error(e) try: ui = syck.load(data) except Exception: e = None return self.manifest_path_error(e) all = ui.get('all', { }) if not ui.get(config.platform, None): pass mine = { } merged = all.copy() merged.update(mine) manifest_path = merged.get(self.release_type, merged.get('release', None)) if manifest_path is None: self.update_check_error(Exception('No manifest URL for %r in %r' % (self.release_type, all))) else: log.info('Got manifest path: %r', manifest_path) self.remote_manifest_path = manifest_path downloader.httpopen(self.remote_manifest_path, method = 'HEAD', success = self.check_manifest_integrity, error = self.manifest_check_error) def help_menu_items(*a): if not common.pref('digsby.updater.help_menu', type = bool, default = True): return [] if sys.TAG and sys.TAG != 'release': txt = _('Check for %s updates') % sys.TAG else: txt = _('Check for Updates') return [ (txt, update_check)] def update_check(*a): p = common.profile() if p is not None: UpdateManager(p).update() def update_check_later(*a): util.Timer(common.pref('digsby.updater.initial_delay', type = int, default = 300), update_check).start() def on_update_complete(*a): for handler in logging.root.handlers: handler.flush() src_file = path.path(sys.LOGFILE_NAME) dst_file = src_file.parent / 'digsby_update_download.log.csv' try: data = src_file.bytes() except Exception: e = None f = io.BytesIO() traceback.print_exc(file = f) data = f.getvalue() del f try: f = _[1] f.write(data) finally: pass def update_cancel(*a): p = common.profile() if p is not None: UpdateManager(p).cancel() def start_fastmode(*a): p = common.profile() if p is not None: UpdateManager(p).set_fastmode(True) def stop_fastmode(*a): p = common.profile() if p is not None: UpdateManager(p).set_fastmode(False) def load_tag_and_install_update(*a): get_client_tag() return install_update() def was_updated(): if sys.opts.updated: p = common.profile() buddy = util.Storage(name = 'digsby.org', service = 'digsby', protocol = p.connection, increase_log_size = (lambda : pass), icon = None) msg = common.message.Message(buddy = buddy, message = _get_release_notes(), content_type = 'text/html', conversation = util.Storage(protocol = p.connection, buddy = buddy, ischat = False)) p.on_message(msg) def _get_release_notes(): try: try: f = _[1] data = f.read() finally: pass return data except Exception: e = None log.error('Release notes not found. %r', e) return '' def install_update(*a): temp_dir = file_integrity.GetUserTempDir() manifest = temp_dir / 'manifest' updateme = temp_dir / 'updateme.txt' deleteme = temp_dir / 'deleteme.txt' if UpdateManager(Null()).should_check_for_updates() and not (sys.opts.update_failed): if updateme.isfile() and deleteme.isfile() and manifest.isfile(): print >>sys.stderr, 'Installing update' log.info('Installing update') helpers.restart_and_update(temp_dir) return False else: _delete_updater_files() print >>sys.stderr, 'Not installing update' log.info('Not installing update') def _delete_updater_files(): temp_dir = file_integrity.GetUserTempDir() manifest = temp_dir / 'manifest' updateme = temp_dir / 'updateme.txt' deleteme = temp_dir / 'deleteme.txt' if updateme.isfile(): updateme.remove() if deleteme.isfile(): deleteme.remove() if manifest.isfile(): manifest.remove() sys.opts.update_failed = False def update_status(): p = common.profile() if p is None: return False um = UpdateManager(p) if um.updating: if um.downloader: return 'downloading' if um.updater: return 'filechecking' return 'checking' return 'idle' def get_client_tag(): if getattr(sys, 'DEV', False): tag = '' else: tag = 'release' tag_fname = 'tag.yaml' for fpath in (stdpaths.userlocaldata / tag_fname, util.program_dir() / tag_fname): try: try: f = _[1] yaml = syck.load(f) tag = yaml['tag'] finally: pass except Exception: e = None log.debug("Didn't get a release tag from %r: %r", fpath, e) continue log.info('Got release tag %r from %r', tag, fpath) sys.TAG = tag return tag class UpdateManager(addons.AddOn): updating = False def setup(self): log.info('UpdateManager setup') self.updating = False self.cancelling = False self.updater = None self.downloader = None self.update_checker = UpdateChecker() self._timer = util.RepeatTimer(common.pref('digsby.updater.update_interval', type = int, default = 21600), self.update) self._timer.start() self.fast_mode = False def set_fastmode(self, v): self.fast_mode = v if self.updater is not None: self.updater.fast_mode = v def cancel(self): if not self.updating: return None self.updating = False self.cancelling = True if self.updater is not None: self.updater.cancel() self.updater = None if self.downloader is not None: self.downloader.cancel() self.downloader = None hooks.notify('digsby.updater.cancelled') def should_check_for_updates(self): retval = True reason = None if not sys.opts.allow_update: retval = False reason = 'sys.opts.allow_updates == False' if sys.DEV and not (sys.opts.force_update): retval = False reason = 'sys.DEV and not sys.opts.force_update' if self.updating: retval = False reason = 'already checking for updates, or currently updating' if not retval: log.info('Not checking for updates because: %r', reason) return retval def update(self): if not self.should_check_for_updates(): if not self.updating: hooks.notify('digsby.updater.update_check_results', False, None, None) return None self.delete_file_changes() self.cancelling = False self.updating = True hooks.notify('digsby.updater.update_start') self.update_checker.release_type = get_client_tag() self.update_checker.update(success = self.update_check_success, error = self.update_check_error) def update_check_success(self, update_required, manifest_path, manifest_data): log.info('Got result for update check. update_required = %r, manifest_path = %r', update_required, manifest_path) hooks.notify('digsby.updater.update_check_results', update_required, manifest_path, manifest_data) if not update_required: self.cancel() return None if self.cancelling: return None log.info('Starting updater.') self.updater = file_integrity.ProgramIntegrityChecker(manifest_path = manifest_path, manifest_data = manifest_data) self.updater.start(success = self.file_check_complete) def update_check_error(self, *a): self.cancel() hooks.notify('digsby.updater.update_check_error', *a) def file_check_complete(self, updater): if not updater.update_files or updater.delete_files: self.cancel() return None self.downloader = downloader.Downloader(updater) auto_download = common.pref('digsby.updater.auto_download', type = bool, default = True) res = [] def after_popup(): if auto_download: self.start_downloader() elif not res or res[0] is None: def dialog_cb(ok): if ok: self.start_downloader() else: self.stop_timer() diag = gui.toolbox.SimpleMessageDialog(None, title = _('Update Available'), message = _('A Digsby update is available to download.\nWould you like to begin downloading it now?'), icon = gui.skin.get('serviceicons.digsby').Resized(32), ok_caption = _('Yes'), cancel_caption = _('No'), wrap = 450) diag.OnTop = True diag.ShowWithCallback(dialog_cb) def do_popup(): res.append(gui.toast.popup(icon = gui.skin.get('serviceicons.digsby'), header = _('Update Available'), minor = _('A Digsby update is available to download.\nWould you like to begin downloading it now?'), sticky = True, buttons = [ ((_('Yes'),), (lambda : self.start_downloader())), (_('No'), self.stop_timer)], size = util.nicebytecount(updater.expected_download_size), onclose = self._download_popup_closed)) wx.CallAfter(after_popup) if not auto_download: wx.CallAfter(do_popup) else: wx.CallAfter(after_popup) def write_file_changes(self, temp, to_update, to_delete): if not temp.isdir(): temp.makedirs() try: out = _[1] if to_delete: write = lambda s: out.write(unicode(s).encode('filesys', 'replace') + '\n') for f in sorted(to_delete, reverse = True): rel_path = self.updater.local_dir.relpathto(f) write(rel_path) finally: pass try: out = _[2] write = lambda s: out.write(unicode(s).encode('filesys', 'replace') + '\n') write('manifest') for f in sorted(to_update, reverse = True): if f.path.lower() != helpers.get_exe_name().lower(): write(f.path) continue (open(temp / 'updateme.txt', 'wb').__exit__,) finally: pass def delete_file_changes(self): _delete_updater_files() def start_downloader(self): if self.cancelling: return None self.downloader.start(success = self.download_success, error = self.download_error) def stop_timer(self, *a): log.info('Stopping update checker timer.') self._timer.stop() self.cancel() def _download_popup_closed(self, *a, **k): if k.get('userClose', False): self.stop_timer() def download_error(self, error_files, success_files): log.error('Update incomplete. %d successful files, %d errored files', len(success_files), len(error_files)) for f in error_files: log.error('\t%r', f.path) self.cancel() hooks.notify('digsby.updater.update_failed') auto_download = common.pref('digsby.updater.auto_download', type = bool, default = True) if not auto_download: popup = gui.toast.popup(icon = gui.skin.get('serviceicons.digsby'), header = _('Update Failed'), minor = _('Digsby was unable to complete the download. This update will be attempted again later.'), sticky = True, buttons = [ (_('Manual Update'), (lambda : wx.LaunchDefaultBrowser('http://install.digsby.com'))), ((_('Close'),), (lambda : popup.cancel()))]) def download_success(self, success_files): log.info('Downloaded files. %d files downloaded', len(success_files)) updater = self.updater if updater is None: self.cancel() return None self.write_file_changes(updater.temp_dir, updater.update_files, updater.delete_files) hooks.notify('digsby.updater.update_complete') if not common.pref('digsby.updater.install_prompt', type = bool, default = False): log.debug('Update install prompt disabled. Scheduling install') self.schedule_install() else: res = [] def after_popup(): if not res or res[0] is None: log.debug('Popup was not shown. Scheduling install') self.schedule_install() def do_popup(): res.append(gui.toast.popup(icon = gui.skin.get('serviceicons.digsby'), header = _('Update Ready'), minor = _('A new version of Digsby is ready to install. Restart Digsby to apply the update.'), sticky = True, buttons = [ (_('Restart Now'), self.do_install), (_('Restart Later'), self.schedule_install)], onclose = self._install_popup_closed)) wx.CallAfter(after_popup) do_popup = (None, (None, None), wx.CallAfter)(do_popup) def do_install(self): log.info('Doing install!') if self.cancelling: log.info("\tNevermind, we're cancelling. Install not happening now.") return None install_update() def _install_popup_closed(self, *a, **k): if k.get('userClose', False): self.schedule_install() def schedule_install(self): log.info('Schedule install somehow!') self.stop_timer()