Exemplo n.º 1
0
Arquivo: dist.py Projeto: ygini/munki
def get_blocking_apps_from_dom(dom):
    '''Gets must-close items from parsed su_dist and returns an array of
    blocking_applications in the format Munki wants'''
    # get blocking_applications, if any.
    # First, find all the must-close items.
    must_close_app_ids = []
    must_close_items = dom.getElementsByTagName('must-close')
    for item in must_close_items:
        apps = item.getElementsByTagName('app')
        for app in apps:
            keys = app.attributes.keys()
            if 'id' in keys:
                must_close_app_ids.append(app.attributes['id'].value)

    # next, we convert Apple's must-close items to
    # Munki's blocking_applications
    blocking_apps = []
    # this will only find blocking_applications that are currently installed
    # on the machine running this code, but that's OK for our needs
    #
    # use set() to eliminate any duplicate application ids
    for app_id in set(must_close_app_ids):
        dummy_resultcode, dummy_fileref, nsurl = LSFindApplicationForInfo(
            0, app_id, None, None, None)
        if nsurl and nsurl.isFileURL():
            pathname = nsurl.path()
            dirname = os.path.dirname(pathname)
            executable = pkgutils.getAppBundleExecutable(pathname)
            if executable:
                # path to executable should be location agnostic
                executable = executable[len(dirname + '/'):]
            blocking_apps.append(executable or pathname)
    return blocking_apps
Exemplo n.º 2
0
def macosx_update_check():
    """Check for updates on Mac OS X.  Returns zero on success.
    
    Discussion:
    Requires PyObjC bindings for Python.  Works on Mac OS X 10.5 and later, only, unless
    the necessary PyObjC components can be installed manually on earlier systems.  An
    alert is displayed if updates are available, and the user is given an option to
    ignore it or launch TeX Live Utility to handle the updates.
    
    Some sanity checks are present to ensure a login session that can display the alert.
    They may not be sufficient to avoid showing the alert over a full-screen window,
    unless an application has captured the display.
    
    """

    assert sys.platform == "darwin", "incorrect platform"

    from CoreFoundation import CFUserNotificationDisplayNotice, CFUserNotificationDisplayAlert, CFBundleCreate, CFBundleCopyResourceURL, CFPreferencesCopyAppValue
    from CoreFoundation import kCFUserNotificationNoteAlertLevel, kCFUserNotificationAlternateResponse

    from Quartz import CGMainDisplayID, CGDisplayIsCaptured, CGSessionCopyCurrentDictionary
    from Quartz import kCGSessionOnConsoleKey, kCGSessionLoginDoneKey

    from LaunchServices import LSFindApplicationForInfo, LSOpenFromURLSpec
    from LaunchServices import kLSUnknownCreator, LSLaunchURLSpec

    from Foundation import NSURL, NSFoundationVersionNumber
    from math import floor

    # http://developer.apple.com/library/mac/#documentation/MacOSX/Conceptual/BPMultipleUsers/BPMultipleUsers.html
    sessionInfo = CGSessionCopyCurrentDictionary()
    if sessionInfo == None:
        log_message("unable to get session dictionary")
        return 0

    if sessionInfo[kCGSessionOnConsoleKey] is False:
        log_message("not running as console user; skipping update check")
        return 0

    if sessionInfo[kCGSessionLoginDoneKey] is False:
        log_message("login incomplete; skipping update check")
        return 0

    # check this first; no point in continuing if we can't show the alert
    # note: this doesn't help with Skim's full screen mode
    if CGDisplayIsCaptured(CGMainDisplayID()):
        log_message("main display not available for update alert")
        return 0

    # TeX Live Utility bundle identifier
    bundle_id = "com.googlecode.mactlmgr.tlu"

    # if this hasn't been set, try the default path
    texbin_path = CFPreferencesCopyAppValue("TLMTexBinPathPreferenceKey",
                                            bundle_id)
    if texbin_path == None:
        if os.path.exists("/usr/texbin"):
            texbin_path = "/usr/texbin"
        elif os.path.exists("/Library/TeX/texbin"):
            texbin_path = "/Library/TeX/texbin"

    if texbin_path == None:
        log_message(
            "no tlmgr path set; TeX Live update check will not proceed")
        return 1

    repository = CFPreferencesCopyAppValue("TLMFullServerURLPreferenceKey",
                                           bundle_id)
    update_count, actual_repository = check_for_updates(os.path.join(
        texbin_path, "tlmgr"),
                                                        repository=repository)

    if update_count == 0:
        return 0

    if floor(NSFoundationVersionNumber) > 833:

        bundle_id = "com.googlecode.mactlmgr.TLUNotifier"
        ret, tln_fsref, tln_url = LSFindApplicationForInfo(
            kLSUnknownCreator, bundle_id, None, None, None)

        # launch TLUNotifier, passing the URL as an odoc Apple Event
        if ret == 0 and tln_url:
            log_message("using notifier %s with URL %s" %
                        (tln_url, actual_repository))
            spec = LSLaunchURLSpec()
            spec.appURL = tln_url
            spec.itemURLs = [NSURL.URLWithString_(actual_repository)
                             ] if actual_repository else None
            ret, launchedURL = LSOpenFromURLSpec(spec, None)
            if ret:
                log_message("unable to launch TLUNotifier at %s (%d)" %
                            (tln_url, ret))
        else:
            log_message("unable to find TLUNotifier")

    else:

        title = "TeX Live updates available"
        msg = "Updates for %d %s are available for TeX Live.  Would you like to update with TeX Live Utility now, or at a later time?" % (
            update_count, "packages" if update_count > 1 else "package")

        # see if we can find TeX Live Utility...hopefully LaunchServices is working today
        ret, tlu_fsref, tlu_url = LSFindApplicationForInfo(
            kLSUnknownCreator, bundle_id, None, None, None)

        bundle = CFBundleCreate(None, tlu_url) if ret == 0 else None
        icon_url = CFBundleCopyResourceURL(bundle, "TeXDistTool", "icns",
                                           None) if bundle else None

        # show a modal alert, with options to update now or later
        cancel, response = CFUserNotificationDisplayAlert(
            _ALERT_TIMEOUT, kCFUserNotificationNoteAlertLevel, icon_url, None,
            None, title, msg, "Later", "Update", None, None)
        if kCFUserNotificationAlternateResponse == response:

            # launch TeX Live Utility, passing the URL as an odoc Apple Event
            spec = LSLaunchURLSpec()
            spec.appURL = tlu_url
            spec.itemURLs = [NSURL.URLWithString_(actual_repository)
                             ] if actual_repository else None
            ret, launchedURL = LSOpenFromURLSpec(spec, None)

        else:
            log_message("user postponed TeX Live updates")

    return 0
Exemplo n.º 3
0
    for item in must_close_items:
        apps = item.getElementsByTagName('app')
        for app in apps:
            keys = app.attributes.keys()
            if 'id' in keys:
                must_close_app_ids.append(app.attributes['id'].value)

    # next, we convert Apple's must-close items to
    # Munki's blocking_applications
    blocking_apps = []
    # this will only find blocking_applications that are currently installed
    # on the machine running this code, but that's OK for our needs
    #
    # use set() to eliminate any duplicate application ids
    for app_id in set(must_close_app_ids):
        dummy_resultcode, dummy_fileref, nsurl = LSFindApplicationForInfo(
            0, app_id, None, None, None)
        if nsurl and nsurl.isFileURL():
            pathname = nsurl.path()
            dirname = os.path.dirname(pathname)
            executable = pkgutils.getAppBundleExecutable(pathname)
            if executable:
                # path to executable should be location agnostic
                executable = executable[len(dirname + '/'):]
            blocking_apps.append(executable or pathname)

    # get firmware alert text if any
    firmware_alert_text = get_firmware_alert_text(dom)

    # assemble!
    info = {}
    info['name'] = su_choice.get('suDisabledGroupID', '')