mirror of
https://github.com/confirmedcode/Lockdown-iOS.git
synced 2025-12-16 12:00:16 +01:00
322 lines
11 KiB
Swift
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)!
|