diff --git a/Passepartout-iOS/Scenes/Organizer/OrganizerViewController.swift b/Passepartout-iOS/Scenes/Organizer/OrganizerViewController.swift index 6f5c92d3..43c79a83 100644 --- a/Passepartout-iOS/Scenes/Organizer/OrganizerViewController.swift +++ b/Passepartout-iOS/Scenes/Organizer/OrganizerViewController.swift @@ -382,14 +382,14 @@ extension OrganizerViewController { return ids } - private func profileKey(at indexPath: IndexPath) -> ConnectionService.ProfileKey { + private func profileKey(at indexPath: IndexPath) -> ProfileKey { let section = model.section(for: indexPath.section) switch section { case .providers: - return ConnectionService.ProfileKey(.provider, providers[indexPath.row]) + return ProfileKey(.provider, providers[indexPath.row]) case .hosts: - return ConnectionService.ProfileKey(.host, hosts[indexPath.row]) + return ProfileKey(.host, hosts[indexPath.row]) default: fatalError("Profile found in unexpected section: \(section)") @@ -450,7 +450,7 @@ extension OrganizerViewController: ConnectionServiceDelegate { tableView.reloadData() } - func connectionService(didRemoveProfileWithKey key: ConnectionService.ProfileKey) { + func connectionService(didRemoveProfileWithKey key: ProfileKey) { TransientStore.shared.serialize(withProfiles: false) // delete splitViewController?.serviceViewController?.hideProfileIfDeleted() diff --git a/Passepartout.xcodeproj/project.pbxproj b/Passepartout.xcodeproj/project.pbxproj index 2aac80c5..8b5a4404 100644 --- a/Passepartout.xcodeproj/project.pbxproj +++ b/Passepartout.xcodeproj/project.pbxproj @@ -40,6 +40,8 @@ 0E5E5DE521511C5F00E318A3 /* GracefulVPN.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E5E5DE421511C5F00E318A3 /* GracefulVPN.swift */; }; 0E6BE13A20CFB76800A6DD36 /* ApplicationError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E6BE13920CFB76800A6DD36 /* ApplicationError.swift */; }; 0E6BE13F20CFBAB300A6DD36 /* DebugLogViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E6BE13E20CFBAB300A6DD36 /* DebugLogViewController.swift */; }; + 0E79D13F21919EC900BB5FB2 /* PlaceholderConnectionProfile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E79D13E21919EC900BB5FB2 /* PlaceholderConnectionProfile.swift */; }; + 0E79D14121919F5600BB5FB2 /* ProfileKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E79D14021919F5600BB5FB2 /* ProfileKey.swift */; }; 0E89DFC5213DF7AE00741BA1 /* Preferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E89DFC4213DF7AE00741BA1 /* Preferences.swift */; }; 0E89DFC8213E8FC500741BA1 /* SessionProxy+Communication.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E89DFC7213E8FC500741BA1 /* SessionProxy+Communication.swift */; }; 0E89DFCE213EEDFA00741BA1 /* WizardProviderViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E89DFCD213EEDFA00741BA1 /* WizardProviderViewController.swift */; }; @@ -162,6 +164,8 @@ 0E5E5DE421511C5F00E318A3 /* GracefulVPN.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GracefulVPN.swift; sourceTree = ""; }; 0E6BE13920CFB76800A6DD36 /* ApplicationError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApplicationError.swift; sourceTree = ""; }; 0E6BE13E20CFBAB300A6DD36 /* DebugLogViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DebugLogViewController.swift; sourceTree = ""; }; + 0E79D13E21919EC900BB5FB2 /* PlaceholderConnectionProfile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlaceholderConnectionProfile.swift; sourceTree = ""; }; + 0E79D14021919F5600BB5FB2 /* ProfileKey.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileKey.swift; sourceTree = ""; }; 0E89DFC4213DF7AE00741BA1 /* Preferences.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Preferences.swift; sourceTree = ""; }; 0E89DFC7213E8FC500741BA1 /* SessionProxy+Communication.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SessionProxy+Communication.swift"; sourceTree = ""; }; 0E89DFCD213EEDFA00741BA1 /* WizardProviderViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WizardProviderViewController.swift; sourceTree = ""; }; @@ -368,6 +372,8 @@ isa = PBXGroup; children = ( 0EBE3AA3213DC1B000BFA2F5 /* HostConnectionProfile.swift */, + 0E79D13E21919EC900BB5FB2 /* PlaceholderConnectionProfile.swift */, + 0E79D14021919F5600BB5FB2 /* ProfileKey.swift */, 0EBE3AA4213DC1B000BFA2F5 /* ProviderConnectionProfile.swift */, ); path = Profiles; @@ -834,6 +840,7 @@ 0E39BCF3214DA9310035E9DE /* AppConstants.swift in Sources */, 0E05C5D620D1645F006EE732 /* SwiftGen+Scenes.swift in Sources */, 0E2B494220FD16540094784C /* TransientStore.swift in Sources */, + 0E79D14121919F5600BB5FB2 /* ProfileKey.swift in Sources */, 0E89DFC5213DF7AE00741BA1 /* Preferences.swift in Sources */, 0E6BE13A20CFB76800A6DD36 /* ApplicationError.swift in Sources */, 0EFD9440215BED8E00529B64 /* LabelViewController.swift in Sources */, @@ -866,6 +873,7 @@ 0ED38AE721404F100004D387 /* EndpointDataSource.swift in Sources */, 0E8D97E221388B52006FB4A0 /* InfrastructurePreset.swift in Sources */, 0ED31C3720CF38D10027975F /* VPN.swift in Sources */, + 0E79D13F21919EC900BB5FB2 /* PlaceholderConnectionProfile.swift in Sources */, 0ED31C2920CF2A340027975F /* AccountViewController.swift in Sources */, 0E5E5DE521511C5F00E318A3 /* GracefulVPN.swift in Sources */, 0E158ADA20E11B0B00C85A82 /* EndpointViewController.swift in Sources */, @@ -1133,7 +1141,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; TARGETED_DEVICE_FAMILY = "1,2"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Passepartout-iOS.app/Passepartout-iOS"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Passepartout.app/Passepartout"; }; name = Debug; }; @@ -1155,7 +1163,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; TARGETED_DEVICE_FAMILY = "1,2"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Passepartout-iOS.app/Passepartout-iOS"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Passepartout.app/Passepartout"; }; name = Release; }; diff --git a/Passepartout/Resources/en.lproj/Localizable.strings b/Passepartout/Resources/en.lproj/Localizable.strings index b5a06e69..583757bc 100644 --- a/Passepartout/Resources/en.lproj/Localizable.strings +++ b/Passepartout/Resources/en.lproj/Localizable.strings @@ -26,7 +26,7 @@ "global.ok" = "OK"; "global.cancel" = "Cancel"; "global.next" = "Next"; -"global.host.title_input.message" = "Legal characters are alphanumerics plus dash (-), underscore (_) and dot (.)."; +"global.host.title_input.message" = "Acceptable characters are alphanumerics plus dash \"-\", underscore \"_\" and dot \".\"."; "global.host.title_input.placeholder" = "My Profile"; "reddit.title" = "Reddit"; diff --git a/Passepartout/Sources/Model/ConnectionProfile.swift b/Passepartout/Sources/Model/ConnectionProfile.swift index 7ee7b148..ce52d784 100644 --- a/Passepartout/Sources/Model/ConnectionProfile.swift +++ b/Passepartout/Sources/Model/ConnectionProfile.swift @@ -83,6 +83,6 @@ extension ConnectionProfile { extension ConnectionProfile { var description: String { - return "[\(context):\(id)]" + return "(\(context),\(id))" } } diff --git a/Passepartout/Sources/Model/ConnectionService.swift b/Passepartout/Sources/Model/ConnectionService.swift index 790fc2b1..054fb23b 100644 --- a/Passepartout/Sources/Model/ConnectionService.swift +++ b/Passepartout/Sources/Model/ConnectionService.swift @@ -35,7 +35,7 @@ protocol ConnectionServiceDelegate: class { func connectionService(didRename oldProfile: ConnectionProfile, to newProfile: ConnectionProfile) - func connectionService(didRemoveProfileWithKey key: ConnectionService.ProfileKey) + func connectionService(didRemoveProfileWithKey key: ProfileKey) func connectionService(willDeactivate profile: ConnectionProfile) @@ -55,40 +55,6 @@ class ConnectionService: Codable { case preferences } - struct ProfileKey: RawRepresentable, Hashable, Codable { - let context: Context - - let id: String - - init(_ context: Context, _ id: String) { - self.context = context - self.id = id - } - - init(_ profile: ConnectionProfile) { - context = profile.context - id = profile.id - } - - // MARK: RawRepresentable - - var rawValue: String { - return "\(context).\(id)" - } - - init?(rawValue: String) { - let comps = rawValue.components(separatedBy: ".") - guard comps.count == 2 else { - return nil - } - guard let context = Context(rawValue: comps[0]) else { - return nil - } - self.context = context - id = comps[1] - } - } - var directory: String? = nil var rootURL: URL { @@ -209,7 +175,7 @@ class ConnectionService: Codable { cache[key] = PlaceholderConnectionProfile(key) } } catch let e { - log.error("Could not list provider contents: \(e) (\(providersURL))") + log.warning("Could not list provider contents: \(e) (\(providersURL))") } do { let files = try fm.contentsOfDirectory(at: hostsURL, includingPropertiesForKeys: nil, options: []) @@ -222,7 +188,7 @@ class ConnectionService: Codable { cache[key] = PlaceholderConnectionProfile(key) } } catch let e { - log.error("Could not list host contents: \(e) (\(hostsURL))") + log.warning("Could not list host contents: \(e) (\(hostsURL))") } } @@ -538,38 +504,3 @@ class ConnectionService: Codable { // defaults.removeObject(forKey: Keys.vpnLog) // } } - -private class PlaceholderConnectionProfile: ConnectionProfile { - let context: Context - - let id: String - - var username: String? = nil - - var requiresCredentials: Bool = false - - func generate(from configuration: TunnelKitProvider.Configuration, preferences: Preferences) throws -> TunnelKitProvider.Configuration { - fatalError("Generating configuration from a PlaceholderConnectionProfile") - } - - func with(newId: String) -> ConnectionProfile { - return PlaceholderConnectionProfile(ConnectionService.ProfileKey(context, newId)) - } - - var mainAddress: String = "" - - var addresses: [String] = [] - - var protocols: [TunnelKitProvider.EndpointProtocol] = [] - - var canCustomizeEndpoint: Bool = false - - var customAddress: String? - - var customProtocol: TunnelKitProvider.EndpointProtocol? - - init(_ key: ConnectionService.ProfileKey) { - self.context = key.context - self.id = key.id - } -} diff --git a/Passepartout/Sources/Model/Profiles/PlaceholderConnectionProfile.swift b/Passepartout/Sources/Model/Profiles/PlaceholderConnectionProfile.swift new file mode 100644 index 00000000..f2db7645 --- /dev/null +++ b/Passepartout/Sources/Model/Profiles/PlaceholderConnectionProfile.swift @@ -0,0 +1,67 @@ +// +// PlaceholderConnectionProfile.swift +// Passepartout +// +// Created by Davide De Rosa on 11/6/18. +// Copyright (c) 2018 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Foundation +import TunnelKit + +class PlaceholderConnectionProfile: ConnectionProfile { + let context: Context + + let id: String + + var username: String? = nil + + var requiresCredentials: Bool = false + + func generate(from configuration: TunnelKitProvider.Configuration, preferences: Preferences) throws -> TunnelKitProvider.Configuration { + fatalError("Generating configuration from a PlaceholderConnectionProfile") + } + + func with(newId: String) -> ConnectionProfile { + return PlaceholderConnectionProfile(context, newId) + } + + var mainAddress: String = "" + + var addresses: [String] = [] + + var protocols: [TunnelKitProvider.EndpointProtocol] = [] + + var canCustomizeEndpoint: Bool = false + + var customAddress: String? + + var customProtocol: TunnelKitProvider.EndpointProtocol? + + init(_ context: Context, _ id: String) { + self.context = context + self.id = id + } + + init(_ key: ProfileKey) { + context = key.context + id = key.id + } +} diff --git a/Passepartout/Sources/Model/Profiles/ProfileKey.swift b/Passepartout/Sources/Model/Profiles/ProfileKey.swift new file mode 100644 index 00000000..4d99c62b --- /dev/null +++ b/Passepartout/Sources/Model/Profiles/ProfileKey.swift @@ -0,0 +1,60 @@ +// +// ProfileKey.swift +// Passepartout +// +// Created by Davide De Rosa on 11/6/18. +// Copyright (c) 2018 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Foundation + +struct ProfileKey: RawRepresentable, Hashable, Codable { + let context: Context + + let id: String + + init(_ context: Context, _ id: String) { + self.context = context + self.id = id + } + + init(_ profile: ConnectionProfile) { + context = profile.context + id = profile.id + } + + // MARK: RawRepresentable + + var rawValue: String { + return "\(context).\(id)" + } + + init?(rawValue: String) { + let comps = rawValue.components(separatedBy: ".") + guard comps.count == 2 else { + return nil + } + guard let context = Context(rawValue: comps[0]) else { + return nil + } + self.context = context + id = comps[1] + } +} diff --git a/Passepartout/Sources/SwiftGen+Strings.swift b/Passepartout/Sources/SwiftGen+Strings.swift index 866c6c67..01bb24dd 100644 --- a/Passepartout/Sources/SwiftGen+Strings.swift +++ b/Passepartout/Sources/SwiftGen+Strings.swift @@ -245,7 +245,7 @@ internal enum L10n { internal static let ok = L10n.tr("Localizable", "global.ok") internal enum Host { internal enum TitleInput { - /// Legal characters are alphanumerics plus dash (-), underscore (_) and dot (.). + /// Acceptable characters are alphanumerics plus dash "-", underscore "_" and dot ".". internal static let message = L10n.tr("Localizable", "global.host.title_input.message") /// My Profile internal static let placeholder = L10n.tr("Localizable", "global.host.title_input.placeholder") diff --git a/PassepartoutTests-iOS/ConnectionServiceTests.swift b/PassepartoutTests-iOS/ConnectionServiceTests.swift index aefc43fb..d97929cf 100644 --- a/PassepartoutTests-iOS/ConnectionServiceTests.swift +++ b/PassepartoutTests-iOS/ConnectionServiceTests.swift @@ -25,7 +25,7 @@ import XCTest import TunnelKit -@testable import Passepartout_iOS +@testable import Passepartout class ConnectionServiceTests: XCTestCase { let url = Bundle(for: ConnectionServiceTests.self).url(forResource: "ConnectionService", withExtension: "json")! diff --git a/PassepartoutTests-iOS/FileConfigurationTests.swift b/PassepartoutTests-iOS/FileConfigurationTests.swift index ed66541c..3b25f300 100644 --- a/PassepartoutTests-iOS/FileConfigurationTests.swift +++ b/PassepartoutTests-iOS/FileConfigurationTests.swift @@ -25,7 +25,7 @@ import XCTest import TunnelKit -@testable import Passepartout_iOS +@testable import Passepartout class FileConfigurationTests: XCTestCase { override func setUp() { diff --git a/PassepartoutTests-iOS/InfrastructureTests.swift b/PassepartoutTests-iOS/InfrastructureTests.swift index f2db6323..5bf652e9 100644 --- a/PassepartoutTests-iOS/InfrastructureTests.swift +++ b/PassepartoutTests-iOS/InfrastructureTests.swift @@ -24,7 +24,7 @@ // import XCTest -@testable import Passepartout_iOS +@testable import Passepartout import TunnelKit class InfrastructureTests: XCTestCase { diff --git a/README.md b/README.md index c109795e..7c4118fd 100644 --- a/README.md +++ b/README.md @@ -100,7 +100,7 @@ It's highly recommended to use the Git and Ruby packages provided by [Homebrew][ Download the app codebase locally: - $ git clone https://github.com/keeshux/passepartout-ios.git + $ git clone https://github.com/passepartoutvpn/passepartout-ios.git Assuming you have a [working CocoaPods environment][dep-cocoapods], setting up the app workspace only requires installing the pod dependencies: @@ -145,7 +145,7 @@ Website: [passepartoutvpn.app][about-website] [openvpn]: https://openvpn.net/index.php/open-source/overview.html -[app-api]: https://github.com/keeshux/passepartout-api +[app-api]: https://github.com/passepartoutvpn/passepartout-api [app-net-pia]: https://www.privateinternetaccess.com [dep-cocoapods]: https://guides.cocoapods.org/using/getting-started.html