#include #include "TransformFactory.h" #include "NullTransform.h" #include "Digest.h" #include "EncryptTransform.h" #include "GroupTransform.h" #include "Utilities.h" void TransformFactory::RegisterTransforms() { RegisterTransform_prelocked(NullTransform::MakeTransformFactory(), NULL); RegisterTransform_prelocked(DigestTransform::MakeTransformFactory(), NULL); RegisterTransform_prelocked(EncryptTransform::MakeTransformFactory(), NULL); RegisterTransform_prelocked(DecryptTransform::MakeTransformFactory(), NULL); RegisterTransform_prelocked(GroupTransform::MakeTransformFactory(), NULL); } CFMutableDictionaryRef TransformFactory::gRegistered; dispatch_once_t TransformFactory::gSetup; dispatch_queue_t TransformFactory::gRegisteredQueue; bool TransformFactory::RegisterTransform_prelocked(TransformFactory* tf, CFStringRef cfname) { if (!CFDictionaryContainsKey(gRegistered, tf->mCFType)) { CFDictionaryAddValue(gRegistered, tf->mCFType, tf); if (!cfname) { CoreFoundationObject::RegisterObject(tf->mCFType, false); } else { if (!CoreFoundationObject::FindObjectType(cfname)) { CoreFoundationObject::RegisterObject(cfname, false); } } } return true; } void TransformFactory::RegisterTransform(TransformFactory* tf, CFStringRef cfname) { dispatch_once_f(&gSetup, NULL, Setup); dispatch_barrier_sync(gRegisteredQueue, ^{ RegisterTransform_prelocked(tf, cfname); }); } void TransformFactory::Setup(void *) { gRegisteredQueue = dispatch_queue_create("com.apple.security.TransformFactory.Registered", DISPATCH_QUEUE_CONCURRENT); gRegistered = CFDictionaryCreateMutable(NULL, 0, &kCFCopyStringDictionaryKeyCallBacks, NULL); RegisterTransforms(); } void TransformFactory::Setup() { dispatch_once_f(&gSetup, NULL, Setup); } TransformFactory* TransformFactory::FindTransformFactoryByType(CFStringRef name) { dispatch_once_f(&gSetup, NULL, Setup); __block TransformFactory *ret; dispatch_barrier_sync(gRegisteredQueue, ^{ ret = (TransformFactory*)CFDictionaryGetValue(gRegistered, name); }); return ret; } SecTransformRef TransformFactory::MakeTransformWithType(CFStringRef type, CFErrorRef* baseError) { TransformFactory* tf = FindTransformFactoryByType(type); if (!tf) { if (baseError != NULL) { #if 0 // This version lists out all regestered transform types. // It is useful more for debugging then for anything else, // so it is great to keep around, but normally not so good // to run. dispatch_barrier_sync(gRegisteredQueue, ^(void) { CFMutableStringRef transformNames = CFStringCreateMutable(NULL, 0); CFIndex numberRegistered = CFDictionaryGetCount(gRegistered); CFStringRef names[numberRegistered]; CFDictionaryGetKeysAndValues(gRegistered, (const void**)names, NULL); for(int i = 0; i < numberRegistered; i++) { if (i != 0) { CFStringAppend(transformNames, CFSTR(", ")); } CFStringAppend(transformNames, names[i]); } *baseError = CreateSecTransformErrorRef(kSecTransformTransformIsNotRegistered, "The %s transform is not registered, choose from: %@", type,transformNames); }); #else *baseError = CreateSecTransformErrorRef(kSecTransformTransformIsNotRegistered, "The %s transform is not registered", type); #endif } return NULL; } else { return tf->Make(); } } TransformFactory::TransformFactory(CFStringRef type, bool registerGlobally, CFStringRef cftype) : mCFType(type) { if (registerGlobally) { CoreFoundationObject::RegisterObject(cftype ? cftype : type, false); } }