1/* 2 * Copyright (c) 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#include "Relation.h" 25#include <time.h> 26#include "CommonCode.h" 27 28Value::Value (CSSM_DB_ATTRIBUTE_FORMAT format) : mBaseFormat (format) 29{ 30} 31 32 33 34Value::~Value () 35{ 36} 37 38 39 40Value* Value::MakeValueFromAttributeData (const CSSM_DB_ATTRIBUTE_DATA& info) 41{ 42 switch (info.Info.AttributeFormat) { 43 case CSSM_DB_ATTRIBUTE_FORMAT_STRING: 44 return new StringValue ((char*) info.Value->Data, info.Value->Length); 45 46 case CSSM_DB_ATTRIBUTE_FORMAT_SINT32: 47 return new SInt32Value (*(sint32*) info.Value->Data); 48 49 case CSSM_DB_ATTRIBUTE_FORMAT_UINT32: 50 return new UInt32Value (*(uint32*) info.Value->Data); 51 52 case CSSM_DB_ATTRIBUTE_FORMAT_BIG_NUM: 53 return new BigNumValue (info.Value->Data, info.Value->Length); 54 55 case CSSM_DB_ATTRIBUTE_FORMAT_REAL: 56 return new RealValue (*(double*) info.Value->Data); 57 58 case CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE: 59 return new TimeDateValue ((char*) info.Value->Data); 60 61 case CSSM_DB_ATTRIBUTE_FORMAT_BLOB: 62 return new BlobValue (info.Value->Data, info.Value->Length); 63 } 64 CSSMError::ThrowCSSMError (CSSMERR_DL_UNSUPPORTED_FIELD_FORMAT); 65} 66 67 68 69StringValue::StringValue (const char* value) : Value (CSSM_DB_ATTRIBUTE_FORMAT_STRING), mValue (value) 70{ 71} 72 73 74 75StringValue::StringValue (const char* value, uint32 length) : Value (CSSM_DB_ATTRIBUTE_FORMAT_STRING), mValue (value, length) 76{ 77} 78 79 80 81uint8* StringValue::CloneContents (AttachedInstance *ai, uint32 &numberOfItems, uint32 &size) 82{ 83 // clone the string 84 size = mValue.length (); 85 char* s = (char*) ai->malloc (size + 1); 86 strcpy (s, mValue.c_str ()); 87 numberOfItems = 1; 88 return (uint8*) s; 89} 90 91 92 93bool StringValue::Compare (Value* v, CSSM_DB_OPERATOR op) 94{ 95 if (v->GetValueType () != mBaseFormat) 96 CSSMError::ThrowCSSMError (CSSMERR_DL_INCOMPATIBLE_FIELD_FORMAT); 97 98 StringValue* sv = (StringValue*) v; 99 100 const char* vRaw = sv->GetRawValue (); 101 const char* myRaw = GetRawValue (); 102 103 switch (op) { 104 case CSSM_DB_EQUAL: 105 return strcmp (myRaw, vRaw) == 0; 106 case CSSM_DB_NOT_EQUAL: 107 return strcmp (myRaw, vRaw) != 0; 108 case CSSM_DB_LESS_THAN: 109 return strcmp (myRaw, vRaw) < 0; 110 case CSSM_DB_GREATER_THAN: 111 return strcmp (myRaw, vRaw) > 0; 112 default: 113 break; 114 } 115 116 const char* strLocation = strstr (vRaw, myRaw); 117 118 switch (op) { 119 case CSSM_DB_CONTAINS: 120 return strLocation != NULL; 121 case CSSM_DB_CONTAINS_INITIAL_SUBSTRING: 122 return strLocation == myRaw; 123 case CSSM_DB_CONTAINS_FINAL_SUBSTRING: 124 int vRawLen = strlen (vRaw); 125 int myRawLen = strlen (myRaw); 126 return strLocation == myRaw + myRawLen - vRawLen; 127 } 128 129 CSSMError::ThrowCSSMError (CSSMERR_DL_UNSUPPORTED_OPERATOR); 130} 131 132 133 134SInt32Value::SInt32Value (const sint32 value) : Value (CSSM_DB_ATTRIBUTE_FORMAT_SINT32), mValue (value) {} 135 136 137 138bool SInt32Value::Compare (Value* v, CSSM_DB_OPERATOR op) 139{ 140 if (v->GetValueType () != mBaseFormat) 141 CSSMError::ThrowCSSMError (CSSMERR_DL_INCOMPATIBLE_FIELD_FORMAT); 142 143 SInt32Value* sv = (SInt32Value*) v; 144 145 sint32 vRaw = sv->GetRawValue (); 146 sint32 myRaw = GetRawValue (); 147 148 switch (op) { 149 case CSSM_DB_EQUAL: 150 return vRaw == myRaw; 151 case CSSM_DB_NOT_EQUAL: 152 return vRaw != myRaw; 153 case CSSM_DB_LESS_THAN: 154 return myRaw < vRaw; 155 case CSSM_DB_GREATER_THAN: 156 return myRaw > vRaw; 157 } 158 159 CSSMError::ThrowCSSMError (CSSMERR_DL_UNSUPPORTED_OPERATOR); 160} 161 162 163 164uint8* SInt32Value::CloneContents (AttachedInstance* ai, uint32 &numberOfItems, uint32 &size) 165{ 166 sint32* result = (sint32*) ai->malloc (sizeof (sint32)); 167 *result = mValue; 168 size = sizeof (sint32); 169 numberOfItems = 1; 170 return (uint8*) result; 171} 172 173 174 175UInt32Value::UInt32Value (const uint32 value) : Value (CSSM_DB_ATTRIBUTE_FORMAT_UINT32) 176{ 177 mValue = value; 178} 179 180 181 182uint8* UInt32Value::CloneContents (AttachedInstance *ai, uint32 &numberOfItems, uint32 &size) 183{ 184 uint32* result = (uint32*) ai->malloc (sizeof (uint32)); 185 *result = mValue; 186 size = sizeof (uint32); 187 numberOfItems = 1; 188 return (uint8*) result; 189} 190 191 192 193bool UInt32Value::Compare (Value* v, CSSM_DB_OPERATOR op) 194{ 195 if (v->GetValueType () != mBaseFormat) 196 CSSMError::ThrowCSSMError (CSSMERR_DL_INCOMPATIBLE_FIELD_FORMAT); 197 198 UInt32Value* sv = (UInt32Value*) v; 199 200 uint32 vRaw = sv->GetRawValue (); 201 uint32 myRaw = GetRawValue (); 202 203 switch (op) { 204 case CSSM_DB_EQUAL: 205 return vRaw == myRaw; 206 case CSSM_DB_NOT_EQUAL: 207 return vRaw != myRaw; 208 case CSSM_DB_LESS_THAN: 209 return myRaw < vRaw; 210 case CSSM_DB_GREATER_THAN: 211 return myRaw > vRaw; 212 } 213 214 CSSMError::ThrowCSSMError (CSSMERR_DL_UNSUPPORTED_OPERATOR); 215} 216 217 218 219BigNumValue::BigNumValue (const uint8* value, size_t size) : Value (CSSM_DB_ATTRIBUTE_FORMAT_BIG_NUM), mLengthCache (-1) 220{ 221 mSize = size; 222 mValue = new uint8[size]; 223 memmove (mValue, value, size); 224} 225 226 227 228BigNumValue::~BigNumValue () 229{ 230 delete mValue; 231} 232 233 234 235uint8* BigNumValue::CloneContents (AttachedInstance *ai, uint32 &numberOfItems, uint32 &size) 236{ 237 uint8* returnValue = (uint8*) ai->malloc (mSize); 238 size = mSize; 239 memmove (returnValue, mValue, size); 240 numberOfItems = 1; 241 return (uint8*) returnValue; 242} 243 244 245 246 247bool BigNumValue::GetSignBit () 248{ 249 return mValue[mSize - 1] & 0x80 != 0; 250} 251 252 253 254int BigNumValue::GetAdjustedLength () 255{ 256 if (mLengthCache != -1) 257 return mLengthCache; 258 259 // find the first non-zero byte. 260 261 // Handle the sign bit properly 262 int i = mSize - 1; 263 int value = mValue[i--] & 0x7F; 264 265 // search for the first non-zero byte 266 while (i >= 0 && value == 0) 267 value = mValue[i--]; 268 269 i += 1; 270 if (i == 0) // zero length? 271 mLengthCache = 1; 272 else 273 mLengthCache = i; 274 275 return mLengthCache; 276} 277 278 279 280int BigNumValue::GetByte (int i) 281{ 282 // return the bytes of the bignum, compensating for the sign bit 283 if (i == (int) (mSize - 1)) 284 return mValue[i] & 0x7F; 285 return mValue[i]; 286} 287 288 289 290bool BigNumValue::CompareSignBits (BigNumValue *v, int &result) 291{ 292 bool compareSignBit = v->GetSignBit (); 293 bool mySignBit = GetSignBit (); 294 295 if (!compareSignBit && mySignBit) { 296 result = 1; 297 return true; 298 } else if (compareSignBit && !mySignBit) { 299 result = -1; 300 return true; 301 } 302 303 return false; 304} 305 306 307 308bool BigNumValue::CompareLengths (BigNumValue *v, int &result) 309{ 310 int vSize = v->GetAdjustedLength (); 311 int mySize = GetAdjustedLength (); 312 313 if (vSize == mySize) 314 return false; 315 316 result = vSize - mySize; 317 return true; 318} 319 320 321 322bool BigNumValue::CompareValues (BigNumValue *v, int &result) 323{ 324 // handle the first byte specially, since it contains the sign bit 325 int offset = GetAdjustedLength () - 1; 326 327 result = v->GetByte(offset) - GetByte (offset); 328 offset -= 1; 329 330 while (offset >= 0 && result == 0) 331 result = v->GetByte(offset) - GetByte (offset); 332 offset -= 1; 333 334 return true; 335} 336 337 338 339bool BigNumValue::Compare (Value *v, CSSM_DB_OPERATOR op) 340{ 341 if (v->GetValueType () != mBaseFormat) 342 CSSMError::ThrowCSSMError (CSSMERR_DL_INCOMPATIBLE_FIELD_FORMAT); 343 344 BigNumValue* sv = (BigNumValue*) v; 345 346 int result; 347 348 if (!CompareSignBits (sv, result)) 349 if (!CompareLengths (sv, result)) 350 CompareValues (sv, result); 351 352 switch (op) { 353 case CSSM_DB_EQUAL: 354 return result == 0; 355 case CSSM_DB_NOT_EQUAL: 356 return result != 0; 357 case CSSM_DB_LESS_THAN: 358 return result < 0; 359 case CSSM_DB_GREATER_THAN: 360 return result > 0; 361 } 362 363 CSSMError::ThrowCSSMError (CSSMERR_DL_UNSUPPORTED_OPERATOR); 364} 365 366 367 368RealValue::RealValue (double value) : Value (CSSM_DB_ATTRIBUTE_FORMAT_REAL), mValue (value) {} 369 370 371 372uint8* RealValue::CloneContents (AttachedInstance *ai, uint32 &numberOfItems, uint32 &size) 373{ 374 double* result = (double*) ai->malloc (sizeof (double)); 375 *result = (double) mValue; 376 size = sizeof (double); 377 numberOfItems = 1; 378 return (uint8*) result; 379} 380 381 382 383bool RealValue::Compare (Value* v, CSSM_DB_OPERATOR op) 384{ 385 if (v->GetValueType () != mBaseFormat) 386 CSSMError::ThrowCSSMError (CSSMERR_DL_INCOMPATIBLE_FIELD_FORMAT); 387 388 RealValue* sv = (RealValue*) v; 389 390 double vRaw = sv->GetRawValue (); 391 double myRaw = GetRawValue (); 392 393 switch (op) { 394 case CSSM_DB_EQUAL: 395 return vRaw == myRaw; 396 case CSSM_DB_NOT_EQUAL: 397 return vRaw != myRaw; 398 case CSSM_DB_LESS_THAN: 399 return myRaw < vRaw; 400 case CSSM_DB_GREATER_THAN: 401 return myRaw > vRaw; 402 } 403 404 CSSMError::ThrowCSSMError (CSSMERR_DL_UNSUPPORTED_OPERATOR); 405} 406 407 408 409TimeDateValue::TimeDateValue (time_t tv) : Value (CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE), mValue (tv) {} 410 411 412 413int CharToNum (char c) 414{ 415 return c - '0'; 416} 417 418 419 420TimeDateValue::TimeDateValue (const char* td) : Value (CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE) 421{ 422 struct tm tmStruct; 423 memset (&tmStruct, 0, sizeof (tmStruct)); 424 425 tmStruct.tm_year = CharToNum (td[0]) * 1000 + CharToNum (td[1]) * 100 + CharToNum (td[2]) * 10 + CharToNum (td[3]) - 1900; 426 tmStruct.tm_mon = CharToNum (td[4]) * 10 + CharToNum (td[5]) - 1; 427 tmStruct.tm_mday = CharToNum (td[6]) * 10 + CharToNum (td[7]); 428 tmStruct.tm_hour = CharToNum (td[8]) * 10 + CharToNum (td[9]); 429 tmStruct.tm_min = CharToNum (td[10]) * 10 + CharToNum (td[11]); 430 tmStruct.tm_sec = CharToNum (td[12]) * 10 + CharToNum (td[13]); 431 432 mValue = timegm (&tmStruct); 433} 434 435 436 437uint8* TimeDateValue::CloneContents (AttachedInstance *ai, uint32 &numberOfItems, uint32 &size) 438{ 439 struct tm timeStruct; 440 gmtime_r (&mValue, &timeStruct); 441 442 char buffer[32]; 443 sprintf (buffer, "%04d%02d%02d%0d2%0d%02dZ", timeStruct.tm_year, 444 timeStruct.tm_mon + 1, 445 timeStruct.tm_mday, 446 timeStruct.tm_hour, 447 timeStruct.tm_min, 448 timeStruct.tm_sec); 449 size = strlen (buffer); 450 char* result = (char*) ai->malloc (size + 1); 451 strcpy (result, buffer); 452 numberOfItems = 1; 453 return (uint8*) result; 454} 455 456 457 458bool TimeDateValue::Compare (Value* v, CSSM_DB_OPERATOR op) 459{ 460 if (v->GetValueType () != mBaseFormat) 461 { 462 CSSMError::ThrowCSSMError (CSSMERR_DL_INCOMPATIBLE_FIELD_FORMAT); 463 } 464 465 TimeDateValue* sv = (TimeDateValue*) v; 466 467 time_t vRaw = sv->GetRawValue (); 468 time_t myRaw = GetRawValue (); 469 470 switch (op) { 471 case CSSM_DB_EQUAL: 472 return vRaw == myRaw; 473 case CSSM_DB_NOT_EQUAL: 474 return vRaw != myRaw; 475 case CSSM_DB_LESS_THAN: 476 return myRaw < vRaw; 477 case CSSM_DB_GREATER_THAN: 478 return myRaw > vRaw; 479 } 480 481 CSSMError::ThrowCSSMError (CSSMERR_DL_UNSUPPORTED_OPERATOR); 482} 483 484 485 486BlobValue::BlobValue (const uint8* value, size_t size) : Value (CSSM_DB_ATTRIBUTE_FORMAT_BLOB), mSize (size) 487{ 488 mValue = new uint8[size]; 489 memmove (mValue, value, size); 490} 491 492 493 494BlobValue::BlobValue (CSSM_DATA data) : Value (CSSM_DB_ATTRIBUTE_FORMAT_BLOB), mSize (data.Length) 495{ 496 mValue = new uint8[data.Length]; 497 memmove (mValue, data.Data, data.Length); 498} 499 500 501BlobValue::BlobValue (CFDataRef data) : Value (CSSM_DB_ATTRIBUTE_FORMAT_BLOB), mSize (CFDataGetLength(data)) 502{ 503 mSize = CFDataGetLength(data); 504 mValue = new uint8[mSize]; 505 memmove (mValue, CFDataGetBytePtr(data), mSize); 506} 507 508BlobValue::BlobValue (CFStringRef data) : Value (CSSM_DB_ATTRIBUTE_FORMAT_BLOB), mSize (CFStringGetLength(data)) 509{ 510 mValue = new uint8[mSize+1]; 511 CFStringGetCString(data, (char *)mValue, mSize+1, kCFStringEncodingASCII); 512} 513 514 515BlobValue::~BlobValue () 516{ 517 delete mValue; 518} 519 520 521#ifdef NEVER 522template<class T> void ComputeKMPNext (const T* substring, int64_t* nextArray, size_t substringLength) 523{ 524 int i, j; 525 nextArray[0] = -1; 526 for (i = 0, j = -1; i < (ssize_t) substringLength; i++, j++, nextArray[i] = j) 527 { 528 while ((j >= 0) && (substring[i] != substring[j])) 529 { 530 j = nextArray[j]; 531 } 532 } 533} 534 535 536 537template<class T> int KMPSearch (const T* substring, size_t subLength, const T* mainString, size_t mainLength) 538{ 539 int i, j; 540 541 // make a "next" array 542 int64_t* nextArray = new int64_t[subLength]; 543 ComputeKMPNext (substring, nextArray, subLength); 544 545 for (i = 0, j = 0; j < (ssize_t) subLength && i < (ssize_t) mainLength; ++i, ++j) 546 { 547 while ((j >= 0) && (mainString[i] != substring[j])) 548 { 549 j = nextArray[j]; 550 } 551 } 552 553 delete [] nextArray; 554 555 if (j == (ssize_t) subLength) 556 { 557 return i - subLength; 558 } 559 560 return i; 561} 562#endif 563 564 565static bool CompareBlobs (const uint8* a, size_t aLength, const uint8* b, size_t bLength) 566{ 567 if (aLength != bLength) return false; 568 for (size_t i = 0; i < aLength; ++i) 569 if (a[i] != b[i]) return false; 570 return true; 571} 572 573 574 575uint8* BlobValue::CloneContents (AttachedInstance *ai, uint32 &numberOfItems, uint32 &size) 576{ 577 // clone the data 578 size = mSize; 579 uint8* returnValue = (uint8*) ai->malloc (mSize); 580 memmove (returnValue, mValue, mSize); 581 numberOfItems = 1; 582 return (uint8*) returnValue; 583} 584 585 586 587bool BlobValue::Compare (Value* v, CSSM_DB_OPERATOR op) 588{ 589 if (v->GetValueType () != mBaseFormat) 590 CSSMError::ThrowCSSMError (CSSMERR_DL_INCOMPATIBLE_FIELD_FORMAT); 591 592 BlobValue* sv = (BlobValue*) v; 593 594 const uint8 *vRaw, *myRaw; 595 size_t vLength, myLength; 596 597 vRaw = sv->GetRawValue (vLength); 598 myRaw = GetRawValue (myLength); 599 600 switch (op) 601 { 602 case CSSM_DB_CONTAINS: 603 case CSSM_DB_EQUAL: 604 case CSSM_DB_CONTAINS_INITIAL_SUBSTRING: 605 case CSSM_DB_CONTAINS_FINAL_SUBSTRING: 606 return CompareBlobs (vRaw, vLength, myRaw, myLength); 607 608 case CSSM_DB_NOT_EQUAL: 609 return !CompareBlobs (vRaw, vLength, myRaw, myLength); 610 } 611 612 CSSMError::ThrowCSSMError (CSSMERR_DL_UNSUPPORTED_OPERATOR); 613} 614 615 616 617Tuple::Tuple () {} 618Tuple::~Tuple () {} 619 620 621 622Query::Query (Relation* relation, const CSSM_QUERY *queryBase) : mSelectionPredicates (NULL), mRelation (relation) 623{ 624 mConjunction = queryBase->Conjunctive; 625 626 // fill out the rest of the fields based on queryBase 627 628 mNumSelectionPredicates = queryBase->NumSelectionPredicates; 629 if (mNumSelectionPredicates >= 2 && mConjunction == CSSM_DB_NONE) 630 CSSMError::ThrowCSSMError (CSSMERR_DL_UNSUPPORTED_QUERY); 631 632 if (mNumSelectionPredicates >= 1) { 633 mSelectionPredicates = new CssmSelectionPredicate[mNumSelectionPredicates]; 634 635 // copy the selection predicates 636 unsigned i; 637 for (i = 0; i < mNumSelectionPredicates; ++i) 638 mSelectionPredicates[i] = *(CssmSelectionPredicate*) (queryBase->SelectionPredicate + i); 639 640 // lookup the number of selection 641 mColumnIDs = new int [mNumSelectionPredicates]; 642 for (i = 0; i < mNumSelectionPredicates; ++i) { 643 uint32 columnID; 644 645 switch (mSelectionPredicates[i].GetAttributeNameFormat ()) { 646 case CSSM_DB_ATTRIBUTE_NAME_AS_STRING: 647 // if we have an attribute name format of CSSM_ 648 columnID = relation->GetColumnNumber (mSelectionPredicates[i].GetAttributeName ()); 649 break; 650 case CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER: 651 columnID = mSelectionPredicates[i].GetAttributeID (); 652 break; 653 case CSSM_DB_ATTRIBUTE_NAME_AS_OID: 654 default: 655 CSSMError::ThrowCSSMError (CSSMERR_DL_UNSUPPORTED_QUERY); 656 break; 657 } 658 659 mColumnIDs[i] = columnID; 660 } 661 662 mValues = new Value*[mNumSelectionPredicates]; 663 for (i = 0; i < mNumSelectionPredicates; ++i) 664 mValues[i] = Value::MakeValueFromAttributeData (mSelectionPredicates[i].Attribute); 665 } else { 666 mSelectionPredicates = NULL; 667 } 668} 669 670 671 672Query::~Query () 673{ 674 if (mSelectionPredicates != NULL) { 675 delete [] mSelectionPredicates; 676 delete [] mColumnIDs; 677 678 unsigned i; 679 for (i = 0; i < mNumSelectionPredicates; ++i) 680 delete mValues[i]; 681 682 delete [] mValues; 683 } 684} 685 686 687 688bool Query::EvaluateTuple (Tuple *t) 689{ 690 // do the easy case first 691 if(!t) return false; 692 if (mNumSelectionPredicates <= 0) return true; 693 694 for(uint i=0; i < mNumSelectionPredicates; i++) { 695 Value* v = t->GetValue (mColumnIDs[i]); 696 if (v != NULL && v->Compare (mValues[i], mSelectionPredicates[i].DbOperator)){ 697 if(mConjunction != CSSM_DB_AND) return true; 698 } else if(mConjunction == CSSM_DB_AND) return false; 699 } 700 701 return true; 702} 703 704 705 706Relation::Relation (CSSM_DB_RECORDTYPE recordType) : mRecordType (recordType) {} 707Relation::~Relation () {} 708 709 710 711UniqueIdentifier::UniqueIdentifier (CSSM_DB_RECORDTYPE recordType) : mRecordType (recordType) {} 712UniqueIdentifier::~UniqueIdentifier () {} 713 714 715 716void CssmSelectionPredicate::CloneCssmSelectionPredicate (CssmSelectionPredicate &a, const CssmSelectionPredicate &b) 717{ 718 a.DbOperator = b.DbOperator; 719 a.Attribute.NumberOfValues = b.Attribute.NumberOfValues; 720 721 // clone the data 722 a.Attribute.Value = new CSSM_DATA; 723 a.Attribute.Value->Length = b.Attribute.Value->Length; 724 if (b.Attribute.Value->Data != NULL) { 725 a.Attribute.Value->Data = (uint8*) malloc (b.Attribute.Value->Length); 726 memcpy (a.Attribute.Value->Data, b.Attribute.Value->Data, b.Attribute.Value->Length); 727 } else { 728 b.Attribute.Value->Data = NULL; 729 } 730 731 // clone the attribute info 732 a.Attribute.Info.AttributeNameFormat = b.Attribute.Info.AttributeNameFormat; 733 a.Attribute.Info.AttributeFormat = b.Attribute.Info.AttributeFormat; 734 735 switch (b.Attribute.Info.AttributeNameFormat) { 736 case CSSM_DB_ATTRIBUTE_NAME_AS_STRING: 737 a.Attribute.Info.Label.AttributeName = strdup (b.Attribute.Info.Label.AttributeName); 738 break; 739 740 case CSSM_DB_ATTRIBUTE_NAME_AS_OID: 741 a.Attribute.Info.Label.AttributeOID.Length = b.Attribute.Info.Label.AttributeOID.Length; 742 a.Attribute.Info.Label.AttributeOID.Data = (uint8*) malloc (b.Attribute.Info.Label.AttributeOID.Length); 743 memcpy (a.Attribute.Info.Label.AttributeOID.Data, b.Attribute.Info.Label.AttributeOID.Data, b.Attribute.Info.Label.AttributeOID.Length); 744 break; 745 746 case CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER: 747 a.Attribute.Info.Label.AttributeID = b.Attribute.Info.Label.AttributeID; 748 break; 749 } 750} 751 752 753 754CssmSelectionPredicate::CssmSelectionPredicate (const CssmSelectionPredicate& pred) 755{ 756 CloneCssmSelectionPredicate (*this, pred); 757} 758 759 760 761CssmSelectionPredicate::~CssmSelectionPredicate () 762{ 763 if (Attribute.Value != NULL) { 764 free (Attribute.Value->Data); 765 delete Attribute.Value; 766 } 767 768 switch (Attribute.Info.AttributeNameFormat) { 769 case CSSM_DB_ATTRIBUTE_NAME_AS_STRING: 770 free (Attribute.Info.Label.AttributeName); 771 break; 772 case CSSM_DB_ATTRIBUTE_NAME_AS_OID: 773 free (Attribute.Info.Label.AttributeOID.Data); 774 break; 775 } 776} 777 778 779 780void CssmSelectionPredicate::operator= (const CssmSelectionPredicate& pred) 781{ 782 CloneCssmSelectionPredicate (*this, pred); 783} 784 785