2 * Copyright (c) 2013-2014 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 <SecureObjectSync/SOSKVSKeys.h>
25 #include <utilities/SecCFWrappers.h>
26 #include <SecureObjectSync/SOSAccountPriv.h>
29 void AppendCircleKeyName(CFMutableArrayRef array
, CFStringRef name
) {
30 CFStringRef circle_key
= SOSCircleKeyCreateWithName(name
, NULL
);
31 CFArrayAppendValue(array
, circle_key
);
32 CFReleaseNull(circle_key
);
38 // TODO: Handle '|' and "¬" in other strings.
40 const CFStringRef kSOSKVSKeyParametersKey
= CFSTR(">KeyParameters");
41 const CFStringRef kSOSKVSInitialSyncKey
= CFSTR("^InitialSync");
42 const CFStringRef kSOSKVSAccountChangedKey
= CFSTR("^AccountChanged");
44 const CFStringRef sWarningPrefix
= CFSTR("!");
45 const CFStringRef sAncientCirclePrefix
= CFSTR("@");
46 const CFStringRef sCirclePrefix
= CFSTR("o");
47 const CFStringRef sRetirementPrefix
= CFSTR("-");
48 const CFStringRef sCircleSeparator
= CFSTR("|");
49 const CFStringRef sFromToSeparator
= CFSTR(":");
51 static CFStringRef
copyStringEndingIn(CFMutableStringRef in
, CFStringRef token
) {
52 if(token
== NULL
) return CFStringCreateCopy(NULL
, in
);
53 CFRange tokenAt
= CFStringFind(in
, token
, 0);
54 if(tokenAt
.location
== kCFNotFound
) return NULL
;
55 CFStringRef retval
= CFStringCreateWithSubstring(NULL
, in
, CFRangeMake(0, tokenAt
.location
));
56 CFStringDelete(in
, CFRangeMake(0, tokenAt
.location
+1));
60 SOSKVSKeyType
SOSKVSKeyGetKeyTypeAndParse(CFStringRef key
, CFStringRef
*circle
, CFStringRef
*from
, CFStringRef
*to
)
62 SOSKVSKeyType retval
= kUnknownKey
;
64 if(CFStringHasPrefix(key
, sCirclePrefix
)) retval
= kCircleKey
;
65 else if(CFStringHasPrefix(key
, sRetirementPrefix
)) retval
= kRetirementKey
;
66 else if(CFStringHasPrefix(key
, kSOSKVSKeyParametersKey
)) retval
= kParametersKey
;
67 else if(CFStringHasPrefix(key
, kSOSKVSInitialSyncKey
)) retval
= kInitialSyncKey
;
68 else if(CFStringHasPrefix(key
, kSOSKVSAccountChangedKey
)) retval
= kAccountChangedKey
;
69 else retval
= kMessageKey
;
74 CFRange fromRange
= CFRangeMake(1, CFStringGetLength(key
)-1);
75 *circle
= CFStringCreateWithSubstring(NULL
, key
, fromRange
);
79 CFStringRef mCircle
= NULL
;
80 CFStringRef mFrom
= NULL
;
81 CFStringRef mTo
= NULL
;
82 CFMutableStringRef keycopy
= CFStringCreateMutableCopy(NULL
, 128, key
);
84 if( ((mCircle
= copyStringEndingIn(keycopy
, sCircleSeparator
)) != NULL
) &&
85 ((mFrom
= copyStringEndingIn(keycopy
, sFromToSeparator
)) != NULL
) &&
86 (CFStringGetLength(mFrom
) > 0) ) {
87 mTo
= copyStringEndingIn(keycopy
, NULL
);
88 if (circle
&& mCircle
) *circle
= CFStringCreateCopy(NULL
, mCircle
);
89 if (from
&& mFrom
) *from
= CFStringCreateCopy(NULL
, mFrom
);
90 if (to
&& mTo
) *to
= CFStringCreateCopy(NULL
, mTo
);
94 CFReleaseNull(mCircle
);
97 CFReleaseNull(keycopy
);
100 case kRetirementKey
: {
101 CFStringRef mCircle
= NULL
;
102 CFStringRef mPeer
= NULL
;
103 CFMutableStringRef keycopy
= CFStringCreateMutableCopy(NULL
, 128, key
);
104 CFStringDelete(keycopy
, CFRangeMake(0, 1));
105 if( ((mCircle
= copyStringEndingIn(keycopy
, sCircleSeparator
)) != NULL
) &&
106 ((mPeer
= copyStringEndingIn(keycopy
, NULL
)) != NULL
)) {
107 if (circle
) *circle
= CFStringCreateCopy(NULL
, mCircle
);
108 if (from
) *from
= CFStringCreateCopy(NULL
, mPeer
);
110 retval
= kUnknownKey
;
112 // TODO - Update our circle
113 CFReleaseNull(mCircle
);
114 CFReleaseNull(mPeer
);
115 CFReleaseNull(keycopy
);
118 case kAccountChangedKey
:
120 case kInitialSyncKey
:
129 SOSKVSKeyType
SOSKVSKeyGetKeyType(CFStringRef key
)
131 return SOSKVSKeyGetKeyTypeAndParse(key
, NULL
, NULL
, NULL
);
134 CFStringRef
SOSCircleKeyCreateWithCircle(SOSCircleRef circle
, CFErrorRef
*error
)
136 return SOSCircleKeyCreateWithName(SOSCircleGetName(circle
), error
);
140 CFStringRef
SOSCircleKeyCreateWithName(CFStringRef circleName
, CFErrorRef
*error
)
142 if(!circleName
) return NULL
;
143 return CFStringCreateWithFormat(NULL
, NULL
, CFSTR("%@%@"), sCirclePrefix
, circleName
);
146 CFStringRef
SOSCircleKeyCopyCircleName(CFStringRef key
, CFErrorRef
*error
)
148 CFStringRef circleName
= NULL
;
150 if (kCircleKey
!= SOSKVSKeyGetKeyTypeAndParse(key
, &circleName
, NULL
, NULL
)) {
151 SOSCreateErrorWithFormat(kSOSErrorNoCircleName
, NULL
, error
, NULL
, CFSTR("Couldn't find circle name in key '%@'"), key
);
153 CFReleaseNull(circleName
);
159 CFStringRef
SOSMessageKeyCopyCircleName(CFStringRef key
, CFErrorRef
*error
)
161 CFStringRef circleName
= NULL
;
163 if (SOSKVSKeyGetKeyTypeAndParse(key
, &circleName
, NULL
, NULL
) != kMessageKey
) {
164 SOSCreateErrorWithFormat(kSOSErrorNoCircleName
, NULL
, error
, NULL
, CFSTR("Couldn't find circle name in key '%@'"), key
);
166 CFReleaseNull(circleName
);
171 CFStringRef
SOSMessageKeyCopyFromPeerName(CFStringRef messageKey
, CFErrorRef
*error
)
173 CFStringRef fromPeer
= NULL
;
175 if (SOSKVSKeyGetKeyTypeAndParse(messageKey
, NULL
, &fromPeer
, NULL
) != kMessageKey
) {
176 SOSCreateErrorWithFormat(kSOSErrorNoCircleName
, NULL
, error
, NULL
, CFSTR("Couldn't find from peer in key '%@'"), messageKey
);
178 CFReleaseNull(fromPeer
);
183 CFStringRef
SOSMessageKeyCreateWithCircleNameAndPeerNames(CFStringRef circleName
, CFStringRef from_peer_name
, CFStringRef to_peer_name
)
185 return CFStringCreateWithFormat(NULL
, NULL
, CFSTR("%@%@%@%@%@"),
186 circleName
, sCircleSeparator
, from_peer_name
, sFromToSeparator
, to_peer_name
);
189 CFStringRef
SOSMessageKeyCreateWithCircleAndPeerNames(SOSCircleRef circle
, CFStringRef from_peer_name
, CFStringRef to_peer_name
)
191 return SOSMessageKeyCreateWithCircleNameAndPeerNames(SOSCircleGetName(circle
), from_peer_name
, to_peer_name
);
194 CFStringRef
SOSMessageKeyCreateWithCircleAndPeerInfos(SOSCircleRef circle
, SOSPeerInfoRef from_peer
, SOSPeerInfoRef to_peer
)
196 return SOSMessageKeyCreateWithCircleAndPeerNames(circle
, SOSPeerInfoGetPeerID(from_peer
), SOSPeerInfoGetPeerID(to_peer
));
199 CFStringRef
SOSMessageKeyCreateFromPeerToTransport(SOSTransportMessageKVSRef transport
, CFStringRef peer_name
) {
200 CFErrorRef error
= NULL
;
201 SOSEngineRef engine
= SOSTransportMessageGetEngine((SOSTransportMessageRef
)transport
);
203 CFStringRef circleName
= SOSTransportMessageKVSGetCircleName(transport
);
204 CFStringRef my_id
= SOSEngineGetMyID(engine
);
206 CFStringRef result
= SOSMessageKeyCreateWithCircleNameAndPeerNames(circleName
, peer_name
, my_id
);
207 CFReleaseSafe(error
);
211 CFStringRef
SOSMessageKeyCreateFromTransportToPeer(SOSTransportMessageKVSRef transport
, CFStringRef peer_name
) {
212 CFErrorRef error
= NULL
;
213 SOSEngineRef engine
= SOSTransportMessageGetEngine((SOSTransportMessageRef
)transport
);
215 CFStringRef circleName
= SOSTransportMessageKVSGetCircleName(transport
);
216 CFStringRef my_id
= SOSEngineGetMyID(engine
);
218 CFStringRef result
= SOSMessageKeyCreateWithCircleNameAndPeerNames(circleName
, my_id
, peer_name
);
219 CFReleaseSafe(error
);
223 CFStringRef
SOSRetirementKeyCreateWithCircleNameAndPeer(CFStringRef circle_name
, CFStringRef retirement_peer_name
)
225 return CFStringCreateWithFormat(NULL
, NULL
, CFSTR("%@%@%@%@"),
226 sRetirementPrefix
, circle_name
, sCircleSeparator
, retirement_peer_name
);
229 CFStringRef
SOSRetirementKeyCreateWithCircleAndPeer(SOSCircleRef circle
, CFStringRef retirement_peer_name
)
231 return SOSRetirementKeyCreateWithCircleNameAndPeer(SOSCircleGetName(circle
), retirement_peer_name
);