]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_transform/lib/TransformFactory.cpp
Security-57337.20.44.tar.gz
[apple/security.git] / OSX / libsecurity_transform / lib / TransformFactory.cpp
1 #include <libkern/OSAtomic.h>
2
3 #include "TransformFactory.h"
4 #include "NullTransform.h"
5 #include "Digest.h"
6 #include "EncryptTransform.h"
7 #include "GroupTransform.h"
8 #include "Utilities.h"
9
10
11 void TransformFactory::RegisterTransforms()
12 {
13 RegisterTransform_prelocked(NullTransform::MakeTransformFactory(), NULL);
14 RegisterTransform_prelocked(DigestTransform::MakeTransformFactory(), NULL);
15 RegisterTransform_prelocked(EncryptTransform::MakeTransformFactory(), NULL);
16 RegisterTransform_prelocked(DecryptTransform::MakeTransformFactory(), NULL);
17 RegisterTransform_prelocked(GroupTransform::MakeTransformFactory(), NULL);
18 }
19
20 CFMutableDictionaryRef TransformFactory::gRegistered;
21 dispatch_once_t TransformFactory::gSetup;
22 dispatch_queue_t TransformFactory::gRegisteredQueue;
23
24 bool TransformFactory::RegisterTransform_prelocked(TransformFactory* tf, CFStringRef cfname)
25 {
26 if (!CFDictionaryContainsKey(gRegistered, tf->mCFType)) {
27 CFDictionaryAddValue(gRegistered, tf->mCFType, tf);
28 if (!cfname) {
29 CoreFoundationObject::RegisterObject(tf->mCFType, false);
30 } else {
31 if (!CoreFoundationObject::FindObjectType(cfname)) {
32 CoreFoundationObject::RegisterObject(cfname, false);
33 }
34 }
35 }
36
37 return true;
38 }
39
40
41 void TransformFactory::RegisterTransform(TransformFactory* tf, CFStringRef cfname)
42 {
43 dispatch_once_f(&gSetup, NULL, Setup);
44 dispatch_barrier_sync(gRegisteredQueue, ^{
45 RegisterTransform_prelocked(tf, cfname);
46 });
47 }
48
49 void TransformFactory::Setup(void *)
50 {
51 gRegisteredQueue = dispatch_queue_create("com.apple.security.TransformFactory.Registered", DISPATCH_QUEUE_CONCURRENT);
52 gRegistered = CFDictionaryCreateMutable(NULL, 0, &kCFCopyStringDictionaryKeyCallBacks, NULL);
53 RegisterTransforms();
54 }
55
56 void TransformFactory::Setup()
57 {
58 dispatch_once_f(&gSetup, NULL, Setup);
59 }
60
61 TransformFactory* TransformFactory::FindTransformFactoryByType(CFStringRef name)
62 {
63 dispatch_once_f(&gSetup, NULL, Setup);
64 __block TransformFactory *ret;
65 dispatch_barrier_sync(gRegisteredQueue, ^{
66 ret = (TransformFactory*)CFDictionaryGetValue(gRegistered, name);
67 });
68 return ret;
69 }
70
71
72
73 SecTransformRef TransformFactory::MakeTransformWithType(CFStringRef type, CFErrorRef* baseError)
74 {
75 TransformFactory* tf = FindTransformFactoryByType(type);
76 if (!tf)
77 {
78 if (baseError != NULL)
79 {
80 #if 0
81 // This version lists out all regestered transform types.
82 // It is useful more for debugging then for anything else,
83 // so it is great to keep around, but normally not so good
84 // to run.
85 dispatch_barrier_sync(gRegisteredQueue, ^(void) {
86 CFMutableStringRef transformNames = CFStringCreateMutable(NULL, 0);
87 CFIndex numberRegistered = CFDictionaryGetCount(gRegistered);
88 CFStringRef names[numberRegistered];
89 CFDictionaryGetKeysAndValues(gRegistered, (const void**)names, NULL);
90 for(int i = 0; i < numberRegistered; i++) {
91 if (i != 0) {
92 CFStringAppend(transformNames, CFSTR(", "));
93 }
94 CFStringAppend(transformNames, names[i]);
95 }
96
97 *baseError = CreateSecTransformErrorRef(kSecTransformTransformIsNotRegistered,
98 "The %s transform is not registered, choose from: %@", type,transformNames);
99
100 });
101 #else
102 *baseError = CreateSecTransformErrorRef(kSecTransformTransformIsNotRegistered,
103 "The %s transform is not registered", type);
104 #endif
105 }
106
107 return NULL;
108 }
109 else
110 {
111 return tf->Make();
112 }
113 }
114
115
116
117 TransformFactory::TransformFactory(CFStringRef type, bool registerGlobally, CFStringRef cftype) : mCFType(type)
118 {
119 if (registerGlobally)
120 {
121 CoreFoundationObject::RegisterObject(cftype ? cftype : type, false);
122 }
123 }