Global: fix up strings

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
This commit is contained in:
Jason A. Donenfeld 2018-11-01 18:59:58 +01:00
parent 196daccdde
commit c2d76b9c45
8 changed files with 43 additions and 53 deletions

View File

@ -39,7 +39,7 @@ struct PeerConfiguration: Codable {
var preSharedKey: Data? { var preSharedKey: Data? {
didSet(value) { didSet(value) {
if let value = value { if let value = value {
if (value.count != 32) { fatalError("Invalid pre-shared key") } if (value.count != 32) { fatalError("Invalid preshared key") }
} }
} }
} }

View File

@ -22,9 +22,9 @@ class TunnelViewModel {
enum PeerField: String { enum PeerField: String {
case publicKey = "Public key" case publicKey = "Public key"
case preSharedKey = "Pre-shared key" case preSharedKey = "Preshared key"
case endpoint = "Endpoint" case endpoint = "Endpoint"
case persistentKeepAlive = "Persistent Keepalive" case persistentKeepAlive = "Persistent keepalive"
case allowedIPs = "Allowed IPs" case allowedIPs = "Allowed IPs"
case excludePrivateIPs = "Exclude private IPs" case excludePrivateIPs = "Exclude private IPs"
case deletePeer = "Delete peer" case deletePeer = "Delete peer"
@ -107,7 +107,7 @@ class TunnelViewModel {
} }
guard let privateKey = Data(base64Encoded: privateKeyString), privateKey.count == 32 else { guard let privateKey = Data(base64Encoded: privateKeyString), privateKey.count == 32 else {
fieldsWithError.insert(.privateKey) fieldsWithError.insert(.privateKey)
return .error("Interface's private key should be a 32-byte key in base64 encoding") return .error("Interface's private key must be a 32-byte key in base64 encoding")
} }
var config = InterfaceConfiguration(name: name, privateKey: privateKey) var config = InterfaceConfiguration(name: name, privateKey: privateKey)
var errorMessages: [String] = [] var errorMessages: [String] = []
@ -119,7 +119,7 @@ class TunnelViewModel {
addresses.append(address) addresses.append(address)
} else { } else {
fieldsWithError.insert(.addresses) fieldsWithError.insert(.addresses)
errorMessages.append("Interface addresses should be a list of comma-separated IP addresses") errorMessages.append("Interface addresses must be a list of comma-separated IP addresses, optionally in CIDR notation")
} }
} }
config.addresses = addresses config.addresses = addresses
@ -129,15 +129,15 @@ class TunnelViewModel {
config.listenPort = listenPort config.listenPort = listenPort
} else { } else {
fieldsWithError.insert(.listenPort) fieldsWithError.insert(.listenPort)
errorMessages.append("Interface's listen port should be a 16-bit integer (0 to 65535)") errorMessages.append("Interface's listen port must be between 0 and 65535, or unspecified")
} }
} }
if let mtuString = scratchpad[.mtu] { if let mtuString = scratchpad[.mtu] {
if let mtu = UInt16(mtuString) { if let mtu = UInt16(mtuString), mtu >= 576 {
config.mtu = mtu config.mtu = mtu
} else { } else {
fieldsWithError.insert(.mtu) fieldsWithError.insert(.mtu)
errorMessages.append("Interface's MTU should be a 16-bit integer (0 to 65535)") errorMessages.append("Interface's MTU must be between 576 and 65535, or unspecified")
} }
} }
if let dnsString = scratchpad[.dns] { if let dnsString = scratchpad[.dns] {
@ -148,7 +148,7 @@ class TunnelViewModel {
dnsServers.append(dnsServer) dnsServers.append(dnsServer)
} else { } else {
fieldsWithError.insert(.dns) fieldsWithError.insert(.dns)
errorMessages.append("Interface's DNS should be a list of comma-separated IP addresses") errorMessages.append("Interface's DNS servers must be a list of comma-separated IP addresses")
} }
} }
config.dns = dnsServers config.dns = dnsServers
@ -243,7 +243,7 @@ class TunnelViewModel {
} }
guard let publicKey = Data(base64Encoded: publicKeyString), publicKey.count == 32 else { guard let publicKey = Data(base64Encoded: publicKeyString), publicKey.count == 32 else {
fieldsWithError.insert(.publicKey) fieldsWithError.insert(.publicKey)
return .error("Peer's public key should be a 32-byte key in base64 encoding") return .error("Peer's public key must be a 32-byte key in base64 encoding")
} }
var config = PeerConfiguration(publicKey: publicKey) var config = PeerConfiguration(publicKey: publicKey)
var errorMessages: [String] = [] var errorMessages: [String] = []
@ -252,7 +252,7 @@ class TunnelViewModel {
config.preSharedKey = preSharedKey config.preSharedKey = preSharedKey
} else { } else {
fieldsWithError.insert(.preSharedKey) fieldsWithError.insert(.preSharedKey)
errorMessages.append("Peer's pre-shared key should be a 32-byte key in base64 encoding") errorMessages.append("Peer's preshared key must be a 32-byte key in base64 encoding")
} }
} }
if let allowedIPsString = scratchpad[.allowedIPs] { if let allowedIPsString = scratchpad[.allowedIPs] {
@ -263,7 +263,7 @@ class TunnelViewModel {
allowedIPs.append(allowedIP) allowedIPs.append(allowedIP)
} else { } else {
fieldsWithError.insert(.allowedIPs) fieldsWithError.insert(.allowedIPs)
errorMessages.append("Peer's allowedIPs should be a list of comma-separated IP addresses in CIDR notation") errorMessages.append("Peer's allowed IPs must be a list of comma-separated IP addresses, optionally in CIDR notation")
} }
} }
config.allowedIPs = allowedIPs config.allowedIPs = allowedIPs
@ -273,7 +273,7 @@ class TunnelViewModel {
config.endpoint = endpoint config.endpoint = endpoint
} else { } else {
fieldsWithError.insert(.endpoint) fieldsWithError.insert(.endpoint)
errorMessages.append("Peer's endpoint should be of the form 'host:port' or '[host]:port'") errorMessages.append("Peer's endpoint must be of the form 'host:port' or '[host]:port'")
} }
} }
if let persistentKeepAliveString = scratchpad[.persistentKeepAlive] { if let persistentKeepAliveString = scratchpad[.persistentKeepAlive] {
@ -281,7 +281,7 @@ class TunnelViewModel {
config.persistentKeepAlive = persistentKeepAlive config.persistentKeepAlive = persistentKeepAlive
} else { } else {
fieldsWithError.insert(.persistentKeepAlive) fieldsWithError.insert(.persistentKeepAlive)
errorMessages.append("Peer's persistent keepalive should be a 16-bit integer (0 to 65535)") errorMessages.append("Peer's persistent keepalive must be between 0 to 65535, or unspecified")
} }
} }

View File

@ -10,21 +10,21 @@ class ErrorPresenter {
// TunnelManagementError // TunnelManagementError
case TunnelManagementError.tunnelAlreadyExistsWithThatName: case TunnelManagementError.tunnelAlreadyExistsWithThatName:
return ("Name already in use", "A tunnel with that name already exists. Please pick a different name.") return ("Name already exists", "A tunnel with that name already exists. Please choose a different name.")
case TunnelManagementError.vpnSystemErrorOnAddTunnel: case TunnelManagementError.vpnSystemErrorOnAddTunnel:
return ("Could not create tunnel", "Internal error") return ("Unable to create tunnel", "Internal error")
case TunnelManagementError.vpnSystemErrorOnModifyTunnel: case TunnelManagementError.vpnSystemErrorOnModifyTunnel:
return ("Could not modify tunnel", "Internal error") return ("Unable to modify tunnel", "Internal error")
case TunnelManagementError.vpnSystemErrorOnRemoveTunnel: case TunnelManagementError.vpnSystemErrorOnRemoveTunnel:
return ("Could not remove tunnel", "Internal error") return ("Unable to remove tunnel", "Internal error")
// TunnelActivationError // TunnelActivationError
case TunnelActivationError.noEndpoint: case TunnelActivationError.noEndpoint:
return ("Endpoint missing", "There must be at least one peer with an endpoint") return ("Endpoint missing", "There must be at least one peer with an endpoint")
case TunnelActivationError.dnsResolutionFailed: case TunnelActivationError.dnsResolutionFailed:
return ("DNS Failure", "One or more endpoint domains could not be resolved") return ("DNS resolution failure", "One or more endpoint domains could not be resolved")
case TunnelActivationError.tunnelActivationFailed: case TunnelActivationError.tunnelActivationFailed:
return ("Activation failed", "The tunnel could not be activated because of an internal error") return ("Activation failure", "The tunnel could not be activated due to an internal error")
case TunnelActivationError.attemptingActivationWhenAnotherTunnelIsBusy(let otherTunnelStatus): case TunnelActivationError.attemptingActivationWhenAnotherTunnelIsBusy(let otherTunnelStatus):
let statusString: String = { let statusString: String = {
switch (otherTunnelStatus) { switch (otherTunnelStatus) {
@ -41,7 +41,7 @@ class ErrorPresenter {
fatalError() fatalError()
} }
}() }()
return ("Activation failed", "Another tunnel is currently \(statusString). Only one tunnel can be in operation at a time.") return ("Activation failure", "Another tunnel is currently \(statusString). Only one tunnel may be in operation at a time.")
default: default:
os_log("ErrorPresenter: Error not presented: %{public}@", log: OSLog.default, type: .error, "\(error)") os_log("ErrorPresenter: Error not presented: %{public}@", log: OSLog.default, type: .error, "\(error)")

View File

@ -40,7 +40,7 @@ class QRScanViewController: UIViewController {
let captureSession = captureSession, let captureSession = captureSession,
captureSession.canAddInput(videoInput), captureSession.canAddInput(videoInput),
captureSession.canAddOutput(metadataOutput) else { captureSession.canAddOutput(metadataOutput) else {
scanDidEncounterError(title: "Scanning Not Supported", message: "This device does not have the ability to scan QR codes.") scanDidEncounterError(title: "Camera Unsupported", message: "This device is not able to scan QR codes.")
return return
} }
@ -108,11 +108,11 @@ class QRScanViewController: UIViewController {
func scanDidComplete(withCode code: String) { func scanDidComplete(withCode code: String) {
let scannedTunnelConfiguration = try? WgQuickConfigFileParser.parse(code, name: "Scanned") let scannedTunnelConfiguration = try? WgQuickConfigFileParser.parse(code, name: "Scanned")
guard let tunnelConfiguration = scannedTunnelConfiguration else { guard let tunnelConfiguration = scannedTunnelConfiguration else {
scanDidEncounterError(title: "Invalid Code", message: "The scanned code is not a valid WireGuard config file.") scanDidEncounterError(title: "Invalid QR Code", message: "The scanned QR code is not a valid WireGuard configuration.")
return return
} }
let alert = UIAlertController(title: NSLocalizedString("Enter a title for new tunnel", comment: ""), message: nil, preferredStyle: .alert) let alert = UIAlertController(title: NSLocalizedString("Please name the scanned tunnel", comment: ""), message: nil, preferredStyle: .alert)
alert.addTextField(configurationHandler: nil) alert.addTextField(configurationHandler: nil)
alert.addAction(UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: .cancel, handler: nil)) alert.addAction(UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: .cancel, handler: nil))
alert.addAction(UIAlertAction(title: NSLocalizedString("Save", comment: ""), style: .default, handler: { [weak self] _ in alert.addAction(UIAlertAction(title: NSLocalizedString("Save", comment: ""), style: .default, handler: { [weak self] _ in

View File

@ -46,7 +46,7 @@ class SettingsTableViewController: UITableViewController {
func exportConfigurationsAsZipFile(sourceView: UIView) { func exportConfigurationsAsZipFile(sourceView: UIView) {
guard let tunnelsManager = tunnelsManager, tunnelsManager.numberOfTunnels() > 0 else { guard let tunnelsManager = tunnelsManager, tunnelsManager.numberOfTunnels() > 0 else {
showErrorAlert(title: "Nothing to export", message: "There are no tunnel configurations to export") showErrorAlert(title: "Nothing to export", message: "There are no tunnels to export")
return return
} }
var inputsToArchiver: [(fileName: String, contents: Data)] = [] var inputsToArchiver: [(fileName: String, contents: Data)] = []
@ -76,21 +76,15 @@ class SettingsTableViewController: UITableViewController {
os_log("Failed to delete file: %{public}@ : %{public}@", log: OSLog.default, type: .error, destinationURL.absoluteString, error.localizedDescription) os_log("Failed to delete file: %{public}@ : %{public}@", log: OSLog.default, type: .error, destinationURL.absoluteString, error.localizedDescription)
} }
var ok = false
do { do {
try ZipArchive.archive(inputs: inputsToArchiver, to: destinationURL) try ZipArchive.archive(inputs: inputsToArchiver, to: destinationURL)
ok = true
} catch {
os_log("Failed to create archive: %{public}@ : %{public}@", log: OSLog.default, type: .error, destinationURL.absoluteString)
}
if (ok) {
let activityVC = UIActivityViewController(activityItems: [destinationURL], applicationActivities: nil) let activityVC = UIActivityViewController(activityItems: [destinationURL], applicationActivities: nil)
// popoverPresentationController shall be non-nil on the iPad // popoverPresentationController shall be non-nil on the iPad
activityVC.popoverPresentationController?.sourceView = sourceView activityVC.popoverPresentationController?.sourceView = sourceView
present(activityVC, animated: true) present(activityVC, animated: true)
} else {
showErrorAlert(title: "Could not export", message: "There was an error creating the tunnel configuration archive") } catch (let error) {
showErrorAlert(title: "Unable to export", message: "There was an error exporting the tunnel configuration archive: \(String(describing: error))")
} }
} }

View File

@ -42,15 +42,13 @@ class TunnelsListTableViewController: UITableViewController {
} }
@objc func addButtonTapped(sender: UIBarButtonItem!) { @objc func addButtonTapped(sender: UIBarButtonItem!) {
let alert = UIAlertController(title: "", let alert = UIAlertController(title: "", message: "Add a new WireGuard tunnel", preferredStyle: .actionSheet)
message: "Add a tunnel", let importFileAction = UIAlertAction(title: "Create from file or archive", style: .default) { [weak self] (action) in
preferredStyle: .actionSheet)
let importFileAction = UIAlertAction(title: "Import file or archive", style: .default) { [weak self] (action) in
self?.presentViewControllerForFileImport() self?.presentViewControllerForFileImport()
} }
alert.addAction(importFileAction) alert.addAction(importFileAction)
let scanQRCodeAction = UIAlertAction(title: "Scan QR code", style: .default) { [weak self] (action) in let scanQRCodeAction = UIAlertAction(title: "Create from QR code", style: .default) { [weak self] (action) in
self?.presentViewControllerForScanningQRCode() self?.presentViewControllerForScanningQRCode()
} }
alert.addAction(scanQRCodeAction) alert.addAction(scanQRCodeAction)
@ -83,8 +81,8 @@ class TunnelsListTableViewController: UITableViewController {
do { do {
let fileContents = try String(contentsOf: configFileURL) let fileContents = try String(contentsOf: configFileURL)
try tunnelConfiguration = WgQuickConfigFileParser.parse(fileContents, name: name) try tunnelConfiguration = WgQuickConfigFileParser.parse(fileContents, name: name)
} catch { } catch (let error) {
showErrorAlert(title: "Could not import config", message: "There was an error importing the config file") showErrorAlert(title: "Unable to import tunnel", message: "An error occured when importing the tunnel configuration: \(String(describing: error))")
return return
} }
tunnelConfiguration?.interface.name = name tunnelConfiguration?.interface.name = name
@ -140,18 +138,18 @@ class TunnelsListTableViewController: UITableViewController {
} }
} }
} else { } else {
showErrorAlert(title: "Could not import", message: "The config file contained errors") showErrorAlert(title: "Unable to import tunnel", message: "An error occured when importing the tunnel configuration.")
} }
} else if (url.pathExtension == "zip") { } else if (url.pathExtension == "zip") {
var unarchivedFiles: [(fileName: String, contents: Data)] = [] var unarchivedFiles: [(fileName: String, contents: Data)] = []
do { do {
unarchivedFiles = try ZipArchive.unarchive(url: url, requiredFileExtensions: ["conf"]) unarchivedFiles = try ZipArchive.unarchive(url: url, requiredFileExtensions: ["conf"])
} catch ZipArchiveError.cantOpenInputZipFile { } catch ZipArchiveError.cantOpenInputZipFile {
showErrorAlert(title: "Cannot read zip archive", message: "The zip file couldn't be read") showErrorAlert(title: "Unable to read zip archive", message: "The zip archive could not be read")
} catch ZipArchiveError.badArchive { } catch ZipArchiveError.badArchive {
showErrorAlert(title: "Cannot read zip archive", message: "Bad archive") showErrorAlert(title: "Unable to read zip archive", message: "Bad or corrupt zip archive")
} catch (let error) { } catch (let error) {
print("Error opening zip archive: \(error)") showErrorAlert(title: "Unable to read zip archive", message: "Unexpected error: \(String(describing: error))")
} }
var numberOfConfigFilesWithErrors = 0 var numberOfConfigFilesWithErrors = 0
var tunnelConfigurationsToAdd: [TunnelConfiguration] = [] var tunnelConfigurationsToAdd: [TunnelConfiguration] = []
@ -167,7 +165,7 @@ class TunnelsListTableViewController: UITableViewController {
} }
} }
guard (tunnelConfigurationsToAdd.count > 0) else { guard (tunnelConfigurationsToAdd.count > 0) else {
showErrorAlert(title: "No configurations found", message: "Zip archive doesn't contain any valid .conf files") showErrorAlert(title: "No configurations found", message: "Zip archive does not contain any valid .conf files")
return return
} }
var numberOfTunnelsRemainingAfterError = 0 var numberOfTunnelsRemainingAfterError = 0
@ -179,8 +177,8 @@ class TunnelsListTableViewController: UITableViewController {
} }
} }
if (numberOfConfigFilesWithErrors > 0) { if (numberOfConfigFilesWithErrors > 0) {
showErrorAlert(title: "Could not import \(numberOfConfigFilesWithErrors + numberOfTunnelsRemainingAfterError) files", showErrorAlert(title: "Created \(unarchivedFiles.count) tunnels",
message: "\(numberOfConfigFilesWithErrors) of \(unarchivedFiles.count) files contained errors or duplicate names and were not imported") message: "Created \(numberOfTunnelsRemainingAfterError) of \(unarchivedFiles.count) tunnels from files in zip archive")
} }
} }
} }
@ -254,8 +252,8 @@ extension TunnelsListTableViewController {
} }
} }
} else { } else {
tunnelsManager.startDeactivation(of: tunnel) { error in tunnelsManager.startDeactivation(of: tunnel) { [weak s] error in
print("Error while deactivating: \(String(describing: error))") s?.showErrorAlert(title: "Deactivation error", message: "Error while bringing down tunnel: \(String(describing: error))")
} }
} }
} }

View File

@ -95,8 +95,6 @@
# define DEF_MEM_LEVEL MAX_MEM_LEVEL # define DEF_MEM_LEVEL MAX_MEM_LEVEL
#endif #endif
#endif #endif
const char zip_copyright[] =" zip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll";
#define SIZEDATA_INDATABLOCK (4096-(4*4)) #define SIZEDATA_INDATABLOCK (4096-(4*4))

View File

@ -29,7 +29,7 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
guard let options = options else { guard let options = options else {
os_log("Starting tunnel failed: No options passed. Possible connection request from preferences.", log: OSLog.default, type: .error) os_log("Starting tunnel failed: No options passed. Possible connection request from preferences.", log: OSLog.default, type: .error)
// displayMessage is deprecated API // displayMessage is deprecated API
displayMessage("Please use the WireGuard app to start up WireGuard VPN configurations.") { (_) in displayMessage("Please use the WireGuard app to start WireGuard tunnels.") { (_) in
startTunnelCompletionHandler(PacketTunnelProviderError.invalidOptions) startTunnelCompletionHandler(PacketTunnelProviderError.invalidOptions)
} }
return return