mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-07-30 07:00:49 +00:00
Use Keychain for some data
- Added SFHFKeyChainUtils with BIT prefix - Save username, email or userid (if provided by the app or the user) in the keychain instead of user defaults or property files
This commit is contained in:
parent
89fa399787
commit
93c2f05fac
@ -208,6 +208,9 @@ NSString *const kBITCrashManagerStatus = @"BITCrashManagerStatus";
|
||||
for (NSUInteger i=0; i < [_crashFiles count]; i++) {
|
||||
[_fileManager removeItemAtPath:[_crashFiles objectAtIndex:i] error:&error];
|
||||
[_fileManager removeItemAtPath:[[_crashFiles objectAtIndex:i] stringByAppendingString:@".meta"] error:&error];
|
||||
[self removeKeyFromKeychain:[NSString stringWithFormat:@"%@.%@", [_crashFiles objectAtIndex:i], kBITCrashMetaUserName]];
|
||||
[self removeKeyFromKeychain:[NSString stringWithFormat:@"%@.%@", [_crashFiles objectAtIndex:i], kBITCrashMetaUserEmail]];
|
||||
[self removeKeyFromKeychain:[NSString stringWithFormat:@"%@.%@", [_crashFiles objectAtIndex:i], kBITCrashMetaUserID]];
|
||||
}
|
||||
[_crashFiles removeAllObjects];
|
||||
[_approvedCrashReports removeAllObjects];
|
||||
@ -321,9 +324,9 @@ NSString *const kBITCrashManagerStatus = @"BITCrashManagerStatus";
|
||||
NSString *applicationLog = @"";
|
||||
NSString *errorString = nil;
|
||||
|
||||
[metaDict setObject:[self userNameForCrashReport] forKey:kBITCrashMetaUserName];
|
||||
[metaDict setObject:[self userEmailForCrashReport] forKey:kBITCrashMetaUserEmail];
|
||||
[metaDict setObject:[self userIDForCrashReport] forKey:kBITCrashMetaUserID];
|
||||
[self addStringValueToKeychain:[self userNameForCrashReport] forKey:[NSString stringWithFormat:@"%@.%@", cacheFilename, kBITCrashMetaUserName]];
|
||||
[self addStringValueToKeychain:[self userEmailForCrashReport] forKey:[NSString stringWithFormat:@"%@.%@", cacheFilename, kBITCrashMetaUserEmail]];
|
||||
[self addStringValueToKeychain:[self userIDForCrashReport] forKey:[NSString stringWithFormat:@"%@.%@", cacheFilename, kBITCrashMetaUserID]];
|
||||
|
||||
if (self.delegate != nil && [self.delegate respondsToSelector:@selector(applicationLogForCrashManager:)]) {
|
||||
applicationLog = [self.delegate applicationLogForCrashManager:self] ?: @"";
|
||||
@ -548,6 +551,10 @@ NSString *const kBITCrashManagerStatus = @"BITCrashManagerStatus";
|
||||
// we cannot do anything with this report, so delete it
|
||||
[_fileManager removeItemAtPath:filename error:&error];
|
||||
[_fileManager removeItemAtPath:[NSString stringWithFormat:@"%@.meta", filename] error:&error];
|
||||
|
||||
[self removeKeyFromKeychain:[NSString stringWithFormat:@"%@.%@", filename, kBITCrashMetaUserName]];
|
||||
[self removeKeyFromKeychain:[NSString stringWithFormat:@"%@.%@", filename, kBITCrashMetaUserEmail]];
|
||||
[self removeKeyFromKeychain:[NSString stringWithFormat:@"%@.%@", filename, kBITCrashMetaUserID]];
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -583,9 +590,9 @@ NSString *const kBITCrashManagerStatus = @"BITCrashManagerStatus";
|
||||
format:&format
|
||||
errorDescription:&errorString];
|
||||
|
||||
username = [metaDict objectForKey:kBITCrashMetaUserName] ?: @"";
|
||||
useremail = [metaDict objectForKey:kBITCrashMetaUserEmail] ?: @"";
|
||||
userid = [metaDict objectForKey:kBITCrashMetaUserID] ?: @"";
|
||||
username = [self stringValueFromKeychainForKey:[NSString stringWithFormat:@"%@.%@", filename, kBITCrashMetaUserName]] ?: @"";
|
||||
useremail = [self stringValueFromKeychainForKey:[NSString stringWithFormat:@"%@.%@", filename, kBITCrashMetaUserEmail]] ?: @"";
|
||||
userid = [self stringValueFromKeychainForKey:[NSString stringWithFormat:@"%@.%@", filename, kBITCrashMetaUserID]] ?: @"";
|
||||
applicationLog = [metaDict objectForKey:kBITCrashMetaApplicationLog] ?: @"";
|
||||
} else {
|
||||
BITHockeyLog(@"ERROR: Reading crash meta data. %@", error);
|
||||
@ -618,6 +625,10 @@ NSString *const kBITCrashManagerStatus = @"BITCrashManagerStatus";
|
||||
// we cannot do anything with this report, so delete it
|
||||
[_fileManager removeItemAtPath:filename error:&error];
|
||||
[_fileManager removeItemAtPath:[NSString stringWithFormat:@"%@.meta", filename] error:&error];
|
||||
|
||||
[self removeKeyFromKeychain:[NSString stringWithFormat:@"%@.%@", filename, kBITCrashMetaUserName]];
|
||||
[self removeKeyFromKeychain:[NSString stringWithFormat:@"%@.%@", filename, kBITCrashMetaUserEmail]];
|
||||
[self removeKeyFromKeychain:[NSString stringWithFormat:@"%@.%@", filename, kBITCrashMetaUserID]];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -295,25 +295,37 @@
|
||||
}
|
||||
|
||||
if (!userIDViaDelegate) {
|
||||
if ([unarchiver containsValueForKey:kBITFeedbackUserID])
|
||||
if ([unarchiver containsValueForKey:kBITFeedbackUserID]) {
|
||||
self.userID = [unarchiver decodeObjectForKey:kBITFeedbackUserID];
|
||||
[self addStringValueToKeychain:self.userID forKey:kBITFeedbackUserID];
|
||||
}
|
||||
self.userID = [self stringValueFromKeychainForKey:kBITFeedbackUserID];
|
||||
}
|
||||
|
||||
if (!userNameViaDelegate) {
|
||||
if ([unarchiver containsValueForKey:kBITFeedbackName])
|
||||
if ([unarchiver containsValueForKey:kBITFeedbackName]) {
|
||||
self.userName = [unarchiver decodeObjectForKey:kBITFeedbackName];
|
||||
[self addStringValueToKeychain:self.userName forKey:kBITFeedbackName];
|
||||
}
|
||||
self.userName = [self stringValueFromKeychainForKey:kBITFeedbackName];
|
||||
}
|
||||
|
||||
if (!userEmailViaDelegate) {
|
||||
if ([unarchiver containsValueForKey:kBITFeedbackEmail])
|
||||
if ([unarchiver containsValueForKey:kBITFeedbackEmail]) {
|
||||
self.userEmail = [unarchiver decodeObjectForKey:kBITFeedbackEmail];
|
||||
[self addStringValueToKeychain:self.userEmail forKey:kBITFeedbackEmail];
|
||||
}
|
||||
self.userEmail = [self stringValueFromKeychainForKey:kBITFeedbackEmail];
|
||||
}
|
||||
|
||||
if ([unarchiver containsValueForKey:kBITFeedbackUserDataAsked])
|
||||
_didAskUserData = YES;
|
||||
|
||||
if ([unarchiver containsValueForKey:kBITFeedbackToken])
|
||||
if ([unarchiver containsValueForKey:kBITFeedbackToken]) {
|
||||
self.token = [unarchiver decodeObjectForKey:kBITFeedbackToken];
|
||||
[self addStringValueToKeychain:self.token forKey:kBITFeedbackToken];
|
||||
}
|
||||
self.token = [self stringValueFromKeychainForKey:kBITFeedbackToken];
|
||||
|
||||
if ([unarchiver containsValueForKey:kBITFeedbackAppID]) {
|
||||
NSString *appID = [unarchiver decodeObjectForKey:kBITFeedbackAppID];
|
||||
@ -359,19 +371,19 @@
|
||||
[archiver encodeObject:[NSNumber numberWithBool:YES] forKey:kBITFeedbackUserDataAsked];
|
||||
|
||||
if (self.token)
|
||||
[archiver encodeObject:self.token forKey:kBITFeedbackToken];
|
||||
[self addStringValueToKeychain:self.token forKey:kBITFeedbackToken];
|
||||
|
||||
if (self.appIdentifier)
|
||||
[archiver encodeObject:self.appIdentifier forKey:kBITFeedbackAppID];
|
||||
|
||||
if (self.userID)
|
||||
[archiver encodeObject:self.userID forKey:kBITFeedbackUserID];
|
||||
[self addStringValueToKeychain:self.userID forKey:kBITFeedbackUserID];
|
||||
|
||||
if (self.userName)
|
||||
[archiver encodeObject:self.userName forKey:kBITFeedbackName];
|
||||
[self addStringValueToKeychain:self.userName forKey:kBITFeedbackName];
|
||||
|
||||
if (self.userEmail)
|
||||
[archiver encodeObject:self.userEmail forKey:kBITFeedbackEmail];
|
||||
[self addStringValueToKeychain:self.userEmail forKey:kBITFeedbackEmail];
|
||||
|
||||
if (self.lastCheck)
|
||||
[archiver encodeObject:self.lastCheck forKey:kBITFeedbackDateOfLastCheck];
|
||||
|
@ -16,6 +16,7 @@
|
||||
#import "BITHockeyBaseViewController.h"
|
||||
|
||||
#import "BITHockeyManagerPrivate.h"
|
||||
#import "BITKeychainUtils.h"
|
||||
|
||||
#import <sys/sysctl.h>
|
||||
#if !TARGET_IPHONE_SIMULATOR
|
||||
@ -192,6 +193,33 @@
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)addStringValueToKeychain:(NSString *)stringValue forKey:(NSString *)key {
|
||||
if (!key || !stringValue)
|
||||
return NO;
|
||||
|
||||
NSString *serviceName = [NSString stringWithFormat:@"%@.HockeySDK", [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleIdentifier"]];
|
||||
|
||||
NSError *error = nil;
|
||||
return [BITKeychainUtils storeUsername:key andPassword:stringValue forServiceName:serviceName updateExisting:YES error:&error];
|
||||
}
|
||||
|
||||
- (NSString *)stringValueFromKeychainForKey:(NSString *)key {
|
||||
if (!key)
|
||||
return nil;
|
||||
|
||||
NSString *serviceName = [NSString stringWithFormat:@"%@.HockeySDK", [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleIdentifier"]];
|
||||
|
||||
NSError *error = nil;
|
||||
return [BITKeychainUtils getPasswordForUsername:key andServiceName:serviceName error:&error];
|
||||
}
|
||||
|
||||
- (BOOL)removeKeyFromKeychain:(NSString *)key {
|
||||
NSString *serviceName = [NSString stringWithFormat:@"%@.HockeySDK", [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleIdentifier"]];
|
||||
|
||||
NSError *error = nil;
|
||||
return [BITKeychainUtils deleteItemForUsername:key andServiceName:serviceName error:&error];
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - Manager Control
|
||||
|
||||
|
@ -34,4 +34,8 @@
|
||||
|
||||
- (NSDate *)parseRFC3339Date:(NSString *)dateString;
|
||||
|
||||
- (BOOL)addStringValueToKeychain:(NSString *)stringValue forKey:(NSString *)key;
|
||||
- (NSString *)stringValueFromKeychainForKey:(NSString *)key;
|
||||
- (BOOL)removeKeyFromKeychain:(NSString *)key;
|
||||
|
||||
@end
|
||||
|
42
Classes/BITKeychainUtils.h
Normal file
42
Classes/BITKeychainUtils.h
Normal file
@ -0,0 +1,42 @@
|
||||
//
|
||||
// SFHFKeychainUtils.h
|
||||
//
|
||||
// Created by Buzz Andersen on 10/20/08.
|
||||
// Based partly on code by Jonathan Wight, Jon Crosby, and Mike Malone.
|
||||
// Copyright 2008 Sci-Fi Hi-Fi. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
|
||||
@interface BITKeychainUtils : NSObject {
|
||||
|
||||
}
|
||||
|
||||
+ (NSString *) getPasswordForUsername: (NSString *) username andServiceName: (NSString *) serviceName error: (NSError **) error;
|
||||
+ (BOOL) storeUsername: (NSString *) username andPassword: (NSString *) password forServiceName: (NSString *) serviceName updateExisting: (BOOL) updateExisting error: (NSError **) error;
|
||||
+ (BOOL) deleteItemForUsername: (NSString *) username andServiceName: (NSString *) serviceName error: (NSError **) error;
|
||||
+ (BOOL) purgeItemsForServiceName:(NSString *) serviceName error: (NSError **) error;
|
||||
|
||||
@end
|
297
Classes/BITKeychainUtils.m
Normal file
297
Classes/BITKeychainUtils.m
Normal file
@ -0,0 +1,297 @@
|
||||
//
|
||||
// SFHFKeychainUtils.m
|
||||
//
|
||||
// Created by Buzz Andersen on 10/20/08.
|
||||
// Based partly on code by Jonathan Wight, Jon Crosby, and Mike Malone.
|
||||
// Copyright 2008 Sci-Fi Hi-Fi. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
#import "BITKeychainUtils.h"
|
||||
#import <Security/Security.h>
|
||||
|
||||
static NSString *BITKeychainUtilsErrorDomain = @"BITKeychainUtilsErrorDomain";
|
||||
|
||||
@implementation BITKeychainUtils
|
||||
|
||||
+ (NSString *) getPasswordForUsername: (NSString *) username andServiceName: (NSString *) serviceName error: (NSError **) error {
|
||||
if (!username || !serviceName) {
|
||||
if (error != nil) {
|
||||
*error = [NSError errorWithDomain: BITKeychainUtilsErrorDomain code: -2000 userInfo: nil];
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
if (error != nil) {
|
||||
*error = nil;
|
||||
}
|
||||
|
||||
// Set up a query dictionary with the base query attributes: item type (generic), username, and service
|
||||
|
||||
NSArray *keys = [[NSArray alloc] initWithObjects: (__bridge_transfer NSString *) kSecClass, kSecAttrAccount, kSecAttrService, nil];
|
||||
NSArray *objects = [[NSArray alloc] initWithObjects: (__bridge_transfer NSString *) kSecClassGenericPassword, username, serviceName, nil];
|
||||
|
||||
NSMutableDictionary *query = [[NSMutableDictionary alloc] initWithObjects: objects forKeys: keys];
|
||||
|
||||
// First do a query for attributes, in case we already have a Keychain item with no password data set.
|
||||
// One likely way such an incorrect item could have come about is due to the previous (incorrect)
|
||||
// version of this code (which set the password as a generic attribute instead of password data).
|
||||
|
||||
NSMutableDictionary *attributeQuery = [query mutableCopy];
|
||||
[attributeQuery setObject: (id) kCFBooleanTrue forKey:(__bridge_transfer id) kSecReturnAttributes];
|
||||
CFTypeRef attrResult = NULL;
|
||||
OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef) attributeQuery, &attrResult);
|
||||
//NSDictionary *attributeResult = (__bridge_transfer NSDictionary *)attrResult;
|
||||
|
||||
if (status != noErr) {
|
||||
// No existing item found--simply return nil for the password
|
||||
if (error != nil && status != errSecItemNotFound) {
|
||||
//Only return an error if a real exception happened--not simply for "not found."
|
||||
*error = [NSError errorWithDomain: BITKeychainUtilsErrorDomain code: status userInfo: nil];
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
// We have an existing item, now query for the password data associated with it.
|
||||
|
||||
NSMutableDictionary *passwordQuery = [query mutableCopy];
|
||||
[passwordQuery setObject: (id) kCFBooleanTrue forKey: (__bridge_transfer id) kSecReturnData];
|
||||
CFTypeRef resData = NULL;
|
||||
status = SecItemCopyMatching((__bridge CFDictionaryRef) passwordQuery, (CFTypeRef *) &resData);
|
||||
NSData *resultData = (__bridge_transfer NSData *)resData;
|
||||
|
||||
if (status != noErr) {
|
||||
if (status == errSecItemNotFound) {
|
||||
// We found attributes for the item previously, but no password now, so return a special error.
|
||||
// Users of this API will probably want to detect this error and prompt the user to
|
||||
// re-enter their credentials. When you attempt to store the re-entered credentials
|
||||
// using storeUsername:andPassword:forServiceName:updateExisting:error
|
||||
// the old, incorrect entry will be deleted and a new one with a properly encrypted
|
||||
// password will be added.
|
||||
if (error != nil) {
|
||||
*error = [NSError errorWithDomain: BITKeychainUtilsErrorDomain code: -1999 userInfo: nil];
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Something else went wrong. Simply return the normal Keychain API error code.
|
||||
if (error != nil) {
|
||||
*error = [NSError errorWithDomain: BITKeychainUtilsErrorDomain code: status userInfo: nil];
|
||||
}
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
NSString *password = nil;
|
||||
|
||||
if (resultData) {
|
||||
password = [[NSString alloc] initWithData: resultData encoding: NSUTF8StringEncoding];
|
||||
}
|
||||
else {
|
||||
// There is an existing item, but we weren't able to get password data for it for some reason,
|
||||
// Possibly as a result of an item being incorrectly entered by the previous code.
|
||||
// Set the -1999 error so the code above us can prompt the user again.
|
||||
if (error != nil) {
|
||||
*error = [NSError errorWithDomain: BITKeychainUtilsErrorDomain code: -1999 userInfo: nil];
|
||||
}
|
||||
}
|
||||
|
||||
return password;
|
||||
}
|
||||
|
||||
+ (BOOL) storeUsername: (NSString *) username andPassword: (NSString *) password forServiceName: (NSString *) serviceName updateExisting: (BOOL) updateExisting error: (NSError **) error
|
||||
{
|
||||
if (!username || !password || !serviceName)
|
||||
{
|
||||
if (error != nil)
|
||||
{
|
||||
*error = [NSError errorWithDomain: BITKeychainUtilsErrorDomain code: -2000 userInfo: nil];
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
// See if we already have a password entered for these credentials.
|
||||
NSError *getError = nil;
|
||||
NSString *existingPassword = [BITKeychainUtils getPasswordForUsername: username andServiceName: serviceName error:&getError];
|
||||
|
||||
if ([getError code] == -1999)
|
||||
{
|
||||
// There is an existing entry without a password properly stored (possibly as a result of the previous incorrect version of this code.
|
||||
// Delete the existing item before moving on entering a correct one.
|
||||
|
||||
getError = nil;
|
||||
|
||||
[self deleteItemForUsername: username andServiceName: serviceName error: &getError];
|
||||
|
||||
if ([getError code] != noErr)
|
||||
{
|
||||
if (error != nil)
|
||||
{
|
||||
*error = getError;
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
else if ([getError code] != noErr)
|
||||
{
|
||||
if (error != nil)
|
||||
{
|
||||
*error = getError;
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
if (error != nil)
|
||||
{
|
||||
*error = nil;
|
||||
}
|
||||
|
||||
OSStatus status = noErr;
|
||||
|
||||
if (existingPassword)
|
||||
{
|
||||
// We have an existing, properly entered item with a password.
|
||||
// Update the existing item.
|
||||
|
||||
if (![existingPassword isEqualToString:password] && updateExisting)
|
||||
{
|
||||
//Only update if we're allowed to update existing. If not, simply do nothing.
|
||||
|
||||
NSArray *keys = [[NSArray alloc] initWithObjects: (__bridge_transfer NSString *) kSecClass,
|
||||
kSecAttrService,
|
||||
kSecAttrLabel,
|
||||
kSecAttrAccount,
|
||||
nil];
|
||||
|
||||
NSArray *objects = [[NSArray alloc] initWithObjects: (__bridge_transfer NSString *) kSecClassGenericPassword,
|
||||
serviceName,
|
||||
serviceName,
|
||||
username,
|
||||
nil];
|
||||
|
||||
NSDictionary *query = [[NSDictionary alloc] initWithObjects: objects forKeys: keys];
|
||||
|
||||
status = SecItemUpdate((__bridge_retained CFDictionaryRef) query, (__bridge_retained CFDictionaryRef) [NSDictionary dictionaryWithObject: [password dataUsingEncoding: NSUTF8StringEncoding] forKey: (__bridge_transfer NSString *) kSecValueData]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// No existing entry (or an existing, improperly entered, and therefore now
|
||||
// deleted, entry). Create a new entry.
|
||||
|
||||
NSArray *keys = [[NSArray alloc] initWithObjects: (__bridge_transfer NSString *) kSecClass,
|
||||
kSecAttrService,
|
||||
kSecAttrLabel,
|
||||
kSecAttrAccount,
|
||||
kSecValueData,
|
||||
nil];
|
||||
|
||||
NSArray *objects = [[NSArray alloc] initWithObjects: (__bridge_transfer NSString *) kSecClassGenericPassword,
|
||||
serviceName,
|
||||
serviceName,
|
||||
username,
|
||||
[password dataUsingEncoding: NSUTF8StringEncoding],
|
||||
nil];
|
||||
|
||||
NSDictionary *query = [[NSDictionary alloc] initWithObjects: objects forKeys: keys];
|
||||
|
||||
status = SecItemAdd((__bridge_retained CFDictionaryRef) query, NULL);
|
||||
}
|
||||
|
||||
if (error != nil && status != noErr)
|
||||
{
|
||||
// Something went wrong with adding the new item. Return the Keychain error code.
|
||||
*error = [NSError errorWithDomain: BITKeychainUtilsErrorDomain code: status userInfo: nil];
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
+ (BOOL) deleteItemForUsername: (NSString *) username andServiceName: (NSString *) serviceName error: (NSError **) error
|
||||
{
|
||||
if (!username || !serviceName)
|
||||
{
|
||||
if (error != nil)
|
||||
{
|
||||
*error = [NSError errorWithDomain: BITKeychainUtilsErrorDomain code: -2000 userInfo: nil];
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
if (error != nil)
|
||||
{
|
||||
*error = nil;
|
||||
}
|
||||
|
||||
NSArray *keys = [[NSArray alloc] initWithObjects: (__bridge_transfer NSString *) kSecClass, kSecAttrAccount, kSecAttrService, kSecReturnAttributes, nil];
|
||||
NSArray *objects = [[NSArray alloc] initWithObjects: (__bridge_transfer NSString *) kSecClassGenericPassword, username, serviceName, kCFBooleanTrue, nil];
|
||||
|
||||
NSDictionary *query = [[NSDictionary alloc] initWithObjects: objects forKeys: keys];
|
||||
|
||||
OSStatus status = SecItemDelete((__bridge CFDictionaryRef) query);
|
||||
|
||||
if (error != nil && status != noErr)
|
||||
{
|
||||
*error = [NSError errorWithDomain: BITKeychainUtilsErrorDomain code: status userInfo: nil];
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
+ (BOOL) purgeItemsForServiceName:(NSString *) serviceName error: (NSError **) error {
|
||||
if (!serviceName)
|
||||
{
|
||||
if (error != nil)
|
||||
{
|
||||
*error = [NSError errorWithDomain: BITKeychainUtilsErrorDomain code: -2000 userInfo: nil];
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
if (error != nil)
|
||||
{
|
||||
*error = nil;
|
||||
}
|
||||
|
||||
NSMutableDictionary *searchData = [NSMutableDictionary new];
|
||||
[searchData setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass];
|
||||
[searchData setObject:serviceName forKey:(__bridge id)kSecAttrService];
|
||||
|
||||
OSStatus status = SecItemDelete((__bridge CFDictionaryRef)searchData);
|
||||
|
||||
if (error != nil && status != noErr)
|
||||
{
|
||||
*error = [NSError errorWithDomain: BITKeychainUtilsErrorDomain code: status userInfo: nil];
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
@end
|
@ -225,7 +225,7 @@
|
||||
|
||||
- (BITUpdateAuthorizationState)authorizationState {
|
||||
NSString *version = [[NSUserDefaults standardUserDefaults] objectForKey:kBITUpdateAuthorizedVersion];
|
||||
NSString *token = [[NSUserDefaults standardUserDefaults] objectForKey:kBITUpdateAuthorizedToken];
|
||||
NSString *token = [self stringValueFromKeychainForKey:kBITUpdateAuthorizedToken];
|
||||
|
||||
if (version != nil && token != nil) {
|
||||
if ([version compare:[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"]] == NSOrderedSame) {
|
||||
@ -602,7 +602,7 @@
|
||||
|
||||
// store the new data
|
||||
[[NSUserDefaults standardUserDefaults] setObject:[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"] forKey:kBITUpdateAuthorizedVersion];
|
||||
[[NSUserDefaults standardUserDefaults] setObject:token forKey:kBITUpdateAuthorizedToken];
|
||||
[self addStringValueToKeychain:token forKey:kBITUpdateAuthorizedToken];
|
||||
[[NSUserDefaults standardUserDefaults] synchronize];
|
||||
|
||||
self.requireAuthorization = NO;
|
||||
@ -618,7 +618,7 @@
|
||||
|
||||
// store the new data
|
||||
[[NSUserDefaults standardUserDefaults] setObject:[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"] forKey:kBITUpdateAuthorizedVersion];
|
||||
[[NSUserDefaults standardUserDefaults] setObject:token forKey:kBITUpdateAuthorizedToken];
|
||||
[self addStringValueToKeychain:token forKey:kBITUpdateAuthorizedToken];
|
||||
[[NSUserDefaults standardUserDefaults] synchronize];
|
||||
|
||||
[self showBlockingScreen:BITHockeyLocalizedString(@"UpdateAuthorizationDenied") image:@"authorize_denied.png"];
|
||||
|
27
LICENSE
27
LICENSE
@ -95,3 +95,30 @@ TTTAttributedLabel is licensed as follows:
|
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
SFHFKeychainUtils is licensed as follows:
|
||||
|
||||
Created by Buzz Andersen on 10/20/08.
|
||||
Based partly on code by Jonathan Wight, Jon Crosby, and Mike Malone.
|
||||
Copyright 2008 Sci-Fi Hi-Fi. All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
files (the "Software"), to deal in the Software without
|
||||
restriction, including without limitation the rights to use,
|
||||
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
@ -1,3 +1,3 @@
|
||||
OTHER_LDFLAGS=$(inherited) -framework CoreText -framework CoreGraphics -framework Foundation -framework QuartzCore -framework SystemConfiguration -framework UIKit
|
||||
OTHER_LDFLAGS=$(inherited) -framework CoreText -framework CoreGraphics -framework Foundation -framework QuartzCore -framework SystemConfiguration -framework UIKit -framework Security
|
||||
HOCKEYSDK_DOCSET_NAME=HockeySDK-iOS
|
||||
GCC_PREPROCESSOR_DEFINITIONS=$(inherited) CONFIGURATION_$(CONFIGURATION)
|
@ -33,6 +33,8 @@
|
||||
/* End PBXAggregateTarget section */
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
1E0FEE28173BDB260061331F /* BITKeychainUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E0FEE26173BDB260061331F /* BITKeychainUtils.h */; };
|
||||
1E0FEE29173BDB260061331F /* BITKeychainUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E0FEE27173BDB260061331F /* BITKeychainUtils.m */; };
|
||||
1E1127C416580C87007067A2 /* buttonRoundedDelete.png in Resources */ = {isa = PBXBuildFile; fileRef = 1E1127BC16580C87007067A2 /* buttonRoundedDelete.png */; };
|
||||
1E1127C516580C87007067A2 /* buttonRoundedDelete@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 1E1127BD16580C87007067A2 /* buttonRoundedDelete@2x.png */; };
|
||||
1E1127C616580C87007067A2 /* buttonRoundedDeleteHighlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = 1E1127BE16580C87007067A2 /* buttonRoundedDeleteHighlighted.png */; };
|
||||
@ -130,6 +132,9 @@
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
1E0FEE22173BD9BB0061331F /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; };
|
||||
1E0FEE26173BDB260061331F /* BITKeychainUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITKeychainUtils.h; sourceTree = "<group>"; };
|
||||
1E0FEE27173BDB260061331F /* BITKeychainUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BITKeychainUtils.m; sourceTree = "<group>"; };
|
||||
1E1127BC16580C87007067A2 /* buttonRoundedDelete.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = buttonRoundedDelete.png; sourceTree = "<group>"; };
|
||||
1E1127BD16580C87007067A2 /* buttonRoundedDelete@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "buttonRoundedDelete@2x.png"; sourceTree = "<group>"; };
|
||||
1E1127BE16580C87007067A2 /* buttonRoundedDeleteHighlighted.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = buttonRoundedDeleteHighlighted.png; sourceTree = "<group>"; };
|
||||
@ -295,6 +300,8 @@
|
||||
1E49A4A4161222B900463151 /* BITHockeyBaseViewController.m */,
|
||||
1E49A4A5161222B900463151 /* BITHockeyHelper.h */,
|
||||
1E49A4A6161222B900463151 /* BITHockeyHelper.m */,
|
||||
1E0FEE26173BDB260061331F /* BITKeychainUtils.h */,
|
||||
1E0FEE27173BDB260061331F /* BITKeychainUtils.m */,
|
||||
1EACC979162F041E007578C5 /* BITAttributedLabel.h */,
|
||||
1EACC97A162F041E007578C5 /* BITAttributedLabel.m */,
|
||||
1E49A4A7161222B900463151 /* BITAppStoreHeader.h */,
|
||||
@ -463,6 +470,7 @@
|
||||
1E754E5F1621FBB70070AB92 /* BITCrashManagerPrivate.h in Headers */,
|
||||
1E754E601621FBB70070AB92 /* BITCrashReportTextFormatter.h in Headers */,
|
||||
1EACC97B162F041E007578C5 /* BITAttributedLabel.h in Headers */,
|
||||
1E0FEE28173BDB260061331F /* BITKeychainUtils.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@ -636,6 +644,7 @@
|
||||
1E754E611621FBB70070AB92 /* BITCrashReportTextFormatter.m in Sources */,
|
||||
1EF95CA7162CB037000AE3AD /* BITFeedbackActivity.m in Sources */,
|
||||
1EACC97C162F041E007578C5 /* BITAttributedLabel.m in Sources */,
|
||||
1E0FEE29173BDB260061331F /* BITKeychainUtils.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -102,6 +102,7 @@ If you need support for iOS 3.x, please check out [HockeyKit](http://support.hoc
|
||||
- `CoreGraphics`
|
||||
- `Foundation`
|
||||
- `QuartzCore`
|
||||
- `Security`
|
||||
- `SystemConfiguration`
|
||||
- `UIKit`
|
||||
|
||||
|
@ -72,6 +72,7 @@ If you need support for iOS 3.x, please check out [HockeyKit](http://support.hoc
|
||||
- `CoreGraphics`
|
||||
- `Foundation`
|
||||
- `QuartzCore`
|
||||
- `Security`
|
||||
- `SystemConfiguration`
|
||||
- `UIKit`
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user