#include "KCCursor.h"
#include "Item.h"
#include "Schema.h"
#include "cssmdatetime.h"
#include "Globals.h"
#include "StorageManager.h"
#include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h>
#include <Security/SecKeychainAPIPriv.h>
using namespace KeychainCore;
using namespace CssmClient;
using namespace CSSMDateTimeUtils;
KCCursorImpl::KCCursorImpl(const StorageManager::KeychainList &searchList, SecItemClass itemClass, const SecKeychainAttributeList *attrList) :
mSearchList(searchList),
mCurrent(mSearchList.begin())
{
recordType(Schema::recordTypeFor(itemClass));
if (!attrList) return;
conjunctive(CSSM_DB_AND);
const SecKeychainAttribute *end=&attrList->attr[attrList->count];
for (const SecKeychainAttribute *attr=attrList->attr; attr != end; ++attr)
{
const CssmDbAttributeInfo &info = Schema::attributeInfo(attr->tag);
void *buf = attr->data;
UInt32 length = attr->length;
uint8 timeString[16];
if (info.format() == CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE)
{
if (length == sizeof(UInt32))
{
MacSecondsToTimeString(*reinterpret_cast<const UInt32 *>(buf),
16, &timeString);
buf = &timeString;
length = 16;
}
else if (length == sizeof(SInt64))
{
MacLongDateTimeToTimeString(*reinterpret_cast<const SInt64 *>(buf),
16, &timeString);
buf = &timeString;
length = 16;
}
}
add(CSSM_DB_EQUAL,info, CssmData(buf,length));
}
}
KCCursorImpl::KCCursorImpl(const StorageManager::KeychainList &searchList, const SecKeychainAttributeList *attrList) :
mSearchList(searchList),
mCurrent(mSearchList.begin())
{
if (!attrList) return;
conjunctive(CSSM_DB_AND);
bool foundClassAttribute=false;
const SecKeychainAttribute *end=&attrList->attr[attrList->count];
for (const SecKeychainAttribute *attr=attrList->attr; attr != end; ++attr)
{
if (attr->tag!=kSecClassItemAttr) {
const CssmDbAttributeInfo &info = Schema::attributeInfo(attr->tag);
void *buf = attr->data;
UInt32 length = attr->length;
uint8 timeString[16];
if (info.format() == CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE)
{
if (length == sizeof(UInt32))
{
MacSecondsToTimeString(*reinterpret_cast<const UInt32 *>(buf),
16, &timeString);
buf = &timeString;
length = 16;
}
else if (length == sizeof(SInt64))
{
MacLongDateTimeToTimeString(*reinterpret_cast<const SInt64 *>(buf),
16, &timeString);
buf = &timeString;
length = 16;
}
}
add(CSSM_DB_EQUAL,info, CssmData(buf,length));
continue;
}
if (foundClassAttribute || attr->length != sizeof(SecItemClass))
MacOSError::throwMe(paramErr);
recordType(Schema::recordTypeFor(*reinterpret_cast<SecItemClass *>(attr->data)));
foundClassAttribute=true;
}
}
KCCursorImpl::~KCCursorImpl()
{
}
bool
KCCursorImpl::next(Item &item)
{
DbAttributes dbAttributes;
DbUniqueRecord uniqueId;
for (;;)
{
if (!mDbCursor)
{
if (mCurrent == mSearchList.end())
{
return false;
}
mDbCursor = DbCursor((*mCurrent)->database(), *this);
}
bool gotRecord;
try
{
gotRecord = mDbCursor->next(&dbAttributes, NULL, uniqueId);
}
catch(const CssmCommonError &err)
{
OSStatus status = err.osStatus();
if (status != CSSMERR_DL_DATASTORE_DOESNOT_EXIST
&& status != CSSMERR_DL_INVALID_RECORDTYPE)
throw;
gotRecord = false;
}
if (!gotRecord)
{
++mCurrent;
mDbCursor = DbCursor();
continue;
}
if (mDbCursor->recordType() == CSSM_DL_DB_RECORD_ANY &&
(dbAttributes.recordType() == 0x80008000
|| dbAttributes.recordType() == CSSM_DL_DB_RECORD_SYMMETRIC_KEY))
continue;
break;
}
item = (*mCurrent)->item(dbAttributes.recordType(), uniqueId);
return true;
}