Compare commits
108 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4ded3f6bfe | |||
| b51113f680 | |||
| be96dea04a | |||
| a786f5df60 | |||
| 9a483a46fa | |||
| 5d2a337332 | |||
| facf776602 | |||
| d3400e3a80 | |||
| 92517bd21e | |||
| 761f635e16 | |||
| 44704ba892 | |||
| 9231c03513 | |||
| 27b32e60b2 | |||
| 9d5b376dcf | |||
| 8fd4883d7e | |||
| d414cec9aa | |||
| 54e3333b72 | |||
| 9f8d0e24df | |||
| 3de7c99301 | |||
| d4fd17cd8f | |||
| d875266db5 | |||
| d696e31b6e | |||
| 90acf2b220 | |||
| 27ef0c6dba | |||
| 8f67435d4a | |||
| b4ebe2440f | |||
| d440a91b0e | |||
| 9e909a3294 | |||
| 75bcf97ab2 | |||
| 0edde8b46f | |||
| bcc34e0bb6 | |||
| 90b41aed89 | |||
| 7930b94981 | |||
| 54a89f6a0e | |||
| 8976a53b05 | |||
| 9849dedf1d | |||
| 547077a808 | |||
| 0b0898dc3c | |||
| 9f9d1ffed8 | |||
| 5a044e4129 | |||
| 35f0ada8a9 | |||
| 39e7ee07ac | |||
| 5a1c9598f1 | |||
| 101a45b6f1 | |||
| fd527f73e6 | |||
| de6aa3eb58 | |||
| c9eafd82ac | |||
| ec57408570 | |||
| 9c38a1b897 | |||
| b34625f511 | |||
| 2e356d3d8f | |||
| 697d449dc8 | |||
| 4f9f61f7a7 | |||
| bceb0a827d | |||
| 2329f712cf | |||
| d2c38702c8 | |||
| def921801f | |||
| 41e006a407 | |||
| 384b514290 | |||
| a6858bd126 | |||
| ef7de2500f | |||
| 6099975b71 | |||
| 828756e8ba | |||
| 4deaf905c1 | |||
| 76c8487a56 | |||
| a05f1233f9 | |||
| 95b833c754 | |||
| 8c057bf928 | |||
| ddf8ade9c6 | |||
| 4cb21b5eb0 | |||
| a03df7d8cc | |||
| 57f66f16f8 | |||
| 737f847c0d | |||
| 671a594945 | |||
| 3646430528 | |||
| e9bd6e576f | |||
| 35300d1c5f | |||
| 112545248e | |||
| 78e6ecc4bc | |||
| 174a6e8e32 | |||
| 20bcabbca4 | |||
| 0a3554cedd | |||
| 2acc7db63d | |||
| 31af7049fc | |||
| 52062a45c1 | |||
| 30406dec6d | |||
| edde27a0a0 | |||
| cfff596c30 | |||
| ba1c968cdf | |||
| c48406ac38 | |||
| 14437477e6 | |||
| 68d928192b | |||
| 028e76eb3f | |||
| cb0c965294 | |||
| d7ce621cb2 | |||
| a1ca4f6eb5 | |||
| 437f0dc46d | |||
| 547eabb4ae | |||
| bb16d3ebc8 | |||
| 1b6170cbc9 | |||
| 4c37a4b7a7 | |||
| 226166bdaf | |||
| 80fa72cabc | |||
| d976d159d0 | |||
| 84ca7fcf40 | |||
| f120a6aab0 | |||
| 0d8108d8da | |||
| e072ebee58 |
@@ -31,6 +31,10 @@ xcuserdata
|
||||
*.hmap
|
||||
*.ipa
|
||||
|
||||
# Swift Package Manager
|
||||
.swiftpm
|
||||
.build/
|
||||
|
||||
# Fastlane
|
||||
*.app.dSYM.zip
|
||||
*.mobileprovision
|
||||
@@ -41,7 +45,7 @@ Preview.html
|
||||
output
|
||||
|
||||
# Wireguard specific
|
||||
WireGuard/WireGuard/Config/Developer.xcconfig
|
||||
Sources/WireGuardApp/Config/Developer.xcconfig
|
||||
|
||||
# Vim
|
||||
.*.sw*
|
||||
|
||||
@@ -7,6 +7,7 @@ disabled_rules:
|
||||
- type_body_length
|
||||
- function_body_length
|
||||
- nesting
|
||||
- inclusive_language
|
||||
opt_in_rules:
|
||||
- empty_count
|
||||
- empty_string
|
||||
@@ -1,4 +1,4 @@
|
||||
Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
|
||||
Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
|
||||
@@ -136,5 +136,5 @@ Here's an example WireGuard configuration payload dictionary:
|
||||
|
||||
Configurations added via .mobileconfig will not be migrated into keychain until the WireGuard application is opened once.
|
||||
|
||||
[wg-quick(8)]: https://git.zx2c4.com/WireGuard/about/src/tools/man/wg-quick.8
|
||||
[wg(8)]: https://git.zx2c4.com/WireGuard/about/src/tools/man/wg.8
|
||||
[wg-quick(8)]: https://git.zx2c4.com/wireguard-tools/about/src/man/wg-quick.8
|
||||
[wg(8)]: https://git.zx2c4.com/wireguard-tools/about/src/man/wg.8
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
// swift-tools-version:5.3
|
||||
// The swift-tools-version declares the minimum version of Swift required to build this package.
|
||||
|
||||
import PackageDescription
|
||||
|
||||
let package = Package(
|
||||
name: "WireGuardKit",
|
||||
platforms: [
|
||||
.macOS(.v10_14),
|
||||
.iOS(.v12)
|
||||
],
|
||||
products: [
|
||||
.library(name: "WireGuardKit", targets: ["WireGuardKit"])
|
||||
],
|
||||
dependencies: [],
|
||||
targets: [
|
||||
.target(
|
||||
name: "WireGuardKit",
|
||||
dependencies: ["WireGuardKitGo", "WireGuardKitC"]
|
||||
),
|
||||
.target(
|
||||
name: "WireGuardKitC",
|
||||
dependencies: [],
|
||||
publicHeadersPath: "."
|
||||
),
|
||||
.target(
|
||||
name: "WireGuardKitGo",
|
||||
dependencies: [],
|
||||
exclude: [
|
||||
"goruntime-boottime-over-monotonic.diff",
|
||||
"go.mod",
|
||||
"go.sum",
|
||||
"api-ios.go",
|
||||
"Makefile"
|
||||
],
|
||||
publicHeadersPath: ".",
|
||||
linkerSettings: [.linkedLibrary("wg-go")]
|
||||
)
|
||||
]
|
||||
)
|
||||
@@ -14,11 +14,11 @@ $ cd wireguard-apple
|
||||
- Rename and populate developer team ID file:
|
||||
|
||||
```
|
||||
$ cp WireGuard/WireGuard/Config/Developer.xcconfig.template WireGuard/WireGuard/Config/Developer.xcconfig
|
||||
$ vim WireGuard/WireGuard/Config/Developer.xcconfig
|
||||
$ cp Sources/WireGuardApp/Config/Developer.xcconfig.template Sources/WireGuardApp/Config/Developer.xcconfig
|
||||
$ vim Sources/WireGuardApp/Config/Developer.xcconfig
|
||||
```
|
||||
|
||||
- Install swiftlint and go:
|
||||
- Install swiftlint and go 1.15:
|
||||
|
||||
```
|
||||
$ brew install swiftlint go
|
||||
@@ -27,11 +27,57 @@ $ brew install swiftlint go
|
||||
- Open project in Xcode:
|
||||
|
||||
```
|
||||
$ open ./WireGuard/WireGuard.xcodeproj
|
||||
$ open WireGuard.xcodeproj
|
||||
```
|
||||
|
||||
- Flip switches, press buttons, and make whirling noises until Xcode builds it.
|
||||
|
||||
## WireGuardKit integration
|
||||
|
||||
1. Open your Xcode project and add the Swift package with the following URL:
|
||||
|
||||
```
|
||||
https://git.zx2c4.com/wireguard-apple
|
||||
```
|
||||
|
||||
2. `WireGuardKit` links against `wireguard-go-bridge` library, but it cannot build it automatically
|
||||
due to Swift package manager limitations. So it needs a little help from a developer.
|
||||
Please follow the instructions below to create a build target(s) for `wireguard-go-bridge`.
|
||||
|
||||
- In Xcode, click File -> New -> Target. Switch to "Other" tab and choose "External Build
|
||||
System".
|
||||
- Type in `WireGuardGoBridge<PLATFORM>` under the "Product name", replacing the `<PLATFORM>`
|
||||
placeholder with the name of the platform. For example, when targeting macOS use `macOS`, or
|
||||
when targeting iOS use `iOS`.
|
||||
Make sure the build tool is set to: `/usr/bin/make` (default).
|
||||
- In the appeared "Info" tab of a newly created target, type in the "Directory" path under
|
||||
the "External Build Tool Configuration":
|
||||
|
||||
```
|
||||
$BUILD_DIR/../../SourcePackages/checkouts/wireguard-apple/Sources/WireGuardKitGo
|
||||
```
|
||||
|
||||
- Switch to "Build Settings" and find `SDKROOT`.
|
||||
Type in `macosx` if you target macOS, or type in `iphoneos` if you target iOS.
|
||||
|
||||
3. Go to Xcode project settings and locate your network extension target and switch to
|
||||
"Build Phases" tab.
|
||||
|
||||
- Locate "Dependencies" section and hit "+" to add `WireGuardGoBridge<PLATFORM>` replacing
|
||||
the `<PLATFORM>` placeholder with the name of platform matching the network extension
|
||||
deployment target (i.e macOS or iOS).
|
||||
|
||||
- Locate the "Link with binary libraries" section and hit "+" to add `WireGuardKit`.
|
||||
|
||||
4. In Xcode project settings, locate your main bundle app and switch to "Build Phases" tab.
|
||||
Locate the "Link with binary libraries" section and hit "+" to add `WireGuardKit`.
|
||||
|
||||
5. iOS only: Locate Bitcode settings under your application target, Build settings -> Enable Bitcode,
|
||||
change the corresponding value to "No".
|
||||
|
||||
Note that if you ship your app for both iOS and macOS, make sure to repeat the steps 2-4 twice,
|
||||
once per platform.
|
||||
|
||||
## MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
|
||||
// Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
|
||||
|
||||
import Foundation
|
||||
import os.log
|
||||
@@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
|
||||
// Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
|
||||
|
||||
import Foundation
|
||||
import Security
|
||||
@@ -7,9 +7,9 @@ import Security
|
||||
class Keychain {
|
||||
static func openReference(called ref: Data) -> String? {
|
||||
var result: CFTypeRef?
|
||||
let ret = SecItemCopyMatching([kSecClass as String: kSecClassGenericPassword,
|
||||
kSecValuePersistentRef as String: ref,
|
||||
kSecReturnData as String: true] as CFDictionary,
|
||||
let ret = SecItemCopyMatching([kSecClass: kSecClassGenericPassword,
|
||||
kSecValuePersistentRef: ref,
|
||||
kSecReturnData: true] as CFDictionary,
|
||||
&result)
|
||||
if ret != errSecSuccess || result == nil {
|
||||
wg_log(.error, message: "Unable to open config from keychain: \(ret)")
|
||||
@@ -21,27 +21,28 @@ class Keychain {
|
||||
|
||||
static func makeReference(containing value: String, called name: String, previouslyReferencedBy oldRef: Data? = nil) -> Data? {
|
||||
var ret: OSStatus
|
||||
guard var id = Bundle.main.bundleIdentifier else {
|
||||
guard var bundleIdentifier = Bundle.main.bundleIdentifier else {
|
||||
wg_log(.error, staticMessage: "Unable to determine bundle identifier")
|
||||
return nil
|
||||
}
|
||||
if id.hasSuffix(".network-extension") {
|
||||
id.removeLast(".network-extension".count)
|
||||
if bundleIdentifier.hasSuffix(".network-extension") {
|
||||
bundleIdentifier.removeLast(".network-extension".count)
|
||||
}
|
||||
var items: [String: Any] = [kSecClass as String: kSecClassGenericPassword,
|
||||
kSecAttrLabel as String: "WireGuard Tunnel: " + name,
|
||||
kSecAttrAccount as String: name + ": " + UUID().uuidString,
|
||||
kSecAttrDescription as String: "wg-quick(8) config",
|
||||
kSecAttrService as String: id,
|
||||
kSecValueData as String: value.data(using: .utf8) as Any,
|
||||
kSecReturnPersistentRef as String: true]
|
||||
let itemLabel = "WireGuard Tunnel: \(name)"
|
||||
var items: [CFString: Any] = [kSecClass: kSecClassGenericPassword,
|
||||
kSecAttrLabel: itemLabel,
|
||||
kSecAttrAccount: name + ": " + UUID().uuidString,
|
||||
kSecAttrDescription: "wg-quick(8) config",
|
||||
kSecAttrService: bundleIdentifier,
|
||||
kSecValueData: value.data(using: .utf8) as Any,
|
||||
kSecReturnPersistentRef: true]
|
||||
|
||||
#if os(iOS)
|
||||
items[kSecAttrAccessGroup as String] = FileManager.appGroupId
|
||||
items[kSecAttrAccessible as String] = kSecAttrAccessibleAfterFirstUnlock
|
||||
items[kSecAttrAccessGroup] = FileManager.appGroupId
|
||||
items[kSecAttrAccessible] = kSecAttrAccessibleAfterFirstUnlock
|
||||
#elseif os(macOS)
|
||||
items[kSecAttrSynchronizable as String] = false
|
||||
items[kSecAttrAccessible as String] = kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly
|
||||
items[kSecAttrSynchronizable] = false
|
||||
items[kSecAttrAccessible] = kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly
|
||||
|
||||
guard let extensionPath = Bundle.main.builtInPlugInsURL?.appendingPathComponent("WireGuardNetworkExtension.appex").path else {
|
||||
wg_log(.error, staticMessage: "Unable to determine app extension path")
|
||||
@@ -60,14 +61,12 @@ class Keychain {
|
||||
return nil
|
||||
}
|
||||
var access: SecAccess?
|
||||
ret = SecAccessCreate((items[kSecAttrLabel as String] as? String)! as CFString,
|
||||
[extensionApp!, mainApp!] as CFArray,
|
||||
&access)
|
||||
ret = SecAccessCreate(itemLabel as CFString, [extensionApp!, mainApp!] as CFArray, &access)
|
||||
if ret != errSecSuccess || access == nil {
|
||||
wg_log(.error, message: "Unable to create keychain ACL object: \(ret)")
|
||||
return nil
|
||||
}
|
||||
items[kSecAttrAccess as String] = access!
|
||||
items[kSecAttrAccess] = access!
|
||||
#else
|
||||
#error("Unimplemented")
|
||||
#endif
|
||||
@@ -85,7 +84,7 @@ class Keychain {
|
||||
}
|
||||
|
||||
static func deleteReference(called ref: Data) {
|
||||
let ret = SecItemDelete([kSecValuePersistentRef as String: ref] as CFDictionary)
|
||||
let ret = SecItemDelete([kSecValuePersistentRef: ref] as CFDictionary)
|
||||
if ret != errSecSuccess {
|
||||
wg_log(.error, message: "Unable to delete config from keychain: \(ret)")
|
||||
}
|
||||
@@ -93,10 +92,10 @@ class Keychain {
|
||||
|
||||
static func deleteReferences(except whitelist: Set<Data>) {
|
||||
var result: CFTypeRef?
|
||||
let ret = SecItemCopyMatching([kSecClass as String: kSecClassGenericPassword,
|
||||
kSecAttrService as String: Bundle.main.bundleIdentifier as Any,
|
||||
kSecMatchLimit as String: kSecMatchLimitAll,
|
||||
kSecReturnPersistentRef as String: true] as CFDictionary,
|
||||
let ret = SecItemCopyMatching([kSecClass: kSecClassGenericPassword,
|
||||
kSecAttrService: Bundle.main.bundleIdentifier as Any,
|
||||
kSecMatchLimit: kSecMatchLimitAll,
|
||||
kSecReturnPersistentRef: true] as CFDictionary,
|
||||
&result)
|
||||
if ret != errSecSuccess || result == nil {
|
||||
return
|
||||
@@ -110,8 +109,8 @@ class Keychain {
|
||||
}
|
||||
|
||||
static func verifyReference(called ref: Data) -> Bool {
|
||||
return SecItemCopyMatching([kSecClass as String: kSecClassGenericPassword,
|
||||
kSecValuePersistentRef as String: ref] as CFDictionary,
|
||||
nil) == errSecSuccess
|
||||
return SecItemCopyMatching([kSecClass: kSecClassGenericPassword,
|
||||
kSecValuePersistentRef: ref] as CFDictionary,
|
||||
nil) != errSecItemNotFound
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
|
||||
// Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
|
||||
|
||||
import Foundation
|
||||
import os.log
|
||||
@@ -49,8 +49,8 @@ public class Logger {
|
||||
if let appBuild = Bundle.main.infoDictionary?["CFBundleVersion"] as? String {
|
||||
appVersion += " (\(appBuild))"
|
||||
}
|
||||
let goBackendVersion = WIREGUARD_GO_VERSION
|
||||
Logger.global?.log(message: "App version: \(appVersion); Go backend version: \(goBackendVersion)")
|
||||
|
||||
Logger.global?.log(message: "App version: \(appVersion)")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
@@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
|
||||
*/
|
||||
|
||||
#ifndef RINGLOGGER_H
|
||||
@@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
|
||||
// Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
|
||||
|
||||
import NetworkExtension
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
|
||||
// Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
|
||||
|
||||
import Foundation
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
|
||||
// Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
|
||||
|
||||
import Foundation
|
||||
|
||||
@@ -111,7 +111,7 @@ extension TunnelConfiguration {
|
||||
}
|
||||
|
||||
let peerPublicKeysArray = peerConfigurations.map { $0.publicKey }
|
||||
let peerPublicKeysSet = Set<Data>(peerPublicKeysArray)
|
||||
let peerPublicKeysSet = Set<PublicKey>(peerPublicKeysArray)
|
||||
if peerPublicKeysArray.count != peerPublicKeysSet.count {
|
||||
throw ParseError.multiplePeersWithSamePublicKey
|
||||
}
|
||||
@@ -125,9 +125,7 @@ extension TunnelConfiguration {
|
||||
|
||||
func asWgQuickConfig() -> String {
|
||||
var output = "[Interface]\n"
|
||||
if let privateKey = interface.privateKey.base64Key() {
|
||||
output.append("PrivateKey = \(privateKey)\n")
|
||||
}
|
||||
output.append("PrivateKey = \(interface.privateKey.base64Key)\n")
|
||||
if let listenPort = interface.listenPort {
|
||||
output.append("ListenPort = \(listenPort)\n")
|
||||
}
|
||||
@@ -135,8 +133,10 @@ extension TunnelConfiguration {
|
||||
let addressString = interface.addresses.map { $0.stringRepresentation }.joined(separator: ", ")
|
||||
output.append("Address = \(addressString)\n")
|
||||
}
|
||||
if !interface.dns.isEmpty {
|
||||
let dnsString = interface.dns.map { $0.stringRepresentation }.joined(separator: ", ")
|
||||
if !interface.dns.isEmpty || !interface.dnsSearch.isEmpty {
|
||||
var dnsLine = interface.dns.map { $0.stringRepresentation }
|
||||
dnsLine.append(contentsOf: interface.dnsSearch)
|
||||
let dnsString = dnsLine.joined(separator: ", ")
|
||||
output.append("DNS = \(dnsString)\n")
|
||||
}
|
||||
if let mtu = interface.mtu {
|
||||
@@ -145,10 +145,8 @@ extension TunnelConfiguration {
|
||||
|
||||
for peer in peers {
|
||||
output.append("\n[Peer]\n")
|
||||
if let publicKey = peer.publicKey.base64Key() {
|
||||
output.append("PublicKey = \(publicKey)\n")
|
||||
}
|
||||
if let preSharedKey = peer.preSharedKey?.base64Key() {
|
||||
output.append("PublicKey = \(peer.publicKey.base64Key)\n")
|
||||
if let preSharedKey = peer.preSharedKey?.base64Key {
|
||||
output.append("PresharedKey = \(preSharedKey)\n")
|
||||
}
|
||||
if !peer.allowedIPs.isEmpty {
|
||||
@@ -170,7 +168,7 @@ extension TunnelConfiguration {
|
||||
guard let privateKeyString = attributes["privatekey"] else {
|
||||
throw ParseError.interfaceHasNoPrivateKey
|
||||
}
|
||||
guard let privateKey = Data(base64Key: privateKeyString), privateKey.count == TunnelConfiguration.keyLength else {
|
||||
guard let privateKey = PrivateKey(base64Key: privateKeyString) else {
|
||||
throw ParseError.interfaceHasInvalidPrivateKey(privateKeyString)
|
||||
}
|
||||
var interface = InterfaceConfiguration(privateKey: privateKey)
|
||||
@@ -192,13 +190,16 @@ extension TunnelConfiguration {
|
||||
}
|
||||
if let dnsString = attributes["dns"] {
|
||||
var dnsServers = [DNSServer]()
|
||||
var dnsSearch = [String]()
|
||||
for dnsServerString in dnsString.splitToArray(trimmingCharacters: .whitespacesAndNewlines) {
|
||||
guard let dnsServer = DNSServer(from: dnsServerString) else {
|
||||
throw ParseError.interfaceHasInvalidDNS(dnsServerString)
|
||||
if let dnsServer = DNSServer(from: dnsServerString) {
|
||||
dnsServers.append(dnsServer)
|
||||
} else {
|
||||
dnsSearch.append(dnsServerString)
|
||||
}
|
||||
dnsServers.append(dnsServer)
|
||||
}
|
||||
interface.dns = dnsServers
|
||||
interface.dnsSearch = dnsSearch
|
||||
}
|
||||
if let mtuString = attributes["mtu"] {
|
||||
guard let mtu = UInt16(mtuString) else {
|
||||
@@ -213,12 +214,12 @@ extension TunnelConfiguration {
|
||||
guard let publicKeyString = attributes["publickey"] else {
|
||||
throw ParseError.peerHasNoPublicKey
|
||||
}
|
||||
guard let publicKey = Data(base64Key: publicKeyString), publicKey.count == TunnelConfiguration.keyLength else {
|
||||
guard let publicKey = PublicKey(base64Key: publicKeyString) else {
|
||||
throw ParseError.peerHasInvalidPublicKey(publicKeyString)
|
||||
}
|
||||
var peer = PeerConfiguration(publicKey: publicKey)
|
||||
if let preSharedKeyString = attributes["presharedkey"] {
|
||||
guard let preSharedKey = Data(base64Key: preSharedKeyString), preSharedKey.count == TunnelConfiguration.keyLength else {
|
||||
guard let preSharedKey = PreSharedKey(base64Key: preSharedKeyString) else {
|
||||
throw ParseError.peerHasInvalidPreSharedKey(preSharedKeyString)
|
||||
}
|
||||
peer.preSharedKey = preSharedKey
|
||||
@@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
|
||||
// Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
|
||||
|
||||
// iOS permission prompts
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
|
||||
// Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
|
||||
|
||||
// Generic alert action names
|
||||
|
||||
@@ -349,6 +349,8 @@
|
||||
|
||||
"macButtonDeleteTunnels (%d)" = "Delete %d tunnels";
|
||||
|
||||
"macButtonEdit" = "Edit";
|
||||
|
||||
// Mac detail/edit view fields
|
||||
|
||||
"macFieldKey (%@)" = "%@:";
|
||||
@@ -437,3 +439,7 @@
|
||||
"macAppStoreUpdatingAlertMessage" = "App Store would like to update WireGuard";
|
||||
"macAppStoreUpdatingAlertInfoWithOnDemand (%@)" = "Please disable on-demand for tunnel ‘%@’, deactivate it, and then continue updating in App Store.";
|
||||
"macAppStoreUpdatingAlertInfoWithoutOnDemand (%@)" = "Please deactivate tunnel ‘%@’ and then continue updating in App Store.";
|
||||
|
||||
// Donation
|
||||
|
||||
"donateLink" = "♥ Donate to the WireGuard Project";
|
||||
@@ -0,0 +1,2 @@
|
||||
VERSION_NAME = 1.0.10
|
||||
VERSION_ID = 19
|
||||
@@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
|
||||
// Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
|
||||
|
||||
import Foundation
|
||||
|
||||
|
Before Width: | Height: | Size: 953 B After Width: | Height: | Size: 953 B |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.3 KiB |
@@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
|
||||
// Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
|
||||
|
||||
import NetworkExtension
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
|
||||
// Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
|
||||
|
||||
import NetworkExtension
|
||||
|
||||
@@ -26,11 +26,11 @@ class MockTunnels {
|
||||
static func createMockTunnels() -> [NETunnelProviderManager] {
|
||||
return tunnelNames.map { tunnelName -> NETunnelProviderManager in
|
||||
|
||||
var interface = InterfaceConfiguration(privateKey: Curve25519.generatePrivateKey())
|
||||
var interface = InterfaceConfiguration(privateKey: PrivateKey())
|
||||
interface.addresses = [IPAddressRange(from: String(format: address, Int.random(in: 1 ... 10), Int.random(in: 1 ... 254)))!]
|
||||
interface.dns = dnsServers.map { DNSServer(from: $0)! }
|
||||
|
||||
var peer = PeerConfiguration(publicKey: Curve25519.generatePublicKey(fromPrivateKey: Curve25519.generatePrivateKey()))
|
||||
var peer = PeerConfiguration(publicKey: PrivateKey().publicKey)
|
||||
peer.endpoint = Endpoint(from: endpoint)
|
||||
peer.allowedIPs = [IPAddressRange(from: allowedIPs)!]
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
|
||||
// Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
|
||||
|
||||
import Foundation
|
||||
|
||||
@@ -67,13 +67,14 @@ extension TunnelConfiguration {
|
||||
}
|
||||
|
||||
let peerPublicKeysArray = peerConfigurations.map { $0.publicKey }
|
||||
let peerPublicKeysSet = Set<Data>(peerPublicKeysArray)
|
||||
let peerPublicKeysSet = Set<PublicKey>(peerPublicKeysArray)
|
||||
if peerPublicKeysArray.count != peerPublicKeysSet.count {
|
||||
throw ParseError.multiplePeersWithSamePublicKey
|
||||
}
|
||||
|
||||
interfaceConfiguration?.addresses = base?.interface.addresses ?? []
|
||||
interfaceConfiguration?.dns = base?.interface.dns ?? []
|
||||
interfaceConfiguration?.dnsSearch = base?.interface.dnsSearch ?? []
|
||||
interfaceConfiguration?.mtu = base?.interface.mtu
|
||||
|
||||
if let interfaceConfiguration = interfaceConfiguration {
|
||||
@@ -87,7 +88,7 @@ extension TunnelConfiguration {
|
||||
guard let privateKeyString = attributes["private_key"] else {
|
||||
throw ParseError.interfaceHasNoPrivateKey
|
||||
}
|
||||
guard let privateKey = Data(hexKey: privateKeyString), privateKey.count == TunnelConfiguration.keyLength else {
|
||||
guard let privateKey = PrivateKey(hexKey: privateKeyString) else {
|
||||
throw ParseError.interfaceHasInvalidPrivateKey(privateKeyString)
|
||||
}
|
||||
var interface = InterfaceConfiguration(privateKey: privateKey)
|
||||
@@ -106,18 +107,18 @@ extension TunnelConfiguration {
|
||||
guard let publicKeyString = attributes["public_key"] else {
|
||||
throw ParseError.peerHasNoPublicKey
|
||||
}
|
||||
guard let publicKey = Data(hexKey: publicKeyString), publicKey.count == TunnelConfiguration.keyLength else {
|
||||
guard let publicKey = PublicKey(hexKey: publicKeyString) else {
|
||||
throw ParseError.peerHasInvalidPublicKey(publicKeyString)
|
||||
}
|
||||
var peer = PeerConfiguration(publicKey: publicKey)
|
||||
if let preSharedKeyString = attributes["preshared_key"] {
|
||||
guard let preSharedKey = Data(hexKey: preSharedKeyString), preSharedKey.count == TunnelConfiguration.keyLength else {
|
||||
guard let preSharedKey = PreSharedKey(hexKey: preSharedKeyString) else {
|
||||
throw ParseError.peerHasInvalidPreSharedKey(preSharedKeyString)
|
||||
}
|
||||
// TODO(zx2c4): does the compiler optimize this away?
|
||||
var accumulator: UInt8 = 0
|
||||
for index in 0..<preSharedKey.count {
|
||||
accumulator |= preSharedKey[index]
|
||||
for index in 0..<preSharedKey.rawValue.count {
|
||||
accumulator |= preSharedKey.rawValue[index]
|
||||
}
|
||||
if accumulator != 0 {
|
||||
peer.preSharedKey = preSharedKey
|
||||
@@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
|
||||
// Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
|
||||
|
||||
import NetworkExtension
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
|
||||
// Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
|
||||
|
||||
import Foundation
|
||||
import NetworkExtension
|
||||
@@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
|
||||
// Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
|
||||
|
||||
import Foundation
|
||||
import NetworkExtension
|
||||
@@ -70,6 +70,7 @@ class TunnelsManager {
|
||||
if let ref = passwordRef {
|
||||
refs.insert(ref)
|
||||
} else {
|
||||
wg_log(.info, message: "Removing orphaned tunnel with non-verifying keychain entry: \(tunnelManager.localizedDescription ?? "<unknown>")")
|
||||
tunnelManager.removeFromPreferences { _ in }
|
||||
tunnelManagers.remove(at: index)
|
||||
}
|
||||
@@ -448,8 +449,8 @@ class TunnelsManager {
|
||||
}
|
||||
}
|
||||
|
||||
static func tunnelNameIsLessThan(_ a: String, _ b: String) -> Bool {
|
||||
return a.compare(b, options: [.caseInsensitive, .diacriticInsensitive, .widthInsensitive, .numeric]) == .orderedAscending
|
||||
static func tunnelNameIsLessThan(_ lhs: String, _ rhs: String) -> Bool {
|
||||
return lhs.compare(rhs, options: [.caseInsensitive, .diacriticInsensitive, .widthInsensitive, .numeric]) == .orderedAscending
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
|
||||
// Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
|
||||
|
||||
import Foundation
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
|
||||
// Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
|
||||
|
||||
protocol ErrorPresenterProtocol {
|
||||
static func showErrorAlert(title: String, message: String, from sourceVC: AnyObject?, onPresented: (() -> Void)?, onDismissal: (() -> Void)?)
|
||||
@@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
|
||||
// Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
|
||||
|
||||
import Foundation
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
|
||||
// Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
|
||||
|
||||
import Foundation
|
||||
import LocalAuthentication
|
||||
@@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
|
||||
// Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
|
||||
|
||||
import Foundation
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
|
||||
// Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
|
||||
|
||||
import Foundation
|
||||
|
||||
@@ -109,9 +109,9 @@ class TunnelViewModel {
|
||||
scratchpad[field] = stringValue
|
||||
}
|
||||
if field == .privateKey {
|
||||
if stringValue.count == TunnelViewModel.keyLengthInBase64, let privateKey = Data(base64Key: stringValue), privateKey.count == TunnelConfiguration.keyLength {
|
||||
let publicKey = Curve25519.generatePublicKey(fromPrivateKey: privateKey).base64Key() ?? ""
|
||||
scratchpad[.publicKey] = publicKey
|
||||
if stringValue.count == TunnelViewModel.keyLengthInBase64,
|
||||
let privateKey = PrivateKey(base64Key: stringValue) {
|
||||
scratchpad[.publicKey] = privateKey.publicKey.base64Key
|
||||
} else {
|
||||
scratchpad.removeValue(forKey: .publicKey)
|
||||
}
|
||||
@@ -128,8 +128,8 @@ class TunnelViewModel {
|
||||
private static func createScratchPad(from config: InterfaceConfiguration, name: String) -> [InterfaceField: String] {
|
||||
var scratchpad = [InterfaceField: String]()
|
||||
scratchpad[.name] = name
|
||||
scratchpad[.privateKey] = config.privateKey.base64Key() ?? ""
|
||||
scratchpad[.publicKey] = config.publicKey.base64Key() ?? ""
|
||||
scratchpad[.privateKey] = config.privateKey.base64Key
|
||||
scratchpad[.publicKey] = config.privateKey.publicKey.base64Key
|
||||
if !config.addresses.isEmpty {
|
||||
scratchpad[.addresses] = config.addresses.map { $0.stringRepresentation }.joined(separator: ", ")
|
||||
}
|
||||
@@ -139,8 +139,10 @@ class TunnelViewModel {
|
||||
if let mtu = config.mtu {
|
||||
scratchpad[.mtu] = String(mtu)
|
||||
}
|
||||
if !config.dns.isEmpty {
|
||||
scratchpad[.dns] = config.dns.map { $0.stringRepresentation }.joined(separator: ", ")
|
||||
if !config.dns.isEmpty || !config.dnsSearch.isEmpty {
|
||||
var dns = config.dns.map { $0.stringRepresentation }
|
||||
dns.append(contentsOf: config.dnsSearch)
|
||||
scratchpad[.dns] = dns.joined(separator: ", ")
|
||||
}
|
||||
return scratchpad
|
||||
}
|
||||
@@ -158,7 +160,7 @@ class TunnelViewModel {
|
||||
fieldsWithError.insert(.privateKey)
|
||||
return .error(tr("alertInvalidInterfaceMessagePrivateKeyRequired"))
|
||||
}
|
||||
guard let privateKey = Data(base64Key: privateKeyString), privateKey.count == TunnelConfiguration.keyLength else {
|
||||
guard let privateKey = PrivateKey(base64Key: privateKeyString) else {
|
||||
fieldsWithError.insert(.privateKey)
|
||||
return .error(tr("alertInvalidInterfaceMessagePrivateKeyInvalid"))
|
||||
}
|
||||
@@ -194,15 +196,16 @@ class TunnelViewModel {
|
||||
}
|
||||
if let dnsString = scratchpad[.dns] {
|
||||
var dnsServers = [DNSServer]()
|
||||
var dnsSearch = [String]()
|
||||
for dnsServerString in dnsString.splitToArray(trimmingCharacters: .whitespacesAndNewlines) {
|
||||
if let dnsServer = DNSServer(from: dnsServerString) {
|
||||
dnsServers.append(dnsServer)
|
||||
} else {
|
||||
fieldsWithError.insert(.dns)
|
||||
errorMessages.append(tr("alertInvalidInterfaceMessageDNSInvalid"))
|
||||
dnsSearch.append(dnsServerString)
|
||||
}
|
||||
}
|
||||
config.dns = dnsServers
|
||||
config.dnsSearch = dnsSearch
|
||||
}
|
||||
|
||||
guard errorMessages.isEmpty else { return .error(errorMessages.first!) }
|
||||
@@ -251,12 +254,12 @@ class TunnelViewModel {
|
||||
var scratchpad = [PeerField: String]()
|
||||
var fieldsWithError = Set<PeerField>()
|
||||
var validatedConfiguration: PeerConfiguration?
|
||||
var publicKey: Data? {
|
||||
var publicKey: PublicKey? {
|
||||
if let validatedConfiguration = validatedConfiguration {
|
||||
return validatedConfiguration.publicKey
|
||||
}
|
||||
if let scratchPadPublicKey = scratchpad[.publicKey] {
|
||||
return Data(base64Key: scratchPadPublicKey)
|
||||
return PublicKey(base64Key: scratchPadPublicKey)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -301,10 +304,8 @@ class TunnelViewModel {
|
||||
|
||||
private static func createScratchPad(from config: PeerConfiguration) -> [PeerField: String] {
|
||||
var scratchpad = [PeerField: String]()
|
||||
if let publicKey = config.publicKey.base64Key() {
|
||||
scratchpad[.publicKey] = publicKey
|
||||
}
|
||||
if let preSharedKey = config.preSharedKey?.base64Key() {
|
||||
scratchpad[.publicKey] = config.publicKey.base64Key
|
||||
if let preSharedKey = config.preSharedKey?.base64Key {
|
||||
scratchpad[.preSharedKey] = preSharedKey
|
||||
}
|
||||
if !config.allowedIPs.isEmpty {
|
||||
@@ -337,14 +338,14 @@ class TunnelViewModel {
|
||||
fieldsWithError.insert(.publicKey)
|
||||
return .error(tr("alertInvalidPeerMessagePublicKeyRequired"))
|
||||
}
|
||||
guard let publicKey = Data(base64Key: publicKeyString), publicKey.count == TunnelConfiguration.keyLength else {
|
||||
guard let publicKey = PublicKey(base64Key: publicKeyString) else {
|
||||
fieldsWithError.insert(.publicKey)
|
||||
return .error(tr("alertInvalidPeerMessagePublicKeyInvalid"))
|
||||
}
|
||||
var config = PeerConfiguration(publicKey: publicKey)
|
||||
var errorMessages = [String]()
|
||||
if let preSharedKeyString = scratchpad[.preSharedKey] {
|
||||
if let preSharedKey = Data(base64Key: preSharedKeyString), preSharedKey.count == TunnelConfiguration.keyLength {
|
||||
if let preSharedKey = PreSharedKey(base64Key: preSharedKeyString) {
|
||||
config.preSharedKey = preSharedKey
|
||||
} else {
|
||||
fieldsWithError.insert(.preSharedKey)
|
||||
@@ -559,7 +560,7 @@ class TunnelViewModel {
|
||||
}
|
||||
|
||||
let peerPublicKeysArray = peerConfigurations.map { $0.publicKey }
|
||||
let peerPublicKeysSet = Set<Data>(peerPublicKeysArray)
|
||||
let peerPublicKeysSet = Set<PublicKey>(peerPublicKeysArray)
|
||||
if peerPublicKeysArray.count != peerPublicKeysSet.count {
|
||||
return .error(tr("alertInvalidPeerMessagePublicKeyDuplicated"))
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
|
||||
// Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
|
||||
|
||||
import UIKit
|
||||
import os.log
|
||||
@@ -21,7 +21,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
}
|
||||
|
||||
let window = UIWindow(frame: UIScreen.main.bounds)
|
||||
window.backgroundColor = .white
|
||||
self.window = window
|
||||
|
||||
let mainVC = MainViewController()
|
||||
|
Before Width: | Height: | Size: 80 KiB After Width: | Height: | Size: 80 KiB |
|
Before Width: | Height: | Size: 865 B After Width: | Height: | Size: 865 B |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 4.5 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 6.4 KiB After Width: | Height: | Size: 6.4 KiB |
|
Before Width: | Height: | Size: 6.4 KiB After Width: | Height: | Size: 6.4 KiB |
|
Before Width: | Height: | Size: 9.8 KiB After Width: | Height: | Size: 9.8 KiB |
|
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 8.2 KiB After Width: | Height: | Size: 8.2 KiB |
|
Before Width: | Height: | Size: 9.1 KiB After Width: | Height: | Size: 9.1 KiB |
@@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
|
||||
// Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
|
||||
|
||||
import UIKit
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
|
||||
// Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
|
||||
|
||||
import UIKit
|
||||
import os.log
|
||||
@@ -64,6 +64,8 @@
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
@@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
|
||||
// Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
|
||||
|
||||
import UIKit
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
|
||||
// Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
|
||||
|
||||
import Foundation
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
|
||||
// Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
|
||||
|
||||
import UIKit
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
|
||||
// Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
|
||||
|
||||
import UIKit
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
|
||||
// Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
|
||||
|
||||
import UIKit
|
||||
|
||||
@@ -9,8 +9,8 @@ class ButtonCell: UITableViewCell {
|
||||
set(value) { button.setTitle(value, for: .normal) }
|
||||
}
|
||||
var hasDestructiveAction: Bool {
|
||||
get { return button.tintColor == .red }
|
||||
set(value) { button.tintColor = value ? .red : buttonStandardTintColor }
|
||||
get { return button.tintColor == .systemRed }
|
||||
set(value) { button.tintColor = value ? .systemRed : buttonStandardTintColor }
|
||||
}
|
||||
var onTapped: (() -> Void)?
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
|
||||
// Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
|
||||
|
||||
import UIKit
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
|
||||
// Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
|
||||
|
||||
import UIKit
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
|
||||
// Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
|
||||
|
||||
import UIKit
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
|
||||
// Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
|
||||
|
||||
import UIKit
|
||||
|
||||
@@ -9,7 +9,11 @@ class KeyValueCell: UITableViewCell {
|
||||
let keyLabel = UILabel()
|
||||
keyLabel.font = UIFont.preferredFont(forTextStyle: .body)
|
||||
keyLabel.adjustsFontForContentSizeCategory = true
|
||||
keyLabel.textColor = .black
|
||||
if #available(iOS 13.0, *) {
|
||||
keyLabel.textColor = .label
|
||||
} else {
|
||||
keyLabel.textColor = .black
|
||||
}
|
||||
keyLabel.textAlignment = .left
|
||||
return keyLabel
|
||||
}()
|
||||
@@ -31,7 +35,11 @@ class KeyValueCell: UITableViewCell {
|
||||
valueTextField.autocapitalizationType = .none
|
||||
valueTextField.autocorrectionType = .no
|
||||
valueTextField.spellCheckingType = .no
|
||||
valueTextField.textColor = .gray
|
||||
if #available(iOS 13.0, *) {
|
||||
valueTextField.textColor = .secondaryLabel
|
||||
} else {
|
||||
valueTextField.textColor = .gray
|
||||
}
|
||||
return valueTextField
|
||||
}()
|
||||
|
||||
@@ -56,10 +64,18 @@ class KeyValueCell: UITableViewCell {
|
||||
|
||||
var isValueValid = true {
|
||||
didSet {
|
||||
if isValueValid {
|
||||
keyLabel.textColor = .black
|
||||
if #available(iOS 13.0, *) {
|
||||
if isValueValid {
|
||||
keyLabel.textColor = .label
|
||||
} else {
|
||||
keyLabel.textColor = .systemRed
|
||||
}
|
||||
} else {
|
||||
keyLabel.textColor = .red
|
||||
if isValueValid {
|
||||
keyLabel.textColor = .black
|
||||
} else {
|
||||
keyLabel.textColor = .red
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
|
||||
// Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
|
||||
|
||||
import UIKit
|
||||
|
||||
@@ -16,7 +16,11 @@ class SwitchCell: UITableViewCell {
|
||||
get { return switchView.isEnabled }
|
||||
set(value) {
|
||||
switchView.isEnabled = value
|
||||
textLabel?.textColor = value ? .black : .gray
|
||||
if #available(iOS 13.0, *) {
|
||||
textLabel?.textColor = value ? .label : .secondaryLabel
|
||||
} else {
|
||||
textLabel?.textColor = value ? .black : .gray
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
|
||||
// Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
|
||||
|
||||
import UIKit
|
||||
|
||||
@@ -28,7 +28,11 @@ class TextCell: UITableViewCell {
|
||||
override func prepareForReuse() {
|
||||
super.prepareForReuse()
|
||||
message = ""
|
||||
setTextColor(.black)
|
||||
if #available(iOS 13.0, *) {
|
||||
setTextColor(.label)
|
||||
} else {
|
||||
setTextColor(.black)
|
||||
}
|
||||
setTextAlignment(.left)
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
|
||||
// Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
|
||||
|
||||
import UIKit
|
||||
|
||||
@@ -30,7 +30,11 @@ class TunnelEditEditableKeyValueCell: TunnelEditKeyValueCell {
|
||||
super.init(style: style, reuseIdentifier: reuseIdentifier)
|
||||
|
||||
copyableGesture = false
|
||||
valueTextField.textColor = .black
|
||||
if #available(iOS 13.0, *) {
|
||||
valueTextField.textColor = .label
|
||||
} else {
|
||||
valueTextField.textColor = .black
|
||||
}
|
||||
valueTextField.isEnabled = true
|
||||
valueLabelScrollView.isScrollEnabled = false
|
||||
valueTextField.widthAnchor.constraint(equalTo: valueLabelScrollView.widthAnchor).isActive = true
|
||||
@@ -1,20 +1,20 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
|
||||
// Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
|
||||
|
||||
import UIKit
|
||||
|
||||
class TunnelListCell: UITableViewCell {
|
||||
var tunnel: TunnelContainer? {
|
||||
didSet(value) {
|
||||
didSet {
|
||||
// Bind to the tunnel's name
|
||||
nameLabel.text = tunnel?.name ?? ""
|
||||
nameObservationToken = tunnel?.observe(\.name) { [weak self] tunnel, _ in
|
||||
self?.nameLabel.text = tunnel.name
|
||||
}
|
||||
// Bind to the tunnel's status
|
||||
update(from: tunnel?.status)
|
||||
update(from: tunnel?.status, animated: false)
|
||||
statusObservationToken = tunnel?.observe(\.status) { [weak self] tunnel, _ in
|
||||
self?.update(from: tunnel.status)
|
||||
self?.update(from: tunnel.status, animated: true)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -29,88 +29,88 @@ class TunnelListCell: UITableViewCell {
|
||||
}()
|
||||
|
||||
let busyIndicator: UIActivityIndicatorView = {
|
||||
let busyIndicator = UIActivityIndicatorView(style: .gray)
|
||||
let busyIndicator: UIActivityIndicatorView
|
||||
if #available(iOS 13.0, *) {
|
||||
busyIndicator = UIActivityIndicatorView(style: .medium)
|
||||
} else {
|
||||
busyIndicator = UIActivityIndicatorView(style: .gray)
|
||||
}
|
||||
busyIndicator.hidesWhenStopped = true
|
||||
return busyIndicator
|
||||
}()
|
||||
|
||||
let statusSwitch = UISwitch()
|
||||
|
||||
private var statusObservationToken: AnyObject?
|
||||
private var nameObservationToken: AnyObject?
|
||||
private var statusObservationToken: NSKeyValueObservation?
|
||||
private var nameObservationToken: NSKeyValueObservation?
|
||||
|
||||
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
|
||||
super.init(style: style, reuseIdentifier: reuseIdentifier)
|
||||
|
||||
contentView.addSubview(statusSwitch)
|
||||
statusSwitch.translatesAutoresizingMaskIntoConstraints = false
|
||||
accessoryType = .disclosureIndicator
|
||||
|
||||
for subview in [statusSwitch, busyIndicator, nameLabel] {
|
||||
subview.translatesAutoresizingMaskIntoConstraints = false
|
||||
contentView.addSubview(subview)
|
||||
}
|
||||
|
||||
nameLabel.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
|
||||
|
||||
let nameLabelBottomConstraint =
|
||||
contentView.layoutMarginsGuide.bottomAnchor.constraint(equalToSystemSpacingBelow: nameLabel.bottomAnchor, multiplier: 1)
|
||||
nameLabelBottomConstraint.priority = .defaultLow
|
||||
|
||||
NSLayoutConstraint.activate([
|
||||
statusSwitch.centerYAnchor.constraint(equalTo: contentView.centerYAnchor),
|
||||
contentView.trailingAnchor.constraint(equalTo: statusSwitch.trailingAnchor)
|
||||
])
|
||||
statusSwitch.trailingAnchor.constraint(equalTo: contentView.layoutMarginsGuide.trailingAnchor),
|
||||
statusSwitch.leadingAnchor.constraint(equalToSystemSpacingAfter: busyIndicator.trailingAnchor, multiplier: 1),
|
||||
|
||||
contentView.addSubview(busyIndicator)
|
||||
busyIndicator.translatesAutoresizingMaskIntoConstraints = false
|
||||
NSLayoutConstraint.activate([
|
||||
busyIndicator.centerYAnchor.constraint(equalTo: contentView.centerYAnchor),
|
||||
statusSwitch.leadingAnchor.constraint(equalToSystemSpacingAfter: busyIndicator.trailingAnchor, multiplier: 1)
|
||||
])
|
||||
|
||||
contentView.addSubview(nameLabel)
|
||||
nameLabel.translatesAutoresizingMaskIntoConstraints = false
|
||||
nameLabel.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
|
||||
let bottomAnchorConstraint = contentView.layoutMarginsGuide.bottomAnchor.constraint(equalToSystemSpacingBelow: nameLabel.bottomAnchor, multiplier: 1)
|
||||
bottomAnchorConstraint.priority = .defaultLow
|
||||
NSLayoutConstraint.activate([
|
||||
nameLabel.topAnchor.constraint(equalToSystemSpacingBelow: contentView.layoutMarginsGuide.topAnchor, multiplier: 1),
|
||||
nameLabelBottomConstraint,
|
||||
nameLabel.leadingAnchor.constraint(equalToSystemSpacingAfter: contentView.layoutMarginsGuide.leadingAnchor, multiplier: 1),
|
||||
busyIndicator.leadingAnchor.constraint(equalToSystemSpacingAfter: nameLabel.trailingAnchor, multiplier: 1),
|
||||
bottomAnchorConstraint
|
||||
])
|
||||
|
||||
accessoryType = .disclosureIndicator
|
||||
busyIndicator.centerYAnchor.constraint(equalTo: contentView.centerYAnchor),
|
||||
busyIndicator.leadingAnchor.constraint(equalToSystemSpacingAfter: nameLabel.trailingAnchor, multiplier: 1)
|
||||
])
|
||||
|
||||
statusSwitch.addTarget(self, action: #selector(switchToggled), for: .valueChanged)
|
||||
}
|
||||
|
||||
@objc func switchToggled() {
|
||||
onSwitchToggled?(statusSwitch.isOn)
|
||||
}
|
||||
|
||||
private func update(from status: TunnelStatus?) {
|
||||
guard let status = status else {
|
||||
reset()
|
||||
return
|
||||
}
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(200)) { [weak statusSwitch, weak busyIndicator] in
|
||||
guard let statusSwitch = statusSwitch, let busyIndicator = busyIndicator else { return }
|
||||
statusSwitch.isOn = !(status == .deactivating || status == .inactive)
|
||||
statusSwitch.isUserInteractionEnabled = (status == .inactive || status == .active)
|
||||
if status == .inactive || status == .active {
|
||||
busyIndicator.stopAnimating()
|
||||
} else {
|
||||
busyIndicator.startAnimating()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
override func prepareForReuse() {
|
||||
super.prepareForReuse()
|
||||
reset(animated: false)
|
||||
}
|
||||
|
||||
override func setEditing(_ editing: Bool, animated: Bool) {
|
||||
super.setEditing(editing, animated: animated)
|
||||
statusSwitch.isEnabled = !editing
|
||||
}
|
||||
|
||||
private func reset() {
|
||||
statusSwitch.isOn = false
|
||||
@objc private func switchToggled() {
|
||||
onSwitchToggled?(statusSwitch.isOn)
|
||||
}
|
||||
|
||||
private func update(from status: TunnelStatus?, animated: Bool) {
|
||||
guard let status = status else {
|
||||
reset(animated: animated)
|
||||
return
|
||||
}
|
||||
statusSwitch.setOn(!(status == .deactivating || status == .inactive), animated: animated)
|
||||
statusSwitch.isUserInteractionEnabled = (status == .inactive || status == .active)
|
||||
if status == .inactive || status == .active {
|
||||
busyIndicator.stopAnimating()
|
||||
} else {
|
||||
busyIndicator.startAnimating()
|
||||
}
|
||||
}
|
||||
|
||||
private func reset(animated: Bool) {
|
||||
statusSwitch.setOn(false, animated: animated)
|
||||
statusSwitch.isUserInteractionEnabled = false
|
||||
busyIndicator.stopAnimating()
|
||||
}
|
||||
|
||||
override func prepareForReuse() {
|
||||
super.prepareForReuse()
|
||||
reset()
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
|
||||
// Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
|
||||
|
||||
import UIKit
|
||||
|
||||
@@ -15,9 +15,15 @@ class LogViewController: UIViewController {
|
||||
}()
|
||||
|
||||
let busyIndicator: UIActivityIndicatorView = {
|
||||
let busyIndicator = UIActivityIndicatorView(style: .gray)
|
||||
busyIndicator.hidesWhenStopped = true
|
||||
return busyIndicator
|
||||
if #available(iOS 13.0, *) {
|
||||
let busyIndicator = UIActivityIndicatorView(style: .medium)
|
||||
busyIndicator.hidesWhenStopped = true
|
||||
return busyIndicator
|
||||
} else {
|
||||
let busyIndicator = UIActivityIndicatorView(style: .gray)
|
||||
busyIndicator.hidesWhenStopped = true
|
||||
return busyIndicator
|
||||
}
|
||||
}()
|
||||
|
||||
let paragraphStyle: NSParagraphStyle = {
|
||||
@@ -35,7 +41,11 @@ class LogViewController: UIViewController {
|
||||
|
||||
override func loadView() {
|
||||
view = UIView()
|
||||
view.backgroundColor = .white
|
||||
if #available(iOS 13.0, *) {
|
||||
view.backgroundColor = .systemBackground
|
||||
} else {
|
||||
view.backgroundColor = .white
|
||||
}
|
||||
|
||||
view.addSubview(textView)
|
||||
textView.translatesAutoresizingMaskIntoConstraints = false
|
||||
@@ -81,12 +91,18 @@ class LogViewController: UIViewController {
|
||||
let richText = NSMutableAttributedString()
|
||||
let bodyFont = UIFont.preferredFont(forTextStyle: UIFont.TextStyle.body)
|
||||
let captionFont = UIFont.preferredFont(forTextStyle: UIFont.TextStyle.caption1)
|
||||
let lightGrayColor = UIColor(white: 0.88, alpha: 1.0)
|
||||
|
||||
for logEntry in fetchedLogEntries {
|
||||
let bgColor = self.isNextLineHighlighted ? lightGrayColor : UIColor.white
|
||||
let timestampText = NSAttributedString(string: logEntry.timestamp + "\n", attributes: [.font: captionFont, .backgroundColor: bgColor, .paragraphStyle: self.paragraphStyle])
|
||||
let messageText = NSAttributedString(string: logEntry.message + "\n", attributes: [.font: bodyFont, .backgroundColor: bgColor, .paragraphStyle: self.paragraphStyle])
|
||||
var bgColor: UIColor
|
||||
var fgColor: UIColor
|
||||
if #available(iOS 13.0, *) {
|
||||
bgColor = self.isNextLineHighlighted ? .systemGray3 : .systemBackground
|
||||
fgColor = .label
|
||||
} else {
|
||||
bgColor = self.isNextLineHighlighted ? UIColor(white: 0.88, alpha: 1.0) : UIColor.white
|
||||
fgColor = .black
|
||||
}
|
||||
let timestampText = NSAttributedString(string: logEntry.timestamp + "\n", attributes: [.font: captionFont, .backgroundColor: bgColor, .foregroundColor: fgColor, .paragraphStyle: self.paragraphStyle])
|
||||
let messageText = NSAttributedString(string: logEntry.message + "\n", attributes: [.font: bodyFont, .backgroundColor: bgColor, .foregroundColor: fgColor, .paragraphStyle: self.paragraphStyle])
|
||||
richText.append(timestampText)
|
||||
richText.append(messageText)
|
||||
self.isNextLineHighlighted.toggle()
|
||||
@@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
|
||||
// Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
|
||||
|
||||
import UIKit
|
||||
|
||||
@@ -11,7 +11,11 @@ class MainViewController: UISplitViewController {
|
||||
|
||||
init() {
|
||||
let detailVC = UIViewController()
|
||||
detailVC.view.backgroundColor = .white
|
||||
if #available(iOS 13.0, *) {
|
||||
detailVC.view.backgroundColor = .systemBackground
|
||||
} else {
|
||||
detailVC.view.backgroundColor = .white
|
||||
}
|
||||
let detailNC = UINavigationController(rootViewController: detailVC)
|
||||
|
||||
let masterVC = TunnelsListTableViewController()
|
||||
@@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
|
||||
// Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
|
||||
|
||||
import AVFoundation
|
||||
import UIKit
|
||||
@@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
|
||||
// Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
|
||||
|
||||
import UIKit
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
|
||||
// Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
|
||||
|
||||
import UIKit
|
||||
import SystemConfiguration.CaptiveNetwork
|
||||
@@ -176,7 +176,11 @@ extension SSIDOptionEditTableViewController {
|
||||
private func noSSIDsCell(for tableView: UITableView, at indexPath: IndexPath) -> UITableViewCell {
|
||||
let cell: TextCell = tableView.dequeueReusableCell(for: indexPath)
|
||||
cell.message = tr("tunnelOnDemandNoSSIDs")
|
||||
cell.setTextColor(.gray)
|
||||
if #available(iOS 13.0, *) {
|
||||
cell.setTextColor(.secondaryLabel)
|
||||
} else {
|
||||
cell.setTextColor(.gray)
|
||||
}
|
||||
cell.setTextAlignment(.center)
|
||||
return cell
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
|
||||
// Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
|
||||
|
||||
import UIKit
|
||||
import os.log
|
||||
@@ -11,6 +11,7 @@ class SettingsTableViewController: UITableViewController {
|
||||
case goBackendVersion
|
||||
case exportZipArchive
|
||||
case viewLog
|
||||
case donateLink
|
||||
|
||||
var localizedUIString: String {
|
||||
switch self {
|
||||
@@ -18,12 +19,13 @@ class SettingsTableViewController: UITableViewController {
|
||||
case .goBackendVersion: return tr("settingsVersionKeyWireGuardGoBackend")
|
||||
case .exportZipArchive: return tr("settingsExportZipButtonTitle")
|
||||
case .viewLog: return tr("settingsViewLogButtonTitle")
|
||||
case .donateLink: return tr("donateLink")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let settingsFieldsBySection: [[SettingsFields]] = [
|
||||
[.iosAppVersion, .goBackendVersion],
|
||||
[.iosAppVersion, .goBackendVersion, .donateLink],
|
||||
[.exportZipArchive],
|
||||
[.viewLog]
|
||||
]
|
||||
@@ -144,8 +146,8 @@ extension SettingsTableViewController {
|
||||
cell.copyableGesture = false
|
||||
cell.key = field.localizedUIString
|
||||
if field == .iosAppVersion {
|
||||
var appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "Unknown version"
|
||||
if let appBuild = Bundle.main.infoDictionary?["CFBundleVersion"] as? String {
|
||||
var appVersion = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String ?? "Unknown version"
|
||||
if let appBuild = Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion") as? String {
|
||||
appVersion += " (\(appBuild))"
|
||||
}
|
||||
cell.value = appVersion
|
||||
@@ -160,14 +162,23 @@ extension SettingsTableViewController {
|
||||
self?.exportConfigurationsAsZipFile(sourceView: cell.button)
|
||||
}
|
||||
return cell
|
||||
} else {
|
||||
assert(field == .viewLog)
|
||||
} else if field == .viewLog {
|
||||
let cell: ButtonCell = tableView.dequeueReusableCell(for: indexPath)
|
||||
cell.buttonText = field.localizedUIString
|
||||
cell.onTapped = { [weak self] in
|
||||
self?.presentLogView()
|
||||
}
|
||||
return cell
|
||||
} else if field == .donateLink {
|
||||
let cell: ButtonCell = tableView.dequeueReusableCell(for: indexPath)
|
||||
cell.buttonText = field.localizedUIString
|
||||
cell.onTapped = {
|
||||
if let url = URL(string: "https://www.wireguard.com/donations/"), UIApplication.shared.canOpenURL(url) {
|
||||
UIApplication.shared.open(url, options: [:])
|
||||
}
|
||||
}
|
||||
return cell
|
||||
}
|
||||
fatalError()
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
|
||||
// Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
|
||||
|
||||
import UIKit
|
||||
|
||||
@@ -120,7 +120,7 @@ class TunnelDetailTableViewController: UITableViewController {
|
||||
let editVC = TunnelEditTableViewController(tunnelsManager: self.tunnelsManager, tunnel: self.tunnel)
|
||||
editVC.delegate = self
|
||||
let editNC = UINavigationController(rootViewController: editVC)
|
||||
editNC.modalPresentationStyle = .formSheet
|
||||
editNC.modalPresentationStyle = .fullScreen
|
||||
self.present(editNC, animated: true)
|
||||
}
|
||||
}
|
||||
@@ -152,8 +152,8 @@ class TunnelDetailTableViewController: UITableViewController {
|
||||
}
|
||||
}!
|
||||
let firstPeerSectionIndex = interfaceSectionIndex + 1
|
||||
var interfaceFieldIsVisible = self.interfaceFieldIsVisible
|
||||
var peerFieldIsVisible = self.peerFieldIsVisible
|
||||
let interfaceFieldIsVisible = self.interfaceFieldIsVisible
|
||||
let peerFieldIsVisible = self.peerFieldIsVisible
|
||||
|
||||
func handleSectionFieldsModified<T>(fields: [T], fieldIsVisible: [Bool], section: Int, changes: [T: TunnelViewModel.Changes.FieldChange]) {
|
||||
for (index, field) in fields.enumerated() {
|
||||
@@ -343,10 +343,8 @@ extension TunnelDetailTableViewController {
|
||||
text = tr("tunnelStatusWaiting")
|
||||
}
|
||||
cell.textLabel?.text = text
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(200)) { [weak cell] in
|
||||
cell?.switchView.isOn = !(status == .deactivating || status == .inactive)
|
||||
cell?.switchView.isUserInteractionEnabled = (status == .inactive || status == .active)
|
||||
}
|
||||
cell.switchView.isOn = !(status == .deactivating || status == .inactive)
|
||||
cell.switchView.isUserInteractionEnabled = (status == .inactive || status == .active)
|
||||
cell.isEnabled = status == .active || status == .inactive
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
|
||||
// Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
|
||||
|
||||
import UIKit
|
||||
|
||||
@@ -214,7 +214,7 @@ extension TunnelEditTableViewController {
|
||||
cell.onTapped = { [weak self] in
|
||||
guard let self = self else { return }
|
||||
|
||||
self.tunnelViewModel.interfaceData[.privateKey] = Curve25519.generatePrivateKey().base64Key() ?? ""
|
||||
self.tunnelViewModel.interfaceData[.privateKey] = PrivateKey().base64Key
|
||||
if let privateKeyRow = self.interfaceFieldsBySection[indexPath.section].firstIndex(of: .privateKey),
|
||||
let publicKeyRow = self.interfaceFieldsBySection[indexPath.section].firstIndex(of: .publicKey) {
|
||||
let privateKeyIndex = IndexPath(row: privateKeyRow, section: indexPath.section)
|
||||
@@ -266,7 +266,7 @@ extension TunnelEditTableViewController {
|
||||
guard let self = self else { return }
|
||||
let isAllowedIPsChanged = self.tunnelViewModel.updateDNSServersInAllowedIPsIfRequired(oldDNSServers: oldValue, newDNSServers: newValue)
|
||||
if isAllowedIPsChanged {
|
||||
let section = self.sections.firstIndex { if case .peer(_) = $0 { return true } else { return false } }
|
||||
let section = self.sections.firstIndex { if case .peer = $0 { return true } else { return false } }
|
||||
if let section = section, let row = self.peerFields.firstIndex(of: .allowedIPs) {
|
||||
self.tableView.reloadRows(at: [IndexPath(row: row, section: section)], with: .none)
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
|
||||
// Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
|
||||
|
||||
import UIKit
|
||||
import MobileCoreServices
|
||||
@@ -32,7 +32,12 @@ class TunnelsListTableViewController: UIViewController {
|
||||
}()
|
||||
|
||||
let busyIndicator: UIActivityIndicatorView = {
|
||||
let busyIndicator = UIActivityIndicatorView(style: .gray)
|
||||
let busyIndicator: UIActivityIndicatorView
|
||||
if #available(iOS 13.0, *) {
|
||||
busyIndicator = UIActivityIndicatorView(style: .medium)
|
||||
} else {
|
||||
busyIndicator = UIActivityIndicatorView(style: .gray)
|
||||
}
|
||||
busyIndicator.hidesWhenStopped = true
|
||||
return busyIndicator
|
||||
}()
|
||||
@@ -46,7 +51,11 @@ class TunnelsListTableViewController: UIViewController {
|
||||
|
||||
override func loadView() {
|
||||
view = UIView()
|
||||
view.backgroundColor = .white
|
||||
if #available(iOS 13.0, *) {
|
||||
view.backgroundColor = .systemBackground
|
||||
} else {
|
||||
view.backgroundColor = .white
|
||||
}
|
||||
|
||||
tableView.dataSource = self
|
||||
tableView.delegate = self
|
||||
@@ -178,7 +187,7 @@ class TunnelsListTableViewController: UIViewController {
|
||||
func presentViewControllerForTunnelCreation(tunnelsManager: TunnelsManager) {
|
||||
let editVC = TunnelEditTableViewController(tunnelsManager: tunnelsManager)
|
||||
let editNC = UINavigationController(rootViewController: editVC)
|
||||
editNC.modalPresentationStyle = .formSheet
|
||||
editNC.modalPresentationStyle = .fullScreen
|
||||
present(editNC, animated: true)
|
||||
}
|
||||
|
||||
@@ -389,7 +398,11 @@ extension TunnelsListTableViewController: TunnelsManagerListDelegate {
|
||||
(splitViewController.viewControllers[0] as? UINavigationController)?.popToRootViewController(animated: false)
|
||||
} else {
|
||||
let detailVC = UIViewController()
|
||||
detailVC.view.backgroundColor = .white
|
||||
if #available(iOS 13.0, *) {
|
||||
detailVC.view.backgroundColor = .systemBackground
|
||||
} else {
|
||||
detailVC.view.backgroundColor = .white
|
||||
}
|
||||
let detailNC = UINavigationController(rootViewController: detailVC)
|
||||
splitViewController.showDetailViewController(detailNC, sender: self)
|
||||
}
|
||||
@@ -402,12 +415,12 @@ extension TunnelsListTableViewController: TunnelsManagerListDelegate {
|
||||
}
|
||||
|
||||
extension UISplitViewController {
|
||||
func showDetailViewController(_ vc: UIViewController, sender: Any?, animated: Bool) {
|
||||
func showDetailViewController(_ viewController: UIViewController, sender: Any?, animated: Bool) {
|
||||
if animated {
|
||||
showDetailViewController(vc, sender: sender)
|
||||
showDetailViewController(viewController, sender: sender)
|
||||
} else {
|
||||
UIView.performWithoutAnimation {
|
||||
showDetailViewController(vc, sender: sender)
|
||||
showDetailViewController(viewController, sender: sender)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
|
||||
// Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
|
||||
|
||||
import Cocoa
|
||||
import ServiceManagement
|
||||
@@ -213,7 +213,8 @@ extension AppDelegate {
|
||||
NSApp.activate(ignoringOtherApps: true)
|
||||
NSApp.orderFrontStandardAboutPanel(options: [
|
||||
.applicationVersion: appVersionString,
|
||||
.version: ""
|
||||
.version: "",
|
||||
.credits: ""
|
||||
])
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
|
||||
// Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
|
||||
|
||||
import Cocoa
|
||||
|
||||
|
Before Width: | Height: | Size: 88 KiB After Width: | Height: | Size: 88 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 49 KiB |
|
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 49 KiB |
|
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 4.9 KiB |