1 #include "SecTransformReadTransform.h"
2 #include "SecCustomTransform.h"
5 static CFStringRef kStreamTransformName
= CFSTR("SecReadStreamTransform");
6 static CFStringRef kStreamMaxSize
= CFSTR("MAX_READSIZE");
8 static SecTransformInstanceBlock
StreamTransformImplementation(CFStringRef name
,
9 SecTransformRef newTransform
,
10 SecTransformImplementationRef ref
)
12 SecTransformInstanceBlock instanceBlock
=
14 CFErrorRef result
= NULL
;
16 if (NULL
== name
|| NULL
== newTransform
)
20 // define the storage for our block
21 __block CFIndex blockSize
= 4096; // make a default block size
23 // it's not necessary to set the input stream size
24 SecTransformCustomSetAttribute(ref
, kStreamMaxSize
, kSecTransformMetaAttributeRequired
, kCFBooleanFalse
);
26 // define the action if we change the max read size
27 SecTransformSetAttributeAction(ref
, kSecTransformActionAttributeNotification
, kStreamMaxSize
,
28 ^(SecTransformAttributeRef attribute
, CFTypeRef value
)
30 CFNumberGetValue((CFNumberRef
) value
, kCFNumberCFIndexType
, &blockSize
);
34 // define for our input action
35 SecTransformSetAttributeAction(ref
, kSecTransformActionAttributeNotification
, kSecTransformInputAttributeName
,
36 ^(SecTransformAttributeRef attribute
, CFTypeRef value
)
40 return (CFTypeRef
) NULL
;
43 CFArrayRef array
= (CFArrayRef
) value
;
44 CFReadStreamRef input
= (CFReadStreamRef
) CFArrayGetValueAtIndex(array
, 0);
47 if (!CFReadStreamOpen(input
))
49 // We didn't open properly. Error out
50 return (CFTypeRef
) CreateSecTransformErrorRef(kSecTransformErrorInvalidInput
, "An error occurred while opening the stream.");
53 // allocate the read buffer on the heap
54 u_int8_t
* buffer
= (u_int8_t
*) malloc(blockSize
);
58 bytesRead
= CFReadStreamRead(input
, buffer
, blockSize
);
61 // make data from what was read
62 CFDataRef value
= CFDataCreate(NULL
, buffer
, bytesRead
);
64 // send it down the chain
65 SecTransformCustomSetAttribute(ref
, kSecTransformOutputAttributeName
, kSecTransformMetaAttributeValue
, value
);
70 bytesRead
= CFReadStreamRead(input
, buffer
, blockSize
);
75 SecTransformCustomSetAttribute(ref
, kSecTransformOutputAttributeName
, kSecTransformMetaAttributeValue
, (CFTypeRef
) NULL
);
77 return (CFTypeRef
) NULL
;
83 return Block_copy(instanceBlock
);
88 SecTransformRef
SecTransformCreateReadTransformWithReadStream(CFReadStreamRef inputStream
)
90 static dispatch_once_t once
= 0;
92 __block
bool ok
= true;
93 __block CFErrorRef result
= NULL
;
97 ok
= SecTransformRegister(kStreamTransformName
, &StreamTransformImplementation
, &result
);
107 SecTransformRef transform
= SecTransformCreate(kStreamTransformName
, &result
);
108 if (NULL
!= transform
)
110 // if we add the read stream directly to the transform the internal source stream
111 // will take over. This is bad. Instead, we wrap this in a CFArray so that we can
112 // pass through undetected
113 CFTypeRef arrayData
[] = {inputStream
};
114 CFArrayRef arrayRef
= CFArrayCreate(NULL
, arrayData
, 1, &kCFTypeArrayCallBacks
);
116 // add the input to the transform
117 SecTransformSetAttribute(transform
, kSecTransformInputAttributeName
, arrayRef
, &result
);