from Authorization import Authorization, kAuthorizationFlagDestroyRights from Foundation import NSBundle, NSNotificationCenter, NSObject, NSURL from AppKit import NSWorkspace from appscript import app, k, its from appscript.specifier import CommandError import os, osax, subprocess, tempfile, SCNetworkReachability appBundle = NSBundle.mainBundle() def ensureKerberosPrincipalsValid(principals): kerberosApp = app(id='edu.mit.Kerberos.KerberosApp') validPrincipals = kerberosApp.caches.filter( \ (its.time_remaining.startswith('Expired').NOT) \ .AND(its.time_remaining.startswith('Not Valid').NOT)) \ .principal.get() for principal in principals: if principal not in validPrincipals: # XXX make these async kerberosApp.renew_tickets(for_principal=principal) # kerberosApp.get_tickets(for_principal=principal) def setVolumePercent(percent): # XXX should use CoreAudio: see Pester/Source/NJRSoundManager.m osax.setvolume(int(7 * percent)) def _openURL(url): ws = NSWorkspace.sharedWorkspace() url = NSURL.URLWithString_(url) return ws.openURL_(url) class _LDURLWatcher(NSObject): def URLIsReachable_(self, notification): _openURL(notification.object()) _urlWatcher = _LDURLWatcher.alloc().init() NSNotificationCenter.defaultCenter().addObserver_selector_name_object_( _urlWatcher, 'URLIsReachable:', SCNetworkReachability.SCNetworkIsReachable, None) def openURL(url): hostname = NSURL.URLWithString_(url).host() if not SCNetworkReachability.notify_when_reachable(hostname, url): _openURL(url) def openInBackground(path): ws = NSWorkspace.sharedWorkspace() path = os.path.expanduser(path) return ws.openFile_withApplication_andDeactivate_(path, None, False) def openApplicationWithName(name): ws = NSWorkspace.sharedWorkspace() return ws.launchApplication_(name) def setDisplayBrightnessPercent(percent): # XXX create brightness module pathToBrightness = appBundle.pathForResource_ofType_('brightness', None) subprocess.call([pathToBrightness, str(percent)], stderr=subprocess.STDOUT, stdout=subprocess.PIPE) def setAdiumStatus(status): # XXX doesn't match preset status if available adiumApp = app(id='com.adiumX.adiumX') if adiumApp.my_status_type() == k.offline: adiumApp.my_status.status_message_string.set(status) else: adiumApp.my_status_message.set(status) adiumApp.my_status_type.set(k.available) def moveWindow(appName, windowName, position, ifSizeMatches=None): # XXX support locations relative to screen corners systemEventsApp = app(id='com.apple.systemevents') try: if ifSizeMatches: size = tuple(systemEventsApp.processes[appName].windows[windowName].size()) ifSizeMatches = tuple(ifSizeMatches) if size != ifSizeMatches: print "Window size didn't match: %s in %s" % (windowName, appName) print "- Wanted %s, got %s" % (ifSizeMatches, size) return False systemEventsApp.processes[appName].windows[windowName].position.set(position) except CommandError: print "CommandError: %s in %s" % (windowName, appName) return False return True def terminalDo(command): # XXX if this launches Terminal, it inherits our PYTHONPATH terminalApp = app(id='com.apple.Terminal') # XXX this does not create a new Terminal window; fix terminalApp.do_script(command + '; exit') _auth = None def authorizationDo(command, *args): global _auth if not _auth: _auth = Authorization(destroyflags=(kAuthorizationFlagDestroyRights,)) return _auth.executeWithPrivileges(command, *args) def stopVPNC(): # killall uses your uid, not your euid to determine which user's # processes to kill; without '-u root', this fails authorizationDo('/usr/bin/killall', '-u', 'root', 'vpnc') def startVPNC(vpncProfile=None): stopVPNC() args = ['--kernel-ipsec'] if vpncProfile: args.append('/etc/vpnc/%s.conf' % vpncProfile) # XXX get password from keychain, then use: # authorizationDo('/usr/local/sbin/vpnc', *args) terminalDo('sudo /usr/local/sbin/vpnc %s' % ' '.join(args))