-
Notifications
You must be signed in to change notification settings - Fork 85
/
Copy pathShared.swift
321 lines (286 loc) · 11.1 KB
/
Shared.swift
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
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
//
// SharedConstants.swift
// LockdowniOS
//
// Created by Johnny Lin on 8/8/19.
// Copyright © 2019 Confirmed Inc. All rights reserved.
//
// These are constants and functions shared by the main app and the extensions
import Foundation
import CocoaLumberjackSwift
import KeychainAccess
let isTestFlight = Bundle.main.appStoreReceiptURL?.lastPathComponent == "sandboxReceipt"
var appInstallDate: Date? {
if let documentsFolder = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).last {
if let installDate = try! FileManager.default.attributesOfItem(atPath: documentsFolder.path)[.creationDate] as? Date {
return installDate
}
}
return nil
}
@discardableResult
func appHasJustBeenUpgradedOrIsNewInstall() -> Bool {
let currentVersion = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String
let versionOfLastRun = UserDefaults.standard.object(forKey: kVersionOfLastRun) as? String
DDLogInfo("APP UPGRADED CHECK: LAST RUN \(versionOfLastRun ?? "n/a") | CURRENT \(currentVersion ?? "n/a")")
UserDefaults.standard.set(currentVersion, forKey: kVersionOfLastRun)
if (versionOfLastRun == nil || versionOfLastRun != currentVersion) {
// either first time this check has occurred, or app was updated since last run
DDLogInfo("APP UPGRADED CHECK: TRUE - LAST RUN \(versionOfLastRun ?? "n/a") | CURRENT \(currentVersion ?? "n/a")")
return true
} else {
// nothing changed
DDLogInfo("APP UPGRADED CHECK: FALSE")
return false
}
}
let reachability = Availability()
let keychain = Keychain(service: "com.confirmed.tunnels").synchronizable(true)
// MARK: - VPN Credentials
let kVPNCredentialsKeyBase64 = "VPNCredentialsKeyBase64"
let kVPNCredentialsId = "VPNCredentialsId"
let kICloudContainer = "iCloud.com.confirmed.lockdown"
let kOpenFirewallTunnelRecord = "OpenFirewallTunnelRemotely"
let kCloseFirewallTunnelRecord = "CloseFirewallTunnelRemotely"
let kRestartFirewallTunnelRecord = "RestartFirewallTunnelRemotely"
struct VPNCredentials {
var id: String = ""
var keyBase64: String = ""
}
func setVPNCredentials(id: String, keyBase64: String) throws {
DDLogInfo("Setting VPN Credentials: \(id), base64: \(keyBase64)")
if (id == "") {
throw "ID was blank"
}
if (keyBase64 == "") {
throw "Key was blank"
}
do {
try keychain.set(id, key: kVPNCredentialsId)
try keychain.set(keyBase64, key: kVPNCredentialsKeyBase64)
}
catch {
throw "Unable to set VPN credentials on keychain"
}
}
func getVPNCredentials() -> VPNCredentials? {
DDLogInfo("Getting stored VPN credentials")
var id: String? = nil
do {
id = try keychain.get(kVPNCredentialsId)
if id == nil {
DDLogError("No stored credential id")
return nil
}
}
catch {
DDLogError("Error getting stored VPN credentials id: \(error)")
return nil
}
var keyBase64: String? = nil
do {
keyBase64 = try keychain.get(kVPNCredentialsKeyBase64)
if keyBase64 == nil {
DDLogError("No stored credential keyBase64")
return nil
}
}
catch {
DDLogError("Error getting stored VPN credentials keyBase64: \(error)")
return nil
}
DDLogInfo("Returning stored VPN credentials: \(id!) \(keyBase64!)")
return VPNCredentials(id: id!, keyBase64: keyBase64!)
}
// MARK: - API Credentials
let kAPICredentialsEmail = "APICredentialsEmail"
let kAPICredentialsPassword = "APICredentialsPassword"
struct APICredentials {
var email: String = ""
var password: String = ""
}
func setAPICredentials(email: String, password: String) throws {
DDLogInfo("Setting API Credentials with email: \(email)")
if (email == "") {
throw "Email was blank"
}
if (password == "") {
throw "Password was blank"
}
do {
try keychain.set(email, key: kAPICredentialsEmail)
try keychain.set(password, key: kAPICredentialsPassword)
}
catch {
throw "Unable to set API credentials on keychain"
}
}
func clearAPICredentials() {
try? keychain.remove(kAPICredentialsEmail)
try? keychain.remove(kAPICredentialsPassword)
}
func getAPICredentials() -> APICredentials? {
print("Getting stored API credentials")
var email: String? = nil
do {
email = try keychain.get(kAPICredentialsEmail)
if email == nil {
print("No stored API credential email")
return nil
}
}
catch {
print("Error getting stored API credentials email: \(error)")
return nil
}
var password: String? = nil
do {
password = try keychain.get(kAPICredentialsPassword)
if password == nil {
print("No stored API credential password")
return nil
}
}
catch {
print("Error getting stored API credentials password: \(error)")
return nil
}
print("Returning stored API credentials with email: \(email!)")
return APICredentials(email: email!, password: password!)
}
func getAPICredentialsConfirmed() -> Bool {
return defaults.bool(forKey: kAPICredentialsConfirmed)
}
func setAPICredentialsConfirmed(confirmed: Bool) {
defaults.set(confirmed, forKey: kAPICredentialsConfirmed)
}
// MARK: - Extensions
extension String: Error { // Error makes it easy to throw errors as one-liners
func base64Encoded() -> String? {
if let data = self.data(using: .utf8) {
return data.base64EncodedString()
}
return nil
}
func base64Decoded() -> String? {
if let data = Data(base64Encoded: self) {
return String(data: data, encoding: .utf8)
}
return nil
}
}
extension UIColor {
static let confirmedBlue = UIColor(named: "Confirmed Blue") ?? UIColor.tunnelsBlue
static let tunnelsBlue = UIColor(red: 0/255.0, green: 173/255.0, blue: 231/255.0, alpha: 1.0)
static let tunnelsWarning = UIColor(red: 231/255.0, green: 76/255.0, blue: 68/255.0, alpha: 1.0)
static let tunnelsDarkBlue = UIColor(red: 0/255.0, green: 117/255.0, blue: 157/255.0, alpha: 1.0)
static let tunnelsLightBlue = UIColor(red: 223/255.0, green: 243/255.0, blue: 251/255.0, alpha: 1.0)
static let paywallOrange = UIColor(red: 255/255, green: 171/255, blue: 0/255, alpha: 1)
static let paywallNew = UIColor(red: 0.225, green: 0.219, blue: 0.6, alpha: 1.0)
static let borderGray = UIColor(red: 0.6, green: 0.6, blue: 0.6, alpha: 1)
static let borderBlue = UIColor(red: 0, green: 0.678, blue: 0.906, alpha: 1)
static let smallGrey = UIColor(red: 0.8, green: 0.8, blue: 0.8, alpha: 1)
static var purplePaywall = UIColor(red: 134/255.0, green: 26/255.0, blue: 201/255.0, alpha: 1)
static var purplePaywall2 = UIColor(red: 103/255.0, green: 26/255.0, blue: 201/255.0, alpha: 1)
static var extraLightGray = UIColor(red: 242/255.0, green: 244/255.0, blue: 245/255.0, alpha: 1)
static var gradientPink1 = UIColor(red: 0.788, green: 0.102, blue: 0.788, alpha: 1)
static var gradientPink2 = UIColor(red: 0.405, green: 0.103, blue: 0.789, alpha: 1)
static let tunnelsBlueTest = UIColor(red: 0/255.0, green: 173/255.0, blue: 231/255.0, alpha: 0.0)
static let lockdownRed = UIColor(red: 214.0/255.0, green: 87.0/255.0, blue: 75.0/255.0, alpha: 1.0)
static let panelSecondaryBackground = UIColor(named: "Panel Secondary Background")
static let tableCellBackground = UIColor(named: "tableCellBackground")
static let tableCellSelectedBackground = UIColor(named: "tableCellSelectedBackground")
static let disabledGray = UIColor(red: 0.3, green: 0.3, blue: 0.3, alpha: 1)
}
extension UnicodeScalar {
var hexNibble:UInt8 {
let value = self.value
if 48 <= value && value <= 57 {
return UInt8(value - 48)
}
else if 65 <= value && value <= 70 {
return UInt8(value - 55)
}
else if 97 <= value && value <= 102 {
return UInt8(value - 87)
}
fatalError("\(self) not a legal hex nibble")
}
}
extension Data {
init(hex: String) {
let scalars = hex.unicodeScalars
var bytes = Array<UInt8>(repeating: 0, count: (scalars.count + 1) >> 1)
for (index, scalar) in scalars.enumerated() {
var nibble = scalar.hexNibble
if index & 1 == 0 {
nibble <<= 4
}
bytes[index >> 1] |= nibble
}
self = Data(bytes: bytes)
}
}
extension UIDevice {
var modelName: String {
var systemInfo = utsname()
uname(&systemInfo)
let machineMirror = Mirror(reflecting: systemInfo.machine)
let identifier = machineMirror.children.reduce("") { identifier, element in
guard let value = element.value as? Int8, value != 0 else { return identifier }
return identifier + String(UnicodeScalar(UInt8(value)))
}
return identifier
}
}
enum AppConfiguration {
case Debug
case TestFlight
case AppStore
}
struct Config {
private static let isTestFlight = Bundle.main.appStoreReceiptURL?.lastPathComponent == "sandboxReceipt"
static var isDebug: Bool {
#if DEBUG
return true
#else
return false
#endif
}
static var appConfiguration: AppConfiguration {
if isDebug {
return .Debug
} else if isTestFlight {
return .TestFlight
} else {
return .AppStore
}
}
}
// MARK: - Fonts
let fontRegular12 = UIFont(name: "Montserrat-Regular", size: 12)!
let fontRegular14 = UIFont(name: "Montserrat-Regular", size: 14)!
let fontRegular15 = UIFont(name: "Montserrat-Regular", size: 15)!
let fontRegular17 = UIFont(name: "Montserrat-Regular", size: 17)!
let fontMedium14 = UIFont(name: "Montserrat-Medium", size: 14)!
let fontMedium11 = UIFont(name: "Montserrat-Medium", size: 11)!
let fontMedium13 = UIFont(name: "Montserrat-Medium", size: 13)!
let fontMedium15 = UIFont(name: "Montserrat-Medium", size: 15)!
let fontMedium16 = UIFont(name: "Montserrat-Medium", size: 16)!
let fontMedium17 = UIFont(name: "Montserrat-Medium", size: 17)!
let fontMedium18 = UIFont(name: "Montserrat-Medium", size: 18)!
let fontSemiBold13 = UIFont(name: "Montserrat-SemiBold", size: 13)!
let fontSemiBold15 = UIFont(name: "Montserrat-SemiBold", size: 15)!
let fontSemiBold15_5 = UIFont(name: "Montserrat-SemiBold", size: 15.5)!
let fontSemiBold17 = UIFont(name: "Montserrat-SemiBold", size: 17)!
let fontSemiBold22 = UIFont(name: "Montserrat-SemiBold", size: 22)!
let fontBold11 = UIFont(name: "Montserrat-Bold", size: 11)!
let fontBold13 = UIFont(name: "Montserrat-Bold", size: 13)!
let fontBold15 = UIFont(name: "Montserrat-Bold", size: 15)!
let fontBold17 = UIFont(name: "Montserrat-Bold", size: 17)!
let fontBold18 = UIFont(name: "Montserrat-Bold", size: 18)!
let fontBold22 = UIFont(name: "Montserrat-Bold", size: 22)!
let fontBold24 = UIFont(name: "Montserrat-Bold", size: 24)!
let fontBold26 = UIFont(name: "Montserrat-Bold", size: 26)!
let fontBold28 = UIFont(name: "Montserrat-Bold", size: 28)!
let fontBold34 = UIFont(name: "Montserrat-Bold", size: 34)!