Compare commits

...

29 Commits

Author SHA1 Message Date
Jason A. Donenfeld 87f0526f09 App: version bump
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2021-06-16 18:34:54 +02:00
Jason A. Donenfeld 060c027325 Kit: Go: mod bump
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2021-06-16 18:03:28 +02:00
Jason A. Donenfeld 23bf3cfccb Kit: Adapter: use more reliable utun detection technique
Rather than hoping that the AF_SYSTEM fd is of type utun, and then
calling "2" on it to get the name -- which could be defined as something
else for a different AF_SYSTEM socket type -- instead simply query the
AF_SYSTEM control socket ID with getpeername. This has one catch, which
is that the ID is dynamically allocated, so we resolve it using the
qualified name. Normally we'd make a new AF_SYSTEM socket for this, but
since that's not allowed in the sandbox, we reuse the AF_SYSTEM socket
that we're checking. At this point in the flow, we know that it's a
proper AF_SYSTEM one, based on the first sockaddr member; we just don't
know that it's a utun variety.

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2021-06-16 17:40:12 +02:00
Jason A. Donenfeld 7f5ad3e503 Kit: Adapter: iterate through all FDs to find UTUN
This is a bit of a kludge, until I find something better. We simply
iterate through all FDs, and call getsockopt on each one until we find
the utun FD. This works, and completes rather quickly (fd is usually 6
or 7). Rather than maintain the old path for older kernels, just use
this for all versions, to get more coverage. Other techniques involve
undocumented APIs; this one has the advantage of using nothing
undocumented.

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2021-06-16 15:56:21 +02:00
Andrej Mihajlov 820fa55380 SPM: update exclude rules
Fixes missing excluded file warning in Xcode. api-ios.go was renamed to api-apple.go.

Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2021-06-16 15:23:11 +02:00
Jason A. Donenfeld eb528c766b UI: iOS: asynchronously load from NEHotspotNetwork on iOS 14
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2021-03-09 09:10:07 -07:00
Jason A. Donenfeld 53235eb38f UI: iOS: clean up visuals in SSID editor
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2021-03-09 09:10:07 -07:00
Jason A. Donenfeld b9ff5c2e94 README: account for funky xcode paths
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2021-03-09 09:10:07 -07:00
Jason A. Donenfeld b7f69d20b6 Kit: Go: bump to latest API
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2021-03-09 09:10:04 -07:00
Andrej Mihajlov 6c4f4109eb UI: iOS: Disable "copy" action on on-demand cells
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2021-01-11 13:09:41 +01:00
Jason A. Donenfeld 7b5b564a6e Kit: netcfg: add explicit IP mask routes
macOS will use the wrong source address unless we add explicit routes
that mention the self-pointing gateway. Actually, it won't add any
implicit routes on its own, so in order to route the masks of the
addresses, we have to add our own routes explicitly.

However, this still doesn't fix the problem while inside of the network
extension, even though it works outside it.

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2021-01-01 18:28:14 +01:00
Jason A. Donenfeld 695f868b1f Kit: Go: mod bump
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2020-12-23 22:54:47 +01:00
Andrej Mihajlov e724c043d9 UI: iOS: Remove duplicate call to addSubview
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2020-12-23 16:14:03 +01:00
Andrej Mihajlov 491301f58b UI: iOS: Fix placeholder label alignment in text fields.
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2020-12-23 16:14:03 +01:00
Jason A. Donenfeld c4f79beb8d App: version bump
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2020-12-23 15:05:56 +01:00
Jason A. Donenfeld a613fec2ff project: sync translations and improve id generation again
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2020-12-23 14:55:29 +01:00
Andrej Mihajlov e54a5d9a13 UI: macOS: Group more than 10 tunnels into submenu
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2020-12-23 14:40:54 +01:00
Andrej Mihajlov 6d57c8b6f9 UI: Avoid force unwrap when checking for errors
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2020-12-23 14:17:59 +01:00
Jason A. Donenfeld b67acaccff Kit: do not crash on [abcd::] with missing port
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2020-12-23 14:06:26 +01:00
Jason A. Donenfeld d8568b0e31 Kit: Go: bump module and simplify API
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2020-12-23 13:40:24 +01:00
Andrej Mihajlov 373bb2ae99 UI: pause VPN configurations observer while adding or removing multiple tunnels
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2020-12-22 12:47:02 +01:00
Andrej Mihajlov 631286e2d1 UI: use NotificationToken to properly clean up observers
When the variable goes out of scope, the observer isn't removed unless
an explicit call is made to the token.

Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2020-12-22 12:46:30 +01:00
Andrej Mihajlov 74cd7041dc Keychain: prevent call to stat() when determining appex path
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2020-12-22 12:46:14 +01:00
Jason A. Donenfeld 21d920c8b0 Kit: Go: use Windows-style retry sleep loop on bind updates
Something odd happens in the network extension that we still don't
understand. Attempt to poke it in this terrible way.

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2020-12-18 23:53:39 +01:00
Jason A. Donenfeld 44c4df1cd5 UI: Model: remove 0.0.0.0/8 from non-private IPs
macOS freaks out if you try to explicitly route to 0.0.0.0/8 in its
includedRoutes parameter. Even though 0.0.0.0/8 isn't RFC1918, it is
marked in RFC6890 as "this host on this network", so removing it from
the Internet routes makes sense semantically too.

This commit changes 0.0.0.0/5 into:
- 1.0.0.0/8
- 2.0.0.0/8
- 3.0.0.0/8
- 4.0.0.0/6

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2020-12-18 23:53:39 +01:00
Jason A. Donenfeld a4fc0f64b8 UI: iOS: remove donation link
Apple forbids us from having a simple link to wireguard.com/donations/
in the version info window, citing the existence of this link as a form
of payment outside of their in-app purchase framework that requires 30%.
The link had been there for around two years. After rejecting an app
update for a critical networking regression unrelated to this, they
wrote:

    Dec 17, 2020 at 8:35 PM
    From Apple

    3.1.1 - Business - Payments - In-App Purchase

    We noticed that your app allows users to contribute donations to the
    development of your app with a mechanism other than the in-app
    purchase API, which is not appropriate for the App Store.

    Next Steps

    To resolve this issue, please revise your app to use the in-app
    purchase API to pay for this type of transaction. Please note that
    even though tipping another individual is optional, the tip is
    connected to or associated with the receipt of digital content or
    services in your app and must be purchased through in-app purchase
    in accordance with guideline 3.1.1 of the App Store Review
    Guidelines.

    Please see attached screenshot for details.

Trying to appeal this or reason with Apple is not going to be a fruitful
endeavor, so instead we simply cut our losses and remove the donation
link entirely. The goal, anyway, is to get a timely critical update into
the hands of users, and encouraging Apple to block that further would be
a disservice.

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2020-12-17 22:44:30 +01:00
Andrej Mihajlov 9269c7c1c1 UI: macOS: Fix UTF-8 and UTF-16 conversions in highlighter code
NSString uses UTF-16 internally, while String uses UTF-8 in Swift 5.

Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2020-12-17 17:36:46 +01:00
Jason A. Donenfeld 403ee63615 project: generate more stable locale IDs
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2020-12-17 12:41:23 +01:00
Andrej Mihajlov b622fde291 build: disable hardened runtime on iOS but keep it enabled on macOS
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2020-12-17 11:58:50 +01:00
48 changed files with 1390 additions and 677 deletions
+1 -1
View File
@@ -30,7 +30,7 @@ let package = Package(
"goruntime-boottime-over-monotonic.diff",
"go.mod",
"go.sum",
"api-ios.go",
"api-apple.go",
"Makefile"
],
publicHeadersPath: ".",
+1 -1
View File
@@ -54,7 +54,7 @@ $ open WireGuard.xcodeproj
the "External Build Tool Configuration":
```
$BUILD_DIR/../../SourcePackages/checkouts/wireguard-apple/Sources/WireGuardKitGo
${BUILD_DIR%Build/*}SourcePackages/checkouts/wireguard-apple/Sources/WireGuardKitGo
```
- Switch to "Build Settings" and find `SDKROOT`.
+1 -1
View File
@@ -44,7 +44,7 @@ class Keychain {
items[kSecAttrSynchronizable] = false
items[kSecAttrAccessible] = kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly
guard let extensionPath = Bundle.main.builtInPlugInsURL?.appendingPathComponent("WireGuardNetworkExtension.appex").path else {
guard let extensionPath = Bundle.main.builtInPlugInsURL?.appendingPathComponent("WireGuardNetworkExtension.appex", isDirectory: true).path else {
wg_log(.error, staticMessage: "Unable to determine app extension path")
return nil
}
+33
View File
@@ -0,0 +1,33 @@
// SPDX-License-Identifier: MIT
// Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
import Foundation
/// This source file contains bits of code from:
/// https://oleb.net/blog/2018/01/notificationcenter-removeobserver/
/// Wraps the observer token received from
/// `NotificationCenter.addObserver(forName:object:queue:using:)`
/// and unregisters it in deinit.
final class NotificationToken {
let notificationCenter: NotificationCenter
let token: Any
init(notificationCenter: NotificationCenter = .default, token: Any) {
self.notificationCenter = notificationCenter
self.token = token
}
deinit {
notificationCenter.removeObserver(token)
}
}
extension NotificationCenter {
/// Convenience wrapper for addObserver(forName:object:queue:using:)
/// that returns our custom `NotificationToken`.
func observe(name: NSNotification.Name?, object obj: Any?, queue: OperationQueue?, using block: @escaping (Notification) -> Void) -> NotificationToken {
let token = addObserver(forName: name, object: obj, queue: queue, using: block)
return NotificationToken(notificationCenter: self, token: token)
}
}
@@ -109,6 +109,7 @@
"tunnelOnDemandSectionTitleAddSSIDs" = "Add SSIDs";
"tunnelOnDemandAddMessageAddConnectedSSID (%@)" = "Add connected: %@";
"tunnelOnDemandAddMessageAddNewSSID" = "Add new";
"tunnelOnDemandSSIDTextFieldPlaceholder" = "SSID";
"tunnelOnDemandKey" = "On demand";
"tunnelOnDemandOptionOff" = "Off";
@@ -297,6 +298,7 @@
"macMenuNetworksNone" = "Networks: None";
"macMenuTitle" = "WireGuard";
"macTunnelsMenuTitle" = "Tunnels";
"macMenuManageTunnels" = "Manage Tunnels";
"macMenuImportTunnels" = "Import Tunnel(s) from File…";
"macMenuAddEmptyTunnel" = "Add Empty Tunnel…";
+2 -2
View File
@@ -1,2 +1,2 @@
VERSION_NAME = 1.0.11
VERSION_ID = 20
VERSION_NAME = 1.0.13
VERSION_ID = 24
@@ -23,9 +23,9 @@ class TunnelsManager {
private var tunnels: [TunnelContainer]
weak var tunnelsListDelegate: TunnelsManagerListDelegate?
weak var activationDelegate: TunnelsManagerActivationDelegate?
private var statusObservationToken: AnyObject?
private var waiteeObservationToken: AnyObject?
private var configurationsObservationToken: AnyObject?
private var statusObservationToken: NotificationToken?
private var waiteeObservationToken: NSKeyValueObservation?
private var configurationsObservationToken: NotificationToken?
init(tunnelProviders: [NETunnelProviderManager]) {
tunnels = tunnelProviders.map { TunnelContainer(tunnel: $0) }.sorted { TunnelsManager.tunnelNameIsLessThan($0.name, $1.name) }
@@ -138,10 +138,10 @@ class TunnelsManager {
let activeTunnel = tunnels.first { $0.status == .active || $0.status == .activating }
tunnelProviderManager.saveToPreferences { [weak self] error in
guard error == nil else {
wg_log(.error, message: "Add: Saving configuration failed: \(error!)")
if let error = error {
wg_log(.error, message: "Add: Saving configuration failed: \(error)")
(tunnelProviderManager.protocolConfiguration as? NETunnelProviderProtocol)?.destroyConfigurationReference()
completionHandler(.failure(TunnelsManagerError.systemErrorOnAddTunnel(systemError: error!)))
completionHandler(.failure(TunnelsManagerError.systemErrorOnAddTunnel(systemError: error)))
return
}
@@ -169,7 +169,20 @@ class TunnelsManager {
}
func addMultiple(tunnelConfigurations: [TunnelConfiguration], completionHandler: @escaping (UInt, TunnelsManagerError?) -> Void) {
addMultiple(tunnelConfigurations: ArraySlice(tunnelConfigurations), numberSuccessful: 0, lastError: nil, completionHandler: completionHandler)
// Temporarily pause observation of changes to VPN configurations to prevent the feedback
// loop that causes `reload()` to be called on each newly added tunnel, which significantly
// impacts performance.
configurationsObservationToken = nil
self.addMultiple(tunnelConfigurations: ArraySlice(tunnelConfigurations), numberSuccessful: 0, lastError: nil) { [weak self] numSucceeded, error in
completionHandler(numSucceeded, error)
// Restart observation of changes to VPN configrations.
self?.startObservingTunnelConfigurations()
// Force reload all configurations to make sure that all tunnels are up to date.
self?.reload()
}
}
private func addMultiple(tunnelConfigurations: ArraySlice<TunnelConfiguration>, numberSuccessful: UInt, lastError: TunnelsManagerError?, completionHandler: @escaping (UInt, TunnelsManagerError?) -> Void) {
@@ -222,10 +235,10 @@ class TunnelsManager {
onDemandOption.apply(on: tunnelProviderManager)
tunnelProviderManager.saveToPreferences { [weak self] error in
guard error == nil else {
if let error = error {
//TODO: the passwordReference for the old one has already been removed at this point and we can't easily roll back!
wg_log(.error, message: "Modify: Saving configuration failed: \(error!)")
completionHandler(TunnelsManagerError.systemErrorOnModifyTunnel(systemError: error!))
wg_log(.error, message: "Modify: Saving configuration failed: \(error)")
completionHandler(TunnelsManagerError.systemErrorOnModifyTunnel(systemError: error))
return
}
guard let self = self else { return }
@@ -253,12 +266,12 @@ class TunnelsManager {
// Without this, the tunnel stopes getting updates on the tunnel status from iOS.
tunnelProviderManager.loadFromPreferences { error in
tunnel.isActivateOnDemandEnabled = tunnelProviderManager.isOnDemandEnabled
guard error == nil else {
wg_log(.error, message: "Modify: Re-loading after saving configuration failed: \(error!)")
completionHandler(TunnelsManagerError.systemErrorOnModifyTunnel(systemError: error!))
return
if let error = error {
wg_log(.error, message: "Modify: Re-loading after saving configuration failed: \(error)")
completionHandler(TunnelsManagerError.systemErrorOnModifyTunnel(systemError: error))
} else {
completionHandler(nil)
}
completionHandler(nil)
}
} else {
completionHandler(nil)
@@ -278,9 +291,9 @@ class TunnelsManager {
#error("Unimplemented")
#endif
tunnelProviderManager.removeFromPreferences { [weak self] error in
guard error == nil else {
wg_log(.error, message: "Remove: Saving configuration failed: \(error!)")
completionHandler(TunnelsManagerError.systemErrorOnRemoveTunnel(systemError: error!))
if let error = error {
wg_log(.error, message: "Remove: Saving configuration failed: \(error)")
completionHandler(TunnelsManagerError.systemErrorOnRemoveTunnel(systemError: error))
return
}
if let self = self, let index = self.tunnels.firstIndex(of: tunnel) {
@@ -296,7 +309,20 @@ class TunnelsManager {
}
func removeMultiple(tunnels: [TunnelContainer], completionHandler: @escaping (TunnelsManagerError?) -> Void) {
removeMultiple(tunnels: ArraySlice(tunnels), completionHandler: completionHandler)
// Temporarily pause observation of changes to VPN configurations to prevent the feedback
// loop that causes `reload()` to be called for each removed tunnel, which significantly
// impacts performance.
configurationsObservationToken = nil
removeMultiple(tunnels: ArraySlice(tunnels)) { [weak self] error in
completionHandler(error)
// Restart observation of changes to VPN configrations.
self?.startObservingTunnelConfigurations()
// Force reload all configurations to make sure that all tunnels are up to date.
self?.reload()
}
}
private func removeMultiple(tunnels: ArraySlice<TunnelContainer>, completionHandler: @escaping (TunnelsManagerError?) -> Void) {
@@ -406,7 +432,7 @@ class TunnelsManager {
}
private func startObservingTunnelStatuses() {
statusObservationToken = NotificationCenter.default.addObserver(forName: .NEVPNStatusDidChange, object: nil, queue: OperationQueue.main) { [weak self] statusChangeNotification in
statusObservationToken = NotificationCenter.default.observe(name: .NEVPNStatusDidChange, object: nil, queue: OperationQueue.main) { [weak self] statusChangeNotification in
guard let self = self,
let session = statusChangeNotification.object as? NETunnelProviderSession,
let tunnelProvider = session.manager as? NETunnelProviderManager,
@@ -438,7 +464,7 @@ class TunnelsManager {
}
func startObservingTunnelConfigurations() {
configurationsObservationToken = NotificationCenter.default.addObserver(forName: .NEVPNConfigurationChange, object: nil, queue: OperationQueue.main) { [weak self] _ in
configurationsObservationToken = NotificationCenter.default.observe(name: .NEVPNConfigurationChange, object: nil, queue: OperationQueue.main) { [weak self] _ in
DispatchQueue.main.async { [weak self] in
// We schedule reload() in a subsequent runloop to ensure that the completion handler of loadAllFromPreferences
// (reload() calls loadAllFromPreferences) is called after the completion handler of the saveToPreferences or
@@ -398,12 +398,13 @@ class TunnelViewModel {
static let ipv4DefaultRouteString = "0.0.0.0/0"
static let ipv4DefaultRouteModRFC1918String = [ // Set of all non-private IPv4 IPs
"0.0.0.0/5", "8.0.0.0/7", "11.0.0.0/8", "12.0.0.0/6", "16.0.0.0/4", "32.0.0.0/3",
"64.0.0.0/2", "128.0.0.0/3", "160.0.0.0/5", "168.0.0.0/6", "172.0.0.0/12",
"172.32.0.0/11", "172.64.0.0/10", "172.128.0.0/9", "173.0.0.0/8", "174.0.0.0/7",
"176.0.0.0/4", "192.0.0.0/9", "192.128.0.0/11", "192.160.0.0/13", "192.169.0.0/16",
"192.170.0.0/15", "192.172.0.0/14", "192.176.0.0/12", "192.192.0.0/10",
"193.0.0.0/8", "194.0.0.0/7", "196.0.0.0/6", "200.0.0.0/5", "208.0.0.0/4"
"1.0.0.0/8", "2.0.0.0/8", "3.0.0.0/8", "4.0.0.0/6", "8.0.0.0/7", "11.0.0.0/8",
"12.0.0.0/6", "16.0.0.0/4", "32.0.0.0/3", "64.0.0.0/2", "128.0.0.0/3",
"160.0.0.0/5", "168.0.0.0/6", "172.0.0.0/12", "172.32.0.0/11", "172.64.0.0/10",
"172.128.0.0/9", "173.0.0.0/8", "174.0.0.0/7", "176.0.0.0/4", "192.0.0.0/9",
"192.128.0.0/11", "192.160.0.0/13", "192.169.0.0/16", "192.170.0.0/15",
"192.172.0.0/14", "192.176.0.0/12", "192.192.0.0/10", "193.0.0.0/8",
"194.0.0.0/7", "196.0.0.0/6", "200.0.0.0/5", "208.0.0.0/4"
]
static func excludePrivateIPsFieldStates(isSinglePeer: Bool, allowedIPs: Set<String>) -> (shouldAllowExcludePrivateIPsControl: Bool, excludePrivateIPsValue: Bool) {
@@ -9,6 +9,11 @@ class EditableTextCell: UITableViewCell {
set(value) { valueTextField.text = value }
}
var placeholder: String? {
get { return valueTextField.placeholder }
set(value) { valueTextField.placeholder = value }
}
let valueTextField: UITextField = {
let valueTextField = UITextField()
valueTextField.textAlignment = .left
@@ -29,12 +34,13 @@ class EditableTextCell: UITableViewCell {
valueTextField.delegate = self
contentView.addSubview(valueTextField)
valueTextField.translatesAutoresizingMaskIntoConstraints = false
let bottomAnchorConstraint = contentView.layoutMarginsGuide.bottomAnchor.constraint(equalToSystemSpacingBelow: valueTextField.bottomAnchor, multiplier: 1)
// Reduce the bottom margin by 0.5pt to maintain the default cell height (44pt)
let bottomAnchorConstraint = contentView.layoutMarginsGuide.bottomAnchor.constraint(equalTo: valueTextField.bottomAnchor, constant: -0.5)
bottomAnchorConstraint.priority = .defaultLow
NSLayoutConstraint.activate([
valueTextField.leadingAnchor.constraint(equalToSystemSpacingAfter: contentView.layoutMarginsGuide.leadingAnchor, multiplier: 1),
contentView.layoutMarginsGuide.trailingAnchor.constraint(equalToSystemSpacingAfter: valueTextField.trailingAnchor, multiplier: 1),
valueTextField.topAnchor.constraint(equalToSystemSpacingBelow: contentView.layoutMarginsGuide.topAnchor, multiplier: 1),
valueTextField.leadingAnchor.constraint(equalTo: contentView.layoutMarginsGuide.leadingAnchor),
contentView.layoutMarginsGuide.trailingAnchor.constraint(equalTo: valueTextField.trailingAnchor),
contentView.layoutMarginsGuide.topAnchor.constraint(equalTo: valueTextField.topAnchor),
bottomAnchorConstraint
])
}
@@ -50,6 +56,7 @@ class EditableTextCell: UITableViewCell {
override func prepareForReuse() {
super.prepareForReuse()
message = ""
placeholder = nil
}
}
@@ -27,7 +27,7 @@ class KeyValueCell: UITableViewCell {
}()
let valueTextField: UITextField = {
let valueTextField = UITextField()
let valueTextField = KeyValueCellTextField()
valueTextField.textAlignment = .right
valueTextField.isEnabled = false
valueTextField.font = UIFont.preferredFont(forTextStyle: .body)
@@ -115,8 +115,6 @@ class KeyValueCell: UITableViewCell {
expandToFitValueLabelConstraint.priority = .defaultLow + 1
expandToFitValueLabelConstraint.isActive = true
contentView.addSubview(valueLabelScrollView)
contentView.addSubview(valueLabelScrollView)
valueLabelScrollView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
@@ -234,3 +232,10 @@ extension KeyValueCell: UITextFieldDelegate {
}
}
class KeyValueCellTextField: UITextField {
override func placeholderRect(forBounds bounds: CGRect) -> CGRect {
// UIKit renders the placeholder label 0.5pt higher
return super.placeholderRect(forBounds: bounds).integral.offsetBy(dx: 0, dy: -0.5)
}
}
@@ -3,6 +3,7 @@
import UIKit
import SystemConfiguration.CaptiveNetwork
import NetworkExtension
protocol SSIDOptionEditTableViewControllerDelegate: class {
func ssidOptionSaved(option: ActivateOnDemandViewModel.OnDemandSSIDOption, ssids: [String])
@@ -39,9 +40,16 @@ class SSIDOptionEditTableViewController: UITableViewController {
selectedOption = option
selectedSSIDs = ssids
super.init(style: .grouped)
connectedSSID = getConnectedSSID()
loadSections()
loadAddSSIDRows()
addSSIDRows.removeAll()
addSSIDRows.append(.addNewSSID)
getConnectedSSID { [weak self] ssid in
guard let self = self else { return }
self.connectedSSID = ssid
self.updateCurrentSSIDEntry()
self.updateTableViewAddSSIDRows()
}
}
required init?(coder aDecoder: NSCoder) {
@@ -60,6 +68,7 @@ class SSIDOptionEditTableViewController: UITableViewController {
tableView.register(TextCell.self)
tableView.isEditing = true
tableView.allowsSelectionDuringEditing = true
tableView.keyboardDismissMode = .onDrag
}
func loadSections() {
@@ -71,14 +80,14 @@ class SSIDOptionEditTableViewController: UITableViewController {
}
}
func loadAddSSIDRows() {
addSSIDRows.removeAll()
if let connectedSSID = connectedSSID {
if !selectedSSIDs.contains(connectedSSID) {
addSSIDRows.append(.addConnectedSSID(connectedSSID: connectedSSID))
func updateCurrentSSIDEntry() {
if let connectedSSID = connectedSSID, !selectedSSIDs.contains(connectedSSID) {
if let first = addSSIDRows.first, case .addNewSSID = first {
addSSIDRows.insert(.addConnectedSSID(connectedSSID: connectedSSID), at: 0)
}
} else if let first = addSSIDRows.first, case .addConnectedSSID = first {
addSSIDRows.removeFirst()
}
addSSIDRows.append(.addNewSSID)
}
func updateTableViewAddSSIDRows() {
@@ -188,12 +197,13 @@ extension SSIDOptionEditTableViewController {
private func selectedSSIDCell(for tableView: UITableView, at indexPath: IndexPath) -> UITableViewCell {
let cell: EditableTextCell = tableView.dequeueReusableCell(for: indexPath)
cell.message = selectedSSIDs[indexPath.row]
cell.placeholder = tr("tunnelOnDemandSSIDTextFieldPlaceholder")
cell.isEditing = true
cell.onValueBeingEdited = { [weak self, weak cell] text in
guard let self = self, let cell = cell else { return }
if let row = self.tableView.indexPath(for: cell)?.row {
self.selectedSSIDs[row] = text
self.loadAddSSIDRows()
self.updateCurrentSSIDEntry()
self.updateTableViewAddSSIDRows()
}
}
@@ -224,7 +234,7 @@ extension SSIDOptionEditTableViewController {
} else {
tableView.reloadRows(at: [indexPath], with: .automatic)
}
loadAddSSIDRows()
updateCurrentSSIDEntry()
updateTableViewAddSSIDRows()
case .addSSIDs:
assert(editingStyle == .insert)
@@ -244,7 +254,7 @@ extension SSIDOptionEditTableViewController {
} else {
tableView.insertRows(at: [indexPath], with: .automatic)
}
loadAddSSIDRows()
updateCurrentSSIDEntry()
updateTableViewAddSSIDRows()
if newSSID.isEmpty {
if let selectedSSIDCell = tableView.cellForRow(at: indexPath) as? EditableTextCell {
@@ -253,6 +263,31 @@ extension SSIDOptionEditTableViewController {
}
}
}
private func getConnectedSSID(completionHandler: @escaping (String?) -> Void) {
#if targetEnvironment(simulator)
completionHandler("Simulator Wi-Fi")
#else
if #available(iOS 14, *) {
NEHotspotNetwork.fetchCurrent { hotspotNetwork in
completionHandler(hotspotNetwork?.ssid)
}
} else {
if let supportedInterfaces = CNCopySupportedInterfaces() as? [CFString] {
for interface in supportedInterfaces {
if let networkInfo = CNCopyCurrentNetworkInfo(interface) {
if let ssid = (networkInfo as NSDictionary)[kCNNetworkInfoKeySSID as String] as? String {
completionHandler(!ssid.isEmpty ? ssid : nil)
return
}
}
}
}
completionHandler(nil)
}
#endif
}
}
extension SSIDOptionEditTableViewController {
@@ -290,14 +325,3 @@ extension SSIDOptionEditTableViewController {
}
}
private func getConnectedSSID() -> String? {
guard let supportedInterfaces = CNCopySupportedInterfaces() as? [CFString] else { return nil }
for interface in supportedInterfaces {
if let networkInfo = CNCopyCurrentNetworkInfo(interface) {
if let ssid = (networkInfo as NSDictionary)[kCNNetworkInfoKeySSID as String] as? String {
return !ssid.isEmpty ? ssid : nil
}
}
}
return nil
}
@@ -11,7 +11,6 @@ class SettingsTableViewController: UITableViewController {
case goBackendVersion
case exportZipArchive
case viewLog
case donateLink
var localizedUIString: String {
switch self {
@@ -19,13 +18,12 @@ class SettingsTableViewController: UITableViewController {
case .goBackendVersion: return tr("settingsVersionKeyWireGuardGoBackend")
case .exportZipArchive: return tr("settingsExportZipButtonTitle")
case .viewLog: return tr("settingsViewLogButtonTitle")
case .donateLink: return tr("donateLink")
}
}
}
let settingsFieldsBySection: [[SettingsFields]] = [
[.iosAppVersion, .goBackendVersion, .donateLink],
[.iosAppVersion, .goBackendVersion],
[.exportZipArchive],
[.viewLog]
]
@@ -169,15 +167,6 @@ extension SettingsTableViewController {
self?.presentLogView()
}
return cell
} else if field == .donateLink {
let cell: ButtonCell = tableView.dequeueReusableCell(for: indexPath)
cell.buttonText = field.localizedUIString
cell.onTapped = {
if let url = URL(string: "https://www.wireguard.com/donations/"), UIApplication.shared.canOpenURL(url) {
UIApplication.shared.open(url, options: [:])
}
}
return cell
}
fatalError()
}
@@ -395,6 +395,7 @@ extension TunnelDetailTableViewController {
let cell: KeyValueCell = tableView.dequeueReusableCell(for: indexPath)
cell.key = field.localizedUIString
cell.value = onDemandViewModel.localizedInterfaceDescription
cell.copyableGesture = false
return cell
} else {
assert(field == .ssid)
@@ -402,6 +403,7 @@ extension TunnelDetailTableViewController {
let cell: KeyValueCell = tableView.dequeueReusableCell(for: indexPath)
cell.key = field.localizedUIString
cell.value = onDemandViewModel.ssidOption.localizedUIString
cell.copyableGesture = false
return cell
} else {
let cell: ChevronCell = tableView.dequeueReusableCell(for: indexPath)
+139 -34
View File
@@ -14,8 +14,14 @@ class StatusMenu: NSMenu {
var statusMenuItem: NSMenuItem?
var networksMenuItem: NSMenuItem?
var deactivateMenuItem: NSMenuItem?
var firstTunnelMenuItemIndex = 0
var numberOfTunnelMenuItems = 0
private let tunnelsBreakdownMenu = NSMenu()
private let tunnelsMenuItem = NSMenuItem(title: tr("macTunnelsMenuTitle"), action: nil, keyEquivalent: "")
private let tunnelsMenuSeparatorItem = NSMenuItem.separator()
private var firstTunnelMenuItemIndex = 0
private var numberOfTunnelMenuItems = 0
private var tunnelsPresentationStyle = StatusMenuTunnelsPresentationStyle.inline
var currentTunnel: TunnelContainer? {
didSet {
@@ -26,16 +32,20 @@ class StatusMenu: NSMenu {
init(tunnelsManager: TunnelsManager) {
self.tunnelsManager = tunnelsManager
super.init(title: tr("macMenuTitle"))
addStatusMenuItems()
addItem(NSMenuItem.separator())
tunnelsMenuItem.submenu = tunnelsBreakdownMenu
addItem(tunnelsMenuItem)
firstTunnelMenuItemIndex = numberOfItems
let isAdded = addTunnelMenuItems()
if isAdded {
addItem(NSMenuItem.separator())
}
populateInitialTunnelMenuItems()
addItem(tunnelsMenuSeparatorItem)
addTunnelManagementItems()
addItem(NSMenuItem.separator())
addApplicationItems()
@@ -108,15 +118,6 @@ class StatusMenu: NSMenu {
deactivateMenuItem.isHidden = tunnel.status != .active
}
func addTunnelMenuItems() -> Bool {
let numberOfTunnels = tunnelsManager.numberOfTunnels()
for index in 0 ..< tunnelsManager.numberOfTunnels() {
let tunnel = tunnelsManager.tunnel(at: index)
insertTunnelMenuItem(for: tunnel, at: numberOfTunnelMenuItems)
}
return numberOfTunnels > 0
}
func addTunnelManagementItems() {
let manageItem = NSMenuItem(title: tr("macMenuManageTunnels"), action: #selector(manageTunnelsClicked), keyEquivalent: "")
manageItem.target = self
@@ -166,34 +167,121 @@ class StatusMenu: NSMenu {
extension StatusMenu {
func insertTunnelMenuItem(for tunnel: TunnelContainer, at tunnelIndex: Int) {
let menuItem = TunnelMenuItem(tunnel: tunnel, action: #selector(tunnelClicked(sender:)))
menuItem.target = self
menuItem.isHidden = !tunnel.isTunnelAvailableToUser
insertItem(menuItem, at: firstTunnelMenuItemIndex + tunnelIndex)
if numberOfTunnelMenuItems == 0 {
insertItem(NSMenuItem.separator(), at: firstTunnelMenuItemIndex + tunnelIndex + 1)
let nextNumberOfTunnels = numberOfTunnelMenuItems + 1
guard !reparentTunnelMenuItems(nextNumberOfTunnels: nextNumberOfTunnels) else {
return
}
numberOfTunnelMenuItems += 1
let menuItem = makeTunnelItem(tunnel: tunnel)
switch tunnelsPresentationStyle {
case .submenu:
tunnelsBreakdownMenu.insertItem(menuItem, at: tunnelIndex)
case .inline:
insertItem(menuItem, at: firstTunnelMenuItemIndex + tunnelIndex)
}
numberOfTunnelMenuItems = nextNumberOfTunnels
updateTunnelsMenuItemVisibility()
}
func removeTunnelMenuItem(at tunnelIndex: Int) {
removeItem(at: firstTunnelMenuItemIndex + tunnelIndex)
numberOfTunnelMenuItems -= 1
if numberOfTunnelMenuItems == 0 {
if let firstItem = item(at: firstTunnelMenuItemIndex), firstItem.isSeparatorItem {
removeItem(at: firstTunnelMenuItemIndex)
}
let nextNumberOfTunnels = numberOfTunnelMenuItems - 1
guard !reparentTunnelMenuItems(nextNumberOfTunnels: nextNumberOfTunnels) else {
return
}
switch tunnelsPresentationStyle {
case .submenu:
tunnelsBreakdownMenu.removeItem(at: tunnelIndex)
case .inline:
removeItem(at: firstTunnelMenuItemIndex + tunnelIndex)
}
numberOfTunnelMenuItems = nextNumberOfTunnels
updateTunnelsMenuItemVisibility()
}
func moveTunnelMenuItem(from oldTunnelIndex: Int, to newTunnelIndex: Int) {
guard let oldMenuItem = item(at: firstTunnelMenuItemIndex + oldTunnelIndex) as? TunnelMenuItem else { return }
let oldMenuItemTunnel = oldMenuItem.tunnel
removeItem(at: firstTunnelMenuItemIndex + oldTunnelIndex)
let menuItem = TunnelMenuItem(tunnel: oldMenuItemTunnel, action: #selector(tunnelClicked(sender:)))
menuItem.target = self
insertItem(menuItem, at: firstTunnelMenuItemIndex + newTunnelIndex)
let tunnel = tunnelsManager.tunnel(at: newTunnelIndex)
let menuItem = makeTunnelItem(tunnel: tunnel)
switch tunnelsPresentationStyle {
case .submenu:
tunnelsBreakdownMenu.removeItem(at: oldTunnelIndex)
tunnelsBreakdownMenu.insertItem(menuItem, at: newTunnelIndex)
case .inline:
removeItem(at: firstTunnelMenuItemIndex + oldTunnelIndex)
insertItem(menuItem, at: firstTunnelMenuItemIndex + newTunnelIndex)
}
}
private func makeTunnelItem(tunnel: TunnelContainer) -> TunnelMenuItem {
let menuItem = TunnelMenuItem(tunnel: tunnel, action: #selector(tunnelClicked(sender:)))
menuItem.target = self
menuItem.isHidden = !tunnel.isTunnelAvailableToUser
return menuItem
}
private func populateInitialTunnelMenuItems() {
let numberOfTunnels = tunnelsManager.numberOfTunnels()
let initialStyle = tunnelsPresentationStyle.preferredPresentationStyle(numberOfTunnels: numberOfTunnels)
tunnelsPresentationStyle = initialStyle
switch initialStyle {
case .inline:
numberOfTunnelMenuItems = addTunnelMenuItems(into: self, at: firstTunnelMenuItemIndex)
case .submenu:
numberOfTunnelMenuItems = addTunnelMenuItems(into: tunnelsBreakdownMenu, at: 0)
}
updateTunnelsMenuItemVisibility()
}
private func reparentTunnelMenuItems(nextNumberOfTunnels: Int) -> Bool {
let nextStyle = tunnelsPresentationStyle.preferredPresentationStyle(numberOfTunnels: nextNumberOfTunnels)
switch (tunnelsPresentationStyle, nextStyle) {
case (.inline, .submenu):
tunnelsPresentationStyle = nextStyle
for index in (0..<numberOfTunnelMenuItems).reversed() {
removeItem(at: firstTunnelMenuItemIndex + index)
}
numberOfTunnelMenuItems = addTunnelMenuItems(into: tunnelsBreakdownMenu, at: 0)
updateTunnelsMenuItemVisibility()
return true
case (.submenu, .inline):
tunnelsPresentationStyle = nextStyle
tunnelsBreakdownMenu.removeAllItems()
numberOfTunnelMenuItems = addTunnelMenuItems(into: self, at: firstTunnelMenuItemIndex)
updateTunnelsMenuItemVisibility()
return true
case (.submenu, .submenu), (.inline, .inline):
return false
}
}
private func addTunnelMenuItems(into menu: NSMenu, at startIndex: Int) -> Int {
let numberOfTunnels = tunnelsManager.numberOfTunnels()
for tunnelIndex in 0..<numberOfTunnels {
let tunnel = tunnelsManager.tunnel(at: tunnelIndex)
let menuItem = makeTunnelItem(tunnel: tunnel)
menu.insertItem(menuItem, at: startIndex + tunnelIndex)
}
return numberOfTunnels
}
private func updateTunnelsMenuItemVisibility() {
switch tunnelsPresentationStyle {
case .inline:
tunnelsMenuItem.isHidden = true
case .submenu:
tunnelsMenuItem.isHidden = false
}
tunnelsMenuSeparatorItem.isHidden = numberOfTunnelMenuItems == 0
}
}
@@ -232,3 +320,20 @@ class TunnelMenuItem: NSMenuItem {
state = shouldShowCheckmark ? .on : .off
}
}
private enum StatusMenuTunnelsPresentationStyle {
case inline
case submenu
func preferredPresentationStyle(numberOfTunnels: Int) -> StatusMenuTunnelsPresentationStyle {
let maxInlineTunnels = 10
if case .inline = self, numberOfTunnels > maxInlineTunnels {
return .submenu
} else if case .submenu = self, numberOfTunnels <= maxInlineTunnels {
return .inline
} else {
return self
}
}
}
@@ -67,7 +67,7 @@ class ConfTextStorage: NSTextStorage {
override func replaceCharacters(in range: NSRange, with str: String) {
beginEditing()
backingStore.replaceCharacters(in: range, with: str)
edited(.editedCharacters, range: range, changeInLength: str.count - range.length)
edited(.editedCharacters, range: range, changeInLength: str.utf16.count - range.length)
endEditing()
}
@@ -94,6 +94,7 @@ class ConfTextStorage: NSTextStorage {
func evaluateExcludePrivateIPs(highlightSpans: UnsafePointer<highlight_span>) {
var spans = highlightSpans
let string = backingStore.string
enum FieldType: String {
case dns
case allowedips
@@ -102,7 +103,7 @@ class ConfTextStorage: NSTextStorage {
resetLastPeer()
while spans.pointee.type != HighlightEnd {
let span = spans.pointee
var substring = backingStore.attributedSubstring(from: NSRange(location: span.start, length: span.len)).string.lowercased()
var substring = String(string.substring(higlightSpan: span)).lowercased()
if span.type == HighlightError {
resetLastPeer()
@@ -123,8 +124,9 @@ class ConfTextStorage: NSTextStorage {
let next = spans.successor()
let nextnext = next.successor()
if next.pointee.type == HighlightDelimiter && nextnext.pointee.type == HighlightCidr {
substring += backingStore.attributedSubstring(from: NSRange(location: next.pointee.start, length: next.pointee.len)).string +
backingStore.attributedSubstring(from: NSRange(location: nextnext.pointee.start, length: nextnext.pointee.len)).string
let delimiter = string.substring(higlightSpan: next.pointee)
let cidr = string.substring(higlightSpan: nextnext.pointee)
substring += delimiter + cidr
}
lastOnePeerAllowedIPs.append(substring)
} else if span.type == HighlightPublicKey {
@@ -139,7 +141,8 @@ class ConfTextStorage: NSTextStorage {
hasError = false
privateKeyString = nil
let fullTextRange = NSRange(location: 0, length: (backingStore.string as NSString).length)
let string = backingStore.string
let fullTextRange = NSRange(..<string.endIndex, in: string)
backingStore.beginEditing()
let defaultAttributes: [NSAttributedString.Key: Any] = [
@@ -147,15 +150,19 @@ class ConfTextStorage: NSTextStorage {
.font: defaultFont
]
backingStore.setAttributes(defaultAttributes, range: fullTextRange)
var spans = highlight_config(backingStore.string)!
var spans = highlight_config(string)!
evaluateExcludePrivateIPs(highlightSpans: spans)
let spansStart = spans
while spans.pointee.type != HighlightEnd {
let span = spans.pointee
let range = NSRange(location: span.start, length: span.len)
let startIndex = string.utf8.index(string.startIndex, offsetBy: span.start)
let endIndex = string.utf8.index(startIndex, offsetBy: span.len)
let range = NSRange(startIndex..<endIndex, in: string)
backingStore.setAttributes(nonColorAttributes(for: span.type), range: range)
let color = textColorTheme.colorMap[span.type.rawValue, default: textColorTheme.defaultColor]
backingStore.addAttribute(.foregroundColor, value: color, range: range)
@@ -164,7 +171,7 @@ class ConfTextStorage: NSTextStorage {
}
if span.type == HighlightPrivateKey {
privateKeyString = backingStore.attributedSubstring(from: NSRange(location: span.start, length: span.len)).string
privateKeyString = String(string.substring(higlightSpan: span))
}
spans = spans.successor()
@@ -178,3 +185,12 @@ class ConfTextStorage: NSTextStorage {
}
}
private extension String {
func substring(higlightSpan span: highlight_span) -> Substring {
let startIndex = self.utf8.index(self.utf8.startIndex, offsetBy: span.start)
let endIndex = self.utf8.index(startIndex, offsetBy: span.len)
return self[startIndex..<endIndex]
}
}
@@ -70,7 +70,7 @@ class ConfTextView: NSTextView {
}
func setConfText(_ text: String) {
let fullTextRange = NSRange(location: 0, length: (string as NSString).length)
let fullTextRange = NSRange(..<string.endIndex, in: string)
if shouldChangeText(in: fullTextRange, replacementString: text) {
replaceCharacters(in: fullTextRange, with: text)
didChangeText()
@@ -18,6 +18,9 @@ class LogViewController: NSViewController {
}
}
private var boundsChangedNotificationToken: NotificationToken?
private var frameChangedNotificationToken: NotificationToken?
let scrollView: NSScrollView = {
let scrollView = NSScrollView()
scrollView.hasVerticalScroller = true
@@ -104,13 +107,13 @@ class LogViewController: NSViewController {
clipView.documentView = tableView
scrollView.contentView = clipView
_ = NotificationCenter.default.addObserver(forName: NSView.boundsDidChangeNotification, object: clipView, queue: OperationQueue.main) { [weak self] _ in
boundsChangedNotificationToken = NotificationCenter.default.observe(name: 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
frameChangedNotificationToken = NotificationCenter.default.observe(name: NSView.frameDidChangeNotification, object: tableView, queue: OperationQueue.main) { [weak self] _ in
guard let self = self else { return }
if self.isInScrolledToEndMode {
DispatchQueue.main.async {
@@ -235,6 +235,7 @@
"macMenuFile" = "File";
"tunnelStatusActivating" = "Activating";
"macToolTipToggleStatus" = "Toggle status (⌘T)";
"macTunnelsMenuTitle" = "Tunnels";
"alertTunnelActivationSystemErrorTitle" = "Activation failure";
"alertInvalidInterfaceMessagePrivateKeyRequired" = "Interfaces private key is required";
"alertNoTunnelsToExportTitle" = "Nothing to export";
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
// Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
// Generic alert action names
@@ -443,3 +443,4 @@
// Donation
"donateLink" = "♥ Spende an das WireGuard Projekt";
"macTunnelsMenuTitle" = "Tunnels";
+170 -93
View File
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
// Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
// Generic alert action names
@@ -80,7 +80,7 @@
"tunnelPeerPublicKey" = "Clave pública";
"tunnelPeerPreSharedKey" = "Clave precompartida";
"tunnelPeerEndpoint" = "Punto final";
"tunnelPeerPersistentKeepalive" = "Mantenimiento persistente";
"tunnelPeerPersistentKeepalive" = "Keepalive persistente";
"tunnelPeerAllowedIPs" = "IPs permitidas";
"tunnelPeerRxBytes" = "Datos recibidos";
"tunnelPeerTxBytes" = "Datos enviados";
@@ -177,142 +177,219 @@
"alertInvalidPeerMessagePreSharedKeyInvalid" = "La clave precompartida del par debe ser de 32 bytes en codificación base64";
"alertInvalidPeerMessageAllowedIPsInvalid" = "Las IPs permitidas del par deben ser una lista de direcciones IP separadas por comas, opcionalmente en notación CIDR";
"alertInvalidPeerMessageEndpointInvalid" = "El punto final del par debe ser de la forma host:port o [host]:port";
"alertInvalidPeerMessagePersistentKeepaliveInvalid" = "El keepalive persistente del par debe estar entre 0 y 65535, o no especificado";
"alertInvalidPeerMessagePersistentKeepaliveInvalid" = "El keepalive persistente del peer debe estar entre 0 y 65535, o no especificado";
"alertInvalidPeerMessagePublicKeyDuplicated" = "Dos o mas pares no pueden tener la misma llave pùblica";
// Scanning QR code UI
"scanQRCodeViewTitle" = "Escanear código QR";
"scanQRCodeTipText" = "Consejo: generar con `qrencode -t ansiutf8 tunnel.conf`";
// Scanning QR code alerts
"alertScanQRCodeCameraUnsupportedTitle" = "Cámara no soportada";
"alertScanQRCodeCameraUnsupportedMessage" = "Este dispositivo no es capaz de escanear códigos QR";
"alertScanQRCodeInvalidQRCodeTitle" = "Código QR inválido";
"alertScanQRCodeInvalidQRCodeMessage" = "El código QR escaneado no es una configuración válida de WireGuard";
"alertScanQRCodeUnreadableQRCodeTitle" = "Código inválido";
"alertScanQRCodeUnreadableQRCodeMessage" = "El código escaneado no pudo ser leído";
"alertScanQRCodeNamePromptTitle" = "Por favor, nombra el túnel escaneado";
// Settings UI
"settingsViewTitle" = "Configuración";
"settingsSectionTitleAbout" = "Acerca de";
"settingsVersionKeyWireGuardForIOS" = "WireGuard para iOS";
"settingsSectionTitleExportConfigurations" = "Exportar configuraciones";
"settingsExportZipButtonTitle" = "Exportar archivo zip";
"settingsSectionTitleTunnelLog" = "Registro";
"settingsViewLogButtonTitle" = "Ver registro";
// Log view
"logViewTitle" = "Registro";
// Log alerts
"alertUnableToRemovePreviousLogTitle" = "Exportación de registros fallida";
"alertUnableToRemovePreviousLogMessage" = "El registro preexistente no ha podido ser borrado";
"alertUnableToWriteLogTitle" = "Exportación de registros fallida";
"alertUnableToWriteLogMessage" = "No se pudo escribir en el archivo de registros";
// Zip import / export error alerts
"alertCantOpenInputZipFileTitle" = "No se pudo leer el archivo zip";
"alertCantOpenInputZipFileMessage" = "El archivo zip no pudo ser leído.";
"alertCantOpenOutputZipFileForWritingTitle" = "No se pudo crear el archivo zip";
"alertCantOpenOutputZipFileForWritingMessage" = "No se pudo abrir el archivo zip para escribir.";
"alertBadArchiveTitle" = "No se pudo leer el archivo zip";
"alertBadArchiveMessage" = "Archivo zip erróneo o corrupto.";
"alertNoTunnelsToExportTitle" = "Nada para exportar";
"settingsSectionTitleAbout" = "About";
"macMenuDeleteSelected" = "Delete Selected";
"alertSystemErrorMessageTunnelConfigurationInvalid" = "The configuration is invalid.";
"alertNoTunnelsToExportMessage" = "No hay túneles para exportar";
"alertNoTunnelsInImportedZipArchiveTitle" = "No hay túneles en el archivo zip";
// Tunnel management error alerts
"alertTunnelActivationFailureTitle" = "Fallo en la activación";
"alertTunnelActivationFailureMessage" = "El túnel no pudo ser activado. Por favor, asegúrese de estar conectado a Internet.";
"alertTunnelActivationSavedConfigFailureMessage" = "No se ha podido recuperar la información del túnel de la configuración guardada.";
"alertTunnelDNSFailureTitle" = "Fallo en resolución DNS";
"alertSystemErrorOnAddTunnelTitle" = "No se pudo crear el túnel";
"alertSystemErrorOnModifyTunnelTitle" = "No se pudo modificar el túnel";
"alertSystemErrorOnRemoveTunnelTitle" = "No se pudo eliminar el túnel";
/* The alert message for this alert shall include
one of the alertSystemErrorMessage* listed further down */
"alertTunnelActivationSystemErrorTitle" = "Fallo en la activación";
"alertTunnelActivationSystemErrorMessage (%@)" = "No se pudo activar el túnel. %@";
/* alertSystemErrorMessage* messages */
"alertSystemErrorMessageTunnelConfigurationInvalid" = "La configuración es inválida.";
"alertSystemErrorMessageTunnelConfigurationDisabled" = "La configuración está desactivada.";
"alertSystemErrorMessageTunnelConnectionFailed" = "La conexión ha fallado.";
"alertSystemErrorMessageTunnelConfigurationUnknown" = "Error desconocido de sistema.";
"macMenuTitle" = "WireGuard";
"macMenuManageTunnels" = "Gestionar túneles";
"macMenuImportTunnels" = "Importar túnel(es) desde archivo";
"macMenuViewLog" = "Ver registro";
"macMenuAbout" = "Acerca de WireGuard";
"macMenuQuit" = "Salir de WireGuard";
"macMenuHideApp" = "Ocultar WireGuard";
"macMenuShowAllApps" = "Mostrar todo";
"macMenuFile" = "Archivo";
"macMenuCloseWindow" = "Cerrar Ventana";
"macMenuEdit" = "Editar";
"macMenuCut" = "Cortar";
"macMenuCopy" = "Copiar";
"macMenuPaste" = "Pegar";
"macMenuSelectAll" = "Seleccionar todo";
"macMenuTunnel" = "Túnel";
"macMenuToggleStatus" = "Cambiar estado";
"macMenuEditTunnel" = "Editar…";
"macMenuDeleteSelected" = "Eliminar elementos seleccionados";
"macMenuWindow" = "Ventana";
"macMenuMinimize" = "Minimizar";
// Mac manage tunnels window
"macWindowTitleManageTunnels" = "Gestionar Túneles WireGuard";
"macDeleteTunnelConfirmationAlertMessage (%@)" = "¿Estás seguro que deseas eliminar \"%@\"?";
"macDeleteMultipleTunnelsConfirmationAlertMessage (%d)" = "¿Está seguro que desea eliminar %d túneles?";
"macDeleteTunnelConfirmationAlertInfo" = "No puedes deshacer esta acción.";
"macDeleteTunnelConfirmationAlertButtonTitleDelete" = "Eliminar";
"macDeleteTunnelConfirmationAlertButtonTitleCancel" = "Cancelar";
"macDeleteTunnelConfirmationAlertButtonTitleDeleting" = "Eliminando…";
"macButtonImportTunnels" = "Importar túnel(es) desde archivo";
"macSheetButtonImport" = "Importar";
"macNameFieldExportLog" = "Guardar registro en:";
"macSheetButtonExportLog" = "Guardar";
"macNameFieldExportZip" = "Exportar túneles a:";
"macSheetButtonExportZip" = "Guardar";
"macButtonDeleteTunnels (%d)" = "Eliminar %d túneles";
"macButtonEdit" = "Editar";
"macFieldOnDemand" = "Bajo demanda:";
"macFieldOnDemandSSIDs" = "SSIDs:";
// Mac status display
"macStatus (%@)" = "Estado: %@";
// Mac editing config
"macEditDiscard" = "Descartar";
"macEditSave" = "Guardar";
"macAlertDNSInvalid (%@)" = "El DNS %@ no es válido.";
"macAlertPublicKeyInvalid" = "La Clave pública no es válida";
"macAlertPreSharedKeyInvalid" = "La clave compartida no es válida";
"macAlertEndpointInvalid (%@)" = "Endpoint %@ no es válido";
"macAlertPersistentKeepliveInvalid (%@)" = "El valor keepalive persistente '%@' no es válido";
"macAlertInfoUnrecognizedPeerKey" = "Las claves válidas son: PublicKey, PresharedKey, AllowedIPs, Endpoint y PersistentKeepalive";
"macConfirmAndQuitAlertQuitWireGuard" = "Salir de WireGuard";
"macConfirmAndQuitAlertCloseWindow" = "Cerrar Gestor de túneles";
// Mac tooltip
"macToolTipEditTunnel" = "Editar túnel (⌘E)";
"macToolTipToggleStatus" = "Cambiar estado (⌘T)";
// Mac log view
"macLogColumnTitleTime" = "Tiempo";
"macLogColumnTitleLogMessage" = "Mensaje de registro";
"macLogButtonTitleClose" = "Cerrar";
"macLogButtonTitleSave" = "Guardar…";
// Mac unusable tunnel view
"macUnusableTunnelMessage" = "La configuración de este túnel no se encuentra en el llavero.";
"macUnusableTunnelButtonTitleDeleteTunnel" = "Eliminar túnel";
// Mac App Store updating alert
"macAppStoreUpdatingAlertMessage" = "App Store desea actualizar WireGuard";
// Donation
"donateLink" = "♥ Donar al Proyecto WireGuard";
"macAlertNoInterface" = "Configuration must have an Interface section.";
"macNameFieldExportZip" = "Export tunnels to:";
"alertSystemErrorMessageTunnelConfigurationUnknown" = "Unknown system error.";
"macMenuCut" = "Cut";
"macEditDiscard" = "Discard";
"alertScanQRCodeCameraUnsupportedMessage" = "This device is not able to scan QR codes";
"macSheetButtonExportZip" = "Save";
"macWindowTitleManageTunnels" = "Manage WireGuard Tunnels";
"macConfirmAndQuitAlertInfo" = "If you close the tunnels manager, WireGuard will continue to be available from the menu bar icon.";
"macUnusableTunnelInfo" = "In case this tunnel was created by another user, only that user can view, edit, or activate this tunnel.";
"alertTunnelActivationErrorTunnelIsNotInactiveMessage" = "The tunnel is already active or in the process of being activated";
"alertTunnelActivationSetNetworkSettingsMessage" = "Unable to apply network settings to tunnel object.";
"macMenuExportTunnels" = "Export Tunnels to Zip…";
"macMenuShowAllApps" = "Show All";
"alertCantOpenInputConfFileTitle" = "Unable to import from file";
"alertScanQRCodeInvalidQRCodeMessage" = "The scanned QR code is not a valid WireGuard configuration";
"macMenuHideApp" = "Hide WireGuard";
"settingsViewTitle" = "Settings";
"macDeleteTunnelConfirmationAlertInfo" = "You cannot undo this action.";
"macDeleteTunnelConfirmationAlertButtonTitleDeleting" = "Deleting…";
"settingsViewLogButtonTitle" = "View log";
"alertSystemErrorMessageTunnelConnectionFailed" = "The connection failed.";
"macButtonEdit" = "Edit";
"macAlertPublicKeyInvalid" = "Public key is invalid";
"macNameFieldExportLog" = "Save log to:";
"alertSystemErrorOnAddTunnelTitle" = "Unable to create tunnel";
"macConfirmAndQuitAlertMessage" = "Do you want to close the tunnels manager or quit WireGuard entirely?";
"alertTunnelActivationSavedConfigFailureMessage" = "Unable to retrieve tunnel information from the saved configuration.";
"macAlertInfoUnrecognizedInterfaceKey" = "Valid keys are: PrivateKey, ListenPort, Address, DNS and MTU.";
"macLogColumnTitleTime" = "Time";
"alertTunnelNameEmptyMessage" = "Cannot create tunnel with an empty name";
"alertTunnelNameEmptyTitle" = "No name provided";
"alertUnableToWriteLogMessage" = "Unable to write logs to file";
"macMenuQuit" = "Quit WireGuard";
"macMenuAddEmptyTunnel" = "Add Empty Tunnel…";
"macDeleteTunnelConfirmationAlertButtonTitleDelete" = "Delete";
"alertTunnelActivationFailureOnDemandAddendum" = " This tunnel has Activate On Demand enabled, so this tunnel might be re-activated automatically by the OS. You may turn off Activate On Demand in this app by editing the tunnel configuration.";
"alertTunnelActivationFailureTitle" = "Activation failure";
"macLogButtonTitleClose" = "Close";
"settingsExportZipButtonTitle" = "Export zip archive";
"macViewPrivateData" = "view tunnel private keys";
"alertTunnelActivationErrorTunnelIsNotInactiveTitle" = "Activation in progress";
"macAppExitingWithActiveTunnelInfo" = "The tunnel will remain active after exiting. You may disable it by reopening this application or through the Network panel in System Preferences.";
"macMenuEdit" = "Edit";
"donateLink" = "♥ Donate to the WireGuard Project";
"alertScanQRCodeCameraUnsupportedTitle" = "Camera Unsupported";
"macMenuWindow" = "Window";
"alertTunnelActivationFailureMessage" = "The tunnel could not be activated. Please ensure that you are connected to the Internet.";
"macMenuHideOtherApps" = "Hide Others";
"alertCantOpenInputZipFileMessage" = "The zip archive could not be read.";
"macAlertPrivateKeyInvalid" = "Private key is invalid.";
"macDeleteTunnelConfirmationAlertButtonTitleCancel" = "Cancel";
"alertSystemErrorMessageTunnelConfigurationDisabled" = "The configuration is disabled.";
"alertUnableToWriteLogTitle" = "Log export failed";
"macMenuNetworksNone" = "Networks: None";
"alertCantOpenOutputZipFileForWritingMessage" = "Could not open zip file for writing.";
"macMenuSelectAll" = "Select All";
"logViewTitle" = "Log";
"macConfirmAndQuitAlertQuitWireGuard" = "Quit WireGuard";
"alertSystemErrorOnRemoveTunnelTitle" = "Unable to remove tunnel";
"macFieldOnDemand" = "On-Demand:";
"macMenuCloseWindow" = "Close Window";
"macSheetButtonExportLog" = "Save";
"alertSystemErrorOnModifyTunnelTitle" = "Unable to modify tunnel";
"alertSystemErrorMessageTunnelConfigurationReadWriteFailed" = "Reading or writing the configuration failed.";
"macMenuEditTunnel" = "Edit…";
"settingsSectionTitleTunnelLog" = "Log";
"macMenuManageTunnels" = "Manage Tunnels";
"macButtonImportTunnels" = "Import tunnel(s) from file";
"macAppExitingWithActiveTunnelMessage" = "WireGuard is exiting with an active tunnel";
"alertSystemErrorMessageTunnelConfigurationStale" = "The configuration is stale.";
"alertTunnelDNSFailureMessage" = "One or more endpoint domains could not be resolved.";
"alertNoTunnelsInImportedZipArchiveTitle" = "No tunnels in zip archive";
"alertTunnelDNSFailureTitle" = "DNS resolution failure";
"macLogButtonTitleSave" = "Save…";
"macMenuToggleStatus" = "Toggle Status";
"macMenuMinimize" = "Minimize";
"alertCantOpenInputZipFileTitle" = "Unable to read zip archive";
"alertScanQRCodeUnreadableQRCodeMessage" = "The scanned code could not be read";
"alertScanQRCodeUnreadableQRCodeTitle" = "Invalid Code";
"alertSystemErrorOnListingTunnelsTitle" = "Unable to list tunnels";
"settingsVersionKeyWireGuardForIOS" = "WireGuard for iOS";
"macMenuPaste" = "Paste";
"macAlertMultipleInterfaces" = "Configuration must have only one Interface section.";
"macAppStoreUpdatingAlertMessage" = "App Store would like to update WireGuard";
"macUnusableTunnelMessage" = "The configuration for this tunnel cannot be found in the keychain.";
"macToolTipEditTunnel" = "Edit tunnel (⌘E)";
"macMenuZoom" = "Zoom";
"alertBadArchiveTitle" = "Unable to read zip archive";
"macExportPrivateData" = "export tunnel private keys";
"alertTunnelAlreadyExistsWithThatNameTitle" = "Name already exists";
"iosViewPrivateData" = "Authenticate to view tunnel private keys.";
"macAlertPreSharedKeyInvalid" = "Preshared key is invalid";
"macEditSave" = "Save";
"macConfirmAndQuitAlertCloseWindow" = "Close Tunnels Manager";
"macMenuFile" = "File";
"macToolTipToggleStatus" = "Toggle status (⌘T)";
"alertTunnelActivationSystemErrorTitle" = "Activation failure";
"scanQRCodeTipText" = "Tip: Generate with `qrencode -t ansiutf8 < tunnel.conf`";
"alertNoTunnelsToExportMessage" = "There are no tunnels to export";
"macMenuImportTunnels" = "Import Tunnel(s) from File…";
"alertScanQRCodeInvalidQRCodeTitle" = "Invalid QR Code";
"macMenuViewLog" = "View Log";
"macAlertInfoUnrecognizedPeerKey" = "Valid keys are: PublicKey, PresharedKey, AllowedIPs, Endpoint and PersistentKeepalive";
"macUnusableTunnelButtonTitleDeleteTunnel" = "Delete tunnel";
"macMenuTunnel" = "Tunnel";
"macMenuCopy" = "Copy";
"macTunnelsMenuTitle" = "Tunnels";
"alertTunnelAlreadyExistsWithThatNameMessage" = "A tunnel with that name already exists";
"macLogColumnTitleLogMessage" = "Log message";
"iosExportPrivateData" = "Authenticate to export tunnel private keys.";
"macMenuAbout" = "About WireGuard";
"macSheetButtonImport" = "Import";
"alertScanQRCodeNamePromptTitle" = "Please name the scanned tunnel";
"alertUnableToRemovePreviousLogMessage" = "The pre-existing log could not be cleared";
"alertTunnelActivationBackendFailureMessage" = "Unable to turn on Go backend library.";
"settingsSectionTitleExportConfigurations" = "Export configurations";
"alertBadArchiveMessage" = "Bad or corrupt zip archive.";
"settingsVersionKeyWireGuardGoBackend" = "WireGuard Go Backend";
"macFieldOnDemandSSIDs" = "SSIDs:";
"alertCantOpenOutputZipFileForWritingTitle" = "Unable to create zip archive";
"alertNoTunnelsInImportedZipArchiveMessage" = "No .conf tunnel files were found inside the zip archive.";
"alertTunnelActivationFileDescriptorFailureMessage" = "Unable to determine TUN device file descriptor.";
"macAlertNameIsEmpty" = "Name is required";
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
// Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
// Generic alert action names
@@ -389,6 +389,7 @@
"macUnusableTunnelMessage" = "The configuration for this tunnel cannot be found in the keychain.";
"iosViewPrivateData" = "Authenticate to view tunnel private keys.";
"macToolTipToggleStatus" = "Toggle status (⌘T)";
"macTunnelsMenuTitle" = "Tunnels";
"scanQRCodeTipText" = "Tip: Generate with `qrencode -t ansiutf8 < tunnel.conf`";
"macAlertInfoUnrecognizedPeerKey" = "Valid keys are: PublicKey, PresharedKey, AllowedIPs, Endpoint and PersistentKeepalive";
"alertInvalidPeerMessageAllowedIPsInvalid" = "Peers allowed IPs must be a list of comma-separated IP addresses, optionally in CIDR notation";
+313 -158
View File
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
// Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
// Generic alert action names
@@ -12,20 +12,103 @@
"tunnelsListTitle" = "WireGuard";
"tunnelsListSettingsButtonTitle" = "Asetukset";
"tunnelsListCenteredAddTunnelButtonTitle" = "Lisää tunneli";
"tunnelsListSwipeDeleteButtonTitle" = "Poista";
"tunnelsListSelectButtonTitle" = "Valitse";
"tunnelsListSelectAllButtonTitle" = "Valitse kaikki";
"tunnelsListDeleteButtonTitle" = "Poista";
"tunnelsListSelectedTitle (%d)" = "%d poistettu";
// Tunnels list menu
"addTunnelMenuHeader" = "Lisää uusi WireGuard tunneli";
"addTunnelMenuImportFile" = "Luo tiedostosta tai arkistosta";
"addTunnelMenuQRCode" = "Luo QR-koodista";
"addTunnelMenuFromScratch" = "Luo alusta";
// Tunnels list alerts
"alertImportedFromMultipleFilesTitle (%d)" = "Luotu %d tunnelia";
"alertImportedFromMultipleFilesMessage (%1$d of %2$d)" = "Luotu %1$d / %2$d tunnelia tuoduista tiedostoista";
"alertImportedFromZipTitle (%d)" = "Luotu %d tunnelia";
"alertImportedFromZipMessage (%1$d of %2$d)" = "Luotu %1$d / %2$d tunnelia zip-arkistosta";
"alertBadConfigImportTitle" = "Tunnelia ei voitu tuoda";
"alertBadConfigImportMessage (%@)" = "Tiedosto ”%@” ei sisällä kelvollista WireGuard konfiguraatiota";
"deleteTunnelsConfirmationAlertButtonTitle" = "Poista";
"deleteTunnelConfirmationAlertButtonMessage (%d)" = "Poista %d tunneli?";
"deleteTunnelsConfirmationAlertButtonMessage (%d)" = "Poista %d tunnelit?";
// Tunnel detail and edit UI
"newTunnelViewTitle" = "Uusi konfiguraatio";
"editTunnelViewTitle" = "Muokkaa konfiguraatiota";
"tunnelSectionTitleStatus" = "Tila";
"tunnelStatusInactive" = "Ei aktiivinen";
"tunnelStatusActivating" = "Aktivoidaan";
"tunnelStatusActive" = "Aktiivinen";
"tunnelStatusDeactivating" = "Deaktivoidaan";
"tunnelStatusReasserting" = "Aktivoidaan uudelleen";
"tunnelStatusRestarting" = "Käynnistetään uudelleen";
"tunnelStatusWaiting" = "Odotetaan";
"macToggleStatusButtonActivate" = "Aktivoi";
"macToggleStatusButtonActivating" = "Aktivoidaan…";
"macToggleStatusButtonDeactivate" = "Deaktivoi";
"macToggleStatusButtonDeactivating" = "Deaktivoidaan…";
"macToggleStatusButtonReasserting" = "Aktivoidaan uudelleen…";
"macToggleStatusButtonRestarting" = "Käynnistetään uudelleen…";
"macToggleStatusButtonWaiting" = "Odotetaan…";
"tunnelSectionTitleInterface" = "Liittymä";
"tunnelInterfaceName" = "Nimi";
"tunnelInterfacePrivateKey" = "Yksityinen avain";
"tunnelInterfacePublicKey" = "Julkinen avain";
"tunnelInterfaceGenerateKeypair" = "Luo avainpari";
"tunnelInterfaceAddresses" = "Osoitteet";
"tunnelInterfaceListenPort" = "Kuuntele porttia";
"tunnelInterfaceMTU" = "MTU";
"tunnelInterfaceDNS" = "DNS palvelimet";
"tunnelInterfaceStatus" = "Tila";
"tunnelSectionTitlePeer" = "Osapuoli";
"tunnelPeerPublicKey" = "Julkinen avain";
"tunnelPeerPreSharedKey" = "Jaettu avain";
"tunnelPeerEndpoint" = "Päätepiste";
"tunnelPeerPersistentKeepalive" = "Jatkuva keepalive";
"tunnelPeerAllowedIPs" = "Sallitut IP-osoitteet";
"tunnelPeerRxBytes" = "Data vastaanotettu";
"tunnelPeerTxBytes" = "Data lähetetty";
"tunnelPeerLastHandshakeTime" = "Viimeisin kättely";
"tunnelPeerExcludePrivateIPs" = "Jätä pois yksityiset IP-osoitteet";
"tunnelSectionTitleOnDemand" = "Automaattinen käyttöönotto";
"tunnelOnDemandCellular" = "Matkapuhelinverkko";
"tunnelOnDemandEthernet" = "Ethernet";
"tunnelOnDemandWiFi" = "Wi-Fi";
"tunnelOnDemandSSIDsKey" = "SSID:t";
"tunnelOnDemandAnySSID" = "Mikä tahansa SSID";
"tunnelOnDemandOnlyTheseSSIDs" = "Vain nämä SSID:t";
"tunnelOnDemandExceptTheseSSIDs" = "Poislukien SSID:t";
"tunnelOnDemandOnlySSID (%d)" = "Vain %d SSID";
"tunnelOnDemandOnlySSIDs (%d)" = "Vain %d SSID:t";
"tunnelOnDemandExceptSSID (%d)" = "Kaikki paitsi %d SSID";
"tunnelOnDemandExceptSSIDs (%d)" = "Kaikki paitsi %d SSID:t";
"tunnelOnDemandSSIDOptionDescriptionMac (%1$@: %2$@)" = "%1$@: %2$@";
"tunnelOnDemandSSIDViewTitle" = "SSID:t";
"tunnelOnDemandSectionTitleSelectedSSIDs" = "SSID:t";
"tunnelOnDemandNoSSIDs" = "Ei SSID-tietoja";
"tunnelOnDemandSectionTitleAddSSIDs" = "Lisää SSID-tietoja";
"tunnelOnDemandAddMessageAddConnectedSSID (%@)" = "Lisää yhdistetty: %@";
"tunnelOnDemandAddMessageAddNewSSID" = "Lisää uusi";
"tunnelOnDemandKey" = "Tarvittaessa";
"tunnelOnDemandOptionOff" = "Pois päältä";
@@ -35,6 +118,12 @@
"tunnelOnDemandOptionWiFiOrEthernet" = "Wi-Fi tai Ethernet";
"tunnelOnDemandOptionEthernetOnly" = "Vain Ethernet";
"addPeerButtonTitle" = "Lisää toinen osapuoli";
"deletePeerButtonTitle" = "Poista osapuoli";
"deletePeerConfirmationAlertButtonTitle" = "Poista";
"deletePeerConfirmationAlertMessage" = "Poistetaanko tämä osapuoli?";
"deleteTunnelButtonTitle" = "Poista tunneli";
"deleteTunnelConfirmationAlertButtonTitle" = "Poista";
"deleteTunnelConfirmationAlertMessage" = "Poistetaanko tämä tunneli?";
@@ -42,207 +131,273 @@
"tunnelEditPlaceholderTextRequired" = "Pakollinen";
"tunnelEditPlaceholderTextOptional" = "Valinnainen";
"tunnelEditPlaceholderTextAutomatic" = "Automaattinen";
"tunnelEditPlaceholderTextStronglyRecommended" = "Erittäin suositeltavaa";
"tunnelEditPlaceholderTextOff" = "Pois päältä";
"tunnelPeerPersistentKeepaliveValue (%@)" = "joka %@ sekuntin välein";
"tunnelHandshakeTimestampNow" = "Nyt";
"settingsSectionTitleAbout" = "About";
"newTunnelViewTitle" = "New configuration";
"macMenuDeleteSelected" = "Delete Selected";
"alertSystemErrorMessageTunnelConfigurationInvalid" = "The configuration is invalid.";
"tunnelInterfaceDNS" = "DNS servers";
"tunnelPeerEndpoint" = "Endpoint";
"tunnelInterfaceMTU" = "MTU";
"alertInvalidInterfaceMessageListenPortInvalid" = "Interfaces listen port must be between 0 and 65535, or unspecified";
"addPeerButtonTitle" = "Add peer";
"tunnelHandshakeTimestampSystemClockBackward" = "(System clock wound backwards)";
"tunnelsListSwipeDeleteButtonTitle" = "Delete";
"tunnelHandshakeTimestampSystemClockBackward" = "(Järjestelmän kello jättää)";
"tunnelHandshakeTimestampAgo (%@)" = "%@ sitten";
"tunnelHandshakeTimestampYear (%d)" = "%d vuosi";
"tunnelHandshakeTimestampYears (%d)" = "%d vuotta";
"tunnelHandshakeTimestampDay (%d)" = "%d päivä";
"tunnelHandshakeTimestampDays (%d)" = "%d päivää";
"tunnelHandshakeTimestampHour (%d)" = "%d tunti";
"tunnelHandshakeTimestampHours (%d)" = "%d tuntia";
"tunnelHandshakeTimestampMinute (%d)" = "%d minuutti";
"tunnelHandshakeTimestampMinutes (%d)" = "%d minuuttia";
"tunnelHandshakeTimestampSecond (%d)" = "%d sekunti";
"tunnelHandshakeTimestampSeconds (%d)" = "%d sekuntia";
"tunnelHandshakeTimestampHours hh:mm:ss (%@)" = "%@ tuntia";
"tunnelHandshakeTimestampMinutes mm:ss (%@)" = "%@ minuuttia";
"tunnelPeerPresharedKeyEnabled" = "käytössä";
// Error alerts while creating / editing a tunnel configuration
/* Alert title for error in the interface data */
"alertInvalidInterfaceTitle" = "Virheellinen liittymä";
/* Any one of the following alert messages can go with the above title */
"alertInvalidInterfaceMessageNameRequired" = "Sovittimen nimi vaadittu";
"alertInvalidInterfaceMessagePrivateKeyRequired" = "Sovittimen yksityinen avain on vaadittu";
"alertInvalidInterfaceMessagePrivateKeyInvalid" = "Sovittimen yksityinen avain on oltava 32-tavuinen avain base64 enkoodauksella";
"alertInvalidInterfaceMessageAddressInvalid" = "Sovittimen osoitteet on oltava pilkulla erotettujen IP-osoitteiden luettelo, valinnaisesti CIDR-notaatiossa";
"alertInvalidInterfaceMessageListenPortInvalid" = "Sovittimen kuunteluportin on tulee olla väliltä 0 - 65535, tai sen on oltava määrittelemätön";
"alertInvalidInterfaceMessageMTUInvalid" = "Sovittimen MTU on oltava väliltä 576 - 65535, tai sen on oltava määrittelemätön";
"alertInvalidInterfaceMessageDNSInvalid" = "Sovittimen DNS-palvelimien on oltava lista pilkulla erotettu IP-osoitteita";
/* Alert title for error in the peer data */
"alertInvalidPeerTitle" = "Virheellinen osapuoli";
/* Any one of the following alert messages can go with the above title */
"alertInvalidPeerMessagePublicKeyRequired" = "Osapuolen julkinen avain on vaadittu";
"alertInvalidPeerMessagePublicKeyInvalid" = "Osapuolen julkinen avain on oltava 32-tavuinen avain base64 -enkoodauksella";
"alertInvalidPeerMessagePreSharedKeyInvalid" = "Osapuolen jaettu avain on oltava 32-tavuinen avain base64 -enkoodauksella";
"alertInvalidPeerMessageAllowedIPsInvalid" = "Toisen osapuolen sallittujen IP-osoitteiden on oltava pilkulla erotettujen IP-osoitteiden luettelo, valinnaisesti CIDR-notaatiossa";
"alertInvalidPeerMessageEndpointInvalid" = "Käyttäjän päätepisteen on oltava muotoa ”host:port” tai ”[host]:port”";
"alertInvalidPeerMessagePersistentKeepaliveInvalid" = "Käyttäjän pysyvän keepalivin on oltava välillä 065535 tai määrittelemätön";
"alertInvalidPeerMessagePublicKeyDuplicated" = "Kahdella tai useammalla osapuolella ei voi olla samaa julkista avainta";
// Scanning QR code UI
"scanQRCodeViewTitle" = "Skannaa QR-koodi";
"scanQRCodeTipText" = "Vihje: Luo käyttämällä `qrencode -t ansiutf8 < tunnel.conf`";
// Scanning QR code alerts
"alertScanQRCodeCameraUnsupportedTitle" = "Kameraa ei tuettu";
"alertScanQRCodeCameraUnsupportedMessage" = "Tämä laite ei pysty skannaamaan QR-koodeja";
"alertScanQRCodeInvalidQRCodeTitle" = "Virheellinen QR-koodi";
"alertScanQRCodeUnreadableQRCodeTitle" = "Virheellinen koodi";
// Settings UI
"settingsViewTitle" = "Asetukset";
"settingsSectionTitleAbout" = "Tietoa";
"settingsVersionKeyWireGuardForIOS" = "WireGuard iOS:lle";
"settingsVersionKeyWireGuardGoBackend" = "WireGuard Go -moottori";
"settingsSectionTitleTunnelLog" = "Loki";
"settingsViewLogButtonTitle" = "Näytä loki";
// Log view
"logViewTitle" = "Loki";
"alertBadArchiveMessage" = "Huono tai korruptoitunut zip arkisto.";
"alertNoTunnelsToExportTitle" = "Ei mitään vietävää";
"alertNoTunnelsToExportMessage" = "Vietäviä tunneleita ei ole";
"alertNoTunnelsInImportedZipArchiveTitle" = "Zip arkistossa ei ole tunneleita";
// Tunnel management error alerts
"alertTunnelActivationFailureTitle" = "Aktivointi epäonnistui";
"alertTunnelNameEmptyTitle" = "Nimeä ei annettu lainkaan";
"alertTunnelAlreadyExistsWithThatNameTitle" = "Nimi on jo käytössä";
"alertTunnelActivationErrorTunnelIsNotInactiveTitle" = "Aktivointi käynnissä";
// Tunnel management error alerts on system error
/* The alert message that goes with the following titles would be
one of the alertSystemErrorMessage* listed further down */
"alertSystemErrorOnListingTunnelsTitle" = "Tunneleita ei voitu listata";
"alertSystemErrorOnAddTunnelTitle" = "Tunnelia ei voitu luoda";
/* The alert message for this alert shall include
one of the alertSystemErrorMessage* listed further down */
"alertTunnelActivationSystemErrorTitle" = "Aktivointi epäonnistui";
/* alertSystemErrorMessage* messages */
"alertSystemErrorMessageTunnelConfigurationInvalid" = "Konfiguraatio ei kelpaa.";
"alertSystemErrorMessageTunnelConnectionFailed" = "Yhteys epäonnistui.";
"alertSystemErrorMessageTunnelConfigurationReadWriteFailed" = "Konfiguraation lukeminen tai kirjoittaminen epäonnistui.";
"alertSystemErrorMessageTunnelConfigurationUnknown" = "Tuntematon järjestelmävirhe.";
// Mac status bar menu / pulldown menu / main menu
"macMenuNetworks (%@)" = "Verkot: %@";
"macMenuNetworksNone" = "Verkot: Ei mitään";
"macMenuTitle" = "WireGuard";
"macMenuManageTunnels" = "Hallitse tunneleita";
"macMenuImportTunnels" = "Tuo tunneli(t) tiedostosta…";
"macMenuAddEmptyTunnel" = "Lisää tyhjä tunneli…";
"macMenuViewLog" = "Näytä loki";
"macMenuExportTunnels" = "Vie tunnelit Zippinä…";
"macMenuAbout" = "Tietoa WireGuardista";
"macMenuQuit" = "Sulje WireGuard";
"macMenuHideApp" = "Piilota WireGuard";
"macMenuHideOtherApps" = "Piilota muut";
"macMenuShowAllApps" = "Näytä kaikki";
"macMenuFile" = "Tiedosto";
"macMenuCloseWindow" = "Sulje ikkuna";
"macMenuEdit" = "Muokkaa";
"macMenuCut" = "Leikkaa";
"macMenuCopy" = "Kopioi";
"macMenuPaste" = "Liitä";
"macMenuSelectAll" = "Valitse kaikki";
"macMenuTunnel" = "Tunneli";
"macMenuToggleStatus" = "Vaihda tilaa";
"macMenuEditTunnel" = "Muokkaa…";
"macMenuDeleteSelected" = "Poista valitut";
"macMenuWindow" = "Ikkuna";
"macMenuMinimize" = "Pienennä";
"macMenuZoom" = "Lähennä/Loitonna";
// Mac manage tunnels window
"macWindowTitleManageTunnels" = "Hallitse WireGuard tunneleita";
"macDeleteTunnelConfirmationAlertMessage (%@)" = "Oletko varma, että haluat poistaa \"%@\"?";
"macDeleteMultipleTunnelsConfirmationAlertMessage (%d)" = "Haluatko varmasti poistaa %d kohdetta?";
"macDeleteTunnelConfirmationAlertInfo" = "Tätä toimintoa ei voi peruuttaa.";
"macDeleteTunnelConfirmationAlertButtonTitleDelete" = "Poista";
"macDeleteTunnelConfirmationAlertButtonTitleCancel" = "Peruuta";
"macDeleteTunnelConfirmationAlertButtonTitleDeleting" = "Poistetaan…";
"macButtonImportTunnels" = "Tuo tunneli(t) tiedostosta";
"macSheetButtonImport" = "Tuo";
"macNameFieldExportLog" = "Tallenna loki kohteeseen:";
"macSheetButtonExportLog" = "Tallenna";
"macNameFieldExportZip" = "Vie tunnelit kohteeseen:";
"macSheetButtonExportZip" = "Tallenna";
"macButtonDeleteTunnels (%d)" = "Poista %d tunnelia";
"macButtonEdit" = "Muokkaa";
"macFieldOnDemand" = "Tarvittaessa:";
"macFieldOnDemandSSIDs" = "SSIDt:";
// Mac status display
"macStatus (%@)" = "Tila: %@";
// Mac editing config
"macEditDiscard" = "Hylkää";
"macEditSave" = "Tallenna";
"macAlertNameIsEmpty" = "Nimi on pakollinen";
"macAlertPrivateKeyInvalid" = "Yksityinen avain ei kelpaa.";
"macAlertListenPortInvalid (%@)" = "Portti \"%@\" ei kelpaa.";
"macAlertAddressInvalid (%@)" = "Osoite \"%@\" ei kelpaa.";
"macAlertDNSInvalid (%@)" = "DNS %@ ei kelpaa.";
"macAlertMTUInvalid (%@)" = "MTU %@ ei kelpaa.";
"macAlertPublicKeyInvalid" = "Julkinen avain ei kelpaa";
"macAlertPreSharedKeyInvalid" = "Jaettu avain ei kelpaa";
"macAlertAllowedIPInvalid (%@)" = "Sallitut IP-osoitteet %@\" eivät kelpaa";
"macAlertEndpointInvalid (%@)" = "Päätepiste \"%@\" ei kelpaa";
"macAlertPersistentKeepliveInvalid (%@)" = "Pysyvä keepalive arvo %@ ei kelpaa";
"macAlertUnrecognizedPeerKey (%@)" = "Osapuoli sisältää tunnistamattoman avaimen ”%@”";
"macAlertInfoUnrecognizedPeerKey" = "Voimassa olevat avaimet ovat: ”PublicKey”, ”PresharedKey”, ”AllowedIPs”, ”Endpoint” ja ”PersistentKeepalive”";
// Mac about dialog
"macAppVersion (%@)" = "Sovelluksen versio: %@";
"macGoBackendVersion (%@)" = "Go -moottorin versio: %@";
"iosViewPrivateData" = "Todenna nähdäksesi tunnelin yksityiset avaimet.";
"macConfirmAndQuitAlertQuitWireGuard" = "Sulje WireGuard";
"macConfirmAndQuitAlertCloseWindow" = "Sulje tunneleiden hallinta";
// Mac tooltip
"macToolTipEditTunnel" = "Muokkaa tunnelia (⌘E)";
// Mac log view
"macLogColumnTitleTime" = "Aika";
"macLogColumnTitleLogMessage" = "Lokiviesti";
"macLogButtonTitleClose" = "Sulje";
"macLogButtonTitleSave" = "Tallenna…";
"macUnusableTunnelButtonTitleDeleteTunnel" = "Poista tunneli";
// Mac App Store updating alert
"macAppStoreUpdatingAlertMessage" = "App Store haluaa päivittää WireGuardin";
// Donation
"donateLink" = "♥ Lahjoita WireGuard projektille";
"macAlertNoInterface" = "Configuration must have an Interface section.";
"macNameFieldExportZip" = "Export tunnels to:";
"editTunnelViewTitle" = "Edit configuration";
"alertSystemErrorMessageTunnelConfigurationUnknown" = "Unknown system error.";
"macMenuCut" = "Cut";
"macEditDiscard" = "Discard";
"tunnelPeerPresharedKeyEnabled" = "enabled";
"alertScanQRCodeCameraUnsupportedMessage" = "This device is not able to scan QR codes";
"macSheetButtonExportZip" = "Save";
"macWindowTitleManageTunnels" = "Manage WireGuard Tunnels";
"macConfirmAndQuitAlertInfo" = "If you close the tunnels manager, WireGuard will continue to be available from the menu bar icon.";
"macUnusableTunnelInfo" = "In case this tunnel was created by another user, only that user can view, edit, or activate this tunnel.";
"alertTunnelActivationErrorTunnelIsNotInactiveMessage" = "The tunnel is already active or in the process of being activated";
"macToggleStatusButtonReasserting" = "Reactivating…";
"alertTunnelActivationSetNetworkSettingsMessage" = "Unable to apply network settings to tunnel object.";
"macMenuExportTunnels" = "Export Tunnels to Zip…";
"macMenuShowAllApps" = "Show All";
"alertCantOpenInputConfFileTitle" = "Unable to import from file";
"alertScanQRCodeInvalidQRCodeMessage" = "The scanned QR code is not a valid WireGuard configuration";
"macMenuHideApp" = "Hide WireGuard";
"settingsViewTitle" = "Settings";
"tunnelsListSelectAllButtonTitle" = "Select All";
"macDeleteTunnelConfirmationAlertInfo" = "You cannot undo this action.";
"macDeleteTunnelConfirmationAlertButtonTitleDeleting" = "Deleting…";
"tunnelPeerPersistentKeepalive" = "Persistent keepalive";
"settingsViewLogButtonTitle" = "View log";
"alertSystemErrorMessageTunnelConnectionFailed" = "The connection failed.";
"macButtonEdit" = "Edit";
"macAlertPublicKeyInvalid" = "Public key is invalid";
"macNameFieldExportLog" = "Save log to:";
"alertSystemErrorOnAddTunnelTitle" = "Unable to create tunnel";
"macConfirmAndQuitAlertMessage" = "Do you want to close the tunnels manager or quit WireGuard entirely?";
"alertTunnelActivationSavedConfigFailureMessage" = "Unable to retrieve tunnel information from the saved configuration.";
"tunnelOnDemandSectionTitleSelectedSSIDs" = "SSIDs";
"macAlertInfoUnrecognizedInterfaceKey" = "Valid keys are: PrivateKey, ListenPort, Address, DNS and MTU.";
"macLogColumnTitleTime" = "Time";
"alertTunnelNameEmptyMessage" = "Cannot create tunnel with an empty name";
"alertInvalidInterfaceMessageMTUInvalid" = "Interfaces MTU must be between 576 and 65535, or unspecified";
"alertTunnelNameEmptyTitle" = "No name provided";
"macToggleStatusButtonRestarting" = "Restarting…";
"alertUnableToWriteLogMessage" = "Unable to write logs to file";
"macToggleStatusButtonActivating" = "Activating…";
"macMenuQuit" = "Quit WireGuard";
"macMenuAddEmptyTunnel" = "Add Empty Tunnel…";
"tunnelStatusDeactivating" = "Deactivating";
"alertInvalidInterfaceTitle" = "Invalid interface";
"tunnelSectionTitleStatus" = "Status";
"macDeleteTunnelConfirmationAlertButtonTitleDelete" = "Delete";
"alertTunnelActivationFailureOnDemandAddendum" = " This tunnel has Activate On Demand enabled, so this tunnel might be re-activated automatically by the OS. You may turn off Activate On Demand in this app by editing the tunnel configuration.";
"alertTunnelActivationFailureTitle" = "Activation failure";
"tunnelPeerTxBytes" = "Data sent";
"macLogButtonTitleClose" = "Close";
"tunnelOnDemandSSIDViewTitle" = "SSIDs";
"settingsExportZipButtonTitle" = "Export zip archive";
"tunnelSectionTitleOnDemand" = "On-Demand Activation";
"deleteTunnelsConfirmationAlertButtonTitle" = "Delete";
"alertInvalidInterfaceMessageNameRequired" = "Interface name is required";
"macViewPrivateData" = "view tunnel private keys";
"alertInvalidPeerTitle" = "Invalid peer";
"alertInvalidPeerMessageEndpointInvalid" = "Peers endpoint must be of the form host:port or [host]:port";
"alertTunnelActivationErrorTunnelIsNotInactiveTitle" = "Activation in progress";
"tunnelPeerAllowedIPs" = "Allowed IPs";
"alertInvalidPeerMessagePublicKeyDuplicated" = "Two or more peers cannot have the same public key";
"macToggleStatusButtonDeactivate" = "Deactivate";
"addTunnelMenuImportFile" = "Create from file or archive";
"deletePeerConfirmationAlertButtonTitle" = "Delete";
"addTunnelMenuQRCode" = "Create from QR code";
"alertInvalidPeerMessagePreSharedKeyInvalid" = "Peers preshared key must be a 32-byte key in base64 encoding";
"macAppExitingWithActiveTunnelInfo" = "The tunnel will remain active after exiting. You may disable it by reopening this application or through the Network panel in System Preferences.";
"macMenuEdit" = "Edit";
"donateLink" = "♥ Donate to the WireGuard Project";
"alertScanQRCodeCameraUnsupportedTitle" = "Camera Unsupported";
"macMenuWindow" = "Window";
"tunnelStatusRestarting" = "Restarting";
"alertUnableToRemovePreviousLogTitle" = "Log export failed";
"alertTunnelActivationFailureMessage" = "The tunnel could not be activated. Please ensure that you are connected to the Internet.";
"tunnelInterfaceListenPort" = "Listen port";
"macToggleStatusButtonWaiting" = "Waiting…";
"tunnelInterfaceStatus" = "Status";
"macMenuHideOtherApps" = "Hide Others";
"alertCantOpenInputZipFileMessage" = "The zip archive could not be read.";
"alertInvalidInterfaceMessagePrivateKeyInvalid" = "Interfaces private key must be a 32-byte key in base64 encoding";
"tunnelSectionTitleInterface" = "Interface";
"alertInvalidInterfaceMessageDNSInvalid" = "Interfaces DNS servers must be a list of comma-separated IP addresses";
"tunnelStatusInactive" = "Inactive";
"macAlertPrivateKeyInvalid" = "Private key is invalid.";
"macDeleteTunnelConfirmationAlertButtonTitleCancel" = "Cancel";
"alertSystemErrorMessageTunnelConfigurationDisabled" = "The configuration is disabled.";
"alertInvalidPeerMessagePersistentKeepaliveInvalid" = "Peers persistent keepalive must be between 0 to 65535, or unspecified";
"alertUnableToWriteLogTitle" = "Log export failed";
"alertInvalidPeerMessagePublicKeyRequired" = "Peers public key is required";
"macMenuNetworksNone" = "Networks: None";
"alertCantOpenOutputZipFileForWritingMessage" = "Could not open zip file for writing.";
"macMenuSelectAll" = "Select All";
"logViewTitle" = "Log";
"alertInvalidPeerMessagePublicKeyInvalid" = "Peers public key must be a 32-byte key in base64 encoding";
"tunnelOnDemandCellular" = "Cellular";
"macConfirmAndQuitAlertQuitWireGuard" = "Quit WireGuard";
"alertSystemErrorOnRemoveTunnelTitle" = "Unable to remove tunnel";
"macFieldOnDemand" = "On-Demand:";
"macMenuCloseWindow" = "Close Window";
"macSheetButtonExportLog" = "Save";
"alertSystemErrorOnModifyTunnelTitle" = "Unable to modify tunnel";
"alertSystemErrorMessageTunnelConfigurationReadWriteFailed" = "Reading or writing the configuration failed.";
"macMenuEditTunnel" = "Edit…";
"settingsSectionTitleTunnelLog" = "Log";
"macMenuManageTunnels" = "Manage Tunnels";
"macButtonImportTunnels" = "Import tunnel(s) from file";
"macAppExitingWithActiveTunnelMessage" = "WireGuard is exiting with an active tunnel";
"tunnelSectionTitlePeer" = "Peer";
"tunnelsListSelectButtonTitle" = "Select";
"alertSystemErrorMessageTunnelConfigurationStale" = "The configuration is stale.";
"tunnelPeerPreSharedKey" = "Preshared key";
"alertTunnelDNSFailureMessage" = "One or more endpoint domains could not be resolved.";
"tunnelOnDemandAddMessageAddNewSSID" = "Add new";
"alertInvalidInterfaceMessageAddressInvalid" = "Interface addresses must be a list of comma-separated IP addresses, optionally in CIDR notation";
"tunnelOnDemandSectionTitleAddSSIDs" = "Add SSIDs";
"alertNoTunnelsInImportedZipArchiveTitle" = "No tunnels in zip archive";
"alertTunnelDNSFailureTitle" = "DNS resolution failure";
"tunnelOnDemandEthernet" = "Ethernet";
"macLogButtonTitleSave" = "Save…";
"macMenuToggleStatus" = "Toggle Status";
"macMenuMinimize" = "Minimize";
"deletePeerButtonTitle" = "Delete peer";
"tunnelPeerRxBytes" = "Data received";
"alertCantOpenInputZipFileTitle" = "Unable to read zip archive";
"alertScanQRCodeUnreadableQRCodeMessage" = "The scanned code could not be read";
"alertScanQRCodeUnreadableQRCodeTitle" = "Invalid Code";
"alertSystemErrorOnListingTunnelsTitle" = "Unable to list tunnels";
"tunnelPeerExcludePrivateIPs" = "Exclude private IPs";
"settingsVersionKeyWireGuardForIOS" = "WireGuard for iOS";
"macMenuPaste" = "Paste";
"macAlertMultipleInterfaces" = "Configuration must have only one Interface section.";
"scanQRCodeViewTitle" = "Scan QR code";
"macAppStoreUpdatingAlertMessage" = "App Store would like to update WireGuard";
"macUnusableTunnelMessage" = "The configuration for this tunnel cannot be found in the keychain.";
"macToolTipEditTunnel" = "Edit tunnel (⌘E)";
"tunnelEditPlaceholderTextStronglyRecommended" = "Strongly recommended";
"macMenuZoom" = "Zoom";
"alertBadArchiveTitle" = "Unable to read zip archive";
"macExportPrivateData" = "export tunnel private keys";
"alertTunnelAlreadyExistsWithThatNameTitle" = "Name already exists";
"macToggleStatusButtonDeactivating" = "Deactivating…";
"iosViewPrivateData" = "Authenticate to view tunnel private keys.";
"tunnelPeerLastHandshakeTime" = "Latest handshake";
"macAlertPreSharedKeyInvalid" = "Preshared key is invalid";
"alertBadConfigImportTitle" = "Unable to import tunnel";
"macEditSave" = "Save";
"macConfirmAndQuitAlertCloseWindow" = "Close Tunnels Manager";
"macMenuFile" = "File";
"tunnelStatusActivating" = "Activating";
"macToolTipToggleStatus" = "Toggle status (⌘T)";
"alertTunnelActivationSystemErrorTitle" = "Activation failure";
"alertInvalidInterfaceMessagePrivateKeyRequired" = "Interfaces private key is required";
"alertNoTunnelsToExportTitle" = "Nothing to export";
"scanQRCodeTipText" = "Tip: Generate with `qrencode -t ansiutf8 < tunnel.conf`";
"alertNoTunnelsToExportMessage" = "There are no tunnels to export";
"macMenuImportTunnels" = "Import Tunnel(s) from File…";
"alertScanQRCodeInvalidQRCodeTitle" = "Invalid QR Code";
"macMenuViewLog" = "View Log";
"macAlertInfoUnrecognizedPeerKey" = "Valid keys are: PublicKey, PresharedKey, AllowedIPs, Endpoint and PersistentKeepalive";
"tunnelOnDemandNoSSIDs" = "No SSIDs";
"addTunnelMenuHeader" = "Add a new WireGuard tunnel";
"macUnusableTunnelButtonTitleDeleteTunnel" = "Delete tunnel";
"tunnelStatusReasserting" = "Reactivating";
"alertInvalidPeerMessageAllowedIPsInvalid" = "Peers allowed IPs must be a list of comma-separated IP addresses, optionally in CIDR notation";
"macMenuTunnel" = "Tunnel";
"macMenuCopy" = "Copy";
"macTunnelsMenuTitle" = "Tunnels";
"alertTunnelAlreadyExistsWithThatNameMessage" = "A tunnel with that name already exists";
"macLogColumnTitleLogMessage" = "Log message";
"iosExportPrivateData" = "Authenticate to export tunnel private keys.";
"macMenuAbout" = "About WireGuard";
"macSheetButtonImport" = "Import";
"alertScanQRCodeNamePromptTitle" = "Please name the scanned tunnel";
"alertUnableToRemovePreviousLogMessage" = "The pre-existing log could not be cleared";
"alertTunnelActivationBackendFailureMessage" = "Unable to turn on Go backend library.";
"settingsSectionTitleExportConfigurations" = "Export configurations";
"alertBadArchiveMessage" = "Bad or corrupt zip archive.";
"settingsVersionKeyWireGuardGoBackend" = "WireGuard Go Backend";
"macFieldOnDemandSSIDs" = "SSIDs:";
"deletePeerConfirmationAlertMessage" = "Delete this peer?";
"alertCantOpenOutputZipFileForWritingTitle" = "Unable to create zip archive";
"tunnelStatusActive" = "Active";
"tunnelStatusWaiting" = "Waiting";
"alertNoTunnelsInImportedZipArchiveMessage" = "No .conf tunnel files were found inside the zip archive.";
"alertTunnelActivationFileDescriptorFailureMessage" = "Unable to determine TUN device file descriptor.";
"addTunnelMenuFromScratch" = "Create from scratch";
"macToggleStatusButtonActivate" = "Activate";
"macAlertNameIsEmpty" = "Name is required";
"tunnelsListDeleteButtonTitle" = "Delete";
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
// Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
// Generic alert action names
@@ -443,3 +443,4 @@
// Donation
"donateLink" = "♥ Faire un don au projet WireGuard";
"macTunnelsMenuTitle" = "Tunnels";
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
// Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
// Generic alert action names
@@ -233,6 +233,7 @@
"macConfirmAndQuitAlertCloseWindow" = "Close Tunnels Manager";
"macMenuFile" = "File";
"macToolTipToggleStatus" = "Toggle status (⌘T)";
"macTunnelsMenuTitle" = "Tunnels";
"alertTunnelActivationSystemErrorTitle" = "Activation failure";
"alertInvalidInterfaceMessagePrivateKeyRequired" = "Interfaces private key is required";
"tunnelOnDemandAnySSID" = "Any SSID";
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
// Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
// Generic alert action names
@@ -443,3 +443,4 @@
// Donation
"donateLink" = "♥ Fai una donazione al progetto WireGuard";
"macTunnelsMenuTitle" = "Tunnels";
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
// Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
// Generic alert action names
@@ -443,3 +443,4 @@
// Donation
"donateLink" = "♥ WireGuard プロジェクトに寄付する";
"macTunnelsMenuTitle" = "Tunnels";
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
// Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
// Generic alert action names
@@ -209,6 +209,7 @@
"macMenuFile" = "File";
"tunnelStatusActivating" = "Activating";
"macToolTipToggleStatus" = "Toggle status (⌘T)";
"macTunnelsMenuTitle" = "Tunnels";
"alertTunnelActivationSystemErrorTitle" = "Activation failure";
"alertInvalidInterfaceMessagePrivateKeyRequired" = "Interfaces private key is required";
"tunnelOnDemandAnySSID" = "Any SSID";
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
// Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
// Generic alert action names
@@ -443,3 +443,4 @@
// Donation
"donateLink" = "♥ ਵਾਇਰਗਾਰਡ ਪਰੋਜੈਕਟ ਨੂੰ ਦਾਨ ਦਿਓ";
"macTunnelsMenuTitle" = "Tunnels";
+257 -134
View File
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
// Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
// Generic alert action names
@@ -24,6 +24,19 @@
"addTunnelMenuImportFile" = "Utwórz z pliku lub archiwum";
"addTunnelMenuQRCode" = "Utwórz za pomocą kodu QR";
"addTunnelMenuFromScratch" = "Utwórz od podstaw";
// Tunnels list alerts
"alertImportedFromMultipleFilesTitle (%d)" = "Utworzono %d tuneli";
"alertImportedFromMultipleFilesMessage (%1$d of %2$d)" = "Utworzono %1$d z %2$d tuneli z zaimportowanych plików";
"alertImportedFromZipTitle (%d)" = "Utworzono %d tuneli";
"alertImportedFromZipMessage (%1$d of %2$d)" = "Utworzono %1$d z %2$d tuneli z archiwum zip";
"alertBadConfigImportTitle" = "Nie można zaimportować tunelu";
"alertBadConfigImportMessage (%@)" = "Plik „%@” nie zawiera prawidłowej konfiguracji WireGuard";
"deleteTunnelsConfirmationAlertButtonTitle" = "Usuń";
"deleteTunnelConfirmationAlertButtonMessage (%d)" = "Usunąć %d tunel?";
"deleteTunnelsConfirmationAlertButtonMessage (%d)" = "Usunąć %d tunele(i)?";
@@ -34,34 +47,96 @@
"tunnelSectionTitleStatus" = "Status";
"tunnelStatusInactive" = "Nieaktywny";
"tunnelStatusActivating" = "Aktywowanie";
"tunnelStatusActive" = "Aktywny";
"tunnelStatusDeactivating" = "Dezaktywowanie";
"tunnelStatusReasserting" = "Reaktywowanie";
"tunnelStatusRestarting" = "Restartowanie";
"tunnelStatusWaiting" = "Trwa oczekiwanie";
"macToggleStatusButtonActivate" = "Aktywuj";
"macToggleStatusButtonActivating" = "Aktywowanie…";
"macToggleStatusButtonDeactivate" = "Dezaktywuj";
"macToggleStatusButtonDeactivating" = "Dezaktywowanie…";
"macToggleStatusButtonReasserting" = "Reaktywowanie…";
"macToggleStatusButtonRestarting" = "Restartowanie…";
"macToggleStatusButtonWaiting" = "Oczekiwanie…";
"tunnelSectionTitleInterface" = "Interfejs";
"tunnelInterfaceName" = "Nazwa";
"tunnelInterfacePrivateKey" = "Klucz prywatny";
"tunnelInterfacePublicKey" = "Klucz publiczny";
"tunnelInterfaceGenerateKeypair" = "Generowanie pary kluczy";
"tunnelInterfaceAddresses" = "Adresy";
"tunnelInterfaceListenPort" = "Port nasłuchu";
"tunnelInterfaceMTU" = "MTU";
"tunnelInterfaceDNS" = "Serwery DNS";
"tunnelInterfaceStatus" = "Status";
"tunnelSectionTitlePeer" = "Peer";
"tunnelPeerPublicKey" = "Klucz publiczny";
"tunnelPeerPreSharedKey" = "PSK";
"tunnelPeerEndpoint" = "Adres";
"tunnelPeerPersistentKeepalive" = "Utrzymanie połączenia";
"tunnelPeerAllowedIPs" = "Dozwolone adresy IP";
"tunnelPeerRxBytes" = "Otrzymane dane";
"tunnelPeerTxBytes" = "Dane wysłane";
"tunnelPeerLastHandshakeTime" = "Ostatni uścisk dłoni (handshake)";
"tunnelPeerExcludePrivateIPs" = "Wyklucz prywatne adresy IP";
"tunnelSectionTitleOnDemand" = "Aktywacja na żądanie";
"tunnelOnDemandCellular" = "Dane komórkowe";
"tunnelOnDemandEthernet" = "Ethernet";
"tunnelOnDemandWiFi" = "Wi-Fi";
"tunnelOnDemandSSIDsKey" = "Identyfikatory SSID";
"tunnelOnDemandAnySSID" = "Dowolny SSID";
"tunnelOnDemandOnlyTheseSSIDs" = "Tylko te SSID";
"tunnelOnDemandExceptTheseSSIDs" = "Z wyjątkiem tych SSID";
"tunnelOnDemandOnlySSID (%d)" = "Tylko %d SSID";
"tunnelOnDemandOnlySSIDs (%d)" = "Tylko te %d SSID";
"tunnelOnDemandExceptSSID (%d)" = "Z wyjątkiem %d SSID";
"tunnelOnDemandExceptSSIDs (%d)" = "Z wyjątkiem tych %d SSID";
"tunnelOnDemandSSIDOptionDescriptionMac (%1$@: %2$@)" = "%1$@: %2$@";
"tunnelOnDemandSSIDViewTitle" = "Identyfikatory SSID";
"tunnelOnDemandSectionTitleSelectedSSIDs" = "Identyfikatory SSID";
"tunnelOnDemandNoSSIDs" = "Brak SSID";
"tunnelOnDemandSectionTitleAddSSIDs" = "Dodaj SSID";
"tunnelOnDemandAddMessageAddConnectedSSID (%@)" = "Dodaj połączony: %@";
"tunnelOnDemandAddMessageAddNewSSID" = "Dodaj nowy";
"tunnelOnDemandKey" = "Na żądanie";
"tunnelOnDemandOptionOff" = "Wył.";
"tunnelOnDemandOptionWiFiOnly" = "Tylko Wi-Fi";
"tunnelOnDemandOptionWiFiOrCellular" = "Wi-Fi i dane sieci komórkowej";
"tunnelOnDemandOptionCellularOnly" = "Tylko dane sieci komórkowej";
"tunnelOnDemandOptionWiFiOrEthernet" = "Wi-Fi lub sieć ethernet";
"tunnelOnDemandOptionEthernetOnly" = "Tylko sieć ethernet";
"addPeerButtonTitle" = "Dodaj Peer'a";
"deletePeerButtonTitle" = "Usuń peer'a";
"deletePeerConfirmationAlertButtonTitle" = "Usuń";
"deletePeerConfirmationAlertMessage" = "Usunąć tego peer'a?";
"deleteTunnelButtonTitle" = "Usuń tunel";
"deleteTunnelConfirmationAlertButtonTitle" = "Usuń";
"deleteTunnelConfirmationAlertMessage" = "Usunąć ten tunel?";
"tunnelEditPlaceholderTextRequired" = "Wymagane";
"tunnelEditPlaceholderTextOptional" = "Opcjonalne";
"tunnelEditPlaceholderTextAutomatic" = "Automatycznie wybrany";
"tunnelEditPlaceholderTextStronglyRecommended" = "Zalecane";
"tunnelEditPlaceholderTextOff" = "Wył.";
"tunnelPeerPersistentKeepaliveValue (%@)" = "co %@ sekund";
"tunnelHandshakeTimestampNow" = "Teraz";
"tunnelHandshakeTimestampSystemClockBackward" = "(Zegar systemowy został cofnięty)";
"tunnelHandshakeTimestampAgo (%@)" = "%@ temu";
"tunnelHandshakeTimestampYear (%d)" = "%d rok";
"tunnelHandshakeTimestampYears (%d)" = "%d lat/lata";
@@ -79,14 +154,49 @@
"tunnelPeerPresharedKeyEnabled" = "włączony";
// Error alerts while creating / editing a tunnel configuration
/* Alert title for error in the interface data */
"alertInvalidInterfaceTitle" = "Niewłaściwy interfejs";
/* Any one of the following alert messages can go with the above title */
"alertInvalidInterfaceMessageNameRequired" = "Nazwa interfejsu jest wymagana";
"alertInvalidInterfaceMessagePrivateKeyRequired" = "Klucz prywatny interfejsu jest wymagany";
"alertInvalidInterfaceMessagePrivateKeyInvalid" = "Klucz prywatny interfejsu musi być 32-bajtowym kluczem zakodowanym w base64";
"alertInvalidInterfaceMessageAddressInvalid" = "Adresy interfejsu muszą być listą adresów IP rozdzielone przecinkami, opcjonalnie w notacji CIDR";
"alertInvalidInterfaceMessageListenPortInvalid" = "Port nasłuchiwania interfejsu musi wynosić pomiędzy 0 a 65535 lub nieokreślony";
"alertInvalidInterfaceMessageMTUInvalid" = "Wartość MTU musi wynosić pomiędzy 576 a 65535 lub nieokreślona";
"alertInvalidInterfaceMessageDNSInvalid" = "Serwery DNS interfejsu muszą być listą adresów IP rozdzielonych przecinkami";
/* Alert title for error in the peer data */
"alertInvalidPeerTitle" = "Nieprawidłowy peer";
/* Any one of the following alert messages can go with the above title */
"alertInvalidPeerMessagePublicKeyRequired" = "Klucz publiczny peer'a jest wymagany";
"alertInvalidPeerMessagePublicKeyInvalid" = "Klucz prywatny peer'a musi być 32-bajtowym kluczem zakodowanym w base64";
"alertInvalidPeerMessagePreSharedKeyInvalid" = "Klucz publiczny peer'a musi być 32-bajtowym kluczem zakodowanym w base64";
"alertInvalidPeerMessageAllowedIPsInvalid" = "Dozwolone adresy peer'a muszą być listą adresów IP rozdzielone przecinkami, opcjonalnie w notacji CIDR";
"alertInvalidPeerMessageEndpointInvalid" = "Adres peer'a musi być w postaci „adres:port” or „[host]:port”";
"alertInvalidPeerMessagePersistentKeepaliveInvalid" = "Interwał podtrzymywania połączenia musi wynosić pomiędzy 0 a 65535 lub nieokreślony";
"alertInvalidPeerMessagePublicKeyDuplicated" = "Dwa lub więcej peer'ów nie może współdzielić tego samego klucza publicznego";
// Scanning QR code UI
"scanQRCodeViewTitle" = "Skanuj kod QR";
"scanQRCodeTipText" = "Wskazówka: wygeneruj za pomocą `qrencode -t ansiutf8 < tunnel.conf`";
// Scanning QR code alerts
"alertScanQRCodeCameraUnsupportedTitle" = "Kamera nie jest obsługiwana";
"alertScanQRCodeCameraUnsupportedMessage" = "To urządzenie nie jest w stanie zeskanować kodów QR";
"alertScanQRCodeInvalidQRCodeTitle" = "Nieprawidłowy kod QR";
"alertScanQRCodeInvalidQRCodeMessage" = "Zeskanowany kod QR nie jest poprawną konfiguracją WireGuard";
"alertScanQRCodeUnreadableQRCodeTitle" = "Nieprawidłowy kod";
"alertScanQRCodeUnreadableQRCodeMessage" = "Zeskanowany kod nie mógł zostać odczytany";
"alertScanQRCodeNamePromptTitle" = "Nazwij zeskanowany tunel";
// Settings UI
@@ -94,6 +204,10 @@
"settingsSectionTitleAbout" = "O programie";
"settingsVersionKeyWireGuardForIOS" = "WireGuard dla iOS";
"settingsVersionKeyWireGuardGoBackend" = "WireGuard Go Backend";
"settingsSectionTitleExportConfigurations" = "Eksportuj konfiguracje";
"settingsExportZipButtonTitle" = "Eksportuj do archiwum zip";
"settingsSectionTitleTunnelLog" = "Log";
"settingsViewLogButtonTitle" = "Wyświetl log";
@@ -102,6 +216,19 @@
"logViewTitle" = "Log";
// Log alerts
"alertUnableToRemovePreviousLogTitle" = "Export logów nie powiódł się";
"alertUnableToRemovePreviousLogMessage" = "Nie można usunąć już istniejących logów";
"alertUnableToWriteLogTitle" = "Eksport logów nie powiódł się";
"alertUnableToWriteLogMessage" = "Nie można zapisać logów do pliku";
// Zip import / export error alerts
"alertCantOpenInputZipFileTitle" = "Nie można odczytać archiwum zip";
"alertCantOpenInputZipFileMessage" = "Nie można odczytać archiwum zip.";
"alertCantOpenOutputZipFileForWritingTitle" = "Nie można utworzyć archiwum ZIP";
"alertCantOpenOutputZipFileForWritingMessage" = "Nie udało się otworzyć pliku ZIP do zapisu.";
@@ -112,14 +239,65 @@
"alertNoTunnelsToExportMessage" = "Nie ma żadnych tuneli do wyeksportowania";
"alertNoTunnelsInImportedZipArchiveTitle" = "Brak tuneli w archiwum ZIP";
"alertNoTunnelsInImportedZipArchiveMessage" = "Nie znaleziono plików konfiguracyjnych tunelu .conf w archiwum zip.";
// Conf import error alerts
"alertCantOpenInputConfFileTitle" = "Nie można zaimportować z pliku";
"alertCantOpenInputConfFileMessage (%@)" = "Nie można odczytać pliku „%@”.";
// Tunnel management error alerts
"alertTunnelActivationFailureTitle" = "Błąd aktywacji tunelu";
"alertTunnelActivationFailureMessage" = "Tunel nie mógł zostać aktywowany. Upewnij się, że jesteś podłączony do Internetu.";
"alertTunnelActivationSavedConfigFailureMessage" = "Nie można odczytać informacji o tunelu z zapisanej konfiguracji.";
"alertTunnelActivationBackendFailureMessage" = "Nie udało się włącz tunelu bazując na bibliotece Go.";
"alertTunnelActivationFileDescriptorFailureMessage" = "Nie można określić opisu urządzenia TUN.";
"alertTunnelActivationSetNetworkSettingsMessage" = "Nie można zastosować ustawień sieci do tunelu.";
"alertTunnelActivationFailureOnDemandAddendum" = "Ten tunel ma włączoną aktywację na żądanie, więc ten tunel może być ponownie aktywowany automatycznie przez system operacyjny. Możesz wyłączyć aktywację na żądanie poprzez edycję konfiguracji tunelu.";
"alertTunnelDNSFailureTitle" = "Nieudane rozpoznanie DNS";
"alertTunnelDNSFailureMessage" = "Jedna lub więcej domen nie może zostać odnalezionych.";
"alertTunnelNameEmptyTitle" = "Nie podano nazwy";
"alertTunnelNameEmptyMessage" = "Nie można utworzyć tunelu z pustą nazwą";
"alertTunnelAlreadyExistsWithThatNameTitle" = "Nazwa już istnieje";
"alertTunnelAlreadyExistsWithThatNameMessage" = "Tunel o tej nazwie już istnieje";
"alertTunnelActivationErrorTunnelIsNotInactiveTitle" = "Aktywacja w toku";
"alertTunnelActivationErrorTunnelIsNotInactiveMessage" = "Tunel jest już aktywny lub jest już w trakcie aktywowania";
// Tunnel management error alerts on system error
/* The alert message that goes with the following titles would be
one of the alertSystemErrorMessage* listed further down */
"alertSystemErrorOnListingTunnelsTitle" = "Nie można wyświetlić tuneli";
"alertSystemErrorOnAddTunnelTitle" = "Nie można utworzyć tunelu";
"alertSystemErrorOnModifyTunnelTitle" = "Nie można zmodyfikować tunelu";
"alertSystemErrorOnRemoveTunnelTitle" = "Nie można usunąć tunelu";
/* The alert message for this alert shall include
one of the alertSystemErrorMessage* listed further down */
"alertTunnelActivationSystemErrorTitle" = "Błąd aktywacji tunelu";
"alertTunnelActivationSystemErrorMessage (%@)" = "Błąd aktywacji tunelu. %@";
/* alertSystemErrorMessage* messages */
"alertSystemErrorMessageTunnelConfigurationInvalid" = "Ta konfiguracja jest nieprawidłowa.";
"alertSystemErrorMessageTunnelConfigurationDisabled" = "Konfiguracja jest wyłączona.";
"alertSystemErrorMessageTunnelConnectionFailed" = "Połączenie nie powiodło się.";
"alertSystemErrorMessageTunnelConfigurationStale" = "Konfiguracja jest przestarzała.";
"alertSystemErrorMessageTunnelConfigurationReadWriteFailed" = "Czytanie lub zapisywanie konfiguracji nie powiodło się.";
"alertSystemErrorMessageTunnelConfigurationUnknown" = "Nieznany błąd systemowy.";
// Mac status bar menu / pulldown menu / main menu
"macMenuNetworks (%@)" = "Sieci: %@";
"macMenuNetworksNone" = "Sieci: brak";
"macMenuTitle" = "WireGuard";
"macMenuManageTunnels" = "Zarządzaj tunelami";
"macMenuImportTunnels" = "Importuj tunel(e) z pliku…";
"macMenuAddEmptyTunnel" = "Dodaj pusty tunel…";
"macMenuViewLog" = "Wyświetl log";
@@ -128,6 +306,8 @@
"macMenuQuit" = "Wyjdź z programu WireGuard";
"macMenuHideApp" = "Ukryj program WireGuard";
"macMenuHideOtherApps" = "Ukryj pozostałe";
"macMenuShowAllApps" = "Pokaż wszystkie";
"macMenuFile" = "Plik";
"macMenuCloseWindow" = "Zamknij okno";
@@ -139,9 +319,14 @@
"macMenuSelectAll" = "Wybierz wszystko";
"macMenuTunnel" = "Tunel";
"macMenuToggleStatus" = "Przełącz status";
"macMenuEditTunnel" = "Edytuj…";
"macMenuDeleteSelected" = "Usuń wybrane";
"macMenuWindow" = "Okno";
"macMenuMinimize" = "Minimalizuj";
"macMenuZoom" = "Powiększenie";
// Mac manage tunnels window
"macWindowTitleManageTunnels" = "Zarządzaj tunelami WireGuard";
@@ -154,6 +339,7 @@
"macDeleteTunnelConfirmationAlertButtonTitleDeleting" = "Usuwanie…";
"macButtonImportTunnels" = "Importuj tunel(e) z pliku";
"macSheetButtonImport" = "Importuj";
"macNameFieldExportLog" = "Zapisz log do:";
"macSheetButtonExportLog" = "Zapisz";
@@ -161,163 +347,100 @@
"macNameFieldExportZip" = "Wyeksportuj tunele do:";
"macSheetButtonExportZip" = "Zapisz";
"macButtonDeleteTunnels (%d)" = "Usuń %d tunele(i)";
"macButtonEdit" = "Edytuj";
// Mac detail/edit view fields
"macFieldKey (%@)" = "%@:";
"macFieldOnDemand" = "Na żądanie:";
"macFieldOnDemandSSIDs" = "Identyfikatory SSID:";
// Mac status display
"macStatus (%@)" = "Status: %@";
// Mac editing config
"macEditDiscard" = "Odrzuć";
"macEditSave" = "Zapisz";
"macAlertNameIsEmpty" = "Nazwa jest wymagana";
"macAlertDuplicateName (%@)" = "Inny tunel o nazwie „%@” już istnieje.";
"macAlertInvalidLine (%@)" = "Nieprawidłowy wiersz: „%@”.";
"macAlertNoInterface" = "Konfiguracja musi mieć sekcję „Interface”.";
"macAlertMultipleInterfaces" = "Konfiguracja musi posiadać tylko jedną sekcję „Interface”.";
"macAlertPrivateKeyInvalid" = "Klucz prywatny jest nieprawidłowy.";
"macAlertListenPortInvalid (%@)" = "Port nasłuchu „%@” jest nieprawidłowy.";
"macAlertAddressInvalid (%@)" = "Adres \"%@\" jest nieprawidłowy.";
"macAlertDNSInvalid (%@)" = "DNS „%@” jest nieprawidłowy.";
"macAlertMTUInvalid (%@)" = "Wartość MTU %@ jest nieprawidłowa.";
"macAlertUnrecognizedInterfaceKey (%@)" = "Interfejs zawiera nierozpoznawalny klucz „%@”";
"macAlertInfoUnrecognizedInterfaceKey" = "Prawidłowe klucze to: „PrivateKey”, „ListenPort”, „Adres”, „DNS” i „MTU”.";
"macAlertPublicKeyInvalid" = "Klucz publiczny jest nieprawidłowy";
"macAlertPreSharedKeyInvalid" = "Klucz wstępnie współdzielony jest niepoprawny";
"macAlertAllowedIPInvalid (%@)" = "Dozwolony adres IP „%@” jest nieprawidłowy";
"macAlertEndpointInvalid (%@)" = "Adres końcowy „%@” jest nieprawidłowy";
"macAlertPersistentKeepliveInvalid (%@)" = "Obecna wartość keepalive „%@” jest nieprawidłowa";
"macAlertUnrecognizedPeerKey (%@)" = "Peer zawiera nierozpoznawalny klucz „%@”";
"macAlertInfoUnrecognizedPeerKey" = "Prawidłowe klucze to: „PublicKey”, „PresharedKey”, „AllowedIPs”, „Endpoint” i „PersistentKeepalive”";
"macAlertMultipleEntriesForKey (%@)" = "Dla klucza „%@” powinien być tylko jeden wpis w sekcji";
// Mac about dialog
"macAppVersion (%@)" = "Wersja aplikacji: %@";
"macGoBackendVersion (%@)" = "Wersja backend'u Go: %@";
// Privacy
"macExportPrivateData" = "eksportuj klucze prywatne tunelu";
"macViewPrivateData" = "wyświetl klucze prywatne tunelu";
"iosExportPrivateData" = "Uwierzytelnij, aby wyeksportować klucze prywatne tuneli.";
"iosViewPrivateData" = "Uwierzytelnij, aby zobaczyć klucze prywatne.";
// Mac alert
"macConfirmAndQuitAlertMessage" = "Czy chcesz zamknąć menedżera tuneli czy wyłączyć całkowicie WireGuard?";
"macConfirmAndQuitAlertInfo" = "Jeśli zamkniesz menedżera tuneli, WireGuard będzie nadal dostępny z ikony w pasku menu.";
"macConfirmAndQuitInfoWithActiveTunnel (%@)" = "Jeśli zamkniesz menedżera tuneli, WireGuard będzie nadal dostępny z ikony w pasku menu.\n\nZauważ, że jeśli opuścisz WireGuard całkowicie aktywny tunel („%@”) pozostanie aktywny, dopóki nie wyłączysz go z tej aplikacji lub przez panel sieci w ustawieniach systemowych.";
"macConfirmAndQuitAlertQuitWireGuard" = "Wyjdź z programu WireGuard";
"macConfirmAndQuitAlertCloseWindow" = "Zamknij menedżera tuneli";
"macAppExitingWithActiveTunnelMessage" = "WireGuard jest wyłączany wraz z aktywnym tunelem";
"macAppExitingWithActiveTunnelInfo" = "Tunel pozostanie aktywny po wyjściu. Możesz go wyłączyć, ponownie otwierając tę aplikację lub przez panel sieci w ustawieniach systemowych.";
// Mac tooltip
"macToolTipEditTunnel" = "Edytuj tunel (⌘E)";
"macToolTipToggleStatus" = "Przełącz stan (⌘T)";
// Mac log view
"macLogColumnTitleTime" = "Czas";
"macLogColumnTitleLogMessage" = "Dziennik wiadomości";
"macLogButtonTitleClose" = "Zamknij";
"macLogButtonTitleSave" = "Zapisz…";
// Mac unusable tunnel view
"macUnusableTunnelMessage" = "Konfiguracja dla tego tunelu nie może zostać znaleziona w pęku kluczy.";
"macUnusableTunnelInfo" = "W przypadku, gdy ten tunel został utworzony przez innego użytkownika, tylko ten użytkownik może przeglądać, edytować lub aktywować ten tunel.";
"macUnusableTunnelButtonTitleDeleteTunnel" = "Usuń tunel";
"alertSystemErrorMessageTunnelConfigurationInvalid" = "The configuration is invalid.";
"tunnelPeerEndpoint" = "Endpoint";
"alertInvalidInterfaceMessageListenPortInvalid" = "Interfaces listen port must be between 0 and 65535, or unspecified";
"addPeerButtonTitle" = "Add peer";
"tunnelHandshakeTimestampSystemClockBackward" = "(System clock wound backwards)";
"macAlertNoInterface" = "Configuration must have an Interface section.";
"alertSystemErrorMessageTunnelConfigurationUnknown" = "Unknown system error.";
"macEditDiscard" = "Discard";
"alertScanQRCodeCameraUnsupportedMessage" = "This device is not able to scan QR codes";
"macConfirmAndQuitAlertInfo" = "If you close the tunnels manager, WireGuard will continue to be available from the menu bar icon.";
"macUnusableTunnelInfo" = "In case this tunnel was created by another user, only that user can view, edit, or activate this tunnel.";
"alertTunnelActivationErrorTunnelIsNotInactiveMessage" = "The tunnel is already active or in the process of being activated";
"macToggleStatusButtonReasserting" = "Reactivating…";
"alertTunnelActivationSetNetworkSettingsMessage" = "Unable to apply network settings to tunnel object.";
"macMenuShowAllApps" = "Show All";
"alertCantOpenInputConfFileTitle" = "Unable to import from file";
"alertScanQRCodeInvalidQRCodeMessage" = "The scanned QR code is not a valid WireGuard configuration";
"tunnelPeerPersistentKeepalive" = "Persistent keepalive";
"alertSystemErrorMessageTunnelConnectionFailed" = "The connection failed.";
"macConfirmAndQuitAlertMessage" = "Do you want to close the tunnels manager or quit WireGuard entirely?";
"alertTunnelActivationSavedConfigFailureMessage" = "Unable to retrieve tunnel information from the saved configuration.";
"tunnelOnDemandOptionOff" = "Off";
"tunnelOnDemandSectionTitleSelectedSSIDs" = "SSIDs";
"macAlertInfoUnrecognizedInterfaceKey" = "Valid keys are: PrivateKey, ListenPort, Address, DNS and MTU.";
"macLogColumnTitleTime" = "Time";
"alertTunnelNameEmptyMessage" = "Cannot create tunnel with an empty name";
"alertInvalidInterfaceMessageMTUInvalid" = "Interfaces MTU must be between 576 and 65535, or unspecified";
"alertTunnelNameEmptyTitle" = "No name provided";
"tunnelOnDemandOnlyTheseSSIDs" = "Only these SSIDs";
"macToggleStatusButtonRestarting" = "Restarting…";
"tunnelOnDemandExceptTheseSSIDs" = "Except these SSIDs";
"alertUnableToWriteLogMessage" = "Unable to write logs to file";
"macToggleStatusButtonActivating" = "Activating…";
"tunnelStatusDeactivating" = "Deactivating";
"alertInvalidInterfaceTitle" = "Invalid interface";
"alertTunnelActivationFailureOnDemandAddendum" = " This tunnel has Activate On Demand enabled, so this tunnel might be re-activated automatically by the OS. You may turn off Activate On Demand in this app by editing the tunnel configuration.";
"alertTunnelActivationFailureTitle" = "Activation failure";
"tunnelPeerTxBytes" = "Data sent";
"tunnelOnDemandSSIDViewTitle" = "SSIDs";
"tunnelEditPlaceholderTextOptional" = "Optional";
"settingsExportZipButtonTitle" = "Export zip archive";
"tunnelSectionTitleOnDemand" = "On-Demand Activation";
"tunnelInterfaceGenerateKeypair" = "Generate keypair";
"deleteTunnelsConfirmationAlertButtonTitle" = "Delete";
"alertInvalidInterfaceMessageNameRequired" = "Interface name is required";
"tunnelEditPlaceholderTextAutomatic" = "Automatic";
"macViewPrivateData" = "view tunnel private keys";
"alertInvalidPeerTitle" = "Invalid peer";
"alertInvalidPeerMessageEndpointInvalid" = "Peers endpoint must be of the form host:port or [host]:port";
"alertTunnelActivationErrorTunnelIsNotInactiveTitle" = "Activation in progress";
"alertInvalidPeerMessagePublicKeyDuplicated" = "Two or more peers cannot have the same public key";
"macToggleStatusButtonDeactivate" = "Deactivate";
"alertInvalidPeerMessagePreSharedKeyInvalid" = "Peers preshared key must be a 32-byte key in base64 encoding";
"macAppExitingWithActiveTunnelInfo" = "The tunnel will remain active after exiting. You may disable it by reopening this application or through the Network panel in System Preferences.";
"donateLink" = "♥ Donate to the WireGuard Project";
"alertScanQRCodeCameraUnsupportedTitle" = "Camera Unsupported";
"macMenuWindow" = "Window";
"tunnelStatusRestarting" = "Restarting";
"alertUnableToRemovePreviousLogTitle" = "Log export failed";
"tunnelHandshakeTimestampNow" = "Now";
"alertTunnelActivationFailureMessage" = "The tunnel could not be activated. Please ensure that you are connected to the Internet.";
"macToggleStatusButtonWaiting" = "Waiting…";
"macMenuHideOtherApps" = "Hide Others";
"alertCantOpenInputZipFileMessage" = "The zip archive could not be read.";
"alertInvalidInterfaceMessagePrivateKeyInvalid" = "Interfaces private key must be a 32-byte key in base64 encoding";
"tunnelSectionTitleInterface" = "Interface";
"alertInvalidInterfaceMessageDNSInvalid" = "Interfaces DNS servers must be a list of comma-separated IP addresses";
"tunnelStatusInactive" = "Inactive";
"alertSystemErrorMessageTunnelConfigurationDisabled" = "The configuration is disabled.";
"alertInvalidPeerMessagePersistentKeepaliveInvalid" = "Peers persistent keepalive must be between 0 to 65535, or unspecified";
"alertUnableToWriteLogTitle" = "Log export failed";
"alertInvalidPeerMessagePublicKeyRequired" = "Peers public key is required";
"macMenuNetworksNone" = "Networks: None";
"tunnelOnDemandSSIDsKey" = "SSIDs";
"alertInvalidPeerMessagePublicKeyInvalid" = "Peers public key must be a 32-byte key in base64 encoding";
"tunnelOnDemandCellular" = "Cellular";
"macFieldOnDemand" = "On-Demand:";
"alertSystemErrorMessageTunnelConfigurationReadWriteFailed" = "Reading or writing the configuration failed.";
"macMenuManageTunnels" = "Manage Tunnels";
"macAppExitingWithActiveTunnelMessage" = "WireGuard is exiting with an active tunnel";
"tunnelSectionTitlePeer" = "Peer";
"alertSystemErrorMessageTunnelConfigurationStale" = "The configuration is stale.";
"tunnelPeerPreSharedKey" = "Preshared key";
"alertTunnelDNSFailureMessage" = "One or more endpoint domains could not be resolved.";
"tunnelOnDemandAddMessageAddNewSSID" = "Add new";
"alertInvalidInterfaceMessageAddressInvalid" = "Interface addresses must be a list of comma-separated IP addresses, optionally in CIDR notation";
"tunnelOnDemandSectionTitleAddSSIDs" = "Add SSIDs";
"alertTunnelDNSFailureTitle" = "DNS resolution failure";
"macMenuToggleStatus" = "Toggle Status";
"macMenuMinimize" = "Minimize";
"deletePeerButtonTitle" = "Delete peer";
"tunnelPeerRxBytes" = "Data received";
"alertCantOpenInputZipFileTitle" = "Unable to read zip archive";
"alertScanQRCodeUnreadableQRCodeMessage" = "The scanned code could not be read";
"alertSystemErrorOnListingTunnelsTitle" = "Unable to list tunnels";
"tunnelPeerExcludePrivateIPs" = "Exclude private IPs";
"macAlertMultipleInterfaces" = "Configuration must have only one Interface section.";
"macAppStoreUpdatingAlertMessage" = "App Store would like to update WireGuard";
"macUnusableTunnelMessage" = "The configuration for this tunnel cannot be found in the keychain.";
"tunnelEditPlaceholderTextStronglyRecommended" = "Strongly recommended";
"macMenuZoom" = "Zoom";
"macExportPrivateData" = "export tunnel private keys";
"macToggleStatusButtonDeactivating" = "Deactivating…";
"iosViewPrivateData" = "Authenticate to view tunnel private keys.";
"tunnelPeerLastHandshakeTime" = "Latest handshake";
"macAlertPreSharedKeyInvalid" = "Preshared key is invalid";
"alertBadConfigImportTitle" = "Unable to import tunnel";
"macConfirmAndQuitAlertCloseWindow" = "Close Tunnels Manager";
"tunnelStatusActivating" = "Activating";
"alertTunnelActivationSystemErrorTitle" = "Activation failure";
"alertInvalidInterfaceMessagePrivateKeyRequired" = "Interfaces private key is required";
"tunnelOnDemandAnySSID" = "Any SSID";
"macAlertInfoUnrecognizedPeerKey" = "Valid keys are: PublicKey, PresharedKey, AllowedIPs, Endpoint and PersistentKeepalive";
"tunnelOnDemandNoSSIDs" = "No SSIDs";
"tunnelEditPlaceholderTextOff" = "Off";
"tunnelEditPlaceholderTextRequired" = "Required";
"tunnelStatusReasserting" = "Reactivating";
"alertInvalidPeerMessageAllowedIPsInvalid" = "Peers allowed IPs must be a list of comma-separated IP addresses, optionally in CIDR notation";
"macLogColumnTitleLogMessage" = "Log message";
"iosExportPrivateData" = "Authenticate to export tunnel private keys.";
"macSheetButtonImport" = "Import";
"alertScanQRCodeNamePromptTitle" = "Please name the scanned tunnel";
"alertUnableToRemovePreviousLogMessage" = "The pre-existing log could not be cleared";
"alertTunnelActivationBackendFailureMessage" = "Unable to turn on Go backend library.";
"settingsSectionTitleExportConfigurations" = "Export configurations";
"settingsVersionKeyWireGuardGoBackend" = "WireGuard Go Backend";
"macFieldOnDemandSSIDs" = "SSIDs:";
"deletePeerConfirmationAlertMessage" = "Delete this peer?";
"tunnelStatusActive" = "Active";
"tunnelStatusWaiting" = "Waiting";
"alertNoTunnelsInImportedZipArchiveMessage" = "No .conf tunnel files were found inside the zip archive.";
"alertTunnelActivationFileDescriptorFailureMessage" = "Unable to determine TUN device file descriptor.";
"macToggleStatusButtonActivate" = "Activate";
// Mac App Store updating alert
"macAppStoreUpdatingAlertMessage" = "App Store chce zaktualizować WireGuard";
"macAppStoreUpdatingAlertInfoWithOnDemand (%@)" = "Proszę najpierw wyłączyć aktywację na żądanie tunelu „%@”, dezaktywować go, a dopiero następnie kontynuować aktualizację w App Store.";
"macAppStoreUpdatingAlertInfoWithoutOnDemand (%@)" = "Proszę dezaktywować tunel „%@”, a następnie kontynuować aktualizację w App Store.";
// Donation
"donateLink" = "♥ Dotacja dla projektu WireGuard";
"macTunnelsMenuTitle" = "Tunnels";
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
// Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
// Generic alert action names
@@ -443,3 +443,4 @@
// Donation
"donateLink" = "♥ Donează pentru proiectul WireGuard";
"macTunnelsMenuTitle" = "Tunnels";
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
// Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
// Generic alert action names
@@ -443,3 +443,4 @@
// Donation
"donateLink" = "♥ Пожертвовать проекту WireGuard";
"macTunnelsMenuTitle" = "Tunnels";
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
// Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
// Generic alert action names
@@ -443,3 +443,4 @@
// Donation
"donateLink" = "♥ Donirajte projektu WireGuard";
"macTunnelsMenuTitle" = "Tunnels";
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
// Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
// Generic alert action names
@@ -443,3 +443,4 @@
// Donation
"donateLink" = "♥ WireGuard Projesine Bağış Yapın";
"macTunnelsMenuTitle" = "Tunnels";
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
// Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
// Generic alert action names
@@ -443,3 +443,4 @@
// Donation
"donateLink" = "♥ 为 WireGuard 捐赠";
"macTunnelsMenuTitle" = "Tunnels";
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
// Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
// Generic alert action names
@@ -42,7 +42,7 @@
"newTunnelViewTitle" = "新增設定";
"editTunnelViewTitle" = "修改設定";
"tunnelSectionTitleStatus" = "ㄓ望太";
"tunnelSectionTitleStatus" = "狀態";
"tunnelStatusInactive" = "未啟用";
"tunnelStatusActivating" = "啟用中";
@@ -69,6 +69,7 @@
"tunnelInterfaceListenPort" = "監聽埠";
"tunnelInterfaceMTU" = "MTU";
"tunnelInterfaceDNS" = "DNS 伺服器";
"tunnelInterfaceStatus" = "狀態";
"tunnelEditPlaceholderTextAutomatic" = "自動";
"tunnelHandshakeTimestampNow" = "現在";
@@ -85,6 +86,7 @@
"macMenuCopy" = "複製";
"macMenuPaste" = "貼上";
"macMenuSelectAll" = "全選";
"macMenuToggleStatus" = "切換狀態";
"macMenuMinimize" = "最小化";
"macMenuDeleteSelected" = "Delete Selected";
"alertSystemErrorMessageTunnelConfigurationInvalid" = "The configuration is invalid.";
@@ -162,7 +164,6 @@
"alertUnableToRemovePreviousLogTitle" = "Log export failed";
"alertTunnelActivationFailureMessage" = "The tunnel could not be activated. Please ensure that you are connected to the Internet.";
"tunnelOnDemandOptionEthernetOnly" = "Ethernet only";
"tunnelInterfaceStatus" = "Status";
"macMenuHideOtherApps" = "Hide Others";
"alertCantOpenInputZipFileMessage" = "The zip archive could not be read.";
"alertInvalidInterfaceMessagePrivateKeyInvalid" = "Interfaces private key must be a 32-byte key in base64 encoding";
@@ -206,7 +207,6 @@
"alertTunnelDNSFailureTitle" = "DNS resolution failure";
"tunnelOnDemandEthernet" = "Ethernet";
"macLogButtonTitleSave" = "Save…";
"macMenuToggleStatus" = "Toggle Status";
"deletePeerButtonTitle" = "Delete peer";
"tunnelPeerRxBytes" = "Data received";
"alertCantOpenInputZipFileTitle" = "Unable to read zip archive";
@@ -233,6 +233,7 @@
"macConfirmAndQuitAlertCloseWindow" = "Close Tunnels Manager";
"macMenuFile" = "File";
"macToolTipToggleStatus" = "Toggle status (⌘T)";
"macTunnelsMenuTitle" = "Tunnels";
"alertTunnelActivationSystemErrorTitle" = "Activation failure";
"alertInvalidInterfaceMessagePrivateKeyRequired" = "Interfaces private key is required";
"tunnelOnDemandAnySSID" = "Any SSID";
+1
View File
@@ -52,6 +52,7 @@ extension Endpoint {
let startOfHost = string.index(after: string.startIndex)
guard let endOfHost = string.dropFirst().firstIndex(of: "]") else { return nil }
let afterEndOfHost = string.index(after: endOfHost)
if afterEndOfHost == string.endIndex { return nil }
guard string[afterEndOfHost] == ":" else { return nil }
startOfPort = string.index(after: afterEndOfHost)
hostString = String(string[startOfHost ..< endOfHost])
+48
View File
@@ -64,4 +64,52 @@ extension IPAddressRange {
return (address, networkPrefixLength)
}
public func subnetMask() -> IPAddress {
if address is IPv4Address {
let mask = networkPrefixLength > 0 ? ~UInt32(0) << (32 - networkPrefixLength) : UInt32(0)
let bytes = Data([
UInt8(truncatingIfNeeded: mask >> 24),
UInt8(truncatingIfNeeded: mask >> 16),
UInt8(truncatingIfNeeded: mask >> 8),
UInt8(truncatingIfNeeded: mask >> 0)
])
return IPv4Address(bytes)!
}
if address is IPv6Address {
var bytes = Data(repeating: 0, count: 16)
for i in 0..<Int(networkPrefixLength/8) {
bytes[i] = 0xff
}
let nibble = networkPrefixLength % 32
if nibble != 0 {
let mask = ~UInt32(0) << (32 - nibble)
let i = Int(networkPrefixLength / 32 * 4)
bytes[i + 0] = UInt8(truncatingIfNeeded: mask >> 24)
bytes[i + 1] = UInt8(truncatingIfNeeded: mask >> 16)
bytes[i + 2] = UInt8(truncatingIfNeeded: mask >> 8)
bytes[i + 3] = UInt8(truncatingIfNeeded: mask >> 0)
}
return IPv6Address(bytes)!
}
fatalError()
}
public func maskedAddress() -> IPAddress {
let subnet = subnetMask().rawValue
var masked = Data(address.rawValue)
if subnet.count != masked.count {
fatalError()
}
for i in 0..<subnet.count {
masked[i] &= subnet[i]
}
if subnet.count == 4 {
return IPv4Address(masked)!
}
if subnet.count == 16 {
return IPv6Address(masked)!
}
fatalError()
}
}
@@ -113,38 +113,26 @@ class PacketTunnelSettingsGenerator {
networkSettings.mtu = NSNumber(value: mtu)
}
let (ipv4Routes, ipv6Routes) = routes()
let (ipv4Addresses, ipv6Addresses) = addresses()
let (ipv4IncludedRoutes, ipv6IncludedRoutes) = includedRoutes()
let ipv4Settings = NEIPv4Settings(addresses: ipv4Routes.map { $0.destinationAddress }, subnetMasks: ipv4Routes.map { $0.destinationSubnetMask })
let ipv4Settings = NEIPv4Settings(addresses: ipv4Addresses.map { $0.destinationAddress }, subnetMasks: ipv4Addresses.map { $0.destinationSubnetMask })
ipv4Settings.includedRoutes = ipv4IncludedRoutes
networkSettings.ipv4Settings = ipv4Settings
let ipv6Settings = NEIPv6Settings(addresses: ipv6Routes.map { $0.destinationAddress }, networkPrefixLengths: ipv6Routes.map { $0.destinationNetworkPrefixLength })
let ipv6Settings = NEIPv6Settings(addresses: ipv6Addresses.map { $0.destinationAddress }, networkPrefixLengths: ipv6Addresses.map { $0.destinationNetworkPrefixLength })
ipv6Settings.includedRoutes = ipv6IncludedRoutes
networkSettings.ipv6Settings = ipv6Settings
return networkSettings
}
private func ipv4SubnetMaskString(of addressRange: IPAddressRange) -> String {
let length: UInt8 = addressRange.networkPrefixLength
assert(length <= 32)
var octets: [UInt8] = [0, 0, 0, 0]
let subnetMask: UInt32 = length > 0 ? ~UInt32(0) << (32 - length) : UInt32(0)
octets[0] = UInt8(truncatingIfNeeded: subnetMask >> 24)
octets[1] = UInt8(truncatingIfNeeded: subnetMask >> 16)
octets[2] = UInt8(truncatingIfNeeded: subnetMask >> 8)
octets[3] = UInt8(truncatingIfNeeded: subnetMask)
return octets.map { String($0) }.joined(separator: ".")
}
private func routes() -> ([NEIPv4Route], [NEIPv6Route]) {
private func addresses() -> ([NEIPv4Route], [NEIPv6Route]) {
var ipv4Routes = [NEIPv4Route]()
var ipv6Routes = [NEIPv6Route]()
for addressRange in tunnelConfiguration.interface.addresses {
if addressRange.address is IPv4Address {
ipv4Routes.append(NEIPv4Route(destinationAddress: "\(addressRange.address)", subnetMask: ipv4SubnetMaskString(of: addressRange)))
ipv4Routes.append(NEIPv4Route(destinationAddress: "\(addressRange.address)", subnetMask: "\(addressRange.subnetMask())"))
} else if addressRange.address is IPv6Address {
/* Big fat ugly hack for broken iOS networking stack: the smallest prefix that will have
* any effect on iOS is a /120, so we clamp everything above to /120. This is potentially
@@ -160,10 +148,23 @@ class PacketTunnelSettingsGenerator {
private func includedRoutes() -> ([NEIPv4Route], [NEIPv6Route]) {
var ipv4IncludedRoutes = [NEIPv4Route]()
var ipv6IncludedRoutes = [NEIPv6Route]()
for addressRange in tunnelConfiguration.interface.addresses {
if addressRange.address is IPv4Address {
let route = NEIPv4Route(destinationAddress: "\(addressRange.maskedAddress())", subnetMask: "\(addressRange.subnetMask())")
route.gatewayAddress = "\(addressRange.address)"
ipv4IncludedRoutes.append(route)
} else if addressRange.address is IPv6Address {
let route = NEIPv6Route(destinationAddress: "\(addressRange.maskedAddress())", networkPrefixLength: NSNumber(value: addressRange.networkPrefixLength))
route.gatewayAddress = "\(addressRange.address)"
ipv6IncludedRoutes.append(route)
}
}
for peer in tunnelConfiguration.peers {
for addressRange in peer.allowedIPs {
if addressRange.address is IPv4Address {
ipv4IncludedRoutes.append(NEIPv4Route(destinationAddress: "\(addressRange.address)", subnetMask: ipv4SubnetMaskString(of: addressRange)))
ipv4IncludedRoutes.append(NEIPv4Route(destinationAddress: "\(addressRange.address)", subnetMask: "\(addressRange.subnetMask())"))
} else if addressRange.address is IPv6Address {
ipv6IncludedRoutes.append(NEIPv6Route(destinationAddress: "\(addressRange.address)", networkPrefixLength: NSNumber(value: addressRange.networkPrefixLength)))
}
+42 -12
View File
@@ -57,12 +57,43 @@ public class WireGuardAdapter {
/// Tunnel device file descriptor.
private var tunnelFileDescriptor: Int32? {
return self.packetTunnelProvider?.packetFlow.value(forKeyPath: "socket.fileDescriptor") as? Int32
var ctlInfo = ctl_info()
withUnsafeMutablePointer(to: &ctlInfo.ctl_name) {
$0.withMemoryRebound(to: CChar.self, capacity: MemoryLayout.size(ofValue: $0.pointee)) {
_ = strcpy($0, "com.apple.net.utun_control")
}
}
for fd: Int32 in 0...1024 {
var addr = sockaddr_ctl()
var ret: Int32 = -1
var len = socklen_t(MemoryLayout.size(ofValue: addr))
withUnsafeMutablePointer(to: &addr) {
$0.withMemoryRebound(to: sockaddr.self, capacity: 1) {
ret = getpeername(fd, $0, &len)
}
}
if ret != 0 || addr.sc_family != AF_SYSTEM {
continue
}
if ctlInfo.ctl_id == 0 {
ret = ioctl(fd, CTLIOCGINFO, &ctlInfo)
if ret != 0 {
continue
}
}
if addr.sc_id == ctlInfo.ctl_id {
return fd
}
}
return nil
}
/// Returns a WireGuard version.
class var backendVersion: String {
return String(cString: wgVersion())
guard let ver = wgVersion() else { return "unknown" }
let str = String(cString: ver)
free(UnsafeMutableRawPointer(mutating: ver))
return str
}
/// Returns the tunnel device interface name, or nil on error.
@@ -265,7 +296,7 @@ public class WireGuardAdapter {
.takeUnretainedValue()
let swiftString = String(cString: message).trimmingCharacters(in: .newlines)
let tunnelLogLevel = WireGuardLogLevel(rawValue: logLevel) ?? .debug
let tunnelLogLevel = WireGuardLogLevel(rawValue: logLevel) ?? .verbose
unretainedSelf.logHandler(tunnelLogLevel, swiftString)
}
@@ -369,9 +400,9 @@ public class WireGuardAdapter {
switch result {
case .success((let sourceEndpoint, let resolvedEndpoint)):
if sourceEndpoint.host == resolvedEndpoint.host {
self.logHandler(.debug, "DNS64: mapped \(sourceEndpoint.host) to itself.")
self.logHandler(.verbose, "DNS64: mapped \(sourceEndpoint.host) to itself.")
} else {
self.logHandler(.debug, "DNS64: mapped \(sourceEndpoint.host) to \(resolvedEndpoint.host)")
self.logHandler(.verbose, "DNS64: mapped \(sourceEndpoint.host) to \(resolvedEndpoint.host)")
}
case .failure(let resolutionError):
self.logHandler(.error, "Failed to resolve endpoint \(resolutionError.address): \(resolutionError.errorDescription ?? "(nil)")")
@@ -382,7 +413,7 @@ public class WireGuardAdapter {
/// Helper method used by network path monitor.
/// - Parameter path: new network path
private func didReceivePathUpdate(path: Network.NWPath) {
self.logHandler(.debug, "Network change detected with \(path.status) route and interface order \(path.availableInterfaces)")
self.logHandler(.verbose, "Network change detected with \(path.status) route and interface order \(path.availableInterfaces)")
#if os(macOS)
if case .started(let handle, _) = self.state {
@@ -399,7 +430,7 @@ public class WireGuardAdapter {
wgDisableSomeRoamingForBrokenMobileSemantics(handle)
wgBumpSockets(handle)
} else {
self.logHandler(.info, "Connectivity offline, pausing backend.")
self.logHandler(.verbose, "Connectivity offline, pausing backend.")
self.state = .temporaryShutdown(settingsGenerator)
wgTurnOff(handle)
@@ -408,7 +439,7 @@ public class WireGuardAdapter {
case .temporaryShutdown(let settingsGenerator):
guard path.status.isSatisfiable else { return }
self.logHandler(.info, "Connectivity online, resuming backend.")
self.logHandler(.verbose, "Connectivity online, resuming backend.")
do {
try self.setNetworkSettings(settingsGenerator.generateNetworkSettings())
@@ -434,11 +465,10 @@ public class WireGuardAdapter {
}
}
/// A enum describing WireGuard log levels defined in `api-ios.go`.
/// A enum describing WireGuard log levels defined in `api-apple.go`.
public enum WireGuardLogLevel: Int32 {
case debug = 0
case info = 1
case error = 2
case verbose = 0
case error = 1
}
private extension Network.NWPath.Status {
+15
View File
@@ -3,3 +3,18 @@
#include "key.h"
#include "x25519.h"
/* From <sys/kern_control.h> */
#define CTLIOCGINFO 0xc0644e03UL
struct ctl_info {
u_int32_t ctl_id;
char ctl_name[96];
};
struct sockaddr_ctl {
u_char sc_len;
u_char sc_family;
u_int16_t ss_sysaddr;
u_int32_t sc_id;
u_int32_t sc_unit;
u_int32_t sc_reserved[5];
};
+9 -7
View File
@@ -3,9 +3,9 @@
# Copyright (C) 2018-2019 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
# These are generally passed to us by xcode, but we set working defaults for standalone compilation too.
ARCHS ?= x86_64 #TODO: add arm64 to this list once we support apple silicon
SDK_NAME ?= macosx
SDKROOT ?= $(shell xcrun --sdk $(SDK_NAME) --show-sdk-path)
ARCHS ?= x86_64 arm64
PLATFORM_NAME ?= macosx
SDKROOT ?= $(shell xcrun --sdk $(PLATFORM_NAME) --show-sdk-path)
CONFIGURATION_BUILD_DIR ?= $(CURDIR)/out
CONFIGURATION_TEMP_DIR ?= $(CURDIR)/.tmp
@@ -17,6 +17,8 @@ BUILDDIR ?= $(CONFIGURATION_TEMP_DIR)/wireguard-go-bridge
CFLAGS_PREFIX := $(if $(DEPLOYMENT_TARGET_CLANG_FLAG_NAME),-$(DEPLOYMENT_TARGET_CLANG_FLAG_NAME)=$($(DEPLOYMENT_TARGET_CLANG_ENV_NAME)),) -isysroot $(SDKROOT) -arch
GOARCH_arm64 := arm64
GOARCH_x86_64 := amd64
GOOS_macosx := darwin
GOOS_iphoneos := ios
build: $(DESTDIR)/libwg-go.a
version-header: $(DESTDIR)/wireguard-go-version.h
@@ -34,16 +36,16 @@ define libwg-go-a
$(BUILDDIR)/libwg-go-$(1).a: export CGO_ENABLED := 1
$(BUILDDIR)/libwg-go-$(1).a: export CGO_CFLAGS := $(CFLAGS_PREFIX) $(ARCH)
$(BUILDDIR)/libwg-go-$(1).a: export CGO_LDFLAGS := $(CFLAGS_PREFIX) $(ARCH)
$(BUILDDIR)/libwg-go-$(1).a: export GOOS := darwin
$(BUILDDIR)/libwg-go-$(1).a: export GOOS := $(GOOS_$(PLATFORM_NAME))
$(BUILDDIR)/libwg-go-$(1).a: export GOARCH := $(GOARCH_$(1))
$(BUILDDIR)/libwg-go-$(1).a: $(GOROOT)/.prepared go.mod
go build -tags ios -ldflags=-w -trimpath -v -o "$(BUILDDIR)/libwg-go-$(1).a" -buildmode c-archive
go build -ldflags=-w -trimpath -v -o "$(BUILDDIR)/libwg-go-$(1).a" -buildmode c-archive
rm -f "$(BUILDDIR)/libwg-go-$(1).h"
endef
$(foreach ARCH,$(ARCHS),$(eval $(call libwg-go-a,$(ARCH))))
$(DESTDIR)/wireguard-go-version.h: $(GOROOT)/.prepared go.mod
go list -m golang.zx2c4.com/wireguard | sed -n 's/.*v\([0-9.]*\).*/#define WIREGUARD_GO_VERSION "\1"/p' > "$@"
$(DESTDIR)/wireguard-go-version.h: go.mod $(GOROOT)/.prepared
sed -E -n 's/.*golang\.zx2c4\.com\/wireguard +v[0-9.]+-[0-9]+-([0-9a-f]{8})[0-9a-f]{4}.*/#define WIREGUARD_GO_VERSION "\1"/p' "$<" > "$@"
$(DESTDIR)/libwg-go.a: $(foreach ARCH,$(ARCHS),$(BUILDDIR)/libwg-go-$(ARCH).a)
@mkdir -vp "$(DESTDIR)"
@@ -14,37 +14,41 @@ package main
import "C"
import (
"bufio"
"bytes"
"errors"
"golang.org/x/sys/unix"
"golang.zx2c4.com/wireguard/device"
"golang.zx2c4.com/wireguard/tun"
"log"
"fmt"
"math"
"os"
"os/signal"
"runtime"
"runtime/debug"
"strings"
"time"
"unsafe"
"golang.org/x/sys/unix"
"golang.zx2c4.com/wireguard/conn"
"golang.zx2c4.com/wireguard/device"
"golang.zx2c4.com/wireguard/tun"
)
var loggerFunc unsafe.Pointer
var loggerCtx unsafe.Pointer
var versionString *C.char
type CLogger struct {
level C.int
type CLogger int
func cstring(s string) *C.char {
b, err := unix.BytePtrFromString(s)
if err != nil {
b := [1]C.char{}
return &b[0]
}
return (*C.char)(unsafe.Pointer(b))
}
func (l *CLogger) Write(p []byte) (int, error) {
func (l CLogger) Printf(format string, args ...interface{}) {
if uintptr(loggerFunc) == 0 {
return 0, errors.New("No logger initialized")
return
}
message := C.CString(string(p))
C.callLogger(loggerFunc, loggerCtx, l.level, message)
C.free(unsafe.Pointer(message))
return len(p), nil
C.callLogger(loggerFunc, loggerCtx, C.int(l), cstring(fmt.Sprintf(format, args...)))
}
type tunnelHandle struct {
@@ -55,7 +59,6 @@ type tunnelHandle struct {
var tunnelHandles = make(map[int32]tunnelHandle)
func init() {
versionString = C.CString(device.WireGuardGoVersion)
signals := make(chan os.Signal)
signal.Notify(signals, unix.SIGUSR2)
go func() {
@@ -82,40 +85,39 @@ func wgSetLogger(context, loggerFn uintptr) {
//export wgTurnOn
func wgTurnOn(settings *C.char, tunFd int32) int32 {
logger := &device.Logger{
Debug: log.New(&CLogger{level: 0}, "", 0),
Info: log.New(&CLogger{level: 1}, "", 0),
Error: log.New(&CLogger{level: 2}, "", 0),
Verbosef: CLogger(0).Printf,
Errorf: CLogger(1).Printf,
}
dupTunFd, err := unix.Dup(int(tunFd))
if err != nil {
logger.Error.Println(err)
logger.Errorf("Unable to dup tun fd: %v", err)
return -1
}
err = unix.SetNonblock(dupTunFd, true)
if err != nil {
logger.Error.Println(err)
logger.Errorf("Unable to set tun fd as non blocking: %v", err)
unix.Close(dupTunFd)
return -1
}
tun, err := tun.CreateTUNFromFile(os.NewFile(uintptr(dupTunFd), "/dev/tun"), 0)
if err != nil {
logger.Error.Println(err)
logger.Errorf("Unable to create new tun device from fd: %v", err)
unix.Close(dupTunFd)
return -1
}
logger.Info.Println("Attaching to interface")
device := device.NewDevice(tun, logger)
logger.Verbosef("Attaching to interface")
dev := device.NewDevice(tun, conn.NewStdNetBind(), logger)
setError := device.IpcSetOperation(bufio.NewReader(strings.NewReader(C.GoString(settings))))
if setError != nil {
logger.Error.Println(setError)
err = dev.IpcSet(C.GoString(settings))
if err != nil {
logger.Errorf("Unable to set IPC settings: %v", err)
unix.Close(dupTunFd)
return -1
}
device.Up()
logger.Info.Println("Device started")
dev.Up()
logger.Verbosef("Device started")
var i int32
for i = 0; i < math.MaxInt32; i++ {
@@ -127,18 +129,18 @@ func wgTurnOn(settings *C.char, tunFd int32) int32 {
unix.Close(dupTunFd)
return -1
}
tunnelHandles[i] = tunnelHandle{device, logger}
tunnelHandles[i] = tunnelHandle{dev, logger}
return i
}
//export wgTurnOff
func wgTurnOff(tunnelHandle int32) {
device, ok := tunnelHandles[tunnelHandle]
dev, ok := tunnelHandles[tunnelHandle]
if !ok {
return
}
delete(tunnelHandles, tunnelHandle)
device.Close()
dev.Close()
}
//export wgSetConfig
@@ -147,9 +149,9 @@ func wgSetConfig(tunnelHandle int32, settings *C.char) int64 {
if !ok {
return 0
}
err := dev.IpcSetOperation(bufio.NewReader(strings.NewReader(C.GoString(settings))))
err := dev.IpcSet(C.GoString(settings))
if err != nil {
dev.Error.Println(err)
dev.Errorf("Unable to set IPC settings: %v", err)
if ipcErr, ok := err.(*device.IPCError); ok {
return ipcErr.ErrorCode()
}
@@ -164,38 +166,58 @@ func wgGetConfig(tunnelHandle int32) *C.char {
if !ok {
return nil
}
settings := new(bytes.Buffer)
writer := bufio.NewWriter(settings)
err := device.IpcGetOperation(writer)
settings, err := device.IpcGet()
if err != nil {
return nil
}
writer.Flush()
return C.CString(settings.String())
return C.CString(settings)
}
//export wgBumpSockets
func wgBumpSockets(tunnelHandle int32) {
device, ok := tunnelHandles[tunnelHandle]
dev, ok := tunnelHandles[tunnelHandle]
if !ok {
return
}
device.BindUpdate()
device.SendKeepalivesToPeersWithCurrentKeypair()
go func() {
for i := 0; i < 10; i++ {
err := dev.BindUpdate()
if err == nil {
dev.SendKeepalivesToPeersWithCurrentKeypair()
return
}
dev.Errorf("Unable to update bind, try %d: %v", i+1, err)
time.Sleep(time.Second / 2)
}
dev.Errorf("Gave up trying to update bind; tunnel is likely dysfunctional")
}()
}
//export wgDisableSomeRoamingForBrokenMobileSemantics
func wgDisableSomeRoamingForBrokenMobileSemantics(tunnelHandle int32) {
device, ok := tunnelHandles[tunnelHandle]
dev, ok := tunnelHandles[tunnelHandle]
if !ok {
return
}
device.DisableSomeRoamingForBrokenMobileSemantics()
dev.DisableSomeRoamingForBrokenMobileSemantics()
}
//export wgVersion
func wgVersion() *C.char {
return versionString
info, ok := debug.ReadBuildInfo()
if !ok {
return C.CString("unknown")
}
for _, dep := range info.Deps {
if dep.Path == "golang.zx2c4.com/wireguard" {
parts := strings.Split(dep.Version, "-")
if len(parts) == 3 && len(parts[2]) == 12 {
return C.CString(parts[2][:7])
}
return C.CString(dep.Version)
}
}
return C.CString("unknown")
}
func main() {}
+6 -6
View File
@@ -1,10 +1,10 @@
module golang.zx2c4.com/wireguard/ios
module golang.zx2c4.com/wireguard/apple
go 1.13
go 1.16
require (
golang.org/x/crypto v0.0.0-20201208171446-5f87f3452ae9 // indirect
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11 // indirect
golang.org/x/sys v0.0.0-20201214210602-f9fddec55a1e
golang.zx2c4.com/wireguard v0.0.20201118
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a // indirect
golang.org/x/net v0.0.0-20210614182718-04defd469f4e // indirect
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22
golang.zx2c4.com/wireguard v0.0.0-20210604143328-f9b48a961cd2
)
+13 -14
View File
@@ -1,24 +1,23 @@
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20201208171446-5f87f3452ae9 h1:sYNJzB4J8toYPQTM6pAkcmBRgw9SnQKP9oXCHfgy604=
golang.org/x/crypto v0.0.0-20201208171446-5f87f3452ae9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a h1:kr2P4QFmQr29mSLA43kwrOcgcReGTfbE9N577tCTuBc=
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11 h1:lwlPPsmjDKK0J6eG6xDWd5XPehI0R024zxjDnw3esPA=
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210614182718-04defd469f4e h1:XpT3nA5TvE525Ne3hInMh6+GETgn27Zfm9dxsThnX2Q=
golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201117222635-ba5294a509c7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201214210602-f9fddec55a1e h1:AyodaIpKjppX+cBfTASF2E1US3H2JFBj920Ot3rtDjs=
golang.org/x/sys v0.0.0-20201214210602-f9fddec55a1e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22 h1:RqytpXGR1iVNX7psjB3ff8y7sNFinVFvkx1c8SjBkio=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.zx2c4.com/wireguard v0.0.20201118 h1:QL8y2C7uO8T6z1GY+UX/hSeWiYEBurQkXjOTRFtCvXU=
golang.zx2c4.com/wireguard v0.0.20201118/go.mod h1:Dz+cq5bnrai9EpgYj4GDof/+qaGzbRWbeaAOs1bUYa0=
golang.zx2c4.com/wireguard v0.0.0-20210604143328-f9b48a961cd2 h1:wfOOSvHgIzTZ9h5Vb6yUFZNn7uf3bT7PeYsHOO7tYDM=
golang.zx2c4.com/wireguard v0.0.0-20210604143328-f9b48a961cd2/go.mod h1:laHzsbfMhGSobUmruXWAyMKKHSqvIcrqZJMyHD+/3O8=
@@ -1,4 +1,4 @@
From aa85e0f90c9031ff5be32296e9fed1637a2eceae Mon Sep 17 00:00:00 2001
From 516dc0c15ff1ab781e0677606b5be72919251b3e Mon Sep 17 00:00:00 2001
From: "Jason A. Donenfeld" <Jason@zx2c4.com>
Date: Wed, 9 Dec 2020 14:07:06 +0100
Subject: [PATCH] runtime: use libc_mach_continuous_time in nanotime on Darwin
@@ -18,23 +18,23 @@ Change-Id: Ia3282e8bd86f95ad2b76427063e60a005563f4eb
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/runtime/sys_darwin.go b/src/runtime/sys_darwin.go
index 06474434c9..6f7ca37122 100644
index 4a3f2fc453..4a69403b32 100644
--- a/src/runtime/sys_darwin.go
+++ b/src/runtime/sys_darwin.go
@@ -469,7 +469,7 @@ func setNonblock(fd int32) {
@@ -440,7 +440,7 @@ func setNonblock(fd int32) {
//go:cgo_import_dynamic libc_usleep usleep "/usr/lib/libSystem.B.dylib"
//go:cgo_import_dynamic libc_mach_timebase_info mach_timebase_info "/usr/lib/libSystem.B.dylib"
-//go:cgo_import_dynamic libc_mach_absolute_time mach_absolute_time "/usr/lib/libSystem.B.dylib"
+//go:cgo_import_dynamic libc_mach_continuous_time mach_continuous_time "/usr/lib/libSystem.B.dylib"
//go:cgo_import_dynamic libc_gettimeofday gettimeofday "/usr/lib/libSystem.B.dylib"
//go:cgo_import_dynamic libc_clock_gettime clock_gettime "/usr/lib/libSystem.B.dylib"
//go:cgo_import_dynamic libc_sigaction sigaction "/usr/lib/libSystem.B.dylib"
//go:cgo_import_dynamic libc_pthread_sigmask pthread_sigmask "/usr/lib/libSystem.B.dylib"
diff --git a/src/runtime/sys_darwin_amd64.s b/src/runtime/sys_darwin_amd64.s
index 825852d673..5a8b994fb1 100644
index 630fb5df64..4499c88802 100644
--- a/src/runtime/sys_darwin_amd64.s
+++ b/src/runtime/sys_darwin_amd64.s
@@ -109,7 +109,7 @@ TEXT runtime·nanotime_trampoline(SB),NOSPLIT,$0
@@ -114,7 +114,7 @@ TEXT runtime·nanotime_trampoline(SB),NOSPLIT,$0
PUSHQ BP
MOVQ SP, BP
MOVQ DI, BX
@@ -44,10 +44,10 @@ index 825852d673..5a8b994fb1 100644
MOVL timebase<>+machTimebaseInfo_numer(SB), SI
MOVL timebase<>+machTimebaseInfo_denom(SB), DI // atomic read
diff --git a/src/runtime/sys_darwin_arm64.s b/src/runtime/sys_darwin_arm64.s
index 585d4f2c64..c556d88730 100644
index 96d2ed1076..f046545395 100644
--- a/src/runtime/sys_darwin_arm64.s
+++ b/src/runtime/sys_darwin_arm64.s
@@ -135,7 +135,7 @@ GLOBL timebase<>(SB),NOPTR,$(machTimebaseInfo__size)
@@ -143,7 +143,7 @@ GLOBL timebase<>(SB),NOPTR,$(machTimebaseInfo__size)
TEXT runtime·nanotime_trampoline(SB),NOSPLIT,$40
MOVD R0, R19
@@ -57,5 +57,5 @@ index 585d4f2c64..c556d88730 100644
MOVW timebase<>+machTimebaseInfo_numer(SB), R20
MOVD $timebase<>+machTimebaseInfo_denom(SB), R21
--
2.29.2
2.30.1
@@ -109,10 +109,8 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
extension WireGuardLogLevel {
var osLogLevel: OSLogType {
switch self {
case .debug:
case .verbose:
return .debug
case .info:
return .info
case .error:
return .error
}
+50 -40
View File
@@ -7,6 +7,8 @@
objects = {
/* Begin PBXBuildFile section */
58233BCF2591F842002060A8 /* NotificationToken.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58233BCE2591F842002060A8 /* NotificationToken.swift */; };
58233BD02591F842002060A8 /* NotificationToken.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58233BCE2591F842002060A8 /* NotificationToken.swift */; };
585B105A2577E293004F691E /* InterfaceConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 585B10462577E293004F691E /* InterfaceConfiguration.swift */; };
585B105B2577E293004F691E /* InterfaceConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 585B10462577E293004F691E /* InterfaceConfiguration.swift */; };
585B105C2577E293004F691E /* InterfaceConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 585B10462577E293004F691E /* InterfaceConfiguration.swift */; };
@@ -280,6 +282,7 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
58233BCE2591F842002060A8 /* NotificationToken.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationToken.swift; sourceTree = "<group>"; };
585B10462577E293004F691E /* InterfaceConfiguration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InterfaceConfiguration.swift; sourceTree = "<group>"; };
585B10472577E293004F691E /* PeerConfiguration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PeerConfiguration.swift; sourceTree = "<group>"; };
585B10482577E293004F691E /* DNSServer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DNSServer.swift; sourceTree = "<group>"; };
@@ -344,6 +347,8 @@
6F6483E6229293300075BA15 /* LaunchedAtLoginDetector.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LaunchedAtLoginDetector.swift; sourceTree = "<group>"; };
6F689999218043390012E523 /* WireGuard-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "WireGuard-Bridging-Header.h"; sourceTree = "<group>"; };
6F70E20D221058DF008BDFB4 /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Sources/WireGuardApp/Base.lproj/InfoPlist.strings; sourceTree = "<group>"; };
6F70E20D221058DF008BDFBA /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "Sources/WireGuardApp/zh-Hans.lproj/Localizable.strings"; sourceTree = "<group>"; };
6F70E20D221058DF008BDFC6 /* zh-Hant */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant"; path = "Sources/WireGuardApp/zh-Hant.lproj/Localizable.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>"; };
@@ -399,24 +404,24 @@
6FDEF801218646B900D8FBF6 /* ZipArchive.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ZipArchive.swift; sourceTree = "<group>"; };
6FDEF805218725D200D8FBF6 /* SettingsTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsTableViewController.swift; sourceTree = "<group>"; };
6FE1765521C90BBE002690EA /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Sources/WireGuardApp/Base.lproj/Localizable.strings; sourceTree = "<group>"; };
B42B98244F62B9607F9B45CA /* zh-Hant */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = zh-Hant; path = Sources/WireGuardApp/zh-Hant.lproj/Localizable.strings; sourceTree = "<group>"; };
30DA2ED43960DE77912BD89D /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = zh-Hans; path = Sources/WireGuardApp/zh-Hans.lproj/Localizable.strings; sourceTree = "<group>"; };
2A4344354DDBADE335B5FD2D /* id */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = id; path = Sources/WireGuardApp/id.lproj/Localizable.strings; sourceTree = "<group>"; };
B829B6E3BE26C748A53A64EE /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = Sources/WireGuardApp/it.lproj/Localizable.strings; sourceTree = "<group>"; };
5042B6E2E62F7B7537D0EE57 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = Sources/WireGuardApp/de.lproj/Localizable.strings; sourceTree = "<group>"; };
7872E185E096988E9990CC29 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = Sources/WireGuardApp/fr.lproj/Localizable.strings; sourceTree = "<group>"; };
36AFA3DAC2091DD81699B978 /* fi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fi; path = Sources/WireGuardApp/fi.lproj/Localizable.strings; sourceTree = "<group>"; };
9A06FF3EF8255B77287F0195 /* fa */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fa; path = Sources/WireGuardApp/fa.lproj/Localizable.strings; sourceTree = "<group>"; };
A7C540D3D2E36084F9AB8A0E /* sl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sl; path = Sources/WireGuardApp/sl.lproj/Localizable.strings; sourceTree = "<group>"; };
241E007502395B1D0666EE3B /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = Sources/WireGuardApp/pl.lproj/Localizable.strings; sourceTree = "<group>"; };
95493F9EF05B71D3B1A5131C /* pa */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pa; path = Sources/WireGuardApp/pa.lproj/Localizable.strings; sourceTree = "<group>"; };
C56DE3E0E402E403CA43BF97 /* ko */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ko; path = Sources/WireGuardApp/ko.lproj/Localizable.strings; sourceTree = "<group>"; };
5BE8673E6D8166A17C07E2BC /* ca */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ca; path = Sources/WireGuardApp/ca.lproj/Localizable.strings; sourceTree = "<group>"; };
63ADFB23B4BDD4ECA5B8E84B /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = Sources/WireGuardApp/ru.lproj/Localizable.strings; sourceTree = "<group>"; };
47F144079FFBAE33E6A7320E /* ro */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ro; path = Sources/WireGuardApp/ro.lproj/Localizable.strings; sourceTree = "<group>"; };
C383A8BE821704F21E30AC2A /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = Sources/WireGuardApp/tr.lproj/Localizable.strings; sourceTree = "<group>"; };
BD397C79F39F133A747A55BB /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = Sources/WireGuardApp/ja.lproj/Localizable.strings; sourceTree = "<group>"; };
88C333FB84302A6942903F37 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = Sources/WireGuardApp/es.lproj/Localizable.strings; sourceTree = "<group>"; };
6FE1765521C90BBE002690FC /* zh-Hant */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = zh-Hant; path = Sources/WireGuardApp/zh-Hant.lproj/Localizable.strings; sourceTree = "<group>"; };
6FE1765521C90BBE002690F0 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = zh-Hans; path = Sources/WireGuardApp/zh-Hans.lproj/Localizable.strings; sourceTree = "<group>"; };
6FE1765521C90BBE002690FB /* id */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = id; path = Sources/WireGuardApp/id.lproj/Localizable.strings; sourceTree = "<group>"; };
6FE1765521C90BBE002690F2 /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = Sources/WireGuardApp/it.lproj/Localizable.strings; sourceTree = "<group>"; };
6FE1765521C90BBE002690F9 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = Sources/WireGuardApp/de.lproj/Localizable.strings; sourceTree = "<group>"; };
6FE1765521C90BBE002690EB /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = Sources/WireGuardApp/fr.lproj/Localizable.strings; sourceTree = "<group>"; };
6FE1765521C90BBE002690F5 /* fi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fi; path = Sources/WireGuardApp/fi.lproj/Localizable.strings; sourceTree = "<group>"; };
6FE1765521C90BBE002690F4 /* fa */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fa; path = Sources/WireGuardApp/fa.lproj/Localizable.strings; sourceTree = "<group>"; };
6FE1765521C90BBE002690FA /* sl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sl; path = Sources/WireGuardApp/sl.lproj/Localizable.strings; sourceTree = "<group>"; };
6FE1765521C90BBE002690EC /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = Sources/WireGuardApp/pl.lproj/Localizable.strings; sourceTree = "<group>"; };
6FE1765521C90BBE002690EF /* pa */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pa; path = Sources/WireGuardApp/pa.lproj/Localizable.strings; sourceTree = "<group>"; };
6FE1765521C90BBE002690F7 /* ko */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ko; path = Sources/WireGuardApp/ko.lproj/Localizable.strings; sourceTree = "<group>"; };
6FE1765521C90BBE002690EE /* ca */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ca; path = Sources/WireGuardApp/ca.lproj/Localizable.strings; sourceTree = "<group>"; };
6FE1765521C90BBE002690F6 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = Sources/WireGuardApp/ru.lproj/Localizable.strings; sourceTree = "<group>"; };
6FE1765521C90BBE002690F3 /* ro */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ro; path = Sources/WireGuardApp/ro.lproj/Localizable.strings; sourceTree = "<group>"; };
6FE1765521C90BBE002690F8 /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = Sources/WireGuardApp/tr.lproj/Localizable.strings; sourceTree = "<group>"; };
6FE1765521C90BBE002690F1 /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = Sources/WireGuardApp/ja.lproj/Localizable.strings; sourceTree = "<group>"; };
6FE1765521C90BBE002690ED /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = Sources/WireGuardApp/es.lproj/Localizable.strings; sourceTree = "<group>"; };
6FE1765921C90E87002690EA /* LocalizationHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalizationHelper.swift; sourceTree = "<group>"; };
6FE254FA219C10800028284D /* ZipImporter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ZipImporter.swift; sourceTree = "<group>"; };
6FE254FE219C60290028284D /* ZipExporter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ZipExporter.swift; sourceTree = "<group>"; };
@@ -580,6 +585,7 @@
6F7774E6217201E0006A79B3 /* Model */,
6F5A2B4421AFDE020081EDD8 /* FileManager+Extension.swift */,
6B5C5E26220A48D30024272E /* Keychain.swift */,
58233BCE2591F842002060A8 /* NotificationToken.swift */,
);
name = Shared;
path = Sources/Shared;
@@ -1021,8 +1027,8 @@
knownRegions = (
Base,
en,
zh-Hant,
zh-Hans,
"zh-Hant",
"zh-Hans",
id,
it,
de,
@@ -1289,6 +1295,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
58233BD02591F842002060A8 /* NotificationToken.swift in Sources */,
6FBA101521D613F90051C35F /* Application.swift in Sources */,
6FB1BDCC21D50F5300A991BF /* TunnelsManager.swift in Sources */,
6F8F0D7222258153000E8335 /* ActivateOnDemandViewModel.swift in Sources */,
@@ -1442,6 +1449,7 @@
6F61F1EB21B937EF00483816 /* WireGuardResult.swift in Sources */,
6F7774F321774263006A79B3 /* TunnelEditTableViewController.swift in Sources */,
6FBA103B21D6B4290051C35F /* ErrorPresenterProtocol.swift in Sources */,
58233BCF2591F842002060A8 /* NotificationToken.swift in Sources */,
585B10862577E294004F691E /* IPAddressRange.swift in Sources */,
6FDEF802218646BA00D8FBF6 /* ZipArchive.swift in Sources */,
585B10922577E294004F691E /* key.c in Sources */,
@@ -1501,24 +1509,24 @@
6FE1765421C90BBE002690EA /* Localizable.strings */ = {
isa = PBXVariantGroup;
children = (
B42B98244F62B9607F9B45CA /* zh-Hant */,
30DA2ED43960DE77912BD89D /* zh-Hans */,
2A4344354DDBADE335B5FD2D /* id */,
B829B6E3BE26C748A53A64EE /* it */,
5042B6E2E62F7B7537D0EE57 /* de */,
7872E185E096988E9990CC29 /* fr */,
36AFA3DAC2091DD81699B978 /* fi */,
9A06FF3EF8255B77287F0195 /* fa */,
A7C540D3D2E36084F9AB8A0E /* sl */,
241E007502395B1D0666EE3B /* pl */,
95493F9EF05B71D3B1A5131C /* pa */,
C56DE3E0E402E403CA43BF97 /* ko */,
5BE8673E6D8166A17C07E2BC /* ca */,
63ADFB23B4BDD4ECA5B8E84B /* ru */,
47F144079FFBAE33E6A7320E /* ro */,
C383A8BE821704F21E30AC2A /* tr */,
BD397C79F39F133A747A55BB /* ja */,
88C333FB84302A6942903F37 /* es */,
6FE1765521C90BBE002690FC /* zh-Hant */,
6FE1765521C90BBE002690F0 /* zh-Hans */,
6FE1765521C90BBE002690FB /* id */,
6FE1765521C90BBE002690F2 /* it */,
6FE1765521C90BBE002690F9 /* de */,
6FE1765521C90BBE002690EB /* fr */,
6FE1765521C90BBE002690F5 /* fi */,
6FE1765521C90BBE002690F4 /* fa */,
6FE1765521C90BBE002690FA /* sl */,
6FE1765521C90BBE002690EC /* pl */,
6FE1765521C90BBE002690EF /* pa */,
6FE1765521C90BBE002690F7 /* ko */,
6FE1765521C90BBE002690EE /* ca */,
6FE1765521C90BBE002690F6 /* ru */,
6FE1765521C90BBE002690F3 /* ro */,
6FE1765521C90BBE002690F8 /* tr */,
6FE1765521C90BBE002690F1 /* ja */,
6FE1765521C90BBE002690ED /* es */,
6FE1765521C90BBE002690EA /* Base */,
);
name = Localizable.strings;
@@ -1612,6 +1620,7 @@
CODE_SIGN_ENTITLEMENTS = Sources/WireGuardApp/UI/macOS/WireGuard.entitlements;
CODE_SIGN_IDENTITY = "Mac Developer";
COMBINE_HIDPI_IMAGES = YES;
ENABLE_HARDENED_RUNTIME = YES;
INFOPLIST_FILE = Sources/WireGuardApp/UI/macOS/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
@@ -1632,6 +1641,7 @@
CODE_SIGN_ENTITLEMENTS = Sources/WireGuardApp/UI/macOS/WireGuard.entitlements;
CODE_SIGN_IDENTITY = "Mac Developer";
COMBINE_HIDPI_IMAGES = YES;
ENABLE_HARDENED_RUNTIME = YES;
INFOPLIST_FILE = Sources/WireGuardApp/UI/macOS/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
@@ -1651,6 +1661,7 @@
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO;
CODE_SIGN_ENTITLEMENTS = Sources/WireGuardNetworkExtension/WireGuardNetworkExtension_macOS.entitlements;
CODE_SIGN_IDENTITY = "Mac Developer";
ENABLE_HARDENED_RUNTIME = YES;
INFOPLIST_FILE = Sources/WireGuardNetworkExtension/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
@@ -1673,6 +1684,7 @@
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO;
CODE_SIGN_ENTITLEMENTS = Sources/WireGuardNetworkExtension/WireGuardNetworkExtension_macOS.entitlements;
CODE_SIGN_IDENTITY = "Mac Developer";
ENABLE_HARDENED_RUNTIME = YES;
INFOPLIST_FILE = Sources/WireGuardNetworkExtension/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
@@ -1759,7 +1771,6 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_HARDENED_RUNTIME = YES;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
@@ -1827,7 +1838,6 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_HARDENED_RUNTIME = YES;
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
+6 -2
View File
@@ -23,11 +23,14 @@ done < Sources/WireGuardApp/Base.lproj/Localizable.strings
git add Sources/WireGuardApp/*.lproj
declare -A LOCALE_MAP
[[ $(< WireGuard.xcodeproj/project.pbxproj) =~ [[:space:]]([0-9A-F]{24})\ /\*\ Base\ \*/\ =\ [^$'\n']*Base\.lproj/Localizable\.strings ]]
base_id="${BASH_REMATCH[1]:0:16}"
idx=$(( "0x${BASH_REMATCH[1]:16}" ))
while read -r filename; do
l="$(basename "$(dirname "$filename")" .lproj)"
[[ $l == Base ]] && continue
read -r -n 24 hex < <(LC_ALL=C tr -dc "A-F0-9" < /dev/urandom)
LOCALE_MAP["$l"]="$hex"
((++idx))
LOCALE_MAP["$l"]="$(printf '%s%08X' "$base_id" $idx)"
done < <(find Sources/WireGuardApp -name Localizable.strings -type f)
inkr=0 inls=0 inlsc=0
@@ -43,6 +46,7 @@ while IFS= read -r line; do
echo "$line"
printf '\t\t\t\tBase,\n\t\t\t\ten,\n'
for l in "${!LOCALE_MAP[@]}"; do
[[ $l == *-* ]] && l="\"$l\""
printf '\t\t\t\t%s,\n' "$l"
done
inkr=1