#include <Security/SecureObjectSync/SOSKVSKeys.h>
#include <utilities/SecCFWrappers.h>
#include <Security/SecureObjectSync/SOSAccountPriv.h>
#include <CoreFoundation/CFDate.h>
void AppendCircleKeyName(CFMutableArrayRef array, CFStringRef name) {
CFStringRef circle_key = SOSCircleKeyCreateWithName(name, NULL);
CFArrayAppendValue(array, circle_key);
CFReleaseNull(circle_key);
}
const CFStringRef kSOSKVSKeyParametersKey = CFSTR(">KeyParameters");
const CFStringRef kSOSKVSInitialSyncKey = CFSTR("^InitialSync");
const CFStringRef kSOSKVSAccountChangedKey = CFSTR("^AccountChanged");
const CFStringRef kSOSKVSRequiredKey = CFSTR("^Required");
const CFStringRef kSOSKVSOfficialDSIDKey = CFSTR("^OfficialDSID");
const CFStringRef kSOSKVSDebugScope = CFSTR("^DebugScope");
const CFStringRef sPeerInfoPrefix = CFSTR("+");
const CFStringRef sRingPrefix = CFSTR("~");
const CFStringRef sDebugInfoPrefix = CFSTR("dbg-");
const CFStringRef sWarningPrefix = CFSTR("!");
const CFStringRef sAncientCirclePrefix = CFSTR("@");
const CFStringRef sCirclePrefix = CFSTR("o");
const CFStringRef sRetirementPrefix = CFSTR("-");
const CFStringRef sLastCirclePushedPrefix = CFSTR("p");
const CFStringRef sLastKeyParametersPushedPrefix = CFSTR("k");
const CFStringRef sCircleSeparator = CFSTR("|");
const CFStringRef sFromToSeparator = CFSTR(":");
static CFStringRef copyStringEndingIn(CFMutableStringRef in, CFStringRef token) {
if(token == NULL) return CFStringCreateCopy(NULL, in);
CFRange tokenAt = CFStringFind(in, token, 0);
if(tokenAt.location == kCFNotFound) return NULL;
CFStringRef retval = CFStringCreateWithSubstring(NULL, in, CFRangeMake(0, tokenAt.location));
CFStringDelete(in, CFRangeMake(0, tokenAt.location+1));
return retval;
}
SOSKVSKeyType SOSKVSKeyGetKeyTypeAndParse(CFStringRef key, CFStringRef *circle, CFStringRef *peerInfo, CFStringRef *ring, CFStringRef *backupName, CFStringRef *from, CFStringRef *to)
{
SOSKVSKeyType retval = kUnknownKey;
if(CFStringHasPrefix(key, sCirclePrefix)) retval = kCircleKey;
else if (CFStringHasPrefix(key, sRingPrefix)) retval = kRingKey;
else if(CFStringHasPrefix(key, sPeerInfoPrefix)) retval = kPeerInfoKey;
else if(CFStringHasPrefix(key, sRetirementPrefix)) retval = kRetirementKey;
else if(CFStringHasPrefix(key, kSOSKVSKeyParametersKey)) retval = kParametersKey;
else if(CFStringHasPrefix(key, kSOSKVSInitialSyncKey)) retval = kInitialSyncKey;
else if(CFStringHasPrefix(key, kSOSKVSAccountChangedKey)) retval = kAccountChangedKey;
else if(CFStringHasPrefix(key, sDebugInfoPrefix)) retval = kDebugInfoKey;
else if(CFStringHasPrefix(key, sLastCirclePushedPrefix)) retval = kLastCircleKey;
else if(CFStringHasPrefix(key, sLastKeyParametersPushedPrefix)) retval = kLastKeyParameterKey;
else retval = kMessageKey;
switch(retval) {
case kCircleKey:
if (circle) {
CFRange fromRange = CFRangeMake(1, CFStringGetLength(key)-1);
*circle = CFStringCreateWithSubstring(NULL, key, fromRange);
}
break;
case kMessageKey: {
CFStringRef mCircle = NULL;
CFStringRef mFrom = NULL;
CFStringRef mTo = NULL;
CFMutableStringRef keycopy = CFStringCreateMutableCopy(NULL, 128, key);
if( ((mCircle = copyStringEndingIn(keycopy, sCircleSeparator)) != NULL) &&
((mFrom = copyStringEndingIn(keycopy, sFromToSeparator)) != NULL) &&
(CFStringGetLength(mFrom) > 0) ) {
mTo = copyStringEndingIn(keycopy, NULL);
if (circle && mCircle) *circle = CFStringCreateCopy(NULL, mCircle);
if (from && mFrom) *from = CFStringCreateCopy(NULL, mFrom);
if (to && mTo) *to = CFStringCreateCopy(NULL, mTo);
} else {
retval = kUnknownKey;
}
CFReleaseNull(mCircle);
CFReleaseNull(mFrom);
CFReleaseNull(mTo);
CFReleaseNull(keycopy);
}
break;
case kRetirementKey: {
CFStringRef mCircle = NULL;
CFStringRef mPeer = NULL;
CFMutableStringRef keycopy = CFStringCreateMutableCopy(NULL, 128, key);
CFStringDelete(keycopy, CFRangeMake(0, 1));
if( ((mCircle = copyStringEndingIn(keycopy, sCircleSeparator)) != NULL) &&
((mPeer = copyStringEndingIn(keycopy, NULL)) != NULL)) {
if (circle) *circle = CFStringCreateCopy(NULL, mCircle);
if (from) *from = CFStringCreateCopy(NULL, mPeer);
} else {
retval = kUnknownKey;
}
CFReleaseNull(mCircle);
CFReleaseNull(mPeer);
CFReleaseNull(keycopy);
}
break;
case kRingKey:
if (ring) {
CFRange fromRange = CFRangeMake(1, CFStringGetLength(key)-1);
*ring = CFStringCreateWithSubstring(NULL, key, fromRange);
}
break;
case kPeerInfoKey:
if (peerInfo) {
CFRange fromRange = CFRangeMake(1, CFStringGetLength(key)-1);
*peerInfo = CFStringCreateWithSubstring(NULL, key, fromRange);
}
break;
case kDebugInfoKey:
if (peerInfo) {
CFRange dbgRange = CFRangeMake(CFStringGetLength(sDebugInfoPrefix),
CFStringGetLength(key)-CFStringGetLength(sDebugInfoPrefix));
*peerInfo = CFStringCreateWithSubstring(NULL, key, dbgRange);
}
break;
case kAccountChangedKey:
case kParametersKey:
case kInitialSyncKey:
case kUnknownKey:
case kLastKeyParameterKey:
case kLastCircleKey:
break;
}
return retval;
}
SOSKVSKeyType SOSKVSKeyGetKeyType(CFStringRef key)
{
return SOSKVSKeyGetKeyTypeAndParse(key, NULL, NULL, NULL, NULL, NULL, NULL);
}
CFStringRef SOSCircleKeyCreateWithCircle(SOSCircleRef circle, CFErrorRef *error)
{
return SOSCircleKeyCreateWithName(SOSCircleGetName(circle), error);
}
CFStringRef SOSCircleKeyCreateWithName(CFStringRef circleName, CFErrorRef *error)
{
if(!circleName) return NULL;
return CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@"), sCirclePrefix, circleName);
}
CFStringRef SOSPeerInfoKeyCreateWithName(CFStringRef peer_info_name, CFErrorRef *error)
{
if(!peer_info_name) return NULL;
return CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@"), sPeerInfoPrefix, peer_info_name);
}
CFStringRef SOSRingKeyCreateWithName(CFStringRef ring_name, CFErrorRef *error)
{
if(!ring_name) return NULL;
return CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@"), sRingPrefix, ring_name);
}
CFStringRef SOSCircleKeyCopyCircleName(CFStringRef key, CFErrorRef *error)
{
CFStringRef circleName = NULL;
if (kCircleKey != SOSKVSKeyGetKeyTypeAndParse(key, &circleName, NULL, NULL, NULL, NULL, NULL)) {
SOSCreateErrorWithFormat(kSOSErrorNoCircleName, NULL, error, NULL, CFSTR("Couldn't find circle name in key '%@'"), key);
CFReleaseNull(circleName);
}
return circleName;
}
CFStringRef SOSMessageKeyCopyCircleName(CFStringRef key, CFErrorRef *error)
{
CFStringRef circleName = NULL;
if (SOSKVSKeyGetKeyTypeAndParse(key, &circleName, NULL, NULL, NULL, NULL, NULL) != kMessageKey) {
SOSCreateErrorWithFormat(kSOSErrorNoCircleName, NULL, error, NULL, CFSTR("Couldn't find circle name in key '%@'"), key);
CFReleaseNull(circleName);
}
return circleName;
}
CFStringRef SOSMessageKeyCopyFromPeerName(CFStringRef messageKey, CFErrorRef *error)
{
CFStringRef fromPeer = NULL;
if (SOSKVSKeyGetKeyTypeAndParse(messageKey, NULL, NULL, NULL, NULL, &fromPeer, NULL) != kMessageKey) {
SOSCreateErrorWithFormat(kSOSErrorNoCircleName, NULL, error, NULL, CFSTR("Couldn't find from peer in key '%@'"), messageKey);
CFReleaseNull(fromPeer);
}
return fromPeer;
}
CFStringRef SOSMessageKeyCreateWithCircleNameAndPeerNames(CFStringRef circleName, CFStringRef from_peer_name, CFStringRef to_peer_name)
{
return CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@%@%@%@"),
circleName, sCircleSeparator, from_peer_name, sFromToSeparator, to_peer_name);
}
CFStringRef SOSMessageKeyCreateWithCircleNameAndTransportType(CFStringRef circleName, CFStringRef transportType)
{
return CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@%@%@%@"),
circleName, sCircleSeparator, transportType, sFromToSeparator, SOSTransportMessageTypeIDS);
}
CFStringRef SOSMessageKeyCreateWithCircleAndPeerNames(SOSCircleRef circle, CFStringRef from_peer_name, CFStringRef to_peer_name)
{
return SOSMessageKeyCreateWithCircleNameAndPeerNames(SOSCircleGetName(circle), from_peer_name, to_peer_name);
}
CFStringRef SOSMessageKeyCreateWithCircleAndPeerInfos(SOSCircleRef circle, SOSPeerInfoRef from_peer, SOSPeerInfoRef to_peer)
{
return SOSMessageKeyCreateWithCircleAndPeerNames(circle, SOSPeerInfoGetPeerID(from_peer), SOSPeerInfoGetPeerID(to_peer));
}
CFStringRef SOSMessageKeyCreateFromPeerToTransport(SOSTransportMessageKVSRef transport, CFStringRef peer_name) {
CFErrorRef error = NULL;
SOSEngineRef engine = SOSTransportMessageGetEngine((SOSTransportMessageRef)transport);
CFStringRef circleName = SOSTransportMessageGetCircleName((SOSTransportMessageRef)transport);
CFStringRef my_id = SOSEngineGetMyID(engine);
CFStringRef result = SOSMessageKeyCreateWithCircleNameAndPeerNames(circleName, peer_name, my_id);
CFReleaseSafe(error);
return result;
}
CFStringRef SOSMessageKeyCreateFromTransportToPeer(SOSTransportMessageKVSRef transport, CFStringRef peer_name) {
CFErrorRef error = NULL;
SOSEngineRef engine = SOSTransportMessageGetEngine((SOSTransportMessageRef)transport);
CFStringRef circleName = SOSTransportMessageGetCircleName((SOSTransportMessageRef)transport);
CFStringRef my_id = SOSEngineGetMyID(engine);
CFStringRef result = SOSMessageKeyCreateWithCircleNameAndPeerNames(circleName, my_id, peer_name);
CFReleaseSafe(error);
return result;
}
CFStringRef SOSRetirementKeyCreateWithCircleNameAndPeer(CFStringRef circle_name, CFStringRef retirement_peer_name)
{
return CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@%@%@"),
sRetirementPrefix, circle_name, sCircleSeparator, retirement_peer_name);
}
CFStringRef SOSPeerInfoV2KeyCreateWithPeerName(CFStringRef peer_name)
{
return CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@"),
sPeerInfoPrefix, peer_name);
}
CFStringRef SOSRingKeyCreateWithRingName(CFStringRef ring_name)
{
return CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@"),
sRingPrefix, ring_name);
}
CFStringRef SOSRetirementKeyCreateWithCircleAndPeer(SOSCircleRef circle, CFStringRef retirement_peer_name)
{
return SOSRetirementKeyCreateWithCircleNameAndPeer(SOSCircleGetName(circle), retirement_peer_name);
}
CFStringRef SOSLastCirclePushedKeyCreateWithCircleNameAndPeerID(CFStringRef circleName, CFStringRef peerID){
return CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@%@%@%@"),
sLastCirclePushedPrefix, sCirclePrefix, circleName, sCircleSeparator, peerID);
}
CFStringRef SOSLastCirclePushedKeyCreateWithAccountGestalt(SOSAccountRef account){
CFStringRef gestaltInfo = SOSAccountCreateCompactDescription(account);
CFStringRef key = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@%@"),
sLastCirclePushedPrefix, sCirclePrefix, gestaltInfo);
CFReleaseNull(gestaltInfo);
return key;
}
CFStringRef SOSLastKeyParametersPushedKeyCreateWithPeerID(CFStringRef peerID){
return CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@%@%@"),
sLastKeyParametersPushedPrefix,kSOSKVSKeyParametersKey, sCircleSeparator, peerID);
}
CFStringRef SOSLastKeyParametersPushedKeyCreateWithAccountGestalt(SOSAccountRef account){
CFStringRef gestaltInfo = SOSAccountCreateCompactDescription(account);
CFStringRef key= CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@%@%@"),
sLastKeyParametersPushedPrefix, kSOSKVSKeyParametersKey, sCircleSeparator, gestaltInfo);
CFReleaseNull(gestaltInfo);
return key;
}
CFStringRef SOSDebugInfoKeyCreateWithTypeName(CFStringRef type_name)
{
return CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@"),
sDebugInfoPrefix, type_name);
}