diff --git a/Passepartout-iOS-Tunnel/Tunnel.entitlements b/Passepartout-iOS-Tunnel/Tunnel.entitlements
index ad9e428b..c2da4ee5 100644
--- a/Passepartout-iOS-Tunnel/Tunnel.entitlements
+++ b/Passepartout-iOS-Tunnel/Tunnel.entitlements
@@ -8,7 +8,7 @@
com.apple.security.application-groups
- group.com.algoritmico.Passepartout
+ group.$(CFG_GROUP_ID)
diff --git a/Passepartout-iOS/Config.xcconfig b/Passepartout-iOS/Config.xcconfig
new file mode 100644
index 00000000..6b0607df
--- /dev/null
+++ b/Passepartout-iOS/Config.xcconfig
@@ -0,0 +1,32 @@
+//
+// Config.xcconfig
+// Passepartout
+//
+// Created by Davide De Rosa on 5/24/19.
+// Copyright (c) 2019 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 .
+//
+
+// Configuration settings file format documentation can be found at:
+// https://help.apple.com/xcode/#/dev745c5c974
+
+CFG_TEAM_ID = DTDYD63ZX9
+CFG_APP_ID = com.algoritmico.ios.Passepartout
+CFG_GROUP_ID = com.algoritmico.Passepartout
+CFG_APPSTORE_ID = 1433648537
diff --git a/Passepartout-iOS/Info.plist b/Passepartout-iOS/Info.plist
index d521790a..a930e4a9 100644
--- a/Passepartout-iOS/Info.plist
+++ b/Passepartout-iOS/Info.plist
@@ -105,5 +105,12 @@
+ com.algoritmico.Passepartout.config
+
+ group_id
+ group.$(CFG_GROUP_ID)
+ appstore_id
+ $(CFG_APPSTORE_ID)
+
diff --git a/Passepartout-iOS/Passepartout.entitlements b/Passepartout-iOS/Passepartout.entitlements
index 20e38ffd..25d1fc93 100644
--- a/Passepartout-iOS/Passepartout.entitlements
+++ b/Passepartout-iOS/Passepartout.entitlements
@@ -12,7 +12,7 @@
com.apple.security.application-groups
- group.com.algoritmico.Passepartout
+ group.$(CFG_GROUP_ID)
diff --git a/Passepartout-iOS/Scenes/Organizer/OrganizerViewController.swift b/Passepartout-iOS/Scenes/Organizer/OrganizerViewController.swift
index 79bdc85e..e3371a90 100644
--- a/Passepartout-iOS/Scenes/Organizer/OrganizerViewController.swift
+++ b/Passepartout-iOS/Scenes/Organizer/OrganizerViewController.swift
@@ -319,7 +319,7 @@ class OrganizerViewController: UITableViewController, TableModelHost {
}
private func writeReview() {
- let url = AppConstants.URLs.review(withId: GroupConstants.App.appId)
+ let url = AppConstants.URLs.review(withId: AppConstants.App.appStoreId)
UIApplication.shared.open(url, options: [:], completionHandler: nil)
}
diff --git a/Passepartout.xcodeproj/project.pbxproj b/Passepartout.xcodeproj/project.pbxproj
index 0f71b737..f706b326 100644
--- a/Passepartout.xcodeproj/project.pbxproj
+++ b/Passepartout.xcodeproj/project.pbxproj
@@ -185,6 +185,7 @@
0E158AD920E11B0B00C85A82 /* EndpointViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EndpointViewController.swift; sourceTree = ""; };
0E1D72B1213BFFCF00BA1586 /* ProviderPresetViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProviderPresetViewController.swift; sourceTree = ""; };
0E1D72B3213C118500BA1586 /* ConfigurationViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigurationViewController.swift; sourceTree = ""; };
+ 0E23B4A12298559800304C30 /* Config.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Config.xcconfig; sourceTree = ""; };
0E242735225944060064A1A3 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Intents.strings; sourceTree = ""; };
0E24273B225950450064A1A3 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/About.storyboard; sourceTree = ""; };
0E24273F225951B00064A1A3 /* InApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InApp.swift; sourceTree = ""; };
@@ -461,6 +462,7 @@
0E1066CA20E0F85C004F98B7 /* Cells */,
0ECEE44C20E1120F00A6BB43 /* Tables */,
0EDE8DF120C93ED8004C739C /* Scenes */,
+ 0E23B4A12298559800304C30 /* Config.xcconfig */,
0EDE8DE220C86A13004C739C /* Passepartout.entitlements */,
0E57F63B20C83FC5008323CF /* AppDelegate.swift */,
0E24273C225950450064A1A3 /* About.storyboard */,
@@ -1341,6 +1343,7 @@
};
0E57F65320C83FC7008323CF /* Debug */ = {
isa = XCBuildConfiguration;
+ baseConfigurationReference = 0E23B4A12298559800304C30 /* Config.xcconfig */;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = "$(ARCHS_STANDARD_64_BIT)";
@@ -1407,6 +1410,7 @@
};
0E57F65420C83FC7008323CF /* Release */ = {
isa = XCBuildConfiguration;
+ baseConfigurationReference = 0E23B4A12298559800304C30 /* Config.xcconfig */;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = "$(ARCHS_STANDARD_64_BIT)";
@@ -1480,7 +1484,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
- PRODUCT_BUNDLE_IDENTIFIER = com.algoritmico.ios.Passepartout;
+ PRODUCT_BUNDLE_IDENTIFIER = "$(CFG_APP_ID)";
PRODUCT_NAME = Passepartout;
PROVISIONING_PROFILE_SPECIFIER = "match Development com.algoritmico.ios.Passepartout";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
@@ -1504,7 +1508,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
- PRODUCT_BUNDLE_IDENTIFIER = com.algoritmico.ios.Passepartout;
+ PRODUCT_BUNDLE_IDENTIFIER = "$(CFG_APP_ID)";
PRODUCT_NAME = Passepartout;
PROVISIONING_PROFILE_SPECIFIER = "match Development com.algoritmico.ios.Passepartout";
SWIFT_VERSION = 5.0;
@@ -1527,7 +1531,7 @@
"@executable_path/../../Frameworks",
);
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
- PRODUCT_BUNDLE_IDENTIFIER = com.algoritmico.ios.Passepartout.Tunnel;
+ PRODUCT_BUNDLE_IDENTIFIER = "$(CFG_APP_ID).Tunnel";
PRODUCT_NAME = "Passepartout-Tunnel";
PROVISIONING_PROFILE_SPECIFIER = "match Development com.algoritmico.ios.Passepartout.Tunnel";
SKIP_INSTALL = YES;
@@ -1550,7 +1554,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
- PRODUCT_BUNDLE_IDENTIFIER = com.algoritmico.ios.Passepartout.Tunnel;
+ PRODUCT_BUNDLE_IDENTIFIER = "$(CFG_APP_ID).Tunnel";
PRODUCT_NAME = "Passepartout-Tunnel";
PROVISIONING_PROFILE_SPECIFIER = "match Development com.algoritmico.ios.Passepartout.Tunnel";
SKIP_INSTALL = YES;
diff --git a/Passepartout/Sources/AppConstants.swift b/Passepartout/Sources/AppConstants.swift
index 2ecdc4e7..1312436d 100644
--- a/Passepartout/Sources/AppConstants.swift
+++ b/Passepartout/Sources/AppConstants.swift
@@ -28,6 +28,22 @@ import TunnelKit
import SwiftyBeaver
public class AppConstants {
+ public class App {
+ public static let appStoreId: String = {
+ guard let identifier = GroupConstants.App.config["appstore_id"] as? String else {
+ fatalError("Missing appstore_id from Info.plist config")
+ }
+ return identifier
+ }()
+
+ public static let tunnelBundleId: String = {
+ guard let identifier = Bundle.main.infoDictionary?[kCFBundleIdentifierKey as String] as? String else {
+ fatalError("Missing kCFBundleIdentifierKey from Info.plist")
+ }
+ return "\(identifier).Tunnel"
+ }()
+ }
+
public class Flags {
public static let isBeta = false
}
diff --git a/Passepartout/Sources/GroupConstants.swift b/Passepartout/Sources/GroupConstants.swift
index a6120a51..4061ce1a 100644
--- a/Passepartout/Sources/GroupConstants.swift
+++ b/Passepartout/Sources/GroupConstants.swift
@@ -39,23 +39,23 @@ public class GroupConstants {
public static let buildNumber = Int(Bundle.main.infoDictionary![kCFBundleVersionKey as String] as! String)!
public static let versionString = "\(versionNumber) (\(buildNumber))"
-
- public static let teamId = "DTDYD63ZX9"
- public static let appId = "1433648537"
+ public static let config: [String: Any] = {
+ guard let cfg = Bundle.main.infoDictionary?["com.algoritmico.Passepartout.config"] as? [String: Any] else {
+ fatalError("Missing app config from Info.plist")
+ }
+ return cfg
+ }()
- #if os(iOS)
- public static let appGroup = "group.com.algoritmico.Passepartout"
-
- public static let tunnelIdentifier = "com.algoritmico.ios.Passepartout.Tunnel"
- #else
- public static let appGroup = "\(teamId).group.com.algoritmico.Passepartout"
-
- public static let tunnelIdentifier = "com.algoritmico.macos.Passepartout.Tunnel"
- #endif
+ public static let groupId: String = {
+ guard let identifier = config["group_id"] as? String else {
+ fatalError("Missing group_id from Info.plist config")
+ }
+ return identifier
+ }()
private static var containerURL: URL {
- guard let url = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: appGroup) else {
+ guard let url = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: groupId) else {
print("Unable to access App Group container")
return FileManager.default.userURL(for: .documentDirectory, appending: nil)
}
diff --git a/Passepartout/Sources/Model/ConnectionService.swift b/Passepartout/Sources/Model/ConnectionService.swift
index 5f553c34..c1c52761 100644
--- a/Passepartout/Sources/Model/ConnectionService.swift
+++ b/Passepartout/Sources/Model/ConnectionService.swift
@@ -539,7 +539,7 @@ public class ConnectionService: Codable {
}
let protocolConfiguration = try cfg.generatedTunnelProtocol(
- withBundleIdentifier: GroupConstants.App.tunnelIdentifier,
+ withBundleIdentifier: AppConstants.App.tunnelBundleId,
appGroup: appGroup,
credentials: creds
)
diff --git a/Passepartout/Sources/Model/TransientStore.swift b/Passepartout/Sources/Model/TransientStore.swift
index 3ec4c3cc..afda9a0e 100644
--- a/Passepartout/Sources/Model/TransientStore.swift
+++ b/Passepartout/Sources/Model/TransientStore.swift
@@ -119,7 +119,7 @@ public class TransientStore {
} catch let e {
log.error("Could not decode service: \(e)")
service = ConnectionService(
- withAppGroup: GroupConstants.App.appGroup,
+ withAppGroup: GroupConstants.App.groupId,
baseConfiguration: cfg
)
diff --git a/Passepartout/Sources/VPN/VPN.swift b/Passepartout/Sources/VPN/VPN.swift
index 184cca7b..443494c2 100644
--- a/Passepartout/Sources/VPN/VPN.swift
+++ b/Passepartout/Sources/VPN/VPN.swift
@@ -29,6 +29,6 @@ public class VPN {
#if targetEnvironment(simulator)
public static let shared = MockVPNProvider()
#else
- public static let shared = StandardVPNProvider(bundleIdentifier: GroupConstants.App.tunnelIdentifier)
+ public static let shared = StandardVPNProvider(bundleIdentifier: AppConstants.App.tunnelBundleId)
#endif
}
diff --git a/README.md b/README.md
index 300c37a3..7a79138e 100644
--- a/README.md
+++ b/README.md
@@ -108,12 +108,12 @@ For the VPN to work properly, the app requires:
both in the main app and the tunnel extension target.
-Make sure to also update the following constants in `Passepartout/Sources/GroupConstants.swift` according to your developer account and your target bundle identifiers:
+Make sure to update `Passepartout-iOS/Config.xcconfig` according to your developer account and your identifiers:
- public static let teamId
- public static let appId
- public static let appGroup
- public static let tunnelIdentifier
+ CFG_TEAM_ID = A1B2C3D4E5
+ CFG_APP_ID = com.example.ios.MyApp
+ CFG_GROUP_ID = com.example.MyAppGroup // omit the "group." prefix
+ CFG_APPSTORE_ID = 1234567890
## License