From 7b02207537d35bfa1714bf8beafc921f717d100a Mon Sep 17 00:00:00 2001 From: 单军华 Date: Wed, 11 Jul 2018 10:47:42 +0800 Subject: [PATCH] 首次上传 --- screendisplay/Pods/UICKeyChainStore/Lib/UICKeyChainStore/UICKeyChainStore.m | 1392 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 1,392 insertions(+), 0 deletions(-) diff --git a/screendisplay/Pods/UICKeyChainStore/Lib/UICKeyChainStore/UICKeyChainStore.m b/screendisplay/Pods/UICKeyChainStore/Lib/UICKeyChainStore/UICKeyChainStore.m new file mode 100755 index 0000000..ace499b --- /dev/null +++ b/screendisplay/Pods/UICKeyChainStore/Lib/UICKeyChainStore/UICKeyChainStore.m @@ -0,0 +1,1392 @@ +// +// UICKeyChainStore.m +// UICKeyChainStore +// +// Created by Kishikawa Katsumi on 11/11/20. +// Copyright (c) 2011 Kishikawa Katsumi. All rights reserved. +// + +#import "UICKeyChainStore.h" + +NSString * const UICKeyChainStoreErrorDomain = @"com.kishikawakatsumi.uickeychainstore"; +static NSString *_defaultService; + +@interface UICKeyChainStore () + +@end + +@implementation UICKeyChainStore + ++ (NSString *)defaultService +{ + if (!_defaultService) { + _defaultService = [[NSBundle mainBundle] bundleIdentifier] ?: @""; + } + + return _defaultService; +} + ++ (void)setDefaultService:(NSString *)defaultService +{ + _defaultService = defaultService; +} + +#pragma mark - + ++ (UICKeyChainStore *)keyChainStore +{ + return [[self alloc] initWithService:nil accessGroup:nil]; +} + ++ (UICKeyChainStore *)keyChainStoreWithService:(NSString *)service +{ + return [[self alloc] initWithService:service accessGroup:nil]; +} + ++ (UICKeyChainStore *)keyChainStoreWithService:(NSString *)service accessGroup:(NSString *)accessGroup +{ + return [[self alloc] initWithService:service accessGroup:accessGroup]; +} + +#pragma mark - + ++ (UICKeyChainStore *)keyChainStoreWithServer:(NSURL *)server protocolType:(UICKeyChainStoreProtocolType)protocolType +{ + return [[self alloc] initWithServer:server protocolType:protocolType authenticationType:UICKeyChainStoreAuthenticationTypeDefault]; +} + ++ (UICKeyChainStore *)keyChainStoreWithServer:(NSURL *)server protocolType:(UICKeyChainStoreProtocolType)protocolType authenticationType:(UICKeyChainStoreAuthenticationType)authenticationType +{ + return [[self alloc] initWithServer:server protocolType:protocolType authenticationType:authenticationType]; +} + +#pragma mark - + +- (instancetype)init +{ + return [self initWithService:[self.class defaultService] accessGroup:nil]; +} + +- (instancetype)initWithService:(NSString *)service +{ + return [self initWithService:service accessGroup:nil]; +} + +- (instancetype)initWithService:(NSString *)service accessGroup:(NSString *)accessGroup +{ + self = [super init]; + if (self) { + _itemClass = UICKeyChainStoreItemClassGenericPassword; + + if (!service) { + service = [self.class defaultService]; + } + _service = service.copy; + _accessGroup = accessGroup.copy; + [self commonInit]; + } + + return self; +} + +#pragma mark - + +- (instancetype)initWithServer:(NSURL *)server protocolType:(UICKeyChainStoreProtocolType)protocolType +{ + return [self initWithServer:server protocolType:protocolType authenticationType:UICKeyChainStoreAuthenticationTypeDefault]; +} + +- (instancetype)initWithServer:(NSURL *)server protocolType:(UICKeyChainStoreProtocolType)protocolType authenticationType:(UICKeyChainStoreAuthenticationType)authenticationType +{ + self = [super init]; + if (self) { + _itemClass = UICKeyChainStoreItemClassInternetPassword; + + _server = server.copy; + _protocolType = protocolType; + _authenticationType = authenticationType; + + [self commonInit]; + } + + return self; +} + +#pragma mark - + +- (void)commonInit +{ + _accessibility = UICKeyChainStoreAccessibilityAfterFirstUnlock; +} + +#pragma mark - + ++ (NSString *)stringForKey:(NSString *)key +{ + return [self stringForKey:key service:nil accessGroup:nil error:nil]; +} + ++ (NSString *)stringForKey:(NSString *)key error:(NSError *__autoreleasing *)error +{ + return [self stringForKey:key service:nil accessGroup:nil error:error]; +} + ++ (NSString *)stringForKey:(NSString *)key service:(NSString *)service +{ + return [self stringForKey:key service:service accessGroup:nil error:nil]; +} + ++ (NSString *)stringForKey:(NSString *)key service:(NSString *)service error:(NSError *__autoreleasing *)error +{ + return [self stringForKey:key service:service accessGroup:nil error:error]; +} + ++ (NSString *)stringForKey:(NSString *)key service:(NSString *)service accessGroup:(NSString *)accessGroup +{ + return [self stringForKey:key service:service accessGroup:accessGroup error:nil]; +} + ++ (NSString *)stringForKey:(NSString *)key service:(NSString *)service accessGroup:(NSString *)accessGroup error:(NSError *__autoreleasing *)error +{ + if (!key) { + NSError *e = [self argumentError:NSLocalizedString(@"the key must not to be nil", nil)]; + if (error) { + *error = e; + } + return nil; + } + if (!service) { + service = [self defaultService]; + } + + UICKeyChainStore *keychain = [UICKeyChainStore keyChainStoreWithService:service accessGroup:accessGroup]; + return [keychain stringForKey:key error:error]; +} + +#pragma mark - + ++ (BOOL)setString:(NSString *)value forKey:(NSString *)key +{ + return [self setString:value forKey:key service:nil accessGroup:nil genericAttribute:nil error:nil]; +} + ++ (BOOL)setString:(NSString *)value forKey:(NSString *)key error:(NSError *__autoreleasing *)error +{ + return [self setString:value forKey:key service:nil accessGroup:nil genericAttribute:nil error:error]; +} + ++ (BOOL)setString:(NSString *)value forKey:(NSString *)key genericAttribute:(id)genericAttribute +{ + return [self setString:value forKey:key service:nil accessGroup:nil genericAttribute:genericAttribute error:nil]; +} + ++ (BOOL)setString:(NSString *)value forKey:(NSString *)key genericAttribute:(id)genericAttribute error:(NSError * __autoreleasing *)error +{ + return [self setString:value forKey:key service:nil accessGroup:nil genericAttribute:genericAttribute error:error]; +} + ++ (BOOL)setString:(NSString *)value forKey:(NSString *)key service:(NSString *)service +{ + return [self setString:value forKey:key service:service accessGroup:nil genericAttribute:nil error:nil]; +} + ++ (BOOL)setString:(NSString *)value forKey:(NSString *)key service:(NSString *)service error:(NSError *__autoreleasing *)error +{ + return [self setString:value forKey:key service:service accessGroup:nil genericAttribute:nil error:error]; +} + ++ (BOOL)setString:(NSString *)value forKey:(NSString *)key service:(NSString *)service genericAttribute:(id)genericAttribute +{ + return [self setString:value forKey:key service:service accessGroup:nil genericAttribute:genericAttribute error:nil]; +} + ++ (BOOL)setString:(NSString *)value forKey:(NSString *)key service:(NSString *)service genericAttribute:(id)genericAttribute error:(NSError * __autoreleasing *)error +{ + return [self setString:value forKey:key service:service accessGroup:nil genericAttribute:genericAttribute error:error]; +} + ++ (BOOL)setString:(NSString *)value forKey:(NSString *)key service:(NSString *)service accessGroup:(NSString *)accessGroup +{ + return [self setString:value forKey:key service:service accessGroup:accessGroup genericAttribute:nil error:nil]; +} + ++ (BOOL)setString:(NSString *)value forKey:(NSString *)key service:(NSString *)service accessGroup:(NSString *)accessGroup error:(NSError *__autoreleasing *)error +{ + return [self setString:value forKey:key service:service accessGroup:accessGroup genericAttribute:nil error:error]; +} + ++ (BOOL)setString:(NSString *)value forKey:(NSString *)key service:(NSString *)service accessGroup:(NSString *)accessGroup genericAttribute:(id)genericAttribute +{ + return [self setString:value forKey:key service:service accessGroup:accessGroup genericAttribute:genericAttribute error:nil]; +} + ++ (BOOL)setString:(NSString *)value forKey:(NSString *)key service:(NSString *)service accessGroup:(NSString *)accessGroup genericAttribute:(id)genericAttribute error:(NSError * __autoreleasing *)error +{ + if (!value) { + return [self removeItemForKey:key service:service accessGroup:accessGroup error:error]; + } + NSData *data = [value dataUsingEncoding:NSUTF8StringEncoding]; + if (data) { + return [self setData:data forKey:key service:service accessGroup:accessGroup genericAttribute:genericAttribute error:error]; + } + NSError *e = [self conversionError:NSLocalizedString(@"failed to convert string to data", nil)]; + if (error) { + *error = e; + } + return NO; +} + +#pragma mark - + ++ (NSData *)dataForKey:(NSString *)key +{ + return [self dataForKey:key service:nil accessGroup:nil error:nil]; +} + ++ (NSData *)dataForKey:(NSString *)key error:(NSError *__autoreleasing *)error +{ + return [self dataForKey:key service:nil accessGroup:nil error:error]; +} + ++ (NSData *)dataForKey:(NSString *)key service:(NSString *)service +{ + return [self dataForKey:key service:service accessGroup:nil error:nil]; +} + ++ (NSData *)dataForKey:(NSString *)key service:(NSString *)service error:(NSError *__autoreleasing *)error +{ + return [self dataForKey:key service:service accessGroup:nil error:error]; +} + ++ (NSData *)dataForKey:(NSString *)key service:(NSString *)service accessGroup:(NSString *)accessGroup +{ + return [self dataForKey:key service:service accessGroup:accessGroup error:nil]; +} + ++ (NSData *)dataForKey:(NSString *)key service:(NSString *)service accessGroup:(NSString *)accessGroup error:(NSError *__autoreleasing *)error +{ + if (!key) { + NSError *e = [self argumentError:NSLocalizedString(@"the key must not to be nil", nil)]; + if (error) { + *error = e; + } + return nil; + } + if (!service) { + service = [self defaultService]; + } + + UICKeyChainStore *keychain = [UICKeyChainStore keyChainStoreWithService:service accessGroup:accessGroup]; + return [keychain dataForKey:key error:error]; +} + +#pragma mark - + ++ (BOOL)setData:(NSData *)data forKey:(NSString *)key +{ + return [self setData:data forKey:key service:nil accessGroup:nil genericAttribute:nil error:nil]; +} + ++ (BOOL)setData:(NSData *)data forKey:(NSString *)key error:(NSError *__autoreleasing *)error +{ + return [self setData:data forKey:key service:nil accessGroup:nil genericAttribute:nil error:error]; +} + ++ (BOOL)setData:(NSData *)data forKey:(NSString *)key genericAttribute:(id)genericAttribute +{ + return [self setData:data forKey:key service:nil accessGroup:nil genericAttribute:genericAttribute error:nil]; +} + ++ (BOOL)setData:(NSData *)data forKey:(NSString *)key genericAttribute:(id)genericAttribute error:(NSError * __autoreleasing *)error +{ + return [self setData:data forKey:key service:nil accessGroup:nil genericAttribute:genericAttribute error:error]; +} + ++ (BOOL)setData:(NSData *)data forKey:(NSString *)key service:(NSString *)service +{ + return [self setData:data forKey:key service:service accessGroup:nil genericAttribute:nil error:nil]; +} + ++ (BOOL)setData:(NSData *)data forKey:(NSString *)key service:(NSString *)service error:(NSError *__autoreleasing *)error +{ + return [self setData:data forKey:key service:service accessGroup:nil genericAttribute:nil error:error]; +} + ++ (BOOL)setData:(NSData *)data forKey:(NSString *)key service:(NSString *)service genericAttribute:(id)genericAttribute +{ + return [self setData:data forKey:key service:service accessGroup:nil genericAttribute:genericAttribute error:nil]; +} + ++ (BOOL)setData:(NSData *)data forKey:(NSString *)key service:(NSString *)service genericAttribute:(id)genericAttribute error:(NSError * __autoreleasing *)error +{ + return [self setData:data forKey:key service:service accessGroup:nil genericAttribute:genericAttribute error:error]; +} + ++ (BOOL)setData:(NSData *)data forKey:(NSString *)key service:(NSString *)service accessGroup:(NSString *)accessGroup +{ + return [self setData:data forKey:key service:service accessGroup:accessGroup genericAttribute:nil error:nil]; +} + ++ (BOOL)setData:(NSData *)data forKey:(NSString *)key service:(NSString *)service accessGroup:(NSString *)accessGroup error:(NSError *__autoreleasing *)error +{ + return [self setData:data forKey:key service:service accessGroup:accessGroup genericAttribute:nil error:error]; +} + ++ (BOOL)setData:(NSData *)data forKey:(NSString *)key service:(NSString *)service accessGroup:(NSString *)accessGroup genericAttribute:(id)genericAttribute +{ + return [self setData:data forKey:key service:service accessGroup:accessGroup genericAttribute:genericAttribute error:nil]; +} + ++ (BOOL)setData:(NSData *)data forKey:(NSString *)key service:(NSString *)service accessGroup:(NSString *)accessGroup genericAttribute:(id)genericAttribute error:(NSError * __autoreleasing *)error +{ + if (!key) { + NSError *e = [self argumentError:NSLocalizedString(@"the key must not to be nil", nil)]; + if (error) { + *error = e; + } + return NO; + } + if (!service) { + service = [self defaultService]; + } + + UICKeyChainStore *keychain = [UICKeyChainStore keyChainStoreWithService:service accessGroup:accessGroup]; + return [keychain setData:data forKey:key genericAttribute:genericAttribute]; +} + +#pragma mark - + +- (BOOL)contains:(NSString *)key +{ + NSMutableDictionary *query = [self query]; + query[(__bridge __strong id)kSecAttrAccount] = key; + + OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, NULL); + return status == errSecSuccess; +} + +#pragma mark - + +- (NSString *)stringForKey:(id)key +{ + return [self stringForKey:key error:nil]; +} + +- (NSString *)stringForKey:(id)key error:(NSError *__autoreleasing *)error +{ + NSData *data = [self dataForKey:key error:error]; + if (data) { + NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; + if (string) { + return string; + } + NSError *e = [self.class conversionError:NSLocalizedString(@"failed to convert data to string", nil)]; + if (error) { + *error = e; + } + return nil; + } + + return nil; +} + +#pragma mark - + +- (BOOL)setString:(NSString *)string forKey:(NSString *)key +{ + return [self setString:string forKey:key genericAttribute:nil label:nil comment:nil error:nil]; +} + +- (BOOL)setString:(NSString *)string forKey:(NSString *)key error:(NSError *__autoreleasing *)error +{ + return [self setString:string forKey:key genericAttribute:nil label:nil comment:nil error:error]; +} + +- (BOOL)setString:(NSString *)string forKey:(NSString *)key genericAttribute:(id)genericAttribute +{ + return [self setString:string forKey:key genericAttribute:genericAttribute label:nil comment:nil error:nil]; +} + +- (BOOL)setString:(NSString *)string forKey:(NSString *)key genericAttribute:(id)genericAttribute error:(NSError * __autoreleasing *)error +{ + return [self setString:string forKey:key genericAttribute:genericAttribute label:nil comment:nil error:error]; +} + +- (BOOL)setString:(NSString *)string forKey:(NSString *)key label:(NSString *)label comment:(NSString *)comment +{ + return [self setString:string forKey:key genericAttribute:nil label:label comment:comment error:nil]; +} + +- (BOOL)setString:(NSString *)string forKey:(NSString *)key label:(NSString *)label comment:(NSString *)comment error:(NSError *__autoreleasing *)error +{ + return [self setString:string forKey:key genericAttribute:nil label:label comment:comment error:error]; +} + +- (BOOL)setString:(NSString *)string forKey:(NSString *)key genericAttribute:(id)genericAttribute label:(NSString *)label comment:(NSString *)comment error:(NSError *__autoreleasing *)error +{ + if (!string) { + return [self removeItemForKey:key error:error]; + } + NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding]; + if (data) { + return [self setData:data forKey:key genericAttribute:genericAttribute label:label comment:comment error:error]; + } + NSError *e = [self.class conversionError:NSLocalizedString(@"failed to convert string to data", nil)]; + if (error) { + *error = e; + } + return NO; +} + +#pragma mark - + +- (NSData *)dataForKey:(NSString *)key +{ + return [self dataForKey:key error:nil]; +} + +- (NSData *)dataForKey:(NSString *)key error:(NSError *__autoreleasing *)error +{ + NSMutableDictionary *query = [self query]; + query[(__bridge __strong id)kSecMatchLimit] = (__bridge id)kSecMatchLimitOne; + query[(__bridge __strong id)kSecReturnData] = (__bridge id)kCFBooleanTrue; + + query[(__bridge __strong id)kSecAttrAccount] = key; + + CFTypeRef data = nil; + OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &data); + + if (status == errSecSuccess) { + NSData *ret = [NSData dataWithData:(__bridge NSData *)data]; + if (data) { + CFRelease(data); + return ret; + } else { + NSError *e = [self.class unexpectedError:NSLocalizedString(@"Unexpected error has occurred.", nil)]; + if (error) { + *error = e; + } + return nil; + } + } else if (status == errSecItemNotFound) { + return nil; + } + + NSError *e = [self.class securityError:status]; + if (error) { + *error = e; + } + return nil; +} + +#pragma mark - + +- (BOOL)setData:(NSData *)data forKey:(NSString *)key +{ + return [self setData:data forKey:key genericAttribute:nil label:nil comment:nil error:nil]; +} + +- (BOOL)setData:(NSData *)data forKey:(NSString *)key error:(NSError *__autoreleasing *)error +{ + return [self setData:data forKey:key genericAttribute:nil label:nil comment:nil error:error]; +} + +- (BOOL)setData:(NSData *)data forKey:(NSString *)key genericAttribute:(id)genericAttribute +{ + return [self setData:data forKey:key genericAttribute:genericAttribute label:nil comment:nil error:nil]; +} + +- (BOOL)setData:(NSData *)data forKey:(NSString *)key genericAttribute:(id)genericAttribute error:(NSError * __autoreleasing *)error +{ + return [self setData:data forKey:key genericAttribute:genericAttribute label:nil comment:nil error:error]; +} + +- (BOOL)setData:(NSData *)data forKey:(NSString *)key label:(NSString *)label comment:(NSString *)comment +{ + return [self setData:data forKey:key genericAttribute:nil label:label comment:comment error:nil]; +} + +- (BOOL)setData:(NSData *)data forKey:(NSString *)key label:(NSString *)label comment:(NSString *)comment error:(NSError *__autoreleasing *)error +{ + return [self setData:data forKey:key genericAttribute:nil label:label comment:comment error:error]; +} + +- (BOOL)setData:(NSData *)data forKey:(NSString *)key genericAttribute:(id)genericAttribute label:(NSString *)label comment:(NSString *)comment error:(NSError *__autoreleasing *)error +{ + if (!key) { + NSError *e = [self.class argumentError:NSLocalizedString(@"the key must not to be nil", nil)]; + if (error) { + *error = e; + } + return NO; + } + if (!data) { + return [self removeItemForKey:key error:error]; + } + + NSMutableDictionary *query = [self query]; + query[(__bridge __strong id)kSecAttrAccount] = key; +#if TARGET_OS_IOS + if (floor(NSFoundationVersionNumber) > floor(1144.17)) { // iOS 9+ + query[(__bridge __strong id)kSecUseAuthenticationUI] = (__bridge id)kSecUseAuthenticationUIFail; +#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_9_0 + } else if (floor(NSFoundationVersionNumber) > floor(1047.25)) { // iOS 8+ + query[(__bridge __strong id)kSecUseNoAuthenticationUI] = (__bridge id)kCFBooleanTrue; +#endif + } +#elif TARGET_OS_WATCH || TARGET_OS_TV + query[(__bridge __strong id)kSecUseAuthenticationUI] = (__bridge id)kSecUseAuthenticationUIFail; +#endif + + OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, NULL); + if (status == errSecSuccess || status == errSecInteractionNotAllowed) { + query = [self query]; + query[(__bridge __strong id)kSecAttrAccount] = key; + + NSError *unexpectedError = nil; + NSMutableDictionary *attributes = [self attributesWithKey:nil value:data error:&unexpectedError]; + + if (genericAttribute) { + attributes[(__bridge __strong id)kSecAttrGeneric] = genericAttribute; + } + if (label) { + attributes[(__bridge __strong id)kSecAttrLabel] = label; + } + if (comment) { + attributes[(__bridge __strong id)kSecAttrComment] = comment; + } + + if (unexpectedError) { + NSLog(@"error: [%@] %@", @(unexpectedError.code), NSLocalizedString(@"Unexpected error has occurred.", nil)); + if (error) { + *error = unexpectedError; + } + return NO; + } else { + + if (status == errSecInteractionNotAllowed && floor(NSFoundationVersionNumber) <= floor(1140.11)) { // iOS 8.0.x + if ([self removeItemForKey:key error:error]) { + return [self setData:data forKey:key label:label comment:comment error:error]; + } + } else { + status = SecItemUpdate((__bridge CFDictionaryRef)query, (__bridge CFDictionaryRef)attributes); + } + if (status != errSecSuccess) { + NSError *e = [self.class securityError:status]; + if (error) { + *error = e; + } + return NO; + } + } + } else if (status == errSecItemNotFound) { + NSError *unexpectedError = nil; + NSMutableDictionary *attributes = [self attributesWithKey:key value:data error:&unexpectedError]; + + if (genericAttribute) { + attributes[(__bridge __strong id)kSecAttrGeneric] = genericAttribute; + } + if (label) { + attributes[(__bridge __strong id)kSecAttrLabel] = label; + } + if (comment) { + attributes[(__bridge __strong id)kSecAttrComment] = comment; + } + + if (unexpectedError) { + NSLog(@"error: [%@] %@", @(unexpectedError.code), NSLocalizedString(@"Unexpected error has occurred.", nil)); + if (error) { + *error = unexpectedError; + } + return NO; + } else { + status = SecItemAdd((__bridge CFDictionaryRef)attributes, NULL); + if (status != errSecSuccess) { + NSError *e = [self.class securityError:status]; + if (error) { + *error = e; + } + return NO; + } + } + } else { + NSError *e = [self.class securityError:status]; + if (error) { + *error = e; + } + return NO; + } + + return YES; +} + +#pragma mark - + ++ (BOOL)removeItemForKey:(NSString *)key +{ + return [self removeItemForKey:key service:nil accessGroup:nil error:nil]; +} + ++ (BOOL)removeItemForKey:(NSString *)key error:(NSError *__autoreleasing *)error +{ + return [self removeItemForKey:key service:nil accessGroup:nil error:error]; +} + ++ (BOOL)removeItemForKey:(NSString *)key service:(NSString *)service +{ + return [self removeItemForKey:key service:service accessGroup:nil error:nil]; +} + ++ (BOOL)removeItemForKey:(NSString *)key service:(NSString *)service error:(NSError *__autoreleasing *)error +{ + return [self removeItemForKey:key service:service accessGroup:nil error:error]; +} + ++ (BOOL)removeItemForKey:(NSString *)key service:(NSString *)service accessGroup:(NSString *)accessGroup +{ + return [self removeItemForKey:key service:service accessGroup:accessGroup error:nil]; +} + ++ (BOOL)removeItemForKey:(NSString *)key service:(NSString *)service accessGroup:(NSString *)accessGroup error:(NSError *__autoreleasing *)error +{ + if (!key) { + NSError *e = [self.class argumentError:NSLocalizedString(@"the key must not to be nil", nil)]; + if (error) { + *error = e; + } + return NO; + } + if (!service) { + service = [self defaultService]; + } + + UICKeyChainStore *keychain = [UICKeyChainStore keyChainStoreWithService:service accessGroup:accessGroup]; + return [keychain removeItemForKey:key error:error]; +} + +#pragma mark - + ++ (BOOL)removeAllItems +{ + return [self removeAllItemsForService:nil accessGroup:nil error:nil]; +} + ++ (BOOL)removeAllItemsWithError:(NSError *__autoreleasing *)error +{ + return [self removeAllItemsForService:nil accessGroup:nil error:error]; +} + ++ (BOOL)removeAllItemsForService:(NSString *)service +{ + return [self removeAllItemsForService:service accessGroup:nil error:nil]; +} + ++ (BOOL)removeAllItemsForService:(NSString *)service error:(NSError *__autoreleasing *)error +{ + return [self removeAllItemsForService:service accessGroup:nil error:error]; +} + ++ (BOOL)removeAllItemsForService:(NSString *)service accessGroup:(NSString *)accessGroup +{ + return [self removeAllItemsForService:service accessGroup:accessGroup error:nil]; +} + ++ (BOOL)removeAllItemsForService:(NSString *)service accessGroup:(NSString *)accessGroup error:(NSError *__autoreleasing *)error +{ + UICKeyChainStore *keychain = [UICKeyChainStore keyChainStoreWithService:service accessGroup:accessGroup]; + return [keychain removeAllItemsWithError:error]; +} + +#pragma mark - + +- (BOOL)removeItemForKey:(NSString *)key +{ + return [self removeItemForKey:key error:nil]; +} + +- (BOOL)removeItemForKey:(NSString *)key error:(NSError *__autoreleasing *)error +{ + NSMutableDictionary *query = [self query]; + query[(__bridge __strong id)kSecAttrAccount] = key; + + OSStatus status = SecItemDelete((__bridge CFDictionaryRef)query); + if (status != errSecSuccess && status != errSecItemNotFound) { + NSError *e = [self.class securityError:status]; + if (error) { + *error = e; + } + return NO; + } + + return YES; +} + +#pragma mark - + +- (BOOL)removeAllItems +{ + return [self removeAllItemsWithError:nil]; +} + +- (BOOL)removeAllItemsWithError:(NSError *__autoreleasing *)error +{ + NSMutableDictionary *query = [self query]; +#if !TARGET_OS_IPHONE + query[(__bridge id)kSecMatchLimit] = (__bridge id)kSecMatchLimitAll; +#endif + + OSStatus status = SecItemDelete((__bridge CFDictionaryRef)query); + if (status != errSecSuccess && status != errSecItemNotFound) { + NSError *e = [self.class securityError:status]; + if (error) { + *error = e; + } + return NO; + } + + return YES; +} + +#pragma mark - + +- (NSString *)objectForKeyedSubscript:(NSString <NSCopying> *)key +{ + return [self stringForKey:key]; +} + +- (void)setObject:(NSString *)obj forKeyedSubscript:(NSString <NSCopying> *)key +{ + if (!obj) { + [self removeItemForKey:key]; + } else { + [self setString:obj forKey:key]; + } +} + +#pragma mark - + +- (NSArray UIC_KEY_TYPE *)allKeys +{ + NSArray *items = [self.class prettify:[self itemClassObject] items:[self items]]; + NSMutableArray *keys = [[NSMutableArray alloc] init]; + for (NSDictionary *item in items) { + NSString *key = item[@"key"]; + if (key) { + [keys addObject:key]; + } + } + return keys.copy; +} + ++ (NSArray UIC_KEY_TYPE *)allKeysWithItemClass:(UICKeyChainStoreItemClass)itemClass +{ + CFTypeRef itemClassObject = kSecClassGenericPassword; + if (itemClass == UICKeyChainStoreItemClassGenericPassword) { + itemClassObject = kSecClassGenericPassword; + } else if (itemClass == UICKeyChainStoreItemClassInternetPassword) { + itemClassObject = kSecClassInternetPassword; + } + + NSMutableDictionary *query = [[NSMutableDictionary alloc] init]; + query[(__bridge __strong id)kSecClass] = (__bridge id)itemClassObject; + query[(__bridge __strong id)kSecMatchLimit] = (__bridge id)kSecMatchLimitAll; + query[(__bridge __strong id)kSecReturnAttributes] = (__bridge id)kCFBooleanTrue; + + CFArrayRef result = nil; + CFDictionaryRef cfquery = (CFDictionaryRef)CFBridgingRetain(query); + OSStatus status = SecItemCopyMatching(cfquery, (CFTypeRef *)&result); + CFRelease(cfquery); + + if (status == errSecSuccess) { + NSArray *items = [self prettify:itemClassObject items:(__bridge NSArray *)result]; + NSMutableArray *keys = [[NSMutableArray alloc] init]; + for (NSDictionary *item in items) { + if (itemClassObject == kSecClassGenericPassword) { + [keys addObject:@{@"service": item[@"service"] ?: @"", @"key": item[@"key"] ?: @""}]; + } else if (itemClassObject == kSecClassInternetPassword) { + [keys addObject:@{@"server": item[@"service"] ?: @"", @"key": item[@"key"] ?: @""}]; + } + } + return keys.copy; + } else if (status == errSecItemNotFound) { + return @[]; + } + + return nil; +} + ++ (NSArray *)allItemsWithItemClass:(UICKeyChainStoreItemClass)itemClass +{ + CFTypeRef itemClassObject = kSecClassGenericPassword; + if (itemClass == UICKeyChainStoreItemClassGenericPassword) { + itemClassObject = kSecClassGenericPassword; + } else if (itemClass == UICKeyChainStoreItemClassInternetPassword) { + itemClassObject = kSecClassInternetPassword; + } + + NSMutableDictionary *query = [[NSMutableDictionary alloc] init]; + query[(__bridge __strong id)kSecClass] = (__bridge id)itemClassObject; + query[(__bridge __strong id)kSecMatchLimit] = (__bridge id)kSecMatchLimitAll; + query[(__bridge __strong id)kSecReturnAttributes] = (__bridge id)kCFBooleanTrue; +#if TARGET_OS_IPHONE + query[(__bridge __strong id)kSecReturnData] = (__bridge id)kCFBooleanTrue; +#endif + + CFArrayRef result = nil; + CFDictionaryRef cfquery = (CFDictionaryRef)CFBridgingRetain(query); + OSStatus status = SecItemCopyMatching(cfquery, (CFTypeRef *)&result); + CFRelease(cfquery); + + if (status == errSecSuccess) { + return [self prettify:itemClassObject items:(__bridge NSArray *)result]; + } else if (status == errSecItemNotFound) { + return @[]; + } + + return nil; +} + +- (NSArray *)allItems +{ + return [self.class prettify:[self itemClassObject] items:[self items]]; +} + +- (NSArray *)items +{ + NSMutableDictionary *query = [self query]; + query[(__bridge __strong id)kSecMatchLimit] = (__bridge id)kSecMatchLimitAll; + query[(__bridge __strong id)kSecReturnAttributes] = (__bridge id)kCFBooleanTrue; +#if TARGET_OS_IPHONE + query[(__bridge __strong id)kSecReturnData] = (__bridge id)kCFBooleanTrue; +#endif + + CFArrayRef result = nil; + OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query,(CFTypeRef *)&result); + + if (status == errSecSuccess) { + return CFBridgingRelease(result); + } else if (status == errSecItemNotFound) { + return @[]; + } + + return nil; +} + ++ (NSArray *)prettify:(CFTypeRef)itemClass items:(NSArray *)items +{ + NSMutableArray *prettified = [[NSMutableArray alloc] init]; + + for (NSDictionary *attributes in items) { + NSMutableDictionary *item = [[NSMutableDictionary alloc] init]; + if (itemClass == kSecClassGenericPassword) { + item[@"class"] = @"GenericPassword"; + id service = attributes[(__bridge id)kSecAttrService]; + if (service) { + item[@"service"] = service; + } + id accessGroup = attributes[(__bridge id)kSecAttrAccessGroup]; + if (accessGroup) { + item[@"accessGroup"] = accessGroup; + } + } else if (itemClass == kSecClassInternetPassword) { + item[@"class"] = @"InternetPassword"; + id server = attributes[(__bridge id)kSecAttrServer]; + if (server) { + item[@"server"] = server; + } + id protocolType = attributes[(__bridge id)kSecAttrProtocol]; + if (protocolType) { + item[@"protocol"] = protocolType; + } + id authenticationType = attributes[(__bridge id)kSecAttrAuthenticationType]; + if (authenticationType) { + item[@"authenticationType"] = authenticationType; + } + } + id key = attributes[(__bridge id)kSecAttrAccount]; + if (key) { + item[@"key"] = key; + } + NSData *data = attributes[(__bridge id)kSecValueData]; + NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; + if (string) { + item[@"value"] = string; + } else { + item[@"value"] = data; + } + + id accessible = attributes[(__bridge id)kSecAttrAccessible]; + if (accessible) { + item[@"accessibility"] = accessible; + } + + if (floor(NSFoundationVersionNumber) > floor(993.00)) { // iOS 7+ + id synchronizable = attributes[(__bridge id)kSecAttrSynchronizable]; + if (synchronizable) { + item[@"synchronizable"] = synchronizable; + } + } + + [prettified addObject:item]; + } + + return prettified.copy; +} + +#pragma mark - + +- (void)setSynchronizable:(BOOL)synchronizable +{ + _synchronizable = synchronizable; + if (_authenticationPolicy) { + NSLog(@"%@", @"Cannot specify both an authenticationPolicy and a synchronizable"); + } +} + +- (void)setAccessibility:(UICKeyChainStoreAccessibility)accessibility authenticationPolicy:(UICKeyChainStoreAuthenticationPolicy)authenticationPolicy +{ + _accessibility = accessibility; + _authenticationPolicy = authenticationPolicy; + if (_synchronizable) { + NSLog(@"%@", @"Cannot specify both an authenticationPolicy and a synchronizable"); + } +} + +#pragma mark - + +#if TARGET_OS_IOS +- (void)sharedPasswordWithCompletion:(void (^)(NSString *account, NSString *password, NSError *error))completion +{ + NSString *domain = self.server.host; + if (domain.length > 0) { + [self.class requestSharedWebCredentialForDomain:domain account:nil completion:^(NSArray *credentials, NSError *error) { + NSDictionary *credential = credentials.firstObject; + if (credential) { + NSString *account = credential[@"account"]; + NSString *password = credential[@"password"]; + if (completion) { + completion(account, password, error); + } + } else { + if (completion) { + completion(nil, nil, error); + } + } + }]; + } else { + NSError *error = [self.class argumentError:NSLocalizedString(@"the server property must not to be nil, should use 'keyChainStoreWithServer:protocolType:' initializer to instantiate keychain store", nil)]; + if (completion) { + completion(nil, nil, error); + } + } +} + +- (void)sharedPasswordForAccount:(NSString *)account completion:(void (^)(NSString *password, NSError *error))completion +{ + NSString *domain = self.server.host; + if (domain.length > 0) { + [self.class requestSharedWebCredentialForDomain:domain account:account completion:^(NSArray *credentials, NSError *error) { + NSDictionary *credential = credentials.firstObject; + if (credential) { + NSString *password = credential[@"password"]; + if (completion) { + completion(password, error); + } + } else { + if (completion) { + completion(nil, error); + } + } + }]; + } else { + NSError *error = [self.class argumentError:NSLocalizedString(@"the server property must not to be nil, should use 'keyChainStoreWithServer:protocolType:' initializer to instantiate keychain store", nil)]; + if (completion) { + completion(nil, error); + } + } +} + +- (void)setSharedPassword:(NSString *)password forAccount:(NSString *)account completion:(void (^)(NSError *error))completion +{ + NSString *domain = self.server.host; + if (domain.length > 0) { + SecAddSharedWebCredential((__bridge CFStringRef)domain, (__bridge CFStringRef)account, (__bridge CFStringRef)password, ^(CFErrorRef error) { + if (completion) { + completion((__bridge NSError *)error); + } + }); + } else { + NSError *error = [self.class argumentError:NSLocalizedString(@"the server property must not to be nil, should use 'keyChainStoreWithServer:protocolType:' initializer to instantiate keychain store", nil)]; + if (completion) { + completion(error); + } + } +} + +- (void)removeSharedPasswordForAccount:(NSString *)account completion:(void (^)(NSError *error))completion +{ + [self setSharedPassword:nil forAccount:account completion:completion]; +} + ++ (void)requestSharedWebCredentialWithCompletion:(void (^)(NSArray UIC_CREDENTIAL_TYPE *credentials, NSError *error))completion +{ + [self requestSharedWebCredentialForDomain:nil account:nil completion:completion]; +} + ++ (void)requestSharedWebCredentialForDomain:(NSString *)domain account:(NSString *)account completion:(void (^)(NSArray UIC_CREDENTIAL_TYPE *credentials, NSError *error))completion +{ + SecRequestSharedWebCredential((__bridge CFStringRef)domain, (__bridge CFStringRef)account, ^(CFArrayRef credentials, CFErrorRef error) { + if (error) { + NSError *e = (__bridge NSError *)error; + if (e.code != errSecItemNotFound) { + NSLog(@"error: [%@] %@", @(e.code), e.localizedDescription); + } + } + + NSMutableArray *sharedCredentials = [[NSMutableArray alloc] init]; + for (NSDictionary *credential in (__bridge NSArray *)credentials) { + NSMutableDictionary *sharedCredential = [[NSMutableDictionary alloc] init]; + NSString *server = credential[(__bridge __strong id)kSecAttrServer]; + if (server) { + sharedCredential[@"server"] = server; + } + NSString *account = credential[(__bridge __strong id)kSecAttrAccount]; + if (account) { + sharedCredential[@"account"] = account; + } + NSString *password = credential[(__bridge __strong id)kSecSharedPassword]; + if (password) { + sharedCredential[@"password"] = password; + } + [sharedCredentials addObject:sharedCredential]; + } + + if (completion) { + completion(sharedCredentials.copy, (__bridge NSError *)error); + } + }); +} + ++ (NSString *)generatePassword +{ + return (NSString *)CFBridgingRelease(SecCreateSharedWebCredentialPassword()); +} + +#endif + +#pragma mark - + +- (NSString *)description +{ + NSArray *items = [self allItems]; + if (items.count == 0) { + return @"()"; + } + NSMutableString *description = [[NSMutableString alloc] initWithString:@"(\n"]; + for (NSDictionary *item in items) { + [description appendFormat:@" %@", item]; + } + [description appendString:@")"]; + return description.copy; +} + +- (NSString *)debugDescription +{ + return [NSString stringWithFormat:@"%@", [self items]]; +} + +#pragma mark - + +- (NSMutableDictionary *)query +{ + NSMutableDictionary *query = [[NSMutableDictionary alloc] init]; + + CFTypeRef itemClass = [self itemClassObject]; + query[(__bridge __strong id)kSecClass] =(__bridge id)itemClass; + if (floor(NSFoundationVersionNumber) > floor(993.00)) { // iOS 7+ (NSFoundationVersionNumber_iOS_6_1) + query[(__bridge __strong id)kSecAttrSynchronizable] = (__bridge id)kSecAttrSynchronizableAny; + } + + if (itemClass == kSecClassGenericPassword) { + query[(__bridge __strong id)(kSecAttrService)] = _service; +#if !TARGET_OS_SIMULATOR + if (_accessGroup) { + query[(__bridge __strong id)kSecAttrAccessGroup] = _accessGroup; + } +#endif + } else { + if (_server.host) { + query[(__bridge __strong id)kSecAttrServer] = _server.host; + } + if (_server.port) { + query[(__bridge __strong id)kSecAttrPort] = _server.port; + } + CFTypeRef protocolTypeObject = [self protocolTypeObject]; + if (protocolTypeObject) { + query[(__bridge __strong id)kSecAttrProtocol] = (__bridge id)protocolTypeObject; + } + CFTypeRef authenticationTypeObject = [self authenticationTypeObject]; + if (authenticationTypeObject) { + query[(__bridge __strong id)kSecAttrAuthenticationType] = (__bridge id)authenticationTypeObject; + } + } + +#if TARGET_OS_IOS + if (_authenticationPrompt) { + if (floor(NSFoundationVersionNumber) > floor(1047.25)) { // iOS 8+ (NSFoundationVersionNumber_iOS_7_1) + query[(__bridge __strong id)kSecUseOperationPrompt] = _authenticationPrompt; + } else { + NSLog(@"%@", @"Unavailable 'authenticationPrompt' attribute on iOS versions prior to 8.0."); + } + } +#endif + + return query; +} + +- (NSMutableDictionary *)attributesWithKey:(NSString *)key value:(NSData *)value error:(NSError *__autoreleasing *)error +{ + NSMutableDictionary *attributes; + + if (key) { + attributes = [self query]; + attributes[(__bridge __strong id)kSecAttrAccount] = key; + } else { + attributes = [[NSMutableDictionary alloc] init]; + } + + attributes[(__bridge __strong id)kSecValueData] = value; + +#if TARGET_OS_IOS + double iOS_7_1_or_10_9_2 = 1047.25; // NSFoundationVersionNumber_iOS_7_1 +#else + double iOS_7_1_or_10_9_2 = 1056.13; // NSFoundationVersionNumber10_9_2 +#endif + CFTypeRef accessibilityObject = [self accessibilityObject]; + if (_authenticationPolicy && accessibilityObject) { + if (floor(NSFoundationVersionNumber) > floor(iOS_7_1_or_10_9_2)) { // iOS 8+ or OS X 10.10+ + CFErrorRef securityError = NULL; + SecAccessControlRef accessControl = SecAccessControlCreateWithFlags(kCFAllocatorDefault, accessibilityObject, (SecAccessControlCreateFlags)_authenticationPolicy, &securityError); + if (securityError) { + NSError *e = (__bridge NSError *)securityError; + NSLog(@"error: [%@] %@", @(e.code), e.localizedDescription); + if (error) { + *error = e; + CFRelease(accessControl); + return nil; + } + } + if (!accessControl) { + NSString *message = NSLocalizedString(@"Unexpected error has occurred.", nil); + NSError *e = [self.class unexpectedError:message]; + if (error) { + *error = e; + } + return nil; + } + attributes[(__bridge __strong id)kSecAttrAccessControl] = (__bridge_transfer id)accessControl; + } else { +#if TARGET_OS_IOS + NSLog(@"%@", @"Unavailable 'Touch ID integration' on iOS versions prior to 8.0."); +#else + NSLog(@"%@", @"Unavailable 'Touch ID integration' on OS X versions prior to 10.10."); +#endif + } + } else { + if (floor(NSFoundationVersionNumber) <= floor(iOS_7_1_or_10_9_2) && _accessibility == UICKeyChainStoreAccessibilityWhenPasscodeSetThisDeviceOnly) { +#if TARGET_OS_IOS + NSLog(@"%@", @"Unavailable 'UICKeyChainStoreAccessibilityWhenPasscodeSetThisDeviceOnly' attribute on iOS versions prior to 8.0."); +#else + NSLog(@"%@", @"Unavailable 'UICKeyChainStoreAccessibilityWhenPasscodeSetThisDeviceOnly' attribute on OS X versions prior to 10.10."); +#endif + } else { + if (accessibilityObject) { + attributes[(__bridge __strong id)kSecAttrAccessible] = (__bridge id)accessibilityObject; + } + } + } + + if (floor(NSFoundationVersionNumber) > floor(993.00)) { // iOS 7+ + attributes[(__bridge __strong id)kSecAttrSynchronizable] = @(_synchronizable); + } + + return attributes; +} + +#pragma mark - + +- (CFTypeRef)itemClassObject +{ + switch (_itemClass) { + case UICKeyChainStoreItemClassGenericPassword: + return kSecClassGenericPassword; + case UICKeyChainStoreItemClassInternetPassword: + return kSecClassInternetPassword; + default: + return nil; + } +} + +- (CFTypeRef)protocolTypeObject +{ + switch (_protocolType) { + case UICKeyChainStoreProtocolTypeFTP: + return kSecAttrProtocolFTP; + case UICKeyChainStoreProtocolTypeFTPAccount: + return kSecAttrProtocolFTPAccount; + case UICKeyChainStoreProtocolTypeHTTP: + return kSecAttrProtocolHTTP; + case UICKeyChainStoreProtocolTypeIRC: + return kSecAttrProtocolIRC; + case UICKeyChainStoreProtocolTypeNNTP: + return kSecAttrProtocolNNTP; + case UICKeyChainStoreProtocolTypePOP3: + return kSecAttrProtocolPOP3; + case UICKeyChainStoreProtocolTypeSMTP: + return kSecAttrProtocolSMTP; + case UICKeyChainStoreProtocolTypeSOCKS: + return kSecAttrProtocolSOCKS; + case UICKeyChainStoreProtocolTypeIMAP: + return kSecAttrProtocolIMAP; + case UICKeyChainStoreProtocolTypeLDAP: + return kSecAttrProtocolLDAP; + case UICKeyChainStoreProtocolTypeAppleTalk: + return kSecAttrProtocolAppleTalk; + case UICKeyChainStoreProtocolTypeAFP: + return kSecAttrProtocolAFP; + case UICKeyChainStoreProtocolTypeTelnet: + return kSecAttrProtocolTelnet; + case UICKeyChainStoreProtocolTypeSSH: + return kSecAttrProtocolSSH; + case UICKeyChainStoreProtocolTypeFTPS: + return kSecAttrProtocolFTPS; + case UICKeyChainStoreProtocolTypeHTTPS: + return kSecAttrProtocolHTTPS; + case UICKeyChainStoreProtocolTypeHTTPProxy: + return kSecAttrProtocolHTTPProxy; + case UICKeyChainStoreProtocolTypeHTTPSProxy: + return kSecAttrProtocolHTTPSProxy; + case UICKeyChainStoreProtocolTypeFTPProxy: + return kSecAttrProtocolFTPProxy; + case UICKeyChainStoreProtocolTypeSMB: + return kSecAttrProtocolSMB; + case UICKeyChainStoreProtocolTypeRTSP: + return kSecAttrProtocolRTSP; + case UICKeyChainStoreProtocolTypeRTSPProxy: + return kSecAttrProtocolRTSPProxy; + case UICKeyChainStoreProtocolTypeDAAP: + return kSecAttrProtocolDAAP; + case UICKeyChainStoreProtocolTypeEPPC: + return kSecAttrProtocolEPPC; + case UICKeyChainStoreProtocolTypeNNTPS: + return kSecAttrProtocolNNTPS; + case UICKeyChainStoreProtocolTypeLDAPS: + return kSecAttrProtocolLDAPS; + case UICKeyChainStoreProtocolTypeTelnetS: + return kSecAttrProtocolTelnetS; + case UICKeyChainStoreProtocolTypeIRCS: + return kSecAttrProtocolIRCS; + case UICKeyChainStoreProtocolTypePOP3S: + return kSecAttrProtocolPOP3S; + default: + return nil; + } +} + +- (CFTypeRef)authenticationTypeObject +{ + switch (_authenticationType) { + case UICKeyChainStoreAuthenticationTypeNTLM: + return kSecAttrAuthenticationTypeNTLM; + case UICKeyChainStoreAuthenticationTypeMSN: + return kSecAttrAuthenticationTypeMSN; + case UICKeyChainStoreAuthenticationTypeDPA: + return kSecAttrAuthenticationTypeDPA; + case UICKeyChainStoreAuthenticationTypeRPA: + return kSecAttrAuthenticationTypeRPA; + case UICKeyChainStoreAuthenticationTypeHTTPBasic: + return kSecAttrAuthenticationTypeHTTPBasic; + case UICKeyChainStoreAuthenticationTypeHTTPDigest: + return kSecAttrAuthenticationTypeHTTPDigest; + case UICKeyChainStoreAuthenticationTypeHTMLForm: + return kSecAttrAuthenticationTypeHTMLForm; + case UICKeyChainStoreAuthenticationTypeDefault: + return kSecAttrAuthenticationTypeDefault; + default: + return nil; + } +} + +- (CFTypeRef)accessibilityObject +{ + switch (_accessibility) { + case UICKeyChainStoreAccessibilityWhenUnlocked: + return kSecAttrAccessibleWhenUnlocked; + case UICKeyChainStoreAccessibilityAfterFirstUnlock: + return kSecAttrAccessibleAfterFirstUnlock; + case UICKeyChainStoreAccessibilityAlways: + return kSecAttrAccessibleAlways; + case UICKeyChainStoreAccessibilityWhenPasscodeSetThisDeviceOnly: + return kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly; + case UICKeyChainStoreAccessibilityWhenUnlockedThisDeviceOnly: + return kSecAttrAccessibleWhenUnlockedThisDeviceOnly; + case UICKeyChainStoreAccessibilityAfterFirstUnlockThisDeviceOnly: + return kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly; + case UICKeyChainStoreAccessibilityAlwaysThisDeviceOnly: + return kSecAttrAccessibleAlwaysThisDeviceOnly; + default: + return nil; + } +} + ++ (NSError *)argumentError:(NSString *)message +{ + NSError *error = [NSError errorWithDomain:UICKeyChainStoreErrorDomain code:UICKeyChainStoreErrorInvalidArguments userInfo:@{NSLocalizedDescriptionKey: message}]; + NSLog(@"error: [%@] %@", @(error.code), error.localizedDescription); + return error; +} + ++ (NSError *)conversionError:(NSString *)message +{ + NSError *error = [NSError errorWithDomain:UICKeyChainStoreErrorDomain code:-67594 userInfo:@{NSLocalizedDescriptionKey: message}]; + NSLog(@"error: [%@] %@", @(error.code), error.localizedDescription); + return error; +} + ++ (NSError *)securityError:(OSStatus)status +{ + NSString *message = @"Security error has occurred."; +#if TARGET_OS_MAC && !TARGET_OS_IPHONE + CFStringRef description = SecCopyErrorMessageString(status, NULL); + if (description) { + message = (__bridge_transfer NSString *)description; + } +#endif + NSError *error = [NSError errorWithDomain:UICKeyChainStoreErrorDomain code:status userInfo:@{NSLocalizedDescriptionKey: message}]; + NSLog(@"OSStatus error: [%@] %@", @(error.code), error.localizedDescription); + return error; +} + ++ (NSError *)unexpectedError:(NSString *)message +{ + NSError *error = [NSError errorWithDomain:UICKeyChainStoreErrorDomain code:-99999 userInfo:@{NSLocalizedDescriptionKey: message}]; + NSLog(@"error: [%@] %@", @(error.code), error.localizedDescription); + return error; +} + +@end + +@implementation UICKeyChainStore (Deprecation) + +- (void)synchronize +{ + // Deprecated, calling this method is no longer required +} + +- (BOOL)synchronizeWithError:(NSError *__autoreleasing *)error +{ + // Deprecated, calling this method is no longer required + return true; +} + +@end -- Gitblit v1.8.0