]> git.saurik.com Git - apple/security.git/blob - cdsa/cdsa_utilities/cssmdb.cpp
Security-163.tar.gz
[apple/security.git] / cdsa / cdsa_utilities / cssmdb.cpp
1 /*
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
3 *
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
8 * using this file.
9 *
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
16 */
17
18
19 // cssmdb.cpp
20 //
21 //
22
23 #ifdef __MWERKS__
24 #define _CPP_UTILITIES
25 #endif
26
27 #include <Security/cssmdb.h>
28
29
30 //
31 // CssmDbAttributeInfo
32 //
33 bool
34 CssmDbAttributeInfo::operator <(const CssmDbAttributeInfo& other) const
35 {
36 if (nameFormat() < other.nameFormat()) return true;
37 if (other.nameFormat() < nameFormat()) return false;
38 // nameFormat's are equal.
39 switch (nameFormat())
40 {
41 case CSSM_DB_ATTRIBUTE_NAME_AS_STRING:
42 {
43 int res = strcmp(static_cast<const char *>(*this), static_cast<const char *>(other));
44 if (res < 0) return true;
45 if (res > 0) return false;
46 break;
47 }
48 case CSSM_DB_ATTRIBUTE_NAME_AS_OID:
49 if (static_cast<const CssmOid &>(*this) < static_cast<const CssmOid &>(other)) return true;
50 if (static_cast<const CssmOid &>(other) < static_cast<const CssmOid &>(*this)) return false;
51 break;
52 case CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER:
53 if (static_cast<uint32>(*this) < static_cast<uint32>(other)) return true;
54 if (static_cast<uint32>(other) < static_cast<uint32>(*this)) return false;
55 break;
56 default:
57 CssmError::throwMe(CSSMERR_DL_INVALID_FIELD_NAME);
58 }
59
60 return format() < other.format();
61 }
62
63 bool
64 CssmDbAttributeInfo::operator ==(const CssmDbAttributeInfo& other) const
65 {
66 if (nameFormat() != other.nameFormat()) return false;
67 if (format() != other.format()) return false;
68 switch (nameFormat())
69 {
70 case CSSM_DB_ATTRIBUTE_NAME_AS_STRING:
71 return !strcmp(static_cast<const char *>(*this), static_cast<const char *>(other));
72 case CSSM_DB_ATTRIBUTE_NAME_AS_OID:
73 return static_cast<const CssmOid &>(*this) == static_cast<const CssmOid &>(other);
74 case CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER:
75 return static_cast<uint32>(*this) == static_cast<uint32>(other);
76 default:
77 CssmError::throwMe(CSSMERR_DL_INVALID_FIELD_NAME);
78 }
79 }
80
81 //
82 // CssmDbAttributeData
83 //
84 void
85 CssmDbAttributeData::deleteValues(CssmAllocator &inAllocator)
86 {
87 // Loop over all values and delete each one.
88 if (Value)
89 {
90 for (uint32 anIndex = 0; anIndex < NumberOfValues; anIndex++)
91 {
92 if (Value[anIndex].Data)
93 {
94 inAllocator.free(Value[anIndex].Data);
95 }
96
97 Value[anIndex].Length = 0;
98 }
99
100 inAllocator.free(Value);
101 Value = NULL;
102 }
103
104 NumberOfValues = 0;
105 }
106
107 bool
108 CssmDbAttributeData::operator <(const CssmDbAttributeData &other) const
109 {
110 if (info() < other.info()) return true;
111 if (other.info() < info()) return false;
112
113 uint32 minSize = min(size(), other.size());
114 for (uint32 ix = 0; ix < minSize; ++ix)
115 {
116 if (at<const CssmData &>(ix) < other.at<const CssmData &>(ix))
117 return true;
118 if (other.at<const CssmData &>(ix) < at<const CssmData &>(ix))
119 return false;
120 }
121
122 return size() < other.size();
123 }
124
125 void
126 CssmDbAttributeData::add(const CssmDbAttributeData &src, CssmAllocator &inAllocator)
127 {
128 // Add all the values from another attribute into this attribute.
129
130 Value = reinterpret_cast<CSSM_DATA *>(inAllocator.realloc(Value,
131 sizeof(*Value) * (NumberOfValues + src.NumberOfValues)));
132
133 for (uint32 srcIndex = 0; srcIndex < src.NumberOfValues; srcIndex++) {
134 uint32 destIndex = NumberOfValues + srcIndex;
135
136 Value[destIndex].Length = 0;
137 Value[destIndex].Data = inAllocator.alloc<uint8>(src.Value[srcIndex].Length);
138 Value[destIndex].Length = src.Value[srcIndex].Length;
139 memcpy(Value[destIndex].Data, src.Value[srcIndex].Data, src.Value[srcIndex].Length);
140 }
141
142 NumberOfValues += src.NumberOfValues;
143 }
144
145 bool
146 CssmDbAttributeData::deleteValue(const CssmData &src, CssmAllocator &inAllocator)
147 {
148 // Delete a single value from this attribute, if it is present.
149
150 for (uint32 i = 0; i < NumberOfValues; i++)
151 if (CssmData::overlay(Value[i]) == src)
152 {
153 inAllocator.free(Value[i].Data);
154 Value[i].Length = 0;
155
156 NumberOfValues--;
157 Value[i].Data = Value[NumberOfValues].Data;
158 Value[i].Length = Value[NumberOfValues].Length;
159
160 return true;
161 }
162
163 return false;
164 }
165
166 // Delete those values found in src from this object, if they are present.
167 // Warning: This is O(N^2) worst case; if this becomes a performance bottleneck
168 // then it will need to be changed.
169
170 void
171 CssmDbAttributeData::deleteValues(const CssmDbAttributeData &src, CssmAllocator &inAllocator)
172 {
173 for (uint32 i = 0; i < src.NumberOfValues; i++)
174 deleteValue(CssmData::overlay(src.Value[i]), inAllocator);
175 }
176
177 //
178 // CssmDbRecordAttributeData
179 //
180 CssmDbAttributeData *
181 CssmDbRecordAttributeData::find(const CSSM_DB_ATTRIBUTE_INFO &inInfo)
182 {
183 const CssmDbAttributeInfo &anInfo = CssmDbAttributeInfo::overlay(inInfo);
184 for (uint32 ix = 0; ix < size(); ++ix)
185 {
186 if (at(ix).info() == anInfo)
187 return &at(ix);
188 }
189
190 return NULL;
191 }
192
193 bool
194 CssmDbRecordAttributeData::operator <(const CssmDbRecordAttributeData &other) const
195 {
196 if (recordType() < other.recordType()) return true;
197 if (other.recordType() < recordType()) return false;
198 if (semanticInformation() < other.semanticInformation()) return true;
199 if (other.semanticInformation() < semanticInformation()) return false;
200
201 uint32 minSize = min(size(), other.size());
202 for (uint32 ix = 0; ix < minSize; ++ix)
203 {
204 if (at(ix) < other.at(ix))
205 return true;
206 if (other.at(ix) < at(ix))
207 return false;
208 }
209
210 return size() < other.size();
211 }
212
213
214 //
215 // CssmAutoDbRecordAttributeData
216 //
217 CssmAutoDbRecordAttributeData::~CssmAutoDbRecordAttributeData()
218 {
219 clear();
220 }
221
222 void
223 CssmAutoDbRecordAttributeData::clear()
224 {
225 deleteValues();
226 ArrayBuilder<CssmDbAttributeData>::clear();
227 }
228
229
230
231 static bool CompareAttributeInfos (const CSSM_DB_ATTRIBUTE_INFO &a, const CSSM_DB_ATTRIBUTE_INFO &b)
232 {
233 // check the format of the names
234 if (a.AttributeNameFormat != b.AttributeNameFormat)
235 {
236 return false;
237 }
238
239 switch (a.AttributeNameFormat)
240 {
241 case CSSM_DB_ATTRIBUTE_NAME_AS_STRING:
242 {
243 return strcmp (a.Label.AttributeName, b.Label.AttributeName) == 0;
244 }
245
246 case CSSM_DB_ATTRIBUTE_NAME_AS_OID:
247 {
248 if (a.Label.AttributeOID.Length != b.Label.AttributeOID.Length)
249 {
250 return false;
251 }
252
253 return memcmp (a.Label.AttributeOID.Data, b.Label.AttributeOID.Data, a.Label.AttributeOID.Length) == 0;
254 }
255
256
257 case CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER:
258 {
259 return a.Label.AttributeID == b.Label.AttributeID;
260 }
261 }
262
263 return true; // just to keep the compiler from complaining
264 }
265
266
267
268 CssmDbAttributeData* CssmAutoDbRecordAttributeData::findAttribute (const CSSM_DB_ATTRIBUTE_INFO &info)
269 {
270 // walk through the data, looking for an attribute of the same type
271 unsigned i;
272 for (i = 0; i < size (); ++i)
273 {
274 CssmDbAttributeData& d = at (i);
275 CSSM_DB_ATTRIBUTE_INFO &inInfo = d.info ();
276
277 if (CompareAttributeInfos (info, inInfo))
278 {
279 return &d;
280 }
281 }
282
283 // found nothing?
284 return NULL;
285 }
286
287
288
289 CssmDbAttributeData& CssmAutoDbRecordAttributeData::getAttributeReference (const CSSM_DB_ATTRIBUTE_INFO &info)
290 {
291 // Either find an existing reference to an attribute in the list, or make a new one.
292 CssmDbAttributeData *anAttr = findAttribute (info);
293 if (anAttr) // was this already in the list?
294 {
295 // clean it up
296 anAttr->deleteValues (mValueAllocator);
297 }
298 else
299 {
300 // make a new one
301 anAttr = &add();
302 }
303
304 return *anAttr;
305 }
306
307
308
309 CssmDbAttributeData &
310 CssmAutoDbRecordAttributeData::add(const CSSM_DB_ATTRIBUTE_INFO &info)
311 {
312 CssmDbAttributeData& anAttr = getAttributeReference (info);
313 anAttr.info(info);
314 return anAttr;
315 }
316
317 CssmDbAttributeData &
318 CssmAutoDbRecordAttributeData::add(const CSSM_DB_ATTRIBUTE_INFO &info, const CssmPolyData &value)
319 {
320 CssmDbAttributeData &anAttr = getAttributeReference (info);
321 anAttr.set(info, value, mValueAllocator);
322 return anAttr;
323 }
324
325 //
326 // CssmAutoQuery
327 //
328 CssmAutoQuery::CssmAutoQuery(const CSSM_QUERY &query, CssmAllocator &allocator)
329 : ArrayBuilder<CssmSelectionPredicate>(CssmSelectionPredicate::overlayVar(SelectionPredicate),
330 NumSelectionPredicates,
331 query.NumSelectionPredicates, allocator)
332 {
333 RecordType = query.RecordType;
334 Conjunctive = query.Conjunctive;
335 QueryLimits = query.QueryLimits;
336 QueryFlags = query.QueryFlags;
337 for (uint32 ix = 0; ix < query.NumSelectionPredicates; ++ix)
338 add().set(query.SelectionPredicate[ix], allocator);
339 }
340
341 CssmAutoQuery::~CssmAutoQuery()
342 {
343 clear();
344 }
345
346 void
347 CssmAutoQuery::clear()
348 {
349 deleteValues();
350 ArrayBuilder<CssmSelectionPredicate>::clear();
351 }
352
353 CssmSelectionPredicate &
354 CssmAutoQuery::add(CSSM_DB_OPERATOR dbOperator, const CSSM_DB_ATTRIBUTE_INFO &info, const CssmPolyData &value)
355 {
356 CssmSelectionPredicate &predicate = add();
357 predicate.dbOperator(dbOperator);
358 predicate.set(info, value, allocator());
359 return predicate;
360 }