Compare commits

...

36 Commits

Author SHA1 Message Date
Jason A. Donenfeld 571349bb3d Version bump
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2019-04-12 10:32:06 +02:00
Roopesh Chander 98ebd55208 Log view: Don't use a global array to store log entries
Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-04-10 17:57:36 +05:30
Roopesh Chander 83d0d34411 macOS: Log view: Stop updating the log once the log view is dismissed
Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-04-10 15:42:39 +05:30
Jason A. Donenfeld 8c7c4b6792 Version bump
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2019-04-09 10:49:48 +02:00
Jason A. Donenfeld 5b34f49166 wireguard-go-bridge: bump again for version file placement
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2019-04-09 10:43:24 +02:00
Roopesh Chander cef3957875 Swift 5 migration: Handle changes in Data's pointer interface
Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-04-09 11:25:04 +05:30
Roopesh Chander d9e88c51bd Swift 5 migration: Fix switch warnings
We now get a warning when switching over enums from system
frameworks even when we handle all public cases because
there can be future cases that aren't handled.

When such a future case is introduced, we'll get a warning.

Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-04-09 11:25:04 +05:30
Jason A. Donenfeld db876647d6 wireguard-go-bridge: version bump to new tag
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2019-04-09 07:44:50 +02:00
Roopesh Chander 90eb45e287 Xcode: Move to Swift 5.0
No code changes were necessary

Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-04-07 16:42:36 +05:30
Roopesh Chander 9f3d86723a macOS: Minor fix to export panel texts
Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-04-06 17:59:42 +05:30
Roopesh Chander 11063d0f88 macOS: Tunnels list: Suppress alert buttons when removing tunnels is in progress
Also refactor the deletion alert into a separate helper class

Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-04-06 17:53:41 +05:30
Roopesh Chander 557ee4390b TunnelsManager: When setting a config, also set isAvailable cache
Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-04-06 00:26:06 +05:30
Roopesh Chander 9ce42d152d macOS: Tunnels list: Show the confirmation alert till removal completes
Fix tunnel selection during deletion

Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-04-06 00:08:45 +05:30
Roopesh Chander 4c1b2e1258 TunnelsManager: Fix comparing tunnels with tunnelProviders in reload()
Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-04-05 13:43:08 +05:30
Roopesh Chander 3bd611aa7c TunnelsManager: Cache isTunnelConfigurationAvailableInKeychain
Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-04-05 13:29:17 +05:30
Roopesh Chander adbe0b065e macOS: Attempt to remove keychain item only if verified
Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-04-04 15:29:25 +05:30
Roopesh Chander 6015661beb macOS: Simplify reusing of the detail VC when applicable
Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-04-04 12:24:32 +05:30
Roopesh Chander 6e6a6b88fb macOS: Hide other-user tunnels in the status menu
Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-04-03 19:18:53 +05:30
Roopesh Chander 9690365dd4 macOS: Better handling of tunnels created by another user
Previously, the tunnels just got deleted.

Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-04-03 19:04:12 +05:30
Roopesh Chander 0299c3929e iOS: Log view: Make log text selectable
Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-04-01 23:29:15 +05:30
Roopesh Chander 0043233872 macOS: Log view: Fix autoscroll to end of log
Looks like the tableview doesn't know how much to scroll to get to the
end when we use usesAutomaticRowHeights. So we wait for the tableview
to realize its frame has changed and then scroll to the bottom of the
frame explicitly.

Also, we keep track of whether the scroll view is scrolled to the end or
not every time scrolling happens, not just when we add log entries to
the table.

Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-04-01 23:07:48 +05:30
Roopesh Chander a74dd24578 macOS: Bring app to front before 'exiting with an active tunnel' alert
Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-03-29 00:17:37 +05:30
Roopesh Chander dd9506ecee macOS: If a sheet is being shown, ignore quit and bring window to front
Otherwise, the 'exiting with an active tunnel' alert could get queued up
to be shown after the current sheet is dismissed.

Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-03-29 00:17:37 +05:30
Jason A. Donenfeld 0c2eb003a0 wireguard-go-bridge: update deps
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2019-03-28 15:55:53 +01:00
Roopesh Chander f83f159f97 macOS: Log view: No need to disable Close button
Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-03-28 19:32:58 +05:30
Roopesh Chander 6175de0438 iOS: Ability to view the log
Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-03-28 19:28:27 +05:30
Roopesh Chander bd61be52e6 iOS: Xcode: Minor project rearrangement
Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-03-28 14:10:42 +05:30
Roopesh Chander 909f88be70 macOS: Ability to view the log
Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-03-28 13:57:06 +05:30
Roopesh Chander b7c3bd0d8c Add LogViewHelper
Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-03-27 17:55:52 +05:30
Roopesh Chander 4237ab4a6f macOS: Syntax highlighter: Free spans array
Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-03-22 17:53:34 +05:30
Roopesh Chander 0fcaf6debb macOS: Hide exclude private IPs when PrivateKey / PublicKey is missing
Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-03-22 16:00:45 +05:30
Roopesh Chander dbd5ea1ff0 macOS: Syntax highlighter: Swift can bridge c strings automatically
Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-03-22 15:31:02 +05:30
Roopesh Chander 9afe230c10 macOS: On Add new, Exclude Private IPs should remain hidden
because there aren't any peers in the bootstrapped config.

Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-03-22 15:15:26 +05:30
Roopesh Chander 4bdfbb518e Xcode: iOS: Remove armv7 as 'Required device capabilities'
Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-03-20 14:23:56 +05:30
Jason A. Donenfeld fbe101eabb macOS: Privacy notice is provided by system dialogs
So it really doesn't make sense to add our own. This causes several
popups when trying to add a tunnel, which is madness.

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2019-03-20 04:24:23 +01:00
Jason A. Donenfeld cda3170970 macOS: Login item: Add a simple login item
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2019-03-19 21:15:38 -06:00
35 changed files with 1052 additions and 203 deletions
+2 -2
View File
@@ -107,7 +107,7 @@ err:
return ret; return ret;
} }
uint32_t view_lines_from_cursor(const struct log *input_log, uint32_t cursor, void(*cb)(const char *, uint64_t)) uint32_t view_lines_from_cursor(const struct log *input_log, uint32_t cursor, void *ctx, void(*cb)(const char *, uint64_t, void *))
{ {
struct log *log; struct log *log;
uint32_t l, i = cursor; uint32_t l, i = cursor;
@@ -132,7 +132,7 @@ uint32_t view_lines_from_cursor(const struct log *input_log, uint32_t cursor, vo
else else
break; break;
} }
cb(line->line, line->time_ns); cb(line->line, line->time_ns, ctx);
cursor = (i + 1) % MAX_LINES; cursor = (i + 1) % MAX_LINES;
} }
free(log); free(log);
+1 -1
View File
@@ -11,7 +11,7 @@
struct log; struct log;
void write_msg_to_log(struct log *log, const char *tag, const char *msg); void write_msg_to_log(struct log *log, const char *tag, const char *msg);
int write_log_to_file(const char *file_name, const struct log *input_log); int write_log_to_file(const char *file_name, const struct log *input_log);
uint32_t view_lines_from_cursor(const struct log *input_log, uint32_t cursor, void(*)(const char *, uint64_t)); uint32_t view_lines_from_cursor(const struct log *input_log, uint32_t cursor, void *ctx, void(*)(const char *, uint64_t, void *));
struct log *open_log(const char *file_name); struct log *open_log(const char *file_name);
void close_log(struct log *log); void close_log(struct log *log);
+32 -6
View File
@@ -13,8 +13,8 @@ extension Data {
return nil return nil
} }
var out = Data(repeating: 0, count: Int(WG_KEY_LEN_HEX)) var out = Data(repeating: 0, count: Int(WG_KEY_LEN_HEX))
out.withUnsafeMutableBytes { outBytes in out.withUnsafeMutableInt8Bytes { outBytes in
self.withUnsafeBytes { inBytes in self.withUnsafeUInt8Bytes { inBytes in
key_to_hex(outBytes, inBytes) key_to_hex(outBytes, inBytes)
} }
} }
@@ -25,7 +25,7 @@ extension Data {
init?(hexKey hexString: String) { init?(hexKey hexString: String) {
self.init(repeating: 0, count: Int(WG_KEY_LEN)) self.init(repeating: 0, count: Int(WG_KEY_LEN))
if !self.withUnsafeMutableBytes { key_from_hex($0, hexString) } { if !self.withUnsafeMutableUInt8Bytes { key_from_hex($0, hexString) } {
return nil return nil
} }
} }
@@ -35,8 +35,8 @@ extension Data {
return nil return nil
} }
var out = Data(repeating: 0, count: Int(WG_KEY_LEN_BASE64)) var out = Data(repeating: 0, count: Int(WG_KEY_LEN_BASE64))
out.withUnsafeMutableBytes { outBytes in out.withUnsafeMutableInt8Bytes { outBytes in
self.withUnsafeBytes { inBytes in self.withUnsafeUInt8Bytes { inBytes in
key_to_base64(outBytes, inBytes) key_to_base64(outBytes, inBytes)
} }
} }
@@ -47,8 +47,34 @@ extension Data {
init?(base64Key base64String: String) { init?(base64Key base64String: String) {
self.init(repeating: 0, count: Int(WG_KEY_LEN)) self.init(repeating: 0, count: Int(WG_KEY_LEN))
if !self.withUnsafeMutableBytes { key_from_base64($0, base64String) } { if !self.withUnsafeMutableUInt8Bytes { key_from_base64($0, base64String) } {
return nil return nil
} }
} }
} }
extension Data {
func withUnsafeUInt8Bytes<R>(_ body: (UnsafePointer<UInt8>) -> R) -> R {
assert(!isEmpty)
return self.withUnsafeBytes { (ptr: UnsafeRawBufferPointer) -> R in
let bytes = ptr.bindMemory(to: UInt8.self)
return body(bytes.baseAddress!) // might crash if self.count == 0
}
}
mutating func withUnsafeMutableUInt8Bytes<R>(_ body: (UnsafeMutablePointer<UInt8>) -> R) -> R {
assert(!isEmpty)
return self.withUnsafeMutableBytes { (ptr: UnsafeMutableRawBufferPointer) -> R in
let bytes = ptr.bindMemory(to: UInt8.self)
return body(bytes.baseAddress!) // might crash if self.count == 0
}
}
mutating func withUnsafeMutableInt8Bytes<R>(_ body: (UnsafeMutablePointer<Int8>) -> R) -> R {
assert(!isEmpty)
return self.withUnsafeMutableBytes { (ptr: UnsafeMutableRawBufferPointer) -> R in
let bytes = ptr.bindMemory(to: Int8.self)
return body(bytes.baseAddress!) // might crash if self.count == 0
}
}
}
+6
View File
@@ -36,6 +36,8 @@ extension Endpoint {
return "\(address):\(port)" return "\(address):\(port)"
case .ipv6(let address): case .ipv6(let address):
return "[\(address)]:\(port)" return "[\(address)]:\(port)"
@unknown default:
fatalError()
} }
} }
@@ -78,6 +80,8 @@ extension Endpoint {
return true return true
case .ipv6: case .ipv6:
return true return true
@unknown default:
fatalError()
} }
} }
@@ -89,6 +93,8 @@ extension Endpoint {
return nil return nil
case .ipv6: case .ipv6:
return nil return nil
@unknown default:
fatalError()
} }
} }
} }
@@ -49,9 +49,9 @@ extension NETunnelProviderProtocol {
Keychain.deleteReference(called: ref) Keychain.deleteReference(called: ref)
} }
func verifyConfigurationReference() -> Data? { func verifyConfigurationReference() -> Bool {
guard let ref = passwordReference else { return nil } guard let ref = passwordReference else { return false }
return Keychain.verifyReference(called: ref) ? ref : nil return Keychain.verifyReference(called: ref)
} }
@discardableResult @discardableResult
+149 -9
View File
@@ -41,15 +41,16 @@
6B62E45F220A6FA900EF34A6 /* PrivateDataConfirmation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6B62E45E220A6FA900EF34A6 /* PrivateDataConfirmation.swift */; }; 6B62E45F220A6FA900EF34A6 /* PrivateDataConfirmation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6B62E45E220A6FA900EF34A6 /* PrivateDataConfirmation.swift */; };
6B62E460220A6FA900EF34A6 /* PrivateDataConfirmation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6B62E45E220A6FA900EF34A6 /* PrivateDataConfirmation.swift */; }; 6B62E460220A6FA900EF34A6 /* PrivateDataConfirmation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6B62E45E220A6FA900EF34A6 /* PrivateDataConfirmation.swift */; };
6B653B86220DE2960050E69C /* NetworkExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6FF4AC462120B9E0002C96EB /* NetworkExtension.framework */; }; 6B653B86220DE2960050E69C /* NetworkExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6FF4AC462120B9E0002C96EB /* NetworkExtension.framework */; };
6B6956362211DA80001B618A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6B6956352211DA80001B618A /* main.m */; };
6B707D8421F918D4000A8F73 /* TunnelConfiguration+UapiConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6B707D8321F918D4000A8F73 /* TunnelConfiguration+UapiConfig.swift */; }; 6B707D8421F918D4000A8F73 /* TunnelConfiguration+UapiConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6B707D8321F918D4000A8F73 /* TunnelConfiguration+UapiConfig.swift */; };
6B707D8621F918D4000A8F73 /* TunnelConfiguration+UapiConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6B707D8321F918D4000A8F73 /* TunnelConfiguration+UapiConfig.swift */; }; 6B707D8621F918D4000A8F73 /* TunnelConfiguration+UapiConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6B707D8321F918D4000A8F73 /* TunnelConfiguration+UapiConfig.swift */; };
6BAC16E6221634B300A5FB78 /* AppStorePrivacyNotice.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6BAC16E42216324B00A5FB78 /* AppStorePrivacyNotice.swift */; };
6BD5C97B220D1AE200784E08 /* key.c in Sources */ = {isa = PBXBuildFile; fileRef = 6BD5C979220D1AE100784E08 /* key.c */; }; 6BD5C97B220D1AE200784E08 /* key.c in Sources */ = {isa = PBXBuildFile; fileRef = 6BD5C979220D1AE100784E08 /* key.c */; };
6BD5C97C220D1AE200784E08 /* key.c in Sources */ = {isa = PBXBuildFile; fileRef = 6BD5C979220D1AE100784E08 /* key.c */; }; 6BD5C97C220D1AE200784E08 /* key.c in Sources */ = {isa = PBXBuildFile; fileRef = 6BD5C979220D1AE100784E08 /* key.c */; };
6BD5C97D220D1AE200784E08 /* key.c in Sources */ = {isa = PBXBuildFile; fileRef = 6BD5C979220D1AE100784E08 /* key.c */; }; 6BD5C97D220D1AE200784E08 /* key.c in Sources */ = {isa = PBXBuildFile; fileRef = 6BD5C979220D1AE100784E08 /* key.c */; };
6BD5C97E220D1AE200784E08 /* key.c in Sources */ = {isa = PBXBuildFile; fileRef = 6BD5C979220D1AE100784E08 /* key.c */; }; 6BD5C97E220D1AE200784E08 /* key.c in Sources */ = {isa = PBXBuildFile; fileRef = 6BD5C979220D1AE100784E08 /* key.c */; };
6F0F44C9222D55BB00B0FF04 /* TextCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F0F44C8222D55BB00B0FF04 /* TextCell.swift */; }; 6F0F44C9222D55BB00B0FF04 /* TextCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F0F44C8222D55BB00B0FF04 /* TextCell.swift */; };
6F0F44CB222D55FD00B0FF04 /* EditableTextCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F0F44CA222D55FD00B0FF04 /* EditableTextCell.swift */; }; 6F0F44CB222D55FD00B0FF04 /* EditableTextCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F0F44CA222D55FD00B0FF04 /* EditableTextCell.swift */; };
6F1075642258AE9800D78929 /* DeleteTunnelsConfirmationAlert.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F1075632258AE9800D78929 /* DeleteTunnelsConfirmationAlert.swift */; };
6F19D30422402B8700A126F2 /* ConfirmationAlertPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F19D30322402B8700A126F2 /* ConfirmationAlertPresenter.swift */; }; 6F19D30422402B8700A126F2 /* ConfirmationAlertPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F19D30322402B8700A126F2 /* ConfirmationAlertPresenter.swift */; };
6F4DD16B21DA558800690EAE /* TunnelListRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F4DD16A21DA558800690EAE /* TunnelListRow.swift */; }; 6F4DD16B21DA558800690EAE /* TunnelListRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F4DD16A21DA558800690EAE /* TunnelListRow.swift */; };
6F4DD16C21DA558F00690EAE /* NSTableView+Reuse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F4DD16721DA552B00690EAE /* NSTableView+Reuse.swift */; }; 6F4DD16C21DA558F00690EAE /* NSTableView+Reuse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F4DD16721DA552B00690EAE /* NSTableView+Reuse.swift */; };
@@ -70,6 +71,7 @@
6F693A562179E556008551C1 /* Endpoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F693A552179E556008551C1 /* Endpoint.swift */; }; 6F693A562179E556008551C1 /* Endpoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F693A552179E556008551C1 /* Endpoint.swift */; };
6F70E20E221058E1008BDFB4 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 6F70E20C221058DF008BDFB4 /* InfoPlist.strings */; }; 6F70E20E221058E1008BDFB4 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 6F70E20C221058DF008BDFB4 /* InfoPlist.strings */; };
6F70E20F221058E1008BDFB4 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 6F70E20C221058DF008BDFB4 /* InfoPlist.strings */; }; 6F70E20F221058E1008BDFB4 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 6F70E20C221058DF008BDFB4 /* InfoPlist.strings */; };
6F70E23D22109E15008BDFB4 /* WireGuardLoginItemHelper.app in Embed Login Item Helper */ = {isa = PBXBuildFile; fileRef = 6F70E22922106A2D008BDFB4 /* WireGuardLoginItemHelper.app */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
6F7774E1217181B1006A79B3 /* MainViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F7774DF217181B1006A79B3 /* MainViewController.swift */; }; 6F7774E1217181B1006A79B3 /* MainViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F7774DF217181B1006A79B3 /* MainViewController.swift */; };
6F7774E2217181B1006A79B3 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F7774E0217181B1006A79B3 /* AppDelegate.swift */; }; 6F7774E2217181B1006A79B3 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F7774E0217181B1006A79B3 /* AppDelegate.swift */; };
6F7774E421718281006A79B3 /* TunnelsListTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F7774E321718281006A79B3 /* TunnelsListTableViewController.swift */; }; 6F7774E421718281006A79B3 /* TunnelsListTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F7774E321718281006A79B3 /* TunnelsListTableViewController.swift */; };
@@ -84,12 +86,15 @@
6F8F0D7222258153000E8335 /* ActivateOnDemandViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F8F0D7022258153000E8335 /* ActivateOnDemandViewModel.swift */; }; 6F8F0D7222258153000E8335 /* ActivateOnDemandViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F8F0D7022258153000E8335 /* ActivateOnDemandViewModel.swift */; };
6F8F0D7422267AD2000E8335 /* ChevronCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F8F0D7322267AD2000E8335 /* ChevronCell.swift */; }; 6F8F0D7422267AD2000E8335 /* ChevronCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F8F0D7322267AD2000E8335 /* ChevronCell.swift */; };
6F8F0D7722267C57000E8335 /* SSIDOptionEditTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F8F0D7622267C57000E8335 /* SSIDOptionEditTableViewController.swift */; }; 6F8F0D7722267C57000E8335 /* SSIDOptionEditTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F8F0D7622267C57000E8335 /* SSIDOptionEditTableViewController.swift */; };
6F907C9C224663A2003CED21 /* LogViewHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F907C9B224663A2003CED21 /* LogViewHelper.swift */; };
6F907C9D224663A2003CED21 /* LogViewHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F907C9B224663A2003CED21 /* LogViewHelper.swift */; };
6F919EC3218A2AE90023B400 /* ErrorPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F919EC2218A2AE90023B400 /* ErrorPresenter.swift */; }; 6F919EC3218A2AE90023B400 /* ErrorPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F919EC2218A2AE90023B400 /* ErrorPresenter.swift */; };
6F919ED9218C65C50023B400 /* wireguard_doc_logo_22x29.png in Resources */ = {isa = PBXBuildFile; fileRef = 6F919ED5218C65C50023B400 /* wireguard_doc_logo_22x29.png */; }; 6F919ED9218C65C50023B400 /* wireguard_doc_logo_22x29.png in Resources */ = {isa = PBXBuildFile; fileRef = 6F919ED5218C65C50023B400 /* wireguard_doc_logo_22x29.png */; };
6F919EDA218C65C50023B400 /* wireguard_doc_logo_44x58.png in Resources */ = {isa = PBXBuildFile; fileRef = 6F919ED6218C65C50023B400 /* wireguard_doc_logo_44x58.png */; }; 6F919EDA218C65C50023B400 /* wireguard_doc_logo_44x58.png in Resources */ = {isa = PBXBuildFile; fileRef = 6F919ED6218C65C50023B400 /* wireguard_doc_logo_44x58.png */; };
6F919EDB218C65C50023B400 /* wireguard_doc_logo_64x64.png in Resources */ = {isa = PBXBuildFile; fileRef = 6F919ED7218C65C50023B400 /* wireguard_doc_logo_64x64.png */; }; 6F919EDB218C65C50023B400 /* wireguard_doc_logo_64x64.png in Resources */ = {isa = PBXBuildFile; fileRef = 6F919ED7218C65C50023B400 /* wireguard_doc_logo_64x64.png */; };
6F919EDC218C65C50023B400 /* wireguard_doc_logo_320x320.png in Resources */ = {isa = PBXBuildFile; fileRef = 6F919ED8218C65C50023B400 /* wireguard_doc_logo_320x320.png */; }; 6F919EDC218C65C50023B400 /* wireguard_doc_logo_320x320.png in Resources */ = {isa = PBXBuildFile; fileRef = 6F919ED8218C65C50023B400 /* wireguard_doc_logo_320x320.png */; };
6F9B8A8E223398610041B9C4 /* SSIDOptionDetailTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F9B8A8D223398610041B9C4 /* SSIDOptionDetailTableViewController.swift */; }; 6F9B8A8E223398610041B9C4 /* SSIDOptionDetailTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F9B8A8D223398610041B9C4 /* SSIDOptionDetailTableViewController.swift */; };
6FADE96C2254B8C300B838A4 /* UnusableTunnelDetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6FADE96A2254A6C200B838A4 /* UnusableTunnelDetailViewController.swift */; };
6FB1017921C57DE600766195 /* MockTunnels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6FB1017821C57DE600766195 /* MockTunnels.swift */; }; 6FB1017921C57DE600766195 /* MockTunnels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6FB1017821C57DE600766195 /* MockTunnels.swift */; };
6FB17946222FD5960018AE71 /* OnDemandWiFiControls.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6FB17945222FD5960018AE71 /* OnDemandWiFiControls.swift */; }; 6FB17946222FD5960018AE71 /* OnDemandWiFiControls.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6FB17945222FD5960018AE71 /* OnDemandWiFiControls.swift */; };
6FB1BD6021D2607A00A991BF /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6FB1BD5F21D2607A00A991BF /* AppDelegate.swift */; }; 6FB1BD6021D2607A00A991BF /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6FB1BD5F21D2607A00A991BF /* AppDelegate.swift */; };
@@ -155,6 +160,9 @@
6FCD99B121E0EDA900BA4C82 /* TunnelEditViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6FCD99B021E0EDA900BA4C82 /* TunnelEditViewController.swift */; }; 6FCD99B121E0EDA900BA4C82 /* TunnelEditViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6FCD99B021E0EDA900BA4C82 /* TunnelEditViewController.swift */; };
6FDB3C3B21DCF47400A0C0BF /* TunnelDetailTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6FDB3C3A21DCF47400A0C0BF /* TunnelDetailTableViewController.swift */; }; 6FDB3C3B21DCF47400A0C0BF /* TunnelDetailTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6FDB3C3A21DCF47400A0C0BF /* TunnelDetailTableViewController.swift */; };
6FDB3C3C21DCF6BB00A0C0BF /* TunnelViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F628C3C217F09E9003482A3 /* TunnelViewModel.swift */; }; 6FDB3C3C21DCF6BB00A0C0BF /* TunnelViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F628C3C217F09E9003482A3 /* TunnelViewModel.swift */; };
6FDB6D13224A15BF00EE4BC3 /* LogViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6FDB6D12224A15BE00EE4BC3 /* LogViewController.swift */; };
6FDB6D15224CB2CE00EE4BC3 /* LogViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6FDB6D14224CB2CE00EE4BC3 /* LogViewCell.swift */; };
6FDB6D18224CC05A00EE4BC3 /* LogViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6FDB6D16224CC04E00EE4BC3 /* LogViewController.swift */; };
6FDEF7E421846C1A00D8FBF6 /* libwg-go.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 6FDEF7E321846C1A00D8FBF6 /* libwg-go.a */; }; 6FDEF7E421846C1A00D8FBF6 /* libwg-go.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 6FDEF7E321846C1A00D8FBF6 /* libwg-go.a */; };
6FDEF7E62185EFB200D8FBF6 /* QRScanViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6FDEF7E52185EFAF00D8FBF6 /* QRScanViewController.swift */; }; 6FDEF7E62185EFB200D8FBF6 /* QRScanViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6FDEF7E52185EFAF00D8FBF6 /* QRScanViewController.swift */; };
6FDEF7FB21863B6100D8FBF6 /* unzip.c in Sources */ = {isa = PBXBuildFile; fileRef = 6FDEF7F621863B6100D8FBF6 /* unzip.c */; }; 6FDEF7FB21863B6100D8FBF6 /* unzip.c in Sources */ = {isa = PBXBuildFile; fileRef = 6FDEF7F621863B6100D8FBF6 /* unzip.c */; };
@@ -194,6 +202,13 @@
remoteGlobalIDString = 6F5D0C19218352EF000F85AD; remoteGlobalIDString = 6F5D0C19218352EF000F85AD;
remoteInfo = WireGuardNetworkExtension; remoteInfo = WireGuardNetworkExtension;
}; };
6F70E23A22109DD3008BDFB4 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 6FF4AC0C211EC46F002C96EB /* Project object */;
proxyType = 1;
remoteGlobalIDString = 6F70E22822106A2D008BDFB4;
remoteInfo = WireGuardmacOSLoginItemHelper;
};
6FB1BD9721D4BFE700A991BF /* PBXContainerItemProxy */ = { 6FB1BD9721D4BFE700A991BF /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy; isa = PBXContainerItemProxy;
containerPortal = 6FF4AC0C211EC46F002C96EB /* Project object */; containerPortal = 6FF4AC0C211EC46F002C96EB /* Project object */;
@@ -229,6 +244,17 @@
name = "Embed App Extensions"; name = "Embed App Extensions";
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
6F70E23C22109DE5008BDFB4 /* Embed Login Item Helper */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = Contents/Library/LoginItems;
dstSubfolderSpec = 1;
files = (
6F70E23D22109E15008BDFB4 /* WireGuardLoginItemHelper.app in Embed Login Item Helper */,
);
name = "Embed Login Item Helper";
runOnlyForDeploymentPostprocessing = 0;
};
6FB1BD9D21D4BFE700A991BF /* Embed App Extensions */ = { 6FB1BD9D21D4BFE700A991BF /* Embed App Extensions */ = {
isa = PBXCopyFilesBuildPhase; isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
@@ -264,12 +290,13 @@
6B586C52220CBA6D00427C51 /* Data+KeyEncoding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Data+KeyEncoding.swift"; sourceTree = "<group>"; }; 6B586C52220CBA6D00427C51 /* Data+KeyEncoding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Data+KeyEncoding.swift"; sourceTree = "<group>"; };
6B5C5E26220A48D30024272E /* Keychain.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Keychain.swift; sourceTree = "<group>"; }; 6B5C5E26220A48D30024272E /* Keychain.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Keychain.swift; sourceTree = "<group>"; };
6B62E45E220A6FA900EF34A6 /* PrivateDataConfirmation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrivateDataConfirmation.swift; sourceTree = "<group>"; }; 6B62E45E220A6FA900EF34A6 /* PrivateDataConfirmation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrivateDataConfirmation.swift; sourceTree = "<group>"; };
6B6956352211DA80001B618A /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
6B707D8321F918D4000A8F73 /* TunnelConfiguration+UapiConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TunnelConfiguration+UapiConfig.swift"; sourceTree = "<group>"; }; 6B707D8321F918D4000A8F73 /* TunnelConfiguration+UapiConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TunnelConfiguration+UapiConfig.swift"; sourceTree = "<group>"; };
6BAC16E42216324B00A5FB78 /* AppStorePrivacyNotice.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppStorePrivacyNotice.swift; sourceTree = "<group>"; };
6BD5C979220D1AE100784E08 /* key.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = key.c; sourceTree = "<group>"; }; 6BD5C979220D1AE100784E08 /* key.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = key.c; sourceTree = "<group>"; };
6BD5C97A220D1AE200784E08 /* key.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = key.h; sourceTree = "<group>"; }; 6BD5C97A220D1AE200784E08 /* key.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = key.h; sourceTree = "<group>"; };
6F0F44C8222D55BB00B0FF04 /* TextCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextCell.swift; sourceTree = "<group>"; }; 6F0F44C8222D55BB00B0FF04 /* TextCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextCell.swift; sourceTree = "<group>"; };
6F0F44CA222D55FD00B0FF04 /* EditableTextCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditableTextCell.swift; sourceTree = "<group>"; }; 6F0F44CA222D55FD00B0FF04 /* EditableTextCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditableTextCell.swift; sourceTree = "<group>"; };
6F1075632258AE9800D78929 /* DeleteTunnelsConfirmationAlert.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeleteTunnelsConfirmationAlert.swift; sourceTree = "<group>"; };
6F19D30322402B8700A126F2 /* ConfirmationAlertPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfirmationAlertPresenter.swift; sourceTree = "<group>"; }; 6F19D30322402B8700A126F2 /* ConfirmationAlertPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfirmationAlertPresenter.swift; sourceTree = "<group>"; };
6F4DD16721DA552B00690EAE /* NSTableView+Reuse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSTableView+Reuse.swift"; sourceTree = "<group>"; }; 6F4DD16721DA552B00690EAE /* NSTableView+Reuse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSTableView+Reuse.swift"; sourceTree = "<group>"; };
6F4DD16A21DA558800690EAE /* TunnelListRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelListRow.swift; sourceTree = "<group>"; }; 6F4DD16A21DA558800690EAE /* TunnelListRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelListRow.swift; sourceTree = "<group>"; };
@@ -295,6 +322,9 @@
6F6899A7218044FC0012E523 /* Curve25519.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Curve25519.swift; sourceTree = "<group>"; }; 6F6899A7218044FC0012E523 /* Curve25519.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Curve25519.swift; sourceTree = "<group>"; };
6F693A552179E556008551C1 /* Endpoint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Endpoint.swift; sourceTree = "<group>"; }; 6F693A552179E556008551C1 /* Endpoint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Endpoint.swift; sourceTree = "<group>"; };
6F70E20D221058DF008BDFB4 /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = WireGuard/Base.lproj/InfoPlist.strings; sourceTree = "<group>"; }; 6F70E20D221058DF008BDFB4 /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = WireGuard/Base.lproj/InfoPlist.strings; sourceTree = "<group>"; };
6F70E22922106A2D008BDFB4 /* WireGuardLoginItemHelper.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = WireGuardLoginItemHelper.app; sourceTree = BUILT_PRODUCTS_DIR; };
6F70E23222106A31008BDFB4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
6F70E23922109BEF008BDFB4 /* LoginItemHelper.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = LoginItemHelper.entitlements; sourceTree = "<group>"; };
6F7774DF217181B1006A79B3 /* MainViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainViewController.swift; sourceTree = "<group>"; }; 6F7774DF217181B1006A79B3 /* MainViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainViewController.swift; sourceTree = "<group>"; };
6F7774E0217181B1006A79B3 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; }; 6F7774E0217181B1006A79B3 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
6F7774E321718281006A79B3 /* TunnelsListTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TunnelsListTableViewController.swift; sourceTree = "<group>"; }; 6F7774E321718281006A79B3 /* TunnelsListTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TunnelsListTableViewController.swift; sourceTree = "<group>"; };
@@ -308,12 +338,14 @@
6F8F0D7022258153000E8335 /* ActivateOnDemandViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActivateOnDemandViewModel.swift; sourceTree = "<group>"; }; 6F8F0D7022258153000E8335 /* ActivateOnDemandViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActivateOnDemandViewModel.swift; sourceTree = "<group>"; };
6F8F0D7322267AD2000E8335 /* ChevronCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChevronCell.swift; sourceTree = "<group>"; }; 6F8F0D7322267AD2000E8335 /* ChevronCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChevronCell.swift; sourceTree = "<group>"; };
6F8F0D7622267C57000E8335 /* SSIDOptionEditTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SSIDOptionEditTableViewController.swift; sourceTree = "<group>"; }; 6F8F0D7622267C57000E8335 /* SSIDOptionEditTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SSIDOptionEditTableViewController.swift; sourceTree = "<group>"; };
6F907C9B224663A2003CED21 /* LogViewHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogViewHelper.swift; sourceTree = "<group>"; };
6F919EC2218A2AE90023B400 /* ErrorPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorPresenter.swift; sourceTree = "<group>"; }; 6F919EC2218A2AE90023B400 /* ErrorPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorPresenter.swift; sourceTree = "<group>"; };
6F919ED5218C65C50023B400 /* wireguard_doc_logo_22x29.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = wireguard_doc_logo_22x29.png; sourceTree = "<group>"; }; 6F919ED5218C65C50023B400 /* wireguard_doc_logo_22x29.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = wireguard_doc_logo_22x29.png; sourceTree = "<group>"; };
6F919ED6218C65C50023B400 /* wireguard_doc_logo_44x58.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = wireguard_doc_logo_44x58.png; sourceTree = "<group>"; }; 6F919ED6218C65C50023B400 /* wireguard_doc_logo_44x58.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = wireguard_doc_logo_44x58.png; sourceTree = "<group>"; };
6F919ED7218C65C50023B400 /* wireguard_doc_logo_64x64.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = wireguard_doc_logo_64x64.png; sourceTree = "<group>"; }; 6F919ED7218C65C50023B400 /* wireguard_doc_logo_64x64.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = wireguard_doc_logo_64x64.png; sourceTree = "<group>"; };
6F919ED8218C65C50023B400 /* wireguard_doc_logo_320x320.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = wireguard_doc_logo_320x320.png; sourceTree = "<group>"; }; 6F919ED8218C65C50023B400 /* wireguard_doc_logo_320x320.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = wireguard_doc_logo_320x320.png; sourceTree = "<group>"; };
6F9B8A8D223398610041B9C4 /* SSIDOptionDetailTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SSIDOptionDetailTableViewController.swift; sourceTree = "<group>"; }; 6F9B8A8D223398610041B9C4 /* SSIDOptionDetailTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SSIDOptionDetailTableViewController.swift; sourceTree = "<group>"; };
6FADE96A2254A6C200B838A4 /* UnusableTunnelDetailViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnusableTunnelDetailViewController.swift; sourceTree = "<group>"; };
6FB1017821C57DE600766195 /* MockTunnels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockTunnels.swift; sourceTree = "<group>"; }; 6FB1017821C57DE600766195 /* MockTunnels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockTunnels.swift; sourceTree = "<group>"; };
6FB17945222FD5960018AE71 /* OnDemandWiFiControls.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnDemandWiFiControls.swift; sourceTree = "<group>"; }; 6FB17945222FD5960018AE71 /* OnDemandWiFiControls.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnDemandWiFiControls.swift; sourceTree = "<group>"; };
6FB1BD5D21D2607A00A991BF /* WireGuard.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = WireGuard.app; sourceTree = BUILT_PRODUCTS_DIR; }; 6FB1BD5D21D2607A00A991BF /* WireGuard.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = WireGuard.app; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -335,6 +367,9 @@
6FCD99AE21E0EA1700BA4C82 /* ImportPanelPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImportPanelPresenter.swift; sourceTree = "<group>"; }; 6FCD99AE21E0EA1700BA4C82 /* ImportPanelPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImportPanelPresenter.swift; sourceTree = "<group>"; };
6FCD99B021E0EDA900BA4C82 /* TunnelEditViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelEditViewController.swift; sourceTree = "<group>"; }; 6FCD99B021E0EDA900BA4C82 /* TunnelEditViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelEditViewController.swift; sourceTree = "<group>"; };
6FDB3C3A21DCF47400A0C0BF /* TunnelDetailTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelDetailTableViewController.swift; sourceTree = "<group>"; }; 6FDB3C3A21DCF47400A0C0BF /* TunnelDetailTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelDetailTableViewController.swift; sourceTree = "<group>"; };
6FDB6D12224A15BE00EE4BC3 /* LogViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LogViewController.swift; sourceTree = "<group>"; };
6FDB6D14224CB2CE00EE4BC3 /* LogViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogViewCell.swift; sourceTree = "<group>"; };
6FDB6D16224CC04E00EE4BC3 /* LogViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogViewController.swift; sourceTree = "<group>"; };
6FDEF7E321846C1A00D8FBF6 /* libwg-go.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = "libwg-go.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 6FDEF7E321846C1A00D8FBF6 /* libwg-go.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = "libwg-go.a"; sourceTree = BUILT_PRODUCTS_DIR; };
6FDEF7E52185EFAF00D8FBF6 /* QRScanViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QRScanViewController.swift; sourceTree = "<group>"; }; 6FDEF7E52185EFAF00D8FBF6 /* QRScanViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QRScanViewController.swift; sourceTree = "<group>"; };
6FDEF7F621863B6100D8FBF6 /* unzip.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = unzip.c; sourceTree = "<group>"; }; 6FDEF7F621863B6100D8FBF6 /* unzip.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = unzip.c; sourceTree = "<group>"; };
@@ -432,6 +467,7 @@
6F7774DF217181B1006A79B3 /* MainViewController.swift */, 6F7774DF217181B1006A79B3 /* MainViewController.swift */,
6F8F0D7622267C57000E8335 /* SSIDOptionEditTableViewController.swift */, 6F8F0D7622267C57000E8335 /* SSIDOptionEditTableViewController.swift */,
6F9B8A8D223398610041B9C4 /* SSIDOptionDetailTableViewController.swift */, 6F9B8A8D223398610041B9C4 /* SSIDOptionDetailTableViewController.swift */,
6FDB6D16224CC04E00EE4BC3 /* LogViewController.swift */,
); );
path = ViewController; path = ViewController;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -448,6 +484,8 @@
6FE3661C21F64F6B00F78C7D /* ConfTextColorTheme.swift */, 6FE3661C21F64F6B00F78C7D /* ConfTextColorTheme.swift */,
6F5EA59A223E58A8002B380A /* ButtonRow.swift */, 6F5EA59A223E58A8002B380A /* ButtonRow.swift */,
6FB17945222FD5960018AE71 /* OnDemandWiFiControls.swift */, 6FB17945222FD5960018AE71 /* OnDemandWiFiControls.swift */,
6FDB6D14224CB2CE00EE4BC3 /* LogViewCell.swift */,
6F1075632258AE9800D78929 /* DeleteTunnelsConfirmationAlert.swift */,
); );
path = View; path = View;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -488,6 +526,16 @@
path = Crypto; path = Crypto;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
6F70E22A22106A2D008BDFB4 /* LoginItemHelper */ = {
isa = PBXGroup;
children = (
6F70E23922109BEF008BDFB4 /* LoginItemHelper.entitlements */,
6F70E23222106A31008BDFB4 /* Info.plist */,
6B6956352211DA80001B618A /* main.m */,
);
path = LoginItemHelper;
sourceTree = "<group>";
};
6F7774DD217181B1006A79B3 /* UI */ = { 6F7774DD217181B1006A79B3 /* UI */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
@@ -498,6 +546,7 @@
6FBA103D21D6B6D70051C35F /* TunnelImporter.swift */, 6FBA103D21D6B6D70051C35F /* TunnelImporter.swift */,
6FBA103A21D6B4280051C35F /* ErrorPresenterProtocol.swift */, 6FBA103A21D6B4280051C35F /* ErrorPresenterProtocol.swift */,
6B62E45E220A6FA900EF34A6 /* PrivateDataConfirmation.swift */, 6B62E45E220A6FA900EF34A6 /* PrivateDataConfirmation.swift */,
6F907C9B224663A2003CED21 /* LogViewHelper.swift */,
); );
path = UI; path = UI;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -507,8 +556,8 @@
children = ( children = (
6FF4AC1E211EC472002C96EB /* Assets.xcassets */, 6FF4AC1E211EC472002C96EB /* Assets.xcassets */,
6FF4AC20211EC472002C96EB /* LaunchScreen.storyboard */, 6FF4AC20211EC472002C96EB /* LaunchScreen.storyboard */,
5F4541AC21C4720B00994C13 /* ViewController */,
5F4541A721C44F5B00994C13 /* View */, 5F4541A721C44F5B00994C13 /* View */,
5F4541AC21C4720B00994C13 /* ViewController */,
6F7774E0217181B1006A79B3 /* AppDelegate.swift */, 6F7774E0217181B1006A79B3 /* AppDelegate.swift */,
6F919EC2218A2AE90023B400 /* ErrorPresenter.swift */, 6F919EC2218A2AE90023B400 /* ErrorPresenter.swift */,
6F19D30322402B8700A126F2 /* ConfirmationAlertPresenter.swift */, 6F19D30322402B8700A126F2 /* ConfirmationAlertPresenter.swift */,
@@ -573,6 +622,7 @@
6FB1BD5E21D2607A00A991BF /* macOS */ = { 6FB1BD5E21D2607A00A991BF /* macOS */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
6F70E22A22106A2D008BDFB4 /* LoginItemHelper */,
6F4DD16921DA556600690EAE /* View */, 6F4DD16921DA556600690EAE /* View */,
6FBA104421D7EA750051C35F /* ViewController */, 6FBA104421D7EA750051C35F /* ViewController */,
6FBA101321D613F30051C35F /* Application.swift */, 6FBA101321D613F30051C35F /* Application.swift */,
@@ -588,7 +638,6 @@
6F4DD16721DA552B00690EAE /* NSTableView+Reuse.swift */, 6F4DD16721DA552B00690EAE /* NSTableView+Reuse.swift */,
5F52D0BE21E3788900283CEA /* NSColor+Hex.swift */, 5F52D0BE21E3788900283CEA /* NSColor+Hex.swift */,
6FFACD1E21E4D89600E9A2A5 /* ParseError+WireGuardAppError.swift */, 6FFACD1E21E4D89600E9A2A5 /* ParseError+WireGuardAppError.swift */,
6BAC16E42216324B00A5FB78 /* AppStorePrivacyNotice.swift */,
); );
path = macOS; path = macOS;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -601,6 +650,8 @@
6FDB3C3A21DCF47400A0C0BF /* TunnelDetailTableViewController.swift */, 6FDB3C3A21DCF47400A0C0BF /* TunnelDetailTableViewController.swift */,
6FCD99A821E0E0C700BA4C82 /* ButtonedDetailViewController.swift */, 6FCD99A821E0E0C700BA4C82 /* ButtonedDetailViewController.swift */,
6FCD99B021E0EDA900BA4C82 /* TunnelEditViewController.swift */, 6FCD99B021E0EDA900BA4C82 /* TunnelEditViewController.swift */,
6FDB6D12224A15BE00EE4BC3 /* LogViewController.swift */,
6FADE96A2254A6C200B838A4 /* UnusableTunnelDetailViewController.swift */,
); );
path = ViewController; path = ViewController;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -667,6 +718,7 @@
6F5D0C1A218352EF000F85AD /* WireGuardNetworkExtension.appex */, 6F5D0C1A218352EF000F85AD /* WireGuardNetworkExtension.appex */,
6FB1BD5D21D2607A00A991BF /* WireGuard.app */, 6FB1BD5D21D2607A00A991BF /* WireGuard.app */,
6FB1BD9121D4BFE600A991BF /* WireGuardNetworkExtension.appex */, 6FB1BD9121D4BFE600A991BF /* WireGuardNetworkExtension.appex */,
6F70E22922106A2D008BDFB4 /* WireGuardLoginItemHelper.app */,
); );
name = Products; name = Products;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -753,6 +805,21 @@
productReference = 6F5D0C1A218352EF000F85AD /* WireGuardNetworkExtension.appex */; productReference = 6F5D0C1A218352EF000F85AD /* WireGuardNetworkExtension.appex */;
productType = "com.apple.product-type.app-extension"; productType = "com.apple.product-type.app-extension";
}; };
6F70E22822106A2D008BDFB4 /* WireGuardmacOSLoginItemHelper */ = {
isa = PBXNativeTarget;
buildConfigurationList = 6F70E23622106A31008BDFB4 /* Build configuration list for PBXNativeTarget "WireGuardmacOSLoginItemHelper" */;
buildPhases = (
6F70E22522106A2D008BDFB4 /* Sources */,
);
buildRules = (
);
dependencies = (
);
name = WireGuardmacOSLoginItemHelper;
productName = WireGuardmacOSLoginItemHelper;
productReference = 6F70E22922106A2D008BDFB4 /* WireGuardLoginItemHelper.app */;
productType = "com.apple.product-type.application";
};
6FB1BD5C21D2607A00A991BF /* WireGuardmacOS */ = { 6FB1BD5C21D2607A00A991BF /* WireGuardmacOS */ = {
isa = PBXNativeTarget; isa = PBXNativeTarget;
buildConfigurationList = 6FB1BD6A21D2607E00A991BF /* Build configuration list for PBXNativeTarget "WireGuardmacOS" */; buildConfigurationList = 6FB1BD6A21D2607E00A991BF /* Build configuration list for PBXNativeTarget "WireGuardmacOS" */;
@@ -764,10 +831,12 @@
6FB1BD5A21D2607A00A991BF /* Frameworks */, 6FB1BD5A21D2607A00A991BF /* Frameworks */,
6FB1BD5B21D2607A00A991BF /* Resources */, 6FB1BD5B21D2607A00A991BF /* Resources */,
6FB1BD9D21D4BFE700A991BF /* Embed App Extensions */, 6FB1BD9D21D4BFE700A991BF /* Embed App Extensions */,
6F70E23C22109DE5008BDFB4 /* Embed Login Item Helper */,
); );
buildRules = ( buildRules = (
); );
dependencies = ( dependencies = (
6F70E23B22109DD3008BDFB4 /* PBXTargetDependency */,
6FB1BD9821D4BFE700A991BF /* PBXTargetDependency */, 6FB1BD9821D4BFE700A991BF /* PBXTargetDependency */,
); );
name = WireGuardmacOS; name = WireGuardmacOS;
@@ -829,10 +898,19 @@
TargetAttributes = { TargetAttributes = {
6F5D0C19218352EF000F85AD = { 6F5D0C19218352EF000F85AD = {
CreatedOnToolsVersion = 10.0; CreatedOnToolsVersion = 10.0;
LastSwiftMigration = 1000; LastSwiftMigration = 1020;
};
6F70E22822106A2D008BDFB4 = {
CreatedOnToolsVersion = 10.1;
SystemCapabilities = {
com.apple.Sandbox = {
enabled = 1;
};
};
}; };
6FB1BD5C21D2607A00A991BF = { 6FB1BD5C21D2607A00A991BF = {
CreatedOnToolsVersion = 10.1; CreatedOnToolsVersion = 10.1;
LastSwiftMigration = 1020;
SystemCapabilities = { SystemCapabilities = {
com.apple.ApplicationGroups.Mac = { com.apple.ApplicationGroups.Mac = {
enabled = 1; enabled = 1;
@@ -847,6 +925,7 @@
}; };
6FB1BD9021D4BFE600A991BF = { 6FB1BD9021D4BFE600A991BF = {
CreatedOnToolsVersion = 10.1; CreatedOnToolsVersion = 10.1;
LastSwiftMigration = 1020;
SystemCapabilities = { SystemCapabilities = {
com.apple.ApplicationGroups.Mac = { com.apple.ApplicationGroups.Mac = {
enabled = 1; enabled = 1;
@@ -858,7 +937,7 @@
}; };
6FF4AC13211EC46F002C96EB = { 6FF4AC13211EC46F002C96EB = {
CreatedOnToolsVersion = 9.4.1; CreatedOnToolsVersion = 9.4.1;
LastSwiftMigration = 1000; LastSwiftMigration = 1020;
SystemCapabilities = { SystemCapabilities = {
com.apple.AccessWiFi = { com.apple.AccessWiFi = {
enabled = 1; enabled = 1;
@@ -892,6 +971,7 @@
6FB1BD5C21D2607A00A991BF /* WireGuardmacOS */, 6FB1BD5C21D2607A00A991BF /* WireGuardmacOS */,
6FB1BD9021D4BFE600A991BF /* WireGuardNetworkExtensionmacOS */, 6FB1BD9021D4BFE600A991BF /* WireGuardNetworkExtensionmacOS */,
6FDAA03421CE69D000FA6925 /* WireGuardGoBridgemacOS */, 6FDAA03421CE69D000FA6925 /* WireGuardGoBridgemacOS */,
6F70E22822106A2D008BDFB4 /* WireGuardmacOSLoginItemHelper */,
); );
}; };
/* End PBXProject section */ /* End PBXProject section */
@@ -1151,6 +1231,14 @@
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
6F70E22522106A2D008BDFB4 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
6B6956362211DA80001B618A /* main.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
6FB1BD5921D2607A00A991BF /* Sources */ = { 6FB1BD5921D2607A00A991BF /* Sources */ = {
isa = PBXSourcesBuildPhase; isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
@@ -1167,6 +1255,7 @@
6FB1BDD321D50F5300A991BF /* ZipArchive.swift in Sources */, 6FB1BDD321D50F5300A991BF /* ZipArchive.swift in Sources */,
6FB1BDD421D50F5300A991BF /* ioapi.c in Sources */, 6FB1BDD421D50F5300A991BF /* ioapi.c in Sources */,
6FDB3C3C21DCF6BB00A0C0BF /* TunnelViewModel.swift in Sources */, 6FDB3C3C21DCF6BB00A0C0BF /* TunnelViewModel.swift in Sources */,
6FDB6D13224A15BF00EE4BC3 /* LogViewController.swift in Sources */,
6B5C5E29220A48D30024272E /* Keychain.swift in Sources */, 6B5C5E29220A48D30024272E /* Keychain.swift in Sources */,
6FCD99AF21E0EA1700BA4C82 /* ImportPanelPresenter.swift in Sources */, 6FCD99AF21E0EA1700BA4C82 /* ImportPanelPresenter.swift in Sources */,
6FB1BDD521D50F5300A991BF /* unzip.c in Sources */, 6FB1BDD521D50F5300A991BF /* unzip.c in Sources */,
@@ -1187,7 +1276,6 @@
6FB1BDCA21D50F1700A991BF /* x25519.c in Sources */, 6FB1BDCA21D50F1700A991BF /* x25519.c in Sources */,
6FB1BDCB21D50F1700A991BF /* Curve25519.swift in Sources */, 6FB1BDCB21D50F1700A991BF /* Curve25519.swift in Sources */,
6B586C55220CBA6D00427C51 /* Data+KeyEncoding.swift in Sources */, 6B586C55220CBA6D00427C51 /* Data+KeyEncoding.swift in Sources */,
6BAC16E6221634B300A5FB78 /* AppStorePrivacyNotice.swift in Sources */,
6FB17946222FD5960018AE71 /* OnDemandWiFiControls.swift in Sources */, 6FB17946222FD5960018AE71 /* OnDemandWiFiControls.swift in Sources */,
6FB1BDBB21D50F0200A991BF /* Localizable.strings in Sources */, 6FB1BDBB21D50F0200A991BF /* Localizable.strings in Sources */,
6FB1BDBC21D50F0200A991BF /* ringlogger.c in Sources */, 6FB1BDBC21D50F0200A991BF /* ringlogger.c in Sources */,
@@ -1196,12 +1284,15 @@
6F89E17A21EDEB0E00C97BB9 /* StatusItemController.swift in Sources */, 6F89E17A21EDEB0E00C97BB9 /* StatusItemController.swift in Sources */,
6F5EA59B223E58A8002B380A /* ButtonRow.swift in Sources */, 6F5EA59B223E58A8002B380A /* ButtonRow.swift in Sources */,
6F4DD16B21DA558800690EAE /* TunnelListRow.swift in Sources */, 6F4DD16B21DA558800690EAE /* TunnelListRow.swift in Sources */,
6FDB6D15224CB2CE00EE4BC3 /* LogViewCell.swift in Sources */,
6FE3661D21F64F6B00F78C7D /* ConfTextColorTheme.swift in Sources */, 6FE3661D21F64F6B00F78C7D /* ConfTextColorTheme.swift in Sources */,
5F52D0BF21E3788900283CEA /* NSColor+Hex.swift in Sources */, 5F52D0BF21E3788900283CEA /* NSColor+Hex.swift in Sources */,
6FB1BDBE21D50F0200A991BF /* Logger.swift in Sources */, 6FB1BDBE21D50F0200A991BF /* Logger.swift in Sources */,
6FB1BDBF21D50F0200A991BF /* TunnelConfiguration+WgQuickConfig.swift in Sources */, 6FB1BDBF21D50F0200A991BF /* TunnelConfiguration+WgQuickConfig.swift in Sources */,
6FADE96C2254B8C300B838A4 /* UnusableTunnelDetailViewController.swift in Sources */,
6FFACD2021E4D8D500E9A2A5 /* ParseError+WireGuardAppError.swift in Sources */, 6FFACD2021E4D8D500E9A2A5 /* ParseError+WireGuardAppError.swift in Sources */,
6FB1BDC021D50F0200A991BF /* NETunnelProviderProtocol+Extension.swift in Sources */, 6FB1BDC021D50F0200A991BF /* NETunnelProviderProtocol+Extension.swift in Sources */,
6F1075642258AE9800D78929 /* DeleteTunnelsConfirmationAlert.swift in Sources */,
6FBA101821D656000051C35F /* StatusMenu.swift in Sources */, 6FBA101821D656000051C35F /* StatusMenu.swift in Sources */,
6F613D9B21DE33B8004B217A /* KeyValueRow.swift in Sources */, 6F613D9B21DE33B8004B217A /* KeyValueRow.swift in Sources */,
6FB1BDC121D50F0200A991BF /* String+ArrayConversion.swift in Sources */, 6FB1BDC121D50F0200A991BF /* String+ArrayConversion.swift in Sources */,
@@ -1214,6 +1305,7 @@
6FB1BDC521D50F0300A991BF /* Endpoint.swift in Sources */, 6FB1BDC521D50F0300A991BF /* Endpoint.swift in Sources */,
6FB1BDC621D50F0300A991BF /* DNSServer.swift in Sources */, 6FB1BDC621D50F0300A991BF /* DNSServer.swift in Sources */,
6FB1BDC721D50F0300A991BF /* InterfaceConfiguration.swift in Sources */, 6FB1BDC721D50F0300A991BF /* InterfaceConfiguration.swift in Sources */,
6F907C9D224663A2003CED21 /* LogViewHelper.swift in Sources */,
6FB1BDC821D50F0300A991BF /* PeerConfiguration.swift in Sources */, 6FB1BDC821D50F0300A991BF /* PeerConfiguration.swift in Sources */,
6FB1BDC921D50F0300A991BF /* FileManager+Extension.swift in Sources */, 6FB1BDC921D50F0300A991BF /* FileManager+Extension.swift in Sources */,
6FB1BD6021D2607A00A991BF /* AppDelegate.swift in Sources */, 6FB1BD6021D2607A00A991BF /* AppDelegate.swift in Sources */,
@@ -1264,6 +1356,7 @@
6B586C53220CBA6D00427C51 /* Data+KeyEncoding.swift in Sources */, 6B586C53220CBA6D00427C51 /* Data+KeyEncoding.swift in Sources */,
6F693A562179E556008551C1 /* Endpoint.swift in Sources */, 6F693A562179E556008551C1 /* Endpoint.swift in Sources */,
6FDEF7E62185EFB200D8FBF6 /* QRScanViewController.swift in Sources */, 6FDEF7E62185EFB200D8FBF6 /* QRScanViewController.swift in Sources */,
6FDB6D18224CC05A00EE4BC3 /* LogViewController.swift in Sources */,
6FFA5D952194454A0001E2F7 /* NETunnelProviderProtocol+Extension.swift in Sources */, 6FFA5D952194454A0001E2F7 /* NETunnelProviderProtocol+Extension.swift in Sources */,
5FF7B96221CC95DE00A7DD74 /* InterfaceConfiguration.swift in Sources */, 5FF7B96221CC95DE00A7DD74 /* InterfaceConfiguration.swift in Sources */,
5F4541A921C451D100994C13 /* TunnelStatus.swift in Sources */, 5F4541A921C451D100994C13 /* TunnelStatus.swift in Sources */,
@@ -1309,6 +1402,7 @@
6F7774E1217181B1006A79B3 /* MainViewController.swift in Sources */, 6F7774E1217181B1006A79B3 /* MainViewController.swift in Sources */,
6FFA5DA42197085D0001E2F7 /* ActivateOnDemandOption.swift in Sources */, 6FFA5DA42197085D0001E2F7 /* ActivateOnDemandOption.swift in Sources */,
5F4541B221CBFAEE00994C13 /* String+ArrayConversion.swift in Sources */, 5F4541B221CBFAEE00994C13 /* String+ArrayConversion.swift in Sources */,
6F907C9C224663A2003CED21 /* LogViewHelper.swift in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@@ -1320,6 +1414,11 @@
target = 6F5D0C19218352EF000F85AD /* WireGuardNetworkExtensioniOS */; target = 6F5D0C19218352EF000F85AD /* WireGuardNetworkExtensioniOS */;
targetProxy = 6F5D0C20218352EF000F85AD /* PBXContainerItemProxy */; targetProxy = 6F5D0C20218352EF000F85AD /* PBXContainerItemProxy */;
}; };
6F70E23B22109DD3008BDFB4 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 6F70E22822106A2D008BDFB4 /* WireGuardmacOSLoginItemHelper */;
targetProxy = 6F70E23A22109DD3008BDFB4 /* PBXContainerItemProxy */;
};
6FB1BD9821D4BFE700A991BF /* PBXTargetDependency */ = { 6FB1BD9821D4BFE700A991BF /* PBXTargetDependency */ = {
isa = PBXTargetDependency; isa = PBXTargetDependency;
target = 6FB1BD9021D4BFE600A991BF /* WireGuardNetworkExtensionmacOS */; target = 6FB1BD9021D4BFE600A991BF /* WireGuardNetworkExtensionmacOS */;
@@ -1383,7 +1482,7 @@
PRODUCT_NAME = WireGuardNetworkExtension; PRODUCT_NAME = WireGuardNetworkExtension;
SKIP_INSTALL = YES; SKIP_INSTALL = YES;
SWIFT_OBJC_BRIDGING_HEADER = "WireGuardNetworkExtension/WireGuardNetworkExtension-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "WireGuardNetworkExtension/WireGuardNetworkExtension-Bridging-Header.h";
SWIFT_VERSION = 4.2; SWIFT_VERSION = 5.0;
}; };
name = Debug; name = Debug;
}; };
@@ -1405,7 +1504,33 @@
PRODUCT_NAME = WireGuardNetworkExtension; PRODUCT_NAME = WireGuardNetworkExtension;
SKIP_INSTALL = YES; SKIP_INSTALL = YES;
SWIFT_OBJC_BRIDGING_HEADER = "WireGuardNetworkExtension/WireGuardNetworkExtension-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "WireGuardNetworkExtension/WireGuardNetworkExtension-Bridging-Header.h";
SWIFT_VERSION = 4.2; SWIFT_VERSION = 5.0;
};
name = Release;
};
6F70E23422106A31008BDFB4 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_ENTITLEMENTS = WireGuard/UI/macOS/LoginItemHelper/LoginItemHelper.entitlements;
CODE_SIGN_IDENTITY = "Mac Developer";
INFOPLIST_FILE = WireGuard/UI/macOS/Info.plist;
PRODUCT_BUNDLE_IDENTIFIER = "$(APP_ID_MACOS).login-item-helper";
PRODUCT_NAME = WireGuardLoginItemHelper;
SDKROOT = macosx;
SKIP_INSTALL = YES;
};
name = Debug;
};
6F70E23522106A31008BDFB4 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_ENTITLEMENTS = WireGuard/UI/macOS/LoginItemHelper/LoginItemHelper.entitlements;
CODE_SIGN_IDENTITY = "Mac Developer";
INFOPLIST_FILE = WireGuard/UI/macOS/Info.plist;
PRODUCT_BUNDLE_IDENTIFIER = "$(APP_ID_MACOS).login-item-helper";
PRODUCT_NAME = WireGuardLoginItemHelper;
SDKROOT = macosx;
SKIP_INSTALL = YES;
}; };
name = Release; name = Release;
}; };
@@ -1425,6 +1550,7 @@
PRODUCT_BUNDLE_IDENTIFIER = "$(APP_ID_MACOS)"; PRODUCT_BUNDLE_IDENTIFIER = "$(APP_ID_MACOS)";
PRODUCT_NAME = WireGuard; PRODUCT_NAME = WireGuard;
SDKROOT = macosx; SDKROOT = macosx;
SWIFT_VERSION = 5.0;
}; };
name = Debug; name = Debug;
}; };
@@ -1444,6 +1570,7 @@
PRODUCT_BUNDLE_IDENTIFIER = "$(APP_ID_MACOS)"; PRODUCT_BUNDLE_IDENTIFIER = "$(APP_ID_MACOS)";
PRODUCT_NAME = WireGuard; PRODUCT_NAME = WireGuard;
SDKROOT = macosx; SDKROOT = macosx;
SWIFT_VERSION = 5.0;
}; };
name = Release; name = Release;
}; };
@@ -1465,6 +1592,7 @@
SDKROOT = macosx; SDKROOT = macosx;
SKIP_INSTALL = YES; SKIP_INSTALL = YES;
SWIFT_OBJC_BRIDGING_HEADER = "WireGuardNetworkExtension/WireGuardNetworkExtension-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "WireGuardNetworkExtension/WireGuardNetworkExtension-Bridging-Header.h";
SWIFT_VERSION = 5.0;
}; };
name = Debug; name = Debug;
}; };
@@ -1486,6 +1614,7 @@
SDKROOT = macosx; SDKROOT = macosx;
SKIP_INSTALL = YES; SKIP_INSTALL = YES;
SWIFT_OBJC_BRIDGING_HEADER = "WireGuardNetworkExtension/WireGuardNetworkExtension-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "WireGuardNetworkExtension/WireGuardNetworkExtension-Bridging-Header.h";
SWIFT_VERSION = 5.0;
}; };
name = Release; name = Release;
}; };
@@ -1662,6 +1791,7 @@
); );
PRODUCT_BUNDLE_IDENTIFIER = "$(APP_ID_IOS)"; PRODUCT_BUNDLE_IDENTIFIER = "$(APP_ID_IOS)";
PRODUCT_NAME = WireGuard; PRODUCT_NAME = WireGuard;
SWIFT_VERSION = 5.0;
}; };
name = Debug; name = Debug;
}; };
@@ -1678,6 +1808,7 @@
); );
PRODUCT_BUNDLE_IDENTIFIER = "$(APP_ID_IOS)"; PRODUCT_BUNDLE_IDENTIFIER = "$(APP_ID_IOS)";
PRODUCT_NAME = WireGuard; PRODUCT_NAME = WireGuard;
SWIFT_VERSION = 5.0;
}; };
name = Release; name = Release;
}; };
@@ -1693,6 +1824,15 @@
defaultConfigurationIsVisible = 0; defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release; defaultConfigurationName = Release;
}; };
6F70E23622106A31008BDFB4 /* Build configuration list for PBXNativeTarget "WireGuardmacOSLoginItemHelper" */ = {
isa = XCConfigurationList;
buildConfigurations = (
6F70E23422106A31008BDFB4 /* Debug */,
6F70E23522106A31008BDFB4 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
6FB1BD6A21D2607E00A991BF /* Build configuration list for PBXNativeTarget "WireGuardmacOS" */ = { 6FB1BD6A21D2607E00A991BF /* Build configuration list for PBXNativeTarget "WireGuardmacOS" */ = {
isa = XCConfigurationList; isa = XCConfigurationList;
buildConfigurations = ( buildConfigurations = (
@@ -209,10 +209,14 @@
"settingsSectionTitleExportConfigurations" = "Export configurations"; "settingsSectionTitleExportConfigurations" = "Export configurations";
"settingsExportZipButtonTitle" = "Export zip archive"; "settingsExportZipButtonTitle" = "Export zip archive";
"settingsSectionTitleTunnelLog" = "Tunnel log"; "settingsSectionTitleTunnelLog" = "Log";
"settingsExportLogFileButtonTitle" = "Export log file"; "settingsViewLogButtonTitle" = "View log";
// Settings alerts // Log view
"logViewTitle" = "Log";
// Log alerts
"alertUnableToRemovePreviousLogTitle" = "Log export failed"; "alertUnableToRemovePreviousLogTitle" = "Log export failed";
"alertUnableToRemovePreviousLogMessage" = "The pre-existing log could not be cleared"; "alertUnableToRemovePreviousLogMessage" = "The pre-existing log could not be cleared";
@@ -296,7 +300,7 @@
"macMenuManageTunnels" = "Manage tunnels"; "macMenuManageTunnels" = "Manage tunnels";
"macMenuImportTunnels" = "Import tunnel(s) from file…"; "macMenuImportTunnels" = "Import tunnel(s) from file…";
"macMenuAddEmptyTunnel" = "Add empty tunnel…"; "macMenuAddEmptyTunnel" = "Add empty tunnel…";
"macMenuExportLog" = "Export log to file…"; "macMenuViewLog" = "View log";
"macMenuExportTunnels" = "Export tunnels to zip…"; "macMenuExportTunnels" = "Export tunnels to zip…";
"macMenuAbout" = "About WireGuard"; "macMenuAbout" = "About WireGuard";
"macMenuQuit" = "Quit"; "macMenuQuit" = "Quit";
@@ -310,14 +314,15 @@
"macDeleteTunnelConfirmationAlertInfo" = "You cannot undo this action."; "macDeleteTunnelConfirmationAlertInfo" = "You cannot undo this action.";
"macDeleteTunnelConfirmationAlertButtonTitleDelete" = "Delete"; "macDeleteTunnelConfirmationAlertButtonTitleDelete" = "Delete";
"macDeleteTunnelConfirmationAlertButtonTitleCancel" = "Cancel"; "macDeleteTunnelConfirmationAlertButtonTitleCancel" = "Cancel";
"macDeleteTunnelConfirmationAlertButtonTitleDeleting" = "Deleting…";
"macButtonImportTunnels" = "Import tunnel(s) from file"; "macButtonImportTunnels" = "Import tunnel(s) from file";
"macSheetButtonImport" = "Import"; "macSheetButtonImport" = "Import";
"macNameFieldExportLog" = "Export log to"; "macNameFieldExportLog" = "Save log to:";
"macSheetButtonExportLog" = "Save"; "macSheetButtonExportLog" = "Save";
"macNameFieldExportZip" = "Export tunnels to"; "macNameFieldExportZip" = "Export tunnels to:";
"macSheetButtonExportZip" = "Save"; "macSheetButtonExportZip" = "Save";
"macButtonDeleteTunnels (%d)" = "Delete %d tunnels"; "macButtonDeleteTunnels (%d)" = "Delete %d tunnels";
@@ -387,3 +392,16 @@
"macToolTipEditTunnel" = "Edit tunnel (⌘E)"; "macToolTipEditTunnel" = "Edit tunnel (⌘E)";
"macToolTipToggleStatus" = "Toggle status (⌘T)"; "macToolTipToggleStatus" = "Toggle status (⌘T)";
// Mac log view
"macLogColumnTitleTime" = "Time";
"macLogColumnTitleLogMessage" = "Log message";
"macLogButtonTitleClose" = "Close";
"macLogButtonTitleSave" = "Save…";
// Mac unusable tunnel view
"macUnusableTunnelMessage" = "The configuration for this tunnel cannot be found in the keychain.";
"macUnusableTunnelInfo" = "In case this tunnel was created by another user, only that user can view, edit, or activate this tunnel.";
"macUnusableTunnelButtonTitleDeleteTunnel" = "Delete tunnel";
+2 -2
View File
@@ -1,2 +1,2 @@
VERSION_NAME = 0.0.20190319 VERSION_NAME = 0.0.20190409
VERSION_ID = 5 VERSION_ID = 7
+3 -3
View File
@@ -9,7 +9,7 @@ struct Curve25519 {
static func generatePrivateKey() -> Data { static func generatePrivateKey() -> Data {
var privateKey = Data(repeating: 0, count: TunnelConfiguration.keyLength) var privateKey = Data(repeating: 0, count: TunnelConfiguration.keyLength)
privateKey.withUnsafeMutableBytes { bytes in privateKey.withUnsafeMutableUInt8Bytes { bytes in
curve25519_generate_private_key(bytes) curve25519_generate_private_key(bytes)
} }
assert(privateKey.count == TunnelConfiguration.keyLength) assert(privateKey.count == TunnelConfiguration.keyLength)
@@ -19,8 +19,8 @@ struct Curve25519 {
static func generatePublicKey(fromPrivateKey privateKey: Data) -> Data { static func generatePublicKey(fromPrivateKey privateKey: Data) -> Data {
assert(privateKey.count == TunnelConfiguration.keyLength) assert(privateKey.count == TunnelConfiguration.keyLength)
var publicKey = Data(repeating: 0, count: TunnelConfiguration.keyLength) var publicKey = Data(repeating: 0, count: TunnelConfiguration.keyLength)
privateKey.withUnsafeBytes { privateKeyBytes in privateKey.withUnsafeUInt8Bytes { privateKeyBytes in
publicKey.withUnsafeMutableBytes { bytes in publicKey.withUnsafeMutableUInt8Bytes { bytes in
curve25519_derive_public_key(bytes, privateKeyBytes) curve25519_derive_public_key(bytes, privateKeyBytes)
} }
} }
@@ -27,6 +27,8 @@ import NetworkExtension
self = .reasserting self = .reasserting
case .invalid: case .invalid:
self = .inactive self = .inactive
@unknown default:
fatalError()
} }
} }
} }
@@ -54,6 +56,8 @@ extension NEVPNStatus: CustomDebugStringConvertible {
case .disconnecting: return "disconnecting" case .disconnecting: return "disconnecting"
case .reasserting: return "reasserting" case .reasserting: return "reasserting"
case .invalid: return "invalid" case .invalid: return "invalid"
@unknown default:
fatalError()
} }
} }
} }
@@ -47,11 +47,18 @@ class TunnelsManager {
var tunnelManagers = managers ?? [] var tunnelManagers = managers ?? []
var refs: Set<Data> = [] var refs: Set<Data> = []
for (index, tunnelManager) in tunnelManagers.enumerated().reversed() { for (index, tunnelManager) in tunnelManagers.enumerated().reversed() {
let proto = tunnelManager.protocolConfiguration as? NETunnelProviderProtocol guard let proto = tunnelManager.protocolConfiguration as? NETunnelProviderProtocol else { continue }
if proto?.migrateConfigurationIfNeeded(called: tunnelManager.localizedDescription ?? "unknown") ?? false { if proto.migrateConfigurationIfNeeded(called: tunnelManager.localizedDescription ?? "unknown") {
tunnelManager.saveToPreferences { _ in } tunnelManager.saveToPreferences { _ in }
} }
if let ref = proto?.verifyConfigurationReference() { #if os(iOS)
let passwordRef = proto.verifyConfigurationReference() ? proto.passwordReference : nil
#elseif os(macOS)
let passwordRef = proto.passwordReference // To handle multiple users in macOS, we skip verifying
#else
#error("Unimplemented")
#endif
if let ref = passwordRef {
refs.insert(ref) refs.insert(ref)
} else { } else {
tunnelManager.removeFromPreferences { _ in } tunnelManager.removeFromPreferences { _ in }
@@ -71,14 +78,14 @@ class TunnelsManager {
let loadedTunnelProviders = managers ?? [] let loadedTunnelProviders = managers ?? []
for (index, currentTunnel) in self.tunnels.enumerated().reversed() { for (index, currentTunnel) in self.tunnels.enumerated().reversed() {
if !loadedTunnelProviders.contains(where: { $0.tunnelConfiguration == currentTunnel.tunnelConfiguration }) { if !loadedTunnelProviders.contains(where: { $0.isEquivalentTo(currentTunnel) }) {
// Tunnel was deleted outside the app // Tunnel was deleted outside the app
self.tunnels.remove(at: index) self.tunnels.remove(at: index)
self.tunnelsListDelegate?.tunnelRemoved(at: index, tunnel: currentTunnel) self.tunnelsListDelegate?.tunnelRemoved(at: index, tunnel: currentTunnel)
} }
} }
for loadedTunnelProvider in loadedTunnelProviders { for loadedTunnelProvider in loadedTunnelProviders {
if let matchingTunnel = self.tunnels.first(where: { $0.tunnelConfiguration == loadedTunnelProvider.tunnelConfiguration }) { if let matchingTunnel = self.tunnels.first(where: { loadedTunnelProvider.isEquivalentTo($0) }) {
matchingTunnel.tunnelProvider = loadedTunnelProvider matchingTunnel.tunnelProvider = loadedTunnelProvider
matchingTunnel.refreshStatus() matchingTunnel.refreshStatus()
} else { } else {
@@ -238,7 +245,9 @@ class TunnelsManager {
func remove(tunnel: TunnelContainer, completionHandler: @escaping (TunnelsManagerError?) -> Void) { func remove(tunnel: TunnelContainer, completionHandler: @escaping (TunnelsManagerError?) -> Void) {
let tunnelProviderManager = tunnel.tunnelProvider let tunnelProviderManager = tunnel.tunnelProvider
(tunnelProviderManager.protocolConfiguration as? NETunnelProviderProtocol)?.destroyConfigurationReference() if tunnel.isTunnelConfigurationAvailableInKeychain {
(tunnelProviderManager.protocolConfiguration as? NETunnelProviderProtocol)?.destroyConfigurationReference()
}
tunnelProviderManager.removeFromPreferences { [weak self] error in tunnelProviderManager.removeFromPreferences { [weak self] error in
guard error == nil else { guard error == nil else {
@@ -455,6 +464,10 @@ class TunnelContainer: NSObject {
return tunnelProvider.tunnelConfiguration return tunnelProvider.tunnelConfiguration
} }
var isTunnelConfigurationAvailableInKeychain: Bool {
return tunnelProvider.isTunnelConfigurationAvailableInKeychain
}
var onDemandOption: ActivateOnDemandOption { var onDemandOption: ActivateOnDemandOption {
return ActivateOnDemandOption(from: tunnelProvider) return ActivateOnDemandOption(from: tunnelProvider)
} }
@@ -473,7 +486,7 @@ class TunnelContainer: NSObject {
completionHandler(tunnelConfiguration) completionHandler(tunnelConfiguration)
return return
} }
guard nil != (try? session.sendProviderMessage(Data(bytes: [ 0 ]), responseHandler: { guard nil != (try? session.sendProviderMessage(Data([ UInt8(0) ]), responseHandler: {
guard self.status != .inactive, let data = $0, let base = self.tunnelConfiguration, let settings = String(data: data, encoding: .utf8) else { guard self.status != .inactive, let data = $0, let base = self.tunnelConfiguration, let settings = String(data: data, encoding: .utf8) else {
completionHandler(self.tunnelConfiguration) completionHandler(self.tunnelConfiguration)
return return
@@ -567,7 +580,18 @@ class TunnelContainer: NSObject {
} }
extension NETunnelProviderManager { extension NETunnelProviderManager {
private static var cachedIsConfigAvailableInKeychainKey: UInt8 = 0
private static var cachedConfigKey: UInt8 = 0 private static var cachedConfigKey: UInt8 = 0
var isTunnelConfigurationAvailableInKeychain: Bool {
if let cachedNumber = objc_getAssociatedObject(self, &NETunnelProviderManager.cachedIsConfigAvailableInKeychainKey) as? NSNumber {
return cachedNumber.boolValue
}
let isAvailable = (protocolConfiguration as? NETunnelProviderProtocol)?.verifyConfigurationReference() ?? false
objc_setAssociatedObject(self, &NETunnelProviderManager.cachedIsConfigAvailableInKeychainKey, NSNumber(value: isAvailable), objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
return isAvailable
}
var tunnelConfiguration: TunnelConfiguration? { var tunnelConfiguration: TunnelConfiguration? {
if let cached = objc_getAssociatedObject(self, &NETunnelProviderManager.cachedConfigKey) as? TunnelConfiguration { if let cached = objc_getAssociatedObject(self, &NETunnelProviderManager.cachedConfigKey) as? TunnelConfiguration {
return cached return cached
@@ -583,5 +607,17 @@ extension NETunnelProviderManager {
protocolConfiguration = NETunnelProviderProtocol(tunnelConfiguration: tunnelConfiguration, previouslyFrom: protocolConfiguration) protocolConfiguration = NETunnelProviderProtocol(tunnelConfiguration: tunnelConfiguration, previouslyFrom: protocolConfiguration)
localizedDescription = tunnelConfiguration.name localizedDescription = tunnelConfiguration.name
objc_setAssociatedObject(self, &NETunnelProviderManager.cachedConfigKey, tunnelConfiguration, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC) objc_setAssociatedObject(self, &NETunnelProviderManager.cachedConfigKey, tunnelConfiguration, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
objc_setAssociatedObject(self, &NETunnelProviderManager.cachedIsConfigAvailableInKeychainKey, NSNumber(value: true), objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
func isEquivalentTo(_ tunnel: TunnelContainer) -> Bool {
switch (isTunnelConfigurationAvailableInKeychain, tunnel.isTunnelConfigurationAvailableInKeychain) {
case (true, true):
return tunnelConfiguration == tunnel.tunnelConfiguration
case (false, false):
return localizedDescription == tunnel.name
default:
return false
}
} }
} }
@@ -0,0 +1,57 @@
// SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
import Foundation
public class LogViewHelper {
var log: OpaquePointer
var cursor: UInt32 = UINT32_MAX
static let formatOptions: ISO8601DateFormatter.Options = [
.withYear, .withMonth, .withDay, .withTime,
.withDashSeparatorInDate, .withColonSeparatorInTime, .withSpaceBetweenDateAndTime,
.withFractionalSeconds
]
struct LogEntry {
let timestamp: String
let message: String
func text() -> String {
return timestamp + " " + message
}
}
class LogEntries {
var entries: [LogEntry] = []
}
init?(logFilePath: String?) {
guard let logFilePath = logFilePath else { return nil }
guard let log = open_log(logFilePath) else { return nil }
self.log = log
}
deinit {
close_log(self.log)
}
func fetchLogEntriesSinceLastFetch(completion: @escaping ([LogViewHelper.LogEntry]) -> Void) {
var logEntries = LogEntries()
DispatchQueue.global(qos: .userInitiated).async { [weak self] in
guard let self = self else { return }
let newCursor = view_lines_from_cursor(self.log, self.cursor, &logEntries) { cStr, timestamp, ctx in
let message = cStr != nil ? String(cString: cStr!) : ""
let date = Date(timeIntervalSince1970: Double(timestamp) / 1000000000)
let dateString = ISO8601DateFormatter.string(from: date, timeZone: TimeZone.current, formatOptions: LogViewHelper.formatOptions)
if let logEntries = ctx?.bindMemory(to: LogEntries.self, capacity: 1) {
logEntries.pointee.entries.append(LogEntry(timestamp: dateString, message: message))
}
}
DispatchQueue.main.async { [weak self] in
guard let self = self else { return }
self.cursor = newCursor
completion(logEntries.entries)
}
}
}
}
-1
View File
@@ -82,7 +82,6 @@
<string>LaunchScreen</string> <string>LaunchScreen</string>
<key>UIRequiredDeviceCapabilities</key> <key>UIRequiredDeviceCapabilities</key>
<array> <array>
<string>armv7</string>
</array> </array>
<key>UISupportedInterfaceOrientations</key> <key>UISupportedInterfaceOrientations</key>
<array> <array>
@@ -0,0 +1,129 @@
// SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
import UIKit
class LogViewController: UIViewController {
let textView: UITextView = {
let textView = UITextView()
textView.isEditable = false
textView.isSelectable = true
textView.font = UIFont.preferredFont(forTextStyle: UIFont.TextStyle.body)
textView.adjustsFontForContentSizeCategory = true
return textView
}()
let busyIndicator: UIActivityIndicatorView = {
let busyIndicator = UIActivityIndicatorView(style: .gray)
busyIndicator.hidesWhenStopped = true
return busyIndicator
}()
var logViewHelper: LogViewHelper?
var isFetchingLogEntries = false
private var updateLogEntriesTimer: Timer?
override func loadView() {
view = UIView()
view.backgroundColor = .white
view.addSubview(textView)
textView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
textView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
textView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
textView.topAnchor.constraint(equalTo: view.topAnchor),
textView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
])
view.addSubview(busyIndicator)
busyIndicator.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
busyIndicator.centerXAnchor.constraint(equalTo: view.centerXAnchor),
busyIndicator.centerYAnchor.constraint(equalTo: view.centerYAnchor)
])
busyIndicator.startAnimating()
logViewHelper = LogViewHelper(logFilePath: FileManager.logFileURL?.path)
startUpdatingLogEntries()
}
override func viewDidLoad() {
title = tr("logViewTitle")
navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .save, target: self, action: #selector(saveTapped(sender:)))
}
func updateLogEntries() {
guard !isFetchingLogEntries else { return }
isFetchingLogEntries = true
logViewHelper?.fetchLogEntriesSinceLastFetch { [weak self] fetchedLogEntries in
guard let self = self else { return }
defer {
self.isFetchingLogEntries = false
}
if self.busyIndicator.isAnimating {
self.busyIndicator.stopAnimating()
}
guard !fetchedLogEntries.isEmpty else { return }
let isScrolledToEnd = self.textView.contentSize.height - self.textView.bounds.height - self.textView.contentOffset.y < 1
let text = fetchedLogEntries.reduce("") { $0 + $1.text() + "\n" }
let font = UIFont.preferredFont(forTextStyle: UIFont.TextStyle.body)
let richText = NSAttributedString(string: text, attributes: [.font: font])
self.textView.textStorage.append(richText)
if isScrolledToEnd {
let endOfCurrentText = NSRange(location: (self.textView.text as NSString).length, length: 0)
self.textView.scrollRangeToVisible(endOfCurrentText)
}
}
}
func startUpdatingLogEntries() {
updateLogEntries()
updateLogEntriesTimer?.invalidate()
let timer = Timer(timeInterval: 1 /* second */, repeats: true) { [weak self] _ in
self?.updateLogEntries()
}
updateLogEntriesTimer = timer
RunLoop.main.add(timer, forMode: .common)
}
@objc func saveTapped(sender: AnyObject) {
guard let destinationDir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { return }
let dateFormatter = ISO8601DateFormatter()
dateFormatter.formatOptions = [.withFullDate, .withTime, .withTimeZone] // Avoid ':' in the filename
let timeStampString = dateFormatter.string(from: Date())
let destinationURL = destinationDir.appendingPathComponent("wireguard-log-\(timeStampString).txt")
DispatchQueue.global(qos: .userInitiated).async {
if FileManager.default.fileExists(atPath: destinationURL.path) {
let isDeleted = FileManager.deleteFile(at: destinationURL)
if !isDeleted {
ErrorPresenter.showErrorAlert(title: tr("alertUnableToRemovePreviousLogTitle"), message: tr("alertUnableToRemovePreviousLogMessage"), from: self)
return
}
}
let isWritten = Logger.global?.writeLog(to: destinationURL.path) ?? false
DispatchQueue.main.async {
guard isWritten else {
ErrorPresenter.showErrorAlert(title: tr("alertUnableToWriteLogTitle"), message: tr("alertUnableToWriteLogMessage"), from: self)
return
}
let activityVC = UIActivityViewController(activityItems: [destinationURL], applicationActivities: nil)
if let sender = sender as? UIBarButtonItem {
activityVC.popoverPresentationController?.barButtonItem = sender
}
activityVC.completionWithItemsHandler = { _, _, _, _ in
// Remove the exported log file after the activity has completed
_ = FileManager.deleteFile(at: destinationURL)
}
self.present(activityVC, animated: true)
}
}
}
}
@@ -10,14 +10,14 @@ class SettingsTableViewController: UITableViewController {
case iosAppVersion case iosAppVersion
case goBackendVersion case goBackendVersion
case exportZipArchive case exportZipArchive
case exportLogFile case viewLog
var localizedUIString: String { var localizedUIString: String {
switch self { switch self {
case .iosAppVersion: return tr("settingsVersionKeyWireGuardForIOS") case .iosAppVersion: return tr("settingsVersionKeyWireGuardForIOS")
case .goBackendVersion: return tr("settingsVersionKeyWireGuardGoBackend") case .goBackendVersion: return tr("settingsVersionKeyWireGuardGoBackend")
case .exportZipArchive: return tr("settingsExportZipButtonTitle") case .exportZipArchive: return tr("settingsExportZipButtonTitle")
case .exportLogFile: return tr("settingsExportLogFileButtonTitle") case .viewLog: return tr("settingsViewLogButtonTitle")
} }
} }
} }
@@ -25,7 +25,7 @@ class SettingsTableViewController: UITableViewController {
let settingsFieldsBySection: [[SettingsFields]] = [ let settingsFieldsBySection: [[SettingsFields]] = [
[.iosAppVersion, .goBackendVersion], [.iosAppVersion, .goBackendVersion],
[.exportZipArchive], [.exportZipArchive],
[.exportLogFile] [.viewLog]
] ]
let tunnelsManager: TunnelsManager? let tunnelsManager: TunnelsManager?
@@ -108,41 +108,10 @@ class SettingsTableViewController: UITableViewController {
} }
} }
func exportLogForLastActivatedTunnel(sourceView: UIView) { func presentLogView() {
guard let destinationDir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { return } let logVC = LogViewController()
navigationController?.pushViewController(logVC, animated: true)
let dateFormatter = ISO8601DateFormatter()
dateFormatter.formatOptions = [.withFullDate, .withTime, .withTimeZone] // Avoid ':' in the filename
let timeStampString = dateFormatter.string(from: Date())
let destinationURL = destinationDir.appendingPathComponent("wireguard-log-\(timeStampString).txt")
DispatchQueue.global(qos: .userInitiated).async {
if FileManager.default.fileExists(atPath: destinationURL.path) {
let isDeleted = FileManager.deleteFile(at: destinationURL)
if !isDeleted {
ErrorPresenter.showErrorAlert(title: tr("alertUnableToRemovePreviousLogTitle"), message: tr("alertUnableToRemovePreviousLogMessage"), from: self)
return
}
}
let isWritten = Logger.global?.writeLog(to: destinationURL.path) ?? false
DispatchQueue.main.async {
guard isWritten else {
ErrorPresenter.showErrorAlert(title: tr("alertUnableToWriteLogTitle"), message: tr("alertUnableToWriteLogMessage"), from: self)
return
}
let activityVC = UIActivityViewController(activityItems: [destinationURL], applicationActivities: nil)
activityVC.popoverPresentationController?.sourceView = sourceView
activityVC.popoverPresentationController?.sourceRect = sourceView.bounds
activityVC.completionWithItemsHandler = { _, _, _, _ in
// Remove the exported log file after the activity has completed
_ = FileManager.deleteFile(at: destinationURL)
}
self.present(activityVC, animated: true)
}
}
} }
} }
@@ -192,11 +161,11 @@ extension SettingsTableViewController {
} }
return cell return cell
} else { } else {
assert(field == .exportLogFile) assert(field == .viewLog)
let cell: ButtonCell = tableView.dequeueReusableCell(for: indexPath) let cell: ButtonCell = tableView.dequeueReusableCell(for: indexPath)
cell.buttonText = field.localizedUIString cell.buttonText = field.localizedUIString
cell.onTapped = { [weak self] in cell.onTapped = { [weak self] in
self?.exportLogForLastActivatedTunnel(sourceView: cell.button) self?.presentLogView()
} }
return cell return cell
} }
+19 -2
View File
@@ -2,6 +2,7 @@
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved. // Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
import Cocoa import Cocoa
import ServiceManagement
@NSApplicationMain @NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate { class AppDelegate: NSObject, NSApplicationDelegate {
@@ -15,6 +16,7 @@ class AppDelegate: NSObject, NSApplicationDelegate {
func applicationDidFinishLaunching(_ aNotification: Notification) { func applicationDidFinishLaunching(_ aNotification: Notification) {
Logger.configureGlobal(tagged: "APP", withFilePath: FileManager.logFileURL?.path) Logger.configureGlobal(tagged: "APP", withFilePath: FileManager.logFileURL?.path)
registerLoginItem(shouldLaunchAtLogin: true)
TunnelsManager.create { [weak self] result in TunnelsManager.create { [weak self] result in
guard let self = self else { return } guard let self = self else { return }
@@ -42,6 +44,12 @@ class AppDelegate: NSObject, NSApplicationDelegate {
} }
@objc func quit() { @objc func quit() {
if let manageWindow = manageTunnelsWindowObject, manageWindow.attachedSheet != nil {
NSApp.activate(ignoringOtherApps: true)
manageWindow.orderFront(self)
return
}
registerLoginItem(shouldLaunchAtLogin: false)
guard let currentTunnel = tunnelsTracker?.currentTunnel, currentTunnel.status == .active || currentTunnel.status == .activating else { guard let currentTunnel = tunnelsTracker?.currentTunnel, currentTunnel.status == .active || currentTunnel.status == .activating else {
NSApp.terminate(nil) NSApp.terminate(nil)
return return
@@ -49,8 +57,10 @@ class AppDelegate: NSObject, NSApplicationDelegate {
let alert = NSAlert() let alert = NSAlert()
alert.messageText = tr("macAppExitingWithActiveTunnelMessage") alert.messageText = tr("macAppExitingWithActiveTunnelMessage")
alert.informativeText = tr("macAppExitingWithActiveTunnelInfo") alert.informativeText = tr("macAppExitingWithActiveTunnelInfo")
if let window = manageTunnelsWindowObject { NSApp.activate(ignoringOtherApps: true)
alert.beginSheetModal(for: window) { _ in if let manageWindow = manageTunnelsWindowObject {
manageWindow.orderFront(self)
alert.beginSheetModal(for: manageWindow) { _ in
NSApp.terminate(nil) NSApp.terminate(nil)
} }
} else { } else {
@@ -74,3 +84,10 @@ extension AppDelegate: StatusMenuWindowDelegate {
return manageTunnelsWindowObject! return manageTunnelsWindowObject!
} }
} }
@discardableResult
func registerLoginItem(shouldLaunchAtLogin: Bool) -> Bool {
let appId = Bundle.main.bundleIdentifier!
let helperBundleId = "\(appId).login-item-helper"
return SMLoginItemSetEnabled(helperBundleId as CFString, shouldLaunchAtLogin)
}
@@ -1,29 +0,0 @@
// SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
import Cocoa
class AppStorePrivacyNotice {
// The App Store Review Board does not comprehend the fact that this application
// is not a service and does not have any servers of its own. They therefore require
// us to give a notice regarding collection of user data using our non-existent
// servers. This demand is obviously impossible to fulfill, since it doesn't make sense,
// but we do our best here to show something in that category.
static func show(from sourceVC: NSViewController?, into tunnelsManager: TunnelsManager, _ callback: @escaping () -> Void) {
if tunnelsManager.numberOfTunnels() > 0 {
callback()
return
}
let alert = NSAlert()
alert.messageText = tr("macPrivacyNoticeMessage")
alert.informativeText = tr("macPrivacyNoticeInfo")
alert.alertStyle = NSAlert.Style.warning
if let window = sourceVC?.view.window {
alert.beginSheetModal(for: window) { _ in callback() }
} else {
alert.runModal()
callback()
}
}
}
@@ -13,9 +13,7 @@ class ImportPanelPresenter {
openPanel.beginSheetModal(for: window) { [weak tunnelsManager] response in openPanel.beginSheetModal(for: window) { [weak tunnelsManager] response in
guard let tunnelsManager = tunnelsManager else { return } guard let tunnelsManager = tunnelsManager else { return }
guard response == .OK else { return } guard response == .OK else { return }
AppStorePrivacyNotice.show(from: sourceVC, into: tunnelsManager) { TunnelImporter.importFromFile(urls: openPanel.urls, into: tunnelsManager, sourceVC: sourceVC, errorPresenterType: ErrorPresenter.self)
TunnelImporter.importFromFile(urls: openPanel.urls, into: tunnelsManager, sourceVC: sourceVC, errorPresenterType: ErrorPresenter.self)
}
} }
} }
} }
@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIconFile</key>
<string></string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSMinimumSystemVersion</key>
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
<key>LSBackgroundOnly</key>
<true/>
</dict>
</plist>
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
</dict>
</plist>
@@ -0,0 +1,16 @@
// SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
#import <Cocoa/Cocoa.h>
int main(int argc, char *argv[])
{
NSURL *bundleURL = [NSBundle.mainBundle bundleURL];
// From <path>/WireGuard.app/Contents/Library/LoginItems/WireGuardLoginItemHelper.app, derive <path>/WireGuard.app
for (int i = 0; i < 4; ++i)
bundleURL = [bundleURL URLByDeletingLastPathComponent];
[NSWorkspace.sharedWorkspace launchApplication:[bundleURL path]];
return 0;
}
@@ -184,6 +184,7 @@ extension StatusMenu {
func insertTunnelMenuItem(for tunnel: TunnelContainer, at tunnelIndex: Int) { func insertTunnelMenuItem(for tunnel: TunnelContainer, at tunnelIndex: Int) {
let menuItem = TunnelMenuItem(tunnel: tunnel, action: #selector(tunnelClicked(sender:))) let menuItem = TunnelMenuItem(tunnel: tunnel, action: #selector(tunnelClicked(sender:)))
menuItem.target = self menuItem.target = self
menuItem.isHidden = !tunnel.isTunnelConfigurationAvailableInKeychain
insertItem(menuItem, at: firstTunnelMenuItemIndex + tunnelIndex) insertItem(menuItem, at: firstTunnelMenuItemIndex + tunnelIndex)
if numberOfTunnelMenuItems == 0 { if numberOfTunnelMenuItems == 0 {
insertItem(NSMenuItem.separator(), at: firstTunnelMenuItemIndex + tunnelIndex + 1) insertItem(NSMenuItem.separator(), at: firstTunnelMenuItemIndex + tunnelIndex + 1)
@@ -19,6 +19,7 @@ class ConfTextStorage: NSTextStorage {
private(set) var hasOnePeer: Bool = false private(set) var hasOnePeer: Bool = false
private(set) var lastOnePeerAllowedIPs = [String]() private(set) var lastOnePeerAllowedIPs = [String]()
private(set) var lastOnePeerDNSServers = [String]() private(set) var lastOnePeerDNSServers = [String]()
private(set) var lastOnePeerHasPublicKey = false
override init() { override init() {
backingStore = NSMutableAttributedString(string: "") backingStore = NSMutableAttributedString(string: "")
@@ -88,6 +89,7 @@ class ConfTextStorage: NSTextStorage {
hasOnePeer = false hasOnePeer = false
lastOnePeerAllowedIPs = [] lastOnePeerAllowedIPs = []
lastOnePeerDNSServers = [] lastOnePeerDNSServers = []
lastOnePeerHasPublicKey = false
} }
func evaluateExcludePrivateIPs(highlightSpans: UnsafePointer<highlight_span>) { func evaluateExcludePrivateIPs(highlightSpans: UnsafePointer<highlight_span>) {
@@ -125,6 +127,8 @@ class ConfTextStorage: NSTextStorage {
backingStore.attributedSubstring(from: NSRange(location: nextnext.pointee.start, length: nextnext.pointee.len)).string backingStore.attributedSubstring(from: NSRange(location: nextnext.pointee.start, length: nextnext.pointee.len)).string
} }
lastOnePeerAllowedIPs.append(substring) lastOnePeerAllowedIPs.append(substring)
} else if span.type == HighlightPublicKey {
lastOnePeerHasPublicKey = true
} }
spans = spans.successor() spans = spans.successor()
} }
@@ -143,9 +147,10 @@ class ConfTextStorage: NSTextStorage {
.font: defaultFont .font: defaultFont
] ]
backingStore.setAttributes(defaultAttributes, range: fullTextRange) backingStore.setAttributes(defaultAttributes, range: fullTextRange)
var spans = highlight_config(backingStore.string.cString(using: String.Encoding.utf8))! var spans = highlight_config(backingStore.string)!
evaluateExcludePrivateIPs(highlightSpans: spans) evaluateExcludePrivateIPs(highlightSpans: spans)
let spansStart = spans
while spans.pointee.type != HighlightEnd { while spans.pointee.type != HighlightEnd {
let span = spans.pointee let span = spans.pointee
@@ -165,6 +170,7 @@ class ConfTextStorage: NSTextStorage {
spans = spans.successor() spans = spans.successor()
} }
backingStore.endEditing() backingStore.endEditing()
free(spansStart)
beginEditing() beginEditing()
edited(.editedAttributes, range: fullTextRange, changeInLength: 0) edited(.editedAttributes, range: fullTextRange, changeInLength: 0)
@@ -14,6 +14,7 @@ class ConfTextView: NSTextView {
override var string: String { override var string: String {
didSet { didSet {
confTextStorage.highlightSyntax() confTextStorage.highlightSyntax()
updateConfigData()
} }
} }
@@ -53,6 +54,21 @@ class ConfTextView: NSTextView {
} }
} }
private func updateConfigData() {
if hasError != confTextStorage.hasError {
hasError = confTextStorage.hasError
}
if privateKeyString != confTextStorage.privateKeyString {
privateKeyString = confTextStorage.privateKeyString
}
let hasSyntaxError = confTextStorage.hasError
let hasSemanticError = confTextStorage.privateKeyString == nil || !confTextStorage.lastOnePeerHasPublicKey
let updatedSinglePeerAllowedIPs = confTextStorage.hasOnePeer && !hasSyntaxError && !hasSemanticError ? confTextStorage.lastOnePeerAllowedIPs : nil
if singlePeerAllowedIPs != updatedSinglePeerAllowedIPs {
singlePeerAllowedIPs = updatedSinglePeerAllowedIPs
}
}
func setConfText(_ text: String) { func setConfText(_ text: String) {
let fullTextRange = NSRange(location: 0, length: (string as NSString).length) let fullTextRange = NSRange(location: 0, length: (string as NSString).length)
if shouldChangeText(in: fullTextRange, replacementString: text) { if shouldChangeText(in: fullTextRange, replacementString: text) {
@@ -66,16 +82,7 @@ extension ConfTextView: NSTextViewDelegate {
func textDidChange(_ notification: Notification) { func textDidChange(_ notification: Notification) {
confTextStorage.highlightSyntax() confTextStorage.highlightSyntax()
if hasError != confTextStorage.hasError { updateConfigData()
hasError = confTextStorage.hasError
}
if privateKeyString != confTextStorage.privateKeyString {
privateKeyString = confTextStorage.privateKeyString
}
let updatedSinglePeerAllowedIPs = confTextStorage.hasOnePeer && !confTextStorage.hasError ? confTextStorage.lastOnePeerAllowedIPs : nil
if singlePeerAllowedIPs != updatedSinglePeerAllowedIPs {
singlePeerAllowedIPs = updatedSinglePeerAllowedIPs
}
needsDisplay = true needsDisplay = true
} }
@@ -0,0 +1,36 @@
// SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
import Cocoa
class DeleteTunnelsConfirmationAlert: NSAlert {
var alertDeleteButton: NSButton?
var alertCancelButton: NSButton?
var onDeleteClicked: ((_ completionHandler: @escaping () -> Void) -> Void)?
override init() {
super.init()
let alertDeleteButton = addButton(withTitle: tr("macDeleteTunnelConfirmationAlertButtonTitleDelete"))
alertDeleteButton.target = self
alertDeleteButton.action = #selector(removeTunnelAlertDeleteClicked)
self.alertDeleteButton = alertDeleteButton
self.alertCancelButton = addButton(withTitle: tr("macDeleteTunnelConfirmationAlertButtonTitleCancel"))
}
@objc func removeTunnelAlertDeleteClicked() {
alertDeleteButton?.title = tr("macDeleteTunnelConfirmationAlertButtonTitleDeleting")
alertDeleteButton?.isEnabled = false
alertCancelButton?.isEnabled = false
if let onDeleteClicked = onDeleteClicked {
onDeleteClicked { [weak self] in
guard let self = self else { return }
self.window.sheetParent?.endSheet(self.window)
}
}
}
func beginSheetModal(for sheetWindow: NSWindow) {
beginSheetModal(for: sheetWindow) { _ in }
}
}
@@ -0,0 +1,52 @@
// SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
import Cocoa
class LogViewCell: NSTextField {
init() {
super.init(frame: .zero)
isSelectable = false
isEditable = false
isBordered = false
backgroundColor = .clear
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func prepareForReuse() {
stringValue = ""
preferredMaxLayoutWidth = 0
}
}
class LogViewTimestampCell: LogViewCell {
override init() {
super.init()
maximumNumberOfLines = 1
lineBreakMode = .byClipping
preferredMaxLayoutWidth = 0
setContentCompressionResistancePriority(.defaultHigh, for: .vertical)
setContentHuggingPriority(.defaultLow, for: .vertical)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
class LogViewMessageCell: LogViewCell {
override init() {
super.init()
maximumNumberOfLines = 0
lineBreakMode = .byWordWrapping
setContentCompressionResistancePriority(.required, for: .vertical)
setContentHuggingPriority(.required, for: .vertical)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
@@ -0,0 +1,263 @@
// SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
import Cocoa
class LogViewController: NSViewController {
enum LogColumn: String {
case time = "Time"
case logMessage = "LogMessage"
func createColumn() -> NSTableColumn {
return NSTableColumn(identifier: NSUserInterfaceItemIdentifier(rawValue))
}
func isRepresenting(tableColumn: NSTableColumn?) -> Bool {
return tableColumn?.identifier.rawValue == rawValue
}
}
let scrollView: NSScrollView = {
let scrollView = NSScrollView()
scrollView.hasVerticalScroller = true
scrollView.autohidesScrollers = false
scrollView.borderType = .bezelBorder
return scrollView
}()
let tableView: NSTableView = {
let tableView = NSTableView()
let timeColumn = LogColumn.time.createColumn()
timeColumn.title = tr("macLogColumnTitleTime")
timeColumn.width = 160
timeColumn.resizingMask = []
tableView.addTableColumn(timeColumn)
let messageColumn = LogColumn.logMessage.createColumn()
messageColumn.title = tr("macLogColumnTitleLogMessage")
messageColumn.minWidth = 360
messageColumn.resizingMask = .autoresizingMask
tableView.addTableColumn(messageColumn)
tableView.rowSizeStyle = .custom
tableView.rowHeight = 16
tableView.usesAlternatingRowBackgroundColors = true
tableView.usesAutomaticRowHeights = true
tableView.allowsColumnReordering = false
tableView.allowsColumnResizing = true
tableView.allowsMultipleSelection = true
return tableView
}()
let progressIndicator: NSProgressIndicator = {
let progressIndicator = NSProgressIndicator()
progressIndicator.controlSize = .small
progressIndicator.isIndeterminate = true
progressIndicator.style = .spinning
progressIndicator.isDisplayedWhenStopped = false
return progressIndicator
}()
let closeButton: NSButton = {
let button = NSButton()
button.title = tr("macLogButtonTitleClose")
button.setButtonType(.momentaryPushIn)
button.bezelStyle = .rounded
return button
}()
let saveButton: NSButton = {
let button = NSButton()
button.title = tr("macLogButtonTitleSave")
button.setButtonType(.momentaryPushIn)
button.bezelStyle = .rounded
return button
}()
let logViewHelper: LogViewHelper?
var logEntries = [LogViewHelper.LogEntry]()
var isFetchingLogEntries = false
var isInScrolledToEndMode = true
private var updateLogEntriesTimer: Timer?
init() {
logViewHelper = LogViewHelper(logFilePath: FileManager.logFileURL?.path)
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func loadView() {
tableView.dataSource = self
tableView.delegate = self
closeButton.target = self
closeButton.action = #selector(closeClicked)
saveButton.target = self
saveButton.action = #selector(saveClicked)
saveButton.isEnabled = false
let clipView = NSClipView()
clipView.documentView = tableView
scrollView.contentView = clipView
_ = NotificationCenter.default.addObserver(forName: NSView.boundsDidChangeNotification, object: clipView, queue: OperationQueue.main) { [weak self] _ in
guard let self = self else { return }
let lastVisibleRowIndex = self.tableView.row(at: NSPoint(x: 0, y: self.scrollView.contentView.documentVisibleRect.maxY - 1))
self.isInScrolledToEndMode = lastVisibleRowIndex < 0 || lastVisibleRowIndex == self.logEntries.count - 1
}
_ = NotificationCenter.default.addObserver(forName: NSView.frameDidChangeNotification, object: tableView, queue: OperationQueue.main) { [weak self] _ in
guard let self = self else { return }
if self.isInScrolledToEndMode {
DispatchQueue.main.async {
self.tableView.scroll(NSPoint(x: 0, y: self.tableView.frame.maxY - clipView.documentVisibleRect.height))
}
}
}
let margin: CGFloat = 20
let internalSpacing: CGFloat = 10
let buttonRowStackView = NSStackView()
buttonRowStackView.addView(closeButton, in: .leading)
buttonRowStackView.addView(saveButton, in: .trailing)
buttonRowStackView.orientation = .horizontal
buttonRowStackView.spacing = internalSpacing
let containerView = NSView()
[scrollView, progressIndicator, buttonRowStackView].forEach { view in
containerView.addSubview(view)
view.translatesAutoresizingMaskIntoConstraints = false
}
NSLayoutConstraint.activate([
scrollView.topAnchor.constraint(equalTo: containerView.topAnchor, constant: margin),
scrollView.leftAnchor.constraint(equalTo: containerView.leftAnchor, constant: margin),
containerView.rightAnchor.constraint(equalTo: scrollView.rightAnchor, constant: margin),
buttonRowStackView.topAnchor.constraint(equalTo: scrollView.bottomAnchor, constant: internalSpacing),
buttonRowStackView.leftAnchor.constraint(equalTo: containerView.leftAnchor, constant: margin),
containerView.rightAnchor.constraint(equalTo: buttonRowStackView.rightAnchor, constant: margin),
containerView.bottomAnchor.constraint(equalTo: buttonRowStackView.bottomAnchor, constant: margin),
progressIndicator.centerXAnchor.constraint(equalTo: scrollView.centerXAnchor),
progressIndicator.centerYAnchor.constraint(equalTo: scrollView.centerYAnchor)
])
NSLayoutConstraint.activate([
containerView.widthAnchor.constraint(equalToConstant: 640),
containerView.heightAnchor.constraint(greaterThanOrEqualToConstant: 240)
])
containerView.frame = NSRect(x: 0, y: 0, width: 640, height: 480)
view = containerView
progressIndicator.startAnimation(self)
startUpdatingLogEntries()
}
func updateLogEntries() {
guard !isFetchingLogEntries else { return }
isFetchingLogEntries = true
logViewHelper?.fetchLogEntriesSinceLastFetch { [weak self] fetchedLogEntries in
guard let self = self else { return }
defer {
self.isFetchingLogEntries = false
}
if !self.progressIndicator.isHidden {
self.progressIndicator.stopAnimation(self)
self.saveButton.isEnabled = true
}
guard !fetchedLogEntries.isEmpty else { return }
let oldCount = self.logEntries.count
self.logEntries.append(contentsOf: fetchedLogEntries)
self.tableView.insertRows(at: IndexSet(integersIn: oldCount ..< oldCount + fetchedLogEntries.count), withAnimation: .slideDown)
}
}
func startUpdatingLogEntries() {
updateLogEntries()
updateLogEntriesTimer?.invalidate()
let timer = Timer(timeInterval: 1 /* second */, repeats: true) { [weak self] _ in
self?.updateLogEntries()
}
updateLogEntriesTimer = timer
RunLoop.main.add(timer, forMode: .common)
}
func stopUpdatingLogEntries() {
updateLogEntriesTimer?.invalidate()
updateLogEntriesTimer = nil
}
override func viewWillDisappear() {
super.viewWillDisappear()
stopUpdatingLogEntries()
}
@objc func saveClicked() {
let savePanel = NSSavePanel()
savePanel.prompt = tr("macSheetButtonExportLog")
savePanel.nameFieldLabel = tr("macNameFieldExportLog")
let dateFormatter = ISO8601DateFormatter()
dateFormatter.formatOptions = [.withFullDate, .withTime, .withTimeZone] // Avoid ':' in the filename
let timeStampString = dateFormatter.string(from: Date())
savePanel.nameFieldStringValue = "wireguard-log-\(timeStampString).txt"
savePanel.beginSheetModal(for: self.view.window!) { [weak self] response in
guard response == .OK else { return }
guard let destinationURL = savePanel.url else { return }
DispatchQueue.global(qos: .userInitiated).async { [weak self] in
let isWritten = Logger.global?.writeLog(to: destinationURL.path) ?? false
guard isWritten else {
DispatchQueue.main.async { [weak self] in
ErrorPresenter.showErrorAlert(title: tr("alertUnableToWriteLogTitle"), message: tr("alertUnableToWriteLogMessage"), from: self)
}
return
}
DispatchQueue.main.async { [weak self] in
self?.dismiss(self)
}
}
}
}
@objc func closeClicked() {
dismiss(self)
}
@objc func copy(_ sender: Any?) {
let text = tableView.selectedRowIndexes.sorted().reduce("") { $0 + self.logEntries[$1].text() + "\n" }
let pasteboard = NSPasteboard.general
pasteboard.clearContents()
pasteboard.writeObjects([text as NSString])
}
}
extension LogViewController: NSTableViewDataSource {
func numberOfRows(in tableView: NSTableView) -> Int {
return logEntries.count
}
}
extension LogViewController: NSTableViewDelegate {
func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
if LogColumn.time.isRepresenting(tableColumn: tableColumn) {
let cell: LogViewTimestampCell = tableView.dequeueReusableCell()
cell.stringValue = logEntries[row].timestamp
return cell
} else if LogColumn.logMessage.isRepresenting(tableColumn: tableColumn) {
let cell: LogViewMessageCell = tableView.dequeueReusableCell()
cell.stringValue = logEntries[row].message
cell.preferredMaxLayoutWidth = tableColumn?.width ?? 0
return cell
} else {
fatalError()
}
}
}
@@ -81,16 +81,20 @@ extension ManageTunnelsRootViewController: TunnelsListTableViewControllerDelegat
assert(!tunnelIndices.isEmpty) assert(!tunnelIndices.isEmpty)
if tunnelIndices.count == 1 { if tunnelIndices.count == 1 {
let tunnel = tunnelsManager.tunnel(at: tunnelIndices.first!) let tunnel = tunnelsManager.tunnel(at: tunnelIndices.first!)
let tunnelDetailVC = TunnelDetailTableViewController(tunnelsManager: tunnelsManager, tunnel: tunnel) if tunnel.isTunnelConfigurationAvailableInKeychain {
setTunnelDetailContentVC(tunnelDetailVC) let tunnelDetailVC = TunnelDetailTableViewController(tunnelsManager: tunnelsManager, tunnel: tunnel)
self.tunnelDetailVC = tunnelDetailVC setTunnelDetailContentVC(tunnelDetailVC)
} else if tunnelIndices.count > 1 { self.tunnelDetailVC = tunnelDetailVC
let multiSelectionVC: ButtonedDetailViewController
if let buttonedDetailVC = tunnelDetailContentVC as? ButtonedDetailViewController {
multiSelectionVC = buttonedDetailVC
} else { } else {
multiSelectionVC = ButtonedDetailViewController() let unusableTunnelDetailVC = tunnelDetailContentVC as? UnusableTunnelDetailViewController ?? UnusableTunnelDetailViewController()
unusableTunnelDetailVC.onButtonClicked = { [weak tunnelsListVC] in
tunnelsListVC?.handleRemoveTunnelAction()
}
setTunnelDetailContentVC(unusableTunnelDetailVC)
self.tunnelDetailVC = nil
} }
} else if tunnelIndices.count > 1 {
let multiSelectionVC = tunnelDetailContentVC as? ButtonedDetailViewController ?? ButtonedDetailViewController()
multiSelectionVC.setButtonTitle(tr(format: "macButtonDeleteTunnels (%d)", tunnelIndices.count)) multiSelectionVC.setButtonTitle(tr(format: "macButtonDeleteTunnels (%d)", tunnelIndices.count))
multiSelectionVC.onButtonClicked = { [weak tunnelsListVC] in multiSelectionVC.onButtonClicked = { [weak tunnelsListVC] in
tunnelsListVC?.handleRemoveTunnelAction() tunnelsListVC?.handleRemoveTunnelAction()
@@ -117,6 +117,8 @@ class TunnelEditViewController: NSViewController {
let bootstrappingText = "[Interface]\nPrivateKey = \(privateKey.base64Key() ?? "")\n" let bootstrappingText = "[Interface]\nPrivateKey = \(privateKey.base64Key() ?? "")\n"
publicKeyRow.value = publicKey.base64Key() ?? "" publicKeyRow.value = publicKey.base64Key() ?? ""
textView.string = bootstrappingText textView.string = bootstrappingText
updateExcludePrivateIPsVisibility(singlePeerAllowedIPs: nil)
dnsServersAddedToAllowedIPs = nil
} }
privateKeyObservationToken = textView.observe(\.privateKeyString) { [weak publicKeyRow] textView, _ in privateKeyObservationToken = textView.observe(\.privateKeyString) { [weak publicKeyRow] textView, _ in
if let privateKeyString = textView.privateKeyString, if let privateKeyString = textView.privateKeyString,
@@ -243,17 +245,15 @@ class TunnelEditViewController: NSViewController {
} }
} else { } else {
// We're creating a new tunnel // We're creating a new tunnel
AppStorePrivacyNotice.show(from: self, into: tunnelsManager) { [weak self] in self.tunnelsManager.add(tunnelConfiguration: tunnelConfiguration, onDemandOption: onDemandOption) { [weak self] result in
self?.tunnelsManager.add(tunnelConfiguration: tunnelConfiguration, onDemandOption: onDemandOption) { [weak self] result in self?.setUserInteractionEnabled(true)
self?.setUserInteractionEnabled(true) if let error = result.error {
if let error = result.error { ErrorPresenter.showErrorAlert(error: error, from: self)
ErrorPresenter.showErrorAlert(error: error, from: self) return
return
}
let tunnel: TunnelContainer = result.value!
self?.dismiss(self)
self?.delegate?.tunnelSaved(tunnel: tunnel)
} }
let tunnel: TunnelContainer = result.value!
self?.dismiss(self)
self?.delegate?.tunnelSaved(tunnel: tunnel)
} }
} }
} }
@@ -12,6 +12,7 @@ class TunnelsListTableViewController: NSViewController {
let tunnelsManager: TunnelsManager let tunnelsManager: TunnelsManager
weak var delegate: TunnelsListTableViewControllerDelegate? weak var delegate: TunnelsListTableViewControllerDelegate?
var isRemovingTunnels = false
let tableView: NSTableView = { let tableView: NSTableView = {
let tableView = NSTableView() let tableView = NSTableView()
@@ -53,7 +54,7 @@ class TunnelsListTableViewController: NSViewController {
let menu = NSMenu() let menu = NSMenu()
menu.addItem(imageItem) menu.addItem(imageItem)
menu.addItem(withTitle: tr("macMenuExportLog"), action: #selector(handleExportLogAction), keyEquivalent: "") menu.addItem(withTitle: tr("macMenuViewLog"), action: #selector(handleViewLogAction), keyEquivalent: "")
menu.addItem(withTitle: tr("macMenuExportTunnels"), action: #selector(handleExportTunnelsAction), keyEquivalent: "") menu.addItem(withTitle: tr("macMenuExportTunnels"), action: #selector(handleExportTunnelsAction), keyEquivalent: "")
menu.autoenablesItems = false menu.autoenablesItems = false
@@ -162,60 +163,41 @@ class TunnelsListTableViewController: NSViewController {
@objc func handleRemoveTunnelAction() { @objc func handleRemoveTunnelAction() {
guard let window = view.window else { return } guard let window = view.window else { return }
let selectedTunnelIndices = tableView.selectedRowIndexes.sorted()
let selectedTunnels = selectedTunnelIndices.compactMap { tunnelIndex in let selectedTunnelIndices = tableView.selectedRowIndexes.sorted().filter { $0 >= 0 && $0 < tunnelsManager.numberOfTunnels() }
tunnelIndex >= 0 && tunnelIndex < tunnelsManager.numberOfTunnels() ? tunnelsManager.tunnel(at: tunnelIndex) : nil guard !selectedTunnelIndices.isEmpty else { return }
var nextSelection = selectedTunnelIndices.last! + 1
if nextSelection >= tunnelsManager.numberOfTunnels() {
nextSelection = max(selectedTunnelIndices.first! - 1, 0)
} }
guard !selectedTunnels.isEmpty else { return }
let alert = NSAlert() let alert = DeleteTunnelsConfirmationAlert()
if selectedTunnels.count == 1 { if selectedTunnelIndices.count == 1 {
alert.messageText = tr(format: "macDeleteTunnelConfirmationAlertMessage (%@)", selectedTunnels.first!.name) let firstSelectedTunnel = tunnelsManager.tunnel(at: selectedTunnelIndices.first!)
alert.messageText = tr(format: "macDeleteTunnelConfirmationAlertMessage (%@)", firstSelectedTunnel.name)
} else { } else {
alert.messageText = tr(format: "macDeleteMultipleTunnelsConfirmationAlertMessage (%d)", selectedTunnels.count) alert.messageText = tr(format: "macDeleteMultipleTunnelsConfirmationAlertMessage (%d)", selectedTunnelIndices.count)
} }
alert.informativeText = tr("macDeleteTunnelConfirmationAlertInfo") alert.informativeText = tr("macDeleteTunnelConfirmationAlertInfo")
alert.addButton(withTitle: tr("macDeleteTunnelConfirmationAlertButtonTitleDelete")) alert.onDeleteClicked = { [weak self] completion in
alert.addButton(withTitle: tr("macDeleteTunnelConfirmationAlertButtonTitleCancel")) guard let self = self else { return }
alert.beginSheetModal(for: window) { [weak self] response in self.selectTunnel(at: nextSelection)
guard response == .alertFirstButtonReturn else { return } let selectedTunnels = selectedTunnelIndices.map { self.tunnelsManager.tunnel(at: $0) }
self?.removeButton.isEnabled = false self.tunnelsManager.removeMultiple(tunnels: selectedTunnels) { [weak self] error in
self?.tunnelsManager.removeMultiple(tunnels: selectedTunnels) { [weak self] error in
guard let self = self else { return } guard let self = self else { return }
defer { self.removeButton.isEnabled = true } defer { completion() }
if let error = error { if let error = error {
ErrorPresenter.showErrorAlert(error: error, from: self) ErrorPresenter.showErrorAlert(error: error, from: self)
return return
} }
} }
} }
alert.beginSheetModal(for: window)
} }
@objc func handleExportLogAction() { @objc func handleViewLogAction() {
guard let window = view.window else { return } let logVC = LogViewController()
let savePanel = NSSavePanel() self.presentAsSheet(logVC)
savePanel.prompt = tr("macSheetButtonExportLog")
savePanel.nameFieldLabel = tr("macNameFieldExportLog")
let dateFormatter = ISO8601DateFormatter()
dateFormatter.formatOptions = [.withFullDate, .withTime, .withTimeZone] // Avoid ':' in the filename
let timeStampString = dateFormatter.string(from: Date())
savePanel.nameFieldStringValue = "wireguard-log-\(timeStampString).txt"
savePanel.beginSheetModal(for: window) { response in
guard response == .OK else { return }
guard let destinationURL = savePanel.url else { return }
DispatchQueue.global(qos: .userInitiated).async {
let isWritten = Logger.global?.writeLog(to: destinationURL.path) ?? false
guard isWritten else {
DispatchQueue.main.async { [weak self] in
ErrorPresenter.showErrorAlert(title: tr("alertUnableToWriteLogTitle"), message: tr("alertUnableToWriteLogMessage"), from: self)
}
return
}
}
}
} }
@objc func handleExportTunnelsAction() { @objc func handleExportTunnelsAction() {
@@ -299,15 +281,10 @@ extension TunnelsListTableViewController {
} }
func tunnelRemoved(at index: Int) { func tunnelRemoved(at index: Int) {
let selectedTunnelIndex = tableView.selectedRow
tableView.removeRows(at: IndexSet(integer: index), withAnimation: .slideLeft) tableView.removeRows(at: IndexSet(integer: index), withAnimation: .slideLeft)
if tunnelsManager.numberOfTunnels() == 0 { if tunnelsManager.numberOfTunnels() == 0 {
delegate?.tunnelsListEmpty() delegate?.tunnelsListEmpty()
} }
let tunnelIndex = min(selectedTunnelIndex, self.tunnelsManager.numberOfTunnels() - 1)
if tunnelIndex >= 0 {
self.selectTunnel(at: tunnelIndex)
}
} }
} }
@@ -0,0 +1,71 @@
// SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
import Cocoa
class UnusableTunnelDetailViewController: NSViewController {
var onButtonClicked: (() -> Void)?
let messageLabel: NSTextField = {
let text = tr("macUnusableTunnelMessage")
let boldFont = NSFont.boldSystemFont(ofSize: NSFont.systemFontSize)
let boldText = NSAttributedString(string: text, attributes: [.font: boldFont])
let label = NSTextField(labelWithAttributedString: boldText)
return label
}()
let infoLabel: NSTextField = {
let label = NSTextField(wrappingLabelWithString: tr("macUnusableTunnelInfo"))
return label
}()
let button: NSButton = {
let button = NSButton()
button.title = tr("macUnusableTunnelButtonTitleDeleteTunnel")
button.setButtonType(.momentaryPushIn)
button.bezelStyle = .rounded
return button
}()
init() {
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func loadView() {
button.target = self
button.action = #selector(buttonClicked)
let margin: CGFloat = 20
let internalSpacing: CGFloat = 20
let buttonSpacing: CGFloat = 30
let stackView = NSStackView(views: [messageLabel, infoLabel, button])
stackView.orientation = .vertical
stackView.edgeInsets = NSEdgeInsets(top: margin, left: margin, bottom: margin, right: margin)
stackView.spacing = internalSpacing
stackView.setCustomSpacing(buttonSpacing, after: infoLabel)
let view = NSView()
view.addSubview(stackView)
stackView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
stackView.widthAnchor.constraint(equalToConstant: 360),
stackView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
stackView.centerYAnchor.constraint(equalTo: view.centerYAnchor),
view.widthAnchor.constraint(greaterThanOrEqualToConstant: 420),
view.heightAnchor.constraint(greaterThanOrEqualToConstant: 240)
])
self.view = view
}
@objc func buttonClicked() {
onButtonClicked?()
}
}
@@ -31,7 +31,7 @@ class ZipArchive {
let fileName = input.fileName let fileName = input.fileName
let contents = input.contents let contents = input.contents
zipOpenNewFileInZip(zipFile, fileName.cString(using: .utf8), nil, nil, 0, nil, 0, nil, Z_DEFLATED, Z_DEFAULT_COMPRESSION) zipOpenNewFileInZip(zipFile, fileName.cString(using: .utf8), nil, nil, 0, nil, 0, nil, Z_DEFLATED, Z_DEFAULT_COMPRESSION)
contents.withUnsafeBytes { (ptr: UnsafePointer<UInt8>) -> Void in contents.withUnsafeUInt8Bytes { ptr -> Void in
zipWriteInFileInZip(zipFile, UnsafeRawPointer(ptr), UInt32(contents.count)) zipWriteInFileInZip(zipFile, UnsafeRawPointer(ptr), UInt32(contents.count))
} }
zipCloseFileInZip(zipFile) zipCloseFileInZip(zipFile)
@@ -117,6 +117,8 @@ extension Endpoint {
hostname = "\(address)" hostname = "\(address)"
case .ipv6(let address): case .ipv6(let address):
hostname = "\(address)" hostname = "\(address)"
@unknown default:
fatalError()
} }
var resultPointer = UnsafeMutablePointer<addrinfo>(OpaquePointer(bitPattern: 0)) var resultPointer = UnsafeMutablePointer<addrinfo>(OpaquePointer(bitPattern: 0))
+2 -2
View File
@@ -3,6 +3,6 @@ module golang.zx2c4.com/wireguard/ios
go 1.12 go 1.12
require ( require (
golang.org/x/sys v0.0.0-20190312061237-fead79001313 golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67
golang.zx2c4.com/wireguard v0.0.0-20190310024754-66fb5caf023e golang.zx2c4.com/wireguard v0.0.0-20190409083948-18fa27047265
) )
+12 -10
View File
@@ -1,11 +1,13 @@
github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= github.com/Microsoft/go-winio v0.4.12/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
golang.org/x/crypto v0.0.0-20190228161510-8dd112bcdc25 h1:jsG6UpNLt9iAsb0S2AGW28DveNzzgmbXR+ENoPjUeIU= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190228161510-8dd112bcdc25/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190320223903-b7391e95e576 h1:aUX/1G2gFSs4AsJJg2cL3HuoRhCSCz733FE5GUSuaT4=
golang.org/x/net v0.0.0-20190301231341-16b79f2e4e95 h1:fY7Dsw114eJN4boqzVSbpVHO6rTdhq6/GnXeu+PKnzU= golang.org/x/crypto v0.0.0-20190320223903-b7391e95e576/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/net v0.0.0-20190301231341-16b79f2e4e95/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190320064053-1272bf9dcd53 h1:kcXqo9vE6fsZY5X5Rd7R1l7fTgnWaDCVmln65REefiE=
golang.org/x/net v0.0.0-20190320064053-1272bf9dcd53/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190302025703-b6889370fb10/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190321052220-f7bb7a8bee54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190312061237-fead79001313 h1:pczuHS43Cp2ktBEEmLwScxgjWsBSzdaQiKzUyf3DTTc= golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67 h1:1Fzlr8kkDLQwqMP8GxrhptBLqZG/EDpiATneiZHY998=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.zx2c4.com/wireguard v0.0.0-20190310024754-66fb5caf023e h1:lyp5Vq7gvB3Ei9iCJNhEvzuQx99gteo+GoRZPFOCmRE= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.zx2c4.com/wireguard v0.0.0-20190310024754-66fb5caf023e/go.mod h1:Koyxt99ZAZcr8lJuisBNX9vnaqKVNGcITeWOI1Zkmsw= golang.zx2c4.com/wireguard v0.0.0-20190409083948-18fa27047265 h1:ujM5BaP4MD/2MJZ1n7pmw6IIsyyS7SyPl0fDefnx/2o=
golang.zx2c4.com/wireguard v0.0.0-20190409083948-18fa27047265/go.mod h1:u0Cl3X+pyWdXaax3S583DQrnGDuTASO0QdlKFrs8r/8=