diff --git a/WireGuard/WireGuard.xcodeproj/project.pbxproj b/WireGuard/WireGuard.xcodeproj/project.pbxproj index be93450..e96b34b 100644 --- a/WireGuard/WireGuard.xcodeproj/project.pbxproj +++ b/WireGuard/WireGuard.xcodeproj/project.pbxproj @@ -17,6 +17,7 @@ 5F4541A621C4449E00994C13 /* ButtonCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F4541A521C4449E00994C13 /* ButtonCell.swift */; }; 5F4541A921C451D100994C13 /* TunnelStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F4541A821C451D100994C13 /* TunnelStatus.swift */; }; 5F4541AE21C7704300994C13 /* NEVPNStatus+CustomStringConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F4541AD21C7704300994C13 /* NEVPNStatus+CustomStringConvertible.swift */; }; + 5F4541B221CBFAEE00994C13 /* String+ArrayConversion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F4541B121CBFAEE00994C13 /* String+ArrayConversion.swift */; }; 6F5A2B4621AFDED40081EDD8 /* FileManager+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F5A2B4421AFDE020081EDD8 /* FileManager+Extension.swift */; }; 6F5A2B4821AFF49A0081EDD8 /* FileManager+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F5A2B4421AFDE020081EDD8 /* FileManager+Extension.swift */; }; 6F5D0C1D218352EF000F85AD /* PacketTunnelProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F5D0C1C218352EF000F85AD /* PacketTunnelProvider.swift */; }; @@ -114,6 +115,7 @@ 5F4541A521C4449E00994C13 /* ButtonCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonCell.swift; sourceTree = ""; }; 5F4541A821C451D100994C13 /* TunnelStatus.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelStatus.swift; sourceTree = ""; }; 5F4541AD21C7704300994C13 /* NEVPNStatus+CustomStringConvertible.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NEVPNStatus+CustomStringConvertible.swift"; sourceTree = ""; }; + 5F4541B121CBFAEE00994C13 /* String+ArrayConversion.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+ArrayConversion.swift"; sourceTree = ""; }; 6F5A2B4421AFDE020081EDD8 /* FileManager+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FileManager+Extension.swift"; sourceTree = ""; }; 6F5D0C1421832391000F85AD /* DNSResolver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DNSResolver.swift; sourceTree = ""; }; 6F5D0C1A218352EF000F85AD /* WireGuardNetworkExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = WireGuardNetworkExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -282,6 +284,7 @@ 6F7774E0217181B1006A79B3 /* AppDelegate.swift */, 6F919EC2218A2AE90023B400 /* ErrorPresenter.swift */, 5F45417C21C1B23600994C13 /* UITableViewCell+Reuse.swift */, + 5F4541B121CBFAEE00994C13 /* String+ArrayConversion.swift */, ); path = iOS; sourceTree = ""; @@ -700,6 +703,7 @@ 5F4541A221C2D6DF00994C13 /* BorderedTextButton.swift in Sources */, 6F7774E1217181B1006A79B3 /* MainViewController.swift in Sources */, 6FFA5DA42197085D0001E2F7 /* ActivateOnDemandSetting.swift in Sources */, + 5F4541B221CBFAEE00994C13 /* String+ArrayConversion.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/WireGuard/WireGuard/ConfigFile/WgQuickConfigFileParser.swift b/WireGuard/WireGuard/ConfigFile/WgQuickConfigFileParser.swift index b7239e5..b3c0acd 100644 --- a/WireGuard/WireGuard/ConfigFile/WgQuickConfigFileParser.swift +++ b/WireGuard/WireGuard/ConfigFile/WgQuickConfigFileParser.swift @@ -110,18 +110,16 @@ class WgQuickConfigFileParser { // wg-quick fields if let addressesString = attributes["address"] { var addresses = [IPAddressRange]() - for addressString in addressesString.split(separator: ",") { - let trimmedString = addressString.trimmingCharacters(in: .whitespaces) - guard let address = IPAddressRange(from: trimmedString) else { return nil } + for addressString in addressesString.splitToArray(trimmingCharacters: .whitespaces) { + guard let address = IPAddressRange(from: addressString) else { return nil } addresses.append(address) } interface.addresses = addresses } if let dnsString = attributes["dns"] { var dnsServers = [DNSServer]() - for dnsServerString in dnsString.split(separator: ",") { - let trimmedString = dnsServerString.trimmingCharacters(in: .whitespaces) - guard let dnsServer = DNSServer(from: trimmedString) else { return nil } + for dnsServerString in dnsString.splitToArray(trimmingCharacters: .whitespaces) { + guard let dnsServer = DNSServer(from: dnsServerString) else { return nil } dnsServers.append(dnsServer) } interface.dns = dnsServers @@ -146,9 +144,8 @@ class WgQuickConfigFileParser { } if let allowedIPsString = attributes["allowedips"] { var allowedIPs = [IPAddressRange]() - for allowedIPString in allowedIPsString.split(separator: ",") { - let trimmedString = allowedIPString.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines) - guard let allowedIP = IPAddressRange(from: trimmedString) else { return nil } + for allowedIPString in allowedIPsString.splitToArray(trimmingCharacters: .whitespacesAndNewlines) { + guard let allowedIP = IPAddressRange(from: allowedIPString) else { return nil } allowedIPs.append(allowedIP) } peer.allowedIPs = allowedIPs diff --git a/WireGuard/WireGuard/Tunnel/TunnelsManager.swift b/WireGuard/WireGuard/Tunnel/TunnelsManager.swift index 8382361..f6dcc32 100644 --- a/WireGuard/WireGuard/Tunnel/TunnelsManager.swift +++ b/WireGuard/WireGuard/Tunnel/TunnelsManager.swift @@ -294,7 +294,7 @@ class TunnelsManager { guard let lastErrorFileURL = FileManager.networkExtensionLastErrorFileURL else { return nil } guard let lastErrorData = try? Data(contentsOf: lastErrorFileURL) else { return nil } guard let lastErrorText = String(data: lastErrorData, encoding: .utf8) else { return nil } - let lastErrorStrings = lastErrorText.split(separator: "\n").map { String($0) } + let lastErrorStrings = lastErrorText.splitToArray(separator: "\n") guard lastErrorStrings.count == 3 else { return nil } let attemptIdInDisk = lastErrorStrings[0] if let attemptIdForTunnel = tunnel.activationAttemptId, attemptIdInDisk == attemptIdForTunnel { diff --git a/WireGuard/WireGuard/UI/TunnelViewModel.swift b/WireGuard/WireGuard/UI/TunnelViewModel.swift index 7e19bb7..1a88da2 100644 --- a/WireGuard/WireGuard/UI/TunnelViewModel.swift +++ b/WireGuard/WireGuard/UI/TunnelViewModel.swift @@ -117,9 +117,8 @@ class TunnelViewModel { var errorMessages = [String]() if let addressesString = scratchpad[.addresses] { var addresses = [IPAddressRange]() - for addressString in addressesString.split(separator: ",") { - let trimmedString = addressString.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines) - if let address = IPAddressRange(from: trimmedString) { + for addressString in addressesString.splitToArray(trimmingCharacters: .whitespacesAndNewlines) { + if let address = IPAddressRange(from: addressString) { addresses.append(address) } else { fieldsWithError.insert(.addresses) @@ -146,9 +145,8 @@ class TunnelViewModel { } if let dnsString = scratchpad[.dns] { var dnsServers = [DNSServer]() - for dnsServerString in dnsString.split(separator: ",") { - let trimmedString = dnsServerString.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines) - if let dnsServer = DNSServer(from: trimmedString) { + for dnsServerString in dnsString.splitToArray(trimmingCharacters: .whitespacesAndNewlines) { + if let dnsServer = DNSServer(from: dnsServerString) { dnsServers.append(dnsServer) } else { fieldsWithError.insert(.dns) @@ -169,7 +167,7 @@ class TunnelViewModel { if TunnelViewModel.interfaceFieldsWithControl.contains(field) { return true } - return (!self[field].isEmpty) + return !self[field].isEmpty } // TODO: Cache this to avoid recomputing } @@ -263,9 +261,8 @@ class TunnelViewModel { } if let allowedIPsString = scratchpad[.allowedIPs] { var allowedIPs = [IPAddressRange]() - for allowedIPString in allowedIPsString.split(separator: ",") { - let trimmedString = allowedIPString.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines) - if let allowedIP = IPAddressRange(from: trimmedString) { + for allowedIPString in allowedIPsString.splitToArray(trimmingCharacters: .whitespacesAndNewlines) { + if let allowedIP = IPAddressRange(from: allowedIPString) { allowedIPs.append(allowedIP) } else { fieldsWithError.insert(.allowedIPs) @@ -326,11 +323,7 @@ class TunnelViewModel { if scratchpad.isEmpty { populateScratchpad() } - let allowedIPStrings = Set( - (scratchpad[.allowedIPs] ?? "") - .split(separator: ",") - .map { $0.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines) } - ) + let allowedIPStrings = Set(scratchpad[.allowedIPs].splitToArray(trimmingCharacters: .whitespacesAndNewlines)) if allowedIPStrings.contains(TunnelViewModel.PeerData.ipv4DefaultRouteString) { shouldAllowExcludePrivateIPsControl = true excludePrivateIPsValue = false @@ -344,12 +337,8 @@ class TunnelViewModel { } func excludePrivateIPsValueChanged(isOn: Bool, dnsServers: String) { - let allowedIPStrings = (scratchpad[.allowedIPs] ?? "") - .split(separator: ",") - .map { $0.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines) } - let dnsServerStrings = dnsServers - .split(separator: ",") - .map { $0.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines) } + let allowedIPStrings = scratchpad[.allowedIPs].splitToArray(trimmingCharacters: .whitespacesAndNewlines) + let dnsServerStrings = dnsServers.splitToArray(trimmingCharacters: .whitespacesAndNewlines) let ipv6Addresses = allowedIPStrings.filter { $0.contains(":") } let modifiedAllowedIPStrings: [String] if isOn { @@ -476,5 +465,4 @@ extension TunnelViewModel { static func defaultActivateOnDemandOption() -> ActivateOnDemandOption { return .useOnDemandOverWiFiOrCellular } - } diff --git a/WireGuard/WireGuard/UI/iOS/String+ArrayConversion.swift b/WireGuard/WireGuard/UI/iOS/String+ArrayConversion.swift new file mode 100644 index 0000000..9b69cf4 --- /dev/null +++ b/WireGuard/WireGuard/UI/iOS/String+ArrayConversion.swift @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: MIT +// Copyright © 2018 WireGuard LLC. All Rights Reserved. + +import Foundation + +extension String { + + func splitToArray(separator: Character = ",", trimmingCharacters: CharacterSet? = nil) -> [String] { + return split(separator: separator) + .map { + if let charSet = trimmingCharacters { + return $0.trimmingCharacters(in: charSet) + } else { + return String($0) + } + } + } + +} + +extension Optional where Wrapped == String { + + func splitToArray(separator: Character = ",", trimmingCharacters: CharacterSet? = nil) -> [String] { + switch self { + case .none: + return [] + case .some(let wrapped): + return wrapped.splitToArray(separator: separator, trimmingCharacters: trimmingCharacters) + } + } + +}