static CFURLRef _CFPreferencesURLForStandardDomainWithSafetyLevel(CFStringRef domainName, CFStringRef userName, CFStringRef hostName, unsigned long safeLevel) { CFURLRef theURL = NULL; CFAllocatorRef prefAlloc = __CFPreferencesAllocator(); #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD CFURLRef prefDir = _preferencesDirectoryForUserHostSafetyLevel(userName, hostName, safeLevel); CFStringRef appName; CFStringRef fileName; Boolean mustFreeAppName = false; if (!prefDir) return NULL; if (domainName == kCFPreferencesAnyApplication) { appName = CFSTR(".GlobalPreferences"); } else if (domainName == kCFPreferencesCurrentApplication) { CFBundleRef mainBundle = CFBundleGetMainBundle(); appName = mainBundle ? CFBundleGetIdentifier(mainBundle) : NULL; if (!appName || CFStringGetLength(appName) == 0) { appName = _CFProcessNameString(); } } else { appName = domainName; } if (userName != kCFPreferencesAnyUser) { if (hostName == kCFPreferencesAnyHost) { fileName = CFStringCreateWithFormat(prefAlloc, NULL, CFSTR("%@.plist"), appName); } else if (hostName == kCFPreferencesCurrentHost) { CFStringRef hostID = _CFPreferencesGetByHostIdentifierString(); fileName = CFStringCreateWithFormat(prefAlloc, NULL, CFSTR("%@.%@.plist"), appName, hostID); } else { fileName = CFStringCreateWithFormat(prefAlloc, NULL, CFSTR("%@.%@.plist"), appName, hostName); // sketchy - this allows someone to set an arbitrary hostname. } } else { fileName = CFStringCreateWithFormat(prefAlloc, NULL, CFSTR("%@.plist"), appName); } if (mustFreeAppName) { CFRelease(appName); } if (fileName) { #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD theURL = CFURLCreateWithFileSystemPathRelativeToBase(prefAlloc, fileName, kCFURLPOSIXPathStyle, false, prefDir); #elif DEPLOYMENT_TARGET_WINDOWS theURL = CFURLCreateWithFileSystemPathRelativeToBase(prefAlloc, fileName, kCFURLWindowsPathStyle, false, prefDir); #endif if (prefDir) CFRelease(prefDir); CFRelease(fileName); } #else //#error Do not know where to store NSUserDefaults on this platform #endif return theURL; }
__private_extern__ CFArrayRef _CFPreferencesCreateDomainList(CFStringRef userName, CFStringRef hostName) { CFAllocatorRef prefAlloc = __CFPreferencesAllocator(); CFArrayRef domains; CFMutableArrayRef marray; CFStringRef *cachedDomainKeys; CFPreferencesDomainRef *cachedDomains; SInt32 idx, cnt; CFStringRef suffix; UInt32 suffixLen; CFURLRef prefDir = _preferencesDirectoryForUserHost(userName, hostName); if (!prefDir) { return NULL; } if (hostName == kCFPreferencesAnyHost) { suffix = CFStringCreateWithCString(prefAlloc, ".plist", kCFStringEncodingASCII); } else if (hostName == kCFPreferencesCurrentHost) { CFStringRef hostID = _CFPreferencesGetByHostIdentifierString(); suffix = CFStringCreateWithFormat(prefAlloc, NULL, CFSTR(".%@.plist"), hostID); } else { suffix = CFStringCreateWithFormat(prefAlloc, NULL, CFSTR(".%@.plist"), hostName); // sketchy - this allows someone to create a domain list for an arbitrary hostname. } suffixLen = CFStringGetLength(suffix); domains = (CFArrayRef)CFURLCreatePropertyFromResource(prefAlloc, prefDir, kCFURLFileDirectoryContents, NULL); CFRelease(prefDir); if (domains){ marray = CFArrayCreateMutableCopy(prefAlloc, 0, domains); CFRelease(domains); } else { marray = CFArrayCreateMutable(prefAlloc, 0, & kCFTypeArrayCallBacks); } for (idx = CFArrayGetCount(marray)-1; idx >= 0; idx --) { CFURLRef url = (CFURLRef)CFArrayGetValueAtIndex(marray, idx); CFStringRef string = CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle); if (!CFStringHasSuffix(string, suffix)) { CFArrayRemoveValueAtIndex(marray, idx); } else { CFStringRef dom = CFStringCreateWithSubstring(prefAlloc, string, CFRangeMake(0, CFStringGetLength(string) - suffixLen)); if (CFEqual(dom, CFSTR(".GlobalPreferences"))) { CFArraySetValueAtIndex(marray, idx, kCFPreferencesAnyApplication); } else { CFArraySetValueAtIndex(marray, idx, dom); } CFRelease(dom); } CFRelease(string); } CFRelease(suffix); // Now add any domains added in the cache; delete any that have been deleted in the cache __CFSpinLock(&domainCacheLock); if (!domainCache) { __CFSpinUnlock(&domainCacheLock); return marray; } cnt = CFDictionaryGetCount(domainCache); cachedDomainKeys = (CFStringRef *)CFAllocatorAllocate(prefAlloc, 2 * cnt * sizeof(CFStringRef), 0); cachedDomains = (CFPreferencesDomainRef *)(cachedDomainKeys + cnt); CFDictionaryGetKeysAndValues(domainCache, (const void **)cachedDomainKeys, (const void **)cachedDomains); __CFSpinUnlock(&domainCacheLock); suffix = _CFPreferencesCachePrefixForUserHost(userName, hostName); suffixLen = CFStringGetLength(suffix); for (idx = 0; idx < cnt; idx ++) { CFStringRef domainKey = cachedDomainKeys[idx]; CFPreferencesDomainRef domain = cachedDomains[idx]; CFStringRef domainName; CFIndex keyCount = 0; if (!CFStringHasPrefix(domainKey, suffix)) continue; domainName = CFStringCreateWithSubstring(prefAlloc, domainKey, CFRangeMake(suffixLen, CFStringGetLength(domainKey) - suffixLen)); if (CFEqual(domainName, CFSTR("*"))) { CFRelease(domainName); domainName = (CFStringRef)CFRetain(kCFPreferencesAnyApplication); } else if (CFEqual(domainName, kCFPreferencesCurrentApplication)) { CFRelease(domainName); domainName = (CFStringRef)CFRetain(_CFProcessNameString()); } CFDictionaryRef d = _CFPreferencesDomainDeepCopyDictionary(domain); keyCount = d ? CFDictionaryGetCount(d) : 0; if (keyCount) CFRelease(d); if (keyCount == 0) { // Domain was deleted SInt32 firstIndexOfValue = CFArrayGetFirstIndexOfValue(marray, CFRangeMake(0, CFArrayGetCount(marray)), domainName); if (0 <= firstIndexOfValue) { CFArrayRemoveValueAtIndex(marray, firstIndexOfValue); } } else if (!CFArrayContainsValue(marray, CFRangeMake(0, CFArrayGetCount(marray)), domainName)) { CFArrayAppendValue(marray, domainName); } CFRelease(domainName); } CFRelease(suffix); CFAllocatorDeallocate(prefAlloc, cachedDomainKeys); return marray; }
static SInt32 _CFUserNotificationSendRequest(CFAllocatorRef allocator, CFStringRef sessionID, mach_port_t replyPort, SInt32 token, CFTimeInterval timeout, CFOptionFlags flags, CFDictionaryRef dictionary) { CFDictionaryRef modifiedDictionary = NULL; SInt32 retval = ERR_SUCCESS, itimeout = (timeout > 0.0 && timeout < INT_MAX) ? (SInt32)timeout : 0; CFDataRef data; mach_msg_base_t *msg = NULL; mach_port_t bootstrapPort = MACH_PORT_NULL, serverPort = MACH_PORT_NULL; CFIndex size; char namebuffer[MAX_PORT_NAME_LENGTH + 1]; strlcpy(namebuffer, NOTIFICATION_PORT_NAME, sizeof(namebuffer)); if (sessionID) { char sessionid[MAX_PORT_NAME_LENGTH + 1]; CFIndex len = MAX_PORT_NAME_LENGTH - sizeof(NOTIFICATION_PORT_NAME) - sizeof(NOTIFICATION_PORT_NAME_SUFFIX); CFStringGetBytes(sessionID, CFRangeMake(0, CFStringGetLength(sessionID)), kCFStringEncodingUTF8, 0, false, (uint8_t *)sessionid, len, &size); sessionid[len - 1] = '\0'; strlcat(namebuffer, NOTIFICATION_PORT_NAME_SUFFIX, sizeof(namebuffer)); strlcat(namebuffer, sessionid, sizeof(namebuffer)); } retval = task_get_bootstrap_port(mach_task_self(), &bootstrapPort); if (ERR_SUCCESS == retval && MACH_PORT_NULL != bootstrapPort) retval = bootstrap_look_up2(bootstrapPort, namebuffer, &serverPort, 0, 0); if (ERR_SUCCESS == retval && MACH_PORT_NULL != serverPort) { modifiedDictionary = _CFUserNotificationModifiedDictionary(allocator, dictionary, token, itimeout, _CFProcessNameString()); if (modifiedDictionary) { data = CFPropertyListCreateXMLData(allocator, modifiedDictionary); if (data) { size = sizeof(mach_msg_base_t) + ((CFDataGetLength(data) + 3) & (~0x3)); msg = (mach_msg_base_t *)CFAllocatorAllocate(kCFAllocatorSystemDefault, size, 0); if (__CFOASafe) __CFSetLastAllocationEventName(msg, "CFUserNotification (temp)"); if (msg) { memset(msg, 0, size); msg->header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND_ONCE); msg->header.msgh_size = size; msg->header.msgh_remote_port = serverPort; msg->header.msgh_local_port = replyPort; msg->header.msgh_id = flags; msg->body.msgh_descriptor_count = 0; CFDataGetBytes(data, CFRangeMake(0, CFDataGetLength(data)), (uint8_t *)msg + sizeof(mach_msg_base_t)); //CFShow(CFStringCreateWithBytes(kCFAllocatorSystemDefault, (UInt8 *)msg + sizeof(mach_msg_base_t), CFDataGetLength(data), kCFStringEncodingUTF8, false)); retval = mach_msg((mach_msg_header_t *)msg, MACH_SEND_MSG|MACH_SEND_TIMEOUT, size, 0, MACH_PORT_NULL, MESSAGE_TIMEOUT, MACH_PORT_NULL); CFAllocatorDeallocate(kCFAllocatorSystemDefault, msg); } else { retval = unix_err(ENOMEM); } CFRelease(data); } else { retval = unix_err(ENOMEM); } CFRelease(modifiedDictionary); } else { retval = unix_err(ENOMEM); } } return retval; }