void QMacSettingsPrivate::sync() { for (int i = 0; i < numDomains; ++i) { for (int j = 0; j < numHostNames; ++j) { Boolean ok = CFPreferencesSynchronize(domains[i].applicationOrSuiteId, domains[i].userName, hostNames[j]); // only report failures for the primary file (the one we write to) if (!ok && i == 0 && hostNames[j] == hostName && status == QSettings::NoError) { #if 1 // work around what seems to be a bug in CFPreferences: // don't report an error if there are no preferences for the application QCFType<CFArrayRef> appIds = CFPreferencesCopyApplicationList(domains[i].userName, hostNames[j]); // iterate through all the applications and see if we're there CFIndex size = CFArrayGetCount(appIds); for (CFIndex k = 0; k < size; ++k) { const void *cfvalue = CFArrayGetValueAtIndex(appIds, k); if (CFGetTypeID(cfvalue) == CFStringGetTypeID()) { if (CFStringCompare(static_cast<CFStringRef>(cfvalue), domains[i].applicationOrSuiteId, kCFCompareCaseInsensitive) == kCFCompareEqualTo) { setStatus(QSettings::AccessError); break; } } } #else setStatus(QSettings::AccessError); #endif } } } }
QueryData genOSXDefaultPreferences(QueryContext& context) { QueryData results; CFStringRef username = nullptr; if (context.constraints["username"].exists(EQUALS)) { auto users = context.constraints["username"].getAll(EQUALS); username = CFStringCreateWithCString( kCFAllocatorDefault, (*users.begin()).c_str(), kCFStringEncodingUTF8); } const auto* user = (username != nullptr) ? &username : (isUserAdmin()) ? &kCFPreferencesAnyUser : &kCFPreferencesCurrentUser; // Need lambda to iterate the map. auto preferencesIterator = ([&results, &username](CFMutableArrayRef& am, bool current_host) { for (CFIndex i = 0; i < CFArrayGetCount(am); ++i) { auto domain = static_cast<CFStringRef>(CFArrayGetValueAtIndex(am, i)); genOSXDomainPrefs(username, domain, current_host, results); } }); CFMutableArrayRef app_map = nullptr; if (context.constraints["domain"].exists(EQUALS)) { // If a specific domain is requested, speed up the set of type conversions. auto domains = context.constraints["domain"].getAll(EQUALS); app_map = CFArrayCreateMutable( kCFAllocatorDefault, domains.size(), &kCFTypeArrayCallBacks); for (const auto& domain : domains) { auto cf_domain = CFStringCreateWithCString( kCFAllocatorDefault, domain.c_str(), kCFStringEncodingASCII); CFArrayAppendValue(app_map, cf_domain); CFRelease(cf_domain); } // Iterate over each preference domain (applicationID). preferencesIterator(app_map, true); preferencesIterator(app_map, false); CFRelease(app_map); } else { // Listing ALL application preferences is deprecated. OSQUERY_USE_DEPRECATED( app_map = (CFMutableArrayRef)CFPreferencesCopyApplicationList( *user, kCFPreferencesCurrentHost)); if (app_map != nullptr) { // Iterate over each preference domain (applicationID). preferencesIterator(app_map, true); CFRelease(app_map); } // Again for 'any' host. OSQUERY_USE_DEPRECATED( app_map = (CFMutableArrayRef)CFPreferencesCopyApplicationList( *user, kCFPreferencesAnyHost)); if (app_map != nullptr) { // Iterate over each preference domain (applicationID). preferencesIterator(app_map, false); CFRelease(app_map); } } if (username != nullptr) { CFRelease(username); } return results; }