SecTransformReadTransform.cpp [plain text]
#include "SecTransformReadTransform.h"
#include "SecCustomTransform.h"
#include "Utilities.h"
static CFStringRef kStreamTransformName = CFSTR("SecReadStreamTransform");
static CFStringRef kStreamMaxSize = CFSTR("MAX_READSIZE");
static SecTransformInstanceBlock StreamTransformImplementation(CFStringRef name,
SecTransformRef newTransform,
SecTransformImplementationRef ref)
{
SecTransformInstanceBlock instanceBlock =
^{
CFErrorRef result = NULL;
if (NULL == name || NULL == newTransform)
{
}
__block CFIndex blockSize = 4096;
SecTransformCustomSetAttribute(ref, kStreamMaxSize, kSecTransformMetaAttributeRequired, kCFBooleanFalse);
SecTransformSetAttributeAction(ref, kSecTransformActionAttributeNotification, kStreamMaxSize,
^(SecTransformAttributeRef attribute, CFTypeRef value)
{
CFNumberGetValue((CFNumberRef) value, kCFNumberCFIndexType, &blockSize);
return value;
});
SecTransformSetAttributeAction(ref, kSecTransformActionAttributeNotification, kSecTransformInputAttributeName,
^(SecTransformAttributeRef attribute, CFTypeRef value)
{
if (value == NULL)
{
return (CFTypeRef) NULL;
}
CFArrayRef array = (CFArrayRef) value;
CFReadStreamRef input = (CFReadStreamRef) CFArrayGetValueAtIndex(array, 0);
if (!CFReadStreamOpen(input))
{
return (CFTypeRef) CreateSecTransformErrorRef(kSecTransformErrorInvalidInput, "An error occurred while opening the stream.");
}
u_int8_t* buffer = (u_int8_t*) malloc(blockSize);
CFIndex bytesRead;
bytesRead = CFReadStreamRead(input, buffer, blockSize);
while (bytesRead > 0)
{
CFDataRef value = CFDataCreate(NULL, buffer, bytesRead);
SecTransformCustomSetAttribute(ref, kSecTransformOutputAttributeName, kSecTransformMetaAttributeValue, value);
CFRelease(value);
bytesRead = CFReadStreamRead(input, buffer, blockSize);
}
free(buffer);
SecTransformCustomSetAttribute(ref, kSecTransformOutputAttributeName, kSecTransformMetaAttributeValue, (CFTypeRef) NULL);
return (CFTypeRef) NULL;
});
return result;
};
return Block_copy(instanceBlock);
}
SecTransformRef SecTransformCreateReadTransformWithReadStream(CFReadStreamRef inputStream)
{
static dispatch_once_t once = 0;
__block bool ok = true;
__block CFErrorRef result = NULL;
dispatch_once(&once,
^{
ok = SecTransformRegister(kStreamTransformName, &StreamTransformImplementation, &result);
});
if (!ok)
{
return result;
}
else
{
SecTransformRef transform = SecTransformCreate(kStreamTransformName, &result);
if (NULL != transform)
{
CFTypeRef arrayData[] = {inputStream};
CFArrayRef arrayRef = CFArrayCreate(NULL, arrayData, 1, &kCFTypeArrayCallBacks);
SecTransformSetAttribute(transform, kSecTransformInputAttributeName, arrayRef, &result);
CFRelease(arrayRef);
}
return transform;
}
}