bool OggSpeexMetadata::ReadMetadata(CFErrorRef *error)
{
	// Start from scratch
	CFDictionaryRemoveAllValues(mMetadata);
	CFDictionaryRemoveAllValues(mChangedMetadata);
	
	UInt8 buf [PATH_MAX];
	if(!CFURLGetFileSystemRepresentation(mURL, false, buf, PATH_MAX))
		return false;
	
	// TODO: Use unique_ptr once the switch to C++11 STL is made
	std::auto_ptr<TagLib::FileStream> stream(new TagLib::FileStream(reinterpret_cast<const char *>(buf), true));
	if(!stream->isOpen()) {
		if(error) {
			CFStringRef description = CFCopyLocalizedString(CFSTR("The file “%@” could not be opened for reading."), "");
			CFStringRef failureReason = CFCopyLocalizedString(CFSTR("Input/output error"), "");
			CFStringRef recoverySuggestion = CFCopyLocalizedString(CFSTR("The file may have been renamed, moved, deleted, or you may not have appropriate permissions."), "");

			*error = CreateErrorForURL(AudioMetadataErrorDomain, AudioMetadataInputOutputError, description, mURL, failureReason, recoverySuggestion);

			CFRelease(description), description = nullptr;
			CFRelease(failureReason), failureReason = nullptr;
			CFRelease(recoverySuggestion), recoverySuggestion = nullptr;
		}

		return false;
	}

	TagLib::Ogg::Speex::File file(stream.get());
	if(!file.isValid()) {
		if(nullptr != error) {
			CFStringRef description = CFCopyLocalizedString(CFSTR("The file “%@” is not a valid Ogg Speex file."), "");
			CFStringRef failureReason = CFCopyLocalizedString(CFSTR("Not an Ogg Speex file"), "");
			CFStringRef recoverySuggestion = CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), "");
			
			*error = CreateErrorForURL(AudioMetadataErrorDomain, AudioMetadataInputOutputError, description, mURL, failureReason, recoverySuggestion);
			
			CFRelease(description), description = nullptr;
			CFRelease(failureReason), failureReason = nullptr;
			CFRelease(recoverySuggestion), recoverySuggestion = nullptr;
		}
		
		return false;
	}
	
	CFDictionarySetValue(mMetadata, kPropertiesFormatNameKey, CFSTR("Ogg Speex"));
	
	if(file.audioProperties())
		AddAudioPropertiesToDictionary(mMetadata, file.audioProperties());
	
	if(file.tag()) {
		std::vector<AttachedPicture *> pictures;
		AddXiphCommentToDictionary(mMetadata, pictures, file.tag());
		for(auto picture : pictures)
			AddSavedPicture(picture);
	}
	
	return true;
}
bool WavPackMetadata::ReadMetadata(CFErrorRef *error)
{
	// Start from scratch
	CFDictionaryRemoveAllValues(mMetadata);
	CFDictionaryRemoveAllValues(mChangedMetadata);

	UInt8 buf [PATH_MAX];
	if(!CFURLGetFileSystemRepresentation(mURL, FALSE, buf, PATH_MAX))
		return false;

	auto stream = new TagLib::FileStream(reinterpret_cast<const char *>(buf), true);
	TagLib::WavPack::File file(stream);

	if(!file.isValid()) {
		if(nullptr != error) {
			CFStringRef description = CFCopyLocalizedString(CFSTR("The file “%@” is not a valid WavPack file."), "");
			CFStringRef failureReason = CFCopyLocalizedString(CFSTR("Not a WavPack file"), "");
			CFStringRef recoverySuggestion = CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), "");
			
			*error = CreateErrorForURL(AudioMetadataErrorDomain, AudioMetadataInputOutputError, description, mURL, failureReason, recoverySuggestion);
			
			CFRelease(description), description = nullptr;
			CFRelease(failureReason), failureReason = nullptr;
			CFRelease(recoverySuggestion), recoverySuggestion = nullptr;
		}

		return false;
	}
	
	CFDictionarySetValue(mMetadata, kPropertiesFormatNameKey, CFSTR("WavPack"));
	
	if(file.audioProperties()) {
		auto properties = file.audioProperties();
		AddAudioPropertiesToDictionary(mMetadata, properties);
		
		if(properties->bitsPerSample())
			AddIntToDictionary(mMetadata, kPropertiesBitsPerChannelKey, properties->bitsPerSample());
		if(properties->sampleFrames())
			AddIntToDictionary(mMetadata, kPropertiesTotalFramesKey, properties->sampleFrames());
	}
	
	if(file.ID3v1Tag())
		AddID3v1TagToDictionary(mMetadata, file.ID3v1Tag());

	if(file.APETag()) {
		std::vector<AttachedPicture *> pictures;
		AddAPETagToDictionary(mMetadata, pictures, file.APETag());
		for(auto picture : pictures)
			AddSavedPicture(picture);
	}

	return true;
}
示例#3
0
void SFB::Audio::Metadata::MergeChangedMetadataIntoMetadata()
{
	CFIndex count = CFDictionaryGetCount(mChangedMetadata);
	
	CFTypeRef *keys = (CFTypeRef *)malloc(sizeof(CFTypeRef) * (size_t)count);
	CFTypeRef *values = (CFTypeRef *)malloc(sizeof(CFTypeRef) * (size_t)count);
	
	CFDictionaryGetKeysAndValues(mChangedMetadata, keys, values);
	
	for(CFIndex i = 0; i < count; ++i) {
		if(kCFNull == values[i])
			CFDictionaryRemoveValue(mMetadata, keys[i]);
		else
			CFDictionarySetValue(mMetadata, keys[i], values[i]);
	}
	
	free(keys), keys = nullptr;
	free(values), values = nullptr;
	
	CFDictionaryRemoveAllValues(mChangedMetadata);

	auto iter = std::begin(mPictures);
	while(iter != std::end(mPictures)) {
		auto picture = *iter;
		if(AttachedPicture::ChangeState::Removed == picture->mState)
			iter = mPictures.erase(iter);
		else {
			picture->MergeChangedMetadataIntoMetadata();
			picture->mState = AttachedPicture::ChangeState::Saved;
			++iter;
		}
	}
}
示例#4
0
void SFB::Audio::Metadata::RevertUnsavedChanges()
{
	CFDictionaryRemoveAllValues(mChangedMetadata);

	for(auto picture : mPictures) {
		if(AttachedPicture::ChangeState::Removed == picture->mState)
			picture->mState = AttachedPicture::ChangeState::Saved;
		picture->RevertUnsavedChanges();
	}
}
示例#5
0
void	CASettingsStorage::RemoveAllValues()
{
	//	make sure our cache is up to date
	RefreshSettings();
	
	//	remove the given key
	CFDictionaryRemoveAllValues(mSettingsCache);
	
	//	write the settings to the file
	SaveSettings();
}
示例#6
0
文件: gc.c 项目: prototype/MacRuby
void
rb_gc_call_finalizer_at_exit(void)
{
    if (__os_finalizers != NULL) {
	CFDictionaryApplyFunction((CFDictionaryRef)__os_finalizers,
    	    os_finalize_cb, NULL);
	CFDictionaryRemoveAllValues(__os_finalizers);
	CFRelease(__os_finalizers);
    }

    auto_collect(__auto_zone, AUTO_COLLECT_FULL_COLLECTION, NULL);
}
CarbonEventHandler::~CarbonEventHandler()
{
	if (mHandlers != NULL) {
		int count = CFDictionaryGetCount(mHandlers);
		EventHandlerRef *theHandlers = (EventHandlerRef*) malloc(count * sizeof(EventHandlerRef));
		CFDictionaryGetKeysAndValues(mHandlers, NULL, (const void **)theHandlers);
		
		for (int i = 0; i < count; i++)
			RemoveEventHandler(theHandlers[i]);
		CFDictionaryRemoveAllValues(mHandlers);
		CFRelease (mHandlers);
		free(theHandlers);
	}	
}
示例#8
0
void SFB::Audio::Metadata::RevertUnsavedChanges()
{
	CFDictionaryRemoveAllValues(mChangedMetadata);

	auto iter = std::begin(mPictures);
	while(iter != std::end(mPictures)) {
		auto picture = *iter;
		if(AttachedPicture::ChangeState::Removed == picture->mState) {
			picture->mState = AttachedPicture::ChangeState::Saved;
			picture->RevertUnsavedChanges();
		}
		else
			picture->RevertUnsavedChanges();
	}
}
示例#9
0
/* CF_EXPORT */ void
CFNetServiceBrowserInvalidate(CFNetServiceBrowserRef b) {

	__CFNetServiceBrowser* browser = (__CFNetServiceBrowser*)b;

	// Lock the browser
	__CFSpinLock(&(browser->_lock));

	// Release the user's context info if there is some and a release method
	if (browser->_client.info && browser->_client.release)
		browser->_client.release(browser->_client.info);

	// Cancel the outstanding trigger
	if (browser->_trigger) {

		// Remove the trigger from run loops and modes
		_CFTypeUnscheduleFromMultipleRunLoops(browser->_trigger, browser->_schedules);

		// Go ahead and invalidate the trigger
		_CFTypeInvalidate(browser->_trigger);

		// Release the browse now.
		CFRelease(browser->_trigger);
		browser->_trigger = NULL;
	}

	// Need to clean up the service discovery stuff if there is
	if (browser->_browse) {

		// Release the underlying service discovery reference
		DNSServiceRefDeallocate(browser->_browse);
		browser->_browse = NULL;

		// Dump all the lists of items.
		CFDictionaryRemoveAllValues(browser->_found);
		CFArrayRemoveAllValues(browser->_adds);
		CFArrayRemoveAllValues(browser->_removes);
	}

	// Zero out the callback and client context.
	browser->_callback = NULL;
	memset(&(browser->_client), 0, sizeof(browser->_client));

	// Unlock the browser.
	__CFSpinUnlock(&(browser->_lock));
}
示例#10
0
Boolean
SCPreferencesRemoveAllValues(SCPreferencesRef prefs)
{
	SCPreferencesPrivateRef	prefsPrivate	= (SCPreferencesPrivateRef)prefs;

	if (prefs == NULL) {
		/* sorry, you must provide a session */
		_SCErrorSet(kSCStatusNoPrefsSession);
		return FALSE;
	}

	__SCPreferencesAccess(prefs);

	CFDictionaryRemoveAllValues(prefsPrivate->prefs);
	prefsPrivate->changed  = TRUE;
	return TRUE;
}
示例#11
0
void SFB::Audio::AttachedPicture::MergeChangedMetadataIntoMetadata()
{
	CFIndex count = CFDictionaryGetCount(mChangedMetadata);

	CFTypeRef *keys = (CFTypeRef *)malloc(sizeof(CFTypeRef) * (size_t)count);
	CFTypeRef *values = (CFTypeRef *)malloc(sizeof(CFTypeRef) * (size_t)count);

	CFDictionaryGetKeysAndValues(mChangedMetadata, keys, values);

	for(CFIndex i = 0; i < count; ++i) {
		if(kCFNull == values[i])
			CFDictionaryRemoveValue(mMetadata, keys[i]);
		else
			CFDictionarySetValue(mMetadata, keys[i], values[i]);
	}

	free(keys), keys = nullptr;
	free(values), values = nullptr;

	CFDictionaryRemoveAllValues(mChangedMetadata);
}
bool MP3Metadata::ReadMetadata(CFErrorRef *error)
{
	// Start from scratch
	CFDictionaryRemoveAllValues(mMetadata);
	CFDictionaryRemoveAllValues(mChangedMetadata);
	
	UInt8 buf [PATH_MAX];
	if(!CFURLGetFileSystemRepresentation(mURL, false, buf, PATH_MAX))
		return false;
	
	auto stream = new TagLib::FileStream(reinterpret_cast<const char *>(buf), true);
	TagLib::MPEG::File file(stream, TagLib::ID3v2::FrameFactory::instance());
	
	if(!file.isValid()) {
		if(nullptr != error) {
			CFStringRef description = CFCopyLocalizedString(CFSTR("The file “%@” is not a valid MPEG file."), "");
			CFStringRef failureReason = CFCopyLocalizedString(CFSTR("Not an MPEG file"), "");
			CFStringRef recoverySuggestion = CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), "");
			
			*error = CreateErrorForURL(AudioMetadataErrorDomain, AudioMetadataInputOutputError, description, mURL, failureReason, recoverySuggestion);
			
			CFRelease(description), description = nullptr;
			CFRelease(failureReason), failureReason = nullptr;
			CFRelease(recoverySuggestion), recoverySuggestion = nullptr;
		}
		
		return false;
	}
	
	CFDictionarySetValue(mMetadata, kPropertiesFormatNameKey, CFSTR("MP3"));

	if(file.audioProperties()) {
		auto properties = file.audioProperties();
		AddAudioPropertiesToDictionary(mMetadata, properties);

		// TODO: Is this too much information?
#if 0
		switch(properties->version()) {
			case TagLib::MPEG::Header::Version1:
				switch(properties->layer()) {
					case 1:		CFDictionarySetValue(mMetadata, kPropertiesFormatNameKey, CFSTR("MPEG-1 Layer I"));		break;
					case 2:		CFDictionarySetValue(mMetadata, kPropertiesFormatNameKey, CFSTR("MPEG-1 Layer II"));	break;
					case 3:		CFDictionarySetValue(mMetadata, kPropertiesFormatNameKey, CFSTR("MPEG-1 Layer III"));	break;
				}
				break;
			case TagLib::MPEG::Header::Version2:
				switch(properties->layer()) {
					case 1:		CFDictionarySetValue(mMetadata, kPropertiesFormatNameKey, CFSTR("MPEG-2 Layer I"));		break;
					case 2:		CFDictionarySetValue(mMetadata, kPropertiesFormatNameKey, CFSTR("MPEG-2 Layer II"));	break;
					case 3:		CFDictionarySetValue(mMetadata, kPropertiesFormatNameKey, CFSTR("MPEG-2 Layer III"));	break;
				}
				break;
			case TagLib::MPEG::Header::Version2_5:
				switch(properties->layer()) {
					case 1:		CFDictionarySetValue(mMetadata, kPropertiesFormatNameKey, CFSTR("MPEG-2.5 Layer I"));	break;
					case 2:		CFDictionarySetValue(mMetadata, kPropertiesFormatNameKey, CFSTR("MPEG-2.5 Layer II"));	break;
					case 3:		CFDictionarySetValue(mMetadata, kPropertiesFormatNameKey, CFSTR("MPEG-2.5 Layer III"));	break;
				}
				break;
		}
#endif

		if(properties->xingHeader() && properties->xingHeader()->totalFrames())
			AddIntToDictionary(mMetadata, kPropertiesTotalFramesKey, properties->xingHeader()->totalFrames());
	}

	if(file.APETag()) {
		std::vector<AttachedPicture *> pictures;
		AddAPETagToDictionary(mMetadata, pictures, file.APETag());
		for(auto picture : pictures)
			AddSavedPicture(picture);
	}

	if(file.ID3v1Tag())
		AddID3v1TagToDictionary(mMetadata, file.ID3v1Tag());

	if(file.ID3v2Tag()) {
		std::vector<AttachedPicture *> pictures;
		AddID3v2TagToDictionary(mMetadata, pictures, file.ID3v2Tag());
		for(auto picture : pictures)
			AddSavedPicture(picture);
	}

	return true;
}
示例#13
0
bool FLACMetadata::ReadMetadata(CFErrorRef *error)
{
	// Start from scratch
	CFDictionaryRemoveAllValues(mMetadata);
	CFDictionaryRemoveAllValues(mChangedMetadata);

	UInt8 buf [PATH_MAX];
	if(!CFURLGetFileSystemRepresentation(mURL, false, buf, PATH_MAX))
		return false;

	auto stream = new TagLib::FileStream(reinterpret_cast<const char *>(buf), true);
	TagLib::FLAC::File file(stream, TagLib::ID3v2::FrameFactory::instance());

	if(!file.isValid()) {
		if(nullptr != error) {
			CFStringRef description = CFCopyLocalizedString(CFSTR("The file “%@” is not a valid FLAC file."), "");
			CFStringRef failureReason = CFCopyLocalizedString(CFSTR("Not a FLAC file"), "");
			CFStringRef recoverySuggestion = CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), "");
			
			*error = CreateErrorForURL(AudioMetadataErrorDomain, AudioMetadataInputOutputError, description, mURL, failureReason, recoverySuggestion);
			
			CFRelease(description), description = nullptr;
			CFRelease(failureReason), failureReason = nullptr;
			CFRelease(recoverySuggestion), recoverySuggestion = nullptr;
		}

		return false;
	}

	CFDictionarySetValue(mMetadata, kPropertiesFormatNameKey, CFSTR("FLAC"));

	if(file.audioProperties()) {
		auto properties = file.audioProperties();
		AddAudioPropertiesToDictionary(mMetadata, properties);

		if(properties->sampleWidth())
			AddIntToDictionary(mMetadata, kPropertiesBitsPerChannelKey, properties->sampleWidth());
		if(properties->sampleFrames())
			AddLongLongToDictionary(mMetadata, kPropertiesTotalFramesKey, properties->sampleFrames());
	}

	// Add all tags that are present
	if(file.ID3v1Tag())
		AddID3v1TagToDictionary(mMetadata, file.ID3v1Tag());

	if(file.ID3v2Tag()) {
		std::vector<AttachedPicture *> pictures;
		AddID3v2TagToDictionary(mMetadata, pictures, file.ID3v2Tag());
		for(auto picture : pictures)
			AddSavedPicture(picture);
	}

	if(file.xiphComment()) {
		std::vector<AttachedPicture *> pictures;
		AddXiphCommentToDictionary(mMetadata, pictures, file.xiphComment());
		for(auto picture : pictures)
			AddSavedPicture(picture);
	}

	// Add album art
	for(auto iter : file.pictureList()) {
		CFDataRef data = CFDataCreate(kCFAllocatorDefault, reinterpret_cast<const UInt8 *>(iter->data().data()), iter->data().size());

		CFStringRef description = nullptr;
		if(!iter->description().isNull())
			description = CFStringCreateWithCString(kCFAllocatorDefault, iter->description().toCString(true), kCFStringEncodingUTF8);

		AttachedPicture *picture = new AttachedPicture(data, static_cast<AttachedPicture::Type>(iter->type()), description);
		AddSavedPicture(picture);

		if(data)
			CFRelease(data), data = nullptr;

		if(description)
			CFRelease(description), description = nullptr;
	}

	return true;
}
bool FLACMetadata::ReadMetadata(CFErrorRef *error)
{
	// Start from scratch
	CFDictionaryRemoveAllValues(mMetadata);
	CFDictionaryRemoveAllValues(mChangedMetadata);
	
	UInt8 buf [PATH_MAX];
	if(!CFURLGetFileSystemRepresentation(mURL, false, buf, PATH_MAX))
		return false;
	
	FLAC__Metadata_Chain *chain = FLAC__metadata_chain_new();

	// ENOMEM sux
	if(NULL == chain)
		return false;
	
	if(!FLAC__metadata_chain_read(chain, reinterpret_cast<const char *>(buf))) {

		// Attempt to provide a descriptive error message
		if(NULL != error) {
			CFMutableDictionaryRef errorDictionary = CFDictionaryCreateMutable(kCFAllocatorDefault, 
																			   32,
																			   &kCFTypeDictionaryKeyCallBacks,
																			   &kCFTypeDictionaryValueCallBacks);
			
			switch(FLAC__metadata_chain_status(chain)) {
				case FLAC__METADATA_CHAIN_STATUS_NOT_A_FLAC_FILE:
				{
					CFStringRef displayName = CreateDisplayNameForURL(mURL);
					CFStringRef errorString = CFStringCreateWithFormat(kCFAllocatorDefault, 
																	   NULL, 
																	   CFCopyLocalizedString(CFSTR("The file “%@” is not a valid FLAC file."), ""), 
																	   displayName);
					
					CFDictionarySetValue(errorDictionary, 
										 kCFErrorLocalizedDescriptionKey, 
										 errorString);

					CFDictionarySetValue(errorDictionary, 
										 kCFErrorLocalizedFailureReasonKey, 
										 CFCopyLocalizedString(CFSTR("Not a FLAC file"), ""));
					
					CFDictionarySetValue(errorDictionary, 
										 kCFErrorLocalizedRecoverySuggestionKey, 
										 CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), ""));
					
					CFRelease(errorString), errorString = NULL;
					CFRelease(displayName), displayName = NULL;
					
					break;
				}
					
					
				case FLAC__METADATA_CHAIN_STATUS_BAD_METADATA:
				{
					CFStringRef displayName = CreateDisplayNameForURL(mURL);
					CFStringRef errorString = CFStringCreateWithFormat(kCFAllocatorDefault, 
																	   NULL, 
																	   CFCopyLocalizedString(CFSTR("The file “%@” is not a valid FLAC file."), ""), 
																	   displayName);
					
					CFDictionarySetValue(errorDictionary, 
										 kCFErrorLocalizedDescriptionKey, 
										 errorString);
					
					CFDictionarySetValue(errorDictionary, 
										 kCFErrorLocalizedFailureReasonKey, 
										 CFCopyLocalizedString(CFSTR("Not a FLAC file"), ""));
					
					CFDictionarySetValue(errorDictionary, 
										 kCFErrorLocalizedRecoverySuggestionKey, 
										 CFCopyLocalizedString(CFSTR("The file contains bad metadata."), ""));
					
					CFRelease(errorString), errorString = NULL;
					CFRelease(displayName), displayName = NULL;
					
					break;
				}
					
				default:
				{
					CFStringRef displayName = CreateDisplayNameForURL(mURL);
					CFStringRef errorString = CFStringCreateWithFormat(kCFAllocatorDefault, 
																	   NULL, 
																	   CFCopyLocalizedString(CFSTR("The file “%@” is not a valid FLAC file."), ""), 
																	   displayName);
					
					CFDictionarySetValue(errorDictionary, 
										 kCFErrorLocalizedDescriptionKey, 
										 errorString);
					
					CFDictionarySetValue(errorDictionary, 
										 kCFErrorLocalizedFailureReasonKey, 
										 CFCopyLocalizedString(CFSTR("Not a FLAC file"), ""));
					
					CFDictionarySetValue(errorDictionary, 
										 kCFErrorLocalizedRecoverySuggestionKey, 
										 CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), ""));
					
					CFRelease(errorString), errorString = NULL;
					CFRelease(displayName), displayName = NULL;
					
					break;
				}
			}
			
			*error = CFErrorCreate(kCFAllocatorDefault, 
								   AudioMetadataErrorDomain, 
								   AudioMetadataFileFormatNotRecognizedError, 
								   errorDictionary);
			
			CFRelease(errorDictionary), errorDictionary = NULL;
		}

		FLAC__metadata_chain_delete(chain), chain = NULL;
		
		return false;
	}
	
	FLAC__Metadata_Iterator *iterator = FLAC__metadata_iterator_new();

	if(NULL == iterator) {
		FLAC__metadata_chain_delete(chain), chain = NULL;		
		return false;
	}
	
	CFDictionarySetValue(mMetadata, kPropertiesFormatNameKey, CFSTR("FLAC"));

	FLAC__metadata_iterator_init(iterator, chain);
	
	FLAC__StreamMetadata *block = NULL;
	
	CFMutableDictionaryRef additionalMetadata = CFDictionaryCreateMutable(kCFAllocatorDefault, 
																		  32,
																		  &kCFTypeDictionaryKeyCallBacks,
																		  &kCFTypeDictionaryValueCallBacks);
	
	do {
		block = FLAC__metadata_iterator_get_block(iterator);
		
		if(NULL == block)
			break;
		
		switch(block->type) {					
			case FLAC__METADATA_TYPE_VORBIS_COMMENT:				
				for(unsigned i = 0; i < block->data.vorbis_comment.num_comments; ++i) {
					
					char *fieldName = NULL;
					char *fieldValue = NULL;
					
					// Let FLAC parse the comment for us
					if(!FLAC__metadata_object_vorbiscomment_entry_to_name_value_pair(block->data.vorbis_comment.comments[i], &fieldName, &fieldValue)) {
						// Ignore malformed comments
						continue;
					}
					
					CFStringRef key = CFStringCreateWithBytesNoCopy(kCFAllocatorDefault,
																	reinterpret_cast<const UInt8 *>(fieldName),
																	strlen(fieldName), 
																	kCFStringEncodingASCII,
																	false,
																	kCFAllocatorMalloc);

					CFStringRef value = CFStringCreateWithBytesNoCopy(kCFAllocatorDefault,
																	  reinterpret_cast<const UInt8 *>(fieldValue),
																	  strlen(fieldValue), 
																	  kCFStringEncodingUTF8,
																	  false,
																	  kCFAllocatorMalloc);
					
					if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("ALBUM"), kCFCompareCaseInsensitive))
						CFDictionarySetValue(mMetadata, kMetadataAlbumTitleKey, value);
					else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("ARTIST"), kCFCompareCaseInsensitive))
						CFDictionarySetValue(mMetadata, kMetadataArtistKey, value);
					else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("ALBUMARTIST"), kCFCompareCaseInsensitive))
						CFDictionarySetValue(mMetadata, kMetadataAlbumArtistKey, value);
					else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("COMPOSER"), kCFCompareCaseInsensitive))
						CFDictionarySetValue(mMetadata, kMetadataComposerKey, value);
					else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("GENRE"), kCFCompareCaseInsensitive))
						CFDictionarySetValue(mMetadata, kMetadataGenreKey, value);
					else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("DATE"), kCFCompareCaseInsensitive))
						CFDictionarySetValue(mMetadata, kMetadataReleaseDateKey, value);
					else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("DESCRIPTION"), kCFCompareCaseInsensitive))
						CFDictionarySetValue(mMetadata, kMetadataCommentKey, value);
					else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("TITLE"), kCFCompareCaseInsensitive))
						CFDictionarySetValue(mMetadata, kMetadataTitleKey, value);
					else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("TRACKNUMBER"), kCFCompareCaseInsensitive)) {
						int num = CFStringGetIntValue(value);
						CFNumberRef number = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &num);
						CFDictionarySetValue(mMetadata, kMetadataTrackNumberKey, number);
						CFRelease(number), number = NULL;
					}
					else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("TRACKTOTAL"), kCFCompareCaseInsensitive)) {
						int num = CFStringGetIntValue(value);
						CFNumberRef number = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &num);
						CFDictionarySetValue(mMetadata, kMetadataTrackTotalKey, number);
						CFRelease(number), number = NULL;
					}
					else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("COMPILATION"), kCFCompareCaseInsensitive))
						CFDictionarySetValue(mMetadata, kMetadataCompilationKey, CFStringGetIntValue(value) ? kCFBooleanTrue : kCFBooleanFalse);
					else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("DISCNUMBER"), kCFCompareCaseInsensitive)) {
						int num = CFStringGetIntValue(value);
						CFNumberRef number = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &num);
						CFDictionarySetValue(mMetadata, kMetadataDiscNumberKey, number);
						CFRelease(number), number = NULL;
					}
					else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("DISCTOTAL"), kCFCompareCaseInsensitive)) {
						int num = CFStringGetIntValue(value);
						CFNumberRef number = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &num);
						CFDictionarySetValue(mMetadata, kMetadataDiscTotalKey, number);
						CFRelease(number), number = NULL;
					}
					else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("ISRC"), kCFCompareCaseInsensitive))
						CFDictionarySetValue(mMetadata, kMetadataISRCKey, value);
					else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("MCN"), kCFCompareCaseInsensitive))
						CFDictionarySetValue(mMetadata, kMetadataMCNKey, value);
					else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("REPLAYGAIN_REFERENCE_LOUDNESS"), kCFCompareCaseInsensitive)) {
						double num = CFStringGetDoubleValue(value);
						CFNumberRef number = CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &num);
						CFDictionarySetValue(mMetadata, kReplayGainReferenceLoudnessKey, number);
						CFRelease(number), number = NULL;
					}
					else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("REPLAYGAIN_TRACK_GAIN"), kCFCompareCaseInsensitive)) {
						double num = CFStringGetDoubleValue(value);
						CFNumberRef number = CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &num);
						CFDictionarySetValue(mMetadata, kReplayGainTrackGainKey, number);
						CFRelease(number), number = NULL;
					}
					else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("REPLAYGAIN_TRACK_PEAK"), kCFCompareCaseInsensitive)) {
						double num = CFStringGetDoubleValue(value);
						CFNumberRef number = CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &num);
						CFDictionarySetValue(mMetadata, kReplayGainTrackPeakKey, number);
						CFRelease(number), number = NULL;
					}
					else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("REPLAYGAIN_ALBUM_GAIN"), kCFCompareCaseInsensitive)) {
						double num = CFStringGetDoubleValue(value);
						CFNumberRef number = CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &num);
						CFDictionarySetValue(mMetadata, kReplayGainAlbumGainKey, number);
						CFRelease(number), number = NULL;
					}
					else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("REPLAYGAIN_ALBUM_PEAK"), kCFCompareCaseInsensitive)) {
						double num = CFStringGetDoubleValue(value);
						CFNumberRef number = CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &num);
						CFDictionarySetValue(mMetadata, kReplayGainAlbumPeakKey, number);
						CFRelease(number), number = NULL;
					}
					// Put all unknown tags into the additional metadata
					else
						CFDictionarySetValue(additionalMetadata, key, value);
					
					CFRelease(key), key = NULL;
					CFRelease(value), value = NULL;
					
					fieldName = NULL;
					fieldValue = NULL;
				}
				break;
				
			case FLAC__METADATA_TYPE_PICTURE:
			{
				CFDataRef data = CFDataCreate(kCFAllocatorDefault, block->data.picture.data, block->data.picture.data_length);
				CFDictionarySetValue(mMetadata, kAlbumArtFrontCoverKey, data);
				CFRelease(data), data = NULL;
			}
			break;
				
			case FLAC__METADATA_TYPE_STREAMINFO:
			{
				CFNumberRef sampleRate = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &block->data.stream_info.sample_rate);
				CFDictionarySetValue(mMetadata, kPropertiesSampleRateKey, sampleRate);
				CFRelease(sampleRate), sampleRate = NULL;

				CFNumberRef channelsPerFrame = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &block->data.stream_info.channels);
				CFDictionarySetValue(mMetadata, kPropertiesChannelsPerFrameKey, channelsPerFrame);
				CFRelease(channelsPerFrame), channelsPerFrame = NULL;

				CFNumberRef bitsPerChannel = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &block->data.stream_info.bits_per_sample);
				CFDictionarySetValue(mMetadata, kPropertiesBitsPerChannelKey, bitsPerChannel);
				CFRelease(bitsPerChannel), bitsPerChannel = NULL;
				
				CFNumberRef totalFrames = CFNumberCreate(kCFAllocatorDefault, kCFNumberLongLongType, &block->data.stream_info.total_samples);
				CFDictionarySetValue(mMetadata, kPropertiesTotalFramesKey, totalFrames);
				CFRelease(totalFrames), totalFrames = NULL;

				double length = static_cast<double>(block->data.stream_info.total_samples / block->data.stream_info.sample_rate);
				CFNumberRef duration = CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &length);
				CFDictionarySetValue(mMetadata, kPropertiesDurationKey, duration);
				CFRelease(duration), duration = NULL;

				double losslessBitrate = static_cast<double>(block->data.stream_info.sample_rate * block->data.stream_info.channels * block->data.stream_info.bits_per_sample) / 1000;
				CFNumberRef bitrate = CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &losslessBitrate);
				CFDictionarySetValue(mMetadata, kPropertiesBitrateKey, bitrate);
				CFRelease(bitrate), bitrate = NULL;
			}
			break;

			case FLAC__METADATA_TYPE_PADDING:						break;
			case FLAC__METADATA_TYPE_APPLICATION:					break;
			case FLAC__METADATA_TYPE_SEEKTABLE:						break;
			case FLAC__METADATA_TYPE_CUESHEET:						break;
			case FLAC__METADATA_TYPE_UNDEFINED:						break;

			default:												break;
		}
	} while(FLAC__metadata_iterator_next(iterator));

	if(CFDictionaryGetCount(additionalMetadata))
		SetAdditionalMetadata(additionalMetadata);
	
	CFRelease(additionalMetadata), additionalMetadata = NULL;
	
	FLAC__metadata_iterator_delete(iterator), iterator = NULL;
	FLAC__metadata_chain_delete(chain), chain = NULL;
	
	return true;
}
示例#15
0
/* CF_EXPORT */ void
CFNetServiceBrowserStopSearch(CFNetServiceBrowserRef b, CFStreamError* error) {

	__CFNetServiceBrowser* browser = (__CFNetServiceBrowser*)b;

	// By default, the error is marked as a cancel
	CFStreamError extra = {kCFStreamErrorDomainNetServices , kCFNetServicesErrorCancel};

	// Make sure error has a value.
	if (!error)
		error = &extra;

	// Lock down the browser
	__CFSpinLock(&(browser->_lock));

	// Make sure there is something to cancel.
	if (browser->_trigger) {

		CFRunLoopSourceContext ctxt = {
			0,									// version
			browser,							// info
			NULL,								// retain
			NULL,								// release
			NULL,								// copyDescription
			NULL,								// equal
			NULL,								// hash
			NULL,								// schedule
			NULL,								// cancel
			(void(*)(void*))(&_BrowserCancel)  // perform
		};

		// Remove the trigger from run loops and modes
		_CFTypeUnscheduleFromMultipleRunLoops(browser->_trigger, browser->_schedules);

		// Go ahead and invalidate the trigger
		_CFTypeInvalidate(browser->_trigger);

		// Release the trigger now.
		CFRelease(browser->_trigger);

		// Need to clean up the service discovery stuff if there is
		if (browser->_browse) {

			// Release the underlying service discovery reference
			DNSServiceRefDeallocate(browser->_browse);
			browser->_browse = NULL;

			// Dump all the lists of items.
			CFDictionaryRemoveAllValues(browser->_found);
			CFArrayRemoveAllValues(browser->_adds);
			CFArrayRemoveAllValues(browser->_removes);
		}

		// Copy the error into place
		memmove(&(browser->_error), error, sizeof(error[0]));

		// Create the cancel source
		browser->_trigger = CFRunLoopSourceCreate(CFGetAllocator(browser), 0, &ctxt);

		// If the cancel was created, need to schedule and signal it.
		if (browser->_trigger) {

			CFArrayRef schedules = browser->_schedules;
			CFIndex i, count = CFArrayGetCount(schedules);

			// Schedule the new trigger
			_CFTypeScheduleOnMultipleRunLoops(browser->_trigger, schedules);

			// Signal the cancel for immediate attention.
			CFRunLoopSourceSignal((CFRunLoopSourceRef)(browser->_trigger));

			// Make sure the signal can make it through
			for (i = 0; i < count; i += 2) {

				// Grab the run loop for checking
				CFRunLoopRef runloop = (CFRunLoopRef)CFArrayGetValueAtIndex(schedules, i);

				// If it's sleeping, need to further check it.
				if (CFRunLoopIsWaiting(runloop)) {

					// Grab the mode for further check
					CFStringRef mode = CFRunLoopCopyCurrentMode(runloop);

					if (mode) {

						// If the trigger is in the right mode, need to wake up the run loop.
						if (CFRunLoopContainsSource(runloop, (CFRunLoopSourceRef)(browser->_trigger), mode)) {
							CFRunLoopWakeUp(runloop);
						}

						// Don't need this anymore.
						CFRelease(mode);
					}
				}
			}
		}
	}

	// Unlock the browser
	__CFSpinUnlock(&(browser->_lock));
}
示例#16
0
//
// Insert New NDAS device info.
//
// Return :	false if Bad parameters or No memory.
//			true if success.
//
bool NDASPreferencesInsert(PNDASPreferencesParameter parameter)
{
	CFStringRef				strEntryKey = NULL;
	CFStringRef				strIDKey[4] = { NULL };
	CFStringRef				strWriteKeyKey = NULL;
	CFStringRef				strConfigurationKey = NULL;
	
	CFStringRef				strIDValue[4] = { NULL };
	CFStringRef				strWriteKeyValue = NULL;
	CFNumberRef				numberConfigurationValue = NULL;
	CFStringRef				strNameKey = NULL;
	
	CFMutableDictionaryRef	dictEntry = NULL;
	int						count;
	bool					result = false;
	
	if(parameter->slotNumber == 0) {
		return false;
	}
		
	// Create Dict
	dictEntry = CFDictionaryCreateMutable (kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
	if (NULL == dictEntry) {
		return false;
	}
	
	// Copy ID
	for(count = 0; count < 4; count++) {
		
		// Create Key.
		strIDKey[count] = CFStringCreateWithFormat(NULL, NULL, CFSTR(KEY_ID_STRING), count);		
		// Create Value.
		strIDValue[count] = CFStringCreateWithFormat(NULL, NULL, CFSTR("%s"), parameter->chID[count]);
		if (NULL == strIDKey[count] || NULL == strIDValue[count]) {
			goto cleanup;
		}
				
		if (!NDASPreferencesSetIDorWriteKey(dictEntry, strIDKey[count], strIDValue[count])) {
			goto cleanup;
		}
	}
	
	// Copy WriteKey.
	strWriteKeyKey = CFStringCreateWithFormat(NULL, NULL, CFSTR(KEY_WRITEKEY_STRING));
	strWriteKeyValue = CFStringCreateWithFormat(NULL, NULL, CFSTR("%s"), parameter->chWriteKey);
	if (NULL == strWriteKeyKey || NULL == strWriteKeyValue) {
		goto cleanup;
	}
	
	if(!NDASPreferencesSetIDorWriteKey(dictEntry, strWriteKeyKey, strWriteKeyValue)) {
		goto cleanup;
	}
	
	// Copy Name
	strNameKey = CFStringCreateWithFormat(NULL, NULL, CFSTR(KEY_NAME_STRING));
	if (NULL == strNameKey) {
		goto cleanup;
	}
	
	//strNameValue = CFStringCreateWithFormat(NULL, NULL, CFSTR("%s"), parameter->Name);
	//strNameValue = CFStringCreateWithCharacters(kCFAllocatorDefault, (UniChar *)parameter->Name, MAX_NDAS_NAME_SIZE / 2);
	
	CFDictionaryAddValue(dictEntry, 
						 strNameKey, 
						 parameter->cfsName
						 );
	
	// Copy Configuration.
	strConfigurationKey = CFStringCreateWithFormat(NULL, NULL, CFSTR(KEY_CONFIGURATION_STRING));
	numberConfigurationValue = CFNumberCreate (NULL, kCFNumberSInt32Type, &parameter->configuration);
	if (NULL == strConfigurationKey || NULL == numberConfigurationValue) {
		goto cleanup;
	}
	
	CFDictionaryAddValue(dictEntry, strConfigurationKey, numberConfigurationValue);
	
	// Slot Number is the Key.
	strEntryKey = CFStringCreateWithFormat(NULL, NULL, CFSTR(KEY_SLOT_NUMBER_STRING), parameter->slotNumber);
	
	// Set Values.
	CFPreferencesSetValue(
						  strEntryKey, 
						  dictEntry, 
						  NDAS_PREFERENCES_FILE_REGISTER,
						  kCFPreferencesAnyUser, 
						  kCFPreferencesCurrentHost
						  );
	
	// Write out the preference data.
	CFPreferencesSynchronize( 
							 NDAS_PREFERENCES_FILE_REGISTER,
							 kCFPreferencesAnyUser, 
							 kCFPreferencesCurrentHost
							 );
	
	
	result = true;
	
cleanup:
	
	CFDictionaryRemoveAllValues(dictEntry);
	
	// Clean up.
	if(strEntryKey)					CFRelease(strEntryKey);
	if(dictEntry)					CFRelease(dictEntry);
	
	if(strWriteKeyKey)				CFRelease(strWriteKeyKey);
	if(strWriteKeyValue)			CFRelease(strWriteKeyValue);
	
	if(strConfigurationKey)			CFRelease(strConfigurationKey);
	if(numberConfigurationValue)	CFRelease(numberConfigurationValue);
	if(strNameKey)					CFRelease(strNameKey);
	
	for(count = 0; count < 4; count++) {
		if(strIDKey[count])			CFRelease(strIDKey[count]);
		if(strIDValue[count])		CFRelease(strIDValue[count]);
	}
	
	return result;
}
示例#17
0
/* static */ void
_BrowseReply(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex,
			 DNSServiceErrorType errorCode, const char* serviceName, const char* regtype,
			 const char* replyDomain, void* context)
{
	__CFNetServiceBrowser* browser = context;
	CFNetServiceBrowserClientCallBack cb = NULL;
	CFStreamError error = {0, 0};
	void* info = NULL;
	CFNetServiceRef service = NULL;

	// Retain here to guarantee safety really after the trigger release,
	// but definitely before the callback.
	CFRetain(browser);

	// Lock the browser
	__CFSpinLock(&browser->_lock);

	// If the browse canceled, don't need to do any of this.
	if (browser->_browse) {

		// If there is an error, fold the browse.
		if (errorCode) {

			// Save the error
			browser->_error.error = _DNSServiceErrorToCFNetServiceError(errorCode);
			browser->_error.domain = kCFStreamErrorDomainNetServices;

			// Remove the browse from run loops and modes
			_CFTypeUnscheduleFromMultipleRunLoops(browser->_trigger, browser->_schedules);

			// Go ahead and invalidate the socket
			CFSocketInvalidate((CFSocketRef)(browser->_trigger));

			// Release the browse now.
			CFRelease(browser->_trigger);
			browser->_trigger = NULL;

			// Clean up the underlying service discovery stuff
			DNSServiceRefDeallocate(browser->_browse);
			browser->_browse = NULL;

			// Dump all the lists of items.
			CFDictionaryRemoveAllValues(browser->_found);
			CFArrayRemoveAllValues(browser->_adds);
			CFArrayRemoveAllValues(browser->_removes);
		}

		// If got service info from service discovery, create the CFNetServiceRef.
		else if (serviceName && regtype && replyDomain) {

			// Create CFString's for each of the service components
			CFAllocatorRef alloc = CFGetAllocator(browser);
			CFStringRef domain = CFStringCreateWithCString(alloc, replyDomain, kCFStringEncodingUTF8);
			CFStringRef type = CFStringCreateWithCString(alloc, regtype, kCFStringEncodingUTF8);
			CFStringRef name = CFStringCreateWithCString(alloc, serviceName, kCFStringEncodingUTF8);

			// Can only make the service if all the strings were created.  This
			// will skip over items that are not properly UTF8 encoded on the wire.
			if (domain && type && name)
				service = _CFNetServiceCreateCommon(alloc, domain, type, name, 0);

			if (domain) CFRelease(domain);
			if (type) CFRelease(type);
			if (name) CFRelease(name);

			if (service) {

				intptr_t count = (intptr_t)CFDictionaryGetValue(browser->_found, service);

				if (flags & kDNSServiceFlagsAdd) {

					count++;

					if (count != 1)
						CFDictionaryReplaceValue(browser->_found, service, (const void*)count);

					else {
						CFIndex i = CFArrayGetFirstIndexOfValue(browser->_removes,
																CFRangeMake(0, CFArrayGetCount(browser->_removes)),
																service);

						CFDictionaryAddValue(browser->_found, service, (const void*)count);
						CFArrayAppendValue(browser->_adds, service);

						if (i != kCFNotFound)
							CFArrayRemoveValueAtIndex(browser->_removes, i);
					}
				}

				else {

					count--;
					if (count > 0)
						CFDictionaryReplaceValue(browser->_found, service, (const void*)count);
					else {
						CFIndex i = CFArrayGetFirstIndexOfValue(browser->_adds,
																CFRangeMake(0, CFArrayGetCount(browser->_adds)),
																service);

						CFDictionaryRemoveValue(browser->_found, service);
						CFArrayAppendValue(browser->_removes, service);

						if (i != kCFNotFound)
							CFArrayRemoveValueAtIndex(browser->_adds, i);
					}
				}

				CFRelease(service);
			}
		}

		cb = browser->_callback;

		// Save the error and client information for the callback
		memmove(&error, &(browser->_error), sizeof(error));
		info = browser->_client.info;

	}

	// If there is a callback, inform the client of the error.
	if (cb && error.error) {

		// Unlock the browser so the callback can be made safely.
		__CFSpinUnlock(&browser->_lock);

		cb((CFNetServiceBrowserRef)browser, 0, NULL, &error, info);
	}

	else if (cb && ((flags & kDNSServiceFlagsMoreComing) == 0)) {

		CFIndex i, adds = CFArrayGetCount(browser->_adds);
		CFIndex removes = CFArrayGetCount(browser->_removes);
		CFIndex total = adds + removes;

		for (i = 0; i < adds; i++) {

			const void* saved = browser->_trigger;
			service = (CFNetServiceRef)CFArrayGetValueAtIndex(browser->_adds, i);

			// Unlock the browser so the callback can be made safely.
			__CFSpinUnlock(&browser->_lock);

			cb((CFNetServiceBrowserRef)browser,
			   (i == (total - 1)) ? 0 : kCFNetServiceFlagMoreComing,
			   service,
			   &error,
			   info);

			// Lock the browser
			__CFSpinLock(&browser->_lock);

			if (saved != browser->_trigger) {
				cb = NULL;
				break;
			}
		}

		if (cb) {
			for (i = 0; i < removes; i++) {

				const void* saved = browser->_trigger;
				service = (CFNetServiceRef)CFArrayGetValueAtIndex(browser->_removes, i);

				// Unlock the browser so the callback can be made safely.
				__CFSpinUnlock(&browser->_lock);

				cb((CFNetServiceBrowserRef)browser,
				   kCFNetServiceFlagRemove | ((i == (removes - 1)) ? 0 : kCFNetServiceFlagMoreComing),
				   service,
				   &error,
				   info);

				// Lock the browser
				__CFSpinLock(&browser->_lock);

				if (saved != browser->_trigger)
					break;
			}
		}

		// Dump the lists of items, so can start new again.
		CFArrayRemoveAllValues(browser->_adds);
		CFArrayRemoveAllValues(browser->_removes);

		// Unlock the browser so the callback can be made safely.
		__CFSpinUnlock(&browser->_lock);
	}
	else
		__CFSpinUnlock(&browser->_lock);

	// Go ahead and release now that the callback is done.
	CFRelease(browser);
}
示例#18
0
void DAPreferenceListRefresh( void )
{
    struct stat status1;
    struct stat status2;

    /*
     * Determine whether the preference list is up-to-date.
     */

    if ( stat( ___PREFS_DEFAULT_DIR "/" "autodiskmount.plist", &status1 ) )
    {
        __gDAPreferenceListTime1.tv_sec  = 0;
        __gDAPreferenceListTime1.tv_nsec = 0;
    }

    if ( stat( ___PREFS_DEFAULT_DIR "/" _kDADaemonName ".plist", &status2 ) )
    {
        __gDAPreferenceListTime2.tv_sec  = 0;
        __gDAPreferenceListTime2.tv_nsec = 0;
    }

    if ( __gDAPreferenceListTime1.tv_sec  != status1.st_mtimespec.tv_sec  ||
         __gDAPreferenceListTime1.tv_nsec != status1.st_mtimespec.tv_nsec ||
         __gDAPreferenceListTime2.tv_sec  != status2.st_mtimespec.tv_sec  ||
         __gDAPreferenceListTime2.tv_nsec != status2.st_mtimespec.tv_nsec )
    {
        SCPreferencesRef preferences;

        __gDAPreferenceListTime1.tv_sec  = status1.st_mtimespec.tv_sec;
        __gDAPreferenceListTime1.tv_nsec = status1.st_mtimespec.tv_nsec;
        __gDAPreferenceListTime2.tv_sec  = status2.st_mtimespec.tv_sec;
        __gDAPreferenceListTime2.tv_nsec = status2.st_mtimespec.tv_nsec;

        /*
         * Clear the preference list.
         */

        CFDictionaryRemoveAllValues( gDAPreferenceList );

        /*
         * Build the preference list.
         */

        preferences = SCPreferencesCreate( kCFAllocatorDefault, CFSTR( "autodiskmount" ), CFSTR( "autodiskmount.plist" ) );

        if ( preferences )
        {
            CFTypeRef value;

            value = SCPreferencesGetValue( preferences, CFSTR( "AutomountDisksWithoutUserLogin" ) );

            if ( value == kCFBooleanTrue )
            {
                CFDictionarySetValue( gDAPreferenceList, kDAPreferenceMountDeferExternalKey,  kCFBooleanFalse );
                CFDictionarySetValue( gDAPreferenceList, kDAPreferenceMountDeferRemovableKey, kCFBooleanFalse );
                CFDictionarySetValue( gDAPreferenceList, kDAPreferenceMountTrustExternalKey,  kCFBooleanTrue  );
            }
            else if ( value == kCFBooleanFalse )
            {
                CFDictionarySetValue( gDAPreferenceList, kDAPreferenceMountDeferExternalKey,  kCFBooleanFalse );
                CFDictionarySetValue( gDAPreferenceList, kDAPreferenceMountDeferRemovableKey, kCFBooleanTrue  );
                CFDictionarySetValue( gDAPreferenceList, kDAPreferenceMountTrustExternalKey,  kCFBooleanTrue  );
            }

            CFRelease( preferences );
        }

        preferences = SCPreferencesCreate( kCFAllocatorDefault, CFSTR( _kDADaemonName ), CFSTR( _kDADaemonName ".plist" ) );

        if ( preferences )
        {
            CFTypeRef value;

            value = SCPreferencesGetValue( preferences, kDAPreferenceMountDeferExternalKey );

            if ( value )
            {
                if ( CFGetTypeID( value ) == CFBooleanGetTypeID( ) )
                {
                    CFDictionarySetValue( gDAPreferenceList, kDAPreferenceMountDeferExternalKey, value );
                }
            }

            value = SCPreferencesGetValue( preferences, kDAPreferenceMountDeferInternalKey );

            if ( value )
            {
                if ( CFGetTypeID( value ) == CFBooleanGetTypeID( ) )
                {
                    CFDictionarySetValue( gDAPreferenceList, kDAPreferenceMountDeferInternalKey, value );
                }
            }

            value = SCPreferencesGetValue( preferences, kDAPreferenceMountDeferRemovableKey );

            if ( value )
            {
                if ( CFGetTypeID( value ) == CFBooleanGetTypeID( ) )
                {
                    CFDictionarySetValue( gDAPreferenceList, kDAPreferenceMountDeferRemovableKey, value );
                }
            }

            value = SCPreferencesGetValue( preferences, kDAPreferenceMountTrustExternalKey );

            if ( value )
            {
                if ( CFGetTypeID( value ) == CFBooleanGetTypeID( ) )
                {
                    CFDictionarySetValue( gDAPreferenceList, kDAPreferenceMountTrustExternalKey, value );
                }
            }

            value = SCPreferencesGetValue( preferences, kDAPreferenceMountTrustInternalKey );

            if ( value )
            {
                if ( CFGetTypeID( value ) == CFBooleanGetTypeID( ) )
                {
                    CFDictionarySetValue( gDAPreferenceList, kDAPreferenceMountTrustInternalKey, value );
                }
            }

            value = SCPreferencesGetValue( preferences, kDAPreferenceMountTrustRemovableKey );

            if ( value )
            {
                if ( CFGetTypeID( value ) == CFBooleanGetTypeID( ) )
                {
                    CFDictionarySetValue( gDAPreferenceList, kDAPreferenceMountTrustRemovableKey, value );
                }
            }

            CFRelease( preferences );
        }
    }
}
/* Create and identity and try to retrieve it. */
static void tests(void)
{
    SecCertificateRef cert = NULL;
    SecKeyRef privKey = NULL;
    SecIdentityRef identity = NULL;

    isnt(cert = SecCertificateCreateWithBytes(NULL, _c1, sizeof(_c1)),
            NULL, "create certificate");
    isnt(privKey = SecKeyCreateRSAPrivateKey(NULL, _k1, sizeof(_k1),
                kSecKeyEncodingPkcs1), NULL, "create private key");

    const void *certkeys[] = {
        kSecValueRef
    };
    const void *certvalues[] = {
        cert
    };
    CFDictionaryRef certDict = CFDictionaryCreate(NULL, certkeys, certvalues,
            array_size(certkeys), NULL, NULL);
    ok_status(SecItemAdd(certDict, NULL), "add certificate");
    CFReleaseNull(certDict);

    const void *privkeys[] = {
        kSecValueRef
    };
    const void *privvalues[] = {
        privKey
    };
    CFDictionaryRef privDict = CFDictionaryCreate(NULL, privkeys, privvalues,
            array_size(privkeys), NULL, NULL);
    ok_status(SecItemAdd(privDict, NULL), "add private key");
    CFReleaseNull(privDict);

    isnt(identity = SecIdentityCreate(NULL, cert, privKey), NULL, "create identity");

    /* Lookup the key and certificate using SecItemCopyMatching(). */
    CFDataRef pk_digest = CFDataCreate(NULL, _k1_digest, sizeof(_k1_digest));
    const void *q_keys[] = {
        kSecClass,
        kSecAttrApplicationLabel,
        kSecReturnRef
    };
    const void *q_values[] = {
        kSecClassKey,
        pk_digest,
        kCFBooleanTrue
    };
    CFDictionaryRef query = CFDictionaryCreate(NULL, q_keys, q_values,
            array_size(q_keys), NULL, NULL);
    CFTypeRef result_key;
    ok_status(SecItemCopyMatching(query, &result_key), "lookup key");

    isnt(CFEqual(privKey, result_key), 0, "keys match");
    CFReleaseNull(query);

    q_keys[1] = kSecAttrPublicKeyHash;
    q_values[0] = kSecClassCertificate;
    query = CFDictionaryCreate(NULL, q_keys, q_values,
            array_size(q_keys), NULL, NULL);
    CFTypeRef result_cert;
    ok_status(SecItemCopyMatching(query, &result_cert), "lookup certificate");
    isnt(CFEqual(cert, result_cert), 0, "certificates match");
    CFReleaseNull(query);

    /* Cleanup. */
    CFReleaseNull(result_key);
    CFReleaseNull(result_cert);

    /* identity lookup */
    const void *idnt_keys[] = {
        kSecClass,
        kSecAttrApplicationLabel,
        kSecReturnRef
    };
    const void *idnt_values[] = {
        kSecClassIdentity,
        pk_digest,
        kCFBooleanTrue
    };
    CFTypeRef result_idnt;
    SecCertificateRef result_cert2;
    query = CFDictionaryCreate(NULL, idnt_keys, idnt_values,
            array_size(idnt_keys), NULL, NULL);
    ok_status(SecItemCopyMatching(query, &result_idnt), "lookup identity");
    isnt(result_idnt, NULL, "found identity?");
    is(CFGetRetainCount(result_idnt), 1, "result_idnt rc = 1");
    isnt(CFEqual(identity, result_idnt), 0, "identities match");
    CFReleaseNull(identity);

    ok_status(SecIdentityCopyCertificate((SecIdentityRef)result_idnt, &result_cert2), "get cert from identity");
    isnt(CFEqual(cert, result_cert2), 0, "certificates match");
    CFRelease(query);
    CFRelease(pk_digest);
    CFReleaseNull(result_cert2);

    certDict = CFDictionaryCreate(NULL, certkeys, certvalues,
            array_size(certkeys), NULL, NULL);
    ok_status(SecItemDelete(certDict), "delete certificate via ref");
    is_status(errSecItemNotFound, SecItemCopyMatching(certDict, NULL), "verify certificate is gone");

    CFReleaseNull(certDict);

    privDict = CFDictionaryCreate(NULL, privkeys, privvalues,
            array_size(privkeys), NULL, NULL);
    ok_status(SecItemDelete(privDict), "delete key via ref");
    is_status(errSecItemNotFound, SecItemCopyMatching(privDict, NULL), "verify key is gone");
    CFReleaseNull(privDict);

    /* add certificate to offset cert row id from key row id */
    SecCertificateRef apple_ca_cert = NULL;
    isnt(apple_ca_cert = SecCertificateCreateWithBytes(NULL, _c0, sizeof(_c0)),
            NULL, "create apple ca certificate");
    CFDictionaryRef appleCertDict = CFDictionaryCreate(NULL, (const void **)&kSecValueRef, (const void **)&apple_ca_cert, 1, NULL, NULL);
    ok_status(SecItemAdd(appleCertDict, NULL), "add apple ca certificate to offset key and cert rowid");

    /* add identity, get persistent ref */
    const void *keys_identity[] = {     kSecValueRef,   kSecReturnPersistentRef };
    const void *values_identity[] = {   result_idnt,    kCFBooleanTrue };
    CFDictionaryRef identity_add = CFDictionaryCreate(NULL, keys_identity, values_identity,
        array_size(keys_identity), NULL, NULL);
    CFTypeRef persist = NULL;
    ok_status(SecItemAdd(identity_add, &persist), "add identity ref");
    ok(persist, "got back persistent ref");
    /* <rdar://problem/6537195> SecItemAdd returns success when it shouldn't */
    CFTypeRef persist_again = NULL;
    is_status(errSecDuplicateItem, SecItemAdd(identity_add, &persist_again),
        "fail to add identity ref again");
    ok(!persist_again, "no persistent ref this time");

    /* find by persistent ref */
    const void *keys_persist[] = { kSecReturnRef, kSecValuePersistentRef };
    const void *values_persist[] = { kCFBooleanTrue, persist };
    CFDictionaryRef persist_find = CFDictionaryCreate(NULL, keys_persist, values_persist,
	(array_size(keys_persist)), NULL, NULL);
    CFTypeRef results2 = NULL;
    ok_status(SecItemCopyMatching(persist_find, &results2), "find identity by persistent ref");
    is(CFGetRetainCount(results2), 1, "results2 rc = 1");
    // not implemented ok(CFEqual(result_idnt, results2), "same item (attributes)");
    CFReleaseNull(results2);

    /* find identity, key and cert by ref and return persistent ref */
    const void *keys_ref_to_persist[] = { kSecReturnPersistentRef, kSecValueRef };
    const void *values_ref_to_persist[] = { kCFBooleanTrue, NULL };
    CFTypeRef items[] = { result_idnt, privKey, cert, NULL };
    CFTypeRef *item = items;
    while (*item) {
        values_ref_to_persist[1] = *item;
        CFDictionaryRef ref_to_persist_find = CFDictionaryCreate(NULL, keys_ref_to_persist, values_ref_to_persist,
            (array_size(keys_ref_to_persist)), NULL, NULL);
        results2 = NULL;
        ok_status(SecItemCopyMatching(ref_to_persist_find, &results2), "find persistent ref for identity ref");
        ok(NULL != results2, "good persistent ref");
        is(CFGetRetainCount(results2), 1, "results2 rc = 1");
        CFReleaseNull(results2);
        CFReleaseNull(ref_to_persist_find);
        item++;
    }

    /* delete identity by identity ref */
    ok_status(SecItemDelete(identity_add), "delete identity by identity ref");
    is(SecItemCopyMatching(persist_find, &results2), errSecItemNotFound,
        "make sure identity by persistent ref is no longer there");
    CFRelease(persist_find);
    CFReleaseNull(persist);
    ok_status(SecItemAdd(identity_add, &persist), "add identity ref back");
    CFRelease(identity_add);

    /* delete identity by persistent ref */
    CFDictionaryRef persist_delete = CFDictionaryCreate(NULL,
        &kSecValuePersistentRef, &persist, 1, NULL, NULL);
    ok_status(SecItemDelete(persist_delete),
        "delete identity by persistent ref");
    is(SecItemCopyMatching(persist_delete, &results2), errSecItemNotFound,
        "make sure identity by persistent ref is no longer there");
    CFRelease(persist_delete);
    CFReleaseNull(persist);

	/* add identity with a label set */
	CFStringRef zomg_label = CFSTR("zomg");
	CFMutableDictionaryRef lbl_idnt_query =
		CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
		&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
	CFDictionarySetValue(lbl_idnt_query, kSecValueRef, result_idnt);
	CFDictionarySetValue(lbl_idnt_query, kSecAttrLabel, zomg_label);
    ok_status(SecItemAdd(lbl_idnt_query, NULL), "add identity ref");

	/* find identity with label*/
	CFDictionaryRemoveAllValues(lbl_idnt_query);
	CFDictionarySetValue(lbl_idnt_query, kSecClass, kSecClassIdentity);
	CFDictionarySetValue(lbl_idnt_query, kSecAttrLabel, zomg_label);
	ok_status(SecItemCopyMatching(lbl_idnt_query, NULL), "find identity by label");

	/* find certs with label */
	CFTypeRef zomg_cert;
	CFDictionaryRemoveAllValues(lbl_idnt_query);
	CFDictionarySetValue(lbl_idnt_query, kSecClass, kSecClassCertificate);
	CFDictionarySetValue(lbl_idnt_query, kSecAttrLabel, zomg_label);
	CFDictionarySetValue(lbl_idnt_query, kSecReturnRef, kCFBooleanTrue);
	ok_status(SecItemCopyMatching(lbl_idnt_query, &zomg_cert), "find cert by label");

	/* find keys with label */
	CFTypeRef zomg_key;
	CFDictionaryRemoveAllValues(lbl_idnt_query);
	CFDictionarySetValue(lbl_idnt_query, kSecClass, kSecClassKey);
	CFDictionarySetValue(lbl_idnt_query, kSecAttrLabel, zomg_label);
	CFDictionarySetValue(lbl_idnt_query, kSecReturnRef, kCFBooleanTrue);
	ok_status(SecItemCopyMatching(lbl_idnt_query, &zomg_key), "find key by label");

	/* update label on key */
	CFStringRef new_label_value = CFSTR("zzzomg");
	CFDictionaryRef new_label = CFDictionaryCreate(kCFAllocatorDefault, (const void **)&kSecAttrLabel, (const void **)&new_label_value, 1, NULL, NULL);
	CFDictionaryRemoveAllValues(lbl_idnt_query);
	CFDictionarySetValue(lbl_idnt_query, kSecValueRef, zomg_key);
	ok_status(SecItemUpdate(lbl_idnt_query, new_label), "update label to zzzomg for key");

	CFTypeRef zomg_idnt = NULL;
	CFDictionaryRemoveAllValues(lbl_idnt_query);
	CFDictionarySetValue(lbl_idnt_query, kSecReturnRef, kCFBooleanTrue);
	CFDictionarySetValue(lbl_idnt_query, kSecAttrLabel, zomg_label);
	CFDictionarySetValue(lbl_idnt_query, kSecClass, kSecClassIdentity);
	ok_status(SecItemCopyMatching(lbl_idnt_query, &zomg_idnt), "still finding zomg ident");
	CFReleaseNull(zomg_idnt);


	CFDictionaryRemoveAllValues(lbl_idnt_query);
	CFDictionarySetValue(lbl_idnt_query, kSecValueRef, zomg_cert);
	ok_status(SecItemUpdate(lbl_idnt_query, new_label), "update label to zzzomg for cert");
	CFReleaseNull(new_label);

	CFDictionaryRemoveAllValues(lbl_idnt_query);
	CFDictionarySetValue(lbl_idnt_query, kSecReturnRef, kCFBooleanTrue);
	CFDictionarySetValue(lbl_idnt_query, kSecAttrLabel, zomg_label);
	CFDictionarySetValue(lbl_idnt_query, kSecClass, kSecClassIdentity);
	is_status(errSecItemNotFound, SecItemCopyMatching(lbl_idnt_query, &zomg_idnt), "no longer find identity by label");

	CFDictionaryRemoveAllValues(lbl_idnt_query);
	CFDictionarySetValue(lbl_idnt_query, kSecReturnRef, kCFBooleanTrue);
	CFDictionarySetValue(lbl_idnt_query, kSecAttrLabel, new_label_value);
	CFDictionarySetValue(lbl_idnt_query, kSecClass, kSecClassIdentity);
	ok_status(SecItemCopyMatching(lbl_idnt_query, &zomg_idnt), "finding ident with zzzomg label");

    /* Find zomg identity with canonical issuer */
    {
        unsigned char DN[] = {
            0x30, 0x32, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c,
            0x07, 0x70, 0x6c, 0x75, 0x74, 0x6f, 0x43, 0x41, 0x31, 0x1e, 0x30, 0x1c,
            0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x0c,
            0x0f, 0x70, 0x6c, 0x75, 0x74, 0x6f, 0x40, 0x70, 0x6c, 0x75, 0x74, 0x6f,
            0x2e, 0x63, 0x6f, 0x6d
        };
        unsigned int DN_len = 52;
        CFMutableDictionaryRef find_by_issuer = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
        CFDataRef issuer = SecCertificateGetNormalizedIssuerContent(cert);
        CFTypeRef found_by_issuer = NULL;
        CFDictionarySetValue(find_by_issuer, kSecAttrIssuer, issuer);
        CFDictionarySetValue(find_by_issuer, kSecClass, kSecClassIdentity);
        CFDictionarySetValue(find_by_issuer, kSecReturnRef, kCFBooleanTrue);
        ok_status(SecItemCopyMatching(find_by_issuer, &found_by_issuer), "find identity by cert issuer");
        ok(CFEqual(found_by_issuer, zomg_idnt), "should be same as zomg_idnt");
        CFReleaseNull(found_by_issuer);
        issuer = CFDataCreate(kCFAllocatorDefault, DN, DN_len);
        CFDictionarySetValue(find_by_issuer, kSecAttrIssuer, issuer);
        ok_status(SecItemCopyMatching(find_by_issuer, &found_by_issuer), "find identity by cert issuer");
        CFReleaseNull(issuer);
        ok(CFEqual(found_by_issuer, zomg_idnt), "should be same as zomg_idnt");
        CFReleaseNull(found_by_issuer);
        CFReleaseNull(find_by_issuer);
    }

    ok_status(SecItemDelete(lbl_idnt_query), "delete ident with zzzomg label");

    /* Delete the apple cert last */
    ok_status(SecItemDelete(appleCertDict), "delete apple ca certificate");
    CFReleaseNull(appleCertDict);
    CFReleaseNull(apple_ca_cert);

	CFRelease(zomg_key);
	CFRelease(zomg_cert);
	CFRelease(zomg_idnt);
	CFRelease(zomg_label);
	CFRelease(new_label_value);
	CFRelease(lbl_idnt_query);

    CFReleaseNull(result_idnt);
    CFReleaseNull(privKey);
    CFReleaseNull(cert);
}
示例#20
0
static void tests(void)
{
    SecKeyRef phone_publicKey = NULL, phone_privateKey = NULL;
    SecKeyRef ca_publicKey = NULL, ca_privateKey = NULL;

    int keysize = 2048;
    CFNumberRef key_size_num = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &keysize);
    const void *keygen_keys[] = { kSecAttrKeyType, kSecAttrKeySizeInBits };
    const void *keygen_vals[] = { kSecAttrKeyTypeRSA, key_size_num };
    CFDictionaryRef parameters = CFDictionaryCreate(kCFAllocatorDefault,
        keygen_keys, keygen_vals, array_size(keygen_vals),
        &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks );
    CFReleaseNull(key_size_num);

    CFMutableDictionaryRef subject_alt_names = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
    CFDictionarySetValue(subject_alt_names, CFSTR("dnsname"), CFSTR("xey.nl"));

    int key_usage = kSecKeyUsageDigitalSignature | kSecKeyUsageKeyEncipherment;
    CFNumberRef key_usage_num = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &key_usage);

    CFMutableDictionaryRef random_extensions = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);

    const void *key[] = { kSecCSRChallengePassword, kSecSubjectAltName, kSecCertificateKeyUsage, kSecCertificateExtensions };
    const void *val[] = { CFSTR("magic"), subject_alt_names, key_usage_num, random_extensions };
    CFDictionaryRef csr_parameters = CFDictionaryCreate(kCFAllocatorDefault,
        key, val, array_size(key), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);

    SecATV cn_phone[] = { { kSecOidCommonName, SecASN1PrintableString, CFSTR("My iPhone") }, {} };
    SecATV c[]  = { { kSecOidCountryName, SecASN1PrintableString, CFSTR("US") }, {} };
    SecATV st[] = { { kSecOidStateProvinceName, SecASN1PrintableString, CFSTR("CA") }, {} };
    SecATV l[]  = { { kSecOidLocalityName, SecASN1PrintableString, CFSTR("Cupertino") }, {} };
    SecATV o[]  = { { CFSTR("2.5.4.10"), SecASN1PrintableString, CFSTR("Apple Inc.") }, {} };
    SecATV ou[] = { { kSecOidOrganizationalUnit, SecASN1PrintableString, CFSTR("iPhone") }, {} };

    SecRDN atvs_phone[] = { cn_phone, c, st, l, o, ou, NULL };

    ok_status(SecKeyGeneratePair(parameters, &phone_publicKey, &phone_privateKey), "generate key pair");
    ok_status(SecKeyGeneratePair(parameters, &ca_publicKey, &ca_privateKey), "generate key pair");

    int self_key_usage = kSecKeyUsageKeyCertSign | kSecKeyUsageCRLSign;
    CFNumberRef self_key_usage_num = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &self_key_usage);
    int path_len = 0;
    CFNumberRef path_len_num = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &path_len);
    const void *self_key[] = { kSecCertificateKeyUsage, kSecCSRBasicContraintsPathLen };
    const void *self_val[] = { self_key_usage_num, path_len_num };
    CFDictionaryRef self_signed_parameters = CFDictionaryCreate(kCFAllocatorDefault,
        self_key, self_val, array_size(self_key), NULL, NULL);

    const void * ca_o[] = { kSecOidOrganization, CFSTR("Apple Inc.") };
    const void * ca_cn[] = { kSecOidCommonName, CFSTR("Root CA") };
    CFArrayRef ca_o_dn = CFArrayCreate(kCFAllocatorDefault, ca_o, 2, NULL);
    CFArrayRef ca_cn_dn = CFArrayCreate(kCFAllocatorDefault, ca_cn, 2, NULL);
    const void *ca_dn_array[2];
    ca_dn_array[0] = CFArrayCreate(kCFAllocatorDefault, (const void **)&ca_o_dn, 1, NULL);
    ca_dn_array[1] = CFArrayCreate(kCFAllocatorDefault, (const void **)&ca_cn_dn, 1, NULL);
    CFArrayRef ca_rdns = CFArrayCreate(kCFAllocatorDefault, ca_dn_array, 2, NULL);

    SecCertificateRef ca_cert = SecGenerateSelfSignedCertificate(ca_rdns,
        self_signed_parameters, ca_publicKey, ca_privateKey);
	SecCertificateRef ca_cert_phone_key =
		SecGenerateSelfSignedCertificate(ca_rdns, self_signed_parameters, phone_publicKey, phone_privateKey);

	CFReleaseSafe(self_signed_parameters);
    CFReleaseSafe(self_key_usage_num);
    CFReleaseSafe(path_len_num);
    CFReleaseNull(ca_o_dn);
    CFReleaseNull(ca_cn_dn);
    CFReleaseNull(ca_dn_array[0]);
    CFReleaseNull(ca_dn_array[1]);
    CFReleaseNull(ca_rdns);

    isnt(ca_cert, NULL, "got back a cert");
    ok(SecCertificateIsSelfSignedCA(ca_cert), "cert is self-signed ca cert");
    isnt(ca_cert_phone_key, NULL, "got back a cert");
    ok(SecCertificateIsSelfSignedCA(ca_cert_phone_key), "cert is self-signed ca cert");
    CFDataRef data = SecCertificateCopyData(ca_cert);
    //write_data("/tmp/ca_cert.der", data);
    CFReleaseSafe(data);

    SecIdentityRef ca_identity = SecIdentityCreate(kCFAllocatorDefault, ca_cert, ca_privateKey);
	SecIdentityRef ca_identity_phone_key = SecIdentityCreate(kCFAllocatorDefault, ca_cert_phone_key, phone_privateKey);
    isnt(ca_identity, NULL, "got a identity");
    isnt(ca_identity_phone_key, NULL, "got a identity");
    CFDictionaryRef dict = CFDictionaryCreate(NULL, (const void **)&kSecValueRef, (const void **)&ca_identity, 1, NULL, NULL);
    ok_status(SecItemAdd(dict, NULL), "add ca identity");
    CFReleaseSafe(dict);
#if TARGET_OS_IPHONE
    TODO: {
        todo("Adding a cert with the same issuer/serial but a different key should return something other than errSecDuplicateItem");
#else
    {
#endif
        dict = CFDictionaryCreate(NULL, (const void **)&kSecValueRef, (const void **)&ca_identity_phone_key, 1, NULL, NULL);
        is_status(errSecDuplicateItem, SecItemAdd(dict, NULL), "add ca identity");
        CFReleaseSafe(dict);
    }

    CFDataRef csr = SecGenerateCertificateRequestWithParameters(atvs_phone, NULL, phone_publicKey, phone_privateKey);
    isnt(csr, NULL, "got back a csr");
    CFReleaseNull(csr);

	//dict[kSecSubjectAltName, dict[ntPrincipalName, "*****@*****.**"]]
	CFStringRef nt_princ_name_val = CFSTR("*****@*****.**");
	CFStringRef nt_princ_name_key = CFSTR("ntPrincipalName");
	CFDictionaryRef nt_princ = CFDictionaryCreate(NULL, (const void **)&nt_princ_name_key, (const void **)&nt_princ_name_val, 1, NULL, NULL);
	CFDictionaryRef params = CFDictionaryCreate(NULL, (const void **)&kSecSubjectAltName, (const void **)&nt_princ, 1, NULL, NULL);

    csr = SecGenerateCertificateRequestWithParameters(atvs_phone, params, phone_publicKey, phone_privateKey);
    isnt(csr, NULL, "got back a csr");
	//write_data("/var/tmp/csr-nt-princ", csr);
    CFReleaseNull(csr);
	CFReleaseNull(params);
	CFReleaseNull(nt_princ);

    csr = SecGenerateCertificateRequestWithParameters(atvs_phone, csr_parameters, phone_publicKey, phone_privateKey);
    isnt(csr, NULL, "csr w/ params");
    //write_data("/tmp/csr", csr);
    CFDataRef subject, extensions;
    CFStringRef challenge;
    ok(SecVerifyCertificateRequest(csr, NULL, &challenge, &subject, &extensions), "verify csr");
    CFReleaseNull(csr);

    uint8_t serialno_byte = 42;
    CFDataRef serialno = CFDataCreate(kCFAllocatorDefault, &serialno_byte, sizeof(serialno_byte));
    SecCertificateRef cert = SecIdentitySignCertificate(ca_identity, serialno,
        phone_publicKey, subject, extensions);
    data = SecCertificateCopyData(cert);
    //write_data("/tmp/iphone_cert.der", data);
    CFReleaseNull(data);
    CFReleaseNull(subject);
    CFReleaseNull(extensions);
    CFReleaseNull(challenge);

    const void * email[] = { CFSTR("1.2.840.113549.1.9.1"), CFSTR("*****@*****.**") };
    const void * cn[] = { CFSTR("2.5.4.3"), CFSTR("S/MIME Baby") };
    CFArrayRef email_dn = CFArrayCreate(kCFAllocatorDefault, email, 2, NULL);
    CFArrayRef cn_dn = CFArrayCreate(kCFAllocatorDefault, cn, 2, NULL);
    const void *dn_array[2];
    dn_array[0] = CFArrayCreate(kCFAllocatorDefault, (const void **)&email_dn, 1, NULL);
    dn_array[1] = CFArrayCreate(kCFAllocatorDefault, (const void **)&cn_dn, 1, NULL);
    CFArrayRef rdns = CFArrayCreate(kCFAllocatorDefault, dn_array, 2, NULL);
    CFDictionarySetValue(subject_alt_names, CFSTR("rfc822name"), CFSTR("*****@*****.**"));

    uint8_t random_extension_data[] = { 0xde, 0xad, 0xbe, 0xef };
    CFDataRef random_extension_value = CFDataCreate(kCFAllocatorDefault, random_extension_data, sizeof(random_extension_data));
    CFDictionarySetValue(random_extensions, CFSTR("1.2.840.113635.100.6.1.2"), random_extension_value);  // APPLE_FDR_ACCESS_OID
    CFDictionarySetValue(random_extensions, CFSTR("1.2.840.113635.100.6.1.3"), CFSTR("that guy"));  // APPLE_FDR_CLIENT_IDENTIFIER_OID
    CFReleaseNull(random_extension_value);

    csr = SecGenerateCertificateRequest(rdns, csr_parameters, phone_publicKey, phone_privateKey);
    isnt(csr, NULL, "csr w/ params");
    //write_data("/tmp/csr_neu", csr);
    CFReleaseNull(csr);
    CFReleaseNull(subject_alt_names);
    CFDictionaryRemoveAllValues(random_extensions);

#if TARGET_OS_IPHONE
    CFDataRef scep_request = SecSCEPGenerateCertificateRequest(rdns,
        csr_parameters, phone_publicKey, phone_privateKey, NULL, ca_cert);
    isnt(scep_request, NULL, "got scep blob");
    //write_data("/tmp/scep_request.der", scep_request);
#endif

    CFReleaseNull(email_dn);
    CFReleaseNull(cn_dn);
    CFReleaseNull(dn_array[0]);
    CFReleaseNull(dn_array[1]);
    CFReleaseNull(rdns);

#if TARGET_OS_IPHONE
    CFDataRef scep_reply = SecSCEPCertifyRequest(scep_request, ca_identity, serialno, false);
    isnt(scep_reply, NULL, "produced scep reply");
    //write_data("/tmp/scep_reply.der", scep_reply);

    CFArrayRef issued_certs = NULL;
    ok(issued_certs = SecSCEPVerifyReply(scep_request, scep_reply, ca_cert, NULL), "verify scep reply");

    // take the issued cert and CA cert and pretend it's a RA/CA couple
    CFMutableArrayRef scep_certs = CFArrayCreateMutableCopy(kCFAllocatorDefault, 0, issued_certs);
    CFArrayAppendValue(scep_certs, ca_cert);
    SecCertificateRef ca_certificate = NULL, ra_signing_certificate = NULL, ra_encryption_certificate = NULL;

    ok_status(SecSCEPValidateCACertMessage(scep_certs, NULL,
        &ca_certificate, &ra_signing_certificate,
        &ra_encryption_certificate), "pull apart array again");
    ok(CFEqual(ca_cert, ca_certificate), "found ca");
    ok(CFArrayContainsValue(issued_certs, CFRangeMake(0, CFArrayGetCount(issued_certs)), ra_signing_certificate), "found ra");
    ok(!ra_encryption_certificate, "no separate encryption cert");

    CFReleaseSafe(ca_certificate);
    CFReleaseSafe(ra_signing_certificate);
    CFReleaseSafe(scep_certs);

    CFReleaseSafe(scep_request);
    CFReleaseSafe(scep_reply);
    CFReleaseSafe(issued_certs);
#endif

    // cleanups
    dict = CFDictionaryCreate(NULL, (const void **)&kSecValueRef, (const void **)&ca_identity, 1, NULL, NULL);
    ok_status(SecItemDelete(dict), "delete ca identity");
	CFReleaseSafe(dict);
    dict = CFDictionaryCreate(NULL, (const void **)&kSecValueRef, (const void **)&phone_privateKey, 1, NULL, NULL);
    ok_status(SecItemDelete(dict), "delete phone private key");
	CFReleaseSafe(dict);

    CFReleaseSafe(serialno);

    CFReleaseSafe(cert);
    CFReleaseSafe(ca_identity);
    CFReleaseSafe(ca_cert);
	CFReleaseSafe(ca_identity_phone_key);
	CFReleaseSafe(ca_cert_phone_key);
    CFReleaseSafe(csr_parameters);
    CFReleaseSafe(random_extensions);
    CFReleaseSafe(parameters);
    CFReleaseSafe(ca_publicKey);
    CFReleaseSafe(ca_privateKey);
    CFReleaseSafe(phone_publicKey);
    CFReleaseSafe(phone_privateKey);
}

static void test_ec_csr(void) {
    SecKeyRef ecPublicKey = NULL, ecPrivateKey = NULL;

    int keysize = 256;
    CFNumberRef key_size_num = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &keysize);

    const void *keyParamsKeys[] = { kSecAttrKeyType, kSecAttrKeySizeInBits };
    const void *keyParamsValues[] = { kSecAttrKeyTypeECSECPrimeRandom,  key_size_num};
    CFDictionaryRef keyParameters = CFDictionaryCreate(NULL, keyParamsKeys, keyParamsValues, 2,
                                                       &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
    ok_status(SecKeyGeneratePair(keyParameters, &ecPublicKey, &ecPrivateKey),
              "unable to generate EC key");

    SecATV cn_phone[] = { { kSecOidCommonName, SecASN1PrintableString, CFSTR("My iPhone") }, {} };
    SecATV c[]  = { { kSecOidCountryName, SecASN1PrintableString, CFSTR("US") }, {} };
    SecATV st[] = { { kSecOidStateProvinceName, SecASN1PrintableString, CFSTR("CA") }, {} };
    SecATV l[]  = { { kSecOidLocalityName, SecASN1PrintableString, CFSTR("Cupertino") }, {} };
    SecATV o[]  = { { CFSTR("2.5.4.10"), SecASN1PrintableString, CFSTR("Apple Inc.") }, {} };
    SecATV ou[] = { { kSecOidOrganizationalUnit, SecASN1PrintableString, CFSTR("iPhone") }, {} };

    SecRDN atvs_phone[] = { cn_phone, c, st, l, o, ou, NULL };

    CFMutableDictionaryRef subject_alt_names = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
    CFDictionarySetValue(subject_alt_names, CFSTR("dnsname"), CFSTR("xey.nl"));

    int key_usage = kSecKeyUsageDigitalSignature | kSecKeyUsageKeyEncipherment;
    CFNumberRef key_usage_num = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &key_usage);

    CFMutableDictionaryRef random_extensions = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);

    const void *key[] = { kSecCSRChallengePassword, kSecSubjectAltName, kSecCertificateKeyUsage, kSecCertificateExtensions };
    const void *val[] = { CFSTR("magic"), subject_alt_names, key_usage_num, random_extensions };
    CFDictionaryRef csr_parameters = CFDictionaryCreate(kCFAllocatorDefault,
                                                        key, val, array_size(key), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);


    CFDataRef csr = SecGenerateCertificateRequestWithParameters(atvs_phone, csr_parameters, ecPublicKey, ecPrivateKey);
    isnt(csr, NULL, "csr w/ params");
    //write_data("/tmp/csr", csr);
    CFDataRef subject, extensions;
    CFStringRef challenge;
    ok(SecVerifyCertificateRequest(csr, NULL, &challenge, &subject, &extensions), "verify csr");

    CFReleaseNull(csr);
    CFReleaseNull(key_size_num);
    CFReleaseNull(keyParameters);
    CFReleaseNull(ecPublicKey);
    CFReleaseNull(ecPrivateKey);
    CFReleaseNull(subject_alt_names);
    CFReleaseNull(key_usage_num);
    CFReleaseNull(random_extensions);
    CFReleaseNull(csr_parameters);
    CFReleaseNull(subject);
    CFReleaseNull(extensions);
    CFReleaseNull(challenge);
}
bool MP4Metadata::ReadMetadata(CFErrorRef *error)
{
	// Start from scratch
	CFDictionaryRemoveAllValues(mMetadata);
	CFDictionaryRemoveAllValues(mChangedMetadata);

	UInt8 buf [PATH_MAX];
	if(!CFURLGetFileSystemRepresentation(mURL, FALSE, buf, PATH_MAX))
		return false;
	
	// Open the file for reading
	MP4FileHandle file = MP4Read(reinterpret_cast<const char *>(buf));
	
	if(MP4_INVALID_FILE_HANDLE == file) {
		if(error) {
			CFMutableDictionaryRef errorDictionary = CFDictionaryCreateMutable(kCFAllocatorDefault, 
																			   32,
																			   &kCFTypeDictionaryKeyCallBacks,
																			   &kCFTypeDictionaryValueCallBacks);
			
			CFStringRef displayName = CreateDisplayNameForURL(mURL);
			CFStringRef errorString = CFStringCreateWithFormat(kCFAllocatorDefault, 
															   NULL, 
															   CFCopyLocalizedString(CFSTR("The file “%@” is not a valid MPEG-4 file."), ""), 
															   displayName);
			
			CFDictionarySetValue(errorDictionary, 
								 kCFErrorLocalizedDescriptionKey, 
								 errorString);
			
			CFDictionarySetValue(errorDictionary, 
								 kCFErrorLocalizedFailureReasonKey, 
								 CFCopyLocalizedString(CFSTR("Not an MPEG-4 file"), ""));
			
			CFDictionarySetValue(errorDictionary, 
								 kCFErrorLocalizedRecoverySuggestionKey, 
								 CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), ""));
			
			CFRelease(errorString), errorString = NULL;
			CFRelease(displayName), displayName = NULL;
			
			*error = CFErrorCreate(kCFAllocatorDefault, 
								   AudioMetadataErrorDomain, 
								   AudioMetadataFileFormatNotRecognizedError, 
								   errorDictionary);
			
			CFRelease(errorDictionary), errorDictionary = NULL;				
		}
		
		return false;
	}

	// Read the properties
	if(0 < MP4GetNumberOfTracks(file)) {
		// Should be type 'soun', media data name'mp4a'
		MP4TrackId trackID = MP4FindTrackId(file, 0);

		// Verify this is an MPEG-4 audio file
		if(MP4_INVALID_TRACK_ID == trackID || strncmp("soun", MP4GetTrackType(file, trackID), 4)) {
			MP4Close(file), file = NULL;
			
			if(error) {
				CFMutableDictionaryRef errorDictionary = CFDictionaryCreateMutable(kCFAllocatorDefault, 
																				   32,
																				   &kCFTypeDictionaryKeyCallBacks,
																				   &kCFTypeDictionaryValueCallBacks);
				
				CFStringRef displayName = CreateDisplayNameForURL(mURL);
				CFStringRef errorString = CFStringCreateWithFormat(kCFAllocatorDefault, 
																   NULL, 
																   CFCopyLocalizedString(CFSTR("The file “%@” is not a valid MPEG-4 file."), ""), 
																   displayName);
				
				CFDictionarySetValue(errorDictionary, 
									 kCFErrorLocalizedDescriptionKey, 
									 errorString);
				
				CFDictionarySetValue(errorDictionary, 
									 kCFErrorLocalizedFailureReasonKey, 
									 CFCopyLocalizedString(CFSTR("Not an MPEG-4 file"), ""));
				
				CFDictionarySetValue(errorDictionary, 
									 kCFErrorLocalizedRecoverySuggestionKey, 
									 CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), ""));
				
				CFRelease(errorString), errorString = NULL;
				CFRelease(displayName), displayName = NULL;
				
				*error = CFErrorCreate(kCFAllocatorDefault, 
									   AudioMetadataErrorDomain, 
									   AudioMetadataFileFormatNotSupportedError, 
									   errorDictionary);
				
				CFRelease(errorDictionary), errorDictionary = NULL;				
			}
			
			return false;
		}
		
		MP4Duration mp4Duration = MP4GetTrackDuration(file, trackID);
		uint32_t mp4TimeScale = MP4GetTrackTimeScale(file, trackID);
		
		CFNumberRef totalFrames = CFNumberCreate(kCFAllocatorDefault, kCFNumberLongLongType, &mp4Duration);
		CFDictionarySetValue(mMetadata, kPropertiesTotalFramesKey, totalFrames);
		CFRelease(totalFrames), totalFrames = NULL;
		
		CFNumberRef sampleRate = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &mp4TimeScale);
		CFDictionarySetValue(mMetadata, kPropertiesSampleRateKey, sampleRate);
		CFRelease(sampleRate), sampleRate = NULL;
		
		double length = static_cast<double>(mp4Duration / mp4TimeScale);
		CFNumberRef duration = CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &length);
		CFDictionarySetValue(mMetadata, kPropertiesDurationKey, duration);
		CFRelease(duration), duration = NULL;

		// "mdia.minf.stbl.stsd.*[0].channels"
		int channels = MP4GetTrackAudioChannels(file, trackID);
		CFNumberRef channelsPerFrame = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &channels);
		CFDictionaryAddValue(mMetadata, kPropertiesChannelsPerFrameKey, channelsPerFrame);
		CFRelease(channelsPerFrame), channelsPerFrame = NULL;

		// ALAC files
		if(MP4HaveTrackAtom(file, trackID, "mdia.minf.stbl.stsd.alac")) {
			CFDictionarySetValue(mMetadata, kPropertiesFormatNameKey, CFSTR("Apple Lossless"));
			
			uint64_t sampleSize;
			uint8_t *decoderConfig;
			uint32_t decoderConfigSize;
			if(MP4GetTrackBytesProperty(file, trackID, "mdia.minf.stbl.stsd.alac.alac.decoderConfig", &decoderConfig, &decoderConfigSize) && 28 <= decoderConfigSize) {
				// The ALAC magic cookie seems to have the following layout (28 bytes, BE):
				// Byte 10: Sample size
				// Bytes 25-28: Sample rate
				CFNumberRef bitsPerChannel = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt8Type, decoderConfig + 9);
				CFDictionaryAddValue(mMetadata, kPropertiesBitsPerChannelKey, bitsPerChannel);
				CFRelease(bitsPerChannel), bitsPerChannel = NULL;

				double losslessBitrate = static_cast<double>(mp4TimeScale * channels * sampleSize) / 1000;
				CFNumberRef bitrate = CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &losslessBitrate);
				CFDictionarySetValue(mMetadata, kPropertiesBitrateKey, bitrate);
				CFRelease(bitrate), bitrate = NULL;

				free(decoderConfig), decoderConfig = NULL;
			}			
			else if(MP4GetTrackIntegerProperty(file, trackID, "mdia.minf.stbl.stsd.alac.sampleSize", &sampleSize)) {
				CFNumberRef bitsPerChannel = CFNumberCreate(kCFAllocatorDefault, kCFNumberLongLongType, &sampleSize);
				CFDictionaryAddValue(mMetadata, kPropertiesBitsPerChannelKey, bitsPerChannel);
				CFRelease(bitsPerChannel), bitsPerChannel = NULL;

				double losslessBitrate = static_cast<double>(mp4TimeScale * channels * sampleSize) / 1000;
				CFNumberRef bitrate = CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &losslessBitrate);
				CFDictionarySetValue(mMetadata, kPropertiesBitrateKey, bitrate);
				CFRelease(bitrate), bitrate = NULL;
			}
		}

		// AAC files
		if(MP4HaveTrackAtom(file, trackID, "mdia.minf.stbl.stsd.mp4a")) {
			CFDictionarySetValue(mMetadata, kPropertiesFormatNameKey, CFSTR("AAC"));

			// "mdia.minf.stbl.stsd.*.esds.decConfigDescr.avgBitrate"
			uint32_t trackBitrate = MP4GetTrackBitRate(file, trackID) / 1000;
			CFNumberRef bitrate = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &trackBitrate);
			CFDictionaryAddValue(mMetadata, kPropertiesBitrateKey, bitrate);
			CFRelease(bitrate), bitrate = NULL;
			
		}
	}
	// No valid tracks in file
	else {
		MP4Close(file), file = NULL;
		
		if(error) {
			CFMutableDictionaryRef errorDictionary = CFDictionaryCreateMutable(kCFAllocatorDefault, 
																			   32,
																			   &kCFTypeDictionaryKeyCallBacks,
																			   &kCFTypeDictionaryValueCallBacks);
			
			CFStringRef displayName = CreateDisplayNameForURL(mURL);
			CFStringRef errorString = CFStringCreateWithFormat(kCFAllocatorDefault, 
															   NULL, 
															   CFCopyLocalizedString(CFSTR("The file “%@” is not a valid MPEG-4 file."), ""), 
															   displayName);
			
			CFDictionarySetValue(errorDictionary, 
								 kCFErrorLocalizedDescriptionKey, 
								 errorString);
			
			CFDictionarySetValue(errorDictionary, 
								 kCFErrorLocalizedFailureReasonKey, 
								 CFCopyLocalizedString(CFSTR("Not an MPEG-4 file"), ""));
			
			CFDictionarySetValue(errorDictionary, 
								 kCFErrorLocalizedRecoverySuggestionKey, 
								 CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), ""));
			
			CFRelease(errorString), errorString = NULL;
			CFRelease(displayName), displayName = NULL;
			
			*error = CFErrorCreate(kCFAllocatorDefault, 
								   AudioMetadataErrorDomain, 
								   AudioMetadataFileFormatNotSupportedError, 
								   errorDictionary);
			
			CFRelease(errorDictionary), errorDictionary = NULL;				
		}
		
		return false;
	}

	// Read the tags
	const MP4Tags *tags = MP4TagsAlloc();

	if(NULL == tags) {
		MP4Close(file), file = NULL;

		if(error)
			*error = CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainPOSIX, ENOMEM, NULL);

		return false;
	}
	
	MP4TagsFetch(tags, file);
	
	// Album title
	if(tags->album) {
		CFStringRef str = CFStringCreateWithCString(kCFAllocatorDefault, tags->album, kCFStringEncodingUTF8);
		CFDictionarySetValue(mMetadata, kMetadataAlbumTitleKey, str);
		CFRelease(str), str = NULL;
	}
	
	// Artist
	if(tags->artist) {
		CFStringRef str = CFStringCreateWithCString(kCFAllocatorDefault, tags->artist, kCFStringEncodingUTF8);
		CFDictionarySetValue(mMetadata, kMetadataArtistKey, str);
		CFRelease(str), str = NULL;
	}
	
	// Album Artist
	if(tags->albumArtist) {
		CFStringRef str = CFStringCreateWithCString(kCFAllocatorDefault, tags->albumArtist, kCFStringEncodingUTF8);
		CFDictionarySetValue(mMetadata, kMetadataAlbumArtistKey, str);
		CFRelease(str), str = NULL;
	}
	
	// Genre
	if(tags->genre) {
		CFStringRef str = CFStringCreateWithCString(kCFAllocatorDefault, tags->genre, kCFStringEncodingUTF8);
		CFDictionarySetValue(mMetadata, kMetadataGenreKey, str);
		CFRelease(str), str = NULL;
	}
	
	// Release date
	if(tags->releaseDate) {
		CFStringRef str = CFStringCreateWithCString(kCFAllocatorDefault, tags->releaseDate, kCFStringEncodingUTF8);
		CFDictionarySetValue(mMetadata, kMetadataReleaseDateKey, str);
		CFRelease(str), str = NULL;
	}
	
	// Composer
	if(tags->composer) {
		CFStringRef str = CFStringCreateWithCString(kCFAllocatorDefault, tags->composer, kCFStringEncodingUTF8);
		CFDictionarySetValue(mMetadata, kMetadataComposerKey, str);
		CFRelease(str), str = NULL;
	}
	
	// Comment
	if(tags->comments) {
		CFStringRef str = CFStringCreateWithCString(kCFAllocatorDefault, tags->comments, kCFStringEncodingUTF8);
		CFDictionarySetValue(mMetadata, kMetadataCommentKey, str);
		CFRelease(str), str = NULL;
	}
	
	// Track title
	if(tags->name) {
		CFStringRef str = CFStringCreateWithCString(kCFAllocatorDefault, tags->name, kCFStringEncodingUTF8);
		CFDictionarySetValue(mMetadata, kMetadataTitleKey, str);
		CFRelease(str), str = NULL;
	}
	
	// Track number
	if(tags->track) {
		if(tags->track->index) {
			CFNumberRef num = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt16Type, &tags->track->index);
			CFDictionarySetValue(mMetadata, kMetadataTrackNumberKey, num);
			CFRelease(num), num = NULL;
		}
		
		if(tags->track->total) {
			CFNumberRef num = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt16Type, &tags->track->total);
			CFDictionarySetValue(mMetadata, kMetadataTrackTotalKey, num);
			CFRelease(num), num = NULL;
		}
	}
	
	// Disc number
	if(tags->disk) {
		if(tags->disk->index) {
			CFNumberRef num = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt16Type, &tags->disk->index);
			CFDictionarySetValue(mMetadata, kMetadataDiscNumberKey, num);
			CFRelease(num), num = NULL;
		}
		
		if(tags->disk->total) {
			CFNumberRef num = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt16Type, &tags->disk->total);
			CFDictionarySetValue(mMetadata, kMetadataDiscTotalKey, num);
			CFRelease(num), num = NULL;
		}
	}
	
	// Compilation
	if(tags->compilation)
		CFDictionarySetValue(mMetadata, kMetadataCompilationKey, *(tags->compilation) ? kCFBooleanTrue : kCFBooleanFalse);
	
	// BPM
	if(tags->tempo) {
		
	}
	
	// Lyrics
	if(tags->lyrics) {
		CFStringRef str = CFStringCreateWithCString(kCFAllocatorDefault, tags->lyrics, kCFStringEncodingUTF8);
		CFDictionarySetValue(mMetadata, kMetadataLyricsKey, str);
		CFRelease(str), str = NULL;
	}
	
	// Album art
	if(tags->artworkCount) {
		for(uint32_t i = 0; i < tags->artworkCount; ++i) {
			CFDataRef data = CFDataCreate(kCFAllocatorDefault, reinterpret_cast<const UInt8 *>(tags->artwork[i].data), tags->artwork[i].size);
			CFDictionarySetValue(mMetadata, kAlbumArtFrontCoverKey, data);
			CFRelease(data), data = NULL;
		}
	}
	
	// ReplayGain
	// Reference loudness
	MP4ItmfItemList *items = MP4ItmfGetItemsByMeaning(file, "com.apple.iTunes", "replaygain_reference_loudness");
	if(NULL != items) {
		float referenceLoudnessValue;
		if(1 <= items->size && 1 <= items->elements[0].dataList.size && sscanf(reinterpret_cast<const char *>(items->elements[0].dataList.elements[0].value), "%f", &referenceLoudnessValue)) {
			CFNumberRef referenceLoudness = CFNumberCreate(kCFAllocatorDefault, kCFNumberFloatType, &referenceLoudnessValue);
			CFDictionaryAddValue(mMetadata, kReplayGainReferenceLoudnessKey, referenceLoudness);
			CFRelease(referenceLoudness), referenceLoudness = NULL;
		}
		
		MP4ItmfItemListFree(items), items = NULL;
	}
	
	// Track gain
	items = MP4ItmfGetItemsByMeaning(file, "com.apple.iTunes", "replaygain_track_gain");
	if(NULL != items) {
		float trackGainValue;
		if(1 <= items->size && 1 <= items->elements[0].dataList.size && sscanf(reinterpret_cast<const char *>(items->elements[0].dataList.elements[0].value), "%f", &trackGainValue)) {
			CFNumberRef trackGain = CFNumberCreate(kCFAllocatorDefault, kCFNumberFloatType, &trackGainValue);
			CFDictionaryAddValue(mMetadata, kReplayGainTrackGainKey, trackGain);
			CFRelease(trackGain), trackGain = NULL;
		}
		
		MP4ItmfItemListFree(items), items = NULL;
	}		
	
	// Track peak
	items = MP4ItmfGetItemsByMeaning(file, "com.apple.iTunes", "replaygain_track_peak");
	if(NULL != items) {
		float trackPeakValue;
		if(1 <= items->size && 1 <= items->elements[0].dataList.size && sscanf(reinterpret_cast<const char *>(items->elements[0].dataList.elements[0].value), "%f", &trackPeakValue)) {
			CFNumberRef trackPeak = CFNumberCreate(kCFAllocatorDefault, kCFNumberFloatType, &trackPeakValue);
			CFDictionaryAddValue(mMetadata, kReplayGainTrackPeakKey, trackPeak);
			CFRelease(trackPeak), trackPeak = NULL;
		}
		
		MP4ItmfItemListFree(items), items = NULL;
	}		
	
	// Album gain
	items = MP4ItmfGetItemsByMeaning(file, "com.apple.iTunes", "replaygain_album_gain");
	if(NULL != items) {
		float albumGainValue;
		if(1 <= items->size && 1 <= items->elements[0].dataList.size && sscanf(reinterpret_cast<const char *>(items->elements[0].dataList.elements[0].value), "%f", &albumGainValue)) {
			CFNumberRef albumGain = CFNumberCreate(kCFAllocatorDefault, kCFNumberFloatType, &albumGainValue);
			CFDictionaryAddValue(mMetadata, kReplayGainAlbumGainKey, albumGain);
			CFRelease(albumGain), albumGain = NULL;
		}
		
		MP4ItmfItemListFree(items), items = NULL;
	}		
	
	// Album peak
	items = MP4ItmfGetItemsByMeaning(file, "com.apple.iTunes", "replaygain_album_peak");
	if(NULL != items) {
		float albumPeakValue;
		if(1 <= items->size && 1 <= items->elements[0].dataList.size && sscanf(reinterpret_cast<const char *>(items->elements[0].dataList.elements[0].value), "%f", &albumPeakValue)) {
			CFNumberRef albumPeak = CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &albumPeakValue);
			CFDictionaryAddValue(mMetadata, kReplayGainAlbumPeakKey, albumPeak);
			CFRelease(albumPeak), albumPeak = NULL;
		}
		
		MP4ItmfItemListFree(items), items = NULL;
	}

	// Clean up
	MP4TagsFree(tags), tags = NULL;
	MP4Close(file), file = NULL;

	return true;
}
示例#22
0
void SFB::Audio::Metadata::ClearAllMetadata()
{
	CFDictionaryRemoveAllValues(mMetadata);
	CFDictionaryRemoveAllValues(mChangedMetadata);
	mPictures.clear();
}
示例#23
0
/// The call deallocate all allocated data, close all opened desckriptors.
void task_info_manager_free(void)
{
    CFDictionaryRemoveAllValues(tasks_dict);
    man_info_free();
}
示例#24
0
//-----------------------------------------------------------------------------------
//	TitleChanged
//-----------------------------------------------------------------------------------
void TValuePictControl::TitleChanged()
{
    CFDictionaryRemoveAllValues(mImageCache);
    ValueChanged();
}
示例#25
0
bool MODMetadata::ReadMetadata(CFErrorRef *error)
{
	// Start from scratch
	CFDictionaryRemoveAllValues(mMetadata);
	CFDictionaryRemoveAllValues(mChangedMetadata);
	
	UInt8 buf [PATH_MAX];
	if(!CFURLGetFileSystemRepresentation(mURL, false, buf, PATH_MAX))
		return false;

	CFStringRef pathExtension = CFURLCopyPathExtension(mURL);
	if(nullptr == pathExtension)
		return false;

	bool fileIsValid = false;
	if(kCFCompareEqualTo == CFStringCompare(pathExtension, CFSTR("it"), kCFCompareCaseInsensitive)) {
		auto stream = new TagLib::FileStream(reinterpret_cast<const char *>(buf), true);
		TagLib::IT::File file(stream);

		if(file.isValid()) {
			fileIsValid = true;
			CFDictionarySetValue(mMetadata, kPropertiesFormatNameKey, CFSTR("MOD (Impulse Tracker)"));

			if(file.audioProperties())
				AddAudioPropertiesToDictionary(mMetadata, file.audioProperties());

			if(file.tag())
				AddTagToDictionary(mMetadata, file.tag());
		}
	}
	else if(kCFCompareEqualTo == CFStringCompare(pathExtension, CFSTR("xm"), kCFCompareCaseInsensitive)) {
		auto stream = new TagLib::FileStream(reinterpret_cast<const char *>(buf), true);
		TagLib::XM::File file(stream);

		if(file.isValid()) {
			fileIsValid = true;
			CFDictionarySetValue(mMetadata, kPropertiesFormatNameKey, CFSTR("MOD (Extended Module)"));

			if(file.audioProperties())
				AddAudioPropertiesToDictionary(mMetadata, file.audioProperties());

			if(file.tag())
				AddTagToDictionary(mMetadata, file.tag());
		}
	}
	else if(kCFCompareEqualTo == CFStringCompare(pathExtension, CFSTR("s3m"), kCFCompareCaseInsensitive)) {
		auto stream = new TagLib::FileStream(reinterpret_cast<const char *>(buf), true);
		TagLib::S3M::File file(stream);

		if(file.isValid()) {
			fileIsValid = true;
			CFDictionarySetValue(mMetadata, kPropertiesFormatNameKey, CFSTR("MOD (ScreamTracker III)"));

			if(file.audioProperties())
				AddAudioPropertiesToDictionary(mMetadata, file.audioProperties());

			if(file.tag())
				AddTagToDictionary(mMetadata, file.tag());
		}
	}
	else if(kCFCompareEqualTo == CFStringCompare(pathExtension, CFSTR("mod"), kCFCompareCaseInsensitive)) {
		auto stream = new TagLib::FileStream(reinterpret_cast<const char *>(buf), true);
		TagLib::Mod::File file(stream);

		if(file.isValid()) {
			fileIsValid = true;
			CFDictionarySetValue(mMetadata, kPropertiesFormatNameKey, CFSTR("MOD (Protracker)"));

			if(file.audioProperties())
				AddAudioPropertiesToDictionary(mMetadata, file.audioProperties());

			if(file.tag())
				AddTagToDictionary(mMetadata, file.tag());
		}
	}

	CFRelease(pathExtension), pathExtension = nullptr;

	if(!fileIsValid) {
		if(error) {
			CFStringRef description = CFCopyLocalizedString(CFSTR("The file “%@” is not a valid MOD file."), "");
			CFStringRef failureReason = CFCopyLocalizedString(CFSTR("Not a MOD file"), "");
			CFStringRef recoverySuggestion = CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), "");
			
			*error = CreateErrorForURL(AudioMetadataErrorDomain, AudioMetadataInputOutputError, description, mURL, failureReason, recoverySuggestion);
			
			CFRelease(description), description = nullptr;
			CFRelease(failureReason), failureReason = nullptr;
			CFRelease(recoverySuggestion), recoverySuggestion = nullptr;
		}
		
		return false;
	}

	return true;
}
bool MonkeysAudioMetadata::ReadMetadata(CFErrorRef *error)
{
	// Start from scratch
	CFDictionaryRemoveAllValues(mMetadata);
	CFDictionaryRemoveAllValues(mChangedMetadata);
	
	UInt8 buf [PATH_MAX];
	if(!CFURLGetFileSystemRepresentation(mURL, false, buf, PATH_MAX))
		return false;
	
	TagLib::IOStream *stream = new TagLib::FileStream(reinterpret_cast<const char *>(buf), true);
	TagLib::APE::File file(stream);
	
	if(!file.isValid()) {
		if(NULL != error) {
			CFMutableDictionaryRef errorDictionary = CFDictionaryCreateMutable(kCFAllocatorDefault, 
																			   0,
																			   &kCFTypeDictionaryKeyCallBacks,
																			   &kCFTypeDictionaryValueCallBacks);
			
			CFStringRef displayName = CreateDisplayNameForURL(mURL);
			CFStringRef errorString = CFStringCreateWithFormat(kCFAllocatorDefault, 
															   NULL, 
															   CFCopyLocalizedString(CFSTR("The file “%@” is not a valid Monkey's Audio file."), ""), 
															   displayName);
			
			CFDictionarySetValue(errorDictionary, 
								 kCFErrorLocalizedDescriptionKey, 
								 errorString);
			
			CFDictionarySetValue(errorDictionary, 
								 kCFErrorLocalizedFailureReasonKey, 
								 CFCopyLocalizedString(CFSTR("Not a Monkey's Audio file"), ""));
			
			CFDictionarySetValue(errorDictionary, 
								 kCFErrorLocalizedRecoverySuggestionKey, 
								 CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), ""));
			
			CFRelease(errorString), errorString = NULL;
			CFRelease(displayName), displayName = NULL;
			
			*error = CFErrorCreate(kCFAllocatorDefault, 
								   AudioMetadataErrorDomain, 
								   AudioMetadataInputOutputError, 
								   errorDictionary);
			
			CFRelease(errorDictionary), errorDictionary = NULL;				
		}
		
		return false;
	}
	
	CFDictionarySetValue(mMetadata, kPropertiesFormatNameKey, CFSTR("Monkey's Audio"));
	
	if(file.audioProperties()) {
		AddAudioPropertiesToDictionary(mMetadata, file.audioProperties());
		
		if(0 != file.audioProperties()->bitsPerSample()) {
			int value = file.audioProperties()->bitsPerSample();
			CFNumberRef bitsPerChannel = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &value);
			CFDictionarySetValue(mMetadata, kPropertiesBitsPerChannelKey, bitsPerChannel);
			CFRelease(bitsPerChannel), bitsPerChannel = NULL;
		}
	}

	if(file.ID3v1Tag())
		AddID3v1TagToDictionary(mMetadata, file.ID3v1Tag());

	if(file.APETag())
		AddAPETagToDictionary(mMetadata, file.APETag());

	return true;
}
示例#27
0
int 
pSendDiscover(
			  CFUUIDBytes pHostGuid,
			  PNDAS_HIX_UNITDEVICE_ENTRY_DATA	data,
			  struct sockaddr_lpx				*host
			  )
{
	NDAS_HIX_DISCOVER_REQUEST	request;
	CFDataRef					cfdRequest = NULL;
		
	// Build Request.
	pBuildNHIXHeader(
					 &request.Header,
					 pHostGuid,
					 0,
					 NHIX_TYPE_DISCOVER,
					 sizeof(NDAS_HIX_SURRENDER_ACCESS_REQUEST)
					 );
	
	request.Data.EntryCount = 1;
	
	memcpy(&request.Data.Entry[0], data, sizeof(NDAS_HIX_UNITDEVICE_ENTRY_DATA));

	cfdRequest = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, (UInt8 *) &request, sizeof(NDAS_HIX_SURRENDER_ACCESS_REQUEST), kCFAllocatorNull);

	// Send Request.
	// Per Interface.
	
	CFSocketRef				sockets[4];
	int						numInterfaces = 0;
	
	for(int i = 0; i < numberOfNics; i++) {
	
		CFDataRef	address = 0;
		struct sockaddr_lpx	addr = { 0 };
				
		// Build Socket.
		sockets[numInterfaces] = CFSocketCreate (
												 kCFAllocatorDefault,
												 PF_LPX,
												 SOCK_DGRAM,
												 0,
												 0,
												 0,
												 NULL
												 );
		if(sockets[numInterfaces] == NULL) {
			syslog(LOG_ERR, "pSendSurrenderAccess: Can't Create socket for surrender Access request.");
			
			return -1;
		}
		
		// Bind Interface Address.
		addr.slpx_family = AF_LPX;
		addr.slpx_len = sizeof(struct sockaddr_lpx);
		addr.slpx_port = 0;
		memcpy(addr.slpx_node, ethernetData[i].macAddress, 6);
		
		address = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, 
											  (UInt8 *) &addr, 
											  sizeof(struct sockaddr_lpx), 
											  kCFAllocatorNull);
		
		CFSocketError socketError = CFSocketSetAddress (
														sockets[numInterfaces],
														address
														);
		if(socketError != kCFSocketSuccess) {
			syslog(LOG_ERR, "pSendSurrenderAccess: Can't Bind.");
			continue;
		}
		
		if(address)		CFRelease(address);		address= NULL;
		
		// Create Broadcast address.
		addr.slpx_family = AF_LPX;
		addr.slpx_len = sizeof(struct sockaddr_lpx);
		memset(addr.slpx_node, 0xff, 6);
		addr.slpx_port = htons(NDAS_HIX_LISTEN_PORT);
		
		address = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, 
											  (UInt8 *) &addr, 
											  sizeof(struct sockaddr_lpx), 
											  kCFAllocatorNull);
		
		// Set Broadcast Flag.
		int on = 1;
		if(setsockopt(CFSocketGetNative(sockets[numInterfaces]), SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) != 0) {
			syslog(LOG_ERR, "pSendSurrenderAccess: Error when set option.");
			return false;
		}
		
		// Send Request.
		socketError = CFSocketSendData (
										sockets[numInterfaces],
										address,
										cfdRequest,
										0
										);
		
		if(socketError != kCFSocketSuccess) {
			syslog(LOG_ERR, "pSendSurrenderAccess: Error when send reply.");
			return false;
		}
		
		numInterfaces++;
		
		if(address)		CFRelease(address);
		
	}
		
	if(cfdRequest)	CFRelease(cfdRequest);
	
	// Receive Reply.
	int			maxfdp1;
	socklen_t			fromlen;
	fd_set	rset;
	struct timeval timeout;
	int		bResult;
	struct sockaddr_lpx	addr = { 0 };
	int count;

	int numberOfHosts = 0;

	// HostID Dictionary.
	CFMutableDictionaryRef	HostIDs = CFDictionaryCreateMutable (
																 kCFAllocatorDefault,
																 0,
																 &kCFTypeDictionaryKeyCallBacks,
																 &kCFTypeDictionaryValueCallBacks
																 );
	if (NULL == HostIDs) {
		return -1;
	}
	
retry:

	FD_ZERO(&rset);
	
	maxfdp1 = 0;
	for(count = 0; count < numInterfaces; count++) {
		FD_SET( CFSocketGetNative(sockets[count]), &rset);
		maxfdp1 = (maxfdp1 > CFSocketGetNative(sockets[count])) ? maxfdp1 : CFSocketGetNative(sockets[count]);	
	}
	maxfdp1++;
	
	timeout.tv_sec = 2;	// 2 sec.
	timeout.tv_usec = 0;
			
	int result = select(maxfdp1, &rset, NULL, NULL, &timeout);
	if(result > 0) {
		NDAS_HIX_DISCOVER_REPLY	reply;
		int len;
		
		fromlen = sizeof(struct sockaddr_lpx);
		
		// Find socket.
		for(count = 0; count < numInterfaces; count++) {
			if (FD_ISSET( CFSocketGetNative(sockets[count]), &rset)) {
				
				len = recvfrom(CFSocketGetNative(sockets[count]), &reply, sizeof(NDAS_HIX_DISCOVER_REPLY), 0, (sockaddr *)&addr, &fromlen);
				
				if ( len < sizeof(NDAS_HIX_DISCOVER_REPLY) ) {
					syslog(LOG_WARNING, "pSendDiscover: Too short HIX Discover reply len : %d\n", len);
				
					continue;
				}
					
//				syslog(LOG_ERR, "pSendDiscover: Host %2x:%2x:%2x:%2x:%2x:%2x %d\n",
//					   addr.slpx_node[0], addr.slpx_node[1], addr.slpx_node[2], 
//					   addr.slpx_node[3], addr.slpx_node[4], addr.slpx_node[5], fromlen);
				
				//				syslog(LOG_ERR, "pSendDiscover: Access : %x", reply.Data.Entry[0].AccessType);
				
				if ( len >= sizeof(NDAS_HIX_DISCOVER_REPLY) ) {
					
					if (reply.Data.EntryCount == 1
						&& memcmp(data->DeviceId, reply.Data.Entry[0].DeviceId, 6) == 0
						&& data->UnitNo == reply.Data.Entry[0].UnitNo) {
						
						// Check Duplecation.
						CFDataRef hostID = CFDataCreate(
														kCFAllocatorDefault,
														reply.Header.HostId,
														16
														);
						if (NULL == hostID) {
							goto Out;
						}
						
						if (0 == CFDictionaryGetCountOfKey(HostIDs, hostID)) {
							
							// New Host.
							CFDictionarySetValue(
												 HostIDs,
												 hostID,
												 hostID);
														
							
							syslog(LOG_DEBUG, "[%s] HIX Replay Type : %d\n", __FUNCTION__, reply.Data.Entry[0].AccessType);
							
							switch (reply.Data.Entry[0].AccessType) {
								case NHIX_UDA_WRITE_ACCESS:
								case NHIX_UDA_READ_WRITE_ACCESS:
								case NHIX_UDA_SHARED_READ_WRITE_SECONDARY_ACCESS:
								case NHIX_UDA_SHARED_READ_WRITE_PRIMARY_ACCESS:
								{
									numberOfHosts++;
									
									// Copy Address.
									if (host) {
										memcpy(host, &addr, sizeof(struct sockaddr_lpx));
									}
								}
									break;
								default:
									break;
							}	
						} else {
							syslog(LOG_INFO, "pSendDiscover: Duplicated replay.");
						}
						
						CFRelease(hostID);
					}	
				}
			}
		}
		
		goto  retry;

	} else {
		// Error or timeout.
//		syslog(LOG_ERR, "pSendDiscover: select error or timeout %d Hosts %d\n", result, numberOfHosts);
		
		bResult =  numberOfHosts;
	}
	
	//if(socketSurrender) CFRelease(socketSurrender);     

Out:
		
	if (HostIDs) {
		CFDictionaryRemoveAllValues(HostIDs);
		CFRelease(HostIDs);
	}
	
	for(count = 0; count < numInterfaces; count++) {
		if(sockets[count]) CFRelease(sockets[count]);	
	}
		
	return bResult;
}