]> git.saurik.com Git - apple/security.git/blobdiff - OSX/sec/SOSCircle/SecureObjectSync/SOSViewManager.c
Security-57336.1.9.tar.gz
[apple/security.git] / OSX / sec / SOSCircle / SecureObjectSync / SOSViewManager.c
diff --git a/OSX/sec/SOSCircle/SecureObjectSync/SOSViewManager.c b/OSX/sec/SOSCircle/SecureObjectSync/SOSViewManager.c
new file mode 100644 (file)
index 0000000..7fab73a
--- /dev/null
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 2015 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@
+ */
+
+/*
+ * SOSViewManager.c -  Implementation of a view manager
+ */
+
+#include <Security/SecureObjectSync/SOSViewManager.h>
+#include <Security/SecureObjectSync/SOSInternal.h>
+
+#if 0
+/* SOSViewManager implementation. */
+struct __OpaqueSOSViewManager {
+    CFRuntimeBase _base;
+    CFMutableDictionaryRef views;
+};
+
+const CFStringRef kSOSContextChildInfoKey = CFSTR("cntx");
+const CFStringRef kSOSFunctionChildInfoKey = CFSTR("fctn");
+const CFStringRef kSOSViewNamesChildInfoKey = CFSTR("vwns");
+
+
+static CFStringRef SOSViewManagerCopyFormatDescription(CFTypeRef cf, CFDictionaryRef formatOptions) {
+    SOSViewManagerRef vmgr = (SOSViewManagerRef)cf;
+    CFStringRef desc = CFStringCreateWithFormat(kCFAllocatorDefault, formatOptions, CFSTR("<ViewManager %@ >"), vmgr->views);
+    return desc;
+}
+
+static void SOSViewManagerDestroy(CFTypeRef cf) {
+    SOSViewManagerRef vmgr = (SOSViewManagerRef)cf;
+    CFReleaseSafe(vmgr->views);
+}
+
+CFGiblisFor(SOSViewManager);
+
+
+static SOSViewManagerRef SOSViewManagerCreate(CFAllocatorRef allocator, CFErrorRef *error) {
+    SOSViewManagerRef vmgr = NULL;
+    vmgr = CFTypeAllocate(SOSViewManager, struct __OpaqueSOSViewManager, allocator);
+    if (vmgr)
+        vmgr->views = CFDictionaryCreateMutableForCFTypes(allocator);
+    return vmgr;
+}
+
+CFGiblisGetSingleton(SOSViewManagerRef, SOSGetViewManager, sSOSViewManager,  ^{
+    *sSOSViewManager = SOSViewManagerCreate(kCFAllocatorDefault, NULL);
+});
+
+
+static CFStringRef CFStringCreateWithViewNames(CFArrayRef viewNames) {
+    CFIndex count = CFArrayGetCount(viewNames);
+    CFMutableArrayRef mvn = CFArrayCreateMutableCopy(kCFAllocatorDefault, count, viewNames);
+    CFArraySortValues(mvn, CFRangeMake(0, count), (CFComparatorFunction)CFStringCompare, 0);
+    CFStringRef string = CFStringCreateByCombiningStrings(kCFAllocatorDefault, mvn, CFSTR(":"));
+    CFRelease(mvn);
+    return string;
+}
+
+static SOSViewRef SOSViewManangerCopyViewWithName(SOSViewManagerRef vmgr, CFMutableDictionaryRef referencedViews, CFStringRef viewName, bool isConcrete, CFErrorRef *error) {
+    SOSViewRef view = (SOSViewRef)CFDictionaryGetValue(vmgr->views, viewName);
+    if (view) {
+        if (isConcrete)
+            SOSViewSetConcrete(view, true);
+        CFRetain(view);
+    } else {
+        view = SOSViewCreate(CFGetAllocator(vmgr), isConcrete, NULL, error);
+        if (view) {
+            CFDictionarySetValue(vmgr->views, viewName, view);
+        }
+        // TODO: Query for the initial manifest.
+    }
+    if (view) {
+        if (isConcrete)
+            CFDictionarySetValue(referencedViews, viewName, kCFBooleanTrue);
+        else if (!CFDictionaryContainsKey(referencedViews, viewName))
+            CFDictionarySetValue(referencedViews, viewName, kCFBooleanFalse);
+    }
+    return view;
+}
+
+static SOSViewRef SOSViewManangerCopyCompositeViewWithNames(SOSViewManagerRef vmgr, CFMutableDictionaryRef referencedViews, CFArrayRef viewNames, CFErrorRef *error) {
+    CFStringRef compositeName = CFStringCreateWithViewNames(viewNames);
+    SOSViewRef compositeView = (SOSViewRef)CFDictionaryGetValue(vmgr->views, compositeName);
+    if (compositeView) {
+        CFDictionarySetValue(referencedViews, compositeName, kCFBooleanTrue);
+        CFRetain(compositeView);
+    } else {
+        compositeView = SOSViewCreate(CFGetAllocator(vmgr), true, NULL, error);
+        if (compositeView) {
+            // Find the views for each name, and add the new view as a child to each one.
+            CFStringRef viewName;
+            CFArrayForEachC(viewNames, viewName) {
+                SOSViewRef parent = SOSViewManangerCopyViewWithName(vmgr, referencedViews, viewName, false, error);
+                if (!parent) {
+                    CFReleaseNull(compositeView);
+                    break;
+                }
+                SOSViewAddChild(parent, compositeView);
+                // Update the composite view's manifest by adding each parents manifest.
+                // TODO: Potentially move this out of the loop and create a single multi way manifest union operation
+                SOSManifestRef pmf = SOSViewCopyManifest(parent, error);
+                SOSViewUpdateManifest(compositeView, kSOSDataSourceSOSTransaction, NULL, pmf, error);
+                CFReleaseSafe(pmf);
+            }
+            CFDictionarySetValue(vmgr->views, viewName, compositeView);
+        }
+    }
+    CFReleaseSafe(compositeName);
+    return compositeView;
+}
+
+static bool SOSViewManangerAddChildWithInfo(SOSViewManagerRef vmgr, CFMutableDictionaryRef referencedViews, CFDictionaryRef childInfo, CFErrorRef *error) {
+    CFArrayRef viewNames = (CFArrayRef)CFDictionaryGetValue(childInfo, kSOSViewNamesChildInfoKey);
+//    const void *context = (const void *)CFDictionaryGetValue(childInfo, kSOSContextChildInfoKey);
+//    const void *func = (const void *)CFDictionaryGetValue(childInfo, kSOSFunctionChildInfoKey);
+
+    CFIndex count = CFArrayGetCount(viewNames);
+    if (count == 1) {
+        CFStringRef key = CFArrayGetValueAtIndex(viewNames, 0);
+        SOSViewRef view = SOSViewManangerCopyViewWithName(vmgr, referencedViews, key, true, error);
+        // TODO: Fix this...
+        //SOSViewAddClient(view, context, func);
+        if (view) count++;  // TODO: REMOVE MOVE -- HERE ONLY FOR COMPILER WARNING
+    } else if (count > 1) {
+        SOSViewRef view = SOSViewManangerCopyCompositeViewWithNames(vmgr, referencedViews, viewNames, error);
+        // TODO: Fix this...
+        //SOSViewAddClient(view, context, func);
+        if (view) count++;  // TODO: REMOVE MOVE -- HERE ONLY FOR COMPILER WARNING
+    }
+
+    return true;
+}
+
+struct SOSViewManagerContext {
+    SOSViewManagerRef vmgr;
+    CFDictionaryRef referencedViews;
+};
+
+static void SOSViewManagerUpdateView(const void *key, const void *value, void *context) {
+    struct SOSViewManagerContext *vmc = context;
+    CFBooleanRef isConcrete = CFDictionaryGetValue(vmc->referencedViews, key);
+    if (!isConcrete) {
+        CFDictionaryRemoveValue(vmc->vmgr->views, key);
+    } else if (CFBooleanGetValue(isConcrete) == 0) {
+        SOSViewRef view = (SOSViewRef)CFDictionaryGetValue(vmc->vmgr->views, key);
+        SOSViewSetConcrete(view, false);
+    }
+}
+
+bool SOSViewManagerSetChildren(SOSViewManagerRef vmgr, CFArrayRef children, CFErrorRef *error) {
+    bool ok = true;
+    CFMutableDictionaryRef referencedViews = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault);
+    CFDictionaryRef childInfo;
+    CFArrayForEachC(children, childInfo) {
+        ok &= SOSViewManangerAddChildWithInfo(vmgr, referencedViews, childInfo, error);
+    }
+
+    // Potentially populate all views here.
+
+    // Cleanup, remove any views we no longer reference, and set any views which need not be concrete as such.
+    struct SOSViewManagerContext vmc = {
+        .vmgr = vmgr,
+        .referencedViews = referencedViews,
+    };
+    CFDictionaryApplyFunction(vmgr->views, SOSViewManagerUpdateView, &vmc);
+    CFRetainSafe(referencedViews);
+
+    return ok;
+}
+#endif