def disable_fde_autologin(): '''Disables autologin to the unlocking user's account on a FileVault- encrypted machines.''' # See https://support.apple.com/en-us/HT202842 # We attempt to store the original value of com.apple.loginwindow # DisableFDEAutoLogin so if the local admin has set it to True for #reasons # we don't inadvertently clear it when clearing bootstrap mode # is OriginalDisableFDEAutoLogin already set? If so, bootstrap mode was # already enabled, and never properly cleared. Don't stomp on it. original_value = CFPreferencesCopyValue('OriginalDisableFDEAutoLogin', 'com.apple.loginwindow', kCFPreferencesAnyUser, kCFPreferencesCurrentHost) if not original_value: # get the current value of DisableFDEAutoLogin if any original_value = CFPreferencesCopyValue('DisableFDEAutoLogin', 'com.apple.loginwindow', kCFPreferencesAnyUser, kCFPreferencesCurrentHost) if not original_value: # we need a way to record the original value was not set, # and we can't store None... original_value = '<not set>' # store it so we can restore it later CFPreferencesSetValue('OriginalDisableFDEAutoLogin', original_value, 'com.apple.loginwindow', kCFPreferencesAnyUser, kCFPreferencesCurrentHost) # set com.apple.loginwindow DisableFDEAutoLogin to True CFPreferencesSetValue('DisableFDEAutoLogin', True, 'com.apple.loginwindow', kCFPreferencesAnyUser, kCFPreferencesCurrentHost) CFPreferencesAppSynchronize('com.apple.loginwindow')
def set_pref(pref_name, pref_value): """Sets a preference, See prefs.py for details""" CFPreferencesSetValue(pref_name, pref_value, BUNDLE_ID, kCFPreferencesAnyUser, kCFPreferencesCurrentHost) CFPreferencesAppSynchronize(BUNDLE_ID) print "set pref" try: CFPreferencesSetValue(pref_name, pref_value, BUNDLE_ID, kCFPreferencesAnyUser, kCFPreferencesCurrentHost) CFPreferencesAppSynchronize(BUNDLE_ID) except Exception: pass
def setupSoftwareUpdateCheck(): '''Set defaults for root user and current host. Needed for Leopard.''' CFPreferencesSetValue('AgreedToLicenseAgreement', True, 'com.apple.SoftwareUpdate', kCFPreferencesCurrentUser, kCFPreferencesCurrentHost) CFPreferencesSetValue('AutomaticDownload', True, 'com.apple.SoftwareUpdate', kCFPreferencesCurrentUser, kCFPreferencesCurrentHost) CFPreferencesSetValue('LaunchAppInBackground', True, 'com.apple.SoftwareUpdate', kCFPreferencesCurrentUser, kCFPreferencesCurrentHost) if not CFPreferencesAppSynchronize('com.apple.SoftwareUpdate'): munkicommon.display_warning( 'Error setting com.apple.SoftwareUpdate ByHost preferences')
def __setitem__(self, pref_name, pref_value): """Sets a preference. if the user is kCFPreferencesCurrentUser, the preference actually gets written at the 'ByHost' level due to the use of kCFPreferencesCurrentHost""" CFPreferencesSetValue(pref_name, pref_value, self.bundle_id, self.user, kCFPreferencesCurrentHost) CFPreferencesAppSynchronize(self.bundle_id)
class StartOSInstallRunner(object): '''Handles running startosinstall to set up and kick off an upgrade install of macOS''' def __init__(self, installer, finishing_tasks=None, installinfo=None): self.installer = installer self.installinfo = installinfo self.finishing_tasks = finishing_tasks self.dmg_mountpoint = None self.got_sigusr1 = False def sigusr1_handler(self, dummy_signum, dummy_frame): '''Signal handler for SIGUSR1 from startosinstall, which tells us it's done setting up the macOS install and is ready and waiting to reboot''' display.display_debug1('Got SIGUSR1 from startosinstall') self.got_sigusr1 = True # do cleanup, record-keeping, notifications if self.installinfo and 'postinstall_script' in self.installinfo: # run the postinstall_script dummy_retcode = scriptutils.run_embedded_script( 'postinstall_script', self.installinfo) if self.finishing_tasks: self.finishing_tasks() # set Munki to run at boot after the OS upgrade is complete try: bootstrapping.set_bootstrap_mode() except bootstrapping.SetupError, err: display.display_error( 'Could not set up Munki to run after OS upgrade is complete: ' '%s', err) if pkgutils.hasValidDiskImageExt(self.installer): # remove the diskimage to free up more space for the actual install try: os.unlink(self.installer) except (IOError, OSError): pass # ask authrestartd if we can do an auth restart, or look for a recovery # key (via munkilib.authrestart methods) if (authrestartd.verify_can_attempt_auth_restart() or authrestart.can_attempt_auth_restart()): # # set a secret preference to tell the osinstaller process to exit # instead of restart # this is the equivalent of: # `defaults write /Library/Preferences/.GlobalPreferences # IAQuitInsteadOfReboot -bool YES` # # This preference is referred to in a framework inside the # Install macOS.app: # Contents/Frameworks/OSInstallerSetup.framework/Versions/A/ # Frameworks/OSInstallerSetupInternal.framework/Versions/A/ # OSInstallerSetupInternal # # It might go away in future versions of the macOS installer. # CFPreferencesSetValue('IAQuitInsteadOfReboot', True, '.GlobalPreferences', kCFPreferencesAnyUser, kCFPreferencesCurrentHost) # now tell startosinstall it's OK to proceed subprocess.call(['/usr/bin/killall', '-SIGUSR1', 'startosinstall'])
def main(): # Variables munkiurl = 'https://raw.githubusercontent.com/jamesh37/installapplicationsdemo/master/munki' # noqa backupmanifest = 'production' try: if os.path.isdir('/Library/Managed Installs/icons'): copy_tree('/Library/Managed Installs/icons', '/private/var/munkiicons') except: # noqa pass # Set basic munki preferences CFPreferencesSetValue( 'InstallAppleSoftwareUpdates', True, '/Library/Preferences/ManagedInstalls', kCFPreferencesAnyUser, kCFPreferencesCurrentHost) CFPreferencesSetValue( 'SoftwareRepoURL', munkiurl, '/Library/Preferences/ManagedInstalls', kCFPreferencesAnyUser, kCFPreferencesCurrentHost) CFPreferencesSetValue( 'ClientIdentifier', backupmanifest, '/Library/Preferences/ManagedInstalls', kCFPreferencesAnyUser, kCFPreferencesCurrentHost) # Run Munki with manifest you want to use munkirun('depdemo') # Install downloaded packages munkiinstall() # Revert Munki icons try: if os.path.isdir('/private/var/munkiicons'): copy_tree('/private/var/munkiicons', '/Library/Managed Installs/icons') shutil.rmtree('/private/var/munkiicons') except: # noqa pass CFPreferencesSetValue( 'LastCheckDate', '', '/Library/Preferences/ManagedInstalls', kCFPreferencesAnyUser, kCFPreferencesCurrentHost)
def main(): # Variables munkiurl = 'https://somewhere.tld' backupmanifest = 'somemanifest' try: if os.path.isdir('/Library/Managed Installs/icons'): copy_tree('/Library/Managed Installs/icons', '/private/var/munkiicons') except: # noqa pass # Set basic munki preferences CFPreferencesSetValue( 'InstallAppleSoftwareUpdates', True, '/Library/Preferences/ManagedInstalls', kCFPreferencesAnyUser, kCFPreferencesCurrentHost) CFPreferencesSetValue( 'SoftwareRepoURL', munkurl, '/Library/Preferences/ManagedInstalls', kCFPreferencesAnyUser, kCFPreferencesCurrentHost) CFPreferencesSetValue( 'ClientIdentifier', backupmanifest, '/Library/Preferences/ManagedInstalls', kCFPreferencesAnyUser, kCFPreferencesCurrentHost) # Run Munki with manifest you want to use munkirun('dep') # Install downloaded packages munkiinstall() # Revert Munki icons try: if os.path.isdir('/private/var/munkiicons'): copy_tree('/private/var/munkiicons', '/Library/Managed Installs/icons') shutil.rmtree('/private/var/munkiicons') except: # noqa pass CFPreferencesSetValue( 'LastCheckDate', '', '/Library/Preferences/ManagedInstalls', kCFPreferencesAnyUser, kCFPreferencesCurrentHost)
def set_lockmessage(lockmessage): CFPreferencesSetValue('LoginwindowText', lockmessage, "/Library/Preferences/com.apple.loginwindow", kCFPreferencesAnyUser, kCFPreferencesAnyHost) CFPreferencesSynchronize("/Library/Preferences/com.apple.loginwindow", kCFPreferencesAnyUser, kCFPreferencesAnyHost) logging.info("Set LoginwindowText") return
def set_pref(pref_name, pref_value, bundleid=BUNDLE_ID): """Set a preference, writing it to ~/Library/Preferences/.""" try: CFPreferencesSetValue(pref_name, pref_value, bundleid, kCFPreferencesCurrentUser, kCFPreferencesCurrentHost) CFPreferencesAppSynchronize(BUNDLE_ID) except BaseException: pass
def reset_fde_autologin(): '''Resets the state of com.apple.loginwindow DisableFDEAutoLogin to its value before we set it to True''' # get the previous value of DisableFDEAutoLogin if any original_value = CFPreferencesCopyValue( 'OriginalDisableFDEAutoLogin', 'com.apple.loginwindow', kCFPreferencesAnyUser, kCFPreferencesCurrentHost) if original_value == '<not set>': original_value = None # reset DisableFDEAutoLogin to original value (if original_value is None, # the key gets deleted) CFPreferencesSetValue( 'DisableFDEAutoLogin', original_value, 'com.apple.loginwindow', kCFPreferencesAnyUser, kCFPreferencesCurrentHost) # delete the OriginalDisableFDEAutoLogin key CFPreferencesSetValue( 'OriginalDisableFDEAutoLogin', None, 'com.apple.loginwindow', kCFPreferencesAnyUser, kCFPreferencesCurrentHost) CFPreferencesAppSynchronize('com.apple.loginwindow')
def set_ARD_Field(field, fieldnumber=1): ''' Set's Apple Remote Desktop Fields ''' CFPreferencesSetValue("Text" + fieldnumber, field, "/Library/Preferences/com.apple.RemoteDesktop", kCFPreferencesAnyUser, kCFPreferencesAnyHost) CFPreferencesSynchronize("/Library/Preferences/com.apple.RemoteDesktop", kCFPreferencesAnyUser, kCFPreferencesAnyHost) logging.info("Set ComputerInfo1 Field") return
def setup_authrestart_if_applicable(): '''Sets up the ability to do an authrestart if applicable''' # ask authrestartd if we can do an auth restart, or look for a recovery # key (via munkilib.authrestart methods) if (authrestartd.verify_can_attempt_auth_restart() or authrestart.can_attempt_auth_restart()): display.display_info( 'FileVault is active and we can do an authrestart') #os_version_tuple = osutils.getOsVersion(as_tuple=True) if False: # was: os_version_tuple >= (10, 12): # setup delayed auth restart so that when startosinstall does a # restart, it completes without user credentials display.display_info('Setting up delayed authrestart...') authrestartd.setup_delayed_authrestart() # make sure the special secret InstallAssistant preference is not # set CFPreferencesSetValue('IAQuitInsteadOfReboot', None, '.GlobalPreferences', kCFPreferencesAnyUser, kCFPreferencesCurrentHost) else: # # set an undocumented preference to tell the osinstaller # process to exit instead of restart # this is the equivalent of: # `defaults write /Library/Preferences/.GlobalPreferences # IAQuitInsteadOfReboot -bool YES` # # This preference is referred to in a framework inside the # Install macOS.app: # Contents/Frameworks/OSInstallerSetup.framework/Versions/A/ # Frameworks/OSInstallerSetupInternal.framework/Versions/A/ # OSInstallerSetupInternal # # It might go away in future versions of the macOS installer. # (but it's still there in the macOS 12.0.1 installer!) # display.display_info( 'Configuring startosinstall to quit instead of restart...') CFPreferencesSetValue('IAQuitInsteadOfReboot', True, '.GlobalPreferences', kCFPreferencesAnyUser, kCFPreferencesCurrentHost)
def set_pref(pref_name, pref_value): """Sets a preference, writing it to /Library/Preferences/ManagedInstalls.plist. This should normally be used only for 'bookkeeping' values; values that control the behavior of munki may be overridden elsewhere (by MCX, for example)""" try: CFPreferencesSetValue(pref_name, pref_value, BUNDLE_ID, kCFPreferencesAnyUser, kCFPreferencesCurrentHost) CFPreferencesAppSynchronize(BUNDLE_ID) except BaseException: pass
def main(): '''Main thread''' # pylint: disable=line-too-long munkiurl = 'https://raw.githubusercontent.com/erikng/installapplicationsdemo/main/munki' # pylint: enable=line-too-long backupmanifest = 'production' deplog("Status: Configurating basic Managed Software Center settings...") # Set basic munki preferences CFPreferencesSetValue('InstallAppleSoftwareUpdates', True, '/Library/Preferences/ManagedInstalls', kCFPreferencesAnyUser, kCFPreferencesCurrentHost) CFPreferencesSetValue('SoftwareRepoURL', munkiurl, '/Library/Preferences/ManagedInstalls', kCFPreferencesAnyUser, kCFPreferencesCurrentHost) CFPreferencesSetValue('ClientIdentifier', backupmanifest, '/Library/Preferences/ManagedInstalls', kCFPreferencesAnyUser, kCFPreferencesCurrentHost) CFPreferencesSetValue('FollowHTTPRedirects', 'all', '/Library/Preferences/ManagedInstalls', kCFPreferencesAnyUser, kCFPreferencesCurrentHost) # Run Munki with manifest you want to use deplog( "Command: MainText: The Managed Software Center process may take a few minutes " "to complete. Thanks for being patient!") deplog("Status: Downloading applications from Managed Software Center...") munkirun('depdemo') # Install downloaded packages deplog("Status: Installing applications from Managed Software Center...") munkiinstall() CFPreferencesSetValue('LastCheckDate', '', '/Library/Preferences/ManagedInstalls', kCFPreferencesAnyUser, kCFPreferencesCurrentHost)
def set_pref(pref_name, pref_value): """Sets a Sal preference. The preference file on disk is located at /Library/Preferences/com.github.salopensource.sal.plist. This should normally be used only for 'bookkeeping' values; values that control the behavior of munki may be overridden elsewhere (by MCX, for example) """ try: CFPreferencesSetValue(pref_name, pref_value, BUNDLE_ID, kCFPreferencesAnyUser, kCFPreferencesCurrentHost) CFPreferencesAppSynchronize(BUNDLE_ID) except Exception: pass
def fixSafariSpotlight(): # Safari "Spotlight" respects the system-wide Spotlight privacy settings # EXCEPT when it comes to submitting search metrics to Apple. # # To disable these metrics, we have to disable Safari's *seperate* # "Spotlight Suggestions" setting, in addition to Spotlight's # "Spotlight Suggestions". # # You'll be forgiven if you find this confusing. BUNDLE_ID = "com.apple.Safari" PREF_NAME = "UniversalSearchEnabled" CFPreferencesSetValue(PREF_NAME, False, BUNDLE_ID, kCFPreferencesCurrentUser, kCFPreferencesAnyHost) CFPreferencesSynchronize(BUNDLE_ID, kCFPreferencesCurrentUser, kCFPreferencesAnyHost)
def createmanifest(): ''' Create the manifest using munki enroll php script in repo. ''' progress("") params = {} params["serial"] = get_hardware_serial() params["school"] = manifests[getmanifests()] if n.views['machinename'].stringValue() == "": progress("Machine Name is blank!\nPlease fill it in and try again!") return else: params["displayname"] = n.views['machinename'].stringValue() if n.views['usernamefield'].stringValue() == "": progress("Username field is blank!\nPlease fill it in and try again!") return else: params["user"] = n.views['usernamefield'].stringValue() params["notes"] = getmarketingmodel() overridebutton = n.views['manifestoverridecheckbox'].stringValue() if overridebutton == "0": params["override"] = "false" else: params["override"] = "true" encodedparams = urlencode(params) conn = httplib.HTTPConnection("munki.example.com") conn.request("GET", "/munki-enroll/enroll.php?{}".format(encodedparams)) response = conn.getresponse() data = response.read() if "Override not set" in data: progress("Manfiest not created! If this is a re-imaged machine, "\ "please check override and try again!") return else: CFPreferencesSetValue("ClientIdentifier", None, "/Library/Preferences/ManagedInstalls", kCFPreferencesAnyUser, kCFPreferencesAnyHost) CFPreferencesSynchronize("/Library/Preferences/ManagedInstalls", kCFPreferencesAnyUser, kCFPreferencesAnyHost) progress("Manifest Created!\nRemoved ClientIdentifier from Machine")
def schedule_notification(args): """Schedule a notification to be delivered to users""" # Get the arguments from the system-level preferences (i.e. # /Library/Preferences/com.sheagcraig.yo.plist). This precludes us # from using the _slightly_ shorter CFPreferencesCopyAppValue. notifications = CFPreferencesCopyValue("Notifications", BUNDLE_ID, kCFPreferencesAnyUser, kCFPreferencesAnyHost) # We get an immutable NSCFDictionary back from CFPreferences, so # copy it to a mutable python dict. notifications = dict(notifications) if notifications else {} # Convert args to string representation of a python list for later # reconversion back to python. notifications[repr(args)] = NSDate.alloc().init() CFPreferencesSetValue("Notifications", notifications, BUNDLE_ID, kCFPreferencesAnyUser, kCFPreferencesAnyHost) # Use the simpler `AppSynchroniize`; it seems to flush all changes, # despite having to use the primitive methods above. CFPreferencesAppSynchronize(BUNDLE_ID)
def write_preference(key, value, bundle): """Write a preference key from a preference domain.""" CFPreferencesSetValue(key, value, bundle, kCFPreferencesAnyUser, kCFPreferencesCurrentHost) CFPreferencesAppSynchronize(bundle) return
def start(self): '''Starts a macOS install from an Install macOS.app stored at the root of a disk image, or from a locally installed Install macOS.app. Will always reboot after if the setup is successful. Therefore this must be done at the end of all other actions that Munki performs during a managedsoftwareupdate run.''' if boot_volume_is_cs_converting(): raise StartOSInstallError( 'Skipping macOS upgrade because the boot volume is in the ' 'middle of a CoreStorage conversion.') if self.installinfo and 'preinstall_script' in self.installinfo: # run the preinstall_script retcode = scriptutils.run_embedded_script( 'preinstall_script', self.installinfo) if retcode: # don't install macOS, return failure raise StartOSInstallError( 'Skipping macOS upgrade due to preinstall_script error.') # set up our signal handler signal.signal(signal.SIGUSR1, self.sigusr1_handler) # get our tool paths app_path = self.get_app_path(self.installer) startosinstall_path = os.path.join( app_path, 'Contents/Resources/startosinstall') os_vers_to_install = get_os_version(app_path) # run startosinstall via subprocess # we need to wrap our call to startosinstall with a utility # that makes startosinstall think it is connected to a tty-like # device so its output is unbuffered so we can get progress info # otherwise we get nothing until the process exits. # # Try to find our ptyexec tool # first look in the parent directory of this file's directory # (../) parent_dir = ( os.path.dirname( os.path.dirname( os.path.abspath(__file__)))) ptyexec_path = os.path.join(parent_dir, 'ptyexec') if not os.path.exists(ptyexec_path): # try absolute path in munki's normal install dir ptyexec_path = '/usr/local/munki/ptyexec' if os.path.exists(ptyexec_path): cmd = [ptyexec_path] else: # fall back to /usr/bin/script # this is not preferred because it uses way too much CPU # checking stdin for input that will never come... cmd = ['/usr/bin/script', '-q', '-t', '1', '/dev/null'] cmd.extend([startosinstall_path, '--agreetolicense', '--rebootdelay', '300', '--pidtosignal', str(os.getpid())]) if pkgutils.MunkiLooseVersion( os_vers_to_install) < pkgutils.MunkiLooseVersion('10.14'): # --applicationpath option is _required_ in Sierra and early # releases of High Sierra. It became optional (or is ignored?) in # later releases of High Sierra and causes warnings in Mojave # so don't add this option when installing Mojave cmd.extend(['--applicationpath', app_path]) if pkgutils.MunkiLooseVersion( os_vers_to_install) < pkgutils.MunkiLooseVersion('10.12.4'): # --volume option is _required_ prior to 10.12.4 installer # and must _not_ be included in 10.12.4+ installer's startosinstall cmd.extend(['--volume', '/']) if pkgutils.MunkiLooseVersion( os_vers_to_install) < pkgutils.MunkiLooseVersion('10.13.5'): # --nointeraction is an undocumented option that appears to be # not only no longer needed/useful but seems to trigger some issues # in more recent releases cmd.extend(['--nointeraction']) if (self.installinfo and 'additional_startosinstall_options' in self.installinfo): cmd.extend(self.installinfo['additional_startosinstall_options']) # more magic to get startosinstall to not buffer its output for # percent complete env = {'NSUnbufferedIO': 'YES'} try: job = launchd.Job(cmd, environment_vars=env, cleanup_at_exit=False) job.start() except launchd.LaunchdJobException as err: display.display_error( 'Error with launchd job (%s): %s', cmd, err) display.display_error('Aborting startosinstall run.') raise StartOSInstallError(err) startosinstall_output = [] timeout = 2 * 60 * 60 inactive = 0 while True: if processes.stop_requested(): job.stop() break info_output = job.stdout.readline() if not info_output: if job.returncode() is not None: break else: # no data, but we're still running inactive += 1 if inactive >= timeout: # no output for too long, kill the job display.display_error( "startosinstall timeout after %d seconds" % timeout) job.stop() break # sleep a bit before checking for more output time.sleep(1) continue # we got non-empty output, reset inactive timer inactive = 0 info_output = info_output.decode('UTF-8') # save all startosinstall output in case there is # an error so we can dump it to the log startosinstall_output.append(info_output) # parse output for useful progress info msg = info_output.strip() if msg.startswith('Preparing to '): display.display_status_minor(msg) elif msg.startswith(('Preparing ', 'Preparing: ')): # percent-complete messages percent_str = msg.split()[-1].rstrip('%.') try: percent = int(float(percent_str)) except ValueError: percent = -1 display.display_percent_done(percent, 100) elif msg.startswith(('By using the agreetolicense option', 'If you do not agree,')): # annoying legalese pass elif msg.startswith('Helper tool cr'): # no need to print that stupid message to screen! # 10.12: 'Helper tool creashed' # 10.13: 'Helper tool crashed' munkilog.log(msg) elif msg.startswith( ('Signaling PID:', 'Waiting to reboot', 'Process signaled okay')): # messages around the SIGUSR1 signalling display.display_debug1('startosinstall: %s', msg) elif msg.startswith('System going down for install'): display.display_status_minor( 'System will restart and begin upgrade of macOS.') else: # none of the above, just display display.display_status_minor(msg) # startosinstall exited munkistatus.percent(100) retcode = job.returncode() # previously we unmounted the disk image, but since we're going to # restart very very soon, don't bother #if self.dmg_mountpoint: # dmgutils.unmountdmg(self.dmg_mountpoint) if retcode and not (retcode == 255 and self.got_sigusr1): # append stderr to our startosinstall_output if job.stderr: startosinstall_output.extend(job.stderr.read().splitlines()) display.display_status_minor( "Starting macOS install failed with return code %s" % retcode) display.display_error("-"*78) for line in startosinstall_output: display.display_error(line.rstrip("\n")) display.display_error("-"*78) raise StartOSInstallError( 'startosinstall failed with return code %s' % retcode) elif self.got_sigusr1: # startosinstall got far enough along to signal us it was ready # to finish and reboot, so we can believe it was successful munkilog.log('macOS install successfully set up.') munkilog.log( 'Starting macOS install of %s: SUCCESSFUL' % os_vers_to_install, 'Install.log') # previously we checked if retcode == 255: # that may have been something specific to 10.12's startosinstall # if startosinstall exited after sending us sigusr1 we should # handle the restart. if retcode not in (0, 255): # some logging for possible investigation in the future munkilog.log('startosinstall exited %s' % retcode) munkilog.log('startosinstall quit instead of rebooted; we will ' 'do restart.') # clear our special secret InstallAssistant preference CFPreferencesSetValue( 'IAQuitInsteadOfReboot', None, '.GlobalPreferences', kCFPreferencesAnyUser, kCFPreferencesCurrentHost) # attempt to do an auth restart, or regular restart, or shutdown if not authrestartd.restart(): authrestart.do_authorized_or_normal_restart( shutdown=osutils.bridgeos_update_staged()) else: raise StartOSInstallError( 'startosinstall did not complete successfully. ' 'See /var/log/install.log for details.')
def write_key(key, value): """Writes the given value to the given key""" CFPreferencesSetValue(key, value, kCFPreferencesAnyApplication, kCFPreferencesCurrentUser, kCFPreferencesAnyHost)
def fixSpotlight(): DISABLED_ITEMS = set(["MENU_WEBSEARCH", "MENU_SPOTLIGHT_SUGGESTIONS"]) REQUIRED_ITEM_KEYS = set(["enabled", "name"]) BUNDLE_ID = "com.apple.Spotlight" PREF_NAME = "orderedItems" DEFAULT_VALUE = [{ 'enabled': True, 'name': 'APPLICATIONS' }, { 'enabled': False, 'name': 'MENU_SPOTLIGHT_SUGGESTIONS' }, { 'enabled': True, 'name': 'MENU_CONVERSION' }, { 'enabled': True, 'name': 'MENU_EXPRESSION' }, { 'enabled': True, 'name': 'MENU_DEFINITION' }, { 'enabled': True, 'name': 'SYSTEM_PREFS' }, { 'enabled': True, 'name': 'DOCUMENTS' }, { 'enabled': True, 'name': 'DIRECTORIES' }, { 'enabled': True, 'name': 'PRESENTATIONS' }, { 'enabled': True, 'name': 'SPREADSHEETS' }, { 'enabled': True, 'name': 'PDF' }, { 'enabled': True, 'name': 'MESSAGES' }, { 'enabled': True, 'name': 'CONTACT' }, { 'enabled': True, 'name': 'EVENT_TODO' }, { 'enabled': True, 'name': 'IMAGES' }, { 'enabled': True, 'name': 'BOOKMARKS' }, { 'enabled': True, 'name': 'MUSIC' }, { 'enabled': True, 'name': 'MOVIES' }, { 'enabled': True, 'name': 'FONTS' }, { 'enabled': True, 'name': 'MENU_OTHER' }, { 'enabled': False, 'name': 'MENU_WEBSEARCH' }] items = CFPreferencesCopyValue(PREF_NAME, BUNDLE_ID, kCFPreferencesCurrentUser, kCFPreferencesAnyHost) newItems = None if items is None or len(items) is 0: # Actual preference values are populated on demand; if the user # hasn't previously configured Spotlight, the preference value # will be unavailable newItems = DEFAULT_VALUE else: newItems = NSMutableArray.new() for item in items: missing_keys = [] for key in REQUIRED_ITEM_KEYS: if not item.has_key(key): missing_keys.append(key) if len(missing_keys) != 0: print "Preference item %s is missing expected keys (%s), skipping" % ( item, missing_keys) newItems.append(item) continue if item["name"] not in DISABLED_ITEMS: newItems.append(item) continue newItem = NSMutableDictionary.dictionaryWithDictionary_(item) newItem.setObject_forKey_(0, "enabled") newItems.append(newItem) CFPreferencesSetValue(PREF_NAME, newItems, BUNDLE_ID, kCFPreferencesCurrentUser, kCFPreferencesAnyHost) CFPreferencesSynchronize(BUNDLE_ID, kCFPreferencesCurrentUser, kCFPreferencesAnyHost)
def clear_scheduled_notifications(): """Clear all scheduled notifications""" CFPreferencesSetValue( "Notifications", {}, BUNDLE_ID, kCFPreferencesAnyUser, kCFPreferencesAnyHost) CFPreferencesAppSynchronize(BUNDLE_ID)
def __setitem__(self, pref_name, pref_value): CFPreferencesSetValue(pref_name, pref_value, self.bundle_id, self.user, kCFPreferencesCurrentHost) CFPreferencesAppSynchronize(self.bundle_id)
def delete_key(key): """Deletes the given key""" CFPreferencesSetValue(key, None, kCFPreferencesAnyApplication, kCFPreferencesCurrentUser, kCFPreferencesAnyHost)