Files
lockdown-iOS-mirror/Shared.swift
2024-11-27 12:23:14 +02:00

322 lines
11 KiB
Swift

//
// 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)!