예제 #1
0
/*
    CFJSObjectSetProperty
*/
void CFJSObjectSetProperty(void *data, CFStringRef propertyName, JSObjectRef jsValue)
{
    if (data && propertyName)
    {
        CFTypeRef cfValue = JSObjectCopyCFValue(jsValue);

        if (cfValue)
        {
            if (CFGetTypeID(data) == CFDictionaryGetTypeID())
            {
                CFDictionarySetValue((CFMutableDictionaryRef)data, propertyName, cfValue);
            }
            else if (CFGetTypeID(data) == CFArrayGetTypeID())
            {
                SInt32 index = CFStringGetIntValue(propertyName);
                CFIndex arrayCount = CFArrayGetCount((CFArrayRef)data);
                if (index >= 0)
                {
                    for (; arrayCount < index; arrayCount++)
                    {
                        CFArrayAppendValue((CFMutableArrayRef)data, GetCFNull());
                    }
                    CFArraySetValueAtIndex((CFMutableArrayRef)data, index, cfValue);
                }
            }
            CFRelease(cfValue);
        }
        else
        {
            if (CFGetTypeID(data) == CFDictionaryGetTypeID())
            {
                CFDictionaryRemoveValue((CFMutableDictionaryRef)data, propertyName);
            }
            else if (CFGetTypeID(data) == CFArrayGetTypeID())
            {
                SInt32 index = CFStringGetIntValue(propertyName);
                CFIndex arrayCount = CFArrayGetCount((CFArrayRef)data);
                if (index >= 0)
                {
                    for (; arrayCount < index; arrayCount++)
                    {
                        CFArrayAppendValue((CFMutableArrayRef)data, GetCFNull());
                    }
                    CFArraySetValueAtIndex((CFMutableArrayRef)data, index, GetCFNull());
                }
            }
        }
    }
}
예제 #2
0
파일: plist.c 프로젝트: aburgh/usbmuxd
/**
 * Set the nth item in a #PLIST_ARRAY node.
 * The previous item at index n will be freed using #plist_free
 *
 * @param node the node of type #PLIST_ARRAY
 * @param item the new item at index n
 * @param n the index of the item to get. Range is [0, array_size[. Assert if n is not in range.
 */
void plist_array_set_item(plist_t node, plist_t item, uint32_t n)
{
	assert(CFGetTypeID(node) == CFArrayGetTypeID());

	CFArraySetValueAtIndex((CFMutableArrayRef) node, n, item);
	CFRelease(item);
}
예제 #3
0
파일: rd_prefs.c 프로젝트: kjk/roaringdiff
static void
_rd_prefs_save_recent_files(rd_recent_file_t *r, int num_files, CFStringRef app)
{
    assert(r != NULL);
    assert(app != NULL);

    CFMutableArrayRef the_array = CFArrayCreateMutable(NULL, num_files, &kCFTypeArrayCallBacks);
    assert(the_array != NULL);
    
    int i;
    
    for (i = 0; i < num_files; i++) {
        rd_recent_file_t *f = &r[i];
        if (f->path[0] == '\0') {
            continue;
        }

        CFMutableDictionaryRef f_dict = CFDictionaryCreateMutable(NULL, 2, NULL, NULL);
        assert(f_dict != NULL);

        CFStringRef f_name = CFStringCreateWithCString(NULL, f->path, kCFStringEncodingUTF8);
        assert(f_name != NULL);

        CFNumberRef f_atime = CFNumberCreate(NULL, kCFNumberLongType, &f->last_atime);
        assert(f_atime != NULL);
        
        CFDictionaryAddValue(f_dict, CFSTR("name"),  f_name);
        CFDictionaryAddValue(f_dict, CFSTR("atime"), f_atime);
        
        CFArraySetValueAtIndex(the_array, (CFIndex) i, f_dict);
    }
    
    CFPreferencesSetAppValue(CFSTR("recent_files"), the_array, app);
    CFRelease(the_array);
}
예제 #4
0
/**
 * Converts a Python string list to a :class:`CFMutableArray` of UTF-8 encoded
 * :class:`CFString` and returns a pointer to the array.
 *
 * :param py_string_list:
 *     Python list of Python strings.
 * :type py_string_list:
 *     Pointer to a Python object.
 * :returns:
 *     A :class:`CFMutableArrayRef` (pointer to a mutable array) of
 *     UTF-8-encoded :class:`CFString` instances.
 */
static CFMutableArrayRef
Watchdog_CFMutableArray_From_PyStringList(PyObject *py_string_list)
{
    CFMutableArrayRef array_of_cf_string = NULL;
    CFStringRef cf_string = NULL;
    PyObject *py_string = NULL;
    const char *c_string = NULL;
    Py_ssize_t i = 0;
    Py_ssize_t string_list_size = 0;

    RETURN_NULL_IF_NULL(py_string_list);
    string_list_size = PyList_Size(py_string_list);

    /* Allocate a CFMutableArray */
    array_of_cf_string = CFArrayCreateMutable(kCFAllocatorDefault,
                                              1,
                                              &kCFTypeArrayCallBacks);
    RETURN_NULL_IF_NULL(array_of_cf_string);

    /* Loop through the Python string list and copy strings to the
     * CFString array list. */
    for (i = 0; i < string_list_size; ++i)
        {
            py_string = PyList_GetItem(py_string_list, i);
            c_string = PyString_AS_STRING(py_string);
            cf_string = CFStringCreateWithCString(kCFAllocatorDefault,
                                                  c_string,
                                                  kCFStringEncodingUTF8);
            CFArraySetValueAtIndex(array_of_cf_string, i, cf_string);
            CFRelease(cf_string);
        }

    return array_of_cf_string;
}
예제 #5
0
static void insert_sort_button(int header, IOHIDElementRef tIOHIDElementRef,
                               CFMutableArrayRef elementCFArrayRef, int index,
                               int target)
{
    IOHIDElementRef targetElement;
    int usage;

    CFArraySetValueAtIndex(elementCFArrayRef, header+index, NULL);
    targetElement = ( IOHIDElementRef ) CFArrayGetValueAtIndex( elementCFArrayRef, header+target);
    if (targetElement == NULL)
    {
        CFArraySetValueAtIndex(elementCFArrayRef, header+target,tIOHIDElementRef);
        return;
    }
    usage = IOHIDElementGetUsage( targetElement );
    usage --; /* usage 1 based index */

    insert_sort_button(header, targetElement, elementCFArrayRef, target, usage);
    CFArraySetValueAtIndex(elementCFArrayRef, header+target,tIOHIDElementRef);
}
예제 #6
0
파일: eyed.c 프로젝트: rsms/eye
static FSEventStreamRef my_FSEventStreamCreate(const char **paths, size_t num_paths)
{
  void         *user_data = (void *)(num_paths ? paths[0] : "?");
  FSEventStreamContext  context = {0, user_data, NULL, NULL, NULL};
  FSEventStreamRef    streamRef = NULL;
  CFMutableArrayRef   cfArray;
  
  // Settings
  FSEventStreamEventId sinceWhen = kFSEventStreamEventIdSinceNow;
  int                  flags = 0;
  CFAbsoluteTime       latency = 5.0; // How long it takes from that something 
                                      // happened to an event is dispatched.
  
  // Used as buffer for absolutize_path
  char abspath[PATH_MAX];
  
  // Create paths array
  cfArray = CFArrayCreateMutable(kCFAllocatorDefault, 1, &kCFTypeArrayCallBacks);
  if (NULL == cfArray) {
    log_error("CFArrayCreateMutable() => NULL");
    goto Return;
  }
  
  // Add paths to array
  for(int i=0; i<num_paths; i++) {
    absolutize_path(paths[i], abspath);
    CFStringRef cfStr = CFStringCreateWithCString(kCFAllocatorDefault, abspath, kCFStringEncodingUTF8);
    if (NULL == cfStr) {
      CFRelease(cfArray);
      goto Return;
    }
    CFArraySetValueAtIndex(cfArray, i, cfStr);
    CFRelease(cfStr);
  }
  
  // Create the stream
  streamRef = FSEventStreamCreate(kCFAllocatorDefault,
                  (FSEventStreamCallback)&fsevents_callback,
                  &context,
                  cfArray,
                  /*settings->*/sinceWhen,
                  /*settings->*/latency,
                  /*settings->*/flags);
  
  // Check if FSEventStreamCreate failed
  if (NULL == streamRef) {
    log_error("FSEventStreamCreate() failed");
    goto Return;
  }
  
  // Print the setup
  IFDEBUG(
    FSEventStreamShow(streamRef);
  )
예제 #7
0
bool	CACFArray::SetCFType(UInt32 inIndex, const CFTypeRef inItem)
{
	bool theAnswer = false;
	
	if((mCFArray != NULL) && mMutable && (inIndex <= GetNumberItems()))
	{
		CFArraySetValueAtIndex(mCFArray, inIndex, inItem);
		theAnswer = true;
	}
	
	return theAnswer;
}
예제 #8
0
// Return the constructed certificate chain for this trust reference,
// making output certificates pointer-equivalent to any provided input
// certificates (where possible) for legacy behavioral compatibility.
// Caller must release this array.
//
CFArrayRef SecTrustCopyConstructedChain(SecTrustRef trust)
{
	CFMutableArrayRef certChain = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
	CFIndex idx, count = SecTrustGetCertificateCount(trust);
	for (idx=0; idx < count; idx++) {
		SecCertificateRef certificate = SecTrustGetCertificateAtIndex(trust, idx);
		if (certificate) {
			CFArrayAppendValue(certChain, certificate);
		}
	}
	// <rdar://24393060>
	// Some callers make the assumption that the certificates in
	// this chain are pointer-equivalent to ones they passed to the
	// SecTrustCreateWithCertificates function. We'll maintain that
	// behavior here for compatibility.
	//
	CFArrayRef inputCertArray = SecTrustCopyInputCertificates(trust);
	CFArrayRef inputAnchorArray = SecTrustCopyInputAnchors(trust);
	CFIndex inputCertIdx, inputCertCount = (inputCertArray) ? CFArrayGetCount(inputCertArray) : 0;
	CFIndex inputAnchorIdx, inputAnchorCount = (inputAnchorArray) ? CFArrayGetCount(inputAnchorArray) : 0;
	for (idx=0; idx < count; idx++) {
		SecCertificateRef tmpCert = (SecCertificateRef) CFArrayGetValueAtIndex(certChain, idx);
		if (tmpCert) {
			SecCertificateRef matchCert = NULL;
			for (inputCertIdx=0; inputCertIdx < inputCertCount && !matchCert; inputCertIdx++) {
				SecCertificateRef inputCert = (SecCertificateRef) CFArrayGetValueAtIndex(inputCertArray, inputCertIdx);
				if (inputCert && CFEqual(inputCert, tmpCert)) {
					matchCert = inputCert;
				}
			}
			for (inputAnchorIdx=0; inputAnchorIdx < inputAnchorCount && !matchCert; inputAnchorIdx++) {
				SecCertificateRef inputAnchor = (SecCertificateRef) CFArrayGetValueAtIndex(inputAnchorArray, inputAnchorIdx);
				if (inputAnchor && CFEqual(inputAnchor, tmpCert)) {
					matchCert = inputAnchor;
				}
			}
			if (matchCert) {
				CFArraySetValueAtIndex(certChain, idx, matchCert);
			}
		}
	}
	if (inputCertArray) {
		CFRelease(inputCertArray);
	}
	if (inputAnchorArray) {
		CFRelease(inputAnchorArray);
	}
	return certChain;
}
예제 #9
0
static inline int NXEvSetParameterInt(	NXEventHandle handle,
                                CFStringRef parameterName,
                                unsigned int *parameterArray,
                                unsigned int count)
{

    CFMutableArrayRef 	arrayRef;
    CFNumberRef 	numberRef;
    IOReturn		ret = kIOReturnNoMemory;
    unsigned int	i;


    if (!parameterArray || !count)
        return kIOReturnError;

    if (count > 1)
    {
        arrayRef = CFArrayCreateMutable(kCFAllocatorDefault, count, &kCFTypeArrayCallBacks);
        if ( !arrayRef )
            return kIOReturnNoMemory;

        for (i=0; i<count; i++)
        {
            numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &(parameterArray[i]));

            if (numberRef)
            {
                CFArraySetValueAtIndex(arrayRef, i, numberRef);
                CFRelease(numberRef);
            }
        }

        ret = IOHIDSetCFTypeParameter(handle, parameterName, arrayRef);

        CFRelease(arrayRef);
    }
    else
    {
        numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &(parameterArray[0]));

        if (numberRef)
        {
            ret = IOHIDSetCFTypeParameter(handle, parameterName, numberRef);
            CFRelease(numberRef);
        }

    }
    return ret;
}
예제 #10
0
bool
CAuthAuthority::SetDataForTag( const char *inTagStr, const char *inDataSegment, CFIndex inDataSegmentIndex )
{
	CFIndex dataArrayCount = 0;
	CFStringRef dataSegString = NULL;
	CFMutableDictionaryRef aaDict = this->GetValueForTagAsCFDict( inTagStr );
	if ( aaDict == NULL )
		return false;
	
	CFMutableArrayRef dataArray = (CFMutableArrayRef)CFDictionaryGetValue( aaDict, CFSTR("data") );
	if ( dataArray == NULL )
	{
		if ( inDataSegmentIndex != 0 )
			return false;
		
		dataSegString = CFStringCreateWithCString( NULL, inDataSegment, kCFStringEncodingUTF8 );
		dataArray = CFArrayCreateMutable( NULL, 0, &kCFTypeArrayCallBacks );
		CFArrayAppendValue( dataArray, dataSegString );
		CFRelease( dataSegString );
		
		CFDictionaryAddValue( aaDict, CFSTR("data"), dataArray );
		CFRelease( dataArray );
	}
	else
	{
		// Example: inDataSegmentIndex == 0, CFArrayGetCount(dataArray) == 1, then
		// 0 (replace) & 1 (append) are valid positions, 2+ are not.
		if ( inDataSegmentIndex > (dataArrayCount = CFArrayGetCount(dataArray)) )
			return false;
		
		dataSegString = CFStringCreateWithCString( NULL, inDataSegment, kCFStringEncodingUTF8 );
		if ( inDataSegmentIndex == dataArrayCount )
		{
			CFArrayAppendValue( dataArray, dataSegString );
		}
		else
		{
			CFArraySetValueAtIndex( dataArray, inDataSegmentIndex, dataSegString );
		}
		CFRelease( dataSegString );
	}
	
	return true;
}
예제 #11
0
/**
 * Converts a list of Python strings to a ``CFMutableArray`` of
 * UTF-8 encoded ``CFString`` instances and returns a pointer to
 * the array.
 *
 * :param py_string_list:
 *     List of Python strings.
 * :returns:
 *     A pointer to ``CFMutableArray`` (that is, a
 *     ``CFMutableArrayRef``) of UTF-8 encoded ``CFString``
 *     instances.
 */
static CFMutableArrayRef
watchdog_CFMutableArrayRef_from_PyStringList(PyObject *py_string_list)
{
    Py_ssize_t i = 0;
    Py_ssize_t string_list_size = 0;
    const char *c_string = NULL;
    CFMutableArrayRef array_of_cf_string = NULL;
    CFStringRef cf_string = NULL;
    PyObject *py_string = NULL;

    G_RETURN_NULL_IF_NULL(py_string_list);

    string_list_size = PyList_Size(py_string_list);

    /* Allocate a CFMutableArray. */
    array_of_cf_string = CFArrayCreateMutable(kCFAllocatorDefault, 1,
                                              &kCFTypeArrayCallBacks);
    G_RETURN_NULL_IF_NULL(array_of_cf_string);

    /* Loop through the Python string list and copy strings to the
     * CFString array list. */
    for (i = 0; i < string_list_size; ++i)
    {
        py_string = PyList_GetItem(py_string_list, i);
        G_RETURN_NULL_IF_NULL(py_string);
#if PY_MAJOR_VERSION >= 3
        if (PyUnicode_Check(py_string)) {
          c_string = PyUnicode_AsUTF8(py_string);
        } else {
          c_string = PyBytes_AS_STRING(py_string);
        }
#else
        c_string = PyString_AS_STRING(py_string);
#endif
        cf_string = CFStringCreateWithCString(kCFAllocatorDefault,
                                              c_string,
                                              kCFStringEncodingUTF8);
        CFArraySetValueAtIndex(array_of_cf_string, i, cf_string);
        CFRelease(cf_string);
    }

    return array_of_cf_string;
}
예제 #12
0
static int load_cert(URLContext *h)
{
    TLSContext *c = h->priv_data;
    int ret = 0;
    CFArrayRef certArray = NULL;
    CFArrayRef keyArray = NULL;
    SecIdentityRef id = NULL;
    CFMutableArrayRef outArray = NULL;

    if ((ret = import_pem(h, c->tls_shared.cert_file, &certArray)) < 0)
        goto end;

    if ((ret = import_pem(h, c->tls_shared.key_file, &keyArray)) < 0)
        goto end;

    if (!(id = SecIdentityCreate(kCFAllocatorDefault,
                                 (SecCertificateRef)CFArrayGetValueAtIndex(certArray, 0),
                                 (SecKeyRef)CFArrayGetValueAtIndex(keyArray, 0)))) {
        ret = AVERROR_UNKNOWN;
        goto end;
    }

    if (!(outArray = CFArrayCreateMutableCopy(kCFAllocatorDefault, 0, certArray))) {
        ret = AVERROR(ENOMEM);
        goto end;
    }

    CFArraySetValueAtIndex(outArray, 0, id);

    SSLSetCertificate(c->ssl_context, outArray);

end:
    if (certArray)
        CFRelease(certArray);
    if (keyArray)
        CFRelease(keyArray);
    if (outArray)
        CFRelease(outArray);
    if (id)
        CFRelease(id);
    return ret;
}
bool
mongoc_secure_transport_setup_certificate (mongoc_stream_tls_secure_transport_t *secure_transport,
                                           mongoc_ssl_opt_t *opt)
{
   bool success;
   CFArrayRef items;
   SecIdentityRef id;
   SecKeyRef key = NULL;
   SecCertificateRef cert = NULL;
   SecExternalItemType type = kSecItemTypeCertificate;

   if (!opt->pem_file) {
      MONGOC_INFO ("No private key provided, the server won't be able to verify us");
      return false;
   }

   success = _mongoc_secure_transport_import_pem (opt->pem_file, opt->pem_pwd, &items, &type);
   if (!success) {
      MONGOC_ERROR ("Can't find certificate in: '%s'", opt->pem_file);
      return false;
   }

   if (type != kSecItemTypeAggregate) {
      MONGOC_ERROR ("Cannot work with keys of type \"%d\". Please file a JIRA", type);
      CFRelease (items);
      return false;
   }

   for (CFIndex i = 0; i < CFArrayGetCount (items); ++i) {
      CFTypeID item_id = CFGetTypeID (CFArrayGetValueAtIndex (items, i));

      if (item_id == SecCertificateGetTypeID()) {
         cert = (SecCertificateRef) CFArrayGetValueAtIndex (items, i);
      } else if (item_id == SecKeyGetTypeID()) {
         key = (SecKeyRef) CFArrayGetValueAtIndex (items, i);
      }
   }

   if (!cert || !key) {
      MONGOC_ERROR ("Couldn't find valid private key");
      CFRelease (items);
      return false;
   }

   id = SecIdentityCreate (kCFAllocatorDefault, cert, key);
   secure_transport->my_cert = CFArrayCreateMutableCopy(kCFAllocatorDefault, (CFIndex)2, items);

   CFArraySetValueAtIndex(secure_transport->my_cert, 0, id);
   CFArraySetValueAtIndex(secure_transport->my_cert, 1, cert);

   /*
    *  Secure Transport assumes the following:
    *    * The certificate references remain valid for the lifetime of the session.
    *    * The identity specified in certRefs[0] is capable of signing.
    */
   success = !SSLSetCertificate (secure_transport->ssl_ctx_ref, secure_transport->my_cert);
   MONGOC_DEBUG("Setting client certificate %s", success ? "succeeded" : "failed");

   CFRelease (items);
   return true;
}
예제 #14
0
static Boolean
__SCNetworkSetEstablishDefaultConfigurationForInterfaces(SCNetworkSetRef set, CFArrayRef interfaces, Boolean excludeHidden)
{
	CFSetRef		excluded	= NULL;
	CFIndex			i;
	CFIndex			n		= 0;
	Boolean			ok		= TRUE;
	CFArrayRef		services;
	SCNetworkSetPrivateRef	setPrivate	= (SCNetworkSetPrivateRef)set;
	Boolean			updated		= FALSE;
	Boolean			updatedIFs	= FALSE;

#if	TARGET_OS_IPHONE
	CFArrayRef		orphans		= NULL;
	CFArrayRef		sets;

	sets = SCNetworkSetCopyAll(setPrivate->prefs);
	if (sets != NULL) {
		if (CFArrayGetCount(sets) == 1) {
			services = SCNetworkSetCopyServices(set);
			if (services != NULL) {
				n = CFArrayGetCount(services);
				CFRelease(services);
			}

			if ((n == 0) && CFEqual(set, CFArrayGetValueAtIndex(sets, 0))) {
				// after a "Reset Network Settings" we need to find (and
				// add back) any VPN services that were orphaned.
				orphans = SCNetworkServiceCopyAll(setPrivate->prefs);
			}
		}

		CFRelease(sets);
	}
#endif	// TARGET_OS_IPHONE

	// copy network services
	services = copyServices(set);

	// copy network interfaces to be excluded
	excluded = copyExcludedInterfaces(setPrivate->prefs);

#if	!TARGET_OS_IPHONE
	// look for interfaces that should auto-magically be added
	// to an Ethernet bridge
	n = (interfaces != NULL) ? CFArrayGetCount(interfaces) : 0;
	for (i = 0; i < n; i++) {
		SCBridgeInterfaceRef	bridge		= NULL;
		SCNetworkInterfaceRef	interface;

		interface = CFArrayGetValueAtIndex(interfaces, i);

		if (excludeHidden && skipInterface(interface)) {
			// if not auto-configure
			continue;
		}

		if ((excluded != NULL)
		    && CFSetContainsValue(excluded, interface)) {
			// if this interface is a member of a Bond or Bridge
			continue;
		}

		if (__SCNetworkServiceExistsForInterface(services, interface)) {
			// if this is not a new interface
			continue;
		}

		if (_SCNetworkInterfaceIsBuiltin(interface) &&
		    _SCNetworkInterfaceIsThunderbolt(interface) &&
		    !isA_SCBridgeInterface(interface)) {
			// add built-in Thunderbolt interfaces to bridge
			bridge = copyAutoBridgeInterface(setPrivate->prefs, CFSTR("thunderbolt-bridge"));
		}

		if (bridge != NULL) {
			CFIndex			bridgeIndex;
			CFArrayRef		members;
			CFMutableArrayRef	newMembers;
			CFMutableSetRef		newExcluded;
			CFMutableArrayRef	newInterfaces;
			CFArrayRef		newServices;

			// track the bridge interface (if it's in our list)
			bridgeIndex = CFArrayGetFirstIndexOfValue(interfaces,
								  CFRangeMake(0, CFArrayGetCount(interfaces)),
								  bridge);

			// add new member interface
			members = SCBridgeInterfaceGetMemberInterfaces(bridge);
			if ((members != NULL) && (CFArrayGetCount(members) > 0)) {
				newMembers = CFArrayCreateMutableCopy(NULL, 0, members);
				updated = TRUE;		// if we're updating an existing bridge
			} else {
				newMembers = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
			}
			CFArrayAppendValue(newMembers, interface);
			ok = SCBridgeInterfaceSetMemberInterfaces(bridge, newMembers);
			CFRelease(newMembers);
			if (!ok) {
				SC_log(LOG_INFO, "could not update bridge with \"%@\": %s",
				       SCNetworkInterfaceGetLocalizedDisplayName(interface),
				       SCErrorString(SCError()));
				CFRelease(bridge);
				continue;
			}

			// exclude the new member interface
			newExcluded = CFSetCreateMutableCopy(NULL, 0, excluded);
			CFRelease(excluded);
			CFSetAddValue(newExcluded, interface);
			excluded = newExcluded;

			// update the list of interfaces to include the [new or updated] bridge
			newInterfaces = CFArrayCreateMutableCopy(NULL, 0, interfaces);
			if (bridgeIndex != kCFNotFound) {
				CFArraySetValueAtIndex(newInterfaces, bridgeIndex, bridge);
			} else {
				CFArrayAppendValue(newInterfaces, bridge);
			}
			if (updatedIFs) {
				CFRelease(interfaces);
			}
			interfaces = newInterfaces;
			updatedIFs = TRUE;

			// refresh [existing] services
			newServices = updateServices(services, bridge);
			if (newServices != NULL) {
				CFRelease(services);
				services = newServices;
			}

			CFRelease(bridge);
		}
	}
#endif	// !TARGET_OS_IPHONE

	n = (interfaces != NULL) ? CFArrayGetCount(interfaces) : 0;
	for (i = 0; i < n; i++) {
		SCNetworkInterfaceRef	interface;
		CFMutableArrayRef	interface_list;

		interface = CFArrayGetValueAtIndex(interfaces, i);

		if (excludeHidden && skipInterface(interface)) {
			// if not auto-configure
			continue;
		}

		if ((excluded != NULL)
		    && CFSetContainsValue(excluded, interface)) {
			// if this interface is a member of a Bond or Bridge
			continue;
		}

		if (__SCNetworkServiceExistsForInterface(services, interface)) {
			// if this is not a new interface
			continue;
		}

		interface_list = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
		CFArrayAppendValue(interface_list, interface);

		while (ok && (CFArrayGetCount(interface_list) > 0)) {
			CFArrayRef		protocol_types;

			interface = CFArrayGetValueAtIndex(interface_list, 0);

			protocol_types = SCNetworkInterfaceGetSupportedProtocolTypes(interface);
			if ((protocol_types != NULL) && (CFArrayGetCount(protocol_types) > 0)) {
				SCNetworkServiceRef	service;

				service = SCNetworkServiceCreate(setPrivate->prefs, interface);
				if (service == NULL) {
					SC_log(LOG_INFO, "could not create service for \"%@\": %s",
					       SCNetworkInterfaceGetLocalizedDisplayName(interface),
					       SCErrorString(SCError()));
					ok = FALSE;
					goto nextInterface;
				}

				ok = SCNetworkServiceEstablishDefaultConfiguration(service);
				if (!ok) {
					SC_log(LOG_INFO, "could not estabish default configuration for \"%@\": %s",
					       SCNetworkInterfaceGetLocalizedDisplayName(interface),
					       SCErrorString(SCError()));
					SCNetworkServiceRemove(service);
					CFRelease(service);
					goto nextInterface;
				}

				ok = SCNetworkSetAddService(set, service);
				if (!ok) {
					SC_log(LOG_INFO, "could not add service for \"%@\": %s",
					       SCNetworkInterfaceGetLocalizedDisplayName(interface),
					       SCErrorString(SCError()));
					SCNetworkServiceRemove(service);
					CFRelease(service);
					goto nextInterface;
				}

				CFRelease(service);
				updated = TRUE;
			} else {
				add_supported_interfaces(interface_list, interface);
			}

		    nextInterface :

			CFArrayRemoveValueAtIndex(interface_list, 0);
		}
		CFRelease(interface_list);
	}
	if (updatedIFs)		CFRelease(interfaces);
	if (services != NULL)	CFRelease(services);
	if (excluded != NULL)	CFRelease(excluded);

#if	TARGET_OS_IPHONE
	if (orphans != NULL) {
		if (ok && updated) {
			CFIndex	i;
			CFIndex	n	= CFArrayGetCount(orphans);

			for (i = 0; i < n; i++) {
				SCNetworkServiceRef	service;

				service = CFArrayGetValueAtIndex(orphans, i);
				if (_SCNetworkServiceIsVPN(service)) {
					ok = SCNetworkSetAddService(set, service);
					if (!ok) {
						break;
					}
				}
			}
		}

		CFRelease(orphans);
	}
#endif	// TARGET_OS_IPHONE

	if (ok && !updated) {
		// if no changes were made
		_SCErrorSet(kSCStatusOK);
	}

	return updated;
}
static
CFArrayRef _SecIdentityCopyPossiblePaths(
    CFStringRef name)
{
    // utility function to build and return an array of possible paths for the given name.
    // if name is not a URL, this returns a single-element array.
    // if name is a URL, the array may contain 1..N elements, one for each level of the path hierarchy.

    CFMutableArrayRef names = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
    if (!name) {
        return names;
    }
    CFIndex oldLength = CFStringGetLength(name);
    CFArrayAppendValue(names, name);

    CFURLRef url = CFURLCreateWithString(NULL, name, NULL);
    if (url) {
		if (CFURLCanBeDecomposed(url)) {
			// first, remove the query portion of this URL, if any
			CFStringRef qs = CFURLCopyQueryString(url, NULL);
			if (qs) {
				CFMutableStringRef newName = CFStringCreateMutableCopy(NULL, oldLength, name);
				if (newName) {
					CFIndex qsLength = CFStringGetLength(qs) + 1; // include the '?'
					CFStringDelete(newName, CFRangeMake(oldLength-qsLength, qsLength));
					CFRelease(url);
					url = CFURLCreateWithString(NULL, newName, NULL);
					CFArraySetValueAtIndex(names, 0, newName);
					CFRelease(newName);
				}
				CFRelease(qs);
			}
			// now add an entry for each level of the path
			while (url) {
				CFURLRef parent = CFURLCreateCopyDeletingLastPathComponent(NULL, url);
				if (parent) {
					CFStringRef parentURLString = CFURLGetString(parent);
					if (parentURLString) {
						CFIndex newLength = CFStringGetLength(parentURLString);
						// check that string length has decreased as expected; for file URLs,
						// CFURLCreateCopyDeletingLastPathComponent can insert './' or '../'
						if ((newLength >= oldLength) || (!CFStringHasPrefix(name, parentURLString))) {
							CFRelease(parent);
							CFRelease(url);
							break;
						}
						oldLength = newLength;
						CFArrayAppendValue(names, parentURLString);
					}
				}
				CFRelease(url);
				url = parent;
			}
		}
		else {
			CFRelease(url);
		}
	}
	// finally, add wildcard entries for each subdomain
	url = CFURLCreateWithString(NULL, name, NULL);
	if (url) {
		if (CFURLCanBeDecomposed(url)) {
			CFStringRef netLocString = CFURLCopyNetLocation(url);
			if (netLocString) {
				// first strip off port number, if present
				CFStringRef tmpLocString = netLocString;
				CFArrayRef hostnameArray = CFStringCreateArrayBySeparatingStrings(NULL, netLocString, CFSTR(":"));
				tmpLocString = (CFStringRef)CFRetain((CFStringRef)CFArrayGetValueAtIndex(hostnameArray, 0));
				CFRelease(netLocString);
				CFRelease(hostnameArray);
				netLocString = tmpLocString;
				// split remaining string into domain components
				hostnameArray = CFStringCreateArrayBySeparatingStrings(NULL, netLocString, CFSTR("."));
				CFIndex subdomainCount = CFArrayGetCount(hostnameArray);
				CFIndex i = 0;
				while (++i < subdomainCount) {
					CFIndex j = i;
					CFMutableStringRef wildcardString = CFStringCreateMutable(NULL, 0);
					if (wildcardString) {
						CFStringAppendCString(wildcardString, "*", kCFStringEncodingUTF8);
						while (j < subdomainCount) {
							CFStringRef domainString = (CFStringRef)CFArrayGetValueAtIndex(hostnameArray, j++);
							if (CFStringGetLength(domainString) > 0) {
								CFStringAppendCString(wildcardString, ".", kCFStringEncodingUTF8);
								CFStringAppend(wildcardString, domainString);
							}
						}
						if (CFStringGetLength(wildcardString) > 1) {
							CFArrayAppendValue(names, wildcardString);
						}
						CFRelease(wildcardString);
					}
				}
				CFRelease(hostnameArray);
				CFRelease(netLocString);
			}
		}
		CFRelease(url);
	}

    return names;
}
/*
 * Given a SecIdentityRef, do our best to construct a complete, ordered, and 
 * verified cert chain, returning the result in a CFArrayRef. The result is 
 * suitable for use when calling SSLSetCertificate().
 */
OSStatus sslCompleteCertChain(
	SecIdentityRef 		identity, 
	SecCertificateRef	trustedAnchor,	// optional additional trusted anchor
	bool 				includeRoot, 	// include the root in outArray
	CFArrayRef			*outArray)		// created and RETURNED
{
	CFMutableArrayRef 			certArray;
	SecTrustRef					secTrust = NULL;
	SecPolicyRef				policy = NULL;
	SecPolicySearchRef			policySearch = NULL;
	SecTrustResultType			secTrustResult;
	CSSM_TP_APPLE_EVIDENCE_INFO *dummyEv;			// not used
	CFArrayRef					certChain = NULL;   // constructed chain
	CFIndex 					numResCerts;
	
	certArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
	CFArrayAppendValue(certArray, identity);
	
	/*
	 * Case 1: identity is a root; we're done. Note that this case
	 * overrides the includeRoot argument.
	 */
	SecCertificateRef certRef;
	OSStatus ortn = SecIdentityCopyCertificate(identity, &certRef);
	if(ortn) {
		/* should never happen */
		cssmPerror("SecIdentityCopyCertificate", ortn);
		return ortn;
	}
	bool isRoot = isCertRefRoot(certRef);
	if(isRoot) {
		*outArray = certArray;
		CFRelease(certRef);
		return errSecSuccess;
	}
	
	/* 
	 * Now use SecTrust to get a complete cert chain, using all of the 
	 * user's keychains to look for intermediate certs.
	 * NOTE this does NOT handle root certs which are not in the system
	 * root cert DB. (The above case, where the identity is a root cert, does.)
	 */
	CFMutableArrayRef subjCerts = CFArrayCreateMutable(NULL, 1, &kCFTypeArrayCallBacks);
	CFArraySetValueAtIndex(subjCerts, 0, certRef);
			
	/* the array owns the subject cert ref now */
	CFRelease(certRef);
	
	/* Get a SecPolicyRef for generic X509 cert chain verification */
	ortn = SecPolicySearchCreate(CSSM_CERT_X_509v3,
		&CSSMOID_APPLE_X509_BASIC,
		NULL,				// value
		&policySearch);
	if(ortn) {
		cssmPerror("SecPolicySearchCreate", ortn);
		goto errOut;
	}
	ortn = SecPolicySearchCopyNext(policySearch, &policy);
	if(ortn) {
		cssmPerror("SecPolicySearchCopyNext", ortn);
		goto errOut;
	}

	/* build a SecTrustRef for specified policy and certs */
	ortn = SecTrustCreateWithCertificates(subjCerts,
		policy, &secTrust);
	if(ortn) {
		cssmPerror("SecTrustCreateWithCertificates", ortn);
		goto errOut;
	}
	
	if(trustedAnchor) {
		/* 
		 * Tell SecTrust to trust this one in addition to the current
		 * trusted system-wide anchors.
		 */
		CFMutableArrayRef newAnchors;
		CFArrayRef currAnchors;
		
		ortn = SecTrustCopyAnchorCertificates(&currAnchors);
		if(ortn) {
			/* should never happen */
			cssmPerror("SecTrustCopyAnchorCertificates", ortn);
			goto errOut;
		}
		newAnchors = CFArrayCreateMutableCopy(NULL,
			CFArrayGetCount(currAnchors) + 1,
			currAnchors);
		CFRelease(currAnchors);
		CFArrayAppendValue(newAnchors, trustedAnchor);
		ortn = SecTrustSetAnchorCertificates(secTrust, newAnchors);
		CFRelease(newAnchors);
		if(ortn) {
			cssmPerror("SecTrustSetAnchorCertificates", ortn);
			goto errOut;
		}
	}
	/* evaluate: GO */
	ortn = SecTrustEvaluate(secTrust, &secTrustResult);
	if(ortn) {
		cssmPerror("SecTrustEvaluate", ortn);
		goto errOut;
	}
	switch(secTrustResult) {
		case kSecTrustResultUnspecified:
			/* cert chain valid, no special UserTrust assignments */
		case kSecTrustResultProceed:
			/* cert chain valid AND user explicitly trusts this */
			break;
		default:
			/*
			 * Cert chain construction failed. 
			 * Just go with the single subject cert we were given.
			 */
			printf("***Warning: could not construct completed cert chain\n");
			ortn = errSecSuccess;
			goto errOut;
	}

	/* get resulting constructed cert chain */
	ortn = SecTrustGetResult(secTrust, &secTrustResult, &certChain, &dummyEv);
	if(ortn) {
		cssmPerror("SecTrustEvaluate", ortn);
		goto errOut;
	}
	
	/*
	 * Copy certs from constructed chain to our result array, skipping 
	 * the leaf (which is already there, as a SecIdentityRef) and possibly
	 * a root.
	 */
	numResCerts = CFArrayGetCount(certChain);
	if(numResCerts < 2) {
		/*
		 * Can't happen: if subject was a root, we'd already have returned. 
		 * If chain doesn't verify to a root, we'd have bailed after
		 * SecTrustEvaluate().
		 */
		printf("***sslCompleteCertChain screwup: numResCerts %d\n", 
			(int)numResCerts);
		ortn = errSecSuccess;
		goto errOut;
	}
	if(!includeRoot) {
		/* skip the last (root) cert) */
		numResCerts--;
	}
	for(CFIndex dex=1; dex<numResCerts; dex++) {
		certRef = (SecCertificateRef)CFArrayGetValueAtIndex(certChain, dex);
		CFArrayAppendValue(certArray, certRef);
	}
errOut:
	/* clean up */
	if(secTrust) {
		CFRelease(secTrust);
	}
	if(subjCerts) {
		CFRelease(subjCerts);
	}
	if(policy) {
		CFRelease(policy);
	}
	if(policySearch) {
		CFRelease(policySearch);
	}
	*outArray = certArray;
	return ortn;
}
void
configSet(CFMutableArrayRef config, CFStringRef key, CFStringRef value)
{
	CFMutableStringRef	pref;
	CFIndex			configLen	= CFArrayGetCount(config);
	CFIndex			i;
	CFIndex			n;
	CFMutableStringRef	newValue;
	CFRange			range;
	CFStringRef		specialChars	= CFSTR(" \"'$!|\\<>`{}[]");
	boolean_t		mustQuote	= FALSE;

	/* create search prefix */
	pref = CFStringCreateMutableCopy(NULL, 0, key);
	CFStringAppend(pref, CFSTR("="));

	/*
	 * create new / replacement value
	 *
	 * Note: Since the configuration file may be processed by a
	 *       shell script we need to ensure that, if needed, the
	 *       string is properly quoted.
	 */
	newValue = CFStringCreateMutableCopy(NULL, 0, value);

	n = CFStringGetLength(specialChars);
	for (i = 0; i < n; i++) {
		CFStringRef	specialChar;

		specialChar = CFStringCreateWithSubstring(NULL, specialChars, CFRangeMake(i, 1));
		range = CFStringFind(newValue, specialChar, 0);
		CFRelease(specialChar);
		if (range.location != kCFNotFound) {
			/* this string has at least one special character */
			mustQuote = TRUE;
			break;
		}
	}

	if (mustQuote) {
		CFStringRef	charsToQuote	= CFSTR("\\\"$`");

		/*
		 * in addition to quoting the entire string we also need to escape the
		 * space " " and backslash "\" characters
		 */
		n = CFStringGetLength(charsToQuote);
		for (i = 0; i < n; i++) {
			CFStringRef	quoteChar;
			CFArrayRef	matches;

			quoteChar = CFStringCreateWithSubstring(NULL, charsToQuote, CFRangeMake(i, 1));
			range     = CFRangeMake(0, CFStringGetLength(newValue));
			matches   = CFStringCreateArrayWithFindResults(NULL,
								       newValue,
								       quoteChar,
								       range,
								       0);
			CFRelease(quoteChar);

			if (matches) {
				CFIndex	j = CFArrayGetCount(matches);

				while (--j >= 0) {
					const CFRange	*range;

					range = CFArrayGetValueAtIndex(matches, j);
					CFStringInsert(newValue, range->location, CFSTR("\\"));
				}
				CFRelease(matches);
			}
		}

		CFStringInsert(newValue, 0, CFSTR("\""));
		CFStringAppend(newValue, CFSTR("\""));
	}

	/* locate existing key */
	for (i = 0; i < configLen; i++) {
		if (CFStringHasPrefix(CFArrayGetValueAtIndex(config, i), pref)) {
			break;
		}
	}

	CFStringAppend(pref, newValue);
	CFRelease(newValue);
	if (i < configLen) {
		/* if replacing an existing entry */
		CFArraySetValueAtIndex(config, i, pref);
	} else {
		/*
		 * if new entry, insert it just prior to the last (emtpy)
		 * array element.
		 */
		CFArrayInsertValueAtIndex(config, configLen-1, pref);
	}
	CFRelease(pref);

	return;
}
__private_extern__
CF_RETURNS_RETAINED CFDictionaryRef
proxy_configuration_update(CFDictionaryRef	defaultProxy,
			   CFDictionaryRef	services,
			   CFArrayRef		serviceOrder,
			   CFDictionaryRef	servicesInfo)
{
	CFIndex			i;
	CFMutableDictionaryRef	myDefault;
	Boolean			myOrderAdded	= FALSE;
	CFMutableDictionaryRef	newProxy	= NULL;
	CFIndex			n_proxies;
	CFDictionaryRef		proxy;
	CFMutableArrayRef	proxies;

	// establish full list of proxies

	proxies = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);

	// collect (and add) any "supplemental" proxy configurations

	add_supplemental_proxies(proxies, services, serviceOrder);

	// add the "default" proxy

	add_default_proxy(proxies, defaultProxy, &myOrderAdded);

	// sort proxies, cleanup

	n_proxies = CFArrayGetCount(proxies);
	if (n_proxies > 1) {
		CFArraySortValues(proxies, CFRangeMake(0, n_proxies), compareDomain, NULL);
	}

	// cleanup

	for (i = n_proxies - 1; i >= 0; i--) {
		proxy = CFArrayGetValueAtIndex(proxies, i);

		if ((i > 0) &&
		    !CFDictionaryContainsKey(proxy, kSCPropNetProxiesSupplementalMatchDomain)) {
			// remove non-supplemental proxy
			CFArrayRemoveValueAtIndex(proxies, i);
			n_proxies--;
			continue;
		}

		newProxy = CFDictionaryCreateMutableCopy(NULL, 0, proxy);
		CFDictionaryRemoveValue(newProxy, PROXY_MATCH_ORDER_KEY);
		CFDictionaryRemoveValue(newProxy, ORDER_KEY);
		CFArraySetValueAtIndex(proxies, i, newProxy);
		CFRelease(newProxy);
	}

	// update the default proxy

	myDefault = CFDictionaryCreateMutableCopy(NULL,
						  0,
						  CFArrayGetValueAtIndex(proxies, 0));
	if (myOrderAdded && (n_proxies > 1)) {
		CFDictionaryRef	proxy;

		proxy = CFArrayGetValueAtIndex(proxies, 1);
		if (CFDictionaryContainsKey(proxy, kSCPropNetProxiesSupplementalMatchDomain)) {
			// if not a supplemental "default" proxy (a match domain name is
			// present)
			CFDictionaryRemoveValue(myDefault, PROXY_MATCH_ORDER_KEY);
		}
	}
	CFArraySetValueAtIndex(proxies, 0, myDefault);
	CFRelease(myDefault);

	// establish proxy configuration

	if (n_proxies > 0) {
		CFDictionaryRef		app_layer;
		CFDictionaryRef		scoped;
		CFArrayRef		serviceOrderAll;
		Boolean			skip		= FALSE;
		CFArrayRef		supplemental;

		proxy = CFArrayGetValueAtIndex(proxies, 0);
		if (!CFDictionaryContainsKey(proxy, kSCPropNetProxiesSupplementalMatchDomain)) {
			// if we have "a" default (non-supplemental) proxy
			newProxy = CFDictionaryCreateMutableCopy(NULL, 0, proxy);
			CFDictionaryRemoveValue(newProxy, kSCPropNetProxiesSupplementalMatchDomains);
			CFDictionaryRemoveValue(newProxy, kSCPropNetProxiesSupplementalMatchOrders);
			skip = TRUE;
		} else {
			newProxy = CFDictionaryCreateMutable(NULL,
							     0,
							     &kCFTypeDictionaryKeyCallBacks,
							     &kCFTypeDictionaryValueCallBacks);
		}

		serviceOrderAll = service_order_copy_all(services, serviceOrder);

		// collect (and add) any "supplemental" proxy configurations

		supplemental = copy_supplemental_proxies(proxies, skip);
		if (supplemental != NULL) {
			CFDictionarySetValue(newProxy, kSCPropNetProxiesSupplemental, supplemental);
			CFRelease(supplemental);
		}

		// collect (and add) any "scoped" proxy configurations

		scoped = copy_scoped_proxies(services, serviceOrderAll);
		if (scoped != NULL) {
			CFDictionarySetValue(newProxy, kSCPropNetProxiesScoped, scoped);
			CFRelease(scoped);
		}

		// collect (and add) any "services" based proxy configurations

		app_layer = copy_app_layer_vpn_proxies(services, serviceOrderAll, servicesInfo);
		if (app_layer != NULL) {
			CFDictionarySetValue(newProxy, kSCPropNetProxiesServices, app_layer);
			CFRelease(app_layer);
		}

		if (serviceOrderAll != NULL) {
			CFRelease(serviceOrderAll);
		}
	} else {
		newProxy = NULL;
	}

	CFRelease(proxies);
	return newProxy;
}
예제 #19
0
static PyObject* pyfsevents_schedule(PyObject* self, PyObject* args,
                                     PyObject *keywds) {
    PyObject* thread;
    PyObject* stream;
    PyObject* paths;
    PyObject* callback;
    PyObject* show_file_events;

    // default latency to be used.
    double latency = 0.01; 
    
    static char *kwlist[] = {"thread", "stream", "callback", "paths", 
                             "show_file_events", "latency", NULL};

    if (!PyArg_ParseTupleAndKeywords(args, keywds, "OOOOO|d:schedule", kwlist,
                                     &thread, &stream, &callback, &paths,
                                     &show_file_events, &latency))
        return NULL;
    
    /* stream must not already have been scheduled */
    if (PyDict_Contains(streams, stream) == 1) {
        return NULL;
    }

    /* create path array */
    CFMutableArrayRef cfArray;
    cfArray = CFArrayCreateMutable(kCFAllocatorDefault, 1,
                                   &kCFTypeArrayCallBacks);
    if (cfArray == NULL)
        return NULL;

    int i;
    Py_ssize_t size = PyList_Size(paths);
    const char* path;
    CFStringRef cfStr;
    for (i=0; i<size; i++) {
        path = PyString_AS_STRING(PyList_GetItem(paths, i));
        cfStr = CFStringCreateWithCString(kCFAllocatorDefault,
                                          path,
                                          kCFStringEncodingUTF8);
        CFArraySetValueAtIndex(cfArray, i, cfStr);
        CFRelease(cfStr);
    }

    /* allocate stream info structure */
    FSEventStreamInfo * info = PyMem_New(FSEventStreamInfo, 1);

    /* create event stream */
    FSEventStreamContext context = {0, (void*) info, NULL, NULL, NULL};
    FSEventStreamRef fsstream = NULL;
    
    UInt32 flags = kFSEventStreamCreateFlagNoDefer;
    if(show_file_events == Py_True){
        flags = flags | kFSEventStreamCreateFlagFileEvents;
    }

    fsstream = FSEventStreamCreate(kCFAllocatorDefault,
                                   (FSEventStreamCallback)&handler,
                                   &context,
                                   cfArray,
                                   kFSEventStreamEventIdSinceNow,
                                   latency,
                                   flags);
    CFRelease(cfArray);

    PyObject* value = PyCObject_FromVoidPtr((void*) fsstream, PyMem_Free);
    PyDict_SetItem(streams, stream, value);

    /* get runloop reference from observer info data or current */
    value = PyDict_GetItem(loops, thread);
    CFRunLoopRef loop;
    if (value == NULL) {
        loop = CFRunLoopGetCurrent();
    } else {
        loop = (CFRunLoopRef) PyCObject_AsVoidPtr(value);
    }

    FSEventStreamScheduleWithRunLoop(fsstream, loop, kCFRunLoopDefaultMode);

    /* set stream info for callback */
    info->callback = callback;
    info->stream = fsstream;
    info->loop = loop;
    info->state = PyThreadState_Get();
    Py_INCREF(callback);

    /* start event streams */
    if (!FSEventStreamStart(fsstream)) {
        FSEventStreamInvalidate(fsstream);
        FSEventStreamRelease(fsstream);
        return NULL;
    }

    Py_INCREF(Py_None);
    return Py_None;
}
__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;
}
예제 #21
0
/**
 * Set the nth item in a #PLIST_ARRAY node.
 * The previous item at index n will be freed using #plist_free
 *
 * @param node the node of type #PLIST_ARRAY
 * @param item the new item at index n
 * @param n the index of the item to get. Range is [0, array_size[. Assert if n is not in range.
 */
void plist_array_set_item(plist_t node, plist_t item, uint32_t n)
{
	CFArraySetValueAtIndex((CFMutableArrayRef) node, n, item);
	CFRelease(item);
}