SecCustomTransform.cpp [plain text]
#include "SecCustomTransform.h"
#include "SecTransformValidator.h"
#include "TransformFactory.h"
#include <CoreFoundation/CoreFoundation.h>
#include <Block.h>
#include <syslog.h>
#include "Utilities.h"
#include "misc.h"
static const CFStringRef kSecCustom = CFSTR("CustomTransform");
const CFStringRef kSecTransformPreviousErrorKey = CFSTR("PreviousError");
const CFStringRef kSecTransformAbortOriginatorKey = CFSTR("Originating Transform");
const CFStringRef kSecTransformActionCanExecute = CFSTR("CanExecute");
const CFStringRef kSecCustomTransformWhatIsRequired = CFSTR("WhatIsRequired");
const CFStringRef kSecCustomTransformAttributesToExternalize = CFSTR("AttributesToExternalize");
const CFStringRef kSecTransformActionStartingExecution = CFSTR("ExecuteStarting");
const CFStringRef kSecTransformActionProcessData = CFSTR("TransformProcessData");
const CFStringRef kSecTransformActionAttributeNotification = CFSTR("GenericAttributeSetNotification");
const CFStringRef kSecTransformActionFinalize = CFSTR("Finalize");
const CFStringRef kSecTransformActionExternalizeExtraData = CFSTR("ExternalizeExtraData");
const CFStringRef kSecTransformActionInternalizeExtraData = CFSTR("InternalizeExtraData");
const CFStringRef kSecTransformActionAttributeValidation = CFSTR("AttributeValidation");
typedef CFTypeRef (^SecTransformOverrideTransformAction)(CFStringRef action,
SecTransformActionBlock newAction);
typedef CFTypeRef (^SecTransformOverrideDataAction)(CFStringRef action,
SecTransformDataBlock newAction);
typedef CFTypeRef (^SecTransformOverrideAttributeAction)(
CFStringRef action,
SecTransformStringOrAttributeRef attribute,
SecTransformAttributeActionBlock newAction);
typedef CFTypeRef (^SecTransformGetAttributeBlock)(
SecTransformStringOrAttributeRef attribute,
SecTransformMetaAttributeType type);
typedef CFErrorRef (^SecTransformSetAttributeBlock)(
SecTransformStringOrAttributeRef attribute,
SecTransformMetaAttributeType type,
CFTypeRef value);
typedef CFErrorRef (^SecTransformPushBackAttributeBlock)(
SecTransformStringOrAttributeRef attribute,
CFTypeRef value);
enum
{
kSecTransformCreateBlockParametersVersion = 1
};
extern "C" {
Boolean SecExternalSourceSetValue(SecTransformRef xst, CFTypeRef value, CFErrorRef *error);
}
struct OpaqueSecTransformImplementation
{
CFIndex version;
SecTransformOverrideTransformAction overrideTransform;
SecTransformOverrideDataAction overrideData;
SecTransformOverrideAttributeAction overrideAttribute;
SecTransformGetAttributeBlock get;
SecTransformSetAttributeBlock send;
SecTransformPushBackAttributeBlock pushback;
};
class CustomTransformFactory : public TransformFactory
{
protected:
SecTransformCreateFP createFuncPtr;
public:
CustomTransformFactory(CFStringRef name, SecTransformCreateFP createFP, CFErrorRef *error);
virtual ~CustomTransformFactory() {};
virtual CFTypeRef Make();
};
static SecTransformActionBlock default_can_run = ^{ return (CFTypeRef)NULL; };
static SecTransformActionBlock default_execute_starting = default_can_run;
static SecTransformActionBlock default_finalize = default_execute_starting;
static SecTransformActionBlock default_externalize_data = default_finalize;
static SecTransformDataBlock default_process_data = ^(CFTypeRef value) { return value; };
static SecTransformAttributeActionBlock default_generic_attribute_set_notification =
^(SecTransformAttributeRef ah, CFTypeRef value) { return value; };
static SecTransformAttributeActionBlock default_generic_attribute_validation =
^(SecTransformAttributeRef ah, CFTypeRef value)
{
return (CFTypeRef)NULL;
};
static SecTransformDataBlock default_internalize_data =
^(CFTypeRef value)
{
return (CFTypeRef)NULL;
};
class CustomTransform : public Transform
{
protected:
SecTransformCreateFP createFuncPtr;
SecTransformInstanceBlock instanceBlock;
SecTransformActionBlock can_run;
SecTransformActionBlock execute_starting;
SecTransformActionBlock finalize;
SecTransformAttributeActionBlock generic_attribute_set_notification;
SecTransformAttributeActionBlock generic_attribute_validation;
SecTransformDataBlock process_data;
SecTransformActionBlock externalize_data;
SecTransformDataBlock internalize_data;
SecTransformRef tr;
SecTransformAttributeRef input_ah;
SecTransformAttributeRef output_ah;
OpaqueSecTransformImplementation parameters;
void SetCanExecute(SecTransformActionBlock CanExecuteBlock)
{
Block_release(can_run);
if (CanExecuteBlock)
{
can_run = Block_copy(CanExecuteBlock);
}
else
{
can_run = Block_copy(default_can_run);
}
}
void SetExecuteStarting(SecTransformActionBlock executeStartingBlock)
{
Block_release(execute_starting);
if (executeStartingBlock)
{
execute_starting = Block_copy(executeStartingBlock);
}
else
{
execute_starting = Block_copy(default_execute_starting);
}
}
void SetFinalize(SecTransformActionBlock finalizeBlock)
{
Block_release(finalize);
if (finalizeBlock)
{
finalize = Block_copy(finalizeBlock);
}
else
{
finalize = Block_copy(default_finalize);
}
}
void SetExternalizeExtraData(SecTransformActionBlock externalizeBlock)
{
Block_release(externalizeBlock);
if (externalizeBlock)
{
externalize_data = Block_copy(externalizeBlock);
}
else
{
externalize_data = Block_copy(default_externalize_data);
}
}
void SetProcessData(SecTransformDataBlock processDataBlock)
{
Block_release(process_data);
if (processDataBlock)
{
process_data = Block_copy(processDataBlock);
}
else
{
process_data = Block_copy(default_process_data);
}
}
void SetInternalizeExtraData(SecTransformDataBlock InternalizeExtraDataBlock)
{
Block_release(internalize_data);
if (InternalizeExtraDataBlock)
{
internalize_data = Block_copy(InternalizeExtraDataBlock);
}
else
{
internalize_data = Block_copy(default_internalize_data);
}
}
void SetNotficationBlock(SecTransformStringOrAttributeRef attribute,
SecTransformAttributeActionBlock notificationBlock)
{
SecTransformAttributeActionBlock blockToSet =
Block_copy((notificationBlock) ? notificationBlock :
default_generic_attribute_set_notification);
if (attribute)
{
transform_attribute *ta = getTA(attribute, true);
if (ta->attribute_changed_block)
{
Block_release(ta->attribute_changed_block);
}
ta->attribute_changed_block = blockToSet;
}
else
{
if (generic_attribute_set_notification)
{
Block_release(generic_attribute_set_notification);
}
generic_attribute_set_notification = blockToSet;
}
}
void SetVerifyBlock(SecTransformStringOrAttributeRef attribute,
SecTransformAttributeActionBlock verifyBlock)
{
SecTransformAttributeActionBlock blockToSet =
Block_copy((verifyBlock) ? verifyBlock :
generic_attribute_validation);
if (attribute)
{
transform_attribute *ta = getTA(attribute, true);
if (ta->attribute_validate_block)
{
Block_release(ta->attribute_validate_block);
}
ta->attribute_validate_block = blockToSet;
}
else
{
if (generic_attribute_validation)
{
Block_release(generic_attribute_validation);
}
generic_attribute_validation = blockToSet;
}
}
public:
CustomTransform(CFStringRef name, SecTransformCreateFP createFP);
virtual ~CustomTransform();
void Create();
CFTypeRef rebind_data_action(CFStringRef action,
SecTransformDataBlock new_action);
CFTypeRef rebind_transform_action(CFStringRef action, SecTransformActionBlock new_action);
CFTypeRef rebind_attribute_action(CFStringRef action,
SecTransformStringOrAttributeRef attribute,
SecTransformAttributeActionBlock new_action);
SecTransformRef get_ref() { return tr; }
virtual void AttributeChanged(CFStringRef name, CFTypeRef value);
virtual void AttributeChanged(SecTransformAttributeRef ah, CFTypeRef value);
virtual CFErrorRef TransformStartingExecution();
virtual CFDictionaryRef GetCustomExternalData();
virtual void SetCustomExternalData(CFDictionaryRef customData);
friend Boolean SecExternalSourceSetValue(SecTransformRef xst, CFTypeRef value, CFErrorRef *error);
};
#pragma mark CustomTransformFactory
CustomTransformFactory::CustomTransformFactory(CFStringRef uniqueName, SecTransformCreateFP createFP, CFErrorRef* error) :
TransformFactory(uniqueName, false, kSecCustom),
createFuncPtr(createFP)
{
TransformFactory *existing = FindTransformFactoryByType(uniqueName);
if (existing)
{
if (error)
{
*error = CreateSecTransformErrorRef(kSecTransformErrorNameAlreadyRegistered,
"Custom transform type %s already exists.", uniqueName);
}
return;
}
if (CFStringGetCharacterAtIndex(uniqueName, 0) == '_')
{
if (error)
{
*error = CreateSecTransformErrorRef(kSecTransformInvalidArgument,
"Invalid transform type name %s -- type names must not start with an _", uniqueName);
}
return;
}
static CFCharacterSetRef invalidTypeCharactors = NULL;
static dispatch_once_t setupInvalidTypeCharactors;
dispatch_once(&setupInvalidTypeCharactors, ^{
invalidTypeCharactors = CFCharacterSetCreateWithCharactersInString(NULL, CFSTR("/:"));
});
CFRange has_bad;
if (CFStringFindCharacterFromSet(uniqueName, invalidTypeCharactors, CFRangeMake(0, CFStringGetLength(uniqueName)), 0, &has_bad)) {
if (error)
{
*error = CreateSecTransformErrorRef(kSecTransformInvalidArgument,
"Invalid character '%c' in transform type name %s", CFStringGetCharacterAtIndex(uniqueName, has_bad.location), uniqueName);
}
return;
}
RegisterTransform(this, kSecCustom);
}
CFTypeRef CustomTransformFactory::Make()
{
CustomTransform *ct = new CustomTransform(this->GetTypename(), createFuncPtr);
ct->Create();
return ct->get_ref();
}
#pragma mark MISC
extern "C" {
SecTransformAttributeActionBlock SecTransformCreateValidatorForCFtype(CFTypeID expected_type, Boolean null_allowed) {
SecTransformAttributeActionBlock validate = NULL;
CFErrorRef (^make_error_message)(SecTransformAttributeRef attr, CFTypeRef value, CFTypeID expected_type, Boolean null_allowed) =
^(SecTransformAttributeRef attr, CFTypeRef value, CFTypeID expected_type, Boolean null_allowed) {
CFStringRef expected_type_name = CFCopyTypeIDDescription(expected_type);
CFErrorRef error = NULL;
if (value) {
CFStringRef value_type_name = CFCopyTypeIDDescription(CFGetTypeID(value));
error = CreateSecTransformErrorRef(kSecTransformErrorInvalidType, "%@ received value of type %@ (%@), expected%@ a %@%@",
attr, value_type_name, value,
null_allowed ? CFSTR(" either") : CFSTR(""),
expected_type_name,
null_allowed ? CFSTR(" or a NULL") : CFSTR(""));
CFRelease(value_type_name);
} else {
error = CreateSecTransformErrorRef(kSecTransformErrorInvalidType, "%@ received NULL value, expected a %@",
attr, expected_type_name);
}
CFRelease(expected_type_name);
return error;
};
if (null_allowed) {
validate = ^(SecTransformAttributeRef attr, CFTypeRef value) {
if (value == NULL || CFGetTypeID(value) == expected_type) {
return (CFTypeRef)NULL;
}
return (CFTypeRef)make_error_message(attr, value, expected_type, null_allowed);
};
} else {
validate = ^(SecTransformAttributeRef attr, CFTypeRef value) {
if (value != NULL && CFGetTypeID(value) == expected_type) {
return (CFTypeRef)NULL;
}
return (CFTypeRef)make_error_message(attr, value, expected_type, null_allowed);
};
}
return Block_copy(validate);
}
}
Boolean SecTransformRegister(CFStringRef uniqueName, SecTransformCreateFP createFP, CFErrorRef *caller_error)
{
CFErrorRef error = NULL;
CustomTransformFactory *tf = new CustomTransformFactory(uniqueName, createFP, &error);
if (error)
{
delete tf;
if (caller_error)
{
*caller_error = error;
}
return FALSE;
}
else
{
return TRUE;
}
}
SecTransformRef SecTransformCreate(CFStringRef name, CFErrorRef *error)
{
SecTransformRef tr = TransformFactory::MakeTransformWithType(name, error);
return tr;
}
extern "C" {
Boolean SecExternalSourceSetValue(SecTransformRef xst, CFTypeRef value, CFErrorRef *error)
{
CustomTransform *ct = (CustomTransform *)CoreFoundationHolder::ObjectFromCFType(xst);
extern CFStringRef external_source_name;
if (CFEqual(ct->mTypeName, external_source_name)) {
ct->SetAttribute(ct->input_ah, value);
return true;
} else {
if (error) {
*error = CreateSecTransformErrorRef(kSecTransformErrorInvalidType, "SecExternalSourceSetValue called for %@, you need to pass in an ExternalSource transform not a %@", ct->GetName(), ct->mTypeName);
}
return false;
}
}
}
#pragma mark NoDataClass
class NoDataClass : public CoreFoundationObject
{
protected:
NoDataClass();
public:
virtual ~NoDataClass();
std::string FormattingDescription(CFDictionaryRef options);
std::string DebugDescription();
static CFTypeRef Make();
};
CFTypeRef NoDataClass::Make() {
NoDataClass* obj = new NoDataClass();
return CoreFoundationHolder::MakeHolder(gInternalProtectedCFObjectName, obj);
}
NoDataClass::NoDataClass() : CoreFoundationObject(gInternalProtectedCFObjectName) {
}
NoDataClass::~NoDataClass()
{
}
std::string NoDataClass::DebugDescription()
{
return CoreFoundationObject::DebugDescription() + " | SecTransformNoData";
}
std::string NoDataClass::FormattingDescription(CFDictionaryRef options)
{
return CoreFoundationObject::FormattingDescription(options) + " | SecTransformNoData";
}
CFTypeRef SecTransformNoData()
{
static dispatch_once_t inited;
static CFTypeRef no_data;
dispatch_once(&inited,
^{
no_data = NoDataClass::Make();
});
return no_data;
}
#pragma mark CustomTransform
void CustomTransform::AttributeChanged(CFStringRef name, CFTypeRef value) {
#ifndef NDEBUG
abort();
#else
AttributeChanged(getAH(name, false), value);
#endif
}
void CustomTransform::AttributeChanged(SecTransformAttributeRef ah, CFTypeRef value)
{
transform_attribute *ta = ah2ta(ah);
SecTransformAttributeActionBlock attribute_set_notification = NULL;
SecTransformAttributeActionBlock attribute_validate = NULL;
attribute_validate = (SecTransformAttributeActionBlock)ta->attribute_validate_block;
if (!attribute_validate) {
attribute_validate = generic_attribute_validation;
}
CFTypeRef vr = attribute_validate(ah, value);
if (vr) {
if (CFGetTypeID(vr) == CFErrorGetTypeID()) {
SendAttribute(AbortAH, vr);
CFRelease(vr);
} else {
CFErrorRef e = CreateSecTransformErrorRef(kSecTransformErrorInvalidType, "Invalid return type from a validate action, expected a CFErrorRef got a %@ (%@)", CFCopyTypeIDDescription(CFGetTypeID(vr)), vr);
SendAttribute(AbortAH, e);
CFRelease(vr);
}
return;
}
attribute_set_notification = (SecTransformAttributeActionBlock)ta->attribute_changed_block;
if ((!attribute_set_notification) && ah == input_ah)
{
CFTypeID vtype = value ? CFGetTypeID(value) : CFDataGetTypeID();
if (vtype == CFDataGetTypeID())
{
CFTypeRef output = process_data(value);
if (output == NULL || output != SecTransformNoData())
{
SendAttribute(output_ah, output);
if (output != value && output != NULL)
{
CFRelease(output);
}
}
}
else if (vtype == CFErrorGetTypeID() && !ah2ta(ah)->direct_error_handling)
{
SendAttribute(output_ah, value);
} else
{
attribute_set_notification = attribute_set_notification ? attribute_set_notification : generic_attribute_set_notification;
CFTypeRef new_value = attribute_set_notification(ah, value);
if (new_value != value)
{
SendAttribute(ah, new_value);
}
}
}
else
{
CFTypeID vtype = value ? CFGetTypeID(value) : CFDataGetTypeID();
if (vtype != CFErrorGetTypeID() || ah2ta(ah)->direct_error_handling)
{
attribute_set_notification = attribute_set_notification ? attribute_set_notification : generic_attribute_set_notification;
CFTypeRef new_value = attribute_set_notification(ah, value);
if (new_value != value)
{
SendAttribute(ah, new_value);
}
}
else
{
SendAttribute(output_ah, value);
}
}
}
CFTypeRef CustomTransform::rebind_data_action(CFStringRef action,
SecTransformDataBlock new_action)
{
CFTypeRef result = NULL;
if (kCFCompareEqualTo == CFStringCompare(kSecTransformActionProcessData, action, 0))
{
SetProcessData(new_action);
}
else if (kCFCompareEqualTo == CFStringCompare(kSecTransformActionInternalizeExtraData, action, 0))
{
SetInternalizeExtraData(new_action);
}
else
{
result = (CFTypeRef)CreateSecTransformErrorRef(kSecTransformInvalidOverride, "Unkown override type");
CFStringRef msg = CFStringCreateWithFormat(NULL, NULL,
CFSTR("rebind_data_action (action %@, new_action %p, transform %s)"),
action, (void*)new_action, DebugDescription().c_str());
char *utf8_message = utf8(msg);
syslog(LOG_ERR, "%s", utf8_message);
free(utf8_message);
CFRelease(msg);
}
return result;
}
CFTypeRef CustomTransform::rebind_transform_action(CFStringRef action, SecTransformActionBlock new_action)
{
CFErrorRef result = NULL;
if (kCFCompareEqualTo == CFStringCompare(action, kSecTransformActionCanExecute, 0))
{
SetCanExecute(new_action);
}
else if (kCFCompareEqualTo == CFStringCompare(action, kSecTransformActionStartingExecution, 0))
{
SetExecuteStarting(new_action);
}
else if (kCFCompareEqualTo == CFStringCompare(action, kSecTransformActionFinalize, 0))
{
SetFinalize(new_action);
}
else if (kCFCompareEqualTo == CFStringCompare(action, kSecTransformActionExternalizeExtraData, 0))
{
SetExternalizeExtraData(new_action);
}
else
{
result = CreateSecTransformErrorRef(kSecTransformInvalidOverride, "Unkown override type");
char *action_utf8 = utf8(action);
syslog(LOG_ERR, "rebind_transform_action (action %s, all-attributes, block %p, transform %s)\n", action_utf8, (void*)new_action, DebugDescription().c_str());
free(action_utf8);
}
return result;
}
CFTypeRef CustomTransform::rebind_attribute_action(
CFStringRef action,
SecTransformStringOrAttributeRef attribute,
SecTransformAttributeActionBlock new_action)
{
CFErrorRef result = NULL;
if (kCFCompareEqualTo == CFStringCompare(action, kSecTransformActionAttributeNotification, 0))
{
SetNotficationBlock(attribute, new_action);
}
else if (kCFCompareEqualTo == CFStringCompare(action, kSecTransformActionAttributeValidation, 0))
{
SetVerifyBlock(attribute, new_action);
}
else
{
result = CreateSecTransformErrorRef(kSecTransformInvalidOverride, "Unkown override type");
char *action_utf8 = utf8(action);
syslog(LOG_ERR, "rebind_attribute_action (action %s, all-attributes, block %p, transform %s)\n", action_utf8, (void*)new_action, DebugDescription().c_str());
free(action_utf8);
}
return result;
}
CustomTransform::CustomTransform(CFStringRef cfname, SecTransformCreateFP createFP) :
Transform(cfname),
createFuncPtr(createFP),
instanceBlock(NULL),
can_run(Block_copy(default_can_run)),
execute_starting(Block_copy(default_execute_starting)),
finalize(Block_copy(default_finalize)),
generic_attribute_set_notification(Block_copy(default_generic_attribute_set_notification)),
generic_attribute_validation(Block_copy(default_generic_attribute_validation)),
process_data(Block_copy(default_process_data)),
externalize_data(Block_copy(default_externalize_data)),
internalize_data(Block_copy(default_internalize_data))
{
mAlwaysSelfNotify = true;
input_ah = getAH(kSecTransformInputAttributeName, true);
output_ah = getAH(kSecTransformOutputAttributeName, true);
parameters.version = kSecTransformCreateBlockParametersVersion;
parameters.send = Block_copy(^(SecTransformStringOrAttributeRef attribute, SecTransformMetaAttributeType type, CFTypeRef value)
{
return SendMetaAttribute(attribute, type, value);
});
parameters.pushback = Block_copy(^(SecTransformStringOrAttributeRef attribute, CFTypeRef value)
{
return Pushback(getAH(attribute), value);
});
parameters.get = Block_copy(^(SecTransformStringOrAttributeRef attribute, SecTransformMetaAttributeType type)
{
return GetMetaAttribute(attribute, type);
});
parameters.overrideTransform = Block_copy(^(CFStringRef action, SecTransformActionBlock new_action)
{
return rebind_transform_action(action, new_action);
});
parameters.overrideData = Block_copy(^(CFStringRef action,
SecTransformDataBlock new_action)
{
return rebind_data_action(action, new_action);
});
parameters.overrideAttribute =
Block_copy(^(CFStringRef action, SecTransformStringOrAttributeRef attribute, SecTransformAttributeActionBlock new_action)
{
return rebind_attribute_action(action, attribute, new_action);
});
char *tname = const_cast<char*>(CFStringGetCStringPtr(cfname, kCFStringEncodingUTF8));
if (!tname) {
CFIndex sz = CFStringGetMaximumSizeForEncoding(CFStringGetLength(cfname), kCFStringEncodingUTF8);
tname = static_cast<typeof(tname)>(alloca(sz));
CFStringGetCString(cfname, tname, sz, kCFStringEncodingUTF8);
}
tr = CoreFoundationHolder::MakeHolder(kSecCustom, (CoreFoundationObject*)this);
instanceBlock = (*createFuncPtr)(cfname, tr, ¶meters);
}
void CustomTransform::Create()
{
(void)instanceBlock();
}
CustomTransform::~CustomTransform() {
finalize();
if (instanceBlock)
{
Block_release(instanceBlock);
}
Block_release(can_run);
Block_release(execute_starting);
Block_release(finalize);
Block_release(generic_attribute_set_notification);
Block_release(process_data);
Block_release(externalize_data);
Block_release(internalize_data);
Block_release(parameters.send);
Block_release(parameters.pushback);
Block_release(parameters.get);
Block_release(parameters.overrideTransform);
Block_release(parameters.overrideData);
Block_release(parameters.overrideAttribute);
tr = NULL;
createFuncPtr = NULL;
process_data = NULL;
}
CFErrorRef CustomTransform::TransformStartingExecution()
{
CFTypeRef result = execute_starting();
return (CFErrorRef)result;
}
CFDictionaryRef CustomTransform::GetCustomExternalData()
{
CFTypeRef result = externalize_data();
if (NULL == result)
{
return NULL;
}
if (CFGetTypeID(result) == CFErrorGetTypeID())
{
CFRelease(result);
return NULL;
}
if (CFGetTypeID(result) == CFDictionaryGetTypeID())
{
return (CFDictionaryRef)result;
}
CFRelease(result);
result = NULL;
return (CFDictionaryRef)result;
}
void CustomTransform::SetCustomExternalData(CFDictionaryRef customData)
{
if (NULL != customData)
{
internalize_data(customData);
}
return;
}
CFErrorRef SecTransformSetAttributeAction(SecTransformImplementationRef ref,
CFStringRef action,
SecTransformStringOrAttributeRef attribute,
SecTransformAttributeActionBlock newAction)
{
if (NULL == ref)
{
CFErrorRef result = CreateSecTransformErrorRef(kSecTransformErrorInvalidInput,
"SecTransformSetAttributeNotificationAction called with a NULL SecTransformImplementationRef ref");
return result;
}
return (CFErrorRef)ref->overrideAttribute(action, attribute, newAction);
}
CFErrorRef SecTransformSetDataAction(SecTransformImplementationRef ref,
CFStringRef action,
SecTransformDataBlock newAction)
{
if (NULL == ref)
{
CFErrorRef result = CreateSecTransformErrorRef(kSecTransformErrorInvalidInput,
"SecTransformSetAttributeNotificationAction called with a NULL SecTransformImplementationRef ref");
return result;
}
return (CFErrorRef)ref->overrideData(action, newAction);
}
CFErrorRef SecTransformSetTransformAction(SecTransformImplementationRef ref,
CFStringRef action,
SecTransformActionBlock newAction)
{
if (NULL == ref)
{
CFErrorRef result = CreateSecTransformErrorRef(kSecTransformErrorInvalidInput,
"SecTransformSetAttributeNotificationAction called with a NULL SecTransformImplementationRef ref");
return result;
}
return (CFErrorRef)ref->overrideTransform(action, newAction);
}
CFTypeRef SecTranformCustomGetAttribute(SecTransformImplementationRef ref,
SecTransformStringOrAttributeRef attribute,
SecTransformMetaAttributeType type)
{
if (NULL == ref)
{
CFErrorRef result = CreateSecTransformErrorRef(kSecTransformErrorInvalidInput,
"SecTransformCustomGetAttribute called with a NULL SecTransformImplementationRef ref");
return result;
}
return (CFErrorRef)ref->get(attribute, type);
}
CFTypeRef SecTransformCustomSetAttribute(SecTransformImplementationRef ref,
SecTransformStringOrAttributeRef attribute,
SecTransformMetaAttributeType type,
CFTypeRef value)
{
if (NULL == ref)
{
CFErrorRef result = CreateSecTransformErrorRef(kSecTransformErrorInvalidInput,
"SecTransformCustomSetAttribute called with a NULL SecTransformImplementationRef ref");
return result;
}
return (CFErrorRef)ref->send(attribute, type, value);
}
CFTypeRef SecTransformPushbackAttribute(SecTransformImplementationRef ref,
SecTransformStringOrAttributeRef attribute,
CFTypeRef value)
{
if (NULL == ref)
{
CFErrorRef result = CreateSecTransformErrorRef(kSecTransformErrorInvalidInput,
"SecTransformPushbackAttribute called with a NULL SecTransformImplementationRef ref");
return (CFTypeRef)result;
}
return ref->pushback(attribute, value);
}