// // ICRUserUtil.m // XFFruit // // Created by Xummer on 3/29/15. // Copyright (c) 2015 Xummer. All rights reserved. // #import "ICRUserUtil.h" #import "SSKeychain.h" #import "SSKeychainQuery.h" #import #define kSchemePrefix @"Keychain_" #define kArchiveName @"ICRLocalInfo" NSString *const kSSKeychainPasswordKey = @"password"; NSString *const kSSKeychainUniqueIdentifierKey = @"uniqueIdentifier"; static ICRUserUtil *sharedInstance = nil; @interface ICRUserUtil () @property (copy, nonatomic) NSString *uniqueIdentifier; @end @implementation ICRUserUtil + (instancetype)sharedInstance { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ sharedInstance = [[self class] unarchive]; }); return sharedInstance; } + (id)allocWithZone:(NSZone *)zone { @synchronized(self) { if (sharedInstance == nil) { sharedInstance = [super allocWithZone:zone]; return sharedInstance; } } return nil; } + (id)unarchive { NSString *filePath = [[self class] archivePath]; ICRUserUtil *archive = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath]; if (archive == nil) { archive = [[[self class] alloc] init]; } return archive; } - (id)init { if (self = [super init]) { self.userName = @""; self.password = @""; self.registerCode = @""; self.uniqueIdentifier = @""; self.token = @""; self.currentStoreID = @""; [self saveArchive]; } return self; } - (BOOL)saveArchive { BOOL result; NSString *filePath = [[self class] archivePath]; result = [NSKeyedArchiver archiveRootObject:self toFile:filePath]; if (result) { // Save password in keychain if ([_userName length] > 0 && [_password length] > 0) { [self saveAuthorizeDataToKeychain]; } } return result; } #pragma mark - Getter - (NSString *)uniqueID { if (_uniqueID) { return _uniqueID; } else { self.uniqueID = [[[NSProcessInfo processInfo] globallyUniqueString] substringToIndex:15]; [self saveArchive]; return _uniqueID; } } - (NSString *)mobileID { NSString *uniqID15B = self.uniqueID; if(_uniqueID.length > 15) { uniqID15B = [uniqID15B substringToIndex:15]; } NSString *date15B = [[NSDate date] mobileIDDateString]; NSString *radom6B = [NSString stringWithFormat:@"%@", @( arc4random()%100000 + 100000 )]; return [NSString stringWithFormat:@"%@%@%@", uniqID15B, date15B, radom6B]; } #pragma mark - Public Method - (BOOL)isLogin { return self.token.length > 0; } - (void)logout { if ([_userName length] > 0) { [self deleteAuthorizeDataInKeychain]; } self.password = nil; self.token = nil; self.bAutoLogin = @( NO ); self.currentStoreID = @""; [self saveArchive]; } - (void)storageUserName:(NSString *)userName password:(NSString *)password registerCode:(NSString *)registerCode token:(NSString *)token { self.userName = userName; self.password = password; self.registerCode = registerCode; self.token = token; [self saveArchive]; } - (void)storageCurrentStoreID:(NSString *)currentStoreID { self.currentStoreID = currentStoreID; [self saveArchive]; } - (void)updatePassword:(NSString *)pwd { if ([self isLogin]) { self.password = pwd; [self saveUniqueIdentifierToKeychain]; } } #pragma mark - Utilities + (NSString *)archivePath { NSString *archiveName = [[kArchiveName stringByDeletingPathExtension] stringByAppendingPathExtension:@"archive"]; NSFileManager *fileManager = [NSFileManager defaultManager]; NSURL *baseURL = [fileManager URLForDirectory:NSApplicationSupportDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:YES error:NULL]; return [[baseURL path] stringByAppendingPathComponent:archiveName]; } - (NSString *)urlSchemeString { NSDictionary *infoDict =[[NSBundle mainBundle] infoDictionary]; NSString *appName =[infoDict objectForKey:@"CFBundleDisplayName"]; return [NSString stringWithFormat:@"%@%@_", kSchemePrefix, appName]; } - (void)fetchAuthorizeDataFromKeychain { NSString *serviceName = [[self urlSchemeString] stringByAppendingString:_userName]; self.password = [SSKeychain passwordForService:serviceName account:kSSKeychainPasswordKey]; } - (void)saveAuthorizeDataToKeychain { NSString *serviceName = [[self urlSchemeString] stringByAppendingString:_userName]; [SSKeychain setPassword:_password forService:serviceName account:kSSKeychainPasswordKey]; } - (void)deleteAuthorizeDataInKeychain { NSString *serviceName = [[self urlSchemeString] stringByAppendingString:_userName]; [SSKeychain deletePasswordForService:serviceName account:kSSKeychainPasswordKey]; } - (void)fetchUniqueIdentifierFromKeychain { NSString *serviceName = [[self urlSchemeString] stringByAppendingString:kSSKeychainUniqueIdentifierKey]; self.uniqueIdentifier = [SSKeychain passwordForService:serviceName account:kSSKeychainUniqueIdentifierKey]; } - (void)saveUniqueIdentifierToKeychain { NSString *serviceName = [[self urlSchemeString] stringByAppendingString:kSSKeychainUniqueIdentifierKey]; [SSKeychain setPassword:_uniqueIdentifier forService:serviceName account:kSSKeychainUniqueIdentifierKey]; } - (void)deleteUniqueIdentifierToKeychain { NSString *serviceName = [[self urlSchemeString] stringByAppendingString:kSSKeychainUniqueIdentifierKey]; [SSKeychain deletePasswordForService:serviceName account:kSSKeychainUniqueIdentifierKey]; } #pragma mark - NSCoding - (id)initWithCoder:(NSCoder *)decoder { self = [super init]; if (!self) { return self; } unsigned int count; objc_property_t *properties = class_copyPropertyList([self class], &count); for (NSUInteger i = 0; i < count; i++) { objc_property_t property = properties[i]; NSString *key = [NSString stringWithUTF8String:property_getName(property)]; [self setValue:[decoder decodeObjectForKey:key] forKey:key]; } free(properties); return self; } - (void)encodeWithCoder:(NSCoder *)coder { unsigned int count; objc_property_t *properties = class_copyPropertyList([self class], &count); for (NSUInteger i = 0; i < count; i++) { objc_property_t property = properties[i]; NSString *key = [NSString stringWithUTF8String:property_getName(property)]; [coder encodeObject:[self valueForKey:key] forKey:key]; } free(properties); } #pragma mark - NSCopying protocol methods - (id)copyWithZone:(NSZone *)zone { ICRUserUtil *copy = [[[self class] allocWithZone:zone] init]; unsigned int count; objc_property_t *properties = class_copyPropertyList([self class], &count); for (NSUInteger i = 0; i < count; i++) { objc_property_t property = properties[i]; NSString *key = [NSString stringWithUTF8String:property_getName(property)]; [copy setValue:[self valueForKey:key] forKey:key]; } free(properties); return copy; } @end