void printProperty(
    CFStringRef label,
    CFStringRef propKey,
    CFTypeRef value,
    char lineEnd)
{
    CFTypeID type = CFGetTypeID(value);
    CFStringRef propString = NULL;     // must release
    CFStringRef labeledString = NULL;  // must release
    CFStringRef outputString = NULL;   // do not release
    char * allocString = NULL;         // must free
    char * dataString = NULL;  // must free

    if (type == CFStringGetTypeID()) {
        propString = CFStringCreateWithFormat(
            kCFAllocatorDefault, NULL, CFSTR("%@ = \"%@\"%c"),
            propKey, value, lineEnd);
    } else if (type == CFNumberGetTypeID()) {
        propString = CFStringCreateWithFormat(
            kCFAllocatorDefault, NULL, CFSTR("%@ = %@%c"),
            propKey, value, lineEnd);
    } else if (type == CFBooleanGetTypeID()) {
        propString = CFStringCreateWithFormat(
            kCFAllocatorDefault, NULL, CFSTR("%@ = %@%c"),
            propKey, value, lineEnd);
    } else if (type == CFDataGetTypeID()) {
        CFIndex length = 0;
        length = CFDataGetLength(value);
        const UInt8 * data = CFDataGetBytePtr(value);
        if (!data) {
            propString = CFStringCreateWithFormat(
                kCFAllocatorDefault, NULL, CFSTR("%@[%zd] = <null data pointer>%c"),
                propKey, length, lineEnd);
        } else {
            int numBytes = (int)MIN(length, kMaxPrintableCFDataLength);
            dataString = stringForData(data, MIN(numBytes, kMaxPrintableCFDataLength));
            if (length > kMaxPrintableCFDataLength) {
                propString = CFStringCreateWithFormat(
                    kCFAllocatorDefault, NULL,
                    CFSTR("%@ = <data (%zd bytes): %s...>%c"),
                    propKey, length, dataString, lineEnd);
            } else {
                propString = CFStringCreateWithFormat(
                    kCFAllocatorDefault, NULL,
                    CFSTR("%@ = <data (%zd bytes): %s>%c"),
                    propKey, length, dataString, lineEnd);
            }
        }
    } else if (type == CFDictionaryGetTypeID()) {
        propString = CFStringCreateWithFormat(
            kCFAllocatorDefault, NULL, CFSTR("%@ = <dictionary of %zd items>%c"),
            propKey, CFDictionaryGetCount(value), lineEnd);
    } else if (type == CFArrayGetTypeID()) {
        propString = CFStringCreateWithFormat(
            kCFAllocatorDefault, NULL, CFSTR("%@ = <array of %zd items>%c"),
            propKey, CFArrayGetCount(value), lineEnd);
    } else {
        propString = CFStringCreateWithFormat(
            kCFAllocatorDefault, NULL, CFSTR("%@ = <value of unknown type>%c"),
            propKey, lineEnd);
    }

    if (!propString) {
        goto finish;
    }

    if (label) {
        labeledString = CFStringCreateWithFormat(
            kCFAllocatorDefault, NULL, CFSTR("%@: %@"), label, propString);
        outputString = labeledString;
    } else {
        labeledString = CFStringCreateWithFormat(
            kCFAllocatorDefault, NULL, CFSTR("%@"), propString);
        outputString = labeledString;
    }

    if (!outputString) {
        goto finish;
    }

    allocString = createUTF8CStringForCFString(outputString);
    if (!allocString) {
        goto finish;
    }

    fprintf(stdout, "%s", allocString);

finish:
    if (propString)     CFRelease(propString);
    if (labeledString)  CFRelease(labeledString);
    if (allocString)    free(allocString);
    if (dataString)     free(dataString);
    return;
}
/*****************************************************************************
* AddEventToPlugin
* -
* This method is invoked when launchd wishes the plugin to setup a launch
* event matching the parameters in the dictionary.
*****************************************************************************/
void AddEventToPlugin(BonjourUserEventsPlugin* plugin, CFNumberRef launchdToken, CFDictionaryRef eventParameters)
{
    CFStringRef domain = CFDictionaryGetValue(eventParameters, sServiceDomainKey);
    CFStringRef type = CFDictionaryGetValue(eventParameters, sServiceTypeKey);
    CFStringRef name = CFDictionaryGetValue(eventParameters, sServiceNameKey);
    CFBooleanRef cfOnAdd = CFDictionaryGetValue(eventParameters, sOnServiceAddKey);
    CFBooleanRef cfOnRemove = CFDictionaryGetValue(eventParameters, sOnServiceRemoveKey);

    Boolean onAdd = false;
    Boolean onRemove = false;

    if (cfOnAdd && CFGetTypeID(cfOnAdd) == CFBooleanGetTypeID() && CFBooleanGetValue(cfOnAdd))
        onAdd = true;

    if (cfOnRemove && CFGetTypeID(cfOnRemove) == CFBooleanGetTypeID() && CFBooleanGetValue(cfOnRemove))
        onRemove = true;

    // A type is required. If none is specified, BAIL
    if (!type || CFGetTypeID(type) != CFStringGetTypeID())
    {
        fprintf(stderr, "%s:%s: a LaunchEvent is missing a service type.\n", sPluginIdentifier, __FUNCTION__);
        return;
    }

    // If we aren't suppose to launch on services appearing or disappearing, this service does nothing. Ignore.
    if (!onAdd && !onRemove)
    {
        fprintf(stderr, "%s:%s a LaunchEvent is missing both onAdd and onRemove events\n", sPluginIdentifier, __FUNCTION__);
        return;
    }

    // If no domain is specified, assume local.
    if (!domain)
    {
        domain = CFSTR("local");
    }
    else if (CFGetTypeID(domain) != CFStringGetTypeID() ) // If the domain is not a string, fail
    {
        fprintf(stderr, "%s:%s a LaunchEvent has a domain that is not a string.\n", sPluginIdentifier, __FUNCTION__);
        return;
    }

    // If we have a name filter, but it's not a string. This event is broken, bail.
    if (name && CFGetTypeID(name) != CFStringGetTypeID())
    {
        fprintf(stderr, "%s:%s a LaunchEvent has a domain that is not a string.\n", sPluginIdentifier, __FUNCTION__);
        return;
    }

    // Get us a browser
    NetBrowserInfo* browser = CreateBrowser(plugin, type, domain);

    if (!browser)
    {
        fprintf(stderr, "%s:%s cannot create browser\n", sPluginIdentifier, __FUNCTION__);
        return;
    }

    // Create Event Dictionary
    CFMutableDictionaryRef eventDictionary = CFDictionaryCreateMutable(NULL, 4, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);

    // We store both the Token and the Dictionary. UserEventAgentSetLaunchEventState needs
    // the token and UserEventAgentSetFireEvent needs both the token and the dictionary
    CFDictionarySetValue(eventDictionary, sLaunchdTokenKey, launchdToken);
    CFDictionarySetValue(eventDictionary, sLaunchdDictKey, eventParameters);

    if (name)
        CFDictionarySetValue(eventDictionary, sServiceNameKey, name);

    // Add to the correct dictionary.
    if (onAdd)
    {
        asl_log(NULL, NULL, ASL_LEVEL_INFO, "%s:%s: Adding browser to AddEvents", sPluginIdentifier, __FUNCTION__);
        AddEventDictionary(eventDictionary, plugin->_onAddEvents, browser);
    }

    if (onRemove)
    {
        asl_log(NULL, NULL, ASL_LEVEL_INFO, "%s:%s: Adding browser to RemoveEvents", sPluginIdentifier, __FUNCTION__);
        AddEventDictionary(eventDictionary, plugin->_onRemoveEvents, browser);
    }

    // Add Token Mapping
    CFDictionarySetValue(plugin->_tokenToBrowserMap, launchdToken, browser);

    // Release Memory
    CFRelease(eventDictionary);
}
Beispiel #3
0
OSStatus LSOpenApplication(const LSApplicationParameters *appParams, ProcessSerialNumber *outPSN)
{
	if (!appParams)
		return paramErr;

	std::string exePath;
	std::vector<char*> argv;
	std::unique_ptr<std::vector<char*>> envp;
	int pipefds[2];
	pid_t pid;
	OSStatus rv = noErr;

	if (!FSRefMakePath(appParams->application, exePath))
		return fnfErr;

	if (appParams->argv != nullptr)
	{
		CFIndex count = CFArrayGetCount(appParams->argv);

		for (CFIndex i = 0; i < count; i++)
		{
			CFStringRef ref = (CFStringRef) CFArrayGetValueAtIndex(appParams->argv, i);
			if (CFGetTypeID(ref) != CFStringGetTypeID())
				return paramErr;

			argv.push_back((char*) CFStringGetCStringPtr((CFStringRef) CFArrayGetValueAtIndex(appParams->argv, i), kCFStringEncodingUTF8));
		}
		argv.push_back(nullptr);
	}
	else
	{
		argv.push_back((char*) exePath.c_str());
		argv.push_back(nullptr);
	}

	if (appParams->environment != nullptr)
	{
		CFIndex count = CFDictionaryGetCount(appParams->environment);
		envp.reset(new std::vector<char*>);
		
		CFDictionaryApplyFunction(appParams->environment, [](const void* key, const void* value, void* context) {
					CFStringRef skey = (CFStringRef) key;
					CFStringRef svalue = (CFStringRef) value;
					std::vector<const char*>* envp = (std::vector<const char*>*) context;

					if (CFGetTypeID(skey) == CFStringGetTypeID() && CFGetTypeID(svalue) == CFStringGetTypeID())
					{
						char* str = new char[CFStringGetLength(skey) + CFStringGetLength(svalue) + 1];

						strcpy(str, CFStringGetCStringPtr(skey, kCFStringEncodingUTF8));
						strcat(str, "=");
						strcat(str, CFStringGetCStringPtr(svalue, kCFStringEncodingUTF8));

						envp->push_back(str);
					}
				}, envp.get());
	}

	// https://stackoverflow.com/questions/1584956/how-to-handle-execvp-errors-after-fork
	
	if (pipe(pipefds))
	{
		if (envp)
			std::for_each(envp->begin(), envp->end(), [](char* p) { delete [] p; });

		return makeOSStatus(errno);
	}

	fcntl(pipefds[1], F_SETFD, fcntl(pipefds[1], F_GETFD) | FD_CLOEXEC);

	switch (pid = fork())
	{
		case -1:
			rv = makeOSStatus(errno);
			break;
		case 0:
			close(pipefds[0]);
			execvpe(exePath.c_str(), &argv[0], envp ? &(*envp)[0] : nullptr);
			write(pipefds[1], &errno, sizeof(int));
			_exit(1);
			break;
		default:
		{
			int err, count;
			close(pipefds[1]);

			while ((count = read(pipefds[0], &err, sizeof(errno))) == -1)
			{
				if (errno != EAGAIN && errno != EINTR)
					break;
			}

			if (count > 0)
				rv = makeOSStatus(err);
			close(pipefds[0]);
		}
	}
	
	if (envp)
		std::for_each(envp->begin(), envp->end(), [](char* p) { delete [] p; });

	return rv;
}
Beispiel #4
0
//--------------------------------------------------------------------------
// JSObjectKJSValue
//--------------------------------------------------------------------------
JSValue JSObjectKJSValue(JSUserObject* ptr)
{
    JSGlueAPIEntry entry;

    JSValue result = jsUndefined();
    if (ptr)
    {
        bool handled = false;

        switch (ptr->DataType())
        {
            case kJSUserObjectDataTypeJSValueWrapper:
            {
                JSValueWrapper* wrapper = (JSValueWrapper*)ptr->GetData();
                if (wrapper)
                {
                    result = wrapper->GetValue();
                    handled = true;
                }
                break;
            }

            case kJSUserObjectDataTypeCFType:
            {
                CFTypeRef cfType = (CFTypeRef*)ptr->GetData();
                if (cfType)
                {
                    CFTypeID typeID = CFGetTypeID(cfType);
                    if (typeID == CFStringGetTypeID())
                    {
                        result = jsString(getThreadGlobalExecState(), CFStringToUString((CFStringRef)cfType));
                        handled = true;
                    }
                    else if (typeID == CFNumberGetTypeID())
                    {
                        double num;
                        CFNumberGetValue((CFNumberRef)cfType, kCFNumberDoubleType, &num);
                        result = jsNumber(num);
                        handled = true;
                    }
                    else if (typeID == CFBooleanGetTypeID())
                    {
                        result = jsBoolean(CFBooleanGetValue((CFBooleanRef)cfType));
                        handled = true;
                    }
                    else if (typeID == CFNullGetTypeID())
                    {
                        result = jsNull();
                        handled = true;
                    }
                }
                break;
            }
        }
        if (!handled)
        {
            ExecState* exec = getThreadGlobalExecState();
            result = UserObjectImp::create(exec->globalData(), getThreadGlobalObject()->userObjectStructure(), ptr);
        }
    }
    return result;
}
Beispiel #5
0
static QVariant qtValue(CFPropertyListRef cfvalue)
{
    if (!cfvalue)
        return QVariant();

    CFTypeID typeId = CFGetTypeID(cfvalue);

    /*
        Sorted grossly from most to least frequent type.
    */
    if (typeId == CFStringGetTypeID()) {
        return QSettingsPrivate::stringToVariant(QCFString::toQString(static_cast<CFStringRef>(cfvalue)));
    } else if (typeId == CFNumberGetTypeID()) {
        CFNumberRef cfnumber = static_cast<CFNumberRef>(cfvalue);
        if (CFNumberIsFloatType(cfnumber)) {
            double d;
            CFNumberGetValue(cfnumber, kCFNumberDoubleType, &d);
            return d;
        } else {
            int i;
            qint64 ll;

            if (CFNumberGetValue(cfnumber, kCFNumberIntType, &i))
                return i;
            CFNumberGetValue(cfnumber, kCFNumberLongLongType, &ll);
            return ll;
        }
    } else if (typeId == CFArrayGetTypeID()) {
        CFArrayRef cfarray = static_cast<CFArrayRef>(cfvalue);
        QList<QVariant> list;
        CFIndex size = CFArrayGetCount(cfarray);
        bool metNonString = false;
        for (CFIndex i = 0; i < size; ++i) {
            QVariant value = qtValue(CFArrayGetValueAtIndex(cfarray, i));
            if (value.type() != QVariant::String)
                metNonString = true;
            list << value;
        }
        if (metNonString)
            return list;
        else
            return QVariant(list).toStringList();
    } else if (typeId == CFBooleanGetTypeID()) {
        return (bool)CFBooleanGetValue(static_cast<CFBooleanRef>(cfvalue));
    } else if (typeId == CFDataGetTypeID()) {
        CFDataRef cfdata = static_cast<CFDataRef>(cfvalue);
        return QByteArray(reinterpret_cast<const char *>(CFDataGetBytePtr(cfdata)),
                          CFDataGetLength(cfdata));
    } else if (typeId == CFDictionaryGetTypeID()) {
        CFDictionaryRef cfdict = static_cast<CFDictionaryRef>(cfvalue);
        CFTypeID arrayTypeId = CFArrayGetTypeID();
        int size = (int)CFDictionaryGetCount(cfdict);
        QVarLengthArray<CFPropertyListRef> keys(size);
        QVarLengthArray<CFPropertyListRef> values(size);
        CFDictionaryGetKeysAndValues(cfdict, keys.data(), values.data());

        QMultiMap<QString, QVariant> map;
        for (int i = 0; i < size; ++i) {
            QString key = QCFString::toQString(static_cast<CFStringRef>(keys[i]));

            if (CFGetTypeID(values[i]) == arrayTypeId) {
                CFArrayRef cfarray = static_cast<CFArrayRef>(values[i]);
                CFIndex arraySize = CFArrayGetCount(cfarray);
                for (CFIndex j = arraySize - 1; j >= 0; --j)
                    map.insert(key, qtValue(CFArrayGetValueAtIndex(cfarray, j)));
            } else {
                map.insert(key, qtValue(values[i]));
            }
        }
        return map;
    } else if (typeId == CFDateGetTypeID()) {
        QDateTime dt;
        dt.setTime_t((uint)kCFAbsoluteTimeIntervalSince1970);
        return dt.addSecs((int)CFDateGetAbsoluteTime(static_cast<CFDateRef>(cfvalue)));
    }
    return QVariant();
}
Beispiel #6
0
// Helper function to construct strings for CFDictionaryApplyFunction in
// platform_getmimedescription()
//  key     CFString containing a MIME type.
//  value   CFDictionary containing descriptions and extensions.
//  context char * where we want our NP_GetMIMETypeDescription compatible output.
static void mimetype_dictionary_applier(const void *key,
                                        const void *value,
                                        void *context)
{
    CFDictionaryRef cf_mimetype_dict    = value;
    CFStringRef     cf_mimetype         = key;
    CFIndex         cf_length;
    CFArrayRef      cf_extensions;
    CFStringRef     cf_description;
    CFBooleanRef    cf_enabled;
    char           *mimetype            = strdupa("");
    char           *description         = strdupa("");
    char           *extensions          = strdup("");
    char          **result              = context;

    // Here is an example of the output we want:
    //
    // "application/example:ext1,ext2:Example MIME Type"
    //

    // Verify that we received a CFDictionary object.
    if (CFGetTypeID(cf_mimetype_dict) != CFDictionaryGetTypeID()) {
        goto finished;
    }

    // Verify that the key is a CFString.
    if (CFGetTypeID(cf_mimetype) != CFStringGetTypeID()) {
        goto finished;
    }

    // Find the length of the MIME Type, and allocate stack space for it.
    cf_length = CFStringGetMaximumSizeForEncoding(CFStringGetLength(cf_mimetype),
                                                  kCFStringEncodingUTF8);
    mimetype = alloca(cf_length + 1);

    // Extract the string.
    if (CFStringGetCString(cf_mimetype,
                           mimetype,
                           cf_length + 1,
                           kCFStringEncodingUTF8) != true) {
        goto finished;
    }

    // First we need to check if this type is disabled via WebPluginTypeEnabled.
    if (CFDictionaryGetValueIfPresent(cf_mimetype_dict,
                                      CFSTR("WebPluginTypeEnabled"),
                                      (const void **) &cf_enabled)) {
        // Verify that is a CFBoolean
        if (CFGetTypeID(cf_enabled) != CFBooleanGetTypeID()) {
            goto finished;
        }

        // Test value.
        if (CFBooleanGetValue(cf_enabled) == false) {
            goto finished;
        }
    }


    // Verify we have an empty string.
    if (!extensions) {
        goto finished;
    }

    // Now we need to lookup the extensions requested by the plugin.
    if (CFDictionaryGetValueIfPresent(cf_mimetype_dict,
                                      CFSTR("WebPluginExtensions"),
                                      (const void **) &cf_extensions)) {
        if (CFGetTypeID(cf_extensions) != CFArrayGetTypeID()) {
            goto finished;
        }

        l_debug("discovered %u extensions defined for mimetype %s",
                CFArrayGetCount(cf_extensions),
                mimetype);

        // Apply a function to every extension listed to concatenate them.
        CFArrayApplyFunction(cf_extensions,
                             CFRangeMake(0, CFArrayGetCount(cf_extensions)),
                             extension_array_applier,
                             &extensions);
    }

    // Now we need the description which is a CFString
    if (CFDictionaryGetValueIfPresent(cf_mimetype_dict,
                                      CFSTR("WebPluginTypeDescription"),
                                      (const void **) &cf_description)) {
        if (CFGetTypeID(cf_description) != CFStringGetTypeID()) {
            goto finished;
        }

        // Find the length of the MIME Type, and allocate stack space for it.
        cf_length = CFStringGetMaximumSizeForEncoding(CFStringGetLength(cf_description),
                                                      kCFStringEncodingUTF8);
        description = alloca(cf_length + 1);

        // Extract the string.
        if (CFStringGetCString(cf_description,
                               description,
                               cf_length + 1,
                               kCFStringEncodingUTF8) != true) {
            goto finished;
        }
    }

    // So now we need to assemble the final string.
    *result = realloc(*result,
                      (*result ? strlen(*result) : 0)
                        + strlen(mimetype) + 1
                        + strlen(description) + 1
                        + strlen(extensions) + 1
                        + 1
                        + 1);

    // Verify that worked.
    if (!*result) {
        goto finished;
    }

    // Create the final string.
    sprintf(*result, "%s%s%s:%s:%s",
            *result,
            strlen(*result) ? ";" : "",
            mimetype,
            extensions,
            description);

    l_debug("successfully processed mimetype %s", mimetype);

finished:
    free(extensions);
    return;
}
Beispiel #7
0
static void onDeviceMatched(void * context, IOReturn result, void * sender, IOHIDDeviceRef device) {
	CFArrayRef elements;
	CFIndex elementIndex;
	IOHIDElementRef element;
	CFStringRef cfProductName;
	struct Gamepad_device * deviceRecord;
	struct Gamepad_devicePrivate * hidDeviceRecord;
	IOHIDElementType type;
	char * description;
	struct Gamepad_queuedEvent queuedEvent;
	
	deviceRecord = malloc(sizeof(struct Gamepad_device));
	deviceRecord->deviceID = nextDeviceID++;
	deviceRecord->vendorID = IOHIDDeviceGetVendorID(device);
	deviceRecord->productID = IOHIDDeviceGetProductID(device);
	deviceRecord->numAxes = 0;
	deviceRecord->numButtons = 0;
	devices = realloc(devices, sizeof(struct Gamepad_device *) * (numDevices + 1));
	devices[numDevices++] = deviceRecord;
	
	hidDeviceRecord = malloc(sizeof(struct Gamepad_devicePrivate));
	hidDeviceRecord->deviceRef = device;
	hidDeviceRecord->axisElements = NULL;
	hidDeviceRecord->buttonElements = NULL;
	deviceRecord->privateData = hidDeviceRecord;
	
	cfProductName = IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductKey));
	if (cfProductName == NULL || CFGetTypeID(cfProductName) != CFStringGetTypeID()) {
		description = malloc(strlen("[Unknown]" + 1));
		strcpy(description, "[Unknown]");
		
	} else {
		CFIndex length;
		
		CFStringGetBytes(cfProductName, CFRangeMake(0, CFStringGetLength(cfProductName)), kCFStringEncodingUTF8, '?', false, NULL, 100, &length);
		description = malloc(length + 1);
		CFStringGetBytes(cfProductName, CFRangeMake(0, CFStringGetLength(cfProductName)), kCFStringEncodingUTF8, '?', false, (UInt8 *) description, length + 1, NULL);
		description[length] = '\x00';
	}
	deviceRecord->description = description;
	
	elements = IOHIDDeviceCopyMatchingElements(device, NULL, kIOHIDOptionsTypeNone);
	for (elementIndex = 0; elementIndex < CFArrayGetCount(elements); elementIndex++) {
		element = (IOHIDElementRef) CFArrayGetValueAtIndex(elements, elementIndex);
		type = IOHIDElementGetType(element);
		
		// All of the axis elements I've ever detected have been kIOHIDElementTypeInput_Misc. kIOHIDElementTypeInput_Axis is only included for good faith...
		if (type == kIOHIDElementTypeInput_Misc ||
		    type == kIOHIDElementTypeInput_Axis) {
			
			hidDeviceRecord->axisElements = realloc(hidDeviceRecord->axisElements, sizeof(struct HIDGamepadAxis) * (deviceRecord->numAxes + 1));
			hidDeviceRecord->axisElements[deviceRecord->numAxes].cookie = IOHIDElementGetCookie(element);
			hidDeviceRecord->axisElements[deviceRecord->numAxes].logicalMin = IOHIDElementGetLogicalMin(element);
			hidDeviceRecord->axisElements[deviceRecord->numAxes].logicalMax = IOHIDElementGetLogicalMax(element);
			hidDeviceRecord->axisElements[deviceRecord->numAxes].hasNullState = !!IOHIDElementHasNullState(element);
			hidDeviceRecord->axisElements[deviceRecord->numAxes].isHatSwitch = IOHIDElementGetUsage(element) == kHIDUsage_GD_Hatswitch;
			hidDeviceRecord->axisElements[deviceRecord->numAxes].isHatSwitchSecondAxis = false;
			deviceRecord->numAxes++;
			
			if (hidDeviceRecord->axisElements[deviceRecord->numAxes - 1].isHatSwitch) {
				hidDeviceRecord->axisElements = realloc(hidDeviceRecord->axisElements, sizeof(struct HIDGamepadAxis) * (deviceRecord->numAxes + 1));
				hidDeviceRecord->axisElements[deviceRecord->numAxes].isHatSwitchSecondAxis = true;
				deviceRecord->numAxes++;
			}
			
		} else if (type == kIOHIDElementTypeInput_Button) {
			hidDeviceRecord->buttonElements = realloc(hidDeviceRecord->buttonElements, sizeof(struct HIDGamepadButton) * (deviceRecord->numButtons + 1));
			hidDeviceRecord->buttonElements[deviceRecord->numButtons].cookie = IOHIDElementGetCookie(element);
			deviceRecord->numButtons++;
		}
	}
	CFRelease(elements);
	
	deviceRecord->axisStates = calloc(sizeof(float), deviceRecord->numAxes);
	deviceRecord->buttonStates = calloc(sizeof(bool), deviceRecord->numButtons);
	
	IOHIDDeviceRegisterInputValueCallback(device, onDeviceValueChanged, deviceRecord);
	
	queuedEvent.deviceID = deviceRecord->deviceID;
	queuedEvent.eventType = GAMEPAD_EVENT_DEVICE_ATTACHED;
	queuedEvent.eventData = deviceRecord;
	
	if (deviceEventCount >= deviceEventQueueSize) {
		deviceEventQueueSize = deviceEventQueueSize == 0 ? 1 : deviceEventQueueSize * 2;
		deviceEventQueue = realloc(deviceEventQueue, sizeof(struct Gamepad_queuedEvent) * deviceEventQueueSize);
	}
	deviceEventQueue[deviceEventCount++] = queuedEvent;
}
Beispiel #8
0
bool wxHIDDevice::Create (int nClass, int nType, int nDev)
{
	//Create the mach port
	wxIOCHECK(IOMasterPort(bootstrap_port, &m_pPort), "Could not create mach port");

	//Dictionary that will hold first
	//the matching dictionary for determining which kind of devices we want,
	//then later some registry properties from an iterator (see below)
	CFMutableDictionaryRef pDictionary;

	//Create a dictionary
	//The call to IOServiceMatching filters down the
	//the services we want to hid services (and also eats the
	//dictionary up for us (consumes one reference))
	wxVERIFY((pDictionary = IOServiceMatching(kIOHIDDeviceKey)) != NULL );

	//Here we'll filter down the services to what we want
	if (nType != -1)
	{
		CFNumberRef pType = CFNumberCreate(kCFAllocatorDefault,
									kCFNumberIntType, &nType);
		CFDictionarySetValue(pDictionary, CFSTR(kIOHIDPrimaryUsageKey), pType);
		CFRelease(pType);
	}
	if (nClass != -1)
	{
		CFNumberRef pClass = CFNumberCreate(kCFAllocatorDefault,
									kCFNumberIntType, &nClass);
		CFDictionarySetValue(pDictionary, CFSTR(kIOHIDPrimaryUsagePageKey), pClass);
		CFRelease(pClass);
	}

	//Now get the maching services
	io_iterator_t pIterator;
	wxIOCHECK(IOServiceGetMatchingServices(m_pPort, pDictionary, &pIterator), "No Matching HID Services");
	wxASSERT_MSG(pIterator != 0, wxT("No devices found!"));

	//Now we iterate through them
	io_object_t pObject;
	while ( (pObject = IOIteratorNext(pIterator)) != 0)
	{
        if(--nDev != 0)
            continue;
            
		wxVERIFY(IORegistryEntryCreateCFProperties(pObject, &pDictionary,
											kCFAllocatorDefault, kNilOptions) == KERN_SUCCESS);

		//Just for sanity :)
		wxASSERT(CFGetTypeID(CFDictionaryGetValue(pDictionary, CFSTR(kIOHIDProductKey))) == CFStringGetTypeID());
			
/*
        kIOHIDTransportKey;
        kIOHIDVendorIDKey;
        kIOHIDProductIDKey;
        kIOHIDVersionNumberKey;
        kIOHIDManufacturerKey;
        kIOHIDSerialNumberKey;
        if !kIOHIDLocationIDKey
            kUSBDevicePropertyLocationID
        kIOHIDPrimaryUsageKey
kIOHIDPrimaryUsagePageKey
idProduct
idVendor
USB Product Name
*/
		//Get [product] name
		m_szProductName = wxMacCFStringHolder( (CFStringRef) CFDictionaryGetValue(pDictionary, CFSTR(kIOHIDProductKey)), false ).AsString();
        
        CFNumberRef nref = (CFNumberRef) CFDictionaryGetValue(pDictionary, CFSTR(kIOHIDProductIDKey));
        
        if (nref)
        CFNumberGetValue(
				nref,	
				kCFNumberIntType,
                &m_nProductId
				);

        nref = (CFNumberRef) CFDictionaryGetValue(pDictionary, CFSTR(kIOHIDVendorIDKey));
        if (nref)
	CFNumberGetValue(
				nref,	
				kCFNumberIntType,
                &m_nManufacturerId
				);

		//Create the interface (good grief - long function names!)
		SInt32 nScore;
		IOCFPlugInInterface** ppPlugin;
		wxIOCHECK(IOCreatePlugInInterfaceForService(pObject, kIOHIDDeviceUserClientTypeID,
											kIOCFPlugInInterfaceID, &ppPlugin, &nScore), "");
											   
		//Now, the final thing we can check before we fall back to asserts
		//(because the dtor only checks if the device is ok, so if anything
		//fails from now on the dtor will delete the device anyway, so we can't break from this).
			
		//Get the HID interface from the plugin to the mach port
		wxSCHECK((*ppPlugin)->QueryInterface(ppPlugin,
							CFUUIDGetUUIDBytes(kIOHIDDeviceInterfaceID), (void**) &m_ppDevice), "");
							
		//release the plugin
		(*ppPlugin)->Release(ppPlugin);
		
		//open the HID interface...
		wxVERIFY((*m_ppDevice)->open(m_ppDevice, 0) == S_OK);
		
		//
		//Now the hard part - in order to scan things we need "cookies" -
		//
		wxCFArray CookieArray = CFDictionaryGetValue(pDictionary, CFSTR(kIOHIDElementKey));
		BuildCookies(CookieArray);

		//cleanup
		CFRelease(pDictionary);
		IOObjectRelease(pObject);
		break;
	}
	//iterator cleanup
	IOObjectRelease(pIterator);
		
	return true;
}//end Create()
Beispiel #9
0
static void* handleIPCMessage (void* aMsgParam, CFIndex aMessageSize, CFAllocatorRef anAllocator, void* aMachPort)
{
    SystemStarterIPCMessage*     aMessage = (SystemStarterIPCMessage*) aMsgParam;
    SystemStarterIPCMessage*     aReplyMessage = NULL;
    
    CFDataRef aResult = NULL;
    CFDataRef aData = NULL;

    if (aMessage->aHeader.msgh_bits & MACH_MSGH_BITS_COMPLEX)
      {
        warning(CFSTR("Ignoring out-of-line IPC message.\n"));
        return NULL;
      }
    else
      {
        mach_msg_security_trailer_t* aSecurityTrailer = (mach_msg_security_trailer_t*)
        ((uint8_t*)aMessage + round_msg(sizeof(SystemStarterIPCMessage) + aMessage->aByteLength));

        /* CFRunLoop includes the format 0 message trailer with the passed message. */
        if (aSecurityTrailer->msgh_trailer_type == MACH_MSG_TRAILER_FORMAT_0 &&
            aSecurityTrailer->msgh_sender.val[0] != 0)
          {
            warning(CFSTR("Ignoring IPC message sent from uid %d\n."), aSecurityTrailer->msgh_sender.val[0]);
            return NULL;
          }
      }

    if (aMessage->aProtocol != kIPCProtocolVersion)
      {
        warning(CFSTR("Unsupported IPC protocol version number: %d.  Message ignored.\n"), aMessage->aProtocol);
        return NULL;
      }

    aData = CFDataCreateWithBytesNoCopy(NULL,
                                        (uint8_t*)aMessage + sizeof(SystemStarterIPCMessage),
                                        aMessage->aByteLength,
                                        kCFAllocatorNull);
    /*
     * Dispatch the IPC message.
     */
    if (aData)
      {
        StartupContext	aStartupContext = NULL;
        CFStringRef	anErrorString   = NULL;
        CFDictionaryRef	anIPCMessage    = (CFDictionaryRef) CFPropertyListCreateFromXMLData(NULL, aData, kCFPropertyListImmutable, &anErrorString);
        
        if (gDebugFlag == 2) debug(CFSTR("\nIPC message = %@\n"), anIPCMessage);

        if (aMachPort)
          {
            CFMachPortContext aMachPortContext;
            CFMachPortGetContext((CFMachPortRef)aMachPort, &aMachPortContext);
            aStartupContext = (StartupContext)aMachPortContext.info;
          }
        
        if (anIPCMessage && CFGetTypeID(anIPCMessage) == CFDictionaryGetTypeID())
          {
            /* switch on the type of the IPC message */
            CFStringRef anIPCMessageType = CFDictionaryGetValue(anIPCMessage, kIPCMessageKey);
            if (anIPCMessageType && CFGetTypeID(anIPCMessageType) == CFStringGetTypeID())
              {
                if (CFEqual(anIPCMessageType, kIPCConsoleMessage))
                  {
                    consoleMessage(aStartupContext, anIPCMessage);
                  }
                else if (CFEqual(anIPCMessageType, kIPCStatusMessage))
                  {
                    statusMessage(aStartupContext, anIPCMessage);
                  }
                else if (CFEqual(anIPCMessageType, kIPCQueryMessage))
                  {
                    aResult = queryConfigSetting(aStartupContext, anIPCMessage);
                  }
                else if (CFEqual(anIPCMessageType, kIPCLoadDisplayBundleMessage))
                  {
                    loadDisplayBundle(aStartupContext, anIPCMessage);
                  }
                else if (CFEqual(anIPCMessageType, kIPCUnloadDisplayBundleMessage))
                  {
                    unloadDisplayBundle(aStartupContext, anIPCMessage);
                  }
              }
          }
        else
          {
            error(CFSTR("Unable to parse IPC message: %@\n"), anErrorString);
          }
        CFRelease(aData);
      }
    else
      {
        error(CFSTR("Out of memory.  Could not allocate space for IPC message.\n"));
      }

    /*
     * Generate a Mach message for the result data.
     */
    if (!aResult) aResult = CFDataCreateWithBytesNoCopy(NULL, "", 1, kCFAllocatorNull);
    if (aResult)
    {
        CFIndex aDataSize = CFDataGetLength(aResult);
        CFIndex aReplyMessageSize = round_msg(sizeof(SystemStarterIPCMessage) + aDataSize + 3);
        aReplyMessage = CFAllocatorAllocate(kCFAllocatorSystemDefault, aReplyMessageSize, 0);
        if (aReplyMessage)
          {
            aReplyMessage->aHeader.msgh_id = -1 * (SInt32)aMessage->aHeader.msgh_id;
            aReplyMessage->aHeader.msgh_size = aReplyMessageSize;
            aReplyMessage->aHeader.msgh_remote_port = aMessage->aHeader.msgh_remote_port;
            aReplyMessage->aHeader.msgh_local_port = MACH_PORT_NULL;
            aReplyMessage->aHeader.msgh_reserved = 0;
            aReplyMessage->aHeader.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE, 0);
            aReplyMessage->aBody.msgh_descriptor_count = 0;
            aReplyMessage->aProtocol = kIPCProtocolVersion;
            aReplyMessage->aByteLength = CFDataGetLength(aResult);
            memmove((uint8_t*)aReplyMessage + sizeof(SystemStarterIPCMessage),
                    CFDataGetBytePtr(aResult),
                    CFDataGetLength(aResult));
          }
        CFRelease(aResult);
    }
    if (!aReplyMessage)
      {
        error(CFSTR("Out of memory.  Could not allocate IPC result.\n"));
      }
    return aReplyMessage;
}
void propertyListExample (void) {
    CFMutableDictionaryRef dict;
    CFNumberRef num;
    CFArrayRef array;
    CFDataRef data;
    #define NumKids 2
    CFStringRef kidsNames[] = { CFSTR ("John"), CFSTR ("Kyra") };
    #define NumPets 0
    int yearOfBirth = 1965;
    #define NumBytesInPic 10
    const unsigned char pic[ NumBytesInPic ] = { 0x3c, 0x42, 0x81, 0xa5, 0x81, 0xa5, 0x99, 0x81, 0x42, 0x3c };
    CFDataRef xmlPropertyListData;
    CFStringRef xmlAsString;

    // Create and populate a pretty standard mutable dictionary: CFString keys, CF type values.
    // To be written out as a "propertyList", the tree of CF types can contain only:
    //   CFDictionary, CFArray, CFString, CFData, CFNumber, and CFDate.
    // In addition, the keys of the dictionaries should be CFStrings.

    dict = CFDictionaryCreateMutable (NULL, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks );

    CFDictionarySetValue (dict, CFSTR ("Name"), CFSTR ("John Doe"));

    CFDictionarySetValue (dict, CFSTR ("City of Birth"), CFSTR ("Springfield"));

    num = CFNumberCreate (NULL, kCFNumberIntType, &yearOfBirth);
    CFDictionarySetValue (dict, CFSTR ("Year Of Birth"), num);
    CFRelease (num);

    array = CFArrayCreate (NULL, (const void **)kidsNames, NumKids, &kCFTypeArrayCallBacks); 
    CFDictionarySetValue (dict, CFSTR ("Kids Names"), array);
    CFRelease (array);

    array = CFArrayCreate (NULL, NULL, 0, &kCFTypeArrayCallBacks);
    CFDictionarySetValue (dict, CFSTR ("Pets Names"), array );
    CFRelease (array);

    data = CFDataCreate (NULL, pic, NumBytesInPic);
    CFDictionarySetValue (dict, CFSTR ("Picture"), data);
    CFRelease (data);

    // We now have a dictionary which contains everything we want to know about
    // John Doe; let's show it first:
    show (CFSTR ("John Doe info dictionary:\n%@"), dict);

    // Now create a "property list", which is a flattened, XML version of the
    // dictionary:
    xmlPropertyListData = CFPropertyListCreateXMLData (NULL, dict);

   // The return value is a CFData containing the XML file; show the data

    show (CFSTR ("Shown as XML property list (bytes):\n%@"), xmlPropertyListData);

    // Given CFDatas are shown as ASCII versions of their hex contents, we can also
    // attempt to show the contents of the XML, assuming it was encoded in UTF8
    // (This is the case for XML property lists generated by CoreFoundation currently)

    xmlAsString = CFStringCreateFromExternalRepresentation (NULL, xmlPropertyListData, kCFStringEncodingUTF8);

    show (CFSTR ("The XML property list contents:\n%@"), xmlAsString);

    writePropertyListToFile (xmlPropertyListData);

    CFRelease (dict);
    CFRelease (xmlAsString);
    CFRelease (xmlPropertyListData);

    CFStringRef name = CFSTR("Brent");
    if (CFBundleRef bundle = CFBundleGetMainBundle ())
       if (CFTypeRef bundleExecutable = CFBundleGetValueForInfoDictionaryKey(bundle, kCFBundleExecutableKey))
          if (CFGetTypeID(bundleExecutable) == CFStringGetTypeID())
             name = reinterpret_cast<CFStringRef>(bundleExecutable);

    int value = 1;
    CFNumberRef numRef = CFNumberCreate(0, kCFNumberSInt8Type, &value);
    show (CFSTR ("The number was: %@"), numRef);
    CFRelease (numRef);
}
static void _CFUserNotificationAddToDictionary(const void *key, const void *value, void *context) {
    if (CFGetTypeID(key) == CFStringGetTypeID()) CFDictionarySetValue((CFMutableDictionaryRef)context, key, value);
}
launch_data_t GTMLaunchDataCreateFromCFType(CFTypeRef cf_type_ref,
                                            CFErrorRef *error) {
  launch_data_t result = NULL;
  CFErrorRef local_error = NULL;
  if (cf_type_ref == NULL) {
    local_error = GTMCFLaunchCreateUnlocalizedError(EINVAL,
                                                    CFSTR("NULL CFType"));
    goto exit;
  }

  CFTypeID cf_type = CFGetTypeID(cf_type_ref);
  if (cf_type == CFStringGetTypeID()) {
    CFIndex length = CFStringGetLength(cf_type_ref);
    CFIndex max_length
      = CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8) + 1;
    char *buffer = calloc(max_length, sizeof(char));
    size_t buffer_size = max_length * sizeof(char);
    if (buffer) {
      if (CFStringGetCString(cf_type_ref,
                             buffer,
                             buffer_size,
                             kCFStringEncodingUTF8)) {
        result = launch_data_alloc(LAUNCH_DATA_STRING);
        launch_data_set_string(result, buffer);
      } else {
        local_error
          = GTMCFLaunchCreateUnlocalizedError(EINVAL,
                                              CFSTR("CFStringGetCString failed %@"),
                                              cf_type_ref);
      }
      free(buffer);
    } else {
      local_error = GTMCFLaunchCreateUnlocalizedError(ENOMEM,
                                                      CFSTR("calloc of %lu failed"),
                                                      (unsigned long)buffer_size);
    }
  } else if (cf_type == CFBooleanGetTypeID()) {
    result = launch_data_alloc(LAUNCH_DATA_BOOL);
    launch_data_set_bool(result, CFBooleanGetValue(cf_type_ref));
  } else if (cf_type == CFArrayGetTypeID()) {
    CFIndex count = CFArrayGetCount(cf_type_ref);
    result = launch_data_alloc(LAUNCH_DATA_ARRAY);
    for (CFIndex i = 0; i < count; i++) {
      CFTypeRef array_value = CFArrayGetValueAtIndex(cf_type_ref, i);
      if (array_value) {
        launch_data_t launch_value
          = GTMLaunchDataCreateFromCFType(array_value, &local_error);
        if (local_error) break;
        launch_data_array_set_index(result, launch_value, i);
      }
    }
  } else if (cf_type == CFDictionaryGetTypeID()) {
    result = launch_data_alloc(LAUNCH_DATA_DICTIONARY);
    GTMCFToLDictContext context = { result, &local_error };
    CFDictionaryApplyFunction(cf_type_ref,
                              GTMConvertCFDictEntryToLaunchDataDictEntry,
                              &context);
  } else if (cf_type == CFDataGetTypeID()) {
    result = launch_data_alloc(LAUNCH_DATA_OPAQUE);
    launch_data_set_opaque(result,
                           CFDataGetBytePtr(cf_type_ref),
                           CFDataGetLength(cf_type_ref));
  } else if (cf_type == CFNumberGetTypeID()) {
    CFNumberType cf_number_type = CFNumberGetType(cf_type_ref);
    switch (cf_number_type) {
      case kCFNumberSInt8Type:
      case kCFNumberSInt16Type:
      case kCFNumberSInt32Type:
      case kCFNumberSInt64Type:
      case kCFNumberCharType:
      case kCFNumberShortType:
      case kCFNumberIntType:
      case kCFNumberLongType:
      case kCFNumberLongLongType:
      case kCFNumberCFIndexType:
      case kCFNumberNSIntegerType:{
        long long value;
        if (CFNumberGetValue(cf_type_ref, kCFNumberLongLongType, &value)) {
          result = launch_data_alloc(LAUNCH_DATA_INTEGER);
          launch_data_set_integer(result, value);
        } else {
          local_error
            = GTMCFLaunchCreateUnlocalizedError(EINVAL,
                                                CFSTR("Unknown to convert: %@"),
                                                cf_type_ref);
        }
        break;
      }

      case kCFNumberFloat32Type:
      case kCFNumberFloat64Type:
      case kCFNumberFloatType:
      case kCFNumberDoubleType:
      case kCFNumberCGFloatType: {
        double value;
        if (CFNumberGetValue(cf_type_ref, kCFNumberDoubleType, &value)) {
          result = launch_data_alloc(LAUNCH_DATA_REAL);
          launch_data_set_real(result, value);
        } else {
          local_error
            = GTMCFLaunchCreateUnlocalizedError(EINVAL,
                                                CFSTR("Unknown to convert: %@"),
                                                cf_type_ref);
        }
        break;
      }

      default:
        local_error
          = GTMCFLaunchCreateUnlocalizedError(EINVAL,
                                              CFSTR("Unknown CFNumberType %lld"),
                                              (long long)cf_number_type);
        break;
    }
  } else {
    local_error
      = GTMCFLaunchCreateUnlocalizedError(EINVAL,
                                          CFSTR("Unknown CFTypeID %lu"),
                                          (unsigned long)cf_type);
  }

exit:
  if (error) {
    *error = local_error;
  } else if (local_error) {
#ifdef DEBUG
    CFShow(local_error);
#endif //  DEBUG
    CFRelease(local_error);
  }
  return result;
}
Beispiel #13
0
void InitJoystick()
{
   mach_port_t masterPort = NULL;
	io_iterator_t hidObjectIterator = NULL;

	IOReturn result = IOMasterPort (bootstrap_port, &masterPort);
   if(result != kIOReturnSuccess)
      return;
   
   CFMutableDictionaryRef hidMatchDictionary = IOServiceMatching (kIOHIDDeviceKey);
   if(!hidMatchDictionary)
      return;
	result = IOServiceGetMatchingServices (masterPort, hidMatchDictionary, &hidObjectIterator);
   if(result != kIOReturnSuccess)
      return;

   // find the first joystick/gamepad on the USB
   for(;;)
   {
      IOHIDDeviceInterface **device;
      io_object_t ioHIDDeviceObject = IOIteratorNext(hidObjectIterator);
      if(!ioHIDDeviceObject)
         break;

      CFMutableDictionaryRef hidProperties = 0;
      long kresult = IORegistryEntryCreateCFProperties(ioHIDDeviceObject, &hidProperties, kCFAllocatorDefault, kNilOptions);
      if(kresult == KERN_SUCCESS && hidProperties)
      {
			CFTypeRef refCF = 0;
			refCF = CFDictionaryGetValue (hidProperties, CFSTR(kIOHIDProductKey));
			
			if(CFGetTypeID(refCF) == CFStringGetTypeID())
			{
				CFIndex bufferSize = CFStringGetLength (refCF) + 1;
				char * buffer = (char *)malloc (bufferSize);
				if (buffer)
				{
					if (CFStringGetCString (refCF, buffer, bufferSize, CFStringGetSystemEncoding ()))
						strncpy(gJoystickName, buffer, MaxJoystickNameLen);
					free(buffer);
				}
			}
			refCF = CFDictionaryGetValue (hidProperties, CFSTR(kIOHIDPrimaryUsagePageKey));
         long usage, usagePage;
			CFNumberGetValue (refCF, kCFNumberLongType, &usagePage);
         refCF = CFDictionaryGetValue (hidProperties, CFSTR(kIOHIDPrimaryUsageKey));
			CFNumberGetValue (refCF, kCFNumberLongType, &usage);

   		if ( (usagePage == kHIDPage_GenericDesktop) &&
		     ((usage == kHIDUsage_GD_Joystick ||
		      usage == kHIDUsage_GD_GamePad)) )
         {
	         CFTypeRef refElementTop = CFDictionaryGetValue (hidProperties, CFSTR(kIOHIDElementKey));
	         if (refElementTop)
            {
	            CFTypeID type = CFGetTypeID (refElementTop);
	            if (type == CFArrayGetTypeID()) /* if element is an array */
	            {
		            CFRange range = {0, CFArrayGetCount (refElementTop)};
		            /* CountElementsCFArrayHandler called for each array member */
		            CFArrayApplyFunction (refElementTop, range, HIDGetElementsCFArrayHandler, NULL);

                  IOCFPlugInInterface ** ppPlugInInterface = NULL;
					S32 score;
		            IOReturn result = IOCreatePlugInInterfaceForService (ioHIDDeviceObject, kIOHIDDeviceUserClientTypeID,
													            kIOCFPlugInInterfaceID, &ppPlugInInterface, &score);
		            if (result == kIOReturnSuccess)
		            {
			            // Call a method of the intermediate plug-in to create the device interface
			            (*ppPlugInInterface)->QueryInterface (ppPlugInInterface,
								            CFUUIDGetUUIDBytes (kIOHIDDeviceInterfaceID), (void *) &device);
                     if(device)
                     {
                        result = (*device)->open(device, 0);
                        gController.device = device;
                        gJoystickInit = true;
                     }
                     (*ppPlugInInterface)->Release (ppPlugInInterface);
                  }
               }
            }
         }
         CFRelease(hidProperties);
      }
      IOObjectRelease(ioHIDDeviceObject);
      if(gJoystickInit)
         break;
   }
	IOObjectRelease (hidObjectIterator); /* release the iterator */
}
/*
 * Display a Trust Settings array as obtained from
 * SecTrustSettingsCopyTrustSettings().
 */
static int displayTrustSettings(
	CFArrayRef	trustSettings)
{
	/* must always be there though it may be empty */
	if(trustSettings == NULL) {
		fprintf(stderr, "***displayTrustSettings: missing trust settings array");
		return -1;
	}
	if(CFGetTypeID(trustSettings) != CFArrayGetTypeID()) {
		fprintf(stderr, "***displayTrustSettings: malformed trust settings array");
		return -1;
	}

	int ourRtn = 0;
	CFIndex numUseConstraints = CFArrayGetCount(trustSettings);
	indentIncr();
	indent(); printf("Number of trust settings : %ld\n", (long)numUseConstraints);
	OSStatus ortn;
	SecPolicyRef certPolicy;
	SecTrustedApplicationRef certApp;
	CFDictionaryRef ucDict;
	CFStringRef policyStr;
	CFNumberRef cfNum;
	CFIndex ucDex;

	/* grind thru the trust settings dictionaries */
	for(ucDex=0; ucDex<numUseConstraints; ucDex++) {
		indent(); printf("Trust Setting %ld:\n", (long)ucDex);
		indentIncr();

		ucDict = (CFDictionaryRef)CFArrayGetValueAtIndex(trustSettings, ucDex);
		if(CFGetTypeID(ucDict) != CFDictionaryGetTypeID()) {
			fprintf(stderr, "***displayTrustSettings: malformed usage constraints dictionary");
			ourRtn = -1;
			goto nextAp;
		}

		/* policy - optional */
		certPolicy = (SecPolicyRef)CFDictionaryGetValue(ucDict, kSecTrustSettingsPolicy);
		if(certPolicy != NULL) {
			if(CFGetTypeID(certPolicy) != SecPolicyGetTypeID()) {
				fprintf(stderr, "***displayTrustSettings: malformed certPolicy");
				ourRtn = -1;
				goto nextAp;
			}
			CSSM_OID policyOid;
			ortn = SecPolicyGetOID(certPolicy, &policyOid);
			if(ortn) {
				cssmPerror("SecPolicyGetOID", ortn);
				ourRtn = -1;
				goto nextAp;
			}
			indent(); printf("Policy OID            : %s\n",
					oidToOidString(&policyOid));
		}

		/* app - optional  */
		certApp = (SecTrustedApplicationRef)CFDictionaryGetValue(ucDict,
			kSecTrustSettingsApplication);
		if(certApp != NULL) {
			if(CFGetTypeID(certApp) != SecTrustedApplicationGetTypeID()) {
				fprintf(stderr, "***displayTrustSettings: malformed certApp");
				ourRtn = -1;
				goto nextAp;
			}
			CFDataRef appPath = NULL;
			ortn = SecTrustedApplicationCopyData(certApp, &appPath);
			if(ortn) {
				cssmPerror("SecTrustedApplicationCopyData", ortn);
				ourRtn = -1;
				goto nextAp;
			}
			indent(); printf("Application           : %s", CFDataGetBytePtr(appPath));
			printf("\n");
			CFRelease(appPath);
		}

		/* policy string */
		policyStr = (CFStringRef)CFDictionaryGetValue(ucDict, kSecTrustSettingsPolicyString);
		if(policyStr != NULL) {
			if(CFGetTypeID(policyStr) != CFStringGetTypeID()) {
				fprintf(stderr, "***displayTrustSettings: malformed policyStr");
				ourRtn = -1;
				goto nextAp;
			}
			indent(); printf("Policy String         : ");
			printCfStr(policyStr); printf("\n");
		}

		/* Allowed error */
		cfNum = (CFNumberRef)CFDictionaryGetValue(ucDict, kSecTrustSettingsAllowedError);
		if(cfNum != NULL) {
			if(CFGetTypeID(cfNum) != CFNumberGetTypeID()) {
				fprintf(stderr, "***displayTrustSettings: malformed allowedError");
				ourRtn = -1;
				goto nextAp;
			}
			indent(); printf("Allowed Error         : ");
			printCssmErr(cfNum); printf("\n");
		}

		/* ResultType */
		cfNum = (CFNumberRef)CFDictionaryGetValue(ucDict, kSecTrustSettingsResult);
		if(cfNum != NULL) {
			if(CFGetTypeID(cfNum) != CFNumberGetTypeID()) {
				fprintf(stderr, "***displayTrustSettings: malformed ResultType");
				ourRtn = -1;
				goto nextAp;
			}
			indent(); printf("Result Type           : ");
			printResultType(cfNum); printf("\n");
		}

		/* key usage */
		cfNum = (CFNumberRef)CFDictionaryGetValue(ucDict, kSecTrustSettingsKeyUsage);
		if(cfNum != NULL) {
			if(CFGetTypeID(cfNum) != CFNumberGetTypeID()) {
				fprintf(stderr, "***displayTrustSettings: malformed keyUsage");
				ourRtn = -1;
				goto nextAp;
			}
			indent(); printf("Key Usage             : ");
			printKeyUsage(cfNum); printf("\n");
		}

	nextAp:
		indentDecr();
	}
	indentDecr();
	return ourRtn;
}
char *
_mongoc_secure_transport_RFC2253_from_cert (SecCertificateRef cert)
{
   CFTypeRef value;
   bson_string_t *retval;
   CFTypeRef subject_name;
   CFDictionaryRef cert_dict;

   cert_dict = SecCertificateCopyValues (cert, NULL, NULL);
   if (!cert_dict) {
      return NULL;
   }

   subject_name = CFDictionaryGetValue (cert_dict, kSecOIDX509V1SubjectName);
   if (!subject_name) {
      CFRelease (cert_dict);
      return NULL;
   }

   subject_name = CFDictionaryGetValue (subject_name, kSecPropertyKeyValue);
   if (!subject_name) {
      CFRelease (cert_dict);
      return NULL;
   }

   retval = bson_string_new ("");;

   value = _mongoc_secure_transport_dict_get (subject_name, kSecOIDCommonName);
   _bson_append_cftyperef (retval, "CN=", value);

   value = _mongoc_secure_transport_dict_get (subject_name, kSecOIDOrganizationalUnitName);
   if (value) {
      /* Can be either one unit name, or array of unit names */
      if (CFGetTypeID(value) == CFStringGetTypeID()) {
         _bson_append_cftyperef (retval, ",OU=", value);
      } else if (CFGetTypeID(value) == CFArrayGetTypeID()) {
         CFIndex len = CFArrayGetCount(value);

         if (len > 0) {
            _bson_append_cftyperef (retval, ",OU=", CFArrayGetValueAtIndex(value, 0));
         }
         if (len > 1) {
            _bson_append_cftyperef (retval, ",", CFArrayGetValueAtIndex(value, 1));
         }
         if (len > 2) {
            _bson_append_cftyperef (retval, ",", CFArrayGetValueAtIndex(value, 2));
         }
      }
   }

   value = _mongoc_secure_transport_dict_get (subject_name, kSecOIDOrganizationName);
   _bson_append_cftyperef (retval, ",O=", value);

   value = _mongoc_secure_transport_dict_get (subject_name, kSecOIDLocalityName);
   _bson_append_cftyperef (retval, ",L=", value);

   value = _mongoc_secure_transport_dict_get (subject_name, kSecOIDStateProvinceName);
   _bson_append_cftyperef (retval, ",ST=", value);

   value = _mongoc_secure_transport_dict_get (subject_name, kSecOIDCountryName);
   _bson_append_cftyperef (retval, ",C=", value);

   /* This seems rarely used */
   value = _mongoc_secure_transport_dict_get (subject_name, kSecOIDStreetAddress);
   _bson_append_cftyperef (retval, ",STREET", value);

   CFRelease (cert_dict);
   return bson_string_free (retval, false);
}
Beispiel #16
0
static void MergeStatusCodes(CFTypeRef key, CFTypeRef value, void* context)
{
    // Windows (and therefore .NET) certificate status codes are defined on an int32_t.
    // The top 32 bits will be used to convey error information, the bottom 32 bits
    // as a data aggregator for the status codes.
    uint64_t* pStatus = (uint64_t*)context;

    if (key == NULL)
    {
        return;
    }

    // If any error code was already set.
    if (*pStatus > INT_MAX)
    {
        return;
    }

    if (CFGetTypeID(key) != CFStringGetTypeID())
    {
        *pStatus |= PAL_X509ChainErrorUnknownValueType;
        return;
    }

    (void)value;
    CFStringRef keyString = (CFStringRef)key;

    if (CFEqual(keyString, CFSTR("NotValidBefore")) || CFEqual(keyString, CFSTR("ValidLeaf")) ||
        CFEqual(keyString, CFSTR("ValidIntermediates")) || CFEqual(keyString, CFSTR("ValidRoot")) ||
        CFEqual(keyString, CFSTR("TemporalValidity")))
        *pStatus |= PAL_X509ChainNotTimeValid;
    else if (CFEqual(keyString, CFSTR("Revocation")))
        *pStatus |= PAL_X509ChainRevoked;
    else if (CFEqual(keyString, CFSTR("KeyUsage")))
        *pStatus |= PAL_X509ChainNotValidForUsage;
    else if (CFEqual(keyString, CFSTR("AnchorTrusted")))
        *pStatus |= PAL_X509ChainUntrustedRoot;
    else if (CFEqual(keyString, CFSTR("BasicConstraints")))
        *pStatus |= PAL_X509ChainInvalidBasicConstraints;
    else if (CFEqual(keyString, CFSTR("UsageConstraints")))
        *pStatus |= PAL_X509ChainExplicitDistrust;
    else if (CFEqual(keyString, CFSTR("RevocationResponseRequired")))
        *pStatus |= PAL_X509ChainRevocationStatusUnknown;
    else if (CFEqual(keyString, CFSTR("MissingIntermediate")))
        *pStatus |= PAL_X509ChainPartialChain;
    else if (CFEqual(keyString, CFSTR("WeakLeaf")) || CFEqual(keyString, CFSTR("WeakIntermediates")) ||
             CFEqual(keyString, CFSTR("WeakRoot")) || CFEqual(keyString, CFSTR("WeakKeySize")))
    {
        // Because we won't report this out of a chain built by .NET on Windows,
        // don't report it here.
        //
        // (On Windows CERT_CHAIN_PARA.pStrongSignPara is NULL, so "strongness" checks
        // are not performed).
    }
    else if (CFEqual(keyString, CFSTR("StatusCodes")))
    {
        // 10.13 added a StatusCodes value which may be a numeric rehashing of the string data.
        // It doesn't represent a new error code, and we're still getting the old ones, so
        // just ignore it for now.
    }
    else if (CFEqual(keyString, CFSTR("NonEmptySubject")))
    {
        // Not a "problem" that we report.
    }
    else
    {
#ifdef DEBUGGING_UNKNOWN_VALUE
        printf("%s\n", CFStringGetCStringPtr(keyString, CFStringGetSystemEncoding()));
#endif
        *pStatus |= PAL_X509ChainErrorUnknownValue;
    }
}