#include <security_cdsa_utilities/cssmdb.h>
bool DLDbIdentifier::Impl::operator < (const DLDbIdentifier::Impl &other) const
{
if (mCssmSubserviceUid < other.mCssmSubserviceUid)
return true;
if (mCssmSubserviceUid != other.mCssmSubserviceUid) return false;
const char* a = mDbName.canonicalName();
const char* b = other.mDbName.canonicalName();
if (a == NULL && b != NULL)
{
return true; }
if (a != NULL && b == NULL)
{
return false; }
if (a == NULL && b == NULL)
{
return false; }
return strcmp(a, b) < 0;
}
bool DLDbIdentifier::Impl::operator == (const Impl &other) const
{
bool subserviceIdEqual = mCssmSubserviceUid == other.mCssmSubserviceUid;
if (!subserviceIdEqual)
{
return false;
}
const char* a = mDbName.canonicalName();
const char* b = other.mDbName.canonicalName();
if (a == NULL && b != NULL)
{
return false;
}
if (a != NULL && b == NULL)
{
return false;
}
if (a == NULL && b == NULL)
{
return true;
}
bool namesEqual = strcmp(a, b) == 0;
return namesEqual;
}
CssmDLPolyData::operator CSSM_DATE () const
{
assert(mFormat == CSSM_DB_ATTRIBUTE_FORMAT_BLOB);
if (mData.Length != 8)
CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT);
CSSM_DATE date;
memcpy(date.Year, mData.Data, 4);
memcpy(date.Month, mData.Data + 4, 2);
memcpy(date.Day, mData.Data + 6, 2);
return date;
}
CssmDLPolyData::operator Guid () const
{
assert(mFormat == CSSM_DB_ATTRIBUTE_FORMAT_BLOB);
if (mData.Length != Guid::stringRepLength + 1)
CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT);
return Guid(reinterpret_cast<const char *>(mData.Data));
}
CssmDbAttributeInfo::CssmDbAttributeInfo(const char *name, CSSM_DB_ATTRIBUTE_FORMAT vFormat)
{
clearPod();
AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING;
Label.AttributeName = const_cast<char *>(name); AttributeFormat = vFormat;
}
CssmDbAttributeInfo::CssmDbAttributeInfo(const CSSM_OID &oid, CSSM_DB_ATTRIBUTE_FORMAT vFormat)
{
clearPod();
AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_OID;
Label.AttributeOID = oid;
AttributeFormat = vFormat;
}
CssmDbAttributeInfo::CssmDbAttributeInfo(uint32 id, CSSM_DB_ATTRIBUTE_FORMAT vFormat)
{
clearPod();
AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER;
Label.AttributeID = id;
AttributeFormat = vFormat;
}
bool
CssmDbAttributeInfo::operator <(const CssmDbAttributeInfo& other) const
{
if (nameFormat() < other.nameFormat()) return true;
if (other.nameFormat() < nameFormat()) return false;
switch (nameFormat())
{
case CSSM_DB_ATTRIBUTE_NAME_AS_STRING:
{
int res = strcmp(static_cast<const char *>(*this), static_cast<const char *>(other));
if (res < 0) return true;
if (res > 0) return false;
break;
}
case CSSM_DB_ATTRIBUTE_NAME_AS_OID:
if (static_cast<const CssmOid &>(*this) < static_cast<const CssmOid &>(other)) return true;
if (static_cast<const CssmOid &>(other) < static_cast<const CssmOid &>(*this)) return false;
break;
case CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER:
if (static_cast<uint32>(*this) < static_cast<uint32>(other)) return true;
if (static_cast<uint32>(other) < static_cast<uint32>(*this)) return false;
break;
default:
CssmError::throwMe(CSSMERR_DL_INVALID_FIELD_NAME);
}
return format() < other.format();
}
bool
CssmDbAttributeInfo::operator ==(const CssmDbAttributeInfo& other) const
{
if (nameFormat() != other.nameFormat()) return false;
if (format() != other.format()) return false;
switch (nameFormat())
{
case CSSM_DB_ATTRIBUTE_NAME_AS_STRING:
return !strcmp(static_cast<const char *>(*this), static_cast<const char *>(other));
case CSSM_DB_ATTRIBUTE_NAME_AS_OID:
return static_cast<const CssmOid &>(*this) == static_cast<const CssmOid &>(other);
case CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER:
return static_cast<uint32>(*this) == static_cast<uint32>(other);
default:
CssmError::throwMe(CSSMERR_DL_INVALID_FIELD_NAME);
}
}
CssmDbAttributeData::operator string() const
{
switch (format()) {
case CSSM_DB_ATTRIBUTE_FORMAT_STRING:
case CSSM_DB_ATTRIBUTE_FORMAT_BLOB:
return at(0).toString();
default:
CssmError::throwMe(CSSMERR_DL_INCOMPATIBLE_FIELD_FORMAT);
}
}
CssmDbAttributeData::operator const Guid &() const
{
if (format() == CSSM_DB_ATTRIBUTE_FORMAT_BLOB)
return *at(0).interpretedAs<Guid>();
else
CssmError::throwMe(CSSMERR_DL_INCOMPATIBLE_FIELD_FORMAT);
}
CssmDbAttributeData::operator bool() const
{
switch (format()) {
case CSSM_DB_ATTRIBUTE_FORMAT_UINT32:
case CSSM_DB_ATTRIBUTE_FORMAT_SINT32:
return *at(0).interpretedAs<uint32>();
default:
CssmError::throwMe(CSSMERR_DL_INCOMPATIBLE_FIELD_FORMAT);
}
}
CssmDbAttributeData::operator uint32() const
{
if (format() == CSSM_DB_ATTRIBUTE_FORMAT_UINT32)
return *at(0).interpretedAs<uint32>();
else
CssmError::throwMe(CSSMERR_DL_INCOMPATIBLE_FIELD_FORMAT);
}
CssmDbAttributeData::operator const uint32 *() const
{
if (format() == CSSM_DB_ATTRIBUTE_FORMAT_MULTI_UINT32)
return reinterpret_cast<const uint32 *>(Value[0].Data);
else
CssmError::throwMe(CSSMERR_DL_INCOMPATIBLE_FIELD_FORMAT);
}
CssmDbAttributeData::operator sint32() const
{
if (format() == CSSM_DB_ATTRIBUTE_FORMAT_SINT32)
return *at(0).interpretedAs<sint32>();
else
CssmError::throwMe(CSSMERR_DL_INCOMPATIBLE_FIELD_FORMAT);
}
CssmDbAttributeData::operator double() const
{
if (format() == CSSM_DB_ATTRIBUTE_FORMAT_REAL)
return *at(0).interpretedAs<double>();
else
CssmError::throwMe(CSSMERR_DL_INCOMPATIBLE_FIELD_FORMAT);
}
CssmDbAttributeData::operator const CssmData &() const
{
switch (format()) {
case CSSM_DB_ATTRIBUTE_FORMAT_STRING:
case CSSM_DB_ATTRIBUTE_FORMAT_BIG_NUM:
case CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE:
case CSSM_DB_ATTRIBUTE_FORMAT_BLOB:
case CSSM_DB_ATTRIBUTE_FORMAT_MULTI_UINT32:
return at(0);
default:
CssmError::throwMe(CSSMERR_DL_INCOMPATIBLE_FIELD_FORMAT);
}
}
void CssmDbAttributeData::set(const CSSM_DB_ATTRIBUTE_INFO &inInfo, const CssmPolyData &inValue,
Allocator &inAllocator)
{
info(inInfo);
NumberOfValues = 0;
Value = inAllocator.alloc<CSSM_DATA>();
Value[0].Length = 0;
Value[0].Data = inAllocator.alloc<uint8>((UInt32)inValue.Length);
Value[0].Length = inValue.Length;
memcpy(Value[0].Data, inValue.Data, inValue.Length);
NumberOfValues = 1;
}
void CssmDbAttributeData::add(const CssmPolyData &inValue, Allocator &inAllocator)
{
Value = reinterpret_cast<CSSM_DATA *>(inAllocator.realloc(Value, sizeof(*Value) * (NumberOfValues + 1)));
CssmAutoData valueCopy(inAllocator, inValue);
Value[NumberOfValues++] = valueCopy.release();
}
void CssmDbAttributeData::copyValues(const CssmDbAttributeData &source, Allocator &alloc)
{
assert(size() == 0);
CssmData *vector = alloc.alloc<CssmData>(source.size());
for (uint32 n = 0; n < source.size(); n++)
vector[n] = CssmAutoData(alloc, source[n]).release();
info().format(source.info().format());
NumberOfValues = source.size();
values() = vector;
}
void CssmDbAttributeData::deleteValues(Allocator &alloc)
{
if (values())
{
for (uint32 n = 0; n < size(); n++)
{
alloc.free(at(n).data());
}
alloc.free(values());
}
NumberOfValues = 0;
values() = NULL;
}
bool CssmDbAttributeData::operator <(const CssmDbAttributeData &other) const
{
if (info() < other.info()) return true;
if (other.info() < info()) return false;
uint32 minSize = min(size(), other.size());
for (uint32 ix = 0; ix < minSize; ++ix)
{
if (at<const CssmData &>(ix) < other.at<const CssmData &>(ix))
return true;
if (other.at<const CssmData &>(ix) < at<const CssmData &>(ix))
return false;
}
return size() < other.size();
}
void
CssmDbAttributeData::add(const CssmDbAttributeData &src, Allocator &inAllocator)
{
Value = reinterpret_cast<CSSM_DATA *>(inAllocator.realloc(Value,
sizeof(*Value) * (NumberOfValues + src.NumberOfValues)));
for (uint32 srcIndex = 0; srcIndex < src.NumberOfValues; srcIndex++) {
uint32 destIndex = NumberOfValues + srcIndex;
Value[destIndex].Length = 0;
Value[destIndex].Data = inAllocator.alloc<uint8>((UInt32)src.Value[srcIndex].Length);
Value[destIndex].Length = src.Value[srcIndex].Length;
memcpy(Value[destIndex].Data, src.Value[srcIndex].Data, src.Value[srcIndex].Length);
}
NumberOfValues += src.NumberOfValues;
}
bool
CssmDbAttributeData::deleteValue(const CssmData &src, Allocator &inAllocator)
{
for (uint32 i = 0; i < NumberOfValues; i++)
if (CssmData::overlay(Value[i]) == src)
{
inAllocator.free(Value[i].Data);
Value[i].Length = 0;
NumberOfValues--;
Value[i].Data = Value[NumberOfValues].Data;
Value[i].Length = Value[NumberOfValues].Length;
return true;
}
return false;
}
void
CssmDbAttributeData::deleteValues(const CssmDbAttributeData &src, Allocator &inAllocator)
{
for (uint32 i = 0; i < src.NumberOfValues; i++)
deleteValue(CssmData::overlay(src.Value[i]), inAllocator);
}
CssmDbAttributeData *
CssmDbRecordAttributeData::find(const CSSM_DB_ATTRIBUTE_INFO &inInfo)
{
const CssmDbAttributeInfo &anInfo = CssmDbAttributeInfo::overlay(inInfo);
for (uint32 ix = 0; ix < size(); ++ix)
{
if (at(ix).info() == anInfo)
return &at(ix);
}
return NULL;
}
bool
CssmDbRecordAttributeData::operator <(const CssmDbRecordAttributeData &other) const
{
if (recordType() < other.recordType()) return true;
if (other.recordType() < recordType()) return false;
if (semanticInformation() < other.semanticInformation()) return true;
if (other.semanticInformation() < semanticInformation()) return false;
uint32 minSize = min(size(), other.size());
for (uint32 ix = 0; ix < minSize; ++ix)
{
if (at(ix) < other.at(ix))
return true;
if (other.at(ix) < at(ix))
return false;
}
return size() < other.size();
}
CssmAutoDbRecordAttributeData::~CssmAutoDbRecordAttributeData()
{
clear();
}
void
CssmAutoDbRecordAttributeData::invalidate()
{
NumberOfAttributes = 0;
}
void
CssmAutoDbRecordAttributeData::clear()
{
deleteValues();
ArrayBuilder<CssmDbAttributeData>::clear();
}
static bool CompareAttributeInfos (const CSSM_DB_ATTRIBUTE_INFO &a, const CSSM_DB_ATTRIBUTE_INFO &b)
{
if (a.AttributeNameFormat != b.AttributeNameFormat)
{
return false;
}
switch (a.AttributeNameFormat)
{
case CSSM_DB_ATTRIBUTE_NAME_AS_STRING:
{
return strcmp (a.Label.AttributeName, b.Label.AttributeName) == 0;
}
case CSSM_DB_ATTRIBUTE_NAME_AS_OID:
{
if (a.Label.AttributeOID.Length != b.Label.AttributeOID.Length)
{
return false;
}
return memcmp (a.Label.AttributeOID.Data, b.Label.AttributeOID.Data, a.Label.AttributeOID.Length) == 0;
}
case CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER:
{
return a.Label.AttributeID == b.Label.AttributeID;
}
}
return true; }
CssmDbAttributeData* CssmAutoDbRecordAttributeData::findAttribute (const CSSM_DB_ATTRIBUTE_INFO &info)
{
unsigned i;
for (i = 0; i < size (); ++i)
{
CssmDbAttributeData& d = at (i);
CSSM_DB_ATTRIBUTE_INFO &inInfo = d.info ();
if (CompareAttributeInfos (info, inInfo))
{
return &d;
}
}
return NULL;
}
CssmDbAttributeData& CssmAutoDbRecordAttributeData::getAttributeReference (const CSSM_DB_ATTRIBUTE_INFO &info)
{
CssmDbAttributeData *anAttr = findAttribute (info);
if (anAttr) {
anAttr->deleteValues (mValueAllocator);
}
else
{
anAttr = &add();
}
return *anAttr;
}
CssmDbAttributeData &
CssmAutoDbRecordAttributeData::add(const CSSM_DB_ATTRIBUTE_INFO &info)
{
CssmDbAttributeData& anAttr = getAttributeReference (info);
anAttr.info(info);
return anAttr;
}
CssmDbAttributeData &
CssmAutoDbRecordAttributeData::add(const CSSM_DB_ATTRIBUTE_INFO &info, const CssmPolyData &value)
{
CssmDbAttributeData &anAttr = getAttributeReference (info);
anAttr.set(info, value, mValueAllocator);
return anAttr;
}
CssmAutoQuery::CssmAutoQuery(const CSSM_QUERY &query, Allocator &allocator)
: ArrayBuilder<CssmSelectionPredicate>(CssmSelectionPredicate::overlayVar(SelectionPredicate),
NumSelectionPredicates,
query.NumSelectionPredicates, allocator)
{
RecordType = query.RecordType;
Conjunctive = query.Conjunctive;
QueryLimits = query.QueryLimits;
QueryFlags = query.QueryFlags;
for (uint32 ix = 0; ix < query.NumSelectionPredicates; ++ix)
add().set(query.SelectionPredicate[ix], allocator);
}
CssmAutoQuery::~CssmAutoQuery()
{
clear();
}
void
CssmAutoQuery::clear()
{
deleteValues();
ArrayBuilder<CssmSelectionPredicate>::clear();
}
CssmSelectionPredicate &
CssmAutoQuery::add(CSSM_DB_OPERATOR dbOperator, const CSSM_DB_ATTRIBUTE_INFO &info, const CssmPolyData &value)
{
CssmSelectionPredicate &predicate = add();
predicate.dbOperator(dbOperator);
predicate.set(info, value, allocator());
return predicate;
}