1/* 2 * Copyright (c) 2013-2014 Apple Inc. All Rights Reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24 25#import "KNPersistantState.h" 26 27@implementation KNPersistantState 28 29-(NSURL*)urlForStorage 30{ 31 return [NSURL URLWithString:@"Preferences/com.apple.security.KCN.plist" relativeToURL:[[NSFileManager defaultManager] URLForDirectory:NSLibraryDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:YES error:nil]]; 32} 33 34+(instancetype)loadFromStorage 35{ 36 KNPersistantState *state = [[KNPersistantState alloc] init]; 37 if (!state) { 38 return state; 39 } 40 41 id plist = @{@"lastWritten": [NSDate distantPast]}; 42 43 NSError *error = nil; 44 NSData *stateData = [NSData dataWithContentsOfURL:[state urlForStorage] options:0 error:&error]; 45 if (!stateData) { 46 NSLog(@"Can't read state data (p=%@, err=%@)", [state urlForStorage], error); 47 } else { 48 NSPropertyListFormat format; 49 plist = [NSPropertyListSerialization propertyListWithData:stateData options: NSPropertyListMutableContainersAndLeaves format:&format error:&error]; 50 51 if (plist == nil) { 52 NSLog(@"Can't deserialize %@, e=%@", stateData, error); 53 } 54 } 55 56 state.lastCircleStatus = plist[@"lastCircleStatus"] ? [plist[@"lastCircleStatus"] intValue] : kSOSCCCircleAbsent; 57 state.lastWritten = plist[@"lastWritten"]; 58 state.pendingApplicationReminderInterval = plist[@"pendingApplicationReminderInterval"]; 59 state.debugLeftReason = plist[@"debugLeftReason"]; 60 state.pendingApplicationReminder = plist[@"pendingApplicationReminder"]; 61 state.applcationDate = plist[@"applcationDate"]; 62 if (!state.applcationDate) { 63 state.applcationDate = [NSDate distantPast]; 64 } 65 if (!state.pendingApplicationReminder) { 66 state.pendingApplicationReminder = [NSDate distantFuture]; 67 } 68 if (!state.pendingApplicationReminderInterval || [state.pendingApplicationReminderInterval doubleValue] <= 0) { 69 state.pendingApplicationReminderInterval = [NSNumber numberWithUnsignedInt:60 * 60 * 24 * 2]; 70 } 71 72 return state; 73} 74 75-(void)writeToStorage 76{ 77 NSMutableDictionary *plist = [@{@"lastCircleStatus": [NSNumber numberWithInt:self.lastCircleStatus], 78 @"lastWritten": [NSDate date], 79 @"applcationDate": self.applcationDate, 80 @"pendingApplicationReminder": self.pendingApplicationReminder, 81 } mutableCopy]; 82 if (self.debugLeftReason) { 83 plist[@"debugLeftReason"] = self.debugLeftReason; 84 } 85 if (self.pendingApplicationReminderInterval) { 86 plist[@"pendingApplicationReminderInterval"] = self.pendingApplicationReminderInterval; 87 } 88 NSLog(@"writeToStorage plist=%@", plist); 89 90 NSError *error = nil; 91 NSData *stateData = [NSPropertyListSerialization dataWithPropertyList:[plist copy] format:NSPropertyListXMLFormat_v1_0 options:kCFPropertyListImmutable error:&error]; 92 if (!stateData) { 93 NSLog(@"Can't serialize %@: %@", plist, error); 94 return; 95 } 96 if (![stateData writeToURL:[self urlForStorage] options:NSDataWritingAtomic error:&error]) { 97 NSLog(@"Can't write to %@, error=%@", [self urlForStorage], error); 98 } 99} 100 101 102@end 103