void BELPICDataAttributeCoder::decode(TokenContext *tokenContext,
	const MetaAttribute &metaAttribute, Record &record)
{
	BELPICRecord &belpicRecord = dynamic_cast<BELPICRecord &>(record);
	record.attributeAtIndex(metaAttribute.attributeIndex(),
		belpicRecord.getDataAttribute(tokenContext));
}
void CertificateAttributeCoder::decode(TokenContext *tokenContext,
                                       const MetaAttribute &metaAttribute,
                                       Record &record)
{
	// Get the SecCertificateAdornment off record using a pointer to ourself as
	// the key
	SecCertificateAdornment &sca =
		record.adornment<SecCertificateAdornment>(this, tokenContext,
			metaAttribute, record);

	// Get the keychain item for the certificate from the record's adornment.
	SecKeychainItemRef certificate = sca.certificateItem();
	// Read the attribute with the requested attributeId from the item.
	SecKeychainAttribute ska = { metaAttribute.attributeId() };
	SecKeychainAttributeList skal = { 1, &ska };
	OSStatus status = SecKeychainItemCopyContent(certificate, NULL, &skal,
		NULL, NULL);
	if (status)
		MacOSError::throwMe(status);
	// Add the retrieved attribute as an attribute to the record.
	record.attributeAtIndex(metaAttribute.attributeIndex(),
		new Attribute(ska.data, ska.length));
	// Free the retrieved attribute.
	status = SecKeychainItemFreeContent(&skal, NULL);
	if (status)
		MacOSError::throwMe(status);

	// @@@ The code above only returns one email address.  Fix this.
}
void ConstAttributeCoder::decode(TokenContext *tokenContext,
	const MetaAttribute &metaAttribute, Record &record)
{
	record.attributeAtIndex(metaAttribute.attributeIndex(),
		new Attribute(mValue));
}
void DataAttributeCoder::decode(TokenContext *tokenContext,
	const MetaAttribute &metaAttribute, Record &record)
{
	record.attributeAtIndex(metaAttribute.attributeIndex(),
		record.getDataAttribute(tokenContext));
}
void DescriptionAttributeCoder::decode(TokenContext *tokenContext,
	const MetaAttribute &metaAttribute, Record &record)
{	
	record.attributeAtIndex(metaAttribute.attributeIndex(),
		new Attribute(record.description()));
}
void KeyDataAttributeCoder::decode(TokenContext *tokenContext,
	const MetaAttribute &metaAttribute, Record &record)
{
	const MetaRecord &mr = metaAttribute.metaRecord();
	CssmKey key;
	key.header().cspGuid(Guid::overlay(gGuidAppleSdCSPDL));
	key.blobType(CSSM_KEYBLOB_REFERENCE);
	key.blobFormat(CSSM_KEYBLOB_REF_FORMAT_INTEGER);
	key.algorithm(mr.metaAttribute(kSecKeyKeyType)
		.attribute(tokenContext, record).uint32Value());
	key.keyClass(mr.metaAttribute(kSecKeyKeyClass)
		.attribute(tokenContext, record).uint32Value());
	key.header().LogicalKeySizeInBits =
		mr.metaAttribute(kSecKeyKeySizeInBits).attribute(tokenContext, record)
			.uint32Value();

	key.header().KeyAttr =
		(mr.metaAttribute(kSecKeyPermanent).attribute(tokenContext, record)
			.boolValue() ? CSSM_KEYATTR_PERMANENT : 0)
		| (mr.metaAttribute(kSecKeyPrivate).attribute(tokenContext, record)
			.boolValue() ? CSSM_KEYATTR_PRIVATE : 0)
		| (mr.metaAttribute(kSecKeyModifiable).attribute(tokenContext, record)
			.boolValue() ? CSSM_KEYATTR_MODIFIABLE : 0)
		| (mr.metaAttribute(kSecKeySensitive).attribute(tokenContext, record)
			.boolValue() ? CSSM_KEYATTR_SENSITIVE : 0)
		| (mr.metaAttribute(kSecKeyAlwaysSensitive)
			.attribute(tokenContext, record)
				.boolValue() ? CSSM_KEYATTR_ALWAYS_SENSITIVE : 0)
		| (mr.metaAttribute(kSecKeyExtractable).attribute(tokenContext, record)
			.boolValue() ? CSSM_KEYATTR_EXTRACTABLE : 0)
		| (mr.metaAttribute(kSecKeyNeverExtractable)
			.attribute(tokenContext, record)
				.boolValue() ? CSSM_KEYATTR_NEVER_EXTRACTABLE : 0);

	CSSM_KEYUSE usage =
		(mr.metaAttribute(kSecKeyEncrypt).attribute(tokenContext, record)
			.boolValue() ? CSSM_KEYUSE_ENCRYPT : 0)
		| (mr.metaAttribute(kSecKeyDecrypt).attribute(tokenContext, record)
			.boolValue() ? CSSM_KEYUSE_DECRYPT : 0)
		| (mr.metaAttribute(kSecKeySign).attribute(tokenContext, record)
			.boolValue() ? CSSM_KEYUSE_SIGN : 0)
		| (mr.metaAttribute(kSecKeyVerify).attribute(tokenContext, record)
			.boolValue() ? CSSM_KEYUSE_VERIFY : 0)
		| (mr.metaAttribute(kSecKeySignRecover).attribute(tokenContext, record)
			.boolValue() ? CSSM_KEYUSE_SIGN_RECOVER : 0)
		| (mr.metaAttribute(kSecKeyVerifyRecover)
			.attribute(tokenContext, record)
				.boolValue() ? CSSM_KEYUSE_VERIFY_RECOVER : 0)
		| (mr.metaAttribute(kSecKeyWrap).attribute(tokenContext, record)
			.boolValue() ? CSSM_KEYUSE_WRAP : 0)
		| (mr.metaAttribute(kSecKeyUnwrap).attribute(tokenContext, record)
			.boolValue() ? CSSM_KEYUSE_UNWRAP : 0)
		| (mr.metaAttribute(kSecKeyDerive).attribute(tokenContext, record)
			.boolValue() ? CSSM_KEYUSE_DERIVE : 0);
	if (usage == (CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DECRYPT | CSSM_KEYUSE_SIGN
		| CSSM_KEYUSE_VERIFY | CSSM_KEYUSE_SIGN_RECOVER
		| CSSM_KEYUSE_VERIFY_RECOVER | CSSM_KEYUSE_WRAP | CSSM_KEYUSE_UNWRAP
		| CSSM_KEYUSE_DERIVE))
		usage = CSSM_KEYUSE_ANY;

	key.header().KeyUsage = usage;

	// Dates
	mr.metaAttribute(kSecKeyStartDate).attribute(tokenContext, record)
		.getDateValue(key.header().StartDate);
	mr.metaAttribute(kSecKeyEndDate).attribute(tokenContext, record)
		.getDateValue(key.header().EndDate);

	record.attributeAtIndex(metaAttribute.attributeIndex(),
		new Attribute(&key, sizeof(key)));
}
void ZeroAttributeCoder::decode(TokenContext *tokenContext,
	const MetaAttribute &metaAttribute, Record &record)
{
	record.attributeAtIndex(metaAttribute.attributeIndex(),
		new Attribute(reinterpret_cast<const void *>(NULL), 0));
}
void GuidAttributeCoder::decode(TokenContext *tokenContext,
	const MetaAttribute &metaAttribute, Record &record)
{
	record.attributeAtIndex(metaAttribute.attributeIndex(),
		new Attribute(&mGuid, sizeof(CSSM_GUID)));
}