]>
Commit | Line | Data |
---|---|---|
b1ab9ed8 A |
1 | /* |
2 | * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. | |
3 | * | |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
6 | * This file contains Original Code and/or Modifications of Original Code | |
7 | * as defined in and that are subject to the Apple Public Source License | |
8 | * Version 2.0 (the 'License'). You may not use this file except in | |
9 | * compliance with the License. Please obtain a copy of the License at | |
10 | * http://www.opensource.apple.com/apsl/ and read it before using this | |
11 | * file. | |
12 | * | |
13 | * The Original Code and all software distributed under the License are | |
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. | |
18 | * Please see the License for the specific language governing rights and | |
19 | * limitations under the License. | |
20 | * | |
21 | * @APPLE_LICENSE_HEADER_END@ | |
22 | */ | |
23 | ||
24 | ||
25 | // | |
26 | // CoreFoundation related utilities | |
27 | // | |
28 | #include <security_utilities/cfutilities.h> | |
29 | #include <security_utilities/errors.h> | |
30 | #include <security_utilities/debugging.h> | |
31 | #include <cstdarg> | |
32 | #include <vector> | |
33 | ||
34 | ||
35 | namespace Security { | |
36 | ||
37 | ||
38 | ModuleNexus<CFEmptyArray> cfEmptyArray; | |
39 | ||
40 | CFEmptyArray::CFEmptyArray() | |
41 | { | |
42 | mArray = CFArrayCreate(NULL, NULL, 0, NULL); | |
43 | } | |
44 | ||
45 | ||
46 | // | |
47 | // Turn a C(++) string into a CFURLRef indicating a file: path | |
48 | // | |
49 | CFURLRef makeCFURL(const char *s, bool isDirectory, CFURLRef base) | |
50 | { | |
51 | if (base) | |
52 | return CFURLCreateWithFileSystemPathRelativeToBase(NULL, | |
53 | CFTempString(s), kCFURLPOSIXPathStyle, isDirectory, base); | |
54 | else | |
55 | return CFURLCreateWithFileSystemPath(NULL, | |
56 | CFTempString(s), kCFURLPOSIXPathStyle, isDirectory); | |
57 | } | |
58 | ||
59 | CFURLRef makeCFURL(CFStringRef s, bool isDirectory, CFURLRef base) | |
60 | { | |
61 | if (base) | |
62 | return CFURLCreateWithFileSystemPathRelativeToBase(NULL, s, kCFURLPOSIXPathStyle, isDirectory, base); | |
63 | else | |
64 | return CFURLCreateWithFileSystemPath(NULL, s, kCFURLPOSIXPathStyle, isDirectory); | |
65 | } | |
66 | ||
67 | ||
68 | // | |
69 | // CFMallocData objects | |
70 | // | |
71 | CFMallocData::operator CFDataRef () | |
72 | { | |
73 | CFDataRef result = makeCFDataMalloc(mData, mSize); | |
74 | if (!result) | |
75 | CFError::throwMe(); | |
76 | mData = NULL; // release ownership | |
77 | return result; | |
78 | } | |
79 | ||
80 | ||
81 | // | |
82 | // Make CFDictionaries from stuff | |
83 | // | |
84 | CFDictionaryRef makeCFDictionary(unsigned count, ...) | |
85 | { | |
86 | CFTypeRef keys[count], values[count]; | |
87 | va_list args; | |
88 | va_start(args, count); | |
89 | for (unsigned n = 0; n < count; n++) { | |
90 | keys[n] = va_arg(args, CFTypeRef); | |
91 | values[n] = va_arg(args, CFTypeRef); | |
92 | } | |
93 | va_end(args); | |
94 | return CFDictionaryCreate(NULL, (const void **)keys, (const void **)values, count, | |
95 | &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); | |
96 | } | |
97 | ||
98 | CFMutableDictionaryRef makeCFMutableDictionary() | |
99 | { | |
100 | if (CFMutableDictionaryRef r = CFDictionaryCreateMutable(NULL, 0, | |
101 | &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)) | |
102 | return r; | |
103 | CFError::throwMe(); | |
104 | } | |
105 | ||
106 | CFMutableDictionaryRef makeCFMutableDictionary(unsigned count, ...) | |
107 | { | |
108 | CFMutableDictionaryRef dict = makeCFMutableDictionary(); | |
109 | if (count > 0) { | |
110 | va_list args; | |
111 | va_start(args, count); | |
112 | for (unsigned n = 0; n < count; n++) { | |
113 | CFTypeRef key = va_arg(args, CFTypeRef); | |
114 | CFTypeRef value = va_arg(args, CFTypeRef); | |
115 | CFDictionaryAddValue(dict, key, value); | |
116 | } | |
117 | va_end(args); | |
118 | } | |
119 | return dict; | |
120 | } | |
121 | ||
122 | CFMutableDictionaryRef makeCFMutableDictionary(CFDictionaryRef dict) | |
123 | { | |
124 | if (CFMutableDictionaryRef r = CFDictionaryCreateMutableCopy(NULL, 0, dict)) | |
125 | return r; | |
126 | CFError::throwMe(); | |
127 | } | |
128 | ||
129 | CFDictionaryRef makeCFDictionaryFrom(CFDataRef data) | |
130 | { | |
131 | if (data) { | |
132 | CFPropertyListRef plist = CFPropertyListCreateFromXMLData(NULL, data, | |
133 | kCFPropertyListImmutable, NULL); | |
134 | if (plist && CFGetTypeID(plist) != CFDictionaryGetTypeID()) | |
135 | CFError::throwMe(); | |
136 | return CFDictionaryRef(plist); | |
137 | } else | |
138 | return NULL; | |
139 | ||
140 | } | |
141 | ||
142 | CFDictionaryRef makeCFDictionaryFrom(const void *data, size_t length) | |
143 | { | |
144 | return makeCFDictionaryFrom(CFTempData(data, length).get()); | |
145 | } | |
146 | ||
147 | ||
148 | // | |
149 | // Turn a CFString into a UTF8-encoded C++ string. | |
150 | // If release==true, the argument will be CFReleased even in case of error. | |
151 | // | |
152 | string cfString(CFStringRef str) | |
153 | { | |
154 | if (!str) | |
155 | return ""; | |
156 | // quick path first | |
157 | if (const char *s = CFStringGetCStringPtr(str, kCFStringEncodingUTF8)) { | |
158 | return s; | |
159 | } | |
160 | ||
161 | // need to extract into buffer | |
162 | string ret; | |
163 | CFIndex length = CFStringGetMaximumSizeForEncoding(CFStringGetLength(str), kCFStringEncodingUTF8); | |
164 | std::vector<char> buffer; | |
165 | buffer.resize(length + 1); | |
166 | if (CFStringGetCString(str, &buffer[0], length + 1, kCFStringEncodingUTF8)) | |
167 | ret = &buffer[0]; | |
168 | return ret; | |
169 | } | |
170 | ||
171 | string cfStringRelease(CFStringRef inStr) | |
172 | { | |
173 | CFRef<CFStringRef> str(inStr); | |
174 | return cfString(str); | |
175 | } | |
176 | ||
177 | string cfString(CFURLRef inUrl) | |
178 | { | |
179 | if (!inUrl) | |
180 | CFError::throwMe(); | |
181 | ||
182 | UInt8 buffer[PATH_MAX+1]; | |
183 | if (CFURLGetFileSystemRepresentation(inUrl, true, buffer, sizeof(buffer))) | |
184 | return string(reinterpret_cast<char *>(buffer)); | |
185 | else | |
186 | CFError::throwMe(); | |
187 | } | |
188 | ||
189 | string cfStringRelease(CFURLRef inUrl) | |
190 | { | |
191 | CFRef<CFURLRef> bundle(inUrl); | |
192 | return cfString(bundle); | |
193 | } | |
194 | ||
195 | string cfString(CFBundleRef inBundle) | |
196 | { | |
197 | if (!inBundle) | |
198 | CFError::throwMe(); | |
199 | return cfStringRelease(CFBundleCopyBundleURL(inBundle)); | |
200 | } | |
201 | ||
202 | string cfStringRelease(CFBundleRef inBundle) | |
203 | { | |
204 | CFRef<CFBundleRef> bundle(inBundle); | |
205 | return cfString(bundle); | |
206 | } | |
207 | ||
208 | ||
209 | string cfString(CFTypeRef it, OSStatus err) | |
210 | { | |
211 | if (it == NULL) | |
212 | MacOSError::throwMe(err); | |
213 | CFTypeID id = CFGetTypeID(it); | |
214 | if (id == CFStringGetTypeID()) | |
215 | return cfString(CFStringRef(it)); | |
216 | else if (id == CFURLGetTypeID()) | |
217 | return cfString(CFURLRef(it)); | |
218 | else if (id == CFBundleGetTypeID()) | |
219 | return cfString(CFBundleRef(it)); | |
220 | else | |
221 | return cfString(CFCopyDescription(it), true); | |
222 | } | |
223 | ||
224 | ||
225 | // | |
226 | // CFURLAccess wrappers for specific purposes | |
227 | // | |
228 | CFDataRef cfLoadFile(CFURLRef url) | |
229 | { | |
230 | assert(url); | |
231 | CFDataRef data; | |
232 | SInt32 error; | |
233 | if (CFURLCreateDataAndPropertiesFromResource(NULL, url, | |
234 | &data, NULL, NULL, &error)) { | |
235 | return data; | |
236 | } else { | |
237 | secdebug("cfloadfile", "failed to fetch %s error=%d", cfString(url).c_str(), int(error)); | |
238 | return NULL; | |
239 | } | |
240 | } | |
241 | ||
242 | ||
243 | // | |
244 | // CFArray creators | |
245 | // | |
246 | CFArrayRef makeCFArray(CFIndex count, ...) | |
247 | { | |
248 | CFTypeRef elements[count]; | |
249 | va_list args; | |
250 | va_start(args, count); | |
251 | for (CFIndex n = 0; n < count; n++) | |
252 | elements[n] = va_arg(args, CFTypeRef); | |
253 | va_end(args); | |
254 | return CFArrayCreate(NULL, elements, count, &kCFTypeArrayCallBacks); | |
255 | } | |
256 | ||
257 | CFMutableArrayRef makeCFMutableArray(CFIndex count, ...) | |
258 | { | |
259 | CFMutableArrayRef array = CFArrayCreateMutable(NULL, count, &kCFTypeArrayCallBacks); | |
260 | va_list args; | |
261 | va_start(args, count); | |
262 | for (CFIndex n = 0; n < count; n++) | |
263 | CFArrayAppendValue(array, va_arg(args, CFTypeRef)); | |
264 | va_end(args); | |
265 | return array; | |
266 | } | |
267 | ||
268 | ||
269 | } // end namespace Security |