forked from Matchstic/ReProvision
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathRPVResources.m
232 lines (181 loc) · 8.04 KB
/
RPVResources.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
//
// RPVResources.m
//
//
// Created by Matt Clarke on 09/01/2018.
//
#import "RPVResources.h"
#import "SAMKeychain.h"
#import <UIKit/UIKit.h>
#import <objc/runtime.h>
#include <notify.h>
#include <dlfcn.h>
// For Apple Watch support
@interface NRDevice : NSObject
- (id)valueForProperty:(id)arg1;
@end
@interface NRPairedDeviceRegistry : NSObject
+ (instancetype)sharedInstance;
- (NRDevice*)getActivePairedDevice;
- (bool)isPaired;
@end
static dispatch_once_t nanoRegistryOnceToken;
#define SERVICENAME @"com.matchstic.ReProvision"
@implementation RPVResources
/////////////////////////////////////////////////////////////////////////////////////////////////
// User Settings
/////////////////////////////////////////////////////////////////////////////////////////////////
+ (BOOL)shouldShowDebugAlerts {
id value = [self preferenceValueForKey:@"showDebugAlerts"];
return value ? [value boolValue] : NO;
}
+ (BOOL)shouldShowAlerts {
id value = [self preferenceValueForKey:@"showAlerts"];
return value ? [value boolValue] : YES;
}
+ (BOOL)shouldShowNonUrgentAlerts {
id value = [self preferenceValueForKey:@"showNonUrgentAlerts"];
return value ? [value boolValue] : NO;
}
// How many days left until expiry.
+ (int)thresholdForResigning {
id value = [self preferenceValueForKey:@"thresholdForResigning"];
return value ? [value intValue] : 2;
}
+ (BOOL)shouldAutomaticallyResign {
id value = [self preferenceValueForKey:@"resign"];
return value ? [value boolValue] : YES;
}
+ (BOOL)shouldResignInLowPowerMode {
id value = [self preferenceValueForKey:@"resignInLowPowerMode"];
return value ? [value boolValue] : NO;
}
+ (BOOL)shouldAutoRevokeIfNeeded {
id value = [self preferenceValueForKey:@"shouldAutoRevokeIfNeeded"];
return value ? [value boolValue] : NO;
}
+ (NSTimeInterval)heartbeatTimerInterval {
id value = [[NSUserDefaults standardUserDefaults] objectForKey:@"heartbeatTimerInterval"];
int time = value ? [value intValue] : 2;
NSTimeInterval interval = 3600;
interval *= time;
return interval;
}
+ (id)preferenceValueForKey:(NSString*)key {
return [[NSUserDefaults standardUserDefaults] objectForKey:key];
}
+ (void)setPreferenceValue:(id)value forKey:(NSString*)key withNotification:(NSString*)notification {
[[NSUserDefaults standardUserDefaults] setObject:value forKey:key];
// Write to CFPreferences
CFPreferencesSetValue ((__bridge CFStringRef)key, (__bridge CFPropertyListRef)value, CFSTR("com.matchstic.reprovision.ios"), kCFPreferencesCurrentUser, kCFPreferencesCurrentHost);
CFPreferencesAppSynchronize(CFSTR("com.matchstic.reprovision.ios"));
// Notify daemon of new preferences.
notify_post("com.matchstic.reprovision.ios/updatePreferences");
// Broadcast notification as Darwin
[self _broadcastNotification:notification withUserInfo:nil];
}
+ (void)_broadcastNotification:(NSString*)notifiation withUserInfo:(NSDictionary*)userInfo {
[[NSNotificationCenter defaultCenter] postNotificationName:notifiation object:nil userInfo:userInfo];
}
/////////////////////////////////////////////////////////////////////////////////////////////////
// User Account
/////////////////////////////////////////////////////////////////////////////////////////////////
+ (NSString*)getUsername {
return [[NSUserDefaults standardUserDefaults] objectForKey:@"cachedUsername"];
}
+ (NSString*)getPassword {
return [SAMKeychain passwordForService:SERVICENAME account:[self getUsername]];
}
+ (NSString*)getTeamID {
return [[NSUserDefaults standardUserDefaults] objectForKey:@"cachedTeamID"];
}
+ (void)storeUsername:(NSString*)username password:(NSString*)password andTeamID:(NSString*)teamId {
[[NSUserDefaults standardUserDefaults] setObject:username forKey:@"cachedUsername"];
[SAMKeychain setPassword:password forService:SERVICENAME account:username];
[[NSUserDefaults standardUserDefaults] setObject:teamId forKey:@"cachedTeamID"];
}
+ (void)userDidRequestAccountSignIn {
[self _broadcastNotification:@"RPVDisplayAccountSignInController" withUserInfo:nil];
}
+ (void)userDidRequestAccountSignOut {
NSString *username = [self getUsername];
[[NSUserDefaults standardUserDefaults] removeObjectForKey:@"cachedUsername"];
[[NSUserDefaults standardUserDefaults] removeObjectForKey:@"cachedTeamID"];
// Remove password from Keychain
[SAMKeychain deletePasswordForService:SERVICENAME account:username];
[self _broadcastNotification:@"RPVDisplayAccountSignInController" withUserInfo:nil];
}
/////////////////////////////////////////////////////////////////////////////////////////////////
// Apple Watch
/////////////////////////////////////////////////////////////////////////////////////////////////
+ (BOOL)hasActivePairedWatch {
#if TARGET_OS_SIMULATOR
return NO;
#else
// Load NanoRegistry if needed.
dispatch_once(&nanoRegistryOnceToken, ^{
dlopen("/System/Library/PrivateFrameworks/NanoRegistry.framework/NanoRegistry", RTLD_NOW);
});
NRPairedDeviceRegistry *sharedRegistry = [objc_getClass("NRPairedDeviceRegistry") sharedInstance];
return [sharedRegistry isPaired];
#endif
}
+ (NSString*)activePairedWatchUDID {
return [self _valueForActivePairedWatchWithProperty:@"UDID"];
}
+ (NSString*)activePairedWatchName {
return [self _valueForActivePairedWatchWithProperty:@"name"];
}
+ (id)_valueForActivePairedWatchWithProperty:(NSString*)property {
#if TARGET_OS_SIMULATOR
return @"";
#else
// Load NanoRegistry if needed.
dispatch_once(&nanoRegistryOnceToken, ^{
dlopen("/System/Library/PrivateFrameworks/NanoRegistry.framework/NanoRegistry", RTLD_NOW);
});
NRPairedDeviceRegistry *sharedRegistry = [objc_getClass("NRPairedDeviceRegistry") sharedInstance];
NRDevice *currentWatchDevice = [sharedRegistry getActivePairedDevice];
return [currentWatchDevice valueForProperty:property];
#endif
}
//////////////////////////////////////////////////////////////////////////////////
// Helper methods.
//////////////////////////////////////////////////////////////////////////////////
+ (NSString*)getFormattedTimeRemainingForExpirationDate:(NSDate*)expirationDate {
NSDate *now = [NSDate date];
NSTimeInterval distanceBetweenDates = [expirationDate timeIntervalSinceDate:now];
double secondsInAnHour = 3600;
NSInteger hoursBetweenDates = distanceBetweenDates / secondsInAnHour;
int days = (int)floor((CGFloat)hoursBetweenDates / 24.0);
int minutes = distanceBetweenDates / 60;
if (days > 0) {
// round up days to make more sense to the user
return [NSString stringWithFormat:@"%d day%@, %d hour%@", days, days == 1 ? @"" : @"s", (int)hoursBetweenDates - (days * 24), hoursBetweenDates == 1 ? @"" : @"s"];
} else if (hoursBetweenDates > 0) {
// less than 24 hours, warning time.
return [NSString stringWithFormat:@"%d hour%@", (int)hoursBetweenDates, hoursBetweenDates == 1 ? @"" : @"s"];
} else if (minutes > 0){
// less than 1 hour, warning time. (!!)
return [NSString stringWithFormat:@"%d minute%@", minutes, minutes == 1 ? @"" : @"s"];
} else {
return @"Expired";
}
}
+ (CGRect)boundedRectForFont:(UIFont*)font andText:(NSString*)text width:(CGFloat)width {
if (!text || !font) {
return CGRectZero;
}
if (![text isKindOfClass:[NSAttributedString class]]) {
NSAttributedString *attributedText = [[NSAttributedString alloc] initWithString:text attributes:@{NSFontAttributeName:font}];
CGRect rect = [attributedText boundingRectWithSize:(CGSize){width, CGFLOAT_MAX}
options:NSStringDrawingUsesLineFragmentOrigin
context:nil];
return rect;
} else {
return [(NSAttributedString*)text boundingRectWithSize:(CGSize){width, CGFLOAT_MAX}
options:NSStringDrawingUsesLineFragmentOrigin
context:nil];
}
}
@end