Skip to content

Commit

Permalink
Merge 0179bb0 into 39ab3d3
Browse files Browse the repository at this point in the history
  • Loading branch information
kishikawakatsumi committed Jan 12, 2015
2 parents 39ab3d3 + 0179bb0 commit 55ec2ac
Show file tree
Hide file tree
Showing 4 changed files with 184 additions and 17 deletions.
10 changes: 7 additions & 3 deletions Lib/UICKeyChainStore/UICKeyChainStore.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@ typedef NS_ENUM(NSInteger, UICKeyChainStoreAccessibility) {
UICKeyChainStoreAccessibilityWhenUnlockedThisDeviceOnly,
UICKeyChainStoreAccessibilityAfterFirstUnlockThisDeviceOnly,
UICKeyChainStoreAccessibilityAlwaysThisDeviceOnly,
};
}
__OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_4_0);

typedef NS_ENUM(NSInteger, UICKeyChainStoreAuthenticationPolicy) {
UICKeyChainStoreAuthenticationPolicyUserPresence = kSecAccessControlUserPresence,
Expand All @@ -97,6 +98,9 @@ __OSX_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_8_0);
@property (nonatomic) NSString *authenticationPrompt
__OSX_AVAILABLE_STARTING(__MAC_NA, __IPHONE_8_0);

@property (nonatomic, readonly) NSArray *allKeys;
@property (nonatomic, readonly) NSArray *allItems;

+ (NSString *)defaultService;
+ (void)setDefaultService:(NSString *)defaultService;

Expand Down Expand Up @@ -177,10 +181,10 @@ __OSX_AVAILABLE_STARTING(__MAC_NA, __IPHONE_8_0);
- (NSString *)objectForKeyedSubscript:(NSString <NSCopying> *)key;
- (void)setObject:(NSString *)obj forKeyedSubscript:(NSString <NSCopying> *)key;

+ (NSArray *)allKeysWithItemClass:(CFTypeRef)itemClass;
+ (NSArray *)allKeysWithItemClass:(UICKeyChainStoreItemClass)itemClass;
- (NSArray *)allKeys;

+ (NSArray *)allItemsWithItemClass:(CFTypeRef)itemClass;
+ (NSArray *)allItemsWithItemClass:(UICKeyChainStoreItemClass)itemClass;
- (NSArray *)allItems;

- (void)setAccessibility:(UICKeyChainStoreAccessibility)accessibility authenticationPolicy:(UICKeyChainStoreAuthenticationPolicy)authenticationPolicy
Expand Down
46 changes: 33 additions & 13 deletions Lib/UICKeyChainStore/UICKeyChainStore.m
Original file line number Diff line number Diff line change
Expand Up @@ -643,51 +643,71 @@ - (void)setObject:(NSString *)obj forKeyedSubscript:(NSString <NSCopying> *)key

- (NSArray *)allKeys
{
return [self.class allKeysWithItemClass:[self itemClassObject]];
NSArray *items = [self.class prettify:[self itemClassObject] items:[self items]];
NSMutableArray *keys = [[NSMutableArray alloc] init];
for (NSDictionary *item in items) {
[keys addObject:item[@"key"]];
}
return keys.copy;
}

+ (NSArray *)allKeysWithItemClass:(CFTypeRef)itemClass
+ (NSArray *)allKeysWithItemClass:(UICKeyChainStoreItemClass)itemClass
{
CFTypeRef itemClassObject;
if (itemClass == UICKeyChainStoreItemClassGenericPassword) {
itemClassObject = kSecClassGenericPassword;
} else if (itemClass == UICKeyChainStoreItemClassInternetPassword) {
itemClassObject = kSecClassInternetPassword;
}

NSMutableDictionary *query = [[NSMutableDictionary alloc] init];
query[(__bridge __strong id)kSecClass] = (__bridge id)itemClass;
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;
OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query,(CFTypeRef *)&result);

if (status == errSecSuccess) {
NSArray *items = [self prettify:itemClass items:(__bridge NSArray *)result];
NSArray *items = [self prettify:itemClassObject items:(__bridge NSArray *)result];
NSMutableArray *keys = [[NSMutableArray alloc] init];
for (NSDictionary *item in items) {
if (itemClass == kSecClassGenericPassword) {
if (itemClassObject == kSecClassGenericPassword) {
[keys addObject:@{@"service": item[@"service"] ?: @"", @"key": item[@"key"] ?: @""}];
} else if (itemClass == kSecClassInternetPassword) {
} else if (itemClassObject == kSecClassInternetPassword) {
[keys addObject:@{@"server": item[@"service"] ?: @"", @"key": item[@"key"] ?: @""}];
}
}
return keys.copy;
} else if (status == errSecItemNotFound) {
return @[];
}

return nil;
}

+ (NSArray *)allItemsWithItemClass:(CFTypeRef)itemClass
+ (NSArray *)allItemsWithItemClass:(UICKeyChainStoreItemClass)itemClass
{
CFTypeRef itemClassObject;
if (itemClass == UICKeyChainStoreItemClassGenericPassword) {
itemClassObject = kSecClassGenericPassword;
} else if (itemClass == UICKeyChainStoreItemClassInternetPassword) {
itemClassObject = kSecClassInternetPassword;
}

NSMutableDictionary *query = [[NSMutableDictionary alloc] init];
query[(__bridge __strong id)kSecClass] = (__bridge id)itemClass;
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
#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 [self prettify:itemClass items:(__bridge NSArray *)result];
return [self prettify:itemClassObject items:(__bridge NSArray *)result];
} else if (status == errSecItemNotFound) {
return @[];
}
Expand All @@ -697,15 +717,15 @@ + (NSArray *)allItemsWithItemClass:(CFTypeRef)itemClass

- (NSArray *)allItems
{
return [self.class allItemsWithItemClass:[self itemClassObject]];
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
#if TARGET_OS_IPHONE
query[(__bridge __strong id)kSecReturnData] = (__bridge id)kCFBooleanTrue;
#endif

Expand Down Expand Up @@ -734,7 +754,7 @@ + (NSArray *)prettify:(CFTypeRef)itemClass items:(NSArray *)items
item[@"service"] = service;
}
id accessGroup = attributes[(__bridge id)kSecAttrAccessGroup];
if (service) {
if (accessGroup) {
item[@"accessGroup"] = accessGroup;
}
} else if (itemClass == kSecClassInternetPassword) {
Expand Down
143 changes: 143 additions & 0 deletions Lib/UICKeyChainStoreTests/UICKeyChainStoreTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -987,6 +987,147 @@ - (void)testInstanceMethodsSetAndRemoveWithNilValue
XCTAssertNil(username);
}

#pragma mark -

- (void)testGetAllKeys {
UICKeyChainStore *store = [UICKeyChainStore keyChainStoreWithService:@"github.com"];
[store removeAllItems];

[store setString:@"01234567-89ab-cdef-0123-456789abcdef" forKey:@"kishikawakatsumi"];
[store setString:@"00000000-89ab-cdef-0000-456789abcdef" forKey:@"hirohamada"];
[store setString:@"11111111-89ab-cdef-1111-456789abcdef" forKey:@"honeylemon"];

NSArray *allKeys = store.allKeys;
XCTAssertTrue([allKeys containsObject:@"kishikawakatsumi"]);
XCTAssertTrue([allKeys containsObject:@"hirohamada"]);
XCTAssertTrue([allKeys containsObject:@"honeylemon"]);

XCTAssertEqual(allKeys.count, 3);

[store removeAllItems];
}

- (void)testGetAllItems {
UICKeyChainStore *store = [UICKeyChainStore keyChainStoreWithService:@"github.com"];
[store removeAllItems];

[store setString:@"01234567-89ab-cdef-0123-456789abcdef" forKey:@"kishikawakatsumi"];
[store setString:@"00000000-89ab-cdef-0000-456789abcdef" forKey:@"hirohamada"];
[store setString:@"11111111-89ab-cdef-1111-456789abcdef" forKey:@"honeylemon"];

NSArray *allItems = store.allItems;
for (NSDictionary *item in allItems) {
if ([item[@"key"] isEqualToString:@"kishikawakatsumi"]) {
#if TARGET_OS_IPHONE
XCTAssertEqualObjects(item[@"value"], @"01234567-89ab-cdef-0123-456789abcdef");
#else
XCTAssertEqualObjects(item[@"value"], @"");
#endif
XCTAssertEqualObjects(item[@"service"], @"github.com");
#if TARGET_OS_IPHONE
XCTAssertEqualObjects(item[@"accessibility"], (__bridge id)kSecAttrAccessibleAfterFirstUnlock);
#endif
}
if ([item[@"key"] isEqualToString:@"hirohamada"]) {
#if TARGET_OS_IPHONE
XCTAssertEqualObjects(item[@"value"], @"00000000-89ab-cdef-0000-456789abcdef");
#else
XCTAssertEqualObjects(item[@"value"], @"");
#endif
XCTAssertEqualObjects(item[@"service"], @"github.com");
#if TARGET_OS_IPHONE
XCTAssertEqualObjects(item[@"accessibility"], (__bridge id)kSecAttrAccessibleAfterFirstUnlock);
#endif
}
if ([item[@"key"] isEqualToString:@"honeylemon"]) {
#if TARGET_OS_IPHONE
XCTAssertEqualObjects(item[@"value"], @"11111111-89ab-cdef-1111-456789abcdef");
#else
XCTAssertEqualObjects(item[@"value"], @"");
#endif
XCTAssertEqualObjects(item[@"service"], @"github.com");
#if TARGET_OS_IPHONE
XCTAssertEqualObjects(item[@"accessibility"], (__bridge id)kSecAttrAccessibleAfterFirstUnlock);
#endif
}
}

XCTAssertEqual(allItems.count, 3);

[store removeAllItems];
}

- (void)testGetAllKeysClassMethod {
[UICKeyChainStore removeAllItemsForService:@"github.com"];

[UICKeyChainStore setString:@"01234567-89ab-cdef-0123-456789abcdef" forKey:@"kishikawakatsumi" service:@"github.com"];
[UICKeyChainStore setString:@"00000000-89ab-cdef-0000-456789abcdef" forKey:@"hirohamada" service:@"github.com"];
[UICKeyChainStore setString:@"11111111-89ab-cdef-1111-456789abcdef" forKey:@"honeylemon" service:@"github.com"];

NSArray *allKeysAndServices = [UICKeyChainStore allKeysWithItemClass:UICKeyChainStoreItemClassGenericPassword];
NSMutableArray *keys = [[NSMutableArray alloc] init];
for (NSDictionary *keyAndService in allKeysAndServices) {
if ([keyAndService[@"service"] isEqualToString:@"github.com"]) {
[keys addObject:keyAndService[@"key"]];
}
}

XCTAssertTrue([keys containsObject:@"kishikawakatsumi"]);
XCTAssertTrue([keys containsObject:@"hirohamada"]);
XCTAssertTrue([keys containsObject:@"honeylemon"]);

[UICKeyChainStore removeAllItemsForService:@"github.com"];
}

- (void)testGetAllItemsClassMethod {
[UICKeyChainStore removeAllItemsForService:@"github.com"];

[UICKeyChainStore setString:@"01234567-89ab-cdef-0123-456789abcdef" forKey:@"kishikawakatsumi" service:@"github.com"];
[UICKeyChainStore setString:@"00000000-89ab-cdef-0000-456789abcdef" forKey:@"hirohamada" service:@"github.com"];
[UICKeyChainStore setString:@"11111111-89ab-cdef-1111-456789abcdef" forKey:@"honeylemon" service:@"github.com"];

NSArray *allItems = [UICKeyChainStore allItemsWithItemClass:UICKeyChainStoreItemClassGenericPassword];
for (NSDictionary *item in allItems) {
if ([item[@"key"] isEqualToString:@"kishikawakatsumi"]) {
#if TARGET_OS_IPHONE
XCTAssertEqualObjects(item[@"value"], @"01234567-89ab-cdef-0123-456789abcdef");
#else
XCTAssertEqualObjects(item[@"value"], @"");
#endif
XCTAssertEqualObjects(item[@"service"], @"github.com");
#if TARGET_OS_IPHONE
XCTAssertEqualObjects(item[@"accessibility"], (__bridge id)kSecAttrAccessibleAfterFirstUnlock);
#endif
}
if ([item[@"key"] isEqualToString:@"hirohamada"]) {
#if TARGET_OS_IPHONE
XCTAssertEqualObjects(item[@"value"], @"00000000-89ab-cdef-0000-456789abcdef");
#else
XCTAssertEqualObjects(item[@"value"], @"");
#endif
XCTAssertEqualObjects(item[@"service"], @"github.com");
#if TARGET_OS_IPHONE
XCTAssertEqualObjects(item[@"accessibility"], (__bridge id)kSecAttrAccessibleAfterFirstUnlock);
#endif
}
if ([item[@"key"] isEqualToString:@"honeylemon"]) {
#if TARGET_OS_IPHONE
XCTAssertEqualObjects(item[@"value"], @"11111111-89ab-cdef-1111-456789abcdef");
#else
XCTAssertEqualObjects(item[@"value"], @"");
#endif
XCTAssertEqualObjects(item[@"service"], @"github.com");
#if TARGET_OS_IPHONE
XCTAssertEqualObjects(item[@"accessibility"], (__bridge id)kSecAttrAccessibleAfterFirstUnlock);
#endif
}
}

[UICKeyChainStore removeAllItemsForService:@"github.com"];
}

#pragma mark -

- (void)testSetLabelAndComment
{
UICKeyChainStore *store = [UICKeyChainStore keyChainStoreWithService:@"Twitter"];
Expand All @@ -1002,6 +1143,8 @@ - (void)testSetLabelAndComment
XCTAssertNil(username);
}

#pragma mark -

- (void)testProtocolTypeAndAuthenticationTypePrivateMethod
{
NSURL *URL = [NSURL URLWithString:@"https://kishikawakatsumi.com"];
Expand Down
2 changes: 1 addition & 1 deletion UICKeyChainStore.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Pod::Spec.new do |s|
s.source = { :git => "https://github.com/kishikawakatsumi/UICKeyChainStore.git", :tag => "v#{s.version}" }

s.ios.deployment_target = "4.3"
s.osx.deployment_target = "10.6"
s.osx.deployment_target = "10.7"
s.requires_arc = true

s.source_files = "Lib/UICKeyChainStore/*.{h,m}"
Expand Down

0 comments on commit 55ec2ac

Please sign in to comment.