Repository: SideStore/StosVPN
Branch: main
Commit: 010bc141e6c2
Files: 49
Total size: 127.9 KB
Directory structure:
gitextract_se04d3hj/
├── .github/
│ └── workflows/
│ └── build.yml
├── .gitignore
├── AppIcon.icon/
│ └── icon.json
├── Build.xcconfig
├── CodeSigning.xcconfig.sample
├── LICENSE
├── LICENSE-old
├── README.md
├── StosVPN/
│ ├── Assets.xcassets/
│ │ ├── AccentColor.colorset/
│ │ │ └── Contents.json
│ │ ├── AppIcon.appiconset/
│ │ │ └── Contents.json
│ │ ├── AppIcon.brandassets/
│ │ │ ├── App Icon - App Store.imagestack/
│ │ │ │ ├── Back.imagestacklayer/
│ │ │ │ │ ├── Content.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── Contents.json
│ │ │ │ ├── Front.imagestacklayer/
│ │ │ │ │ ├── Content.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ └── Contents.json
│ │ │ │ └── Middle.imagestacklayer/
│ │ │ │ ├── Content.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ └── Contents.json
│ │ │ ├── AppIcon.imagestack/
│ │ │ │ ├── Back.imagestacklayer/
│ │ │ │ │ ├── Content.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── Contents.json
│ │ │ │ ├── Front.imagestacklayer/
│ │ │ │ │ ├── Content.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ └── Contents.json
│ │ │ │ └── Middle.imagestacklayer/
│ │ │ │ ├── Content.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ └── Contents.json
│ │ │ ├── Contents.json
│ │ │ ├── Top Shelf Image Wide.imageset/
│ │ │ │ └── Contents.json
│ │ │ └── Top Shelf Image.imageset/
│ │ │ └── Contents.json
│ │ └── Contents.json
│ ├── ContentView.swift
│ ├── Info.plist
│ ├── Localization/
│ │ ├── en.lproj/
│ │ │ └── Localizable.strings
│ │ ├── es.lproj/
│ │ │ └── Localizable.strings
│ │ ├── it.lproj/
│ │ │ └── Localizable.strings
│ │ └── pl.lproj/
│ │ └── Localizable.strings
│ ├── Preview Content/
│ │ └── Preview Assets.xcassets/
│ │ └── Contents.json
│ ├── StosVPN-Bridging-Header.h
│ ├── StosVPN.entitlements
│ └── StosVPNApp.swift
├── StosVPN.xcodeproj/
│ ├── project.pbxproj
│ ├── project.xcworkspace/
│ │ ├── contents.xcworkspacedata
│ │ ├── xcshareddata/
│ │ │ └── swiftpm/
│ │ │ └── Package.resolved
│ │ └── xcuserdata/
│ │ └── stossy11.xcuserdatad/
│ │ └── UserInterfaceState.xcuserstate
│ ├── xcshareddata/
│ │ └── xcschemes/
│ │ ├── StosVPN.xcscheme
│ │ └── TunnelProv.xcscheme
│ └── xcuserdata/
│ └── stossy11.xcuserdatad/
│ ├── xcdebugger/
│ │ └── Breakpoints_v2.xcbkptlist
│ └── xcschemes/
│ └── xcschememanagement.plist
└── TunnelProv/
├── Info.plist
├── PacketTunnelProvider.swift
└── TunnelProv.entitlements
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/workflows/build.yml
================================================
name: Build IPA with Fake Signing
on:
push:
branches: [main] # Or your default branch
workflow_dispatch: # Allows manual triggering
jobs:
build:
runs-on: macos-latest # Use the latest macOS runner
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install ldid
run: brew install ldid
- name: Select Xcode version
run: sudo xcode-select -s /Applications/Xcode_16.2.app
- name: Build Xcode Archive
run: |
xcodebuild archive \
-project StosVPN.xcodeproj \
-scheme StosVPN \
-destination 'generic/platform=iOS' \
-archivePath build/StosVPN.xcarchive \
CODE_SIGN_IDENTITY="" \
CODE_SIGNING_REQUIRED=NO \
CODE_SIGNING_ALLOWED=NO
- name: Create Payload directory
run: mkdir -p Payload
- name: Copy App to Payload
run: cp -R build/StosVPN.xcarchive/Products/Applications/StosVPN.app Payload/StosVPN.app
- name: Find and Sign App Extension
run: |
APPEX_PATH=$(find Payload/StosVPN.app/PlugIns -name "*.appex" | head -n 1)
if [ -z "$APPEX_PATH" ]; then
echo "Error: App Extension (.appex) not found in PlugIns directory."
exit 1
fi
echo "Found App Extension at: $APPEX_PATH"
# Use the specific entitlements for the extension
ldid -S"${GITHUB_WORKSPACE}/TunnelProv/TunnelProv.entitlements" "$APPEX_PATH/$(basename "$APPEX_PATH" .appex)"
echo "Signed App Extension."
- name: Sign Main App Bundle
run: |
APP_BINARY_PATH="Payload/StosVPN.app/StosVPN"
# Use the specific entitlements for the main app
ldid -S"${GITHUB_WORKSPACE}/StosVPN/StosVPN.entitlements" "$APP_BINARY_PATH"
echo "Signed Main App Bundle."
- name: Create IPA
run: |
zip -r ./StosVPN-fakesigned.ipa Payload
- name: Upload IPA Artifact
uses: actions/upload-artifact@v4
with:
name: StosVPN-IPA.ipa
path: StosVPN-fakesigned.ipa
================================================
FILE: .gitignore
================================================
CodeSigning.xcconfig
*.ipa
/build
**/.DS_Store
================================================
FILE: AppIcon.icon/icon.json
================================================
{
"fill" : {
"automatic-gradient" : "display-p3:0.23889,0.54053,0.96826,1.00000"
},
"groups" : [
{
"layers" : [
{
"image-name" : "StosPlug.svg",
"name" : "StosPlug"
}
],
"shadow" : {
"kind" : "neutral",
"opacity" : 0.5
},
"translucency-specializations" : [
{
"appearance" : "tinted",
"value" : {
"enabled" : true,
"value" : 0.7
}
}
]
}
],
"supported-platforms" : {
"circles" : [
"watchOS"
],
"squares" : "shared"
}
}
================================================
FILE: Build.xcconfig
================================================
// Configuration settings file format documentation can be found at:
// https://help.apple.com/xcode/#/dev745c5c974
MARKETING_VERSION = 1.2.1
CURRENT_PROJECT_VERSION = 1
// Vars to be overwritten by `CodeSigning.xcconfig` if exists
DEVELOPMENT_TEAM = 95J8WZ4TN8
ORG_IDENTIFIER = com.stossy11
// Codesigning settings defined optionally, see `CodeSigning.xcconfig.example`
#include? "CodeSigning.xcconfig"
ORG_PREFIX = $(ORG_IDENTIFIER)
PRODUCT_BUNDLE_IDENTIFIER = $(ORG_PREFIX).StosVPN
TUNNEL_NAME = TunnelProv
TUNNEL_BUNDLE_IDENTIFIER = $(PRODUCT_BUNDLE_IDENTIFIER).$(TUNNEL_NAME)
// Mute warnings about duplicate classes in AuthKit and AuthUIKit
DEBUG_DUPLICATE_CLASSES = NO
================================================
FILE: CodeSigning.xcconfig.sample
================================================
// Your Team ID.
// If you have a paid Apple Developer account, you can find your Team ID at
// https://developer.apple.com/account/#/membership
DEVELOPMENT_TEAM = 95J8WZ4TN8
// Prefix of unique bundle IDs registered to you in Apple Developer Portal.
// You need to register:
// - com.myuniquename.StosVPN
ORG_IDENTIFIER = com.stossy11
// Name of the iOS development signing certificate, you probably do not need
// to change this.
CODE_SIGN_IDENTITY_IOS = Apple Development
// Name of the iOS development signing certificate, you probably do not need
// to change this.
CODE_SIGN_IDENTITY_TVOS = Apple Development
// The values below are specific to macOS development. If you do not define
// these keys, the build will default to ad-hoc signing. You will need to
// follow `Documentation/MacDevelopment.md` to disable library verification and
// remove unsupported entitlements.
// Name of the macOS development signing certificate. Comment out this line to
// use ad-hoc signing.
CODE_SIGN_IDENTITY_MAC = Apple Development
// Create a Mac provisioning profile for com.myuniquename.UTM with the
// Hypervisor entitlements and get its UUID. If you do not have access to these
// entitlements, comment out the line and delete the following entitlements
// - com.apple.vm.device-access
// from the following file
// - Provenance/macOS.entitlements
PROVISIONING_PROFILE_SPECIFIER_MAC = 00000000-1111-2222-3333-444444444444
================================================
FILE: LICENSE
================================================
StosVPN License
Copyright (c) 2025 SideStore Team
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
**Attribution is clearly given** to the original project and author(s) in a
prominent place (e.g., README, About page, or documentation).
Any derived project **must clearly state** that it is **based on** or **uses
code from** the original project.
Redistribution, rebranding, or publishing of the **entire project** (or a
substantially similar copy) under the same or similar name or branding,
**without explicit written permission**, is **prohibited**.
This clause is intended to prevent unauthorized re-uploads, clones, or
misrepresentation of the original work.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: LICENSE-old
================================================
MIT License
Copyright (c) 2025 SideStore Team
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
# StosVPN
A VPN for SideStore and StikJIT that is much more stable and supports offline JIT Enabling.
================================================
FILE: StosVPN/Assets.xcassets/AccentColor.colorset/Contents.json
================================================
{
"colors" : [
{
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
================================================
FILE: StosVPN/Assets.xcassets/AppIcon.appiconset/Contents.json
================================================
{
"images" : [
{
"filename" : "StosVPN-icon.jpg",
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "tinted"
}
],
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
================================================
FILE: StosVPN/Assets.xcassets/AppIcon.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Content.imageset/Contents.json
================================================
{
"images" : [
{
"filename" : "1280x768 copy 3.jpeg",
"idiom" : "tv"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
================================================
FILE: StosVPN/Assets.xcassets/AppIcon.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Contents.json
================================================
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
================================================
FILE: StosVPN/Assets.xcassets/AppIcon.brandassets/App Icon - App Store.imagestack/Contents.json
================================================
{
"info" : {
"author" : "xcode",
"version" : 1
},
"layers" : [
{
"filename" : "Front.imagestacklayer"
},
{
"filename" : "Middle.imagestacklayer"
},
{
"filename" : "Back.imagestacklayer"
}
]
}
================================================
FILE: StosVPN/Assets.xcassets/AppIcon.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Content.imageset/Contents.json
================================================
{
"images" : [
{
"filename" : "1280x768.png",
"idiom" : "tv"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
================================================
FILE: StosVPN/Assets.xcassets/AppIcon.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Contents.json
================================================
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
================================================
FILE: StosVPN/Assets.xcassets/AppIcon.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json
================================================
{
"images" : [
{
"filename" : "1280x768 copy 3.jpeg",
"idiom" : "tv"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
================================================
FILE: StosVPN/Assets.xcassets/AppIcon.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Contents.json
================================================
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
================================================
FILE: StosVPN/Assets.xcassets/AppIcon.brandassets/AppIcon.imagestack/Back.imagestacklayer/Content.imageset/Contents.json
================================================
{
"images" : [
{
"filename" : "Content.png",
"idiom" : "tv",
"scale" : "1x"
},
{
"filename" : "Content@2x.png",
"idiom" : "tv",
"scale" : "2x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
================================================
FILE: StosVPN/Assets.xcassets/AppIcon.brandassets/AppIcon.imagestack/Back.imagestacklayer/Contents.json
================================================
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
================================================
FILE: StosVPN/Assets.xcassets/AppIcon.brandassets/AppIcon.imagestack/Contents.json
================================================
{
"info" : {
"author" : "xcode",
"version" : 1
},
"layers" : [
{
"filename" : "Front.imagestacklayer"
},
{
"filename" : "Middle.imagestacklayer"
},
{
"filename" : "Back.imagestacklayer"
}
]
}
================================================
FILE: StosVPN/Assets.xcassets/AppIcon.brandassets/AppIcon.imagestack/Front.imagestacklayer/Content.imageset/Contents.json
================================================
{
"images" : [
{
"filename" : "cool.png",
"idiom" : "tv",
"scale" : "1x"
},
{
"filename" : "cool 1.png",
"idiom" : "tv",
"scale" : "2x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
================================================
FILE: StosVPN/Assets.xcassets/AppIcon.brandassets/AppIcon.imagestack/Front.imagestacklayer/Contents.json
================================================
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
================================================
FILE: StosVPN/Assets.xcassets/AppIcon.brandassets/AppIcon.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json
================================================
{
"images" : [
{
"filename" : "Content.png",
"idiom" : "tv",
"scale" : "1x"
},
{
"filename" : "Content@2x.png",
"idiom" : "tv",
"scale" : "2x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
================================================
FILE: StosVPN/Assets.xcassets/AppIcon.brandassets/AppIcon.imagestack/Middle.imagestacklayer/Contents.json
================================================
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
================================================
FILE: StosVPN/Assets.xcassets/AppIcon.brandassets/Contents.json
================================================
{
"assets" : [
{
"filename" : "App Icon - App Store.imagestack",
"idiom" : "tv",
"role" : "primary-app-icon",
"size" : "1280x768"
},
{
"filename" : "AppIcon.imagestack",
"idiom" : "tv",
"role" : "primary-app-icon",
"size" : "400x240"
},
{
"filename" : "Top Shelf Image Wide.imageset",
"idiom" : "tv",
"role" : "top-shelf-image-wide",
"size" : "2320x720"
},
{
"filename" : "Top Shelf Image.imageset",
"idiom" : "tv",
"role" : "top-shelf-image",
"size" : "1920x720"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
================================================
FILE: StosVPN/Assets.xcassets/AppIcon.brandassets/Top Shelf Image Wide.imageset/Contents.json
================================================
{
"images" : [
{
"filename" : "1280x768 copy 4.jpeg",
"idiom" : "tv",
"scale" : "1x"
},
{
"filename" : "1280x768 copy 4 2.jpeg",
"idiom" : "tv",
"scale" : "2x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
================================================
FILE: StosVPN/Assets.xcassets/AppIcon.brandassets/Top Shelf Image.imageset/Contents.json
================================================
{
"images" : [
{
"filename" : "1280x768 copy 4.jpeg",
"idiom" : "tv",
"scale" : "1x"
},
{
"filename" : "1280x768 copy 5.jpeg",
"idiom" : "tv",
"scale" : "2x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
================================================
FILE: StosVPN/Assets.xcassets/Contents.json
================================================
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
================================================
FILE: StosVPN/ContentView.swift
================================================
//
// ContentView.swift
// StosVPN
//
// Created by Stossy11 on 28/03/2025.
//
import SwiftUI
import Foundation
import NetworkExtension
import NavigationBackport
extension Bundle {
var shortVersion: String { object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String ?? "0.0.0" }
var tunnelBundleID: String { bundleIdentifier!.appending(".TunnelProv") }
}
// MARK: - Logging Utility
class VPNLogger: ObservableObject {
@Published var logs: [String] = []
static var shared = VPNLogger()
private init() {}
func log(_ message: Any, file: String = #file, function: String = #function, line: Int = #line) {
#if DEBUG
let fileName = (file as NSString).lastPathComponent
print("[\(fileName):\(line)] \(function): \(message)")
#endif
logs.append("\(message)")
}
}
// MARK: - Tunnel Manager
class TunnelManager: ObservableObject {
@Published var hasLocalDeviceSupport = false
@Published var tunnelStatus: TunnelStatus = .disconnected
static var shared = TunnelManager()
@Published var waitingOnSettings: Bool = false
@Published var vpnManager: NETunnelProviderManager?
private var vpnObserver: NSObjectProtocol?
private var isProcessingStatusChange = false
private var tunnelDeviceIp: String {
UserDefaults.standard.string(forKey: "TunnelDeviceIP") ?? "10.7.0.0"
}
private var tunnelFakeIp: String {
UserDefaults.standard.string(forKey: "TunnelFakeIP") ?? "10.7.0.1"
}
private var tunnelSubnetMask: String {
UserDefaults.standard.string(forKey: "TunnelSubnetMask") ?? "255.255.255.0"
}
private var tunnelBundleId: String {
Bundle.main.bundleIdentifier!.appending(".TunnelProv")
}
enum TunnelStatus {
case disconnected
case connecting
case connected
case disconnecting
case error
var color: Color {
switch self {
case .disconnected: return .gray
case .connecting: return .orange
case .connected: return .green
case .disconnecting: return .orange
case .error: return .red
}
}
var systemImage: String {
switch self {
case .disconnected: return "network.slash"
case .connecting: return "network.badge.shield.half.filled"
case .connected: return "checkmark.shield.fill"
case .disconnecting: return "network.badge.shield.half.filled"
case .error: return "exclamationmark.shield.fill"
}
}
var localizedTitle: LocalizedStringKey {
switch self {
case .disconnected:
return "disconnected"
case .connecting:
return "connecting"
case .connected:
return "connected"
case .disconnecting:
return "disconnecting"
case .error:
return "error"
}
}
}
private init() {
setupStatusObserver()
loadTunnelPreferences()
}
// MARK: - Private Methods
private func loadTunnelPreferences() {
NETunnelProviderManager.loadAllFromPreferences { [weak self] (managers, error) in
guard let self = self else { return }
DispatchQueue.main.async {
if let error = error {
VPNLogger.shared.log("Error loading preferences: \(error.localizedDescription)")
self.tunnelStatus = .error
self.waitingOnSettings = true
return
}
self.hasLocalDeviceSupport = true
self.waitingOnSettings = true
if let managers = managers, !managers.isEmpty {
let stosManagers = managers.filter { manager in
guard let proto = manager.protocolConfiguration as? NETunnelProviderProtocol else {
return false
}
return proto.providerBundleIdentifier == self.tunnelBundleId
}
if !stosManagers.isEmpty {
if stosManagers.count > 1 {
self.cleanupDuplicateManagers(stosManagers)
} else if let manager = stosManagers.first {
self.vpnManager = manager
let currentStatus = manager.connection.status
VPNLogger.shared.log("Loaded existing StosVPN tunnel configuration with status: \(currentStatus.rawValue)")
self.updateTunnelStatus(from: currentStatus)
}
} else {
VPNLogger.shared.log("No StosVPN tunnel configuration found")
}
} else {
VPNLogger.shared.log("No existing tunnel configurations found")
}
}
}
}
private func cleanupDuplicateManagers(_ managers: [NETunnelProviderManager]) {
VPNLogger.shared.log("Found \(managers.count) StosVPN configurations. Cleaning up duplicates...")
let activeManager = managers.first {
$0.connection.status == .connected || $0.connection.status == .connecting
}
let managerToKeep = activeManager ?? managers.first!
DispatchQueue.main.async { [weak self] in
self?.vpnManager = managerToKeep
self?.updateTunnelStatus(from: managerToKeep.connection.status)
}
for manager in managers where manager != managerToKeep {
manager.removeFromPreferences { error in
if let error = error {
VPNLogger.shared.log("Error removing duplicate VPN: \(error.localizedDescription)")
} else {
VPNLogger.shared.log("Successfully removed duplicate VPN configuration")
}
}
}
}
private func setupStatusObserver() {
vpnObserver = NotificationCenter.default.addObserver(
forName: .NEVPNStatusDidChange,
object: nil,
queue: .main
) { [weak self] notification in
guard let self = self else { return }
guard let connection = notification.object as? NEVPNConnection else { return }
VPNLogger.shared.log("VPN Status notification received: \(connection.status.rawValue)")
// Update status immediately if it's our manager
if let manager = self.vpnManager, connection == manager.connection {
self.updateTunnelStatus(from: connection.status)
}
self.handleVPNStatusChange(notification: notification)
}
}
private func updateTunnelStatus(from connectionStatus: NEVPNStatus) {
let newStatus: TunnelStatus
switch connectionStatus {
case .invalid, .disconnected:
newStatus = .disconnected
case .connecting:
newStatus = .connecting
case .connected:
newStatus = .connected
case .disconnecting:
newStatus = .disconnecting
case .reasserting:
newStatus = .connecting
@unknown default:
newStatus = .error
}
DispatchQueue.main.async { [weak self] in
guard let self = self else { return }
if self.tunnelStatus != newStatus {
VPNLogger.shared.log("StosVPN status updated from \(self.tunnelStatus) to \(newStatus)")
}
self.tunnelStatus = newStatus
}
}
private func createStosVPNConfiguration(completion: @escaping (NETunnelProviderManager?) -> Void) {
NETunnelProviderManager.loadAllFromPreferences { [weak self] (managers, error) in
guard let self = self else {
completion(nil)
return
}
if let error = error {
VPNLogger.shared.log("Error checking existing VPN configurations: \(error.localizedDescription)")
completion(nil)
return
}
if let managers = managers {
let stosManagers = managers.filter { manager in
guard let proto = manager.protocolConfiguration as? NETunnelProviderProtocol else {
return false
}
return proto.providerBundleIdentifier == self.tunnelBundleId
}
if let existingManager = stosManagers.first {
VPNLogger.shared.log("Found existing StosVPN configuration, using it instead of creating new one")
completion(existingManager)
return
}
}
let manager = NETunnelProviderManager()
manager.localizedDescription = "StosVPN"
let proto = NETunnelProviderProtocol()
proto.providerBundleIdentifier = self.tunnelBundleId
proto.serverAddress = "StosVPN's Local Network Tunnel"
manager.protocolConfiguration = proto
let onDemandRule = NEOnDemandRuleEvaluateConnection()
onDemandRule.interfaceTypeMatch = .any
onDemandRule.connectionRules = [NEEvaluateConnectionRule(
matchDomains: ["10.7.0.0", "10.7.0.1"],
andAction: .connectIfNeeded
)]
manager.onDemandRules = [onDemandRule]
manager.isOnDemandEnabled = true
manager.isEnabled = true
manager.saveToPreferences { error in
DispatchQueue.main.async {
if let error = error {
VPNLogger.shared.log("Error creating StosVPN configuration: \(error.localizedDescription)")
completion(nil)
return
}
VPNLogger.shared.log("StosVPN configuration created successfully")
completion(manager)
}
}
}
}
private func getActiveVPNManager(completion: @escaping (NETunnelProviderManager?) -> Void) {
NETunnelProviderManager.loadAllFromPreferences { managers, error in
if let error = error {
VPNLogger.shared.log("Error loading VPN configurations: \(error.localizedDescription)")
completion(nil)
return
}
guard let managers = managers else {
completion(nil)
return
}
let activeManager = managers.first { manager in
manager.connection.status == .connected || manager.connection.status == .connecting
}
completion(activeManager)
}
}
// MARK: - Public Methods
func toggleVPNConnection() {
if tunnelStatus == .connected || tunnelStatus == .connecting {
stopVPN()
} else {
startVPN()
}
}
func startVPN() {
if let manager = vpnManager {
let currentStatus = manager.connection.status
VPNLogger.shared.log("Current manager status: \(currentStatus.rawValue)")
if currentStatus == .connected {
VPNLogger.shared.log("VPN already connected, updating UI")
DispatchQueue.main.async { [weak self] in
self?.tunnelStatus = .connected
}
return
}
if currentStatus == .connecting {
VPNLogger.shared.log("VPN already connecting, updating UI")
DispatchQueue.main.async { [weak self] in
self?.tunnelStatus = .connecting
}
return
}
}
getActiveVPNManager { [weak self] activeManager in
guard let self = self else { return }
if let activeManager = activeManager,
(activeManager.protocolConfiguration as? NETunnelProviderProtocol)?.providerBundleIdentifier != self.tunnelBundleId {
VPNLogger.shared.log("Disconnecting existing VPN connection before starting StosVPN")
UserDefaults.standard.set(true, forKey: "ShouldStartStosVPNAfterDisconnect")
activeManager.connection.stopVPNTunnel()
return
}
self.initializeAndStartStosVPN()
}
}
private func initializeAndStartStosVPN() {
if let manager = vpnManager {
manager.loadFromPreferences { [weak self] error in
guard let self = self else { return }
if let error = error {
VPNLogger.shared.log("Error reloading manager: \(error.localizedDescription)")
self.createAndStartVPN()
return
}
self.startExistingVPN(manager: manager)
}
} else {
createAndStartVPN()
}
}
private func createAndStartVPN() {
NETunnelProviderManager.loadAllFromPreferences { [weak self] managers, error in
guard let self = self else { return }
if let error = error {
VPNLogger.shared.log("Error reloading VPN configurations: \(error.localizedDescription)")
}
if let managers = managers {
let stosManagers = managers.filter { manager in
guard let proto = manager.protocolConfiguration as? NETunnelProviderProtocol else {
return false
}
return proto.providerBundleIdentifier == self.tunnelBundleId
}
if !stosManagers.isEmpty {
DispatchQueue.main.async { [weak self] in
self?.vpnManager = stosManagers.first
}
if stosManagers.count > 1 {
self.cleanupDuplicateManagers(stosManagers)
}
if let manager = stosManagers.first {
self.startExistingVPN(manager: manager)
}
return
}
}
self.createStosVPNConfiguration { [weak self] manager in
guard let self = self, let manager = manager else { return }
DispatchQueue.main.async { [weak self] in
self?.vpnManager = manager
}
self.startExistingVPN(manager: manager)
}
}
}
private func startExistingVPN(manager: NETunnelProviderManager) {
// First check the actual current status
let currentStatus = manager.connection.status
VPNLogger.shared.log("Current VPN status before start attempt: \(currentStatus.rawValue)")
if currentStatus == .connected {
VPNLogger.shared.log("StosVPN tunnel is already connected")
DispatchQueue.main.async { [weak self] in
self?.tunnelStatus = .connected
}
return
}
if currentStatus == .connecting {
VPNLogger.shared.log("StosVPN tunnel is already connecting")
DispatchQueue.main.async { [weak self] in
self?.tunnelStatus = .connecting
}
return
}
manager.isEnabled = true
manager.saveToPreferences { [weak self] error in
guard let self = self else { return }
if let error = error {
VPNLogger.shared.log("Error saving preferences: \(error.localizedDescription)")
DispatchQueue.main.async { [weak self] in
self?.tunnelStatus = .error
}
return
}
manager.loadFromPreferences { [weak self] error in
guard let self = self else { return }
if let error = error {
VPNLogger.shared.log("Error reloading preferences: \(error.localizedDescription)")
DispatchQueue.main.async { [weak self] in
self?.tunnelStatus = .error
}
return
}
// Check status again after reload
let statusAfterReload = manager.connection.status
VPNLogger.shared.log("VPN status after reload: \(statusAfterReload.rawValue)")
if statusAfterReload == .connected {
VPNLogger.shared.log("VPN is already connected after reload")
DispatchQueue.main.async { [weak self] in
self?.tunnelStatus = .connected
}
return
}
DispatchQueue.main.async { [weak self] in
self?.tunnelStatus = .connecting
}
let options: [String: NSObject] = [
"TunnelDeviceIP": self.tunnelDeviceIp as NSObject,
"TunnelFakeIP": self.tunnelFakeIp as NSObject,
"TunnelSubnetMask": self.tunnelSubnetMask as NSObject
]
do {
try manager.connection.startVPNTunnel(options: options)
VPNLogger.shared.log("StosVPN tunnel start initiated")
} catch {
DispatchQueue.main.async { [weak self] in
self?.tunnelStatus = .error
}
VPNLogger.shared.log("Failed to start StosVPN tunnel: \(error.localizedDescription)")
}
}
}
}
func stopVPN() {
guard let manager = vpnManager else {
VPNLogger.shared.log("No VPN manager available to stop")
return
}
DispatchQueue.main.async { [weak self] in
self?.tunnelStatus = .disconnecting
}
manager.connection.stopVPNTunnel()
VPNLogger.shared.log("StosVPN tunnel stop initiated")
UserDefaults.standard.removeObject(forKey: "ShouldStartStosVPNAfterDisconnect")
}
func handleVPNStatusChange(notification: Notification) {
guard let connection = notification.object as? NEVPNConnection else { return }
VPNLogger.shared.log("Handling VPN status change: \(connection.status.rawValue)")
// Always update status if it's our manager's connection
if let manager = vpnManager, connection == manager.connection {
VPNLogger.shared.log("Status change is for our StosVPN manager")
updateTunnelStatus(from: connection.status)
}
if connection.status == .disconnected &&
UserDefaults.standard.bool(forKey: "ShouldStartStosVPNAfterDisconnect") {
UserDefaults.standard.removeObject(forKey: "ShouldStartStosVPNAfterDisconnect")
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) { [weak self] in
self?.initializeAndStartStosVPN()
}
return
}
// Prevent recursive calls when checking for duplicates
guard !isProcessingStatusChange else { return }
isProcessingStatusChange = true
// Check for duplicates asynchronously without blocking
DispatchQueue.global(qos: .utility).async { [weak self] in
guard let self = self else { return }
NETunnelProviderManager.loadAllFromPreferences { [weak self] managers, error in
guard let self = self, let managers = managers, !managers.isEmpty else {
DispatchQueue.main.async { [weak self] in
self?.isProcessingStatusChange = false
}
return
}
let stosManagers = managers.filter { manager in
guard let proto = manager.protocolConfiguration as? NETunnelProviderProtocol else {
return false
}
return proto.providerBundleIdentifier == self.tunnelBundleId
}
if stosManagers.count > 1 {
DispatchQueue.main.async { [weak self] in
self?.cleanupDuplicateManagers(stosManagers)
}
}
DispatchQueue.main.async { [weak self] in
self?.isProcessingStatusChange = false
}
}
}
}
// MARK: - Cleanup Utilities
func cleanupAllVPNConfigurations() {
NETunnelProviderManager.loadAllFromPreferences { [weak self] managers, error in
guard let self = self else { return }
if let error = error {
VPNLogger.shared.log("Error loading VPN configurations for cleanup: \(error.localizedDescription)")
return
}
guard let managers = managers else { return }
for manager in managers {
guard let proto = manager.protocolConfiguration as? NETunnelProviderProtocol,
proto.providerBundleIdentifier == self.tunnelBundleId else {
continue
}
if manager.connection.status == .connected || manager.connection.status == .connecting {
manager.connection.stopVPNTunnel()
}
manager.removeFromPreferences { error in
if let error = error {
VPNLogger.shared.log("Error removing VPN configuration: \(error.localizedDescription)")
} else {
VPNLogger.shared.log("Successfully removed VPN configuration")
}
}
}
DispatchQueue.main.async { [weak self] in
self?.vpnManager = nil
self?.tunnelStatus = .disconnected
}
}
}
deinit {
if let observer = vpnObserver {
NotificationCenter.default.removeObserver(observer)
}
}
}
// MARK: - Views
struct ContentView: View {
@StateObject private var tunnelManager = TunnelManager.shared
@State private var showSettings = false
@State var tunnel = false
@AppStorage("autoConnect") private var autoConnect = false
@AppStorage("hasNotCompletedSetup") private var hasNotCompletedSetup = true
var body: some View {
NBNavigationStack {
VStack(spacing: 30) {
Spacer()
StatusIndicatorView()
ConnectionButton(
action: {
tunnelManager.tunnelStatus == .connected ? tunnelManager.stopVPN() : tunnelManager.startVPN()
}
)
Spacer()
if tunnelManager.tunnelStatus == .connected {
ConnectionStatsView()
}
}
.padding()
.navigationTitle("StosVPN")
.tvOSNavigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .topBarTrailing) {
Button {
showSettings = true
} label: {
Image(systemName: "gear")
.foregroundColor(.primary)
}
}
}
.onChange(of: tunnelManager.waitingOnSettings) { finished in
if tunnelManager.tunnelStatus != .connected && autoConnect && finished {
tunnelManager.startVPN()
}
}
.sheet(isPresented: $showSettings) {
SettingsView()
}
.sheet(isPresented: $hasNotCompletedSetup) {
SetupView()
}
}
}
}
extension View {
@ViewBuilder
func tvOSNavigationBarTitleDisplayMode(_ displayMode: NavigationBarItem.TitleDisplayMode) -> some View {
#if os(iOS)
self.navigationBarTitleDisplayMode(displayMode)
#else
self
#endif
}
}
struct StatusIndicatorView: View {
@StateObject private var tunnelManager = TunnelManager.shared
@State private var animationAmount = 1.0
@State private var isAnimating = false
var body: some View {
VStack(spacing: 20) {
ZStack {
Circle()
.stroke(tunnelManager.tunnelStatus.color.opacity(0.2), lineWidth: 20)
.frame(width: 200, height: 200)
Circle()
.stroke(tunnelManager.tunnelStatus.color, lineWidth: 10)
.frame(width: 200, height: 200)
.scaleEffect(animationAmount)
.opacity(2 - animationAmount)
.animation(isAnimating ? Animation.easeOut(duration: 1.5).repeatForever(autoreverses: false) : .default, value: animationAmount)
VStack(spacing: 10) {
Image(systemName: tunnelManager.tunnelStatus.systemImage)
.font(.system(size: 50))
.foregroundColor(tunnelManager.tunnelStatus.color)
Text(tunnelManager.tunnelStatus.localizedTitle)
.font(.headline)
.foregroundColor(.primary)
}
}
.onAppear {
updateAnimation()
}
.onChange(of: tunnelManager.tunnelStatus) { _ in
updateAnimation()
}
Text(tunnelManager.tunnelStatus == .connected ?
NSLocalizedString("local_tunnel_active", comment: "") :
NSLocalizedString("local_tunnel_inactive", comment: ""))
.font(.subheadline)
.foregroundColor(tunnelManager.tunnelStatus == .connected ? .green : .secondary)
}
}
private func updateAnimation() {
switch tunnelManager.tunnelStatus {
case .disconnecting:
isAnimating = false
withAnimation {
animationAmount = 1.0
}
case .disconnected:
isAnimating = false
animationAmount = 1.0
default:
isAnimating = true
animationAmount = 1.0
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
withAnimation {
animationAmount = 2.0
}
}
}
}
}
struct ConnectionButton: View {
@StateObject private var tunnelManager = TunnelManager.shared
let action: () -> Void
var body: some View {
Button(action: action) {
HStack {
Text(buttonText)
.font(.headline)
.fontWeight(.semibold)
if tunnelManager.tunnelStatus == .connecting || tunnelManager.tunnelStatus == .disconnecting {
ProgressView()
.progressViewStyle(CircularProgressViewStyle())
.padding(.leading, 5)
}
}
.frame(width: 200, height: 50)
.background(buttonBackground)
.foregroundColor(.white)
.clipShape(Capsule())
.shadow(color: Color.black.opacity(0.15), radius: 10, x: 0, y: 5)
}
.disabled(tunnelManager.tunnelStatus == .connecting || tunnelManager.tunnelStatus == .disconnecting)
}
private var buttonText: String {
switch tunnelManager.tunnelStatus {
case .connected:
return NSLocalizedString("disconnect", comment: "")
case .connecting:
return NSLocalizedString("connecting_ellipsis", comment: "")
case .disconnecting:
return NSLocalizedString("disconnecting_ellipsis", comment: "")
default:
return NSLocalizedString("connect", comment: "")
}
}
private var buttonBackground: some View {
Group {
if tunnelManager.tunnelStatus == .connected {
LinearGradient(
gradient: Gradient(colors: [Color.red.opacity(0.8), Color.red]),
startPoint: .leading,
endPoint: .trailing
)
} else {
LinearGradient(
gradient: Gradient(colors: [Color.blue.opacity(0.8), Color.blue]),
startPoint: .leading,
endPoint: .trailing
)
}
}
}
}
struct ConnectionStatsView: View {
@State private var time = 0
let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
var body: some View {
VStack(spacing: 25) {
Text("local_tunnel_details")
.font(.headline)
.foregroundColor(.primary)
HStack(spacing: 30) {
StatItemView(
title: "time_connected",
value: formattedTime,
icon: "clock.fill"
)
StatItemView(
title: "status",
value: NSLocalizedString("active", comment: ""),
icon: "checkmark.circle.fill"
)
}
HStack(spacing: 30) {
StatItemView(
title: "network_interface",
value: NSLocalizedString("local", comment: ""),
icon: "network"
)
StatItemView(
title: "assigned_ip",
value: "10.7.0.1",
icon: "number"
)
}
}
.padding()
.background(
RoundedRectangle(cornerRadius: 20)
.fill(Color(UIColor.darkGray))
.shadow(color: Color.black.opacity(0.05), radius: 10, x: 0, y: 5)
)
.onReceive(timer) { _ in
time += 1
}
}
var formattedTime: String {
let minutes = (time / 60) % 60
let hours = time / 3600
let seconds = time % 60
if hours > 0 {
return String(format: "%02d:%02d:%02d", hours, minutes, seconds)
} else {
return String(format: "%02d:%02d", minutes, seconds)
}
}
}
struct StatItemView: View {
let title: LocalizedStringKey
let value: String
let icon: String
var body: some View {
VStack(alignment: .leading, spacing: 10) {
HStack {
Image(systemName: icon)
.foregroundColor(.blue)
Text(title)
.font(.caption)
.foregroundColor(.secondary)
}
Text(value)
.font(.system(size: 16, weight: .semibold))
.foregroundColor(.primary)
}
.frame(maxWidth: .infinity, alignment: .leading)
}
}
// MARK: - Updated SettingsView
struct SettingsView: View {
@Environment(\.presentationMode) var presentationMode
@AppStorage("selectedLanguage") private var selectedLanguage = Locale.current.languageCode ?? "en"
@AppStorage("TunnelDeviceIP") private var deviceIP = "10.7.0.0"
@AppStorage("TunnelFakeIP") private var fakeIP = "10.7.0.1"
@AppStorage("TunnelSubnetMask") private var subnetMask = "255.255.255.0"
@AppStorage("autoConnect") private var autoConnect = false
@AppStorage("shownTunnelAlert") private var shownTunnelAlert = false
@StateObject private var tunnelManager = TunnelManager.shared
@AppStorage("hasNotCompletedSetup") private var hasNotCompletedSetup = true
@State private var showNetworkWarning = false
@State private var showRestartPopUp = false
var body: some View {
NBNavigationStack {
List {
Section(header: Text("connection_settings")) {
Toggle("auto_connect_on_launch", isOn: $autoConnect)
NavigationLink(destination: ConnectionLogView()) {
Label("connection_logs", systemImage: "doc.text")
}
}
Section(header: Text("network_configuration")) {
Group {
networkConfigRow(label: "tunnel_ip", text: $deviceIP)
networkConfigRow(label: "device_ip", text: $fakeIP)
networkConfigRow(label: "subnet_mask", text: $subnetMask)
}
}
Section(header: Text("app_information")) {
Button {
UIApplication.shared.open(URL(string: "https://github.com/stossy11/PrivacyPolicy/blob/main/PrivacyPolicy.md")!, options: [:])
} label: {
Label("privacy_policy", systemImage: "lock.shield")
}
NavigationLink(destination: DataCollectionInfoView()) {
Label("data_collection_policy", systemImage: "hand.raised.slash")
}
HStack {
Text("app_version")
Spacer()
Text(Bundle.main.shortVersion)
.foregroundColor(.secondary)
}
NavigationLink(destination: HelpView()) {
Text("help_and_support")
}
}
Section(header: Text("language")) {
Picker("dropdown_language", selection: $selectedLanguage) {
Text("english").tag("en")
Text("spanish").tag("es")
Text("italian").tag("it")
Text("polish").tag("pl")
}
.onChange(of: selectedLanguage) { newValue in
let languageCode = newValue
LanguageManager.shared.updateLanguage(to: languageCode)
showRestartPopUp = true
}
.alert(isPresented: $showRestartPopUp){
Alert(
title: Text("restart_title"),
message: Text("restart_message"),
dismissButton: .cancel(Text("understand_button")) {
showRestartPopUp = true
}
)
}
}
}
.alert(isPresented: $showNetworkWarning) {
Alert(
title: Text("warning_alert"),
message: Text("warning_message"),
dismissButton: .cancel(Text("understand_button")) {
shownTunnelAlert = true
deviceIP = "10.7.0.0"
fakeIP = "10.7.0.1"
subnetMask = "255.255.255.0"
}
)
}
.navigationTitle(Text("settings"))
.tvOSNavigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .topBarTrailing) {
Button("done") {
dismiss()
}
}
}
}
}
private func dismiss() {
presentationMode.wrappedValue.dismiss()
}
private func networkConfigRow(label: LocalizedStringKey, text: Binding<String>) -> some View {
HStack {
Text(label)
Spacer()
TextField(label, text: text)
.multilineTextAlignment(.trailing)
.foregroundColor(.secondary)
.keyboardType(.numbersAndPunctuation)
.onChange(of: text.wrappedValue) { newValue in
if !shownTunnelAlert {
showNetworkWarning = true
}
tunnelManager.vpnManager?.saveToPreferences { error in
if let error = error {
VPNLogger.shared.log(error.localizedDescription)
}
}
}
}
}
}
// MARK: - New Data Collection Info View
struct DataCollectionInfoView: View {
var body: some View {
ScrollView {
VStack(alignment: .leading, spacing: 20) {
Text("data_collection_policy_title")
.font(.title)
.fontWeight(.bold)
.padding(.bottom, 10)
GroupBox(label: Label("no_data_collection", systemImage: "hand.raised.slash").font(.headline)) {
Text("no_data_collection_description")
.padding(.vertical)
}
GroupBox(label: Label("local_processing_only", systemImage: "iphone").font(.headline)) {
Text("local_processing_only_description")
.padding(.vertical)
}
GroupBox(label: Label("no_third_party_sharing", systemImage: "person.2.slash").font(.headline)) {
Text("no_third_party_sharing_description")
.padding(.vertical)
}
GroupBox(label: Label("why_use_network_permissions", systemImage: "network").font(.headline)) {
Text("why_use_network_permissions_description")
.padding(.vertical)
}
GroupBox(label: Label("our_promise", systemImage: "checkmark.seal").font(.headline)) {
Text("our_promise_description")
.padding(.vertical)
}
}
.padding()
}
.navigationTitle(Text("data_collection_policy_nav"))
.tvOSNavigationBarTitleDisplayMode(.inline)
}
}
struct ConnectionLogView: View {
@StateObject var logger = VPNLogger.shared
var body: some View {
List(logger.logs, id: \.self) { log in
Text(log)
.font(.system(.body, design: .monospaced))
}
.navigationTitle(Text("logs_nav"))
.tvOSNavigationBarTitleDisplayMode(.inline)
}
}
struct HelpView: View {
var body: some View {
List {
Section(header: Text("faq_header")) {
NavigationLink("faq_q1") {
VStack(alignment: .leading, spacing: 15) {
Text("faq_q1_a1")
.padding(.bottom, 10)
Text("faq_common_use_cases")
.fontWeight(.medium)
Text("faq_case1")
Text("faq_case2")
Text("faq_case3")
Text("faq_case4")
}
.padding()
}
NavigationLink("faq_q2") {
VStack(alignment: .leading, spacing: 15) {
Text("faq_q2_a1")
.padding(.bottom, 10)
.font(.headline)
Text("faq_q2_point1")
Text("faq_q2_point2")
Text("faq_q2_point3")
Text("faq_q2_point4")
Text("faq_q2_a2")
.padding(.top, 10)
}
.padding()
}
NavigationLink("faq_q3") {
VStack(alignment: .leading, spacing: 15) {
Text("faq_q3_a1")
.padding(.bottom, 10)
Text("faq_troubleshoot_header")
.font(.headline)
Text("faq_troubleshoot1")
Text("faq_troubleshoot2")
Text("faq_troubleshoot3")
Text("faq_troubleshoot4")
}
.padding()
}
NavigationLink("faq_q4") {
VStack(alignment: .leading, spacing: 15) {
Text("faq_q4_intro")
.font(.headline)
.padding(.bottom, 10)
Text("faq_q4_case1")
Text("faq_q4_case2")
Text("faq_q4_case3")
Text("faq_q4_case4")
Text("faq_q4_conclusion")
.padding(.top, 10)
}
.padding()
}
}
Section(header: Text("business_model_header")) {
NavigationLink("biz_q1") {
VStack(alignment: .leading, spacing: 15) {
Text("biz_q1_a1")
.padding(.bottom, 10)
Text("biz_key_points_header")
.font(.headline)
Text("biz_point1")
Text("biz_point2")
Text("biz_point3")
Text("biz_point4")
Text("biz_point5")
}
.padding()
}
}
Section(header: Text("app_info_header")) {
HStack {
Image(systemName: "exclamationmark.shield")
Text("requires_ios")
}
HStack {
Image(systemName: "lock.shield")
Text("uses_network_extension")
}
}
}
.navigationTitle(Text("help_and_support_nav"))
.tvOSNavigationBarTitleDisplayMode(.inline)
}
}
struct SetupView: View {
@Environment(\.presentationMode) var presentationMode
@AppStorage("hasNotCompletedSetup") private var hasNotCompletedSetup = true
@State private var currentPage = 0
let pages = [
SetupPage(
title: "setup_welcome_title",
description: "setup_welcome_description",
imageName: "checkmark.shield.fill",
details: "setup_welcome_details"
),
SetupPage(
title: "setup_why_title",
description: "setup_why_description",
imageName: "person.2.fill",
details: "setup_why_details"
),
SetupPage(
title: "setup_easy_title",
description: "setup_easy_description",
imageName: "hand.tap.fill",
details: "setup_easy_details"
),
SetupPage(
title: "setup_privacy_title",
description: "setup_privacy_description",
imageName: "lock.shield.fill",
details: "setup_privacy_details"
)
]
var body: some View {
NBNavigationStack {
VStack {
TabView(selection: $currentPage) {
ForEach(0..<pages.count, id: \.self) { index in
SetupPageView(page: pages[index])
.tag(index)
}
}
.tabViewStyle(PageTabViewStyle(indexDisplayMode: .always))
Spacer()
if currentPage == pages.count - 1 {
Button {
hasNotCompletedSetup = false
dismiss()
} label: {
Text("setup_get_started")
.font(.headline)
.fontWeight(.semibold)
.frame(height: 50)
.frame(maxWidth: .infinity)
.background(Color.blue)
.foregroundColor(.white)
.cornerRadius(10)
.padding(.horizontal)
}
.padding(.bottom)
} else {
Button {
withAnimation { currentPage += 1 }
} label: {
Text("setup_next")
.font(.headline)
.fontWeight(.semibold)
.frame(height: 50)
.frame(maxWidth: .infinity)
.background(Color.blue)
.foregroundColor(.white)
.cornerRadius(10)
.padding(.horizontal)
}
.padding(.bottom)
}
}
.navigationTitle(Text("setup_nav"))
.tvOSNavigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .topBarTrailing) {
Button("setup_skip") { hasNotCompletedSetup = false; dismiss() }
}
}
}
}
private func dismiss() {
presentationMode.wrappedValue.dismiss()
}
}
struct SetupPage {
let title: LocalizedStringKey
let description: LocalizedStringKey
let imageName: String
let details: LocalizedStringKey
}
struct SetupPageView: View {
let page: SetupPage
var body: some View {
VStack(spacing: tvOSSpacing) {
Image(systemName: page.imageName)
.font(.system(size: tvOSImageSize))
.foregroundColor(.blue)
.padding(.top, tvOSTopPadding)
Text(page.title)
.font(tvOSTitleFont)
.fontWeight(.bold)
.multilineTextAlignment(.center)
Text(page.description)
.font(tvOSDescriptionFont)
.foregroundColor(.secondary)
.multilineTextAlignment(.center)
ScrollView {
Text(page.details)
.font(tvOSBodyFont)
.multilineTextAlignment(.leading)
.padding(.horizontal)
}
Spacer()
}
.padding()
}
// MARK: - Conditional sizes for tvOS
private var tvOSImageSize: CGFloat {
#if os(tvOS)
return 60
#else
return 80
#endif
}
private var tvOSTopPadding: CGFloat {
#if os(tvOS)
return 30
#else
return 50
#endif
}
private var tvOSSpacing: CGFloat {
#if os(tvOS)
return 20
#else
return 30
#endif
}
private var tvOSTitleFont: Font {
#if os(tvOS)
return .headline //.system(size: 35).bold()
#else
return .title
#endif
}
private var tvOSDescriptionFont: Font {
#if os(tvOS)
return .subheadline
#else
return .headline
#endif
}
private var tvOSBodyFont: Font {
#if os(tvOS)
return .system(size: 18).bold()
#else
return .body
#endif
}
}
class LanguageManager: ObservableObject {
static let shared = LanguageManager()
@Published var currentLanguage: String = Locale.current.languageCode ?? "en"
private let supportedLanguages = ["en", "es", "it", "pl"]
func updateLanguage(to languageCode: String) {
if supportedLanguages.contains(languageCode) {
currentLanguage = languageCode
UserDefaults.standard.set([languageCode], forKey: "AppleLanguages")
UserDefaults.standard.synchronize()
} else {
currentLanguage = "en" //FALLBACK TO DEFAULT LANGUAGE
UserDefaults.standard.set(["en"], forKey: "AppleLanguages")
UserDefaults.standard.synchronize()
}
}
}
#if os(tvOS)
@ViewBuilder
func GroupBox<Content: View>(
label: some View,
@ViewBuilder content: @escaping () -> Content
) -> some View {
#if os(tvOS)
tvOSGroupBox(label: {
label
}, content: content)
#else
SwiftUI.GroupBox(label: label, content: content)
#endif
}
struct tvOSGroupBox<Label: View, Content: View>: View {
@ViewBuilder let label: () -> Label
@ViewBuilder let content: () -> Content
init(
@ViewBuilder label: @escaping () -> Label,
@ViewBuilder content: @escaping () -> Content
) {
self.label = label
self.content = content
}
var body: some View {
VStack(alignment: .leading, spacing: 8) {
label()
.font(.headline)
content()
.padding(.top, 4)
}
.padding()
.background(
RoundedRectangle(cornerRadius: 12, style: .continuous)
.fill(.secondary)
)
.overlay(
RoundedRectangle(cornerRadius: 12, style: .continuous)
.stroke(.separator, lineWidth: 0.5)
)
}
}
#endif
#Preview {
ContentView()
}
================================================
FILE: StosVPN/Info.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSBonjourServices</key>
<array>
<string>_apple-mobdev2._tcp</string>
</array>
</dict>
</plist>
================================================
FILE: StosVPN/Localization/en.lproj/Localizable.strings
================================================
/* MARK: Start Screen */
"disconnected" = "Disconnected";
"connecting" = "Connecting";
"connected" = "Connected";
"disconnecting" = "Disconnecting";
"error" = "Error";
"local_tunnel_active" = "Local Tunnel Active";
"local_tunnel_inactive" = "Local Tunnel Inactive";
"connect" = "Connect";
"disconnect" = "Disconnect";
"connecting_ellipsis" = "Connecting...";
"disconnecting_ellipsis" = "Disconnecting...";
"server_address_name" = "StosVPN Local Tunnel";
"local_tunnel_details" = "Tunnel Details";
"time_connected" = "Time Connected";
"status" = "Status";
"active" = "Active";
"network_interface" = "Network Interface";
"local" = "Local";
"assigned_ip" = "Assigned IP";
/* MARK: Locales */
"english" = "English";
"spanish" = "Spanish";
"italian" = "Italian";
"polish" = "Polish";
/* MARK: Settings */
"connection_settings" = "Connection Settings";
"auto_connect_on_launch" = "Auto Connect on Launch";
"connection_logs" = "Connection Logs";
"network_configuration" = "Network Configuration";
"device_ip" = "Device IP";
"tunnel_ip" = "Tunnel IP";
"subnet_mask" = "Subnet Mask";
"app_information" = "App Information";
"privacy_policy" = "Privacy Policy";
"data_collection_policy" = "Data Collection Policy";
"app_version" = "App Version";
"help_and_support" = "Help and Support";
"language" = "Set Language";
"dropdown_language" = "Language";
"settings" = "Settings";
"done" = "Done";
"warning_alert" = "Warning";
"warning_message" = "Changing tunnel IP settings can disrupt your network connection. Proceed only if you are sure of what you are doing.";
"understand_button" = "I Understand";
"data_collection_policy_title" = "Data Collection Policy";
"no_data_collection" = "No Data Collection";
"no_data_collection_description" = "StosVPN DOES NOT collect user data, traffic information, or browsing activity. This app creates a local network tunnel that stays entirely on your device.";
"local_processing_only" = "Local Processing Only";
"local_processing_only_description" = "All network traffic and configurations are processed locally on your device. No information ever leaves the device or is transmitted over the Internet.";
"no_third_party_sharing" = "No Third Party Sharing";
"no_third_party_sharing_description" = "Since we do not collect data, there is no sharing with third parties. We do not have analytics, tracking, or data collection mechanisms in this app.";
"why_use_network_permissions" = "Why Use Network Permissions?";
"why_use_network_permissions_description" = "StosVPN requires network extension permissions to create a local network interface on your device. This is used exclusively for local development and testing.";
"our_promise" = "Our Promise";
"our_promise_description" = "We are committed to privacy and transparency. This app is designed for developers to test and connect to local servers with no privacy concerns.";
"data_collection_policy_nav" = "Data Collection";
"logs_nav" = "Logs";
"faq_header" = "Frequently Asked Questions";
"faq_q1" = "What does this app do?";
"faq_q1_a1" = "StosVPN creates a local network interface for development and testing. It does not route traffic through external servers: everything stays on the device.";
"faq_common_use_cases" = "Common use cases include:";
"faq_case1" = "• Web app testing with local servers";
"faq_case2" = "• Development and debugging of network features";
"faq_case3" = "• Accessing hosted local development environments";
"faq_case4" = "• Testing apps that require specific network configurations";
"faq_q2" = "Is it a traditional VPN?";
"faq_q2_a1" = "No, StosVPN is NOT a traditional VPN service. It does NOT:";
"faq_q2_point1" = "• Route your traffic through external servers";
"faq_q2_point2" = "• Provide privacy or anonymity for browsing";
"faq_q2_point3" = "• Connect to remote VPN servers";
"faq_q2_point4" = "• Encrypt or route your internet traffic";
"faq_q2_a2" = "StosVPN only creates a local network interface to help developers connect to local services for development and testing.";
"faq_q3" = "Why does the connection fail?";
"faq_q3_a1" = "Connection failures may be due to system permissions, configuration errors, or iOS restrictions.";
"faq_troubleshoot_header" = "Troubleshooting steps:";
"faq_troubleshoot1" = "• Make sure you have approved the network extension permission";
"faq_troubleshoot2" = "• Try restarting the app";
"faq_troubleshoot3" = "• Check if the IP configuration is valid";
"faq_troubleshoot4" = "• Restart the device if problems persist";
"faq_q4" = "Who is this app for?";
"faq_q4_intro" = "StosVPN is primarily designed for:";
"faq_q4_case1" = "• Developers testing local web servers";
"faq_q4_case2" = "• App developers testing network features";
"faq_q4_case3" = "• QA engineers testing apps in isolated environments";
"faq_q4_case4" = "• Anyone needing access to local services on iOS";
"faq_q4_conclusion" = "This app is publicly available and useful for developers who need to test apps with network features on iOS.";
"business_model_header" = "Business Model";
"biz_q1" = "How does StosVPN work?";
"biz_q1_a1" = "StosVPN is a completely free app available to the public. There are no paid features, subscriptions, or in-app purchases.";
"biz_key_points_header" = "Key points of our model:";
"biz_point1" = "• The app is not tied to any company or group";
"biz_point2" = "• Anyone can download and use the app from the App Store";
"biz_point3" = "• No account creation is required";
"biz_point4" = "• All features are free for all users";
"biz_point5" = "• The app is developed and maintained as an open utility for the iOS community";
"app_info_header" = "App Information";
"requires_ios" = "Requires iOS 14.0 or later";
"uses_network_extension" = "Uses Apple Network Extension APIs";
"help_and_support_nav" = "Help & Support";
"setup_welcome_title" = "Welcome to StosVPN";
"setup_welcome_description" = "A simple local network tunnel for developers";
"setup_welcome_details" = "StosVPN creates a local network interface for development, testing, and access to local servers. This app DOES NOT collect user data or route traffic through external servers.";
"setup_why_title" = "Why Use StosVPN?";
"setup_why_description" = "Perfect for iOS developers";
"setup_why_details" = "• Access local web servers and development environments\n• Test apps requiring specific network configurations\n• Connect to local network services without complex setup\n• Create isolated testing environments";
"setup_easy_title" = "Easy to Use";
"setup_easy_description" = "Just one tap to connect";
"setup_easy_details" = "StosVPN is designed to be simple. Just tap the connect button to establish a local tunnel with preconfigured settings.";
"setup_privacy_title" = "Privacy Focused";
"setup_privacy_description" = "Your data stays on the device";
"setup_privacy_details" = "StosVPN creates a local tunnel that does not route traffic through external servers. All traffic stays on your device, ensuring privacy and security. No data is collected or shared with third parties.";
"setup_nav" = "Setup";
"setup_get_started" = "Get Started";
"setup_next" = "Next";
"setup_skip" = "Skip";
/*MARK: Restart pop-up*/
restart_title = "Restart";
restart_message = "To apply the changes, you need to restart the application.";
confirmYes = "Yes";
confirmNo = "No";
================================================
FILE: StosVPN/Localization/es.lproj/Localizable.strings
================================================
/* MARK: Pantalla de inicio */
"disconnected" = "Desconectado";
"connecting" = "Conectando";
"connected" = "Conectado";
"disconnecting" = "Desconectando";
"error" = "Error";
"local_tunnel_active" = "Túnel local activo";
"local_tunnel_inactive" = "Túnel local inactivo";
"connect" = "Conectar";
"disconnect" = "Desconectar";
"connecting_ellipsis" = "Conectando...";
"disconnecting_ellipsis" = "Desconectando...";
"server_address_name" = "Túnel Local de StosVPN";
"local_tunnel_details" = "Detalles del Túnel";
"time_connected" = "Tiempo Conectado";
"status" = "Estado";
"active" = "Activo";
"network_interface" = "Interfaz de Red";
"local" = "Local";
"assigned_ip" = "IP Asignada";
/* MARK: Locales */
"english" = "Inglés";
"spanish" = "Español";
"italian" = "Italiano";
"polish" = "Polaco";
/* MARK: Configuración */
"connection_settings" = "Configuración de Conexión";
"auto_connect_on_launch" = "Conectar automáticamente al iniciar";
"connection_logs" = "Registros de Conexión";
"network_configuration" = "Configuración de Red";
"device_ip" = "IP del Dispositivo";
"tunnel_ip" = "IP del Túnel";
"subnet_mask" = "Máscara de Subred";
"app_information" = "Información de la App";
"privacy_policy" = "Política de Privacidad";
"data_collection_policy" = "Política de Recopilación de Datos";
"app_version" = "Versión de la App";
"help_and_support" = "Ayuda y Soporte";
"language" = "Establecer idioma";
"dropdown_language" = "Idioma";
"settings" = "Configuración";
"done" = "Hecho";
"warning_alert" = "Advertencia";
"warning_message" = "Cambiar la configuración de la IP del túnel puede interrumpir tu conexión de red. Procede solo si estás seguro de lo que haces.";
"understand_button" = "Entiendo";
"data_collection_policy_title" = "Política de Recopilación de Datos";
"no_data_collection" = "No Recopilación de Datos";
"no_data_collection_description" = "StosVPN NO recopila datos de usuarios, información sobre el tráfico o actividad de navegación. Esta app crea un túnel de red local que permanece completamente en tu dispositivo.";
"local_processing_only" = "Solo Procesamiento Local";
"local_processing_only_description" = "Todo el tráfico de red y configuraciones se procesan localmente en tu dispositivo. Ninguna información deja el dispositivo ni se transmite a Internet.";
"no_third_party_sharing" = "No Compartir con Terceros";
"no_third_party_sharing_description" = "Dado que no recopilamos datos, no compartimos con terceros. No tenemos análisis, rastreo ni mecanismos de recopilación de datos en esta app.";
"why_use_network_permissions" = "¿Por Qué Usar Permisos de Red?";
"why_use_network_permissions_description" = "StosVPN requiere permisos de extensión de red para crear una interfaz de red local en tu dispositivo. Esto se utiliza exclusivamente para desarrollo y pruebas locales.";
"our_promise" = "Nuestra Promesa";
"our_promise_description" = "Estamos comprometidos con la privacidad y la transparencia. Esta app está diseñada para desarrolladores para probar y conectarse a servidores locales sin preocupaciones sobre la privacidad.";
"data_collection_policy_nav" = "Recopilación de Datos";
"logs_nav" = "Registros";
"faq_header" = "Preguntas Frecuentes";
"faq_q1" = "¿Qué hace esta app?";
"faq_q1_a1" = "StosVPN crea una interfaz de red local útil para el desarrollo y las pruebas. No enruta el tráfico a través de servidores externos: todo permanece en el dispositivo.";
"faq_common_use_cases" = "Los casos de uso comunes incluyen:";
"faq_case1" = "• Pruebas de aplicaciones web con servidores locales";
"faq_case2" = "• Desarrollo y depuración de funcionalidades de red";
"faq_case3" = "• Acceso a entornos de desarrollo locales alojados";
"faq_case4" = "• Pruebas de apps que requieren configuraciones de red específicas";
"faq_q2" = "¿Es una VPN tradicional?";
"faq_q2_a1" = "No, StosVPN NO es un servicio de VPN tradicional. No:";
"faq_q2_point1" = "• Enruta tu tráfico a través de servidores externos";
"faq_q2_point2" = "• Proporciona privacidad o anonimato para la navegación";
"faq_q2_point3" = "• Se conecta a servidores VPN remotos";
"faq_q2_point4" = "• Cifra o enruta tu tráfico de internet";
"faq_q2_a2" = "StosVPN solo crea una interfaz de red local para ayudar a los desarrolladores a conectarse a servicios locales para el desarrollo y las pruebas.";
"faq_q3" = "¿Por qué falla la conexión?";
"faq_q3_a1" = "Las fallas en la conexión pueden deberse a permisos del sistema, errores de configuración o restricciones de iOS.";
"faq_troubleshoot_header" = "Pasos para solucionar problemas:";
"faq_troubleshoot1" = "• Asegúrate de haber aprobado el permiso de extensión de red";
"faq_troubleshoot2" = "• Intenta reiniciar la app";
"faq_troubleshoot3" = "• Verifica si la configuración IP es válida";
"faq_troubleshoot4" = "• Reinicia el dispositivo si los problemas persisten";
"faq_q4" = "¿Para quién es esta app?";
"faq_q4_intro" = "StosVPN está diseñado principalmente para:";
"faq_q4_case1" = "• Desarrolladores que prueban servidores web locales";
"faq_q4_case2" = "• Desarrolladores de apps que prueban funcionalidades de red";
"faq_q4_case3" = "• Ingenieros de QA que prueban apps en entornos aislados";
"faq_q4_case4" = "• Cualquier persona que necesite acceder a servicios locales en iOS";
"faq_q4_conclusion" = "Esta app está disponible para el público y es útil para desarrolladores que necesitan probar apps con funcionalidades de red en iOS.";
"business_model_header" = "Modelo de Negocio";
"biz_q1" = "¿Cómo funciona StosVPN?";
"biz_q1_a1" = "StosVPN es una app completamente gratuita disponible para el público. No hay funciones de pago, suscripciones ni compras dentro de la app.";
"biz_key_points_header" = "Puntos clave de nuestro modelo:";
"biz_point1" = "• La app no está vinculada a ninguna empresa o grupo";
"biz_point2" = "• Cualquier persona puede descargar y usar la app desde la App Store";
"biz_point3" = "• No es necesario crear una cuenta";
"biz_point4" = "• Todas las funciones son gratuitas para todos los usuarios";
"biz_point5" = "• La app es desarrollada y mantenida como una utilidad abierta para la comunidad de iOS";
"app_info_header" = "Información de la App";
"requires_ios" = "Requiere iOS 14.0 o superior";
"uses_network_extension" = "Usa la API de Extensión de Red de Apple";
"help_and_support_nav" = "Ayuda & Soporte";
"setup_welcome_title" = "Bienvenido a StosVPN";
"setup_welcome_description" = "Un simple túnel de red local para desarrolladores";
"setup_welcome_details" = "StosVPN crea una interfaz de red local para el desarrollo, pruebas y acceso a servidores locales. Esta app NO recopila datos de usuario ni enruta el tráfico a través de servidores externos.";
"setup_why_title" = "¿Por qué usar StosVPN?";
"setup_why_description" = "Ideal para desarrolladores iOS";
"setup_why_details" = "• Accede a servidores web locales y entornos de desarrollo\n• Prueba apps que requieren configuraciones de red específicas\n• Conéctate a servicios de red locales sin configuraciones complejas\n• Crea entornos aislados para pruebas";
"setup_easy_title" = "Fácil de Usar";
"setup_easy_description" = "Conéctate con solo un toque";
"setup_easy_details" = "StosVPN está diseñado para ser simple. Solo toca el botón de conexión para establecer un túnel local con configuraciones predefinidas.";
"setup_privacy_title" = "Enfocado en la Privacidad";
"setup_privacy_description" = "Tus datos permanecen en tu dispositivo";
"setup_privacy_details" = "StosVPN crea un túnel local que no enruta el tráfico a través de servidores externos. Todo el tráfico permanece en tu dispositivo, asegurando privacidad y seguridad. Ningún dato se recopila ni se comparte con terceros.";
"setup_nav" = "Configuración";
"setup_get_started" = "Comenzar";
"setup_next" = "Siguiente";
"setup_skip" = "Saltar";
/*MARK: Restart pop-up*/
restart_title = "Reiniciar";
restart_message = "Para aplicar los cambios, es necesario reiniciar la aplicación.";
confirmYes = "Sí";
confirmNo = "No";
================================================
FILE: StosVPN/Localization/it.lproj/Localizable.strings
================================================
/* MARK: Start Screen */
"disconnected" = "Disconnesso";
"connecting" = "Connessione in corso";
"connected" = "Connesso";
"disconnecting" = "Disconnessione in corso";
"error" = "Errore";
"local_tunnel_active" = "Tunnel locale attivo";
"local_tunnel_inactive" = "Tunnel locale inattivo";
"connect" = "Connetti";
"disconnect" = "Disconnetti";
"connecting_ellipsis" = "Connessione in corso...";
"disconnecting_ellipsis" = "Disconnessione in corso...";
"server_address_name" = "Tunnel Locale di StosVPN";
"local_tunnel_details" = "Dettagli del Tunnel";
"time_connected" = "Tempo Connesso";
"status" = "Stato";
"active" = "Attivo";
"network_interface" = "Interfaccia di Rete";
"local" = "Locale";
"assigned_ip" = "IP Assegnato";
/* MARK: Locales */
"english" = "Inglese";
"spanish" = "Spagnolo";
"italian" = "Italiano";
"polish" = "Polacco";
/* MARK: Settings*/
"connection_settings" = "Impostazioni Connessione";
"auto_connect_on_launch" = "Connessione automatica all’avvio";
"connection_logs" = "Log di Connessione";
"network_configuration" = "Configurazione Rete";
"device_ip" = "Indirizzo IP Dispositivo";
"tunnel_ip" = "Indirizzo IP Tunnel";
"subnet_mask" = "Maschera di Sottorete";
"app_information" = "Informazioni App";
"privacy_policy" = "Privacy Policy";
"data_collection_policy" = "Politica di Raccolta Dati";
"app_version" = "Versione App";
"help_and_support" = "Guida e Supporto";
"language" = "Imposta Lingua";
"dropdown_language" = "Lingua";
"settings" = "Impostazioni";
"done" = "Fine";
"warning_alert" = "Avviso";
"warning_message" = "La modifica delle impostazioni IP del tunnel può interrompere la connessione di rete. Procedi solo se sei sicuro di quello che stai facendo.";
"understand_button" = "Ho capito";
"data_collection_policy_title" = "Politica di Raccolta Dati";
"no_data_collection" = "Nessuna raccolta di dati";
"no_data_collection_description" = "StosVPN NON raccoglie dati utente, informazioni sul traffico o attività di navigazione. Questa app crea un tunnel di rete locale che rimane interamente sul tuo dispositivo.";
"local_processing_only" = "Elaborazione solo sul tuo smartphone";
"local_processing_only_description" = "Tutto il traffico di rete e le configurazioni vengono elaborate localmente sul tuo dispositivo. Nessuna informazione lascia mai il dispositivo o viene trasmessa su Internet.";
"no_third_party_sharing" = "Nessuna condivisione con servizi di terze parti";
"no_third_party_sharing_description" = "Poiché non raccogliamo dati, non c'è alcuna condivisione con terze parti. Non abbiamo analisi, tracciamento o meccanismi di raccolta dati in questa app.";
"why_use_network_permissions" = "Perché concedere i permessi di Rete?";
"why_use_network_permissions_description" = "StosVPN richiede permessi di estensione di rete per creare un'interfaccia di rete locale sul tuo dispositivo. Questo è utilizzato esclusivamente per sviluppo e test locali sul tuo dispositivo.";
"our_promise" = "La nostra promessa";
"our_promise_description" = "Ci impegniamo per la privacy e la trasparenza. Questa app è progettata per sviluppatori per testare e connettersi a server locali senza preoccupazioni sulla privacy.";
"data_collection_policy_nav" = "Raccolta Dati";
"logs_nav" = "Log di connessione";
"faq_header" = "Domande Frequenti";
"faq_q1" = "Cosa fa questa app?";
"faq_q1_a1" = "StosVPN crea un'interfaccia di rete locale utilizzabile per sviluppo e test. Non instrada il traffico attraverso server esterni, tutto rimane sul dispositivo.";
"faq_common_use_cases" = "I casi d'uso comuni includono:";
"faq_case1" = "• Test di applicazioni web con server locali.";
"faq_case2" = "• Sviluppo e Debug di funzionalità di rete.";
"faq_case3" = "• Accesso ad ambienti di sviluppo locali ospitati.";
"faq_case4" = "• Test di applicazioni che richiedono configurazioni di rete specifiche.";
"faq_q2" = "È un VPN tradizionale?";
"faq_q2_a1" = "No, StosVPN NON è un servizio VPN tradizionale. Non:";
"faq_q2_point1" = "• Instrada il tuo traffico attraverso server esterni.";
"faq_q2_point2" = "• Garantisce privacy e la navigazione in incognito.";
"faq_q2_point3" = "• Esegue connessioni a server VPN remoti.";
"faq_q2_point4" = "• Cripta o instrada il tuo traffico internet.";
"faq_q2_a2" = "StosVPN crea solo un'interfaccia di rete locale per aiutare gli sviluppatori a connettersi a servizi locali per lo sviluppo e test.";
"faq_q3" = "Perché non si connette?";
"faq_q3_a1" = "Un errore durante la connessione può essere dovuto a permessi di sistema, errori di configurazione o restrizioni di iOS.";
"faq_troubleshoot_header" = "Passaggi per risolvere:";
"faq_troubleshoot1" = "• Assicurati di aver accettato il permesso di estensione di rete.";
"faq_troubleshoot2" = "• Prova a riavviare l'applicazione.";
"faq_troubleshoot3" = "• Verifica se la configurazione IP è valida.";
"faq_troubleshoot4" = "• Riavvia il dispositivo se i problemi persistono.";
"faq_q4" = "Per chi è questa app?";
"faq_q4_intro" = "StosVPN è progettato principalmente per:";
"faq_q4_case1" = "• Sviluppatori che testano server web locali.";
"faq_q4_case2" = "• Sviluppatori app che testano funzionalità di rete.";
"faq_q4_case3" = "• Ingegneri QA che testano app in ambienti isolati.";
"faq_q4_case4" = "• Chiunque necessiti di accedere a servizi locali sull'iOS.";
"faq_q4_conclusion" = "Questa app è disponibile al pubblico ed è utile per sviluppatori che devono testare app con funzionalità di rete su iOS.";
"business_model_header" = "Modello di Business";
"biz_q1" = "Come funziona StosVPN?";
"biz_q1_a1" = "StosVPN è un'app completamente gratuita disponibile al pubblico. Non ci sono funzionalità a pagamento, abbonamenti o acquisti in‑app.";
"biz_key_points_header" = "Punti chiave del nostro modello:";
"biz_point1" = "• L'app non è vincolata a nessuna azienda o gruppo.";
"biz_point2" = "• Chiunque può scaricare e usare l'app dall'App Store.";
"biz_point3" = "• Non è necessario creare un account.";
"biz_point4" = "• Tutte le funzionalità sono gratuite per tutti gli utenti.";
"biz_point5" = "• L'app è sviluppata e mantenuta come utility open per la comunità iOS.";
"app_info_header" = "Informazioni App";
"requires_ios" = "Richiede iOS 14.0 o superiore";
"uses_network_extension" = "Usa le Network Extension API di Apple";
"help_and_support_nav" = "Guida & Supporto";
"setup_welcome_title" = "Benvenuto in StosVPN";
"setup_welcome_description" = "Un semplice tunnel di rete locale per sviluppatori";
"setup_welcome_details" = "StosVPN crea un'interfaccia di rete locale per sviluppo, test e accesso a server locali. Questa app NON raccoglie dati utente né instrada il traffico attraverso server esterni.";
"setup_why_title" = "Perché Usare StosVPN?";
"setup_why_description" = "Perfetto per sviluppatori iOS";
"setup_why_details" = "• Accedi a server web locali e ambienti di sviluppo\n• Testa app che richiedono configurazioni di rete specifiche\n• Connettiti a servizi di rete locali senza setup complessi\n• Crea ambienti isolati per test";
"setup_easy_title" = "Facile da Usare";
"setup_easy_description" = "Basta un tap per connettersi";
"setup_easy_details" = "StosVPN è progettato per essere semplice. Basta toccare il pulsante di connessione per stabilire un tunnel locale con impostazioni preconfigurate.";
"setup_privacy_title" = "Focalizzato sulla Privacy";
"setup_privacy_description" = "I tuoi dati restano sul dispositivo";
"setup_privacy_details" = "StosVPN crea un tunnel locale che non instrada il traffico attraverso server esterni. Tutto il traffico rimane sul tuo dispositivo, garantendo privacy e sicurezza. Nessun dato viene raccolto o condiviso con terze parti.";
"setup_nav" = "Setup";
"setup_get_started" = "Inizia";
"setup_next" = "Avanti";
"setup_skip" = "Salta";
/*MARK: Restart pop-up*/
restart_title = "Riavvia";
restart_message = "Per applicare le modifiche, c'è bisogno di riavviare l'applicazione.";
confirmYes = "Si";
confirmNo = "No";
================================================
FILE: StosVPN/Localization/pl.lproj/Localizable.strings
================================================
/* MARK: Start Screen */
"disconnected" = "Rozłączony";
"connecting" = "Łączenie";
"connected" = "Połączony";
"disconnecting" = "Rozłączanie";
"error" = "Błąd";
"local_tunnel_active" = "Lokalny tunel aktywny";
"local_tunnel_inactive" = "Lokalny tunel nieaktywny";
"connect" = "Połącz";
"disconnect" = "Rozłącz";
"connecting_ellipsis" = "Łączenie...";
"disconnecting_ellipsis" = "Rozłączanie...";
"server_address_name" = "Lokalny tunel StosVPN";
"local_tunnel_details" = "Szczegóły tunelu";
"time_connected" = "Czas połączenia";
"status" = "Status";
"active" = "Aktywny";
"network_interface" = "Interfejs sieciowy";
"local" = "Lokalny";
"assigned_ip" = "Przydzielony IP";
/* MARK: Locales */
"english" = "Angielski";
"spanish" = "Hiszpański";
"italian" = "Włoski";
"polish" = "Polski";
/* MARK: Settings */
"connection_settings" = "Ustawienia połączenia";
"auto_connect_on_launch" = "Automatyczne łączenie przy uruchomieniu";
"connection_logs" = "Logi połączenia";
"network_configuration" = "Konfiguracja sieci";
"device_ip" = "IP urządzenia";
"tunnel_ip" = "IP tunelu";
"subnet_mask" = "Maska podsieci";
"app_information" = "Informacje o aplikacji";
"privacy_policy" = "Polityka prywatności";
"data_collection_policy" = "Polityka zbierania danych";
"app_version" = "Wersja aplikacji";
"help_and_support" = "Pomoc i wsparcie";
"language" = "Ustaw język";
"dropdown_language" = "Język";
"settings" = "Ustawienia";
"done" = "Gotowe";
"warning_alert" = "Uwaga";
"warning_message" = "Zmiana ustawień IP tunelu może zakłócić połączenie sieciowe. Kontynuuj tylko wtedy, gdy jesteś pewien tego, co robisz.";
"understand_button" = "Rozumiem";
"data_collection_policy_title" = "Polityka zbierania danych";
"no_data_collection" = "Brak zbierania danych";
"no_data_collection_description" = "StosVPN NIE zbiera danych użytkownika, informacji o ruchu ani aktywności w przeglądarce. Aplikacja tworzy lokalny tunel sieciowy, który działa wyłącznie na Twoim urządzeniu.";
"local_processing_only" = "Tylko lokalne przetwarzanie";
"local_processing_only_description" = "Cały ruch sieciowy i konfiguracje są przetwarzane lokalnie na Twoim urządzeniu. Żadne informacje nie opuszczają urządzenia ani nie są przesyłane przez Internet.";
"no_third_party_sharing" = "Brak udostępniania osobom trzecim";
"no_third_party_sharing_description" = "Ponieważ nie zbieramy danych, nie ma żadnego udostępniania osobom trzecim. Aplikacja nie zawiera analityki, śledzenia ani mechanizmów zbierania danych.";
"why_use_network_permissions" = "Dlaczego wymagane są uprawnienia sieciowe";
"why_use_network_permissions_description" = "StosVPN wymaga uprawnień rozszerzenia sieciowego, aby utworzyć lokalny interfejs sieciowy na Twoim urządzeniu. Jest on używany wyłącznie do lokalnego rozwoju i testowania.";
"our_promise" = "Nasza obietnica";
"our_promise_description" = "Zobowiązujemy się do ochrony prywatności i przejrzystości. Ta aplikacja została zaprojektowana z myślą o programistach do testowania i łączenia się z lokalnymi serwerami bez obaw o prywatność.";
"data_collection_policy_nav" = "Zbieranie danych";
"logs_nav" = "Logi";
"faq_header" = "Najczęściej zadawane pytania";
"faq_q1" = "Do czego służy ta aplikacja?";
"faq_q1_a1" = "StosVPN tworzy lokalny interfejs sieciowy do celów rozwojowych i testowych. Nie przekierowuje ruchu przez zewnętrzne serwery – wszystko pozostaje na urządzeniu.";
"faq_common_use_cases" = "Typowe przypadki użycia:";
"faq_case1" = "• Testowanie aplikacji webowych z lokalnymi serwerami";
"faq_case2" = "• Tworzenie i debugowanie funkcji sieciowych";
"faq_case3" = "• Dostęp do lokalnych środowisk deweloperskich";
"faq_case4" = "• Testowanie aplikacji wymagających określonych konfiguracji sieciowych";
"faq_q2" = "Czy to tradycyjna sieć VPN?";
"faq_q2_a1" = "Nie, StosVPN NIE jest tradycyjną usługą VPN. NIE robi:";
"faq_q2_point1" = "• Przekierowywania ruchu przez zewnętrzne serwery";
"faq_q2_point2" = "• Zapewnienia prywatności lub anonimowości przeglądania";
"faq_q2_point3" = "• Łączenia z zewnętrznymi serwerami VPN";
"faq_q2_point4" = "• Szyfrowania lub przekierowywania Twojego ruchu internetowego";
"faq_q2_a2" = "StosVPN jedynie tworzy lokalny interfejs sieciowy, aby pomóc programistom łączyć się z lokalnymi usługami w celu rozwoju i testowania.";
"faq_q3" = "Dlaczego połączenie się nie udaje?";
"faq_q3_a1" = "Nieudane połączenia mogą wynikać z braku uprawnień systemowych, błędów konfiguracji lub ograniczeń iOS.";
"faq_troubleshoot_header" = "Kroki rozwiązywania problemów:";
"faq_troubleshoot1" = "• Upewnij się, że zatwierdziłeś uprawnienia rozszerzenia sieciowego";
"faq_troubleshoot2" = "• Spróbuj ponownie uruchomić aplikację";
"faq_troubleshoot3" = "• Sprawdź, czy konfiguracja IP jest prawidłowa";
"faq_troubleshoot4" = "• Uruchom ponownie urządzenie, jeśli problemy będą się powtarzać";
"faq_q4" = "Dla kogo jest ta aplikacja?";
"faq_q4_intro" = "StosVPN został zaprojektowany głównie dla:";
"faq_q4_case1" = "• Programistów testujących lokalne serwery webowe";
"faq_q4_case2" = "• Twórców aplikacji testujących funkcje sieciowe";
"faq_q4_case3" = "• Inżynierów QA testujących aplikacje w izolowanych środowiskach";
"faq_q4_case4" = "• Każdego, kto potrzebuje dostępu do lokalnych usług na iOS";
"faq_q4_conclusion" = "Aplikacja jest publicznie dostępna i przydatna dla deweloperów testujących aplikacje z funkcjami sieciowymi na iOS.";
"business_model_header" = "Model biznesowy";
"biz_q1" = "Jak działa StosVPN?";
"biz_q1_a1" = "StosVPN to całkowicie darmowa aplikacja dostępna publicznie. Nie ma żadnych płatnych funkcji, subskrypcji ani zakupów w aplikacji.";
"biz_key_points_header" = "Kluczowe cechy naszego modelu:";
"biz_point1" = "• Aplikacja nie jest powiązana z żadną firmą ani organizacją";
"biz_point2" = "• Każdy może pobrać i używać aplikacji z App Store";
"biz_point3" = "• Nie jest wymagane zakładanie konta";
"biz_point4" = "• Wszystkie funkcje są dostępne za darmo dla wszystkich użytkowników";
"biz_point5" = "• Aplikacja jest rozwijana i utrzymywana jako otwarte narzędzie dla społeczności iOS";
"app_info_header" = "Informacje o aplikacji";
"requires_ios" = "Wymaga iOS 14.0 lub nowszego";
"uses_network_extension" = "Wykorzystuje API Apple Network Extension";
"help_and_support_nav" = "Pomoc i wsparcie";
"setup_welcome_title" = "Witamy w StosVPN";
"setup_welcome_description" = "Prosty lokalny tunel sieciowy dla programistów";
"setup_welcome_details" = "StosVPN tworzy lokalny interfejs sieciowy do rozwoju, testowania i dostępu do lokalnych serwerów. Aplikacja NIE zbiera danych użytkownika ani nie przekierowuje ruchu przez zewnętrzne serwery.";
"setup_why_title" = "Dlaczego warto używać StosVPN?";
"setup_why_description" = "Idealny dla programistów iOS";
"setup_why_details" = "• Dostęp do lokalnych serwerów webowych i środowisk deweloperskich\n• Testowanie aplikacji wymagających określonych konfiguracji sieci\n• Łączenie z lokalnymi usługami sieciowymi bez skomplikowanej konfiguracji\n• Tworzenie izolowanych środowisk testowych";
"setup_easy_title" = "Łatwy w użyciu";
"setup_easy_description" = "Połączenie za pomocą jednego kliknięcia";
"setup_easy_details" = "StosVPN został zaprojektowany z myślą o prostocie. Wystarczy kliknąć przycisk połączenia, aby ustanowić lokalny tunel z gotową konfiguracją.";
"setup_privacy_title" = "Skoncentrowany na prywatności";
"setup_privacy_description" = "Twoje dane pozostają na urządzeniu";
"setup_privacy_details" = "StosVPN tworzy lokalny tunel, który nie przekierowuje ruchu przez zewnętrzne serwery. Cały ruch pozostaje na Twoim urządzeniu, zapewniając prywatność i bezpieczeństwo. Żadne dane nie są zbierane ani udostępniane osobom trzecim.";
"setup_nav" = "Konfiguracja";
"setup_get_started" = "Zaczynamy";
"setup_next" = "Dalej";
"setup_skip" = "Pomiń";
/*MARK: Restart pop-up*/
restart_title = "Restartuj";
restart_message = "Aby zastosować zmiany, należy ponownie uruchomić aplikację.";
confirmYes = "Si";
confirmNo = "No";
================================================
FILE: StosVPN/Preview Content/Preview Assets.xcassets/Contents.json
================================================
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
================================================
FILE: StosVPN/StosVPN-Bridging-Header.h
================================================
//
// Use this file to import your target's public headers that you would like to expose to Swift.
//
================================================
FILE: StosVPN/StosVPN.entitlements
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.developer.networking.vpn.api</key>
<array>
<string>allow-vpn</string>
</array>
<key>com.apple.developer.networking.networkextension</key>
<array>
<string>packet-tunnel-provider</string>
</array>
</dict>
</plist>
================================================
FILE: StosVPN/StosVPNApp.swift
================================================
//
// StosVPNApp.swift
// StosVPN
//
// Created by Stossy11 on 28/03/2025.
//
import SwiftUI
@main
struct StosVPNApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
================================================
FILE: StosVPN.xcodeproj/project.pbxproj
================================================
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 70;
objects = {
/* Begin PBXBuildFile section */
0E6351BE2E18EABA002AF750 /* NavigationBackport in Frameworks */ = {isa = PBXBuildFile; productRef = 0E6351BD2E18EABA002AF750 /* NavigationBackport */; };
4EB3C7712D96715400C1B22C /* NetworkExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4EB3C7702D96715400C1B22C /* NetworkExtension.framework */; };
4EB3C7792D96715400C1B22C /* TunnelProv.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 4EB3C76E2D96715400C1B22C /* TunnelProv.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
4EE6B99B2E8F756700E30694 /* AppIcon.icon in Resources */ = {isa = PBXBuildFile; fileRef = 4EE6B99A2E8F756700E30694 /* AppIcon.icon */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
4EB3C7772D96715400C1B22C /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 4EB3C7502D96631A00C1B22C /* Project object */;
proxyType = 1;
remoteGlobalIDString = 4EB3C76D2D96715400C1B22C;
remoteInfo = TunnelProv;
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
4EB3C77E2D96715400C1B22C /* Embed Foundation Extensions */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 13;
files = (
4EB3C7792D96715400C1B22C /* TunnelProv.appex in Embed Foundation Extensions */,
);
name = "Embed Foundation Extensions";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
0E6351B62E18DF53002AF750 /* Build.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Build.xcconfig; sourceTree = "<group>"; };
0E6351B72E18DF53002AF750 /* CodeSigning.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = CodeSigning.xcconfig; sourceTree = "<group>"; };
0E6351B82E18DF53002AF750 /* CodeSigning.xcconfig.sample */ = {isa = PBXFileReference; lastKnownFileType = text; path = CodeSigning.xcconfig.sample; sourceTree = "<group>"; };
4EB3C7582D96631A00C1B22C /* StosVPN.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = StosVPN.app; sourceTree = BUILT_PRODUCTS_DIR; };
4EB3C76E2D96715400C1B22C /* TunnelProv.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = TunnelProv.appex; sourceTree = BUILT_PRODUCTS_DIR; };
4EB3C7702D96715400C1B22C /* NetworkExtension.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = NetworkExtension.framework; path = System/Library/Frameworks/NetworkExtension.framework; sourceTree = SDKROOT; };
4EE6B99A2E8F756700E30694 /* AppIcon.icon */ = {isa = PBXFileReference; lastKnownFileType = folder.iconcomposer.icon; path = AppIcon.icon; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */
4EB3C77A2D96715400C1B22C /* PBXFileSystemSynchronizedBuildFileExceptionSet */ = {
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
membershipExceptions = (
Info.plist,
);
target = 4EB3C76D2D96715400C1B22C /* TunnelProv */;
};
4EB3C7802D9672DE00C1B22C /* PBXFileSystemSynchronizedBuildFileExceptionSet */ = {
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
membershipExceptions = (
Info.plist,
);
target = 4EB3C7572D96631A00C1B22C /* StosVPN */;
};
/* End PBXFileSystemSynchronizedBuildFileExceptionSet section */
/* Begin PBXFileSystemSynchronizedRootGroup section */
4EB3C75A2D96631A00C1B22C /* StosVPN */ = {isa = PBXFileSystemSynchronizedRootGroup; exceptions = (4EB3C7802D9672DE00C1B22C /* PBXFileSystemSynchronizedBuildFileExceptionSet */, ); explicitFileTypes = {}; explicitFolders = (); path = StosVPN; sourceTree = "<group>"; };
4EB3C7722D96715400C1B22C /* TunnelProv */ = {isa = PBXFileSystemSynchronizedRootGroup; exceptions = (4EB3C77A2D96715400C1B22C /* PBXFileSystemSynchronizedBuildFileExceptionSet */, ); explicitFileTypes = {}; explicitFolders = (); path = TunnelProv; sourceTree = "<group>"; };
/* End PBXFileSystemSynchronizedRootGroup section */
/* Begin PBXFrameworksBuildPhase section */
4EB3C7552D96631A00C1B22C /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
0E6351BE2E18EABA002AF750 /* NavigationBackport in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
4EB3C76B2D96715400C1B22C /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
4EB3C7712D96715400C1B22C /* NetworkExtension.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
4EB3C74F2D96631A00C1B22C = {
isa = PBXGroup;
children = (
4EE6B99A2E8F756700E30694 /* AppIcon.icon */,
0E6351B62E18DF53002AF750 /* Build.xcconfig */,
0E6351B72E18DF53002AF750 /* CodeSigning.xcconfig */,
0E6351B82E18DF53002AF750 /* CodeSigning.xcconfig.sample */,
4EB3C75A2D96631A00C1B22C /* StosVPN */,
4EB3C7722D96715400C1B22C /* TunnelProv */,
4EB3C76F2D96715400C1B22C /* Frameworks */,
4EB3C7592D96631A00C1B22C /* Products */,
);
sourceTree = "<group>";
};
4EB3C7592D96631A00C1B22C /* Products */ = {
isa = PBXGroup;
children = (
4EB3C7582D96631A00C1B22C /* StosVPN.app */,
4EB3C76E2D96715400C1B22C /* TunnelProv.appex */,
);
name = Products;
sourceTree = "<group>";
};
4EB3C76F2D96715400C1B22C /* Frameworks */ = {
isa = PBXGroup;
children = (
4EB3C7702D96715400C1B22C /* NetworkExtension.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
4EB3C7572D96631A00C1B22C /* StosVPN */ = {
isa = PBXNativeTarget;
buildConfigurationList = 4EB3C7662D96631B00C1B22C /* Build configuration list for PBXNativeTarget "StosVPN" */;
buildPhases = (
4EB3C7542D96631A00C1B22C /* Sources */,
4EB3C7552D96631A00C1B22C /* Frameworks */,
4EB3C7562D96631A00C1B22C /* Resources */,
4EB3C77E2D96715400C1B22C /* Embed Foundation Extensions */,
);
buildRules = (
);
dependencies = (
4EB3C7782D96715400C1B22C /* PBXTargetDependency */,
);
fileSystemSynchronizedGroups = (
4EB3C75A2D96631A00C1B22C /* StosVPN */,
);
name = StosVPN;
packageProductDependencies = (
0E6351BD2E18EABA002AF750 /* NavigationBackport */,
);
productName = StosVPN;
productReference = 4EB3C7582D96631A00C1B22C /* StosVPN.app */;
productType = "com.apple.product-type.application";
};
4EB3C76D2D96715400C1B22C /* TunnelProv */ = {
isa = PBXNativeTarget;
buildConfigurationList = 4EB3C77B2D96715400C1B22C /* Build configuration list for PBXNativeTarget "TunnelProv" */;
buildPhases = (
4EB3C76A2D96715400C1B22C /* Sources */,
4EB3C76B2D96715400C1B22C /* Frameworks */,
4EB3C76C2D96715400C1B22C /* Resources */,
);
buildRules = (
);
dependencies = (
);
fileSystemSynchronizedGroups = (
4EB3C7722D96715400C1B22C /* TunnelProv */,
);
name = TunnelProv;
packageProductDependencies = (
);
productName = TunnelProv;
productReference = 4EB3C76E2D96715400C1B22C /* TunnelProv.appex */;
productType = "com.apple.product-type.app-extension";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
4EB3C7502D96631A00C1B22C /* Project object */ = {
isa = PBXProject;
attributes = {
BuildIndependentTargetsInParallel = 1;
LastSwiftUpdateCheck = 1620;
LastUpgradeCheck = 1620;
ORGANIZATIONNAME = stossy11;
TargetAttributes = {
4EB3C7572D96631A00C1B22C = {
CreatedOnToolsVersion = 16.2;
LastSwiftMigration = 1620;
};
4EB3C76D2D96715400C1B22C = {
CreatedOnToolsVersion = 16.2;
};
};
};
buildConfigurationList = 4EB3C7532D96631A00C1B22C /* Build configuration list for PBXProject "StosVPN" */;
compatibilityVersion = "Xcode 14.0";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
es,
it,
pl,
);
mainGroup = 4EB3C74F2D96631A00C1B22C;
minimizedProjectReferenceProxies = 1;
packageReferences = (
0E6351BC2E18EABA002AF750 /* XCRemoteSwiftPackageReference "NavigationBackport" */,
);
productRefGroup = 4EB3C7592D96631A00C1B22C /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
4EB3C7572D96631A00C1B22C /* StosVPN */,
4EB3C76D2D96715400C1B22C /* TunnelProv */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
4EB3C7562D96631A00C1B22C /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
4EE6B99B2E8F756700E30694 /* AppIcon.icon in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
4EB3C76C2D96715400C1B22C /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
4EB3C7542D96631A00C1B22C /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
4EB3C76A2D96715400C1B22C /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
4EB3C7782D96715400C1B22C /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 4EB3C76D2D96715400C1B22C /* TunnelProv */;
targetProxy = 4EB3C7772D96715400C1B22C /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin XCBuildConfiguration section */
4EB3C7642D96631B00C1B22C /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 0E6351B62E18DF53002AF750 /* Build.xcconfig */;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_ENTITLEMENTS = "$(TARGET_NAME)/$(TARGET_NAME).entitlements";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = 95J8WZ4TN8;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu17;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = "$(TARGET_NAME)/Info.plist";
INFOPLIST_KEY_CFBundleDisplayName = "$(TARGET_NAME)";
INFOPLIST_KEY_NSHumanReadableCopyright = Stossy11;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
MACOSX_DEPLOYMENT_TARGET = 11.0;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)";
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
TARGETED_DEVICE_FAMILY = "1,2";
TVOS_DEPLOYMENT_TARGET = 15.0;
WATCHOS_DEPLOYMENT_TARGET = 8.0;
XROS_DEPLOYMENT_TARGET = 1.0;
};
name = Debug;
};
4EB3C7652D96631B00C1B22C /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 0E6351B62E18DF53002AF750 /* Build.xcconfig */;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_ENTITLEMENTS = "$(TARGET_NAME)/$(TARGET_NAME).entitlements";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = 95J8WZ4TN8;
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu17;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = "$(TARGET_NAME)/Info.plist";
INFOPLIST_KEY_CFBundleDisplayName = "$(TARGET_NAME)";
INFOPLIST_KEY_NSHumanReadableCopyright = Stossy11;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
MACOSX_DEPLOYMENT_TARGET = 11.0;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_EMIT_LOC_STRINGS = YES;
TARGETED_DEVICE_FAMILY = "1,2";
TVOS_DEPLOYMENT_TARGET = 15.0;
VALIDATE_PRODUCT = YES;
WATCHOS_DEPLOYMENT_TARGET = 8.0;
XROS_DEPLOYMENT_TARGET = 1.0;
};
name = Release;
};
4EB3C7672D96631B00C1B22C /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = YES;
CLANG_ENABLE_MODULES = YES;
DEVELOPMENT_ASSET_PATHS = "\"StosVPN/Preview Content\"";
ENABLE_PREVIEWS = YES;
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
SUPPORTED_PLATFORMS = "appletvos appletvsimulator iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
SWIFT_OBJC_BRIDGING_HEADER = "StosVPN/StosVPN-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2,3";
TVOS_DEPLOYMENT_TARGET = 17.0;
};
name = Debug;
};
4EB3C7682D96631B00C1B22C /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = YES;
CLANG_ENABLE_MODULES = YES;
DEVELOPMENT_ASSET_PATHS = "\"StosVPN/Preview Content\"";
ENABLE_PREVIEWS = YES;
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
SUPPORTED_PLATFORMS = "appletvos appletvsimulator iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
SWIFT_OBJC_BRIDGING_HEADER = "StosVPN/StosVPN-Bridging-Header.h";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2,3";
TVOS_DEPLOYMENT_TARGET = 17.0;
};
name = Release;
};
4EB3C77C2D96715400C1B22C /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
INFOPLIST_KEY_CFBundleDisplayName = TunnelProv;
INFOPLIST_KEY_NSHumanReadableCopyright = Stossy11;
INFOPLIST_KEY_UIRequiredDeviceCapabilities = arm64;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = "$(TUNNEL_BUNDLE_IDENTIFIER)";
SKIP_INSTALL = YES;
SUPPORTED_PLATFORMS = "appletvos appletvsimulator iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
SWIFT_OBJC_BRIDGING_HEADER = "StosVPN/StosVPN-Bridging-Header.h";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2,3";
TVOS_DEPLOYMENT_TARGET = 17.0;
};
name = Debug;
};
4EB3C77D2D96715400C1B22C /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
INFOPLIST_KEY_CFBundleDisplayName = TunnelProv;
INFOPLIST_KEY_NSHumanReadableCopyright = Stossy11;
INFOPLIST_KEY_UIRequiredDeviceCapabilities = arm64;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = "$(TUNNEL_BUNDLE_IDENTIFIER)";
SKIP_INSTALL = YES;
SUPPORTED_PLATFORMS = "appletvos appletvsimulator iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
SWIFT_OBJC_BRIDGING_HEADER = "StosVPN/StosVPN-Bridging-Header.h";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2,3";
TVOS_DEPLOYMENT_TARGET = 17.0;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
4EB3C7532D96631A00C1B22C /* Build configuration list for PBXProject "StosVPN" */ = {
isa = XCConfigurationList;
buildConfigurations = (
4EB3C7642D96631B00C1B22C /* Debug */,
4EB3C7652D96631B00C1B22C /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
4EB3C7662D96631B00C1B22C /* Build configuration list for PBXNativeTarget "StosVPN" */ = {
isa = XCConfigurationList;
buildConfigurations = (
4EB3C7672D96631B00C1B22C /* Debug */,
4EB3C7682D96631B00C1B22C /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
4EB3C77B2D96715400C1B22C /* Build configuration list for PBXNativeTarget "TunnelProv" */ = {
isa = XCConfigurationList;
buildConfigurations = (
4EB3C77C2D96715400C1B22C /* Debug */,
4EB3C77D2D96715400C1B22C /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
/* Begin XCRemoteSwiftPackageReference section */
0E6351BC2E18EABA002AF750 /* XCRemoteSwiftPackageReference "NavigationBackport" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/johnpatrickmorgan/NavigationBackport";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 0.11.5;
};
};
/* End XCRemoteSwiftPackageReference section */
/* Begin XCSwiftPackageProductDependency section */
0E6351BD2E18EABA002AF750 /* NavigationBackport */ = {
isa = XCSwiftPackageProductDependency;
package = 0E6351BC2E18EABA002AF750 /* XCRemoteSwiftPackageReference "NavigationBackport" */;
productName = NavigationBackport;
};
/* End XCSwiftPackageProductDependency section */
};
rootObject = 4EB3C7502D96631A00C1B22C /* Project object */;
}
================================================
FILE: StosVPN.xcodeproj/project.xcworkspace/contents.xcworkspacedata
================================================
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:">
</FileRef>
</Workspace>
================================================
FILE: StosVPN.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
================================================
{
"originHash" : "f57f96c9093592a8dfc088d1e5d0d3894041971d6addbf48412da75073ac96d9",
"pins" : [
{
"identity" : "navigationbackport",
"kind" : "remoteSourceControl",
"location" : "https://github.com/johnpatrickmorgan/NavigationBackport",
"state" : {
"revision" : "5baf99855f6a0a02022f9b479cc41ad99a8e070c",
"version" : "0.11.5"
}
}
],
"version" : 3
}
================================================
FILE: StosVPN.xcodeproj/xcshareddata/xcschemes/StosVPN.xcscheme
================================================
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1620"
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES"
buildArchitectures = "Automatic">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "4EB3C7572D96631A00C1B22C"
BuildableName = "StosVPN.app"
BlueprintName = "StosVPN"
ReferencedContainer = "container:StosVPN.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
shouldAutocreateTestPlan = "YES">
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "4EB3C7572D96631A00C1B22C"
BuildableName = "StosVPN.app"
BlueprintName = "StosVPN"
ReferencedContainer = "container:StosVPN.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "4EB3C7572D96631A00C1B22C"
BuildableName = "StosVPN.app"
BlueprintName = "StosVPN"
ReferencedContainer = "container:StosVPN.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
================================================
FILE: StosVPN.xcodeproj/xcshareddata/xcschemes/TunnelProv.xcscheme
================================================
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1620"
wasCreatedForAppExtension = "YES"
version = "2.0">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES"
buildArchitectures = "Automatic">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "4EB3C76D2D96715400C1B22C"
BuildableName = "TunnelProv.appex"
BlueprintName = "TunnelProv"
ReferencedContainer = "container:StosVPN.xcodeproj">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "4EB3C7572D96631A00C1B22C"
BuildableName = "StosVPN.app"
BlueprintName = "StosVPN"
ReferencedContainer = "container:StosVPN.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
shouldAutocreateTestPlan = "YES">
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = ""
selectedLauncherIdentifier = "Xcode.IDEFoundation.Launcher.PosixSpawn"
launchStyle = "0"
askForAppToLaunch = "Yes"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES"
launchAutomaticallySubstyle = "2">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "4EB3C7572D96631A00C1B22C"
BuildableName = "StosVPN.app"
BlueprintName = "StosVPN"
ReferencedContainer = "container:StosVPN.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES"
askForAppToLaunch = "Yes"
launchAutomaticallySubstyle = "2">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "4EB3C7572D96631A00C1B22C"
BuildableName = "StosVPN.app"
BlueprintName = "StosVPN"
ReferencedContainer = "container:StosVPN.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
================================================
FILE: StosVPN.xcodeproj/xcuserdata/stossy11.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<Bucket
uuid = "E9FBFA8B-D737-454C-9876-DFFB697E8C2D"
type = "1"
version = "2.0">
</Bucket>
================================================
FILE: StosVPN.xcodeproj/xcuserdata/stossy11.xcuserdatad/xcschemes/xcschememanagement.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>SchemeUserState</key>
<dict>
<key>StosVPN.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>0</integer>
</dict>
<key>TunnelProv.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>1</integer>
</dict>
</dict>
<key>SuppressBuildableAutocreation</key>
<dict>
<key>4EB3C7572D96631A00C1B22C</key>
<dict>
<key>primary</key>
<true/>
</dict>
<key>4EB3C76D2D96715400C1B22C</key>
<dict>
<key>primary</key>
<true/>
</dict>
</dict>
</dict>
</plist>
================================================
FILE: TunnelProv/Info.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSExtension</key>
<dict>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.networkextension.packet-tunnel</string>
<key>NSExtensionPrincipalClass</key>
<string>$(PRODUCT_MODULE_NAME).PacketTunnelProvider</string>
</dict>
</dict>
</plist>
================================================
FILE: TunnelProv/PacketTunnelProvider.swift
================================================
//
// PacketTunnelProvider.swift
// TunnelProv
//
// Created by Stossy11 on 28/03/2025.
//
import NetworkExtension
class PacketTunnelProvider: NEPacketTunnelProvider {
var tunnelDeviceIp: String = "10.7.0.0"
var tunnelFakeIp: String = "10.7.0.1"
var tunnelSubnetMask: String = "255.255.255.0"
private var deviceIpValue: UInt32 = 0
private var fakeIpValue: UInt32 = 0
override func startTunnel(options: [String : NSObject]?, completionHandler: @escaping (Error?) -> Void) {
if let deviceIp = options?["TunnelDeviceIP"] as? String {
tunnelDeviceIp = deviceIp
}
if let fakeIp = options?["TunnelFakeIP"] as? String {
tunnelFakeIp = fakeIp
}
deviceIpValue = ipToUInt32(tunnelDeviceIp)
fakeIpValue = ipToUInt32(tunnelFakeIp)
let settings = NEPacketTunnelNetworkSettings(tunnelRemoteAddress: tunnelDeviceIp)
let ipv4 = NEIPv4Settings(addresses: [tunnelDeviceIp], subnetMasks: [tunnelSubnetMask])
ipv4.includedRoutes = [NEIPv4Route(destinationAddress: tunnelDeviceIp, subnetMask: tunnelSubnetMask)]
ipv4.excludedRoutes = [.default()]
settings.ipv4Settings = ipv4
setTunnelNetworkSettings(settings) { error in
guard error == nil else { return completionHandler(error) }
self.setPackets()
completionHandler(nil)
}
}
func setPackets() {
packetFlow.readPackets { [self] packets, protocols in
let fakeip = self.fakeIpValue
let deviceip = self.deviceIpValue
var modified = packets
for i in modified.indices where protocols[i].int32Value == AF_INET && modified[i].count >= 20 {
modified[i].withUnsafeMutableBytes { bytes in
guard let ptr = bytes.baseAddress?.assumingMemoryBound(to: UInt32.self) else { return }
let src = UInt32(bigEndian: ptr[3])
let dst = UInt32(bigEndian: ptr[4])
if src == deviceip { ptr[3] = fakeip.bigEndian }
if dst == fakeip { ptr[4] = deviceip.bigEndian }
}
}
self.packetFlow.writePackets(modified, withProtocols: protocols)
setPackets()
}
}
private func ipToUInt32(_ ipString: String) -> UInt32 {
let components = ipString.split(separator: ".")
guard components.count == 4,
let b1 = UInt32(components[0]),
let b2 = UInt32(components[1]),
let b3 = UInt32(components[2]),
let b4 = UInt32(components[3]) else {
return 0
}
return (b1 << 24) | (b2 << 16) | (b3 << 8) | b4
}
}
================================================
FILE: TunnelProv/TunnelProv.entitlements
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.developer.networking.networkextension</key>
<array>
<string>packet-tunnel-provider</string>
</array>
</dict>
</plist>
gitextract_se04d3hj/
├── .github/
│ └── workflows/
│ └── build.yml
├── .gitignore
├── AppIcon.icon/
│ └── icon.json
├── Build.xcconfig
├── CodeSigning.xcconfig.sample
├── LICENSE
├── LICENSE-old
├── README.md
├── StosVPN/
│ ├── Assets.xcassets/
│ │ ├── AccentColor.colorset/
│ │ │ └── Contents.json
│ │ ├── AppIcon.appiconset/
│ │ │ └── Contents.json
│ │ ├── AppIcon.brandassets/
│ │ │ ├── App Icon - App Store.imagestack/
│ │ │ │ ├── Back.imagestacklayer/
│ │ │ │ │ ├── Content.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── Contents.json
│ │ │ │ ├── Front.imagestacklayer/
│ │ │ │ │ ├── Content.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ └── Contents.json
│ │ │ │ └── Middle.imagestacklayer/
│ │ │ │ ├── Content.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ └── Contents.json
│ │ │ ├── AppIcon.imagestack/
│ │ │ │ ├── Back.imagestacklayer/
│ │ │ │ │ ├── Content.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── Contents.json
│ │ │ │ ├── Front.imagestacklayer/
│ │ │ │ │ ├── Content.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ └── Contents.json
│ │ │ │ └── Middle.imagestacklayer/
│ │ │ │ ├── Content.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ └── Contents.json
│ │ │ ├── Contents.json
│ │ │ ├── Top Shelf Image Wide.imageset/
│ │ │ │ └── Contents.json
│ │ │ └── Top Shelf Image.imageset/
│ │ │ └── Contents.json
│ │ └── Contents.json
│ ├── ContentView.swift
│ ├── Info.plist
│ ├── Localization/
│ │ ├── en.lproj/
│ │ │ └── Localizable.strings
│ │ ├── es.lproj/
│ │ │ └── Localizable.strings
│ │ ├── it.lproj/
│ │ │ └── Localizable.strings
│ │ └── pl.lproj/
│ │ └── Localizable.strings
│ ├── Preview Content/
│ │ └── Preview Assets.xcassets/
│ │ └── Contents.json
│ ├── StosVPN-Bridging-Header.h
│ ├── StosVPN.entitlements
│ └── StosVPNApp.swift
├── StosVPN.xcodeproj/
│ ├── project.pbxproj
│ ├── project.xcworkspace/
│ │ ├── contents.xcworkspacedata
│ │ ├── xcshareddata/
│ │ │ └── swiftpm/
│ │ │ └── Package.resolved
│ │ └── xcuserdata/
│ │ └── stossy11.xcuserdatad/
│ │ └── UserInterfaceState.xcuserstate
│ ├── xcshareddata/
│ │ └── xcschemes/
│ │ ├── StosVPN.xcscheme
│ │ └── TunnelProv.xcscheme
│ └── xcuserdata/
│ └── stossy11.xcuserdatad/
│ ├── xcdebugger/
│ │ └── Breakpoints_v2.xcbkptlist
│ └── xcschemes/
│ └── xcschememanagement.plist
└── TunnelProv/
├── Info.plist
├── PacketTunnelProvider.swift
└── TunnelProv.entitlements
Condensed preview — 49 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (144K chars).
[
{
"path": ".github/workflows/build.yml",
"chars": 2468,
"preview": "name: Build IPA with Fake Signing\n\non:\n push:\n branches: [main] # Or your default branch\n workflow_dispatch"
},
{
"path": ".gitignore",
"chars": 48,
"preview": "CodeSigning.xcconfig\n*.ipa\n/build\n\n**/.DS_Store\n"
},
{
"path": "AppIcon.icon/icon.json",
"chars": 616,
"preview": "{\n \"fill\" : {\n \"automatic-gradient\" : \"display-p3:0.23889,0.54053,0.96826,1.00000\"\n },\n \"groups\" : [\n {\n \""
},
{
"path": "Build.xcconfig",
"chars": 685,
"preview": "// Configuration settings file format documentation can be found at:\n// https://help.apple.com/xcode/#/dev745c5c974\n\nMAR"
},
{
"path": "CodeSigning.xcconfig.sample",
"chars": 1435,
"preview": "// Your Team ID. \n// If you have a paid Apple Developer account, you can find your Team ID at \n// https://developer.appl"
},
{
"path": "LICENSE",
"chars": 1650,
"preview": "StosVPN License\n\nCopyright (c) 2025 SideStore Team\n\nPermission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "LICENSE-old",
"chars": 1071,
"preview": "MIT License\n\nCopyright (c) 2025 SideStore Team\n\nPermission is hereby granted, free of charge, to any person obtaining a "
},
{
"path": "README.md",
"chars": 103,
"preview": "# StosVPN\n\nA VPN for SideStore and StikJIT that is much more stable and supports offline JIT Enabling.\n"
},
{
"path": "StosVPN/Assets.xcassets/AccentColor.colorset/Contents.json",
"chars": 123,
"preview": "{\n \"colors\" : [\n {\n \"idiom\" : \"universal\"\n }\n ],\n \"info\" : {\n \"author\" : \"xcode\",\n \"version\" : 1\n }"
},
{
"path": "StosVPN/Assets.xcassets/AppIcon.appiconset/Contents.json",
"chars": 646,
"preview": "{\n \"images\" : [\n {\n \"filename\" : \"StosVPN-icon.jpg\",\n \"idiom\" : \"universal\",\n \"platform\" : \"ios\",\n "
},
{
"path": "StosVPN/Assets.xcassets/AppIcon.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Content.imageset/Contents.json",
"chars": 159,
"preview": "{\n \"images\" : [\n {\n \"filename\" : \"1280x768 copy 3.jpeg\",\n \"idiom\" : \"tv\"\n }\n ],\n \"info\" : {\n \"auth"
},
{
"path": "StosVPN/Assets.xcassets/AppIcon.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Contents.json",
"chars": 63,
"preview": "{\n \"info\" : {\n \"author\" : \"xcode\",\n \"version\" : 1\n }\n}\n"
},
{
"path": "StosVPN/Assets.xcassets/AppIcon.brandassets/App Icon - App Store.imagestack/Contents.json",
"chars": 250,
"preview": "{\n \"info\" : {\n \"author\" : \"xcode\",\n \"version\" : 1\n },\n \"layers\" : [\n {\n \"filename\" : \"Front.imagestackl"
},
{
"path": "StosVPN/Assets.xcassets/AppIcon.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Content.imageset/Contents.json",
"chars": 151,
"preview": "{\n \"images\" : [\n {\n \"filename\" : \"1280x768.png\",\n \"idiom\" : \"tv\"\n }\n ],\n \"info\" : {\n \"author\" : \"x"
},
{
"path": "StosVPN/Assets.xcassets/AppIcon.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Contents.json",
"chars": 63,
"preview": "{\n \"info\" : {\n \"author\" : \"xcode\",\n \"version\" : 1\n }\n}\n"
},
{
"path": "StosVPN/Assets.xcassets/AppIcon.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json",
"chars": 159,
"preview": "{\n \"images\" : [\n {\n \"filename\" : \"1280x768 copy 3.jpeg\",\n \"idiom\" : \"tv\"\n }\n ],\n \"info\" : {\n \"auth"
},
{
"path": "StosVPN/Assets.xcassets/AppIcon.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Contents.json",
"chars": 63,
"preview": "{\n \"info\" : {\n \"author\" : \"xcode\",\n \"version\" : 1\n }\n}\n"
},
{
"path": "StosVPN/Assets.xcassets/AppIcon.brandassets/AppIcon.imagestack/Back.imagestacklayer/Content.imageset/Contents.json",
"chars": 265,
"preview": "{\n \"images\" : [\n {\n \"filename\" : \"Content.png\",\n \"idiom\" : \"tv\",\n \"scale\" : \"1x\"\n },\n {\n \""
},
{
"path": "StosVPN/Assets.xcassets/AppIcon.brandassets/AppIcon.imagestack/Back.imagestacklayer/Contents.json",
"chars": 63,
"preview": "{\n \"info\" : {\n \"author\" : \"xcode\",\n \"version\" : 1\n }\n}\n"
},
{
"path": "StosVPN/Assets.xcassets/AppIcon.brandassets/AppIcon.imagestack/Contents.json",
"chars": 250,
"preview": "{\n \"info\" : {\n \"author\" : \"xcode\",\n \"version\" : 1\n },\n \"layers\" : [\n {\n \"filename\" : \"Front.imagestackl"
},
{
"path": "StosVPN/Assets.xcassets/AppIcon.brandassets/AppIcon.imagestack/Front.imagestacklayer/Content.imageset/Contents.json",
"chars": 258,
"preview": "{\n \"images\" : [\n {\n \"filename\" : \"cool.png\",\n \"idiom\" : \"tv\",\n \"scale\" : \"1x\"\n },\n {\n \"fil"
},
{
"path": "StosVPN/Assets.xcassets/AppIcon.brandassets/AppIcon.imagestack/Front.imagestacklayer/Contents.json",
"chars": 63,
"preview": "{\n \"info\" : {\n \"author\" : \"xcode\",\n \"version\" : 1\n }\n}\n"
},
{
"path": "StosVPN/Assets.xcassets/AppIcon.brandassets/AppIcon.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json",
"chars": 265,
"preview": "{\n \"images\" : [\n {\n \"filename\" : \"Content.png\",\n \"idiom\" : \"tv\",\n \"scale\" : \"1x\"\n },\n {\n \""
},
{
"path": "StosVPN/Assets.xcassets/AppIcon.brandassets/AppIcon.imagestack/Middle.imagestacklayer/Contents.json",
"chars": 63,
"preview": "{\n \"info\" : {\n \"author\" : \"xcode\",\n \"version\" : 1\n }\n}\n"
},
{
"path": "StosVPN/Assets.xcassets/AppIcon.brandassets/Contents.json",
"chars": 662,
"preview": "{\n \"assets\" : [\n {\n \"filename\" : \"App Icon - App Store.imagestack\",\n \"idiom\" : \"tv\",\n \"role\" : \"prima"
},
{
"path": "StosVPN/Assets.xcassets/AppIcon.brandassets/Top Shelf Image Wide.imageset/Contents.json",
"chars": 282,
"preview": "{\n \"images\" : [\n {\n \"filename\" : \"1280x768 copy 4.jpeg\",\n \"idiom\" : \"tv\",\n \"scale\" : \"1x\"\n },\n "
},
{
"path": "StosVPN/Assets.xcassets/AppIcon.brandassets/Top Shelf Image.imageset/Contents.json",
"chars": 280,
"preview": "{\n \"images\" : [\n {\n \"filename\" : \"1280x768 copy 4.jpeg\",\n \"idiom\" : \"tv\",\n \"scale\" : \"1x\"\n },\n "
},
{
"path": "StosVPN/Assets.xcassets/Contents.json",
"chars": 63,
"preview": "{\n \"info\" : {\n \"author\" : \"xcode\",\n \"version\" : 1\n }\n}\n"
},
{
"path": "StosVPN/ContentView.swift",
"chars": 50767,
"preview": "//\n// ContentView.swift\n// StosVPN\n//\n// Created by Stossy11 on 28/03/2025.\n//\n\nimport SwiftUI\nimport Foundation\nimpo"
},
{
"path": "StosVPN/Info.plist",
"chars": 276,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
},
{
"path": "StosVPN/Localization/en.lproj/Localizable.strings",
"chars": 7357,
"preview": "/* MARK: Start Screen */\n\n\"disconnected\" = \"Disconnected\";\n\"connecting\" = \"Connecting\";\n\"connected\" = \"Connected\";\n\"disc"
},
{
"path": "StosVPN/Localization/es.lproj/Localizable.strings",
"chars": 7942,
"preview": "/* MARK: Pantalla de inicio */\n\n\"disconnected\" = \"Desconectado\";\n\"connecting\" = \"Conectando\";\n\"connected\" = \"Conectado\";"
},
{
"path": "StosVPN/Localization/it.lproj/Localizable.strings",
"chars": 10084,
"preview": "/* MARK: Start Screen */\n\n\"disconnected\" = \"Disconnesso\";\n\"connecting\" = \"Connessione in corso\";\n\"connected\" = \"Connesso"
},
{
"path": "StosVPN/Localization/pl.lproj/Localizable.strings",
"chars": 7949,
"preview": "/* MARK: Start Screen */\n\n\"disconnected\" = \"Rozłączony\";\n\"connecting\" = \"Łączenie\";\n\"connected\" = \"Połączony\";\n\"disconne"
},
{
"path": "StosVPN/Preview Content/Preview Assets.xcassets/Contents.json",
"chars": 63,
"preview": "{\n \"info\" : {\n \"author\" : \"xcode\",\n \"version\" : 1\n }\n}\n"
},
{
"path": "StosVPN/StosVPN-Bridging-Header.h",
"chars": 104,
"preview": "//\n// Use this file to import your target's public headers that you would like to expose to Swift.\n//\n\n"
},
{
"path": "StosVPN/StosVPN.entitlements",
"chars": 408,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
},
{
"path": "StosVPN/StosVPNApp.swift",
"chars": 222,
"preview": "//\n// StosVPNApp.swift\n// StosVPN\n//\n// Created by Stossy11 on 28/03/2025.\n//\n\nimport SwiftUI\n\n@main\nstruct StosVPNAp"
},
{
"path": "StosVPN.xcodeproj/project.pbxproj",
"chars": 22121,
"preview": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 70;\n\tobjects = {\n\n/* Begin PBXBuildFile section *"
},
{
"path": "StosVPN.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
"chars": 135,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n version = \"1.0\">\n <FileRef\n location = \"self:\">\n </FileRef"
},
{
"path": "StosVPN.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved",
"chars": 412,
"preview": "{\n \"originHash\" : \"f57f96c9093592a8dfc088d1e5d0d3894041971d6addbf48412da75073ac96d9\",\n \"pins\" : [\n {\n \"identit"
},
{
"path": "StosVPN.xcodeproj/xcshareddata/xcschemes/StosVPN.xcscheme",
"chars": 2881,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n LastUpgradeVersion = \"1620\"\n version = \"1.7\">\n <BuildAction\n "
},
{
"path": "StosVPN.xcodeproj/xcshareddata/xcschemes/TunnelProv.xcscheme",
"chars": 3607,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n LastUpgradeVersion = \"1620\"\n wasCreatedForAppExtension = \"YES\"\n ve"
},
{
"path": "StosVPN.xcodeproj/xcuserdata/stossy11.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist",
"chars": 140,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Bucket\n uuid = \"E9FBFA8B-D737-454C-9876-DFFB697E8C2D\"\n type = \"1\"\n version"
},
{
"path": "StosVPN.xcodeproj/xcuserdata/stossy11.xcuserdatad/xcschemes/xcschememanagement.plist",
"chars": 693,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
},
{
"path": "TunnelProv/Info.plist",
"chars": 431,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
},
{
"path": "TunnelProv/PacketTunnelProvider.swift",
"chars": 2771,
"preview": "//\n// PacketTunnelProvider.swift\n// TunnelProv\n//\n// Created by Stossy11 on 28/03/2025.\n//\n\nimport NetworkExtension\n\n"
},
{
"path": "TunnelProv/TunnelProv.entitlements",
"chars": 309,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
}
]
// ... and 1 more files (download for full content)
About this extraction
This page contains the full source code of the SideStore/StosVPN GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 49 files (127.9 KB), approximately 34.4k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.