Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added optional NSError parameters to set, get and remove for debugging #38

Closed
wants to merge 7 commits into from
Closed
8 changes: 4 additions & 4 deletions FXKeychain.podspec.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
{
"name": "FXKeychain",
"version": "1.5.3",
"version": "1.5.4",
"license": "zlib",
"summary": "FXKeychain is a lightweight wrapper around the Apple keychain APIs that provides a simple dictionary-like interface.",
"homepage": "https://github.com/nicklockwood/FXKeychain",
"authors": "Nick Lockwood",
"social_media_url": "https://twitter.com/nicklockwood",
"source": {
"git": "https://github.com/nicklockwood/FXKeychain.git",
"tag": "1.5.3"
"git": "https://github.com/julioacarrettoni/FXKeychain.git",
"tag": "1.5.4"
},
"source_files": "FXKeychain/FXKeychain.{h,m}",
"requires_arc": true,
Expand All @@ -17,4 +17,4 @@
"osx": "10.6"
},
"frameworks": "Security"
}
}
4 changes: 4 additions & 0 deletions FXKeychain/FXKeychain.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ typedef NS_ENUM(NSInteger, FXKeychainAccess)
FXKeychainAccessibleAlwaysThisDeviceOnly
};

extern NSString * _Nonnull const kFXKeychainErrorDomain;

@interface FXKeychain : NSObject

Expand All @@ -76,9 +77,12 @@ typedef NS_ENUM(NSInteger, FXKeychainAccess)
accessGroup:(nullable NSString *)accessGroup;

- (BOOL)setObject:(nullable id)object forKey:(nonnull id)key;
- (BOOL)setObject:(nullable id)object forKey:(nonnull id)key error:(NSError * _Nullable * _Nullable) error NS_SWIFT_NAME(verboseSet(object:key:));
- (BOOL)setObject:(nullable id)object forKeyedSubscript:(nonnull id)key;
- (BOOL)removeObjectForKey:(nonnull id)key;
- (BOOL)removeObjectForKey:(nonnull id)key error:(NSError * _Nullable * _Nullable) error NS_SWIFT_NAME(verboseRemove(key:));
- (nullable id)objectForKey:(nonnull id)key;
- (nullable id)objectForKey:(nonnull id)key error:(NSError * _Nullable * _Nullable) error NS_SWIFT_NAME(verboseObject(key:));
- (nullable id)objectForKeyedSubscript:(nonnull id)key;

@end
Expand Down
48 changes: 37 additions & 11 deletions FXKeychain/FXKeychain.m
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#error This class requires automatic reference counting
#endif

NSString * const kFXKeychainErrorDomain = @"FXKeychainErrorDomain";

@implementation NSObject (FXKeychainPropertyListCoding)

Expand Down Expand Up @@ -137,7 +138,7 @@ - (id)initWithService:(NSString *)service
return self;
}

- (NSData *)dataForKey:(id)key
- (NSData *)dataForKey:(id)key error:(NSError **)error
{
//generate query
NSMutableDictionary *query = [NSMutableDictionary dictionary];
Expand All @@ -159,11 +160,20 @@ - (NSData *)dataForKey:(id)key
if (status != errSecSuccess && status != errSecItemNotFound)
{
NSLog(@"FXKeychain failed to retrieve data for key '%@', error: %ld", key, (long)status);
if (error != NULL)
{
*error = [NSError errorWithDomain:kFXKeychainErrorDomain code:status userInfo:nil];
}
}
return CFBridgingRelease(data);
}

- (BOOL)setObject:(id)object forKey:(id)key
{
return [self setObject:object forKey:key error:nil];
}

- (BOOL)setObject:(id)object forKey:(id)key error:(NSError **)error
{
//generate query
NSMutableDictionary *query = [NSMutableDictionary dictionary];
Expand All @@ -179,15 +189,14 @@ - (BOOL)setObject:(id)object forKey:(id)key

//encode object
NSData *data = nil;
NSError *error = nil;
if ([(id)object isKindOfClass:[NSString class]])
{
//check that string data does not represent a binary plist
NSPropertyListFormat format = NSPropertyListBinaryFormat_v1_0;
if (![object hasPrefix:@"bplist"] || ![NSPropertyListSerialization propertyListWithData:[object dataUsingEncoding:NSUTF8StringEncoding]
options:NSPropertyListImmutable
format:&format
error:NULL])
error:error])
{
//safe to encode as a string
data = [object dataUsingEncoding:NSUTF8StringEncoding];
Expand All @@ -200,7 +209,7 @@ - (BOOL)setObject:(id)object forKey:(id)key
data = [NSPropertyListSerialization dataWithPropertyList:[object FXKeychain_propertyListRepresentation]
format:NSPropertyListBinaryFormat_v1_0
options:0
error:&error];
error:error];
#if FXKEYCHAIN_USE_NSCODING

//property list encoding failed. try NSCoding
Expand All @@ -214,7 +223,7 @@ - (BOOL)setObject:(id)object forKey:(id)key
}

//fail if object is invalid
NSAssert(!object || (object && data), @"FXKeychain failed to encode object for key '%@', error: %@", key, error);
NSAssert(!object || (object && data), @"FXKeychain failed to encode object for key '%@', error: %@", key, *error);

if (data)
{
Expand All @@ -233,7 +242,7 @@ - (BOOL)setObject:(id)object forKey:(id)key

//write data
OSStatus status = errSecSuccess;
if ([self dataForKey:key])
if ([self dataForKey:key error:error])
{
//there's already existing data for this key, update it
status = SecItemUpdate((__bridge CFDictionaryRef)query, (__bridge CFDictionaryRef)update);
Expand All @@ -247,6 +256,10 @@ - (BOOL)setObject:(id)object forKey:(id)key
if (status != errSecSuccess)
{
NSLog(@"FXKeychain failed to store data for key '%@', error: %ld", key, (long)status);
if (error != NULL)
{
*error = [NSError errorWithDomain:kFXKeychainErrorDomain code:status userInfo:nil];
}
return NO;
}
}
Expand All @@ -270,6 +283,10 @@ - (BOOL)setObject:(id)object forKey:(id)key
if (status != errSecSuccess)
{
NSLog(@"FXKeychain failed to delete data for key '%@', error: %ld", key, (long)status);
if (error != NULL)
{
*error = [NSError errorWithDomain:kFXKeychainErrorDomain code:status userInfo:nil];
}
return NO;
}
}
Expand All @@ -283,16 +300,25 @@ - (BOOL)setObject:(id)object forKeyedSubscript:(id)key

- (BOOL)removeObjectForKey:(id)key
{
return [self setObject:nil forKey:key];
return [self removeObjectForKey:key error:nil];
}

- (BOOL)removeObjectForKey:(id)key error:(NSError **)error
{
return [self setObject:nil forKey:key error:error];
}

- (id)objectForKey:(id)key
{
NSData *data = [self dataForKey:key];
return [self objectForKey:key error:nil];
}

- (id)objectForKey:(id)key error:(NSError **) error
{
NSData *data = [self dataForKey:key error:error];
if (data)
{
id object = nil;
NSError *error = nil;
NSPropertyListFormat format = NSPropertyListBinaryFormat_v1_0;

//check if data is a binary plist
Expand All @@ -302,7 +328,7 @@ - (id)objectForKey:(id)key
object = [NSPropertyListSerialization propertyListWithData:data
options:NSPropertyListImmutable
format:&format
error:&error];
error:error];

if ([object respondsToSelector:@selector(objectForKey:)] && [(NSDictionary *)object objectForKey:@"$archiver"])
{
Expand All @@ -326,7 +352,7 @@ - (id)objectForKey:(id)key
}
if (!object)
{
NSLog(@"FXKeychain failed to decode data for key '%@', error: %@", key, error);
NSLog(@"FXKeychain failed to decode data for key '%@', error: %@", key, *error);
}
return object;
}
Expand Down