2 * Copyright (c) 2017 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
24 #include <AssertMacros.h>
26 #import <Foundation/Foundation.h>
30 #include <utilities/SecDb.h>
31 #include <securityd/SecDbItem.h>
32 #include <securityd/SecItemSchema.h>
36 #import <CloudKit/CloudKit.h>
39 @implementation CKKSCKRecordHolder
41 - (instancetype) initWithCKRecord: (CKRecord*) record {
42 if(self = [super init]) {
43 self.zoneID = record.recordID.zoneID;
44 [self setFromCKRecord:record];
49 - (instancetype)initWithCKRecordType: (NSString*) recordType encodedCKRecord: (NSData*) encodedCKRecord zoneID:(CKRecordZoneID*)zoneID {
50 if(self = [super init]) {
52 _ckRecordType = recordType;
53 _encodedCKRecord = encodedCKRecord;
55 if(self.encodedCKRecord && ![self.storedCKRecord.recordID.zoneID isEqual: self.zoneID]) {
56 secerror("ckks: mismatching zone ids in a single record: %@ and %@", self.zoneID, self.storedCKRecord.recordID.zoneID);
62 - (CKRecord*) storedCKRecord {
63 if(!_encodedCKRecord) {
66 NSKeyedUnarchiver *coder = [[NSKeyedUnarchiver alloc] initForReadingWithData:_encodedCKRecord];
67 coder.requiresSecureCoding = YES;
68 CKRecord* ckRecord = [[CKRecord alloc] initWithCoder:coder];
69 [coder finishDecoding];
74 - (void) setStoredCKRecord: (CKRecord*) ckRecord {
76 _encodedCKRecord = nil;
79 self.zoneID = ckRecord.recordID.zoneID;
80 self.ckRecordType = ckRecord.recordType;
82 NSMutableData* data = [NSMutableData data];
83 NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
84 [ckRecord encodeWithCoder:archiver];
85 [archiver finishEncoding];
86 _encodedCKRecord = data;
89 - (CKRecord*) CKRecordWithZoneID: (CKRecordZoneID*) zoneID {
90 CKRecordID* recordID = [[CKRecordID alloc] initWithRecordName: [self CKRecordName] zoneID: zoneID];
91 CKRecord* record = nil;
93 if(self.encodedCKRecord == nil) {
94 record = [[CKRecord alloc] initWithRecordType:self.ckRecordType recordID:recordID];
96 record = self.storedCKRecord;
99 [self updateCKRecord:record zoneID:zoneID];
101 self.storedCKRecord = record;
105 - (NSString*) CKRecordName {
106 @throw [NSException exceptionWithName:NSInternalInconsistencyException
107 reason:[NSString stringWithFormat:@"%@ must override %@", NSStringFromClass([self class]), NSStringFromSelector(_cmd)]
110 - (CKRecord*) updateCKRecord: (CKRecord*) record zoneID: (CKRecordZoneID*) zoneID {
111 @throw [NSException exceptionWithName:NSInternalInconsistencyException
112 reason:[NSString stringWithFormat:@"%@ must override %@", NSStringFromClass([self class]), NSStringFromSelector(_cmd)]
115 - (void) setFromCKRecord: (CKRecord*) record {
116 @throw [NSException exceptionWithName:NSInternalInconsistencyException
117 reason:[NSString stringWithFormat:@"%@ must override %@", NSStringFromClass([self class]), NSStringFromSelector(_cmd)]
120 - (bool) matchesCKRecord: (CKRecord*) record {
121 @throw [NSException exceptionWithName:NSInternalInconsistencyException
122 reason:[NSString stringWithFormat:@"%@ must override %@", NSStringFromClass([self class]), NSStringFromSelector(_cmd)]
126 - (instancetype)copyWithZone:(NSZone *)zone {
127 CKKSCKRecordHolder *rhCopy = [super copyWithZone:zone];
128 rhCopy->_zoneID = _zoneID;
129 rhCopy->_ckRecordType = _ckRecordType;
130 rhCopy->_encodedCKRecord = _encodedCKRecord;