+++ /dev/null
-/*
- * Copyright (c) 2010-2011 Apple Inc. All Rights Reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-
-#include "Transform.h"
-#include "SecTransform.h"
-#include "SecCollectTransform.h"
-#include "SecCustomTransform.h"
-#include "misc.h"
-#include "c++utils.h"
-#include "Utilities.h"
-
-static CFStringRef kCollectTransformName = CFSTR("com.apple.security.seccollecttransform");
-
-static SecTransformInstanceBlock CollectTransform(CFStringRef name,
- SecTransformRef newTransform,
- SecTransformImplementationRef ref)
-{
- SecTransformInstanceBlock instanceBlock =
- ^{
- __block CFMutableArrayRef allValues =
- CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
- __block Boolean isSameType = TRUE;
- CFTypeRef input_ah = SecTranformCustomGetAttribute(ref, kSecTransformInputAttributeName, kSecTransformMetaAttributeRef);
- ah2ta(input_ah)->direct_error_handling = 1;
-
- dispatch_block_t no_more_output = ^
- {
- SecTransformSetAttributeAction(ref, kSecTransformActionAttributeNotification, input_ah, ^(SecTransformStringOrAttributeRef a, CFTypeRef v) { return v; });
- };
-
- // Create a block to deal with out of memory errors
- dispatch_block_t oom = ^
- {
- CFTypeRefHolder localErr(GetNoMemoryError());
- SecTransformCustomSetAttribute(ref, kSecTransformOutputAttributeName,
- kSecTransformMetaAttributeValue, localErr.Get());
- no_more_output();
- };
-
- SecTransformSetTransformAction(ref, kSecTransformActionFinalize,
- ^()
- {
- if (NULL != allValues)
- {
- CFRelease(allValues);
- }
-
- return (CFTypeRef) NULL;
- });
-
- SecTransformSetAttributeAction(ref, kSecTransformActionAttributeNotification,
- input_ah,
- ^(SecTransformStringOrAttributeRef attribute, CFTypeRef value)
- {
- CFIndex len = CFArrayGetCount(allValues);
-
-#if 0
- if (NULL == value && 0 == len)
- {
- SecTransformCustomSetAttribute(ref, kSecTransformOutputAttributeName,
- kSecTransformMetaAttributeValue, NULL);
- no_more_output();
- return value;
- }
-#endif
-
- if (value && isSameType && len > 0)
- {
- isSameType = CFGetTypeID(CFArrayGetValueAtIndex(allValues, 0)) == CFGetTypeID(value);
- }
-
- if (value)
- {
-
- if (CFGetTypeID(value) == CFErrorGetTypeID())
- {
- SecTransformCustomSetAttribute(ref, kSecTransformOutputAttributeName,
- kSecTransformMetaAttributeValue, value);
- no_more_output();
- return value;
- }
-
- // For mutable types, we want an immutable copy.
- /// XXX: write a more general CFImutableCopy and use it here.
- if (CFGetTypeID(value) == CFDataGetTypeID())
- {
- CFDataRef copy = CFDataCreateCopy(NULL, (CFDataRef)value);
-
- CFArrayAppendValue(allValues, copy);
- CFRelease(copy);
- }
- else
- {
- CFArrayAppendValue(allValues, value);
- }
-
- if (CFArrayGetCount(allValues) != len +1)
- {
- oom();
- return value;
- }
- }
- else
- {
- if (isSameType)
- {
- // Deal with data or no items at all
- CFTypeID type = CFArrayGetCount(allValues) ?
- CFGetTypeID(CFArrayGetValueAtIndex(allValues, 0)) : CFDataGetTypeID();
- if (CFDataGetTypeID() == type)
- {
- CFIndex total_len = 0;
- CFIndex prev_total_len = 0;
- CFIndex i;
- const CFIndex n_datas = CFArrayGetCount(allValues);
-
- for(i = 0; i < n_datas; i++)
- {
- total_len +=
- CFDataGetLength((CFDataRef)CFArrayGetValueAtIndex(allValues, i));
- if (total_len < prev_total_len)
- {
- oom();
- return value;
- }
- prev_total_len = total_len;
- }
-
- CFMutableDataRef result = CFDataCreateMutable(NULL, total_len);
- if (!result)
- {
- oom();
- return value;
- }
-
- for(i = 0; i < n_datas; i++)
- {
- CFDataRef d = (CFDataRef)CFArrayGetValueAtIndex(allValues, i);
- CFDataAppendBytes(result, CFDataGetBytePtr(d), CFDataGetLength(d));
- }
-
- if (CFDataGetLength(result) != total_len)
- {
- oom();
- return value;
- }
-
- CFDataRef resultData = CFDataCreateCopy(NULL, result);
-
- SecTransformCustomSetAttribute(ref, kSecTransformOutputAttributeName,
- kSecTransformMetaAttributeValue, (CFTypeRef)resultData);
-
- CFRelease(resultData);
-
- SecTransformCustomSetAttribute(ref, kSecTransformOutputAttributeName,
- kSecTransformMetaAttributeValue, (CFTypeRef)value);
- no_more_output();
-
- CFRelease(result);
- return value;
- }
- else if (CFStringGetTypeID() == type)
- {
- // deal with strings
- CFStringRef resultStr = CFStringCreateByCombiningStrings(NULL, allValues, CFSTR(""));
-
- SecTransformCustomSetAttribute(ref, kSecTransformOutputAttributeName,
- kSecTransformMetaAttributeValue, (CFTypeRef)resultStr);
- SecTransformCustomSetAttribute(ref, kSecTransformOutputAttributeName,
- kSecTransformMetaAttributeValue, (CFTypeRef)value);
- no_more_output();
-
- return value;
- }
- else
- {
- // special case the singleton
- if (1 == CFArrayGetCount(allValues))
- {
- CFTypeRef result = (CFTypeRef)CFRetain(CFArrayGetValueAtIndex(allValues, 0));
-
- SecTransformCustomSetAttribute(ref, kSecTransformOutputAttributeName,
- kSecTransformMetaAttributeValue, (CFTypeRef)result);
- SecTransformCustomSetAttribute(ref, kSecTransformOutputAttributeName,
- kSecTransformMetaAttributeValue, (CFTypeRef)value);
- no_more_output();
-
- return value;
- }
- }
- }
- // Fall through for non-homogenous or un-mergable type
- CFArrayRef resultArray = CFArrayCreateCopy(kCFAllocatorDefault, allValues);
- SecTransformCustomSetAttribute(ref, kSecTransformOutputAttributeName,
- kSecTransformMetaAttributeValue, (CFTypeRef)resultArray);
- SecTransformCustomSetAttribute(ref, kSecTransformOutputAttributeName,
- kSecTransformMetaAttributeValue, (CFTypeRef)value);
- no_more_output();
-
- return value;
- }
-
- return value;
-
- });
-
- return (CFErrorRef)NULL;
- };
-
- return Block_copy(instanceBlock);
-}
-
-SecTransformRef SecCreateCollectTransform(CFErrorRef* error)
-{
- static dispatch_once_t once;
- __block Boolean ok = TRUE;
-
- dispatch_block_t aBlock = ^
- {
- ok = SecTransformRegister(kCollectTransformName, &CollectTransform, error);
- };
-
- dispatch_once(&once, aBlock);
-
- if (!ok)
- {
- return NULL;
- }
-
- SecTransformRef yatz = SecTransformCreate(kCollectTransformName, error);
- return yatz;
-}