Permalink
Browse files

Integrated jklundell's NSDate support, and added unit tests for same

  • Loading branch information...
1 parent e4cb51e commit d2b449c14e16dff336aa8a994e0102660facb5a8 @granoff committed Jan 26, 2013
Showing with 72 additions and 41 deletions.
  1. +23 −0 LockBox/UnitTests/LockboxTests.m
  2. +4 −0 Lockbox.h
  3. +43 −39 Lockbox.m
  4. +2 −2 Lockbox.podspec
@@ -14,13 +14,15 @@ @implementation LockboxTests
NSString *testString;
NSArray *testArray;
NSSet *testSet;
+ NSDate *testDate;
}
-(void)setUp
{
testString = @"TestString";
testArray = @[ @"A", @"B", @"C" ];
testSet = [NSSet setWithArray:testArray];
+ testDate = [NSDate date];
}
-(void)tearDown
@@ -73,4 +75,25 @@ -(void)testSetSameKeyWithTwoValues
STAssertTrue([Lockbox setString:@"2" forKey:@"test"], @"Set '2' for key 'test'");
STAssertTrue([[Lockbox stringForKey:@"test"] isEqualToString:@"2"], @"Retrieve '2' for key 'test'");
}
+
+-(void)testSetDateForKey
+{
+ NSString *key = @"TestDateKey";
+ STAssertTrue([Lockbox setDate:testDate forKey:key], @"Should be able to store a date");
+ NSDate *date = [Lockbox dateForKey:key];
+ STAssertEqualObjects(date, testDate, @"Retrieved date should match original");
+}
+
+-(void)testSetNoDateForKey
+{
+ NSString *key = @"TestDateKey";
+ STAssertTrue([Lockbox setDate:nil forKey:key], @"Should be able to remove a stored date");
+}
+
+-(void)testRetrieveDateForNoKey
+{
+ NSString *key =@"NonexistentDateKey";
+ STAssertNil([Lockbox dateForKey:key], @"Should return nil (date) for nonexistent key");
+}
+
@end
View
@@ -19,4 +19,8 @@
+(BOOL)setSet:(NSSet *)value forKey:(NSString *)key accessibility:(CFTypeRef)accessibility;
+(NSSet *)setForKey:(NSString *)key;
++(BOOL)setDate:(NSDate *)value forKey:(NSString *)key;
++(BOOL)setDate:(NSDate *)value forKey:(NSString *)key accessibility:(CFTypeRef)accessibility;
++(NSDate *)dateForKey:(NSString *)key;
+
@end
View
@@ -8,13 +8,15 @@
#import "Lockbox.h"
#import <Security/Security.h>
-#define kDelimeter @"-|-"
+#define kDelimiter @"-|-"
#define DEFAULT_ACCESSIBILITY kSecAttrAccessibleWhenUnlocked
#if __has_feature(objc_arc)
-#define ID __bridge id
+#define LOCKBOX_ID __bridge id
+#define LOCKBOX_DICTREF _bridge CFDictionaryRef
#else
-#define ID id
+#define LOCKBOX_ID id
+#define LOCKBOX_DICTREF CFDictionaryRef
#endif
static NSString *_bundleId = nil;
@@ -30,7 +32,7 @@ +(NSMutableDictionary *)_service
{
NSMutableDictionary* dict = [NSMutableDictionary dictionary];
- [dict setObject: (ID) kSecClassGenericPassword forKey: (ID) kSecClass];
+ [dict setObject: (LOCKBOX_ID) kSecClassGenericPassword forKey: (LOCKBOX_ID) kSecClass];
return dict;
}
@@ -39,8 +41,8 @@ +(NSMutableDictionary *)_query
{
NSMutableDictionary* query = [NSMutableDictionary dictionary];
- [query setObject: (ID) kSecClassGenericPassword forKey: (ID) kSecClass];
- [query setObject: (ID) kCFBooleanTrue forKey: (ID) kSecReturnData];
+ [query setObject: (LOCKBOX_ID) kSecClassGenericPassword forKey: (LOCKBOX_ID) kSecClass];
+ [query setObject: (LOCKBOX_ID) kCFBooleanTrue forKey: (LOCKBOX_ID) kSecReturnData];
return query;
}
@@ -61,39 +63,23 @@ +(BOOL)setObject:(NSString *)obj forKey:(NSString *)key accessibility:(CFTypeRef
// If the object is nil, delete the item
if (!obj) {
NSMutableDictionary *query = [self _query];
- [query setObject:hierKey forKey:(ID)kSecAttrService];
-#if __has_feature(objc_arc)
- status = SecItemDelete((__bridge CFDictionaryRef)query);
-#else
- status = SecItemDelete((CFDictionaryRef)query);
-#endif
+ [query setObject:hierKey forKey:(LOCKBOX_ID)kSecAttrService];
+ status = SecItemDelete((LOCKBOX_DICTREF)query);
return (status == errSecSuccess);
}
NSMutableDictionary *dict = [self _service];
- [dict setObject: hierKey forKey: (ID) kSecAttrService];
- [dict setObject: accessibility forKey: (ID) kSecAttrAccessible];
- [dict setObject: [obj dataUsingEncoding:NSUTF8StringEncoding] forKey: (ID) kSecValueData];
+ [dict setObject: hierKey forKey: (LOCKBOX_ID) kSecAttrService];
+ [dict setObject: accessibility forKey: (LOCKBOX_ID) kSecAttrAccessible];
+ [dict setObject: [obj dataUsingEncoding:NSUTF8StringEncoding] forKey: (LOCKBOX_ID) kSecValueData];
-#if __has_feature(objc_arc)
- status = SecItemAdd ((__bridge CFDictionaryRef) dict, NULL);
-#else
- status = SecItemAdd ((CFDictionaryRef) dict, NULL);
-#endif
+ status = SecItemAdd ((LOCKBOX_DICTREF) dict, NULL);
if (status == errSecDuplicateItem) {
NSMutableDictionary *query = [self _query];
- [query setObject:hierKey forKey:(ID)kSecAttrService];
-#if __has_feature(objc_arc)
- status = SecItemDelete((__bridge CFDictionaryRef)query);
-#else
- status = SecItemDelete((CFDictionaryRef) query);
-#endif
+ [query setObject:hierKey forKey:(LOCKBOX_ID)kSecAttrService];
+ status = SecItemDelete((LOCKBOX_DICTREF)query);
if (status == errSecSuccess)
-#if __has_feature(objc_arc)
- status = SecItemAdd((__bridge CFDictionaryRef) dict, NULL);
-#else
- status = SecItemAdd((CFDictionaryRef) dict, NULL);
-#endif
+ status = SecItemAdd((LOCKBOX_DICTREF) dict, NULL);
}
if (status != errSecSuccess)
NSLog(@"SecItemAdd failed for key %@: %ld", hierKey, status);
@@ -106,15 +92,11 @@ +(NSString *)objectForKey:(NSString *)key
NSString *hierKey = [self _hierarchicalKey:key];
NSMutableDictionary *query = [self _query];
- [query setObject:hierKey forKey: (ID)kSecAttrService];
+ [query setObject:hierKey forKey: (LOCKBOX_ID)kSecAttrService];
CFDataRef data = nil;
OSStatus status =
-#if __has_feature(objc_arc)
- SecItemCopyMatching ( (__bridge CFDictionaryRef) query, (CFTypeRef *) &data );
-#else
- SecItemCopyMatching((CFDictionaryRef) query, (CFTypeRef *)&data);
-#endif
+ SecItemCopyMatching ( (LOCKBOX_DICTREF) query, (CFTypeRef *) &data );
if (status != errSecSuccess)
NSLog(@"SecItemCopyMatching failed for key %@: %ld", hierKey, status);
@@ -160,7 +142,7 @@ +(BOOL)setArray:(NSArray *)value forKey:(NSString *)key
+(BOOL)setArray:(NSArray *)value forKey:(NSString *)key accessibility:(CFTypeRef)accessibility
{
- NSString *components = [value componentsJoinedByString:kDelimeter];
+ NSString *components = [value componentsJoinedByString:kDelimiter];
return [self setObject:components forKey:key accessibility:accessibility];
}
@@ -169,7 +151,7 @@ +(NSArray *)arrayForKey:(NSString *)key
NSArray *array = nil;
NSString *components = [self objectForKey:key];
if (components)
- array = [NSArray arrayWithArray:[components componentsSeparatedByString:kDelimeter]];
+ array = [NSArray arrayWithArray:[components componentsSeparatedByString:kDelimiter]];
return array;
}
@@ -194,4 +176,26 @@ +(NSSet *)setForKey:(NSString *)key
return set;
}
+
++(BOOL)setDate:(NSDate *)value forKey:(NSString *)key
+{
+ return [self setDate:value forKey:key accessibility:DEFAULT_ACCESSIBILITY];
+}
+
++(BOOL)setDate:(NSDate *)value forKey:(NSString *)key accessibility:(CFTypeRef)accessibility
+{
+ if (!value)
+ return [self setObject:nil forKey:key accessibility:accessibility];
+ NSNumber *rti = [NSNumber numberWithDouble:[value timeIntervalSinceReferenceDate]];
+ return [self setObject:[rti stringValue] forKey:key accessibility:accessibility];
+}
+
++(NSDate *)dateForKey:(NSString *)key
+{
+ NSString *dateString = [self objectForKey:key];
+ if (dateString)
+ return [NSDate dateWithTimeIntervalSinceReferenceDate:[dateString doubleValue]];
+ return nil;
+}
+
@end
View
@@ -1,12 +1,12 @@
Pod::Spec.new do |s|
s.name = 'Lockbox'
- s.version = '1.4.0'
+ s.version = '1.4.1'
s.license = 'MIT'
s.summary = 'Lockbox is an Objective-C utility class for storing data securely in the keychain. Use it to store small, sensitive bits of data securely.'
s.homepage = 'https://github.com/granoff/Lockbox'
s.author = 'Mark H. Granoff'
- s.source = { :git => 'https://github.com/granoff/Lockbox.git', :tag => '1.4.0' }
+ s.source = { :git => 'https://github.com/granoff/Lockbox.git', :tag => '1.4.1' }
s.source_files = 'Lockbox.{h,m}'
s.clean_path = 'LockBox'

0 comments on commit d2b449c

Please sign in to comment.