[
  {
    "path": ".gitignore",
    "content": "# Xcode\n#\n# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore\n\n## User settings\nxcuserdata/\n\n## Obj-C/Swift specific\n*.hmap\n\n## App packaging\n*.ipa\n*.dSYM.zip\n*.dSYM\n\n## Playgrounds\ntimeline.xctimeline\nplayground.xcworkspace\n\n# Swift Package Manager\n#\n# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.\n# Packages/\n# Package.pins\n# Package.resolved\n# *.xcodeproj\n#\n# Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata\n# hence it is not needed unless you have added a package configuration file to your project\n# .swiftpm\n\n.build/\n\n# CocoaPods\n#\n# We recommend against adding the Pods directory to your .gitignore. However\n# you should judge for yourself, the pros and cons are mentioned at:\n# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control\n#\n# Pods/\n#\n# Add this line if you want to avoid checking in source code from the Xcode workspace\n# *.xcworkspace\n\n# Carthage\n#\n# Add this line if you want to avoid checking in source code from Carthage dependencies.\n# Carthage/Checkouts\n\nCarthage/Build/\n\n# fastlane\n#\n# It is recommended to not store the screenshots in the git repo.\n# Instead, use fastlane to re-generate the screenshots whenever they are needed.\n# For more information about the recommended setup visit:\n# https://docs.fastlane.tools/best-practices/source-control/#source-control\n\nfastlane/report.xml\nfastlane/Preview.html\nfastlane/screenshots/**/*.png\nfastlane/test_output\n\n.DS_Store"
  },
  {
    "path": "DNS Easy Switcher/AboutView.swift",
    "content": "//\n//  AboutView.swift\n//  DNS Easy Switcher\n//\n//  Created by Gregory LINFORD on 27/02/2025.\n//\n\nimport SwiftUI\n\nstruct AboutView: View {\n    var onClose: () -> Void\n    \n    private var versionText: String {\n        let shortVersion = Bundle.main.infoDictionary?[\"CFBundleShortVersionString\"] as? String ?? \"Unknown\"\n        let buildNumber = Bundle.main.infoDictionary?[\"CFBundleVersion\"] as? String ?? \"\"\n        return buildNumber.isEmpty ? \"Version \\(shortVersion)\" : \"Version \\(shortVersion) (\\(buildNumber))\"\n    }\n    \n    var body: some View {\n        VStack(alignment: .leading, spacing: 12) {\n            Text(\"DNS Easy Switcher\")\n                .font(.headline)\n            \n            Text(versionText)\n                .foregroundColor(.secondary)\n            \n            Link(\"GitHub — glinford/dns-easy-switcher\", destination: URL(string: \"https://github.com/glinford/dns-easy-switcher\")!)\n            \n            HStack {\n                Spacer()\n                Button(\"Close\") {\n                    onClose()\n                }\n                .keyboardShortcut(.escape)\n            }\n            .padding(.top, 8)\n        }\n        .padding()\n        .frame(width: 320)\n    }\n}\n"
  },
  {
    "path": "DNS Easy Switcher/AddCustomDNSView.swift",
    "content": "//\n//  AddCustomDNSView.swift\n//  DNS Easy Switcher\n//\n//  Created by Gregory LINFORD on 23/02/2025.\n//\n\nimport SwiftUI\nimport SwiftData\n\nstruct AddCustomDNSView: View {\n    @State private var name: String = \"\"\n    @State private var primaryDNS: String = \"\"\n    @State private var secondaryDNS: String = \"\"\n    @State private var tertiaryDNS: String = \"\"\n    @State private var quaternaryDNS: String = \"\"\n    var onComplete: (CustomDNSServer?) -> Void\n    \n    var body: some View {\n        VStack(alignment: .leading, spacing: 12) {\n            TextField(\"Name (e.g. Work DNS)\", text: $name)\n                .textFieldStyle(.roundedBorder)\n            \n            TextField(\"Primary DNS (e.g. 8.8.8.8 or 127.0.0.1:5353)\", text: $primaryDNS)\n                .textFieldStyle(.roundedBorder)\n                .help(\"Use comma to add multiple addresses. For custom ports on IPv4, add colon and port number (e.g., 127.0.0.1:5353)\")\n\n            TextField(\"Secondary DNS (optional)\", text: $secondaryDNS)\n                .textFieldStyle(.roundedBorder)\n                .help(\"Use comma to add multiple addresses. For custom ports on IPv4, add colon and port number (e.g., 127.0.0.1:5353)\")\n            \n            TextField(\"Third DNS (IPv6 or IPv4, optional)\", text: $tertiaryDNS)\n                .textFieldStyle(.roundedBorder)\n                .help(\"Tip: bracket IPv6 if adding a port, e.g., [2001:4860:4860::8888]:5353\")\n            \n            TextField(\"Fourth DNS (IPv6 or IPv4, optional)\", text: $quaternaryDNS)\n                .textFieldStyle(.roundedBorder)\n                .help(\"Use comma to add multiple IPv6 entries if needed\")\n            \n            HStack {\n                Button(\"Cancel\") {\n                    onComplete(nil)\n                }\n                .keyboardShortcut(.escape)\n                \n                Spacer()\n                \n                Button(\"Add\") {\n                    guard !name.isEmpty && !primaryDNS.isEmpty else { return }\n                    let server = CustomDNSServer(\n                        name: name,\n                        primaryDNS: primaryDNS,\n                        secondaryDNS: secondaryDNS,\n                        tertiaryDNS: tertiaryDNS,\n                        quaternaryDNS: quaternaryDNS\n                    )\n                    onComplete(server)\n                }\n                .keyboardShortcut(.return)\n                .disabled(name.isEmpty || primaryDNS.isEmpty)\n            }\n        }\n        .padding()\n        .frame(width: 360)\n    }\n}\n"
  },
  {
    "path": "DNS Easy Switcher/Assets.xcassets/AccentColor.colorset/Contents.json",
    "content": "{\n  \"colors\" : [\n    {\n      \"idiom\" : \"universal\"\n    }\n  ],\n  \"info\" : {\n    \"author\" : \"xcode\",\n    \"version\" : 1\n  }\n}\n"
  },
  {
    "path": "DNS Easy Switcher/Assets.xcassets/AppIcon.appiconset/Contents.json",
    "content": "{\"images\":[{\"size\":\"1024x1024\",\"filename\":\"1024-mac.png\",\"expected-size\":\"1024\",\"idiom\":\"ios-marketing\",\"folder\":\"Assets.xcassets/AppIcon.appiconset/\",\"scale\":\"1x\"},{\"size\":\"128x128\",\"expected-size\":\"128\",\"filename\":\"128-mac.png\",\"folder\":\"Assets.xcassets/AppIcon.appiconset/\",\"idiom\":\"mac\",\"scale\":\"1x\"},{\"size\":\"256x256\",\"expected-size\":\"256\",\"filename\":\"256-mac.png\",\"folder\":\"Assets.xcassets/AppIcon.appiconset/\",\"idiom\":\"mac\",\"scale\":\"1x\"},{\"size\":\"128x128\",\"expected-size\":\"256\",\"filename\":\"256-mac.png\",\"folder\":\"Assets.xcassets/AppIcon.appiconset/\",\"idiom\":\"mac\",\"scale\":\"2x\"},{\"size\":\"256x256\",\"expected-size\":\"512\",\"filename\":\"512-mac.png\",\"folder\":\"Assets.xcassets/AppIcon.appiconset/\",\"idiom\":\"mac\",\"scale\":\"2x\"},{\"size\":\"32x32\",\"expected-size\":\"32\",\"filename\":\"32-mac.png\",\"folder\":\"Assets.xcassets/AppIcon.appiconset/\",\"idiom\":\"mac\",\"scale\":\"1x\"},{\"size\":\"512x512\",\"expected-size\":\"512\",\"filename\":\"512-mac.png\",\"folder\":\"Assets.xcassets/AppIcon.appiconset/\",\"idiom\":\"mac\",\"scale\":\"1x\"},{\"size\":\"16x16\",\"expected-size\":\"16\",\"filename\":\"16-mac.png\",\"folder\":\"Assets.xcassets/AppIcon.appiconset/\",\"idiom\":\"mac\",\"scale\":\"1x\"},{\"size\":\"16x16\",\"expected-size\":\"32\",\"filename\":\"32-mac.png\",\"folder\":\"Assets.xcassets/AppIcon.appiconset/\",\"idiom\":\"mac\",\"scale\":\"2x\"},{\"size\":\"32x32\",\"expected-size\":\"64\",\"filename\":\"64-mac.png\",\"folder\":\"Assets.xcassets/AppIcon.appiconset/\",\"idiom\":\"mac\",\"scale\":\"2x\"},{\"size\":\"512x512\",\"expected-size\":\"1024\",\"filename\":\"1024-mac.png\",\"folder\":\"Assets.xcassets/AppIcon.appiconset/\",\"idiom\":\"mac\",\"scale\":\"2x\"}]}"
  },
  {
    "path": "DNS Easy Switcher/Assets.xcassets/Contents.json",
    "content": "{\n  \"info\" : {\n    \"author\" : \"xcode\",\n    \"version\" : 1\n  }\n}\n"
  },
  {
    "path": "DNS Easy Switcher/CustomDNSManagerView.swift",
    "content": "//\n//  CustomDNSManagerView.swift\n//  DNS Easy Switcher\n//\n//  Created by Gregory LINFORD on 25/02/2025.\n//\n\nimport SwiftUI\n\nenum CustomDNSAction {\n    case use, edit, delete\n}\n\nstruct CustomDNSManagerView: View {\n    let customServers: [CustomDNSServer]\n    let onAction: (CustomDNSAction, CustomDNSServer) -> Void\n    let onClose: () -> Void\n    \n    var body: some View {\n        VStack(alignment: .leading, spacing: 8) {\n            Text(\"Manage Custom DNS\")\n                .font(.headline)\n                .padding(.bottom, 4)\n            \n            if customServers.isEmpty {\n                Text(\"No custom DNS servers added\")\n                    .foregroundColor(.secondary)\n                    .padding(.vertical, 12)\n            } else {\n                List {\n                    ForEach(customServers) { server in\n                        HStack {\n                            Text(server.name)\n                                .lineLimit(1)\n                            \n                            Spacer()\n                            \n                            Button(action: {\n                                onAction(.edit, server)\n                            }) {\n                                Image(systemName: \"pencil\")\n                                    .frame(width: 16, height: 16)\n                            }\n                            .buttonStyle(.plain)\n                            .help(\"Edit this DNS\")\n                            .padding(.trailing, 8)\n                            \n                            Button(action: {\n                                onAction(.delete, server)\n                            }) {\n                                Image(systemName: \"trash\")\n                                    .frame(width: 16, height: 16)\n                            }\n                            .buttonStyle(.plain)\n                            .foregroundColor(.red)\n                            .help(\"Delete this DNS\")\n                        }\n                        .padding(.vertical, 4)\n                    }\n                }\n                .frame(minHeight: 100, maxHeight: 200)\n                .listStyle(.plain)\n            }\n            \n            HStack {\n                Spacer()\n                Button(\"Close\") {\n                    onClose()\n                }\n                .keyboardShortcut(.escape)\n            }\n            .padding(.top, 8)\n        }\n        .padding()\n        .frame(width: 300)\n    }\n}\n"
  },
  {
    "path": "DNS Easy Switcher/CustomSheet.swift",
    "content": "//\n//  CustomSheet.swift\n//  DNS Easy Switcher\n//\n//  Created by Gregory LINFORD on 23/02/2025.\n//\n\nimport SwiftUI\nimport AppKit\n\nclass CustomSheetWindowController: NSWindowController {\n    convenience init(view: some View, title: String) {\n        let window = NSWindow(\n            contentRect: NSRect(x: 0, y: 0, width: 300, height: 200),\n            styleMask: [.titled, .closable],\n            backing: .buffered,\n            defer: false\n        )\n        window.title = title\n        window.center()\n        window.contentView = NSHostingView(rootView: view)\n        window.isReleasedWhenClosed = false\n        self.init(window: window)\n    }\n}\n"
  },
  {
    "path": "DNS Easy Switcher/DNSManager.swift",
    "content": "//\n//  DNSManager.swift\n//  DNS Easy Switcher\n//\n//  Created by Gregory LINFORD on 23/02/2025.\n//\n\nimport Foundation\nimport AppKit\nimport LocalAuthentication\n\nclass DNSManager {\n    static let shared = DNSManager()\n    \n    let cloudflareServers = [\n        \"1.1.1.1\",           // IPv4 Primary\n        \"1.0.0.1\",           // IPv4 Secondary\n        \"2606:4700:4700::1111\",  // IPv6 Primary\n        \"2606:4700:4700::1001\"   // IPv6 Secondary\n    ]\n    \n    let quad9Servers = [\n        \"9.9.9.9\",              // IPv4 Primary\n        \"149.112.112.112\",      // IPv4 Secondary\n        \"2620:fe::fe\",          // IPv6 Primary\n        \"2620:fe::9\"            // IPv6 Secondary\n    ]\n    \n    let adguardServers = [\n        \"94.140.14.14\",       // IPv4 Primary\n        \"94.140.15.15\",       // IPv4 Secondary\n        \"2a10:50c0::ad1:ff\",  // IPv6 Primary\n        \"2a10:50c0::ad2:ff\"   // IPv6 Secondary\n    ]\n    \n    let getflixServers: [String: String] = [\n        \"Australia — Melbourne\": \"118.127.62.178\",\n        \"Australia — Perth\": \"45.248.78.99\",\n        \"Australia — Sydney 1\": \"54.252.183.4\",\n        \"Australia — Sydney 2\": \"54.252.183.5\",\n        \"Brazil — São Paulo\": \"54.94.175.250\",\n        \"Canada — Toronto\": \"169.53.182.124\",\n        \"Denmark — Copenhagen\": \"82.103.129.240\",\n        \"Germany — Frankfurt\": \"54.93.169.181\",\n        \"Great Britain — London\": \"212.71.249.225\",\n        \"Hong Kong\": \"119.9.73.44\",\n        \"India — Mumbai\": \"103.13.112.251\",\n        \"Ireland — Dublin\": \"54.72.70.84\",\n        \"Italy — Milan\": \"95.141.39.238\",\n        \"Japan — Tokyo\": \"172.104.90.123\",\n        \"Netherlands — Amsterdam\": \"46.166.189.67\",\n        \"New Zealand — Auckland 1\": \"120.138.27.84\",\n        \"New Zealand — Auckland 2\": \"120.138.22.174\",\n        \"Singapore\": \"54.251.190.247\",\n        \"South Africa — Johannesburg\": \"102.130.116.140\",\n        \"Spain — Madrid\": \"185.93.3.168\",\n        \"Sweden — Stockholm\": \"46.246.29.68\",\n        \"Turkey — Istanbul\": \"212.68.53.190\",\n        \"United States — Dallas (Central)\": \"169.55.51.86\",\n        \"United States — Oregon (West)\": \"54.187.61.200\",\n        \"United States — Virginia (East)\": \"54.164.176.2\"\n    ]\n    \n    private func getNetworkServices() -> [String] {\n        let task = Process()\n        task.launchPath = \"/usr/sbin/networksetup\"\n        task.arguments = [\"-listallnetworkservices\"]\n        \n        let pipe = Pipe()\n        task.standardOutput = pipe\n        \n        do {\n            try task.run()\n            let data = pipe.fileHandleForReading.readDataToEndOfFile()\n            if let services = String(data: data, encoding: .utf8) {\n                return services.components(separatedBy: .newlines)\n                    .dropFirst() // Drop the header line\n                    .filter { !$0.isEmpty && !$0.hasPrefix(\"*\") } // Remove empty lines and disabled services\n            }\n        } catch {\n            print(\"Error getting network services: \\(error)\")\n        }\n        return []\n    }\n    \n    private func findActiveServices() -> [String] {\n        let services = getNetworkServices()\n        let activeServices = services.filter {\n            $0.lowercased().contains(\"wi-fi\") || $0.lowercased().contains(\"ethernet\")\n        }\n        return activeServices.isEmpty ? [services.first].compactMap { $0 } : activeServices\n    }\n    \n    private func executeWithAuthentication(command: String, completion: @escaping (Bool) -> Void) {\n            let context = LAContext()\n            context.localizedReason = \"DNS Easy Switcher needs to modify network settings\"\n            \n            var error: NSError?\n            if context.canEvaluatePolicy(.deviceOwnerAuthentication, error: &error) {\n                context.evaluatePolicy(.deviceOwnerAuthentication, localizedReason: \"DNS Easy Switcher needs to modify network settings\") { success, error in\n                    if success {\n                        DispatchQueue.global(qos: .userInitiated).async {\n                            let task = Process()\n                            task.launchPath = \"/bin/bash\"\n                            task.arguments = [\"-c\", command]\n                            \n                            let pipe = Pipe()\n                            task.standardOutput = pipe\n                            \n                            do {\n                                try task.run()\n                                task.waitUntilExit()\n                                \n                                let success = task.terminationStatus == 0\n                                DispatchQueue.main.async { completion(success) }\n                            } catch {\n                                print(\"Failed to execute command: \\(error)\")\n                                DispatchQueue.main.async { completion(false) }\n                            }\n                        }\n                    } else {\n                        print(\"Authentication failed: \\(error?.localizedDescription ?? \"Unknown error\")\")\n                        DispatchQueue.main.async { completion(false) }\n                    }\n                }\n            } else {\n                // Fall back to AppleScript for admin privileges\n                print(\"Local Authentication not available: \\(error?.localizedDescription ?? \"Unknown error\")\")\n                \n                DispatchQueue.global(qos: .userInitiated).async {\n                    let script = \"\"\"\n                    do shell script \"\\(command)\" with administrator privileges\n                    \"\"\"\n                    \n                    var scriptError: NSDictionary?\n                    if let scriptObject = NSAppleScript(source: script) {\n                        if scriptObject.executeAndReturnError(&scriptError) != nil {\n                            DispatchQueue.main.async { completion(true) }\n                        } else {\n                            print(\"AppleScript error: \\(scriptError ?? [\"error\": \"Unknown error\"] as NSDictionary)\")\n                            DispatchQueue.main.async { completion(false) }\n                        }\n                    } else {\n                        DispatchQueue.main.async { completion(false) }\n                    }\n                }\n            }\n        }\n    \n    func setPredefinedDNS(dnsServers: [String], completion: @escaping (Bool) -> Void) {\n        let services = findActiveServices()\n        guard !services.isEmpty else {\n            completion(false)\n            return\n        }\n        \n        let dispatchGroup = DispatchGroup()\n        var allSucceeded = true\n        \n        for service in services {\n            dispatchGroup.enter()\n            \n            let dnsArgs = dnsServers.joined(separator: \" \")\n            let dnsCommand = \"/usr/sbin/networksetup -setdnsservers '\\(service)' \\(dnsArgs)\"\n            let ipv6Command = \"/usr/sbin/networksetup -setv6off '\\(service)'; /usr/sbin/networksetup -setv6automatic '\\(service)'\"\n            let fullCommand = \"\\(dnsCommand); \\(ipv6Command)\"\n            \n            executeWithAuthentication(command: fullCommand) { success in\n                if !success {\n                    allSucceeded = false\n                }\n                dispatchGroup.leave()\n            }\n        }\n        \n        dispatchGroup.notify(queue: .main) {\n            completion(allSucceeded)\n        }\n    }\n        \n    func setCustomDNS(servers rawServers: [String], completion: @escaping (Bool) -> Void) {\n        let services = findActiveServices()\n        // Allow comma-separated entries in any slot\n        let flattenedServers = rawServers\n            .flatMap { entry in\n                entry\n                    .split(separator: \",\")\n                    .map { $0.trimmingCharacters(in: .whitespacesAndNewlines) }\n            }\n            .filter { !$0.isEmpty }\n        let parsedServers = flattenedServers.compactMap(parseDNSServer)\n        \n        guard !services.isEmpty, !parsedServers.isEmpty else {\n            completion(false)\n            return\n        }\n        \n        let hasCustomPorts = parsedServers.contains { $0.port != nil }\n        \n        // If no custom ports are specified, use the standard network setup method\n        if !hasCustomPorts {\n            let servers = parsedServers.map { $0.address }\n            setStandardDNS(services: services, servers: servers, completion: completion)\n            return\n        }\n        \n        // For DNS servers with custom ports, we need to modify the resolver configuration\n        let resolverContent = createResolverContent(parsedServers)\n        \n        // We'll use the existing executeWithAuthentication method which properly handles\n        // authentication with Touch ID or admin password\n        let createDirCmd = \"sudo mkdir -p /etc/resolver\"\n        executeWithAuthentication(command: createDirCmd) { dirSuccess in\n            if !dirSuccess {\n                print(\"Failed to create resolver directory\")\n                completion(false)\n                return\n            }\n            \n            // Now write the resolver content\n            let writeFileCmd = \"echo '\\(resolverContent)' | sudo tee /etc/resolver/custom > /dev/null\"\n            self.executeWithAuthentication(command: writeFileCmd) { fileSuccess in\n                if !fileSuccess {\n                    print(\"Failed to write resolver configuration\")\n                    completion(false)\n                    return\n                }\n                \n                // Set permissions\n                let permCmd = \"sudo chmod 644 /etc/resolver/custom\"\n                self.executeWithAuthentication(command: permCmd) { permSuccess in\n                    if !permSuccess {\n                        print(\"Failed to set resolver file permissions\")\n                        completion(false)\n                        return\n                    }\n                    \n                    // Also set standard DNS servers to ensure proper resolution\n                    let standardServers = parsedServers.map { $0.address }\n                    self.setStandardDNS(services: services, servers: standardServers, completion: completion)\n                }\n            }\n        }\n    }\n\n    private func createResolverContent(_ servers: [(address: String, port: Int?)]) -> String {\n        var resolverContent = \"# Custom DNS configuration with port\\n\"\n        \n        for server in servers {\n            resolverContent += \"nameserver \\(server.address)\\n\"\n            if let port = server.port {\n                resolverContent += \"port \\(port)\\n\"\n            }\n        }\n        \n        return resolverContent\n    }\n\n    private func parseDNSServer(_ input: String) -> (address: String, port: Int?)? {\n        let trimmed = input.trimmingCharacters(in: .whitespacesAndNewlines)\n        guard !trimmed.isEmpty else { return nil }\n        \n        // Support IPv6 with explicit port using bracket notation: [addr]:port\n        if trimmed.hasPrefix(\"[\"), let closingBracket = trimmed.firstIndex(of: \"]\") {\n            let address = String(trimmed[trimmed.index(after: trimmed.startIndex)..<closingBracket])\n            let remainder = trimmed[trimmed.index(after: closingBracket)..<trimmed.endIndex]\n            if remainder.hasPrefix(\":\") {\n                let portString = remainder.dropFirst()\n                if let port = Int(portString) {\n                    return (address, port)\n                }\n            }\n            return (address, nil)\n        }\n        \n        // IPv4 with port (single colon, numeric suffix)\n        let parts = trimmed.split(separator: \":\", omittingEmptySubsequences: false)\n        if parts.count == 2,\n           let port = Int(parts[1]),\n           !parts[0].contains(\":\") {\n            return (String(parts[0]), port)\n        }\n        \n        // IPv6 or plain address with no port\n        return (trimmed, nil)\n    }\n\n    func disableDNS(completion: @escaping (Bool) -> Void) {\n        let services = findActiveServices()\n        guard !services.isEmpty else {\n            completion(false)\n            return\n        }\n        \n        // Remove any custom resolver configuration\n        let removeResolverCmd = \"sudo rm -f /etc/resolver/custom\"\n        \n        executeWithAuthentication(command: removeResolverCmd) { _ in\n            // Continue with normal DNS reset regardless of resolver removal success\n            let dispatchGroup = DispatchGroup()\n            var allSucceeded = true\n            \n            for service in services {\n                dispatchGroup.enter()\n                \n                let command = \"/usr/sbin/networksetup -setdnsservers '\\(service)' empty\"\n                \n                self.executeWithAuthentication(command: command) { success in\n                    if !success {\n                        allSucceeded = false\n                    }\n                    dispatchGroup.leave()\n                }\n            }\n            \n            dispatchGroup.notify(queue: .main) {\n                completion(allSucceeded)\n            }\n        }\n    }\n\n    // Helper method to set standard DNS settings\n    private func setStandardDNS(services: [String], servers: [String], completion: @escaping (Bool) -> Void) {\n        let dispatchGroup = DispatchGroup()\n        var allSucceeded = true\n        \n        for service in services {\n            dispatchGroup.enter()\n            \n            let dnsArgs = servers.joined(separator: \" \")\n            let dnsCommand = \"/usr/sbin/networksetup -setdnsservers '\\(service)' \\(dnsArgs)\"\n            let ipv6Command = \"/usr/sbin/networksetup -setv6off '\\(service)'; /usr/sbin/networksetup -setv6automatic '\\(service)'\"\n            let fullCommand = \"\\(dnsCommand); \\(ipv6Command)\"\n            \n            executeWithAuthentication(command: fullCommand) { success in\n                if !success {\n                    allSucceeded = false\n                }\n                dispatchGroup.leave()\n            }\n        }\n        \n        dispatchGroup.notify(queue: .main) {\n            completion(allSucceeded)\n        }\n    }\n\n    private func executePrivilegedCommand(arguments: [String]) -> Bool {\n        let services = findActiveServices()\n        guard !services.isEmpty else { return false }\n        \n        var success = true\n        \n        for service in services {\n            // Properly escape the arguments for AppleScript\n            let escapedArgs = arguments.map { arg in\n                return \"\\\\\\\"\" + arg.replacingOccurrences(of: \"\\\\\", with: \"\\\\\\\\\")\n                    .replacingOccurrences(of: \"\\\"\", with: \"\\\\\\\"\") + \"\\\\\\\"\"\n            }.joined(separator: \" \")\n            \n            // Combine IPv4 and IPv6 commands in a single script if we're setting DNS\n            let isSettingDNS = arguments[0] == \"-setdnsservers\"\n\n            let commandScript: String\n            if isSettingDNS {\n                // Combine DNS and IPv6 commands with semicolons in a single admin privilege request\n                let ipv6Script = \"/usr/sbin/networksetup -setv6off '\\(service)'; /usr/sbin/networksetup -setv6automatic '\\(service)'\"\n                commandScript = \"\"\"\n                do shell script \"/usr/sbin/networksetup \\(escapedArgs); \\(ipv6Script)\" with administrator privileges with prompt \"DNS Easy Switcher needs to modify network settings\"\n                \"\"\"\n            } else {\n                // For other commands, keep as is\n                commandScript = \"\"\"\n                do shell script \"/usr/sbin/networksetup \\(escapedArgs)\" with administrator privileges with prompt \"DNS Easy Switcher needs to modify network settings\"\n                \"\"\"\n            }\n            \n            var error: NSDictionary?\n            if let scriptObject = NSAppleScript(source: commandScript) {\n                if scriptObject.executeAndReturnError(&error) == nil {\n                    if let error = error {\n                        print(\"Error executing privileged command: \\(error)\")\n                        success = false\n                    }\n                }\n            } else {\n                success = false\n            }\n        }\n        \n        return success\n    }\n    \n    func clearDNSCache(completion: @escaping (Bool) -> Void) {\n        let flushCommand = \"dscacheutil -flushcache\"\n        \n        executeWithAuthentication(command: flushCommand) { success in\n            if success {\n                let restartCommand = \"killall -HUP mDNSResponder 2>/dev/null || killall -HUP mdnsresponder 2>/dev/null || true\"\n                \n                self.executeWithAuthentication(command: restartCommand) { _ in\n                    completion(success)\n                }\n            } else {\n                completion(false)\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "DNS Easy Switcher/DNSSettings.swift",
    "content": "//\n//  DNSSettings.swift\n//  DNS Easy Switcher\n//\n//  Created by Gregory LINFORD on 23/02/2025.\n//\n\nimport Foundation\nimport SwiftData\n\n@Model\nfinal class CustomDNSServer: Identifiable {\n    var id: String\n    var name: String\n    var primaryDNS: String\n    var secondaryDNS: String\n    var tertiaryDNS: String?\n    var quaternaryDNS: String?\n    var timestamp: Date\n    \n    init(id: String = UUID().uuidString,\n         name: String,\n         primaryDNS: String,\n         secondaryDNS: String,\n         tertiaryDNS: String? = nil,\n         quaternaryDNS: String? = nil,\n         timestamp: Date = Date()) {\n        self.id = id\n        self.name = name\n        self.primaryDNS = primaryDNS\n        self.secondaryDNS = secondaryDNS\n        self.tertiaryDNS = tertiaryDNS\n        self.quaternaryDNS = quaternaryDNS\n        self.timestamp = timestamp\n    }\n}\n\n@Model\nfinal class DNSSettings {\n    @Attribute(.unique) var id: String\n    var isCloudflareEnabled: Bool\n    var isQuad9Enabled: Bool\n    var activeCustomDNSID: String?\n    var timestamp: Date\n    var activeGetFlixLocation: String?\n    var isAdGuardEnabled: Bool?\n    \n    init(id: String = UUID().uuidString,\n         isCloudflareEnabled: Bool = false,\n         isQuad9Enabled: Bool = false,\n         activeCustomDNSID: String? = nil,\n         timestamp: Date = Date(),\n         isAdGuardEnabled: Bool? = false,\n         activeGetFlixLocation: String? = nil) {\n        self.id = id\n        self.isCloudflareEnabled = isCloudflareEnabled\n        self.isQuad9Enabled = isQuad9Enabled\n        self.activeCustomDNSID = activeCustomDNSID\n        self.timestamp = timestamp\n        self.isAdGuardEnabled = isAdGuardEnabled\n    }\n}\n\nextension CustomDNSServer {\n    /// Returns all user-entered DNS entries, supporting comma-separated values per field.\n    var dnsEntries: [String] {\n        [primaryDNS, secondaryDNS, tertiaryDNS ?? \"\", quaternaryDNS ?? \"\"]\n            .flatMap { entry in\n                entry\n                    .split(separator: \",\")\n                    .map { $0.trimmingCharacters(in: .whitespacesAndNewlines) }\n            }\n            .filter { !$0.isEmpty }\n    }\n}\n"
  },
  {
    "path": "DNS Easy Switcher/DNSSpeedTester.swift",
    "content": "//\n//  DNSSpeedTester.swift\n//  DNS Easy Switcher\n//\n//  Created by Gregory LINFORD on 25/02/2025.\n//\n\nimport Foundation\nimport SwiftData\n\nclass DNSSpeedTester {\n    static let shared = DNSSpeedTester()\n    \n    // Result struct to store ping results\n    struct PingResult: Identifiable {\n        let id = UUID()\n        let dnsName: String\n        let server: String\n        let responseTime: Double // in milliseconds\n        let isSuccess: Bool\n        let isCustom: Bool\n        let customID: String?\n        \n        init(dnsName: String, server: String, responseTime: Double, isSuccess: Bool, isCustom: Bool = false, customID: String? = nil) {\n            self.dnsName = dnsName\n            self.server = server\n            self.responseTime = responseTime\n            self.isSuccess = isSuccess\n            self.isCustom = isCustom\n            self.customID = customID\n        }\n    }\n    \n    // Track running tasks to ensure proper cleanup\n    private var runningTasks: [Process] = []\n    private var isCurrentlyTesting = false\n    \n    // Perform ping test for all DNS servers including custom ones\n    func testAllDNS(customServers: [CustomDNSServer], completion: @escaping ([PingResult]) -> Void) {\n        // Safety check to prevent multiple simultaneous tests\n        guard !isCurrentlyTesting else {\n            completion([])\n            return\n        }\n        \n        isCurrentlyTesting = true\n        runningTasks = []\n        \n        let dnsManager = DNSManager.shared\n        \n        var allDNSToTest: [(String, String, Bool, String?)] = [\n            (\"Cloudflare\", dnsManager.cloudflareServers[0], false, nil),\n            (\"Quad9\", dnsManager.quad9Servers[0], false, nil),\n            (\"AdGuard\", dnsManager.adguardServers[0], false, nil)\n        ]\n        \n        // Add all Getflix servers\n        let getflixServers = dnsManager.getflixServers.sorted(by: { $0.key < $1.key })\n        allDNSToTest.append(contentsOf: getflixServers.map { (\"Getflix: \\($0.key)\", $0.value, false, nil) })\n        \n        // Add custom DNS servers (first entry only to keep test time reasonable)\n        for server in customServers {\n            if let firstEntry = server.dnsEntries.first {\n                allDNSToTest.append((server.name, firstEntry, true, server.id))\n            }\n        }\n        \n        // Use serial queue to avoid overwhelming the system\n        let queue = DispatchQueue(label: \"com.glinford.DNSSpeedTest\", qos: .userInitiated)\n        let resultsQueue = DispatchQueue(label: \"com.glinford.DNSSpeedTestResults\", attributes: .concurrent)\n        let resultsLock = NSLock()\n        var results: [PingResult] = []\n        let group = DispatchGroup()\n        \n        // Create a semaphore to limit concurrent operations\n        let semaphore = DispatchSemaphore(value: 5) // Allow 5 concurrent pings\n        \n        for (index, (name, server, isCustom, customID)) in allDNSToTest.enumerated() {\n            group.enter()\n            \n            // Add a small delay between tests to avoid overwhelming the system\n            queue.asyncAfter(deadline: .now() + Double(index) * 0.05) { [weak self] in\n                guard let self = self else {\n                    semaphore.signal()\n                    group.leave()\n                    return\n                }\n                \n                semaphore.wait() // Wait for a slot to become available\n                \n                self.pingServer(server: server) { responseTime, isSuccess in\n                    resultsQueue.async {\n                        resultsLock.lock()\n                        let result = PingResult(\n                            dnsName: name,\n                            server: server,\n                            responseTime: responseTime,\n                            isSuccess: isSuccess,\n                            isCustom: isCustom,\n                            customID: customID\n                        )\n                        results.append(result)\n                        resultsLock.unlock()\n                        \n                        semaphore.signal() // Release the slot\n                        group.leave()\n                    }\n                }\n            }\n        }\n        \n        group.notify(queue: .main) { [weak self] in\n            guard let self = self else { return }\n            \n            // Clean up any remaining processes\n            for task in self.runningTasks {\n                if task.isRunning {\n                    task.terminate()\n                }\n            }\n            self.runningTasks = []\n            self.isCurrentlyTesting = false\n            \n            // Sort results by response time\n            let sortedResults = results.sorted { $0.responseTime < $1.responseTime }\n            completion(sortedResults)\n        }\n    }\n    \n    // Cancel any ongoing tests\n    func cancelTests() {\n        for task in runningTasks {\n            if task.isRunning {\n                task.terminate()\n            }\n        }\n        runningTasks = []\n        isCurrentlyTesting = false\n    }\n    \n    // Clean up when app is terminating\n    func cleanup() {\n        cancelTests()\n    }\n    \n    // Measure ping time to a DNS server with safer implementation\n    private func pingServer(server: String, completion: @escaping (Double, Bool) -> Void) {\n        let task = Process()\n        task.launchPath = \"/sbin/ping\"\n        task.arguments = [\"-c\", \"2\", \"-t\", \"1\", server] // 2 pings with 1-second timeout (reduced for speed)\n        \n        let pipe = Pipe()\n        task.standardOutput = pipe\n        task.standardError = pipe\n        \n        // Keep track of task for cleanup\n        runningTasks.append(task)\n        \n        // Set up termination handler before running\n        task.terminationHandler = { [weak self] process in\n            guard let self = self else { return }\n            \n            // Remove this task from our tracking list\n            if let index = self.runningTasks.firstIndex(where: { $0 === process }) {\n                self.runningTasks.remove(at: index)\n            }\n            \n            let data = pipe.fileHandleForReading.readDataToEndOfFile()\n            let output = String(data: data, encoding: .utf8) ?? \"\"\n            \n            // Parse ping results\n            if process.terminationStatus == 0 && output.contains(\"min/avg/max\") {\n                // More robust parsing approach\n                let lines = output.components(separatedBy: .newlines)\n                for line in lines {\n                    if line.contains(\"min/avg/max\") {\n                        let parts = line.components(separatedBy: \"=\")\n                        if parts.count >= 2 {\n                            let stats = parts[1].trimmingCharacters(in: .whitespaces)\n                            let values = stats.components(separatedBy: \"/\")\n                            if values.count >= 2 {\n                                if let avgTime = Double(values[1].trimmingCharacters(in: .whitespaces)) {\n                                    completion(avgTime, true)\n                                    return\n                                }\n                            }\n                        }\n                    }\n                }\n                // If we get here, parsing failed\n                completion(999, false)\n            } else {\n                completion(999, false) // Ping failed\n            }\n        }\n        \n        do {\n            try task.run()\n        } catch {\n            // Remove this task from our tracking list if it failed to start\n            if let index = runningTasks.firstIndex(where: { $0 === task }) {\n                runningTasks.remove(at: index)\n            }\n            \n            completion(999, false) // Process failed to start\n        }\n    }\n    \n    // Deinitializer to clean up resources\n    deinit {\n        cleanup()\n    }\n}\n"
  },
  {
    "path": "DNS Easy Switcher/DNS_Easy_Switcher.entitlements",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict/>\n</plist>\n"
  },
  {
    "path": "DNS Easy Switcher/DNS_Easy_SwitcherApp.swift",
    "content": "//\n//  DNS_Easy_SwitcherApp.swift\n//  DNS Easy Switcher\n//\n//  Created by Gregory LINFORD on 23/02/2025.\n//\n\nimport SwiftUI\nimport SwiftData\nimport AppKit\n\n@main\nstruct DNS_Easy_SwitcherApp: App {\n    @StateObject private var menuBarController = MenuBarController()\n    \n    let modelContainer: ModelContainer\n    \n    init() {\n        do {\n            let schema = Schema([\n                DNSSettings.self,\n                CustomDNSServer.self\n            ])\n            let modelConfiguration = ModelConfiguration(schema: schema, isStoredInMemoryOnly: false)\n            self.modelContainer = try ModelContainer(for: schema, configurations: [modelConfiguration])\n        } catch {\n            // If the persistent store cannot be created (e.g., corrupted store or permission issue),\n            // fall back to an in-memory container so the app can still launch.\n            let schema = Schema([\n                DNSSettings.self,\n                CustomDNSServer.self\n            ])\n            self.modelContainer = try! ModelContainer(\n                for: schema,\n                configurations: [ModelConfiguration(schema: schema, isStoredInMemoryOnly: true)]\n            )\n            print(\"Warning: Using in-memory store due to ModelContainer error: \\(error)\")\n        }\n    }\n\n    var body: some Scene {\n        WindowGroup(id: \"hidden\") {\n            Color.clear\n                .frame(width: 0, height: 0)\n                .hidden()\n        }\n        .windowStyle(.hiddenTitleBar)\n        .defaultSize(width: 0, height: 0)\n        .modelContainer(modelContainer)\n        \n        MenuBarExtra(\"DNS Switcher\", systemImage: \"network\") {\n            MenuBarView()\n                .environment(\\.modelContext, modelContainer.mainContext)\n                .frame(width: 300)\n        }\n    }\n}\n"
  },
  {
    "path": "DNS Easy Switcher/EditCustomDNSView.swift",
    "content": "//\n//  EditCustomDNSView.swift\n//  DNS Easy Switcher\n//\n//  Created by Gregory LINFORD on 25/02/2025.\n//\n\nimport SwiftUI\n\nstruct EditCustomDNSView: View {\n    let server: CustomDNSServer\n    var onComplete: (CustomDNSServer?) -> Void\n    \n    @State private var name: String\n    @State private var primaryDNS: String\n    @State private var secondaryDNS: String\n    @State private var tertiaryDNS: String\n    @State private var quaternaryDNS: String\n    \n    init(server: CustomDNSServer, onComplete: @escaping (CustomDNSServer?) -> Void) {\n        self.server = server\n        self.onComplete = onComplete\n        _name = State(initialValue: server.name)\n        _primaryDNS = State(initialValue: server.primaryDNS)\n        _secondaryDNS = State(initialValue: server.secondaryDNS)\n        _tertiaryDNS = State(initialValue: server.tertiaryDNS ?? \"\")\n        _quaternaryDNS = State(initialValue: server.quaternaryDNS ?? \"\")\n    }\n    \n    var body: some View {\n        VStack(alignment: .leading, spacing: 12) {\n            TextField(\"Name (e.g. Work DNS)\", text: $name)\n                .textFieldStyle(.roundedBorder)\n            \n            TextField(\"Primary DNS (e.g. 8.8.8.8 or 127.0.0.1:5353)\", text: $primaryDNS)\n                .textFieldStyle(.roundedBorder)\n                .help(\"Use comma to add multiple addresses. For custom ports on IPv4, add colon and port number (e.g., 127.0.0.1:5353)\")\n\n            TextField(\"Secondary DNS (optional)\", text: $secondaryDNS)\n                .textFieldStyle(.roundedBorder)\n                .help(\"Use comma to add multiple addresses. For custom ports on IPv4, add colon and port number (e.g., 127.0.0.1:5353)\")\n            \n            TextField(\"Third DNS (IPv6 or IPv4, optional)\", text: $tertiaryDNS)\n                .textFieldStyle(.roundedBorder)\n                .help(\"Tip: bracket IPv6 if adding a port, e.g., [2001:4860:4860::8888]:5353\")\n            \n            TextField(\"Fourth DNS (IPv6 or IPv4, optional)\", text: $quaternaryDNS)\n                .textFieldStyle(.roundedBorder)\n                .help(\"Use comma to add multiple IPv6 entries if needed\")\n            \n            HStack {\n                Button(\"Cancel\") {\n                    onComplete(nil)\n                }\n                .keyboardShortcut(.escape)\n                \n                Spacer()\n                \n                Button(\"Save\") {\n                    guard !name.isEmpty && !primaryDNS.isEmpty else { return }\n                    let updatedServer = CustomDNSServer(\n                        id: server.id,\n                        name: name,\n                        primaryDNS: primaryDNS,\n                        secondaryDNS: secondaryDNS,\n                        tertiaryDNS: tertiaryDNS,\n                        quaternaryDNS: quaternaryDNS,\n                        timestamp: server.timestamp\n                    )\n                    onComplete(updatedServer)\n                }\n                .keyboardShortcut(.return)\n                .disabled(name.isEmpty || primaryDNS.isEmpty)\n            }\n        }\n        .padding()\n        .frame(width: 360)\n    }\n}\n"
  },
  {
    "path": "DNS Easy Switcher/MenuBarController.swift",
    "content": "//\n//  MenuBarController.swift\n//  DNS Easy Switcher\n//\n//  Created by Gregory LINFORD on 23/02/2025.\n//\n\nimport Foundation\nimport AppKit\n\nclass MenuBarController: ObservableObject {\n    init() {\n        // Hide the dock icon\n        NSApplication.shared.setActivationPolicy(.accessory)\n    }\n}\n"
  },
  {
    "path": "DNS Easy Switcher/MenuBarView.swift",
    "content": "//\n//  MenuBarView.swift\n//  DNS Easy Switcher\n//\n//  Created by Gregory LINFORD on 23/02/2025.\n//\nimport SwiftUI\nimport SwiftData\n\nstruct MenuBarView: View {\n    @Environment(\\.modelContext) private var modelContext\n    @Query(sort: \\DNSSettings.timestamp) private var dnsSettings: [DNSSettings]\n    @Query(sort: \\CustomDNSServer.name) private var customServers: [CustomDNSServer]\n    @State private var isUpdating = false\n    @State private var isSpeedTesting = false\n    @State private var pingResults: [DNSSpeedTester.PingResult] = []\n    @State private var showingAddDNS = false\n    @State private var showingManageDNS = false\n    @State private var aboutWindowController: CustomSheetWindowController?\n    @State private var selectedServer: CustomDNSServer?\n    @State private var windowController: CustomSheetWindowController?\n    \n    var body: some View {\n        Group {\n            VStack {\n                // Cloudflare DNS\n                Toggle(getLabelWithPing(\"Cloudflare DNS\", dnsType: .cloudflare), isOn: Binding(\n                    get: { dnsSettings.first?.isCloudflareEnabled ?? false },\n                    set: { newValue in\n                        if newValue && !isUpdating {\n                            activateDNS(type: .cloudflare)\n                        }\n                    }\n                ))\n                .padding(.horizontal)\n                .disabled(isUpdating || isSpeedTesting)\n                .overlay(alignment: .trailing) {\n                    if isSpeedTesting {\n                        ProgressView()\n                            .scaleEffect(0.6)\n                            .frame(width: 12, height: 12)\n                            .padding(.trailing, 8)\n                    }\n                }\n                \n                // Quad9 DNS\n                Toggle(getLabelWithPing(\"Quad9 DNS\", dnsType: .quad9), isOn: Binding(\n                    get: { dnsSettings.first?.isQuad9Enabled ?? false },\n                    set: { newValue in\n                        if newValue && !isUpdating {\n                            activateDNS(type: .quad9)\n                        }\n                    }\n                ))\n                .padding(.horizontal)\n                .disabled(isUpdating || isSpeedTesting)\n                .overlay(alignment: .trailing) {\n                    if isSpeedTesting {\n                        ProgressView()\n                            .scaleEffect(0.6)\n                            .frame(width: 12, height: 12)\n                            .padding(.trailing, 8)\n                    }\n                }\n                \n                // AdGuard DNS\n                Toggle(getLabelWithPing(\"AdGuard DNS\", dnsType: .adguard), isOn: Binding(\n                    get: { dnsSettings.first?.isAdGuardEnabled ?? false },\n                    set: { newValue in\n                        if newValue && !isUpdating {\n                            activateDNS(type: .adguard)\n                        }\n                    }\n                ))\n                .padding(.horizontal)\n                .disabled(isUpdating || isSpeedTesting)\n                .overlay(alignment: .trailing) {\n                    if isSpeedTesting {\n                        ProgressView()\n                            .scaleEffect(0.6)\n                            .frame(width: 12, height: 12)\n                            .padding(.trailing, 8)\n                    }\n                }\n                \n                // GetFlix DNS Menu\n                Menu {\n                    ForEach(Array(DNSManager.shared.getflixServers.keys.sorted()), id: \\.self) { location in\n                        Button(action: {\n                            activateDNS(type: .getflix(location))\n                        }) {\n                            HStack {\n                                Text(getGetflixLabelWithPing(location))\n                                Spacer()\n                                if dnsSettings.first?.activeGetFlixLocation == location {\n                                    Image(systemName: \"checkmark\")\n                                }\n                            }\n                        }\n                    }\n                } label: {\n                    HStack {\n                        Text(\"GetFlix DNS\")\n                        Spacer()\n                        if let activeLocation = dnsSettings.first?.activeGetFlixLocation {\n                            Circle()\n                                .fill(Color.green)\n                                .frame(width: 8, height: 8)\n                        }\n                        if isSpeedTesting {\n                            ProgressView()\n                                .scaleEffect(0.6)\n                                .frame(width: 12, height: 12)\n                                .padding(.trailing, 4)\n                        }\n                    }\n                }\n                .padding(.horizontal)\n                .disabled(isUpdating || isSpeedTesting)\n                \n                Divider()\n                \n                // Custom DNS section\n                if !customServers.isEmpty {\n                    Menu {\n                        ForEach(customServers) { server in\n                            Button(action: {\n                                activateDNS(type: .custom(server))\n                            }) {\n                                HStack {\n                                    Text(getCustomDNSLabelWithPing(server))\n                                    Spacer()\n                                    if dnsSettings.first?.activeCustomDNSID == server.id {\n                                        Image(systemName: \"checkmark\")\n                                    }\n                                }\n                            }\n                        }\n                    } label: {\n                        HStack {\n                            Text(\"Custom DNS\")\n                            Spacer()\n                            if dnsSettings.first?.activeCustomDNSID != nil {\n                                Circle()\n                                    .fill(Color.green)\n                                    .frame(width: 8, height: 8)\n                            }\n                            if isSpeedTesting {\n                                ProgressView()\n                                    .scaleEffect(0.6)\n                                    .frame(width: 12, height: 12)\n                                    .padding(.trailing, 4)\n                            }\n                        }\n                    }\n                    .padding(.horizontal)\n                    .disabled(isUpdating || isSpeedTesting)\n                    \n                    Button(action: {\n                        showManageCustomDNSSheet()\n                    }) {\n                        Text(\"Manage Custom DNS\")\n                            .frame(maxWidth: .infinity)\n                    }\n                    .buttonStyle(.plain)\n                    .padding(.horizontal)\n                    .padding(.vertical, 5)\n                    .disabled(isSpeedTesting)\n                }\n                \n                Button(action: {\n                    showAddCustomDNSSheet()\n                }) {\n                    Text(\"Add Custom DNS\")\n                        .frame(maxWidth: .infinity)\n                }\n                .buttonStyle(.bordered)\n                .padding(.horizontal)\n                .padding(.vertical, 5)\n                .disabled(isSpeedTesting)\n                \n                Divider()\n                \n                Button(\"Disable DNS Override\") {\n                    if !isUpdating && !isSpeedTesting {\n                        isUpdating = true\n                        DNSManager.shared.disableDNS { success in\n                            if success {\n                                Task { @MainActor in\n                                    updateSettings(type: .none)\n                                }\n                            }\n                            isUpdating = false\n                        }\n                    }\n                }\n                .padding(.vertical, 5)\n                .disabled(isUpdating || isSpeedTesting)\n                \n                // Speed Test Button\n                Button(action: {\n                    runSpeedTest()\n                }) {\n                    HStack {\n                        Text(\"Run Speed Test\")\n                        if isSpeedTesting {\n                            Spacer()\n                            ProgressView()\n                                .scaleEffect(0.8)\n                                .frame(width: 16, height: 16)\n                        }\n                    }\n                    .frame(maxWidth: .infinity)\n                }\n                .buttonStyle(.bordered)\n                .padding(.horizontal)\n                .padding(.vertical, 5)\n                .disabled(isUpdating || isSpeedTesting)\n                \n                Button(action: {\n                    clearDNSCache()\n                }) {\n                    HStack {\n                        Text(\"Clear DNS Cache\")\n                        if isUpdating {\n                            Spacer()\n                            ProgressView()\n                                .scaleEffect(0.8)\n                                .frame(width: 16, height: 16)\n                        }\n                    }\n                    .frame(maxWidth: .infinity)\n                }\n                .buttonStyle(.bordered)\n                .padding(.horizontal)\n                .padding(.vertical, 5)\n                .disabled(isUpdating || isSpeedTesting)\n                \n                Divider()\n\n                Button(\"About\") {\n                    showAboutSheet()\n                }\n                .padding(.vertical, 5)\n\n                Button(\"Quit\") {\n                    NSApplication.shared.terminate(nil)\n                }\n                .padding(.vertical, 5)\n            }\n            .padding(.vertical, 5)\n        }\n        .onAppear {\n            ensureSettingsExist()\n        }\n    }\n    \n    // Helper methods for getting ping results\n    private func getLabelWithPing(_ baseLabel: String, dnsType: DNSType) -> String {\n        guard !pingResults.isEmpty else { return baseLabel }\n        \n        switch dnsType {\n        case .cloudflare:\n            if let result = pingResults.first(where: { $0.dnsName == \"Cloudflare\" }) {\n                return \"\\(baseLabel) (\\(Int(result.responseTime))ms)\"\n            }\n        case .quad9:\n            if let result = pingResults.first(where: { $0.dnsName == \"Quad9\" }) {\n                return \"\\(baseLabel) (\\(Int(result.responseTime))ms)\"\n            }\n        case .adguard:\n            if let result = pingResults.first(where: { $0.dnsName == \"AdGuard\" }) {\n                return \"\\(baseLabel) (\\(Int(result.responseTime))ms)\"\n            }\n        default:\n            break\n        }\n        \n        return baseLabel\n    }\n    \n    private func getGetflixLabelWithPing(_ location: String) -> String {\n        guard !pingResults.isEmpty else { return location }\n        \n        if let result = pingResults.first(where: { $0.dnsName == \"Getflix: \\(location)\" }) {\n            return \"\\(location) (\\(Int(result.responseTime))ms)\"\n        }\n        \n        return location\n    }\n    \n    private func getCustomDNSLabelWithPing(_ server: CustomDNSServer) -> String {\n        guard !pingResults.isEmpty else { return server.name }\n        \n        if let result = pingResults.first(where: { $0.isCustom && $0.customID == server.id }) {\n            return \"\\(server.name) (\\(Int(result.responseTime))ms)\"\n        }\n        \n        return server.name\n    }\n    \n    // Run DNS speed test\n    private func runSpeedTest() {\n        guard !isSpeedTesting else { return }\n        \n        isSpeedTesting = true\n        pingResults = []\n        \n        DNSSpeedTester.shared.testAllDNS(customServers: customServers) { results in\n            self.pingResults = results\n            self.isSpeedTesting = false\n        }\n    }\n    \n    private func showAddCustomDNSSheet() {\n        let addView = AddCustomDNSView { newServer in\n            if let newServer = newServer {\n                modelContext.insert(newServer)\n                try? modelContext.save()\n                // Automatically activate the new DNS\n                activateDNS(type: .custom(newServer))\n            }\n            windowController?.close()\n            windowController = nil\n        }\n        \n        windowController = CustomSheetWindowController(view: addView, title: \"Add Custom DNS\")\n        windowController?.window?.level = .floating\n        windowController?.showWindow(nil)\n        \n        // Position the window relative to the menu bar\n        if let window = windowController?.window,\n           let screenFrame = NSScreen.main?.frame {\n            let windowFrame = window.frame\n            let newOrigin = NSPoint(\n                x: screenFrame.width - windowFrame.width - 20,\n                y: screenFrame.height - 40 - windowFrame.height\n            )\n            window.setFrameTopLeftPoint(newOrigin)\n        }\n    }\n    \n    private func showManageCustomDNSSheet() {\n        let manageView = CustomDNSManagerView(customServers: customServers, onAction: { action, server in\n            switch action {\n            case .edit:\n                editCustomDNS(server)\n            case .delete:\n                modelContext.delete(server)\n                try? modelContext.save()\n                \n                // If this was the active server, disable DNS\n                if dnsSettings.first?.activeCustomDNSID == server.id {\n                    isUpdating = true\n                    DNSManager.shared.disableDNS { success in\n                        if success {\n                            Task { @MainActor in\n                                updateSettings(type: .none)\n                            }\n                        }\n                        isUpdating = false\n                    }\n                }\n            case .use:\n                activateDNS(type: .custom(server))\n            }\n            \n            // Don't close the window for .use or .edit actions\n            if action == .delete {\n                windowController?.close()\n                windowController = nil\n            }\n        }, onClose: {\n            windowController?.close()\n            windowController = nil\n        })\n        \n        windowController = CustomSheetWindowController(view: manageView, title: \"Manage Custom DNS\")\n        windowController?.window?.level = .floating\n        windowController?.showWindow(nil)\n        \n        // Position the window relative to the menu bar\n        if let window = windowController?.window,\n           let screenFrame = NSScreen.main?.frame {\n            let windowFrame = window.frame\n            let newOrigin = NSPoint(\n                x: screenFrame.width - windowFrame.width - 20,\n                y: screenFrame.height - 40 - windowFrame.height\n            )\n            window.setFrameTopLeftPoint(newOrigin)\n        }\n    }\n    \n    private func showAboutSheet() {\n        let aboutView = AboutView {\n            aboutWindowController?.close()\n            aboutWindowController = nil\n        }\n        \n        aboutWindowController?.close()\n        aboutWindowController = CustomSheetWindowController(view: aboutView, title: \"About\")\n        aboutWindowController?.window?.level = .floating\n        aboutWindowController?.showWindow(nil)\n        aboutWindowController?.window?.center()\n    }\n    \n    private func editCustomDNS(_ server: CustomDNSServer) {\n        let editView = EditCustomDNSView(server: server) { updatedServer in\n            if let updatedServer = updatedServer {\n                // Update existing server properties\n                server.name = updatedServer.name\n                server.primaryDNS = updatedServer.primaryDNS\n                server.secondaryDNS = updatedServer.secondaryDNS\n                server.tertiaryDNS = updatedServer.tertiaryDNS\n                server.quaternaryDNS = updatedServer.quaternaryDNS\n                try? modelContext.save()\n                \n                // If this was the active server, update DNS settings\n                if dnsSettings.first?.activeCustomDNSID == server.id {\n                    activateDNS(type: .custom(server))\n                }\n            }\n            \n            windowController?.close()\n            windowController = nil\n        }\n        \n        windowController?.close()\n        \n        windowController = CustomSheetWindowController(view: editView, title: \"Edit Custom DNS\")\n        windowController?.window?.level = .floating\n        windowController?.showWindow(nil)\n        \n        // Position the window relative to the menu bar\n        if let window = windowController?.window,\n           let screenFrame = NSScreen.main?.frame {\n            let windowFrame = window.frame\n            let newOrigin = NSPoint(\n                x: screenFrame.width - windowFrame.width - 20,\n                y: screenFrame.height - 40 - windowFrame.height\n            )\n            window.setFrameTopLeftPoint(newOrigin)\n        }\n    }\n    \n    enum DNSType: Equatable {\n        case none\n        case cloudflare\n        case quad9\n        case adguard\n        case custom(CustomDNSServer)\n        case getflix(String)\n        \n        static func == (lhs: DNSType, rhs: DNSType) -> Bool {\n            switch (lhs, rhs) {\n            case (.none, .none):\n                return true\n            case (.cloudflare, .cloudflare):\n                return true\n            case (.quad9, .quad9):\n                return true\n            case (.adguard, .adguard):\n                return true\n            case (.custom(let lServer), .custom(let rServer)):\n                return lServer.id == rServer.id\n            case (.getflix(let lLocation), .getflix(let rLocation)):\n                return lLocation == rLocation\n            default:\n                return false\n            }\n        }\n    }\n    \n    private func activateDNS(type: DNSType) {\n        isUpdating = true\n        \n        switch type {\n        case .cloudflare:\n            DNSManager.shared.setPredefinedDNS(dnsServers: DNSManager.shared.cloudflareServers) { success in\n                if success {\n                    Task { @MainActor in\n                        updateSettings(type: type)\n                    }\n                }\n                isUpdating = false\n            }\n        case .quad9:\n            DNSManager.shared.setPredefinedDNS(dnsServers: DNSManager.shared.quad9Servers) { success in\n                if success {\n                    Task { @MainActor in\n                        updateSettings(type: type)\n                    }\n                }\n                isUpdating = false\n            }\n        case .adguard:\n            DNSManager.shared.setPredefinedDNS(dnsServers: DNSManager.shared.adguardServers) { success in\n                if success {\n                    Task { @MainActor in\n                        updateSettings(type: type)\n                    }\n                }\n                isUpdating = false\n            }\n        case .custom(let server):\n            DNSManager.shared.setCustomDNS(servers: server.dnsEntries) { success in\n                if success {\n                    Task { @MainActor in\n                        updateSettings(type: type)\n                    }\n                }\n                isUpdating = false\n            }\n        case .getflix(let location):\n            if let dnsServer = DNSManager.shared.getflixServers[location] {\n                DNSManager.shared.setCustomDNS(servers: [dnsServer]) { success in\n                    if success {\n                        Task { @MainActor in\n                            updateSettings(type: type)\n                        }\n                    }\n                    isUpdating = false\n                }\n            }\n        case .none:\n            updateSettings(type: type)\n            isUpdating = false\n        }\n    }\n    \n    private func updateSettings(type: DNSType) {\n        if let settings = dnsSettings.first {\n            settings.isCloudflareEnabled = (type == .cloudflare)\n            settings.isQuad9Enabled = (type == .quad9)\n            settings.isAdGuardEnabled = type == .adguard ? true : nil\n            \n            if case .getflix(let location) = type {\n                settings.activeGetFlixLocation = location\n            } else {\n                settings.activeGetFlixLocation = nil\n            }\n            \n            if case .custom(let server) = type {\n                settings.activeCustomDNSID = server.id\n            } else {\n                settings.activeCustomDNSID = nil\n            }\n            \n            settings.timestamp = Date()\n        }\n    }\n    \n    private func ensureSettingsExist() {\n        if dnsSettings.isEmpty {\n            modelContext.insert(DNSSettings())\n            try? modelContext.save()\n        }\n    }\n    \n    private func clearDNSCache() {\n        if !isUpdating && !isSpeedTesting {\n            isUpdating = true\n            DNSManager.shared.clearDNSCache { success in\n                DispatchQueue.main.async {\n                    self.isUpdating = false\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "DNS Easy Switcher/Preview Content/Preview Assets.xcassets/Contents.json",
    "content": "{\n  \"info\" : {\n    \"author\" : \"xcode\",\n    \"version\" : 1\n  }\n}\n"
  },
  {
    "path": "DNS Easy Switcher.xcodeproj/project.pbxproj",
    "content": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 56;\n\tobjects = {\n\n/* Begin PBXBuildFile section */\n\t\t9165B6682D6B616D00DD9643 /* DNS_Easy_SwitcherApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9165B6672D6B616D00DD9643 /* DNS_Easy_SwitcherApp.swift */; };\n\t\t9165B66A2D6B616D00DD9643 /* MenuBarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9165B6692D6B616D00DD9643 /* MenuBarView.swift */; };\n\t\t9165B66C2D6B616D00DD9643 /* DNSSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9165B66B2D6B616D00DD9643 /* DNSSettings.swift */; };\n\t\t9165B66E2D6B616D00DD9643 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9165B66D2D6B616D00DD9643 /* Assets.xcassets */; };\n\t\t9165B6712D6B616D00DD9643 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9165B6702D6B616D00DD9643 /* Preview Assets.xcassets */; };\n\t\t9165B6792D6B61C500DD9643 /* MenuBarController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9165B6782D6B61C500DD9643 /* MenuBarController.swift */; };\n\t\t9165B67B2D6B62CC00DD9643 /* DNSManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9165B67A2D6B62CC00DD9643 /* DNSManager.swift */; };\n\t\t9165B67D2D6B699A00DD9643 /* AddCustomDNSView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9165B67C2D6B699A00DD9643 /* AddCustomDNSView.swift */; };\n\t\t9165B67F2D6B6D1800DD9643 /* CustomSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9165B67E2D6B6D1800DD9643 /* CustomSheet.swift */; };\n\t\t91FFB82B2D6E6619008C0471 /* CustomDNSManagerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91FFB82A2D6E6619008C0471 /* CustomDNSManagerView.swift */; };\n\t\t91FFB82D2D6E6639008C0471 /* EditCustomDNSView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91FFB82C2D6E6639008C0471 /* EditCustomDNSView.swift */; };\n\t\t91FFB82F2D6E6868008C0471 /* DNSSpeedTester.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91FFB82E2D6E6868008C0471 /* DNSSpeedTester.swift */; };\n\t\t91FFB9002D70E000008C0471 /* AboutView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91FFB8FF2D70E000008C0471 /* AboutView.swift */; };\n/* End PBXBuildFile section */\n\n/* Begin PBXFileReference section */\n\t\t9165B6642D6B616D00DD9643 /* DNS Easy Switcher.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = \"DNS Easy Switcher.app\"; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t9165B6672D6B616D00DD9643 /* DNS_Easy_SwitcherApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DNS_Easy_SwitcherApp.swift; sourceTree = \"<group>\"; };\n\t\t9165B6692D6B616D00DD9643 /* MenuBarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenuBarView.swift; sourceTree = \"<group>\"; };\n\t\t9165B66B2D6B616D00DD9643 /* DNSSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DNSSettings.swift; sourceTree = \"<group>\"; };\n\t\t9165B66D2D6B616D00DD9643 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = \"<group>\"; };\n\t\t9165B6702D6B616D00DD9643 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = \"Preview Assets.xcassets\"; sourceTree = \"<group>\"; };\n\t\t9165B6722D6B616D00DD9643 /* DNS_Easy_Switcher.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DNS_Easy_Switcher.entitlements; sourceTree = \"<group>\"; };\n\t\t9165B6782D6B61C500DD9643 /* MenuBarController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenuBarController.swift; sourceTree = \"<group>\"; };\n\t\t9165B67A2D6B62CC00DD9643 /* DNSManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DNSManager.swift; sourceTree = \"<group>\"; };\n\t\t9165B67C2D6B699A00DD9643 /* AddCustomDNSView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddCustomDNSView.swift; sourceTree = \"<group>\"; };\n\t\t9165B67E2D6B6D1800DD9643 /* CustomSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomSheet.swift; sourceTree = \"<group>\"; };\n\t\t91FFB82A2D6E6619008C0471 /* CustomDNSManagerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomDNSManagerView.swift; sourceTree = \"<group>\"; };\n\t\t91FFB82C2D6E6639008C0471 /* EditCustomDNSView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditCustomDNSView.swift; sourceTree = \"<group>\"; };\n\t\t91FFB82E2D6E6868008C0471 /* DNSSpeedTester.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DNSSpeedTester.swift; sourceTree = \"<group>\"; };\n\t\t91FFB8FF2D70E000008C0471 /* AboutView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutView.swift; sourceTree = \"<group>\"; };\n/* End PBXFileReference section */\n\n/* Begin PBXFrameworksBuildPhase section */\n\t\t9165B6612D6B616D00DD9643 /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXFrameworksBuildPhase section */\n\n/* Begin PBXGroup section */\n\t\t9165B65B2D6B616D00DD9643 = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t9165B6662D6B616D00DD9643 /* DNS Easy Switcher */,\n\t\t\t\t9165B6652D6B616D00DD9643 /* Products */,\n\t\t\t);\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t9165B6652D6B616D00DD9643 /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t9165B6642D6B616D00DD9643 /* DNS Easy Switcher.app */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t9165B6662D6B616D00DD9643 /* DNS Easy Switcher */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t9165B6672D6B616D00DD9643 /* DNS_Easy_SwitcherApp.swift */,\n\t\t\t\t9165B6692D6B616D00DD9643 /* MenuBarView.swift */,\n\t\t\t\t9165B66B2D6B616D00DD9643 /* DNSSettings.swift */,\n\t\t\t\t9165B66D2D6B616D00DD9643 /* Assets.xcassets */,\n\t\t\t\t9165B6722D6B616D00DD9643 /* DNS_Easy_Switcher.entitlements */,\n\t\t\t\t9165B66F2D6B616D00DD9643 /* Preview Content */,\n\t\t\t\t9165B6782D6B61C500DD9643 /* MenuBarController.swift */,\n\t\t\t\t9165B67A2D6B62CC00DD9643 /* DNSManager.swift */,\n\t\t\t\t9165B67C2D6B699A00DD9643 /* AddCustomDNSView.swift */,\n\t\t\t\t9165B67E2D6B6D1800DD9643 /* CustomSheet.swift */,\n\t\t\t\t91FFB82A2D6E6619008C0471 /* CustomDNSManagerView.swift */,\n\t\t\t\t91FFB82C2D6E6639008C0471 /* EditCustomDNSView.swift */,\n\t\t\t\t91FFB82E2D6E6868008C0471 /* DNSSpeedTester.swift */,\n\t\t\t\t91FFB8FF2D70E000008C0471 /* AboutView.swift */,\n\t\t\t);\n\t\t\tpath = \"DNS Easy Switcher\";\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t9165B66F2D6B616D00DD9643 /* Preview Content */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t9165B6702D6B616D00DD9643 /* Preview Assets.xcassets */,\n\t\t\t);\n\t\t\tpath = \"Preview Content\";\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXGroup section */\n\n/* Begin PBXNativeTarget section */\n\t\t9165B6632D6B616D00DD9643 /* DNS Easy Switcher */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 9165B6752D6B616D00DD9643 /* Build configuration list for PBXNativeTarget \"DNS Easy Switcher\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t9165B6602D6B616D00DD9643 /* Sources */,\n\t\t\t\t9165B6612D6B616D00DD9643 /* Frameworks */,\n\t\t\t\t9165B6622D6B616D00DD9643 /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = \"DNS Easy Switcher\";\n\t\t\tproductName = \"DNS Easy Switcher\";\n\t\t\tproductReference = 9165B6642D6B616D00DD9643 /* DNS Easy Switcher.app */;\n\t\t\tproductType = \"com.apple.product-type.application\";\n\t\t};\n/* End PBXNativeTarget section */\n\n/* Begin PBXProject section */\n\t\t9165B65C2D6B616D00DD9643 /* Project object */ = {\n\t\t\tisa = PBXProject;\n\t\t\tattributes = {\n\t\t\t\tBuildIndependentTargetsInParallel = 1;\n\t\t\t\tLastSwiftUpdateCheck = 1500;\n\t\t\t\tLastUpgradeCheck = 1500;\n\t\t\t\tTargetAttributes = {\n\t\t\t\t\t9165B6632D6B616D00DD9643 = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 15.0.1;\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t};\n\t\t\tbuildConfigurationList = 9165B65F2D6B616D00DD9643 /* Build configuration list for PBXProject \"DNS Easy Switcher\" */;\n\t\t\tcompatibilityVersion = \"Xcode 14.0\";\n\t\t\tdevelopmentRegion = en;\n\t\t\thasScannedForEncodings = 0;\n\t\t\tknownRegions = (\n\t\t\t\ten,\n\t\t\t\tBase,\n\t\t\t);\n\t\t\tmainGroup = 9165B65B2D6B616D00DD9643;\n\t\t\tproductRefGroup = 9165B6652D6B616D00DD9643 /* Products */;\n\t\t\tprojectDirPath = \"\";\n\t\t\tprojectRoot = \"\";\n\t\t\ttargets = (\n\t\t\t\t9165B6632D6B616D00DD9643 /* DNS Easy Switcher */,\n\t\t\t);\n\t\t};\n/* End PBXProject section */\n\n/* Begin PBXResourcesBuildPhase section */\n\t\t9165B6622D6B616D00DD9643 /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t9165B6712D6B616D00DD9643 /* Preview Assets.xcassets in Resources */,\n\t\t\t\t9165B66E2D6B616D00DD9643 /* Assets.xcassets in Resources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXResourcesBuildPhase section */\n\n/* Begin PBXSourcesBuildPhase section */\n\t\t9165B6602D6B616D00DD9643 /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t9165B6792D6B61C500DD9643 /* MenuBarController.swift in Sources */,\n\t\t\t\t9165B67F2D6B6D1800DD9643 /* CustomSheet.swift in Sources */,\n\t\t\t\t9165B67D2D6B699A00DD9643 /* AddCustomDNSView.swift in Sources */,\n\t\t\t\t9165B66A2D6B616D00DD9643 /* MenuBarView.swift in Sources */,\n\t\t\t\t91FFB82B2D6E6619008C0471 /* CustomDNSManagerView.swift in Sources */,\n\t\t\t\t9165B66C2D6B616D00DD9643 /* DNSSettings.swift in Sources */,\n\t\t\t\t91FFB82F2D6E6868008C0471 /* DNSSpeedTester.swift in Sources */,\n\t\t\t\t9165B67B2D6B62CC00DD9643 /* DNSManager.swift in Sources */,\n\t\t\t\t91FFB82D2D6E6639008C0471 /* EditCustomDNSView.swift in Sources */,\n\t\t\t\t91FFB9002D70E000008C0471 /* AboutView.swift in Sources */,\n\t\t\t\t9165B6682D6B616D00DD9643 /* DNS_Easy_SwitcherApp.swift in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXSourcesBuildPhase section */\n\n/* Begin XCBuildConfiguration section */\n\t\t9165B6732D6B616D00DD9643 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++20\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_WEAK = YES;\n\t\t\t\tCLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_COMMA = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_DOCUMENTATION_COMMENTS = YES;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INFINITE_RECURSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;\n\t\t\t\tCLANG_WARN_OBJC_LITERAL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;\n\t\t\t\tCLANG_WARN_RANGE_LOOP_ANALYSIS = YES;\n\t\t\t\tCLANG_WARN_STRICT_PROTOTYPES = YES;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVE = YES;\n\t\t\t\tCLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = dwarf;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tENABLE_TESTABILITY = YES;\n\t\t\t\tENABLE_USER_SCRIPT_SANDBOXING = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu17;\n\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"DEBUG=1\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t);\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tLOCALIZATION_PREFERS_STRING_CATALOGS = YES;\n\t\t\t\tMACOSX_DEPLOYMENT_TARGET = 14.0;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;\n\t\t\t\tMTL_FAST_MATH = YES;\n\t\t\t\tONLY_ACTIVE_ARCH = YES;\n\t\t\t\tSDKROOT = macosx;\n\t\t\t\tSWIFT_ACTIVE_COMPILATION_CONDITIONS = \"DEBUG $(inherited)\";\n\t\t\t\tSWIFT_OPTIMIZATION_LEVEL = \"-Onone\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t9165B6742D6B616D00DD9643 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++20\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_WEAK = YES;\n\t\t\t\tCLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_COMMA = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_DOCUMENTATION_COMMENTS = YES;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INFINITE_RECURSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;\n\t\t\t\tCLANG_WARN_OBJC_LITERAL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;\n\t\t\t\tCLANG_WARN_RANGE_LOOP_ANALYSIS = YES;\n\t\t\t\tCLANG_WARN_STRICT_PROTOTYPES = YES;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVE = YES;\n\t\t\t\tCLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tENABLE_NS_ASSERTIONS = NO;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tENABLE_USER_SCRIPT_SANDBOXING = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu17;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tLOCALIZATION_PREFERS_STRING_CATALOGS = YES;\n\t\t\t\tMACOSX_DEPLOYMENT_TARGET = 14.0;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = NO;\n\t\t\t\tMTL_FAST_MATH = YES;\n\t\t\t\tSDKROOT = macosx;\n\t\t\t\tSWIFT_COMPILATION_MODE = wholemodule;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t9165B6762D6B616D00DD9643 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;\n\t\t\t\tASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = YES;\n\t\t\t\tCODE_SIGN_ENTITLEMENTS = \"DNS Easy Switcher/DNS_Easy_Switcher.entitlements\";\n\t\t\t\tCODE_SIGN_IDENTITY = \"Apple Development\";\n\t\t\t\tCODE_SIGN_STYLE = Automatic;\n\t\t\t\tCOMBINE_HIDPI_IMAGES = YES;\n\t\t\t\tCURRENT_PROJECT_VERSION = 1;\n\t\t\t\tDEVELOPMENT_ASSET_PATHS = \"\\\"DNS Easy Switcher/Preview Content\\\"\";\n\t\t\t\tDEVELOPMENT_TEAM = 6645MJMX63;\n\t\t\t\tENABLE_HARDENED_RUNTIME = YES;\n\t\t\t\tENABLE_PREVIEWS = YES;\n\t\t\t\tGENERATE_INFOPLIST_FILE = YES;\n\t\t\t\tINFOPLIST_KEY_CFBundleDisplayName = \"DNS Easy Switcher\";\n\t\t\t\tINFOPLIST_KEY_LSApplicationCategoryType = \"public.app-category.utilities\";\n\t\t\t\tINFOPLIST_KEY_NSHumanReadableCopyright = \"\";\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"@executable_path/../Frameworks\",\n\t\t\t\t);\n\t\t\t\tMACOSX_DEPLOYMENT_TARGET = 14.0;\n\t\t\t\tMARKETING_VERSION = 1.0.7;\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.linfordsoftware.dnseasyswitcher;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tPROVISIONING_PROFILE_SPECIFIER = \"\";\n\t\t\t\tSWIFT_EMIT_LOC_STRINGS = YES;\n\t\t\t\tSWIFT_VERSION = 5.0;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t9165B6772D6B616D00DD9643 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;\n\t\t\t\tASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = YES;\n\t\t\t\tCODE_SIGN_ENTITLEMENTS = \"DNS Easy Switcher/DNS_Easy_Switcher.entitlements\";\n\t\t\t\tCODE_SIGN_IDENTITY = \"Apple Development\";\n\t\t\t\tCODE_SIGN_STYLE = Automatic;\n\t\t\t\tCOMBINE_HIDPI_IMAGES = YES;\n\t\t\t\tCURRENT_PROJECT_VERSION = 1;\n\t\t\t\tDEVELOPMENT_ASSET_PATHS = \"\\\"DNS Easy Switcher/Preview Content\\\"\";\n\t\t\t\tDEVELOPMENT_TEAM = 6645MJMX63;\n\t\t\t\tENABLE_HARDENED_RUNTIME = YES;\n\t\t\t\tENABLE_PREVIEWS = YES;\n\t\t\t\tGENERATE_INFOPLIST_FILE = YES;\n\t\t\t\tINFOPLIST_KEY_CFBundleDisplayName = \"DNS Easy Switcher\";\n\t\t\t\tINFOPLIST_KEY_LSApplicationCategoryType = \"public.app-category.utilities\";\n\t\t\t\tINFOPLIST_KEY_NSHumanReadableCopyright = \"\";\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"@executable_path/../Frameworks\",\n\t\t\t\t);\n\t\t\t\tMACOSX_DEPLOYMENT_TARGET = 14.0;\n\t\t\t\tMARKETING_VERSION = 1.0.7;\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.linfordsoftware.dnseasyswitcher;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tPROVISIONING_PROFILE_SPECIFIER = \"\";\n\t\t\t\tSWIFT_EMIT_LOC_STRINGS = YES;\n\t\t\t\tSWIFT_VERSION = 5.0;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n/* End XCBuildConfiguration section */\n\n/* Begin XCConfigurationList section */\n\t\t9165B65F2D6B616D00DD9643 /* Build configuration list for PBXProject \"DNS Easy Switcher\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t9165B6732D6B616D00DD9643 /* Debug */,\n\t\t\t\t9165B6742D6B616D00DD9643 /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t9165B6752D6B616D00DD9643 /* Build configuration list for PBXNativeTarget \"DNS Easy Switcher\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t9165B6762D6B616D00DD9643 /* Debug */,\n\t\t\t\t9165B6772D6B616D00DD9643 /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n/* End XCConfigurationList section */\n\t};\n\trootObject = 9165B65C2D6B616D00DD9643 /* Project object */;\n}\n"
  },
  {
    "path": "DNS Easy Switcher.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"self:\">\n   </FileRef>\n</Workspace>\n"
  },
  {
    "path": "DNS Easy Switcher.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>IDEDidComputeMac32BitWarning</key>\n\t<true/>\n</dict>\n</plist>\n"
  },
  {
    "path": "DNS Easy Switcher.xcodeproj/xcshareddata/xcschemes/DNS Easy Switcher.xcscheme",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"1500\"\n   version = \"1.7\">\n   <BuildAction\n      parallelizeBuildables = \"YES\"\n      buildImplicitDependencies = \"YES\">\n      <BuildActionEntries>\n         <BuildActionEntry\n            buildForTesting = \"YES\"\n            buildForRunning = \"YES\"\n            buildForProfiling = \"YES\"\n            buildForArchiving = \"YES\"\n            buildForAnalyzing = \"YES\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"9165B6632D6B616D00DD9643\"\n               BuildableName = \"DNS Easy Switcher.app\"\n               BlueprintName = \"DNS Easy Switcher\"\n               ReferencedContainer = \"container:DNS Easy Switcher.xcodeproj\">\n            </BuildableReference>\n         </BuildActionEntry>\n      </BuildActionEntries>\n   </BuildAction>\n   <TestAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\"\n      shouldAutocreateTestPlan = \"YES\">\n   </TestAction>\n   <LaunchAction\n      buildConfiguration = \"Release\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      launchStyle = \"0\"\n      useCustomWorkingDirectory = \"NO\"\n      ignoresPersistentStateOnLaunch = \"NO\"\n      debugDocumentVersioning = \"YES\"\n      debugServiceExtension = \"internal\"\n      allowLocationSimulation = \"YES\">\n      <BuildableProductRunnable\n         runnableDebuggingMode = \"0\">\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"9165B6632D6B616D00DD9643\"\n            BuildableName = \"DNS Easy Switcher.app\"\n            BlueprintName = \"DNS Easy Switcher\"\n            ReferencedContainer = \"container:DNS Easy Switcher.xcodeproj\">\n         </BuildableReference>\n      </BuildableProductRunnable>\n   </LaunchAction>\n   <ProfileAction\n      buildConfiguration = \"Release\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\"\n      savedToolIdentifier = \"\"\n      useCustomWorkingDirectory = \"NO\"\n      debugDocumentVersioning = \"YES\">\n      <BuildableProductRunnable\n         runnableDebuggingMode = \"0\">\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"9165B6632D6B616D00DD9643\"\n            BuildableName = \"DNS Easy Switcher.app\"\n            BlueprintName = \"DNS Easy Switcher\"\n            ReferencedContainer = \"container:DNS Easy Switcher.xcodeproj\">\n         </BuildableReference>\n      </BuildableProductRunnable>\n   </ProfileAction>\n   <AnalyzeAction\n      buildConfiguration = \"Debug\">\n   </AnalyzeAction>\n   <ArchiveAction\n      buildConfiguration = \"Release\"\n      revealArchiveInOrganizer = \"YES\">\n   </ArchiveAction>\n</Scheme>\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2025 Greg\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# DNS Easy Switcher\n\nA simple macOS menu bar app that allows you to quickly switch between different DNS providers (or add custom ones).\n\n![Screenshot of DNS Easy Switcher](screenshot.png)\n\n![downloads](https://img.shields.io/github/downloads/glinford/dns-easy-switcher/total)\n\n## Features\n\n- Easy switching between popular DNS providers:\n  - Cloudflare DNS (1.1.1.1)\n  - Quad9 DNS (9.9.9.9)\n  - AdGuard DNS (94.140.14.14)\n  - GetFlix DNS (with list of all locations)\n- Disable DNS Overrides (DHCP-Provided DNS)\n- Add and manage your own custom DNS servers\n- Test DNS speed to find the fastest provider\n- Flush DNS Cache\n- Touch ID authentication for DNS changes\n- Native macOS menu bar integration\n- Persists your settings between app launches\n- IPv4 and IPv6 support\n\n## Installation\n\n### Using Homebrew (Recommended)\n\nInstall DNS Easy Switcher with Homebrew using these commands:\n\n```bash\nbrew tap glinford/tap\nbrew install --cask dns-easy-switcher\n```\n\nTo update to the latest version when available:\n\n```bash\nbrew upgrade --cask dns-easy-switcher\n```\n\n### Manual Installation\n\n1. Download the latest release from the [Releases](../../releases) page\n2. Mount the DMG file\n3. Drag DNS Easy Switcher to your Applications folder\n4. Launch DNS Easy Switcher from Applications\n\n## First Launch\n\nSince DNS Easy Switcher is distributed outside the Mac App Store, macOS may show a security warning when you first launch it.\n\nTo allow the app to run:\n\n1. Right-click (or Control-click) on DNS Easy Switcher in your Applications folder\n2. Select \"Open\" from the context menu\n3. Click \"Open\" in the dialog that appears\n4. Allow system extensions when prompted (required for DNS changes)\n\n![settings](settings.png)\n\n## Important Note\n\nDue to macOS security requirements, administrator privileges are required each time you switch DNS settings. If you have a Touch ID-enabled Mac, you can now use Touch ID instead of password entry for authentication.\n\n## Requirements\n\n- macOS 14.0 (Sonoma) or later\n- Administrator privileges (required for changing DNS settings)\n- Touch ID compatible Mac (for Touch ID authentication feature)\n\n## Tested Configurations\n\n| macOS Version | Status |\n|--------------|--------|\n| Sonoma 14.5 | ✅ |\n\n## Building from Source\n\n1. Clone the repository:\n```bash\ngit clone https://github.com/glinford/dns-easy-switcher.git\n```\n2. Open the project in Xcode 15 or later\n3. Build and run the project\n\n## License\n\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.\n\n## Contributing\n\nContributions are welcome! Please feel free to submit a Pull Request.\n\n## Acknowledgments\n\n- [Cloudflare DNS](https://1.1.1.1) for their public DNS service\n- [Quad9](https://quad9.net) for their secure DNS service\n- [AdGuard DNS](https://adguard-dns.io/en/welcome.html) for their privacy-focused DNS service with ad blocking capabilities\n- [GetFlix](https://www.getflix.com.au/setup/dns-servers/)\n\n## Privacy\n\nDNS Easy Switcher does not collect any data. All settings are stored locally on your device.\n"
  },
  {
    "path": "Releases/DNS Easy Switcher v1.0.0/DNS Easy Switcher.app/Contents/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>BuildMachineOSBuild</key>\n\t<string>23F79</string>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>en</string>\n\t<key>CFBundleDisplayName</key>\n\t<string>DNS Easy Switcher</string>\n\t<key>CFBundleExecutable</key>\n\t<string>DNS Easy Switcher</string>\n\t<key>CFBundleIconFile</key>\n\t<string>AppIcon</string>\n\t<key>CFBundleIconName</key>\n\t<string>AppIcon</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>com.linfordsoftware.dnseasyswitcher</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>DNS Easy Switcher</string>\n\t<key>CFBundlePackageType</key>\n\t<string>APPL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>1.0</string>\n\t<key>CFBundleSupportedPlatforms</key>\n\t<array>\n\t\t<string>MacOSX</string>\n\t</array>\n\t<key>CFBundleVersion</key>\n\t<string>1</string>\n\t<key>DTCompiler</key>\n\t<string>com.apple.compilers.llvm.clang.1_0</string>\n\t<key>DTPlatformBuild</key>\n\t<string></string>\n\t<key>DTPlatformName</key>\n\t<string>macosx</string>\n\t<key>DTPlatformVersion</key>\n\t<string>14.0</string>\n\t<key>DTSDKBuild</key>\n\t<string>23A334</string>\n\t<key>DTSDKName</key>\n\t<string>macosx14.0</string>\n\t<key>DTXcode</key>\n\t<string>1501</string>\n\t<key>DTXcodeBuild</key>\n\t<string>15A507</string>\n\t<key>LSMinimumSystemVersion</key>\n\t<string>14.0</string>\n</dict>\n</plist>\n"
  },
  {
    "path": "Releases/DNS Easy Switcher v1.0.0/DNS Easy Switcher.app/Contents/PkgInfo",
    "content": "APPL????"
  },
  {
    "path": "Releases/DNS Easy Switcher v1.0.0/DNS Easy Switcher.app/Contents/_CodeSignature/CodeResources",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>files</key>\n\t<dict>\n\t\t<key>Resources/AppIcon.icns</key>\n\t\t<data>\n\t\tF6YGlmox4KixBMRrSRhTusxdld8=\n\t\t</data>\n\t\t<key>Resources/Assets.car</key>\n\t\t<data>\n\t\tIhhuUihlv8TNfeE5CB9OZcOX21w=\n\t\t</data>\n\t</dict>\n\t<key>files2</key>\n\t<dict>\n\t\t<key>Resources/AppIcon.icns</key>\n\t\t<dict>\n\t\t\t<key>hash2</key>\n\t\t\t<data>\n\t\t\tI0wlcCvBzQjHkKQ1llwB0poCp2bmfglbZW45inQqQV0=\n\t\t\t</data>\n\t\t</dict>\n\t\t<key>Resources/Assets.car</key>\n\t\t<dict>\n\t\t\t<key>hash2</key>\n\t\t\t<data>\n\t\t\t/sNzrOXugwAIyPdIJZkIv1275OZELTMDgWfU3DNwkwQ=\n\t\t\t</data>\n\t\t</dict>\n\t</dict>\n\t<key>rules</key>\n\t<dict>\n\t\t<key>^Resources/</key>\n\t\t<true/>\n\t\t<key>^Resources/.*\\.lproj/</key>\n\t\t<dict>\n\t\t\t<key>optional</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>1000</real>\n\t\t</dict>\n\t\t<key>^Resources/.*\\.lproj/locversion.plist$</key>\n\t\t<dict>\n\t\t\t<key>omit</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>1100</real>\n\t\t</dict>\n\t\t<key>^Resources/Base\\.lproj/</key>\n\t\t<dict>\n\t\t\t<key>weight</key>\n\t\t\t<real>1010</real>\n\t\t</dict>\n\t\t<key>^version.plist$</key>\n\t\t<true/>\n\t</dict>\n\t<key>rules2</key>\n\t<dict>\n\t\t<key>.*\\.dSYM($|/)</key>\n\t\t<dict>\n\t\t\t<key>weight</key>\n\t\t\t<real>11</real>\n\t\t</dict>\n\t\t<key>^(.*/)?\\.DS_Store$</key>\n\t\t<dict>\n\t\t\t<key>omit</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>2000</real>\n\t\t</dict>\n\t\t<key>^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/</key>\n\t\t<dict>\n\t\t\t<key>nested</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>10</real>\n\t\t</dict>\n\t\t<key>^.*</key>\n\t\t<true/>\n\t\t<key>^Info\\.plist$</key>\n\t\t<dict>\n\t\t\t<key>omit</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>20</real>\n\t\t</dict>\n\t\t<key>^PkgInfo$</key>\n\t\t<dict>\n\t\t\t<key>omit</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>20</real>\n\t\t</dict>\n\t\t<key>^Resources/</key>\n\t\t<dict>\n\t\t\t<key>weight</key>\n\t\t\t<real>20</real>\n\t\t</dict>\n\t\t<key>^Resources/.*\\.lproj/</key>\n\t\t<dict>\n\t\t\t<key>optional</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>1000</real>\n\t\t</dict>\n\t\t<key>^Resources/.*\\.lproj/locversion.plist$</key>\n\t\t<dict>\n\t\t\t<key>omit</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>1100</real>\n\t\t</dict>\n\t\t<key>^Resources/Base\\.lproj/</key>\n\t\t<dict>\n\t\t\t<key>weight</key>\n\t\t\t<real>1010</real>\n\t\t</dict>\n\t\t<key>^[^/]+$</key>\n\t\t<dict>\n\t\t\t<key>nested</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>10</real>\n\t\t</dict>\n\t\t<key>^embedded\\.provisionprofile$</key>\n\t\t<dict>\n\t\t\t<key>weight</key>\n\t\t\t<real>20</real>\n\t\t</dict>\n\t\t<key>^version\\.plist$</key>\n\t\t<dict>\n\t\t\t<key>weight</key>\n\t\t\t<real>20</real>\n\t\t</dict>\n\t</dict>\n</dict>\n</plist>\n"
  },
  {
    "path": "Releases/DNS Easy Switcher v1.0.1/DNS Easy Switcher.app/Contents/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>BuildMachineOSBuild</key>\n\t<string>23F79</string>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>en</string>\n\t<key>CFBundleDisplayName</key>\n\t<string>DNS Easy Switcher</string>\n\t<key>CFBundleExecutable</key>\n\t<string>DNS Easy Switcher</string>\n\t<key>CFBundleIconFile</key>\n\t<string>AppIcon</string>\n\t<key>CFBundleIconName</key>\n\t<string>AppIcon</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>com.linfordsoftware.dnseasyswitcher</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>DNS Easy Switcher</string>\n\t<key>CFBundlePackageType</key>\n\t<string>APPL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>1.0.1</string>\n\t<key>CFBundleSupportedPlatforms</key>\n\t<array>\n\t\t<string>MacOSX</string>\n\t</array>\n\t<key>CFBundleVersion</key>\n\t<string>2</string>\n\t<key>DTCompiler</key>\n\t<string>com.apple.compilers.llvm.clang.1_0</string>\n\t<key>DTPlatformBuild</key>\n\t<string></string>\n\t<key>DTPlatformName</key>\n\t<string>macosx</string>\n\t<key>DTPlatformVersion</key>\n\t<string>14.0</string>\n\t<key>DTSDKBuild</key>\n\t<string>23A334</string>\n\t<key>DTSDKName</key>\n\t<string>macosx14.0</string>\n\t<key>DTXcode</key>\n\t<string>1501</string>\n\t<key>DTXcodeBuild</key>\n\t<string>15A507</string>\n\t<key>LSApplicationCategoryType</key>\n\t<string>public.app-category.utilities</string>\n\t<key>LSMinimumSystemVersion</key>\n\t<string>14.0</string>\n</dict>\n</plist>\n"
  },
  {
    "path": "Releases/DNS Easy Switcher v1.0.1/DNS Easy Switcher.app/Contents/PkgInfo",
    "content": "APPL????"
  },
  {
    "path": "Releases/DNS Easy Switcher v1.0.1/DNS Easy Switcher.app/Contents/_CodeSignature/CodeResources",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>files</key>\n\t<dict>\n\t\t<key>Resources/AppIcon.icns</key>\n\t\t<data>\n\t\tF6YGlmox4KixBMRrSRhTusxdld8=\n\t\t</data>\n\t\t<key>Resources/Assets.car</key>\n\t\t<data>\n\t\tIhhuUihlv8TNfeE5CB9OZcOX21w=\n\t\t</data>\n\t</dict>\n\t<key>files2</key>\n\t<dict>\n\t\t<key>Resources/AppIcon.icns</key>\n\t\t<dict>\n\t\t\t<key>hash2</key>\n\t\t\t<data>\n\t\t\tI0wlcCvBzQjHkKQ1llwB0poCp2bmfglbZW45inQqQV0=\n\t\t\t</data>\n\t\t</dict>\n\t\t<key>Resources/Assets.car</key>\n\t\t<dict>\n\t\t\t<key>hash2</key>\n\t\t\t<data>\n\t\t\t/sNzrOXugwAIyPdIJZkIv1275OZELTMDgWfU3DNwkwQ=\n\t\t\t</data>\n\t\t</dict>\n\t</dict>\n\t<key>rules</key>\n\t<dict>\n\t\t<key>^Resources/</key>\n\t\t<true/>\n\t\t<key>^Resources/.*\\.lproj/</key>\n\t\t<dict>\n\t\t\t<key>optional</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>1000</real>\n\t\t</dict>\n\t\t<key>^Resources/.*\\.lproj/locversion.plist$</key>\n\t\t<dict>\n\t\t\t<key>omit</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>1100</real>\n\t\t</dict>\n\t\t<key>^Resources/Base\\.lproj/</key>\n\t\t<dict>\n\t\t\t<key>weight</key>\n\t\t\t<real>1010</real>\n\t\t</dict>\n\t\t<key>^version.plist$</key>\n\t\t<true/>\n\t</dict>\n\t<key>rules2</key>\n\t<dict>\n\t\t<key>.*\\.dSYM($|/)</key>\n\t\t<dict>\n\t\t\t<key>weight</key>\n\t\t\t<real>11</real>\n\t\t</dict>\n\t\t<key>^(.*/)?\\.DS_Store$</key>\n\t\t<dict>\n\t\t\t<key>omit</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>2000</real>\n\t\t</dict>\n\t\t<key>^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/</key>\n\t\t<dict>\n\t\t\t<key>nested</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>10</real>\n\t\t</dict>\n\t\t<key>^.*</key>\n\t\t<true/>\n\t\t<key>^Info\\.plist$</key>\n\t\t<dict>\n\t\t\t<key>omit</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>20</real>\n\t\t</dict>\n\t\t<key>^PkgInfo$</key>\n\t\t<dict>\n\t\t\t<key>omit</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>20</real>\n\t\t</dict>\n\t\t<key>^Resources/</key>\n\t\t<dict>\n\t\t\t<key>weight</key>\n\t\t\t<real>20</real>\n\t\t</dict>\n\t\t<key>^Resources/.*\\.lproj/</key>\n\t\t<dict>\n\t\t\t<key>optional</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>1000</real>\n\t\t</dict>\n\t\t<key>^Resources/.*\\.lproj/locversion.plist$</key>\n\t\t<dict>\n\t\t\t<key>omit</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>1100</real>\n\t\t</dict>\n\t\t<key>^Resources/Base\\.lproj/</key>\n\t\t<dict>\n\t\t\t<key>weight</key>\n\t\t\t<real>1010</real>\n\t\t</dict>\n\t\t<key>^[^/]+$</key>\n\t\t<dict>\n\t\t\t<key>nested</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>10</real>\n\t\t</dict>\n\t\t<key>^embedded\\.provisionprofile$</key>\n\t\t<dict>\n\t\t\t<key>weight</key>\n\t\t\t<real>20</real>\n\t\t</dict>\n\t\t<key>^version\\.plist$</key>\n\t\t<dict>\n\t\t\t<key>weight</key>\n\t\t\t<real>20</real>\n\t\t</dict>\n\t</dict>\n</dict>\n</plist>\n"
  },
  {
    "path": "Releases/DNS Easy Switcher v1.0.2/DNS Easy Switcher.app/Contents/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>BuildMachineOSBuild</key>\n\t<string>23F79</string>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>en</string>\n\t<key>CFBundleDisplayName</key>\n\t<string>DNS Easy Switcher</string>\n\t<key>CFBundleExecutable</key>\n\t<string>DNS Easy Switcher</string>\n\t<key>CFBundleIconFile</key>\n\t<string>AppIcon</string>\n\t<key>CFBundleIconName</key>\n\t<string>AppIcon</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>com.linfordsoftware.dnseasyswitcher</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>DNS Easy Switcher</string>\n\t<key>CFBundlePackageType</key>\n\t<string>APPL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>1.0.2</string>\n\t<key>CFBundleSupportedPlatforms</key>\n\t<array>\n\t\t<string>MacOSX</string>\n\t</array>\n\t<key>CFBundleVersion</key>\n\t<string>2</string>\n\t<key>DTCompiler</key>\n\t<string>com.apple.compilers.llvm.clang.1_0</string>\n\t<key>DTPlatformBuild</key>\n\t<string></string>\n\t<key>DTPlatformName</key>\n\t<string>macosx</string>\n\t<key>DTPlatformVersion</key>\n\t<string>14.0</string>\n\t<key>DTSDKBuild</key>\n\t<string>23A334</string>\n\t<key>DTSDKName</key>\n\t<string>macosx14.0</string>\n\t<key>DTXcode</key>\n\t<string>1501</string>\n\t<key>DTXcodeBuild</key>\n\t<string>15A507</string>\n\t<key>LSApplicationCategoryType</key>\n\t<string>public.app-category.utilities</string>\n\t<key>LSMinimumSystemVersion</key>\n\t<string>14.0</string>\n</dict>\n</plist>\n"
  },
  {
    "path": "Releases/DNS Easy Switcher v1.0.2/DNS Easy Switcher.app/Contents/PkgInfo",
    "content": "APPL????"
  },
  {
    "path": "Releases/DNS Easy Switcher v1.0.2/DNS Easy Switcher.app/Contents/_CodeSignature/CodeResources",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>files</key>\n\t<dict>\n\t\t<key>Resources/AppIcon.icns</key>\n\t\t<data>\n\t\tF6YGlmox4KixBMRrSRhTusxdld8=\n\t\t</data>\n\t\t<key>Resources/Assets.car</key>\n\t\t<data>\n\t\tIhhuUihlv8TNfeE5CB9OZcOX21w=\n\t\t</data>\n\t</dict>\n\t<key>files2</key>\n\t<dict>\n\t\t<key>Resources/AppIcon.icns</key>\n\t\t<dict>\n\t\t\t<key>hash2</key>\n\t\t\t<data>\n\t\t\tI0wlcCvBzQjHkKQ1llwB0poCp2bmfglbZW45inQqQV0=\n\t\t\t</data>\n\t\t</dict>\n\t\t<key>Resources/Assets.car</key>\n\t\t<dict>\n\t\t\t<key>hash2</key>\n\t\t\t<data>\n\t\t\t/sNzrOXugwAIyPdIJZkIv1275OZELTMDgWfU3DNwkwQ=\n\t\t\t</data>\n\t\t</dict>\n\t</dict>\n\t<key>rules</key>\n\t<dict>\n\t\t<key>^Resources/</key>\n\t\t<true/>\n\t\t<key>^Resources/.*\\.lproj/</key>\n\t\t<dict>\n\t\t\t<key>optional</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>1000</real>\n\t\t</dict>\n\t\t<key>^Resources/.*\\.lproj/locversion.plist$</key>\n\t\t<dict>\n\t\t\t<key>omit</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>1100</real>\n\t\t</dict>\n\t\t<key>^Resources/Base\\.lproj/</key>\n\t\t<dict>\n\t\t\t<key>weight</key>\n\t\t\t<real>1010</real>\n\t\t</dict>\n\t\t<key>^version.plist$</key>\n\t\t<true/>\n\t</dict>\n\t<key>rules2</key>\n\t<dict>\n\t\t<key>.*\\.dSYM($|/)</key>\n\t\t<dict>\n\t\t\t<key>weight</key>\n\t\t\t<real>11</real>\n\t\t</dict>\n\t\t<key>^(.*/)?\\.DS_Store$</key>\n\t\t<dict>\n\t\t\t<key>omit</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>2000</real>\n\t\t</dict>\n\t\t<key>^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/</key>\n\t\t<dict>\n\t\t\t<key>nested</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>10</real>\n\t\t</dict>\n\t\t<key>^.*</key>\n\t\t<true/>\n\t\t<key>^Info\\.plist$</key>\n\t\t<dict>\n\t\t\t<key>omit</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>20</real>\n\t\t</dict>\n\t\t<key>^PkgInfo$</key>\n\t\t<dict>\n\t\t\t<key>omit</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>20</real>\n\t\t</dict>\n\t\t<key>^Resources/</key>\n\t\t<dict>\n\t\t\t<key>weight</key>\n\t\t\t<real>20</real>\n\t\t</dict>\n\t\t<key>^Resources/.*\\.lproj/</key>\n\t\t<dict>\n\t\t\t<key>optional</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>1000</real>\n\t\t</dict>\n\t\t<key>^Resources/.*\\.lproj/locversion.plist$</key>\n\t\t<dict>\n\t\t\t<key>omit</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>1100</real>\n\t\t</dict>\n\t\t<key>^Resources/Base\\.lproj/</key>\n\t\t<dict>\n\t\t\t<key>weight</key>\n\t\t\t<real>1010</real>\n\t\t</dict>\n\t\t<key>^[^/]+$</key>\n\t\t<dict>\n\t\t\t<key>nested</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>10</real>\n\t\t</dict>\n\t\t<key>^embedded\\.provisionprofile$</key>\n\t\t<dict>\n\t\t\t<key>weight</key>\n\t\t\t<real>20</real>\n\t\t</dict>\n\t\t<key>^version\\.plist$</key>\n\t\t<dict>\n\t\t\t<key>weight</key>\n\t\t\t<real>20</real>\n\t\t</dict>\n\t</dict>\n</dict>\n</plist>\n"
  },
  {
    "path": "Releases/DNS Easy Switcher v1.0.3/DNS Easy Switcher.app/Contents/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>BuildMachineOSBuild</key>\n\t<string>23F79</string>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>en</string>\n\t<key>CFBundleDisplayName</key>\n\t<string>DNS Easy Switcher</string>\n\t<key>CFBundleExecutable</key>\n\t<string>DNS Easy Switcher</string>\n\t<key>CFBundleIconFile</key>\n\t<string>AppIcon</string>\n\t<key>CFBundleIconName</key>\n\t<string>AppIcon</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>com.linfordsoftware.dnseasyswitcher</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>DNS Easy Switcher</string>\n\t<key>CFBundlePackageType</key>\n\t<string>APPL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>1.0.3</string>\n\t<key>CFBundleSupportedPlatforms</key>\n\t<array>\n\t\t<string>MacOSX</string>\n\t</array>\n\t<key>CFBundleVersion</key>\n\t<string>4</string>\n\t<key>DTCompiler</key>\n\t<string>com.apple.compilers.llvm.clang.1_0</string>\n\t<key>DTPlatformBuild</key>\n\t<string></string>\n\t<key>DTPlatformName</key>\n\t<string>macosx</string>\n\t<key>DTPlatformVersion</key>\n\t<string>14.0</string>\n\t<key>DTSDKBuild</key>\n\t<string>23A334</string>\n\t<key>DTSDKName</key>\n\t<string>macosx14.0</string>\n\t<key>DTXcode</key>\n\t<string>1501</string>\n\t<key>DTXcodeBuild</key>\n\t<string>15A507</string>\n\t<key>LSApplicationCategoryType</key>\n\t<string>public.app-category.utilities</string>\n\t<key>LSMinimumSystemVersion</key>\n\t<string>14.0</string>\n</dict>\n</plist>\n"
  },
  {
    "path": "Releases/DNS Easy Switcher v1.0.3/DNS Easy Switcher.app/Contents/PkgInfo",
    "content": "APPL????"
  },
  {
    "path": "Releases/DNS Easy Switcher v1.0.3/DNS Easy Switcher.app/Contents/_CodeSignature/CodeResources",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>files</key>\n\t<dict>\n\t\t<key>Resources/AppIcon.icns</key>\n\t\t<data>\n\t\tF6YGlmox4KixBMRrSRhTusxdld8=\n\t\t</data>\n\t\t<key>Resources/Assets.car</key>\n\t\t<data>\n\t\tIhhuUihlv8TNfeE5CB9OZcOX21w=\n\t\t</data>\n\t</dict>\n\t<key>files2</key>\n\t<dict>\n\t\t<key>Resources/AppIcon.icns</key>\n\t\t<dict>\n\t\t\t<key>hash2</key>\n\t\t\t<data>\n\t\t\tI0wlcCvBzQjHkKQ1llwB0poCp2bmfglbZW45inQqQV0=\n\t\t\t</data>\n\t\t</dict>\n\t\t<key>Resources/Assets.car</key>\n\t\t<dict>\n\t\t\t<key>hash2</key>\n\t\t\t<data>\n\t\t\t/sNzrOXugwAIyPdIJZkIv1275OZELTMDgWfU3DNwkwQ=\n\t\t\t</data>\n\t\t</dict>\n\t</dict>\n\t<key>rules</key>\n\t<dict>\n\t\t<key>^Resources/</key>\n\t\t<true/>\n\t\t<key>^Resources/.*\\.lproj/</key>\n\t\t<dict>\n\t\t\t<key>optional</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>1000</real>\n\t\t</dict>\n\t\t<key>^Resources/.*\\.lproj/locversion.plist$</key>\n\t\t<dict>\n\t\t\t<key>omit</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>1100</real>\n\t\t</dict>\n\t\t<key>^Resources/Base\\.lproj/</key>\n\t\t<dict>\n\t\t\t<key>weight</key>\n\t\t\t<real>1010</real>\n\t\t</dict>\n\t\t<key>^version.plist$</key>\n\t\t<true/>\n\t</dict>\n\t<key>rules2</key>\n\t<dict>\n\t\t<key>.*\\.dSYM($|/)</key>\n\t\t<dict>\n\t\t\t<key>weight</key>\n\t\t\t<real>11</real>\n\t\t</dict>\n\t\t<key>^(.*/)?\\.DS_Store$</key>\n\t\t<dict>\n\t\t\t<key>omit</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>2000</real>\n\t\t</dict>\n\t\t<key>^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/</key>\n\t\t<dict>\n\t\t\t<key>nested</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>10</real>\n\t\t</dict>\n\t\t<key>^.*</key>\n\t\t<true/>\n\t\t<key>^Info\\.plist$</key>\n\t\t<dict>\n\t\t\t<key>omit</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>20</real>\n\t\t</dict>\n\t\t<key>^PkgInfo$</key>\n\t\t<dict>\n\t\t\t<key>omit</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>20</real>\n\t\t</dict>\n\t\t<key>^Resources/</key>\n\t\t<dict>\n\t\t\t<key>weight</key>\n\t\t\t<real>20</real>\n\t\t</dict>\n\t\t<key>^Resources/.*\\.lproj/</key>\n\t\t<dict>\n\t\t\t<key>optional</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>1000</real>\n\t\t</dict>\n\t\t<key>^Resources/.*\\.lproj/locversion.plist$</key>\n\t\t<dict>\n\t\t\t<key>omit</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>1100</real>\n\t\t</dict>\n\t\t<key>^Resources/Base\\.lproj/</key>\n\t\t<dict>\n\t\t\t<key>weight</key>\n\t\t\t<real>1010</real>\n\t\t</dict>\n\t\t<key>^[^/]+$</key>\n\t\t<dict>\n\t\t\t<key>nested</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>10</real>\n\t\t</dict>\n\t\t<key>^embedded\\.provisionprofile$</key>\n\t\t<dict>\n\t\t\t<key>weight</key>\n\t\t\t<real>20</real>\n\t\t</dict>\n\t\t<key>^version\\.plist$</key>\n\t\t<dict>\n\t\t\t<key>weight</key>\n\t\t\t<real>20</real>\n\t\t</dict>\n\t</dict>\n</dict>\n</plist>\n"
  },
  {
    "path": "Releases/DNS Easy Switcher v1.0.3/DistributionSummary.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>DNS Easy Switcher</key>\n\t<array>\n\t\t<dict>\n\t\t\t<key>architectures</key>\n\t\t\t<array>\n\t\t\t\t<string>x86_64</string>\n\t\t\t\t<string>arm64</string>\n\t\t\t</array>\n\t\t\t<key>buildNumber</key>\n\t\t\t<string>4</string>\n\t\t\t<key>certificate</key>\n\t\t\t<dict>\n\t\t\t\t<key>SHA1</key>\n\t\t\t\t<string>8FB842802AF0A81CD08194DB5E6CA6B5FB771823</string>\n\t\t\t\t<key>dateExpires</key>\n\t\t\t\t<string>26/02/2030</string>\n\t\t\t\t<key>type</key>\n\t\t\t\t<string>Developer ID Application</string>\n\t\t\t</dict>\n\t\t\t<key>name</key>\n\t\t\t<string>DNS Easy Switcher.app</string>\n\t\t\t<key>team</key>\n\t\t\t<dict>\n\t\t\t\t<key>id</key>\n\t\t\t\t<string>6645MJMX63</string>\n\t\t\t\t<key>name</key>\n\t\t\t\t<string>Gregory Linford</string>\n\t\t\t</dict>\n\t\t\t<key>versionNumber</key>\n\t\t\t<string>1.0.3</string>\n\t\t</dict>\n\t</array>\n</dict>\n</plist>\n"
  },
  {
    "path": "Releases/DNS Easy Switcher v1.0.3/ExportOptions.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>destination</key>\n\t<string>export</string>\n\t<key>method</key>\n\t<string>developer-id</string>\n\t<key>signingStyle</key>\n\t<string>automatic</string>\n\t<key>teamID</key>\n\t<string>6645MJMX63</string>\n</dict>\n</plist>\n"
  },
  {
    "path": "Releases/DNS Easy Switcher v1.0.3/Packaging.log",
    "content": "2025-02-25 22:00:11 +0000  Initial pipeline context: <IDEDistributionProcessingPipelineContext: 0x12ff20ce0; archive(resolved)=\"<IDEArchive: 0x600008e05380>\", distributionTask(resolved)=\"2\", distributionDestination(resolved)=\"1\", distributionMethod(resolved)=\"<IDEDistributionMethodDeveloperID: 0x60000a9d6ab0>\", team(resolved)=\"<IDEProvisioningDisambiguatableBasicTeam: 0x6000071c8400; teamID='6645MJMX63', teamName='Gregory Linford', teamType='Individual', username='greglin19@gmail.com', isFreeProvisioningTeam='0'>\">\n\tChain (13, self inclusive):\n\t<IDEDistributionProcessingPipelineContext: 0x12ff20ce0; archive = \"<IDEArchive: 0x600008e05380>\", distributionMethod=\"<IDEDistributionMethodDeveloperID: 0x60000a9d6ab0>\", team=\"<IDEProvisioningDisambiguatableBasicTeam: 0x6000071c8400; teamID='6645MJMX63', teamName='Gregory Linford', teamType='Individual', username='greglin19@gmail.com', isFreeProvisioningTeam='0'>\">\n\t<IDEDistributionProcessingPipelineContext: 0x12ff20a40; archive = \"<IDEArchive: 0x600008e05380>\", distributionMethod=\"<IDEDistributionMethodDeveloperID: 0x60000a9d6ab0>\", team=\"<IDEProvisioningDisambiguatableBasicTeam: 0x6000071c8400; teamID='6645MJMX63', teamName='Gregory Linford', teamType='Individual', username='greglin19@gmail.com', isFreeProvisioningTeam='0'>\">\n\t<IDEDistributionContext: 0x1691170b0; archive = \"<IDEArchive: 0x600008e05380>\", distributionMethod=\"<IDEDistributionMethodDeveloperID: 0x60000a9d6ab0>\", team=\"<IDEProvisioningDisambiguatableBasicTeam: 0x6000071c8400; teamID='6645MJMX63', teamName='Gregory Linford', teamType='Individual', username='greglin19@gmail.com', isFreeProvisioningTeam='0'>\">\n\t<IDEDistributionContext: 0x313e57e20; archive = \"<IDEArchive: 0x600008e05380>\", distributionMethod=\"<IDEDistributionMethodDeveloperID: 0x60000a9d6ab0>\", team=\"<IDEProvisioningDisambiguatableBasicTeam: 0x6000071c8400; teamID='6645MJMX63', teamName='Gregory Linford', teamType='Individual', username='greglin19@gmail.com', isFreeProvisioningTeam='0'>\">\n\t<IDEDistributionContext: 0x10ba89ed0; archive = \"<IDEArchive: 0x600008e05380>\", distributionMethod=\"<IDEDistributionMethodDeveloperID: 0x60000a9d6ab0>\", team=\"<IDEProvisioningDisambiguatableBasicTeam: 0x6000071c8400; teamID='6645MJMX63', teamName='Gregory Linford', teamType='Individual', username='greglin19@gmail.com', isFreeProvisioningTeam='0'>\">\n\t<IDEDistributionContext: 0x12ff143a0; archive = \"<IDEArchive: 0x600008e05380>\", distributionMethod=\"<IDEDistributionMethodDeveloperID: 0x60000a9d6ab0>\", team=\"<IDEProvisioningDisambiguatableBasicTeam: 0x6000071c8400; teamID='6645MJMX63', teamName='Gregory Linford', teamType='Individual', username='greglin19@gmail.com', isFreeProvisioningTeam='0'>\">\n\t<IDEDistributionContext: 0x12ff13ff0; archive = \"<IDEArchive: 0x600008e05380>\", distributionMethod=\"<IDEDistributionMethodDeveloperID: 0x60000a9d6ab0>\", team=\"<IDEProvisioningDisambiguatableBasicTeam: 0x6000071c8400; teamID='6645MJMX63', teamName='Gregory Linford', teamType='Individual', username='greglin19@gmail.com', isFreeProvisioningTeam='0'>\">\n\t<IDEDistributionContext: 0x12ff14900; archive = \"<IDEArchive: 0x600008e05380>\", distributionMethod=\"<IDEDistributionMethodDeveloperID: 0x60000a9d6ab0>\", team=\"<IDEProvisioningDisambiguatableBasicTeam: 0x6000071c8400; teamID='6645MJMX63', teamName='Gregory Linford', teamType='Individual', username='greglin19@gmail.com', isFreeProvisioningTeam='0'>\">\n\t<IDEDistributionContext: 0x10bafd670; archive = \"<IDEArchive: 0x600008e05380>\", distributionMethod=\"<IDEDistributionMethodDeveloperID: 0x60000a9d6ab0>\", team=\"<IDEProvisioningDisambiguatableBasicTeam: 0x6000071c8400; teamID='6645MJMX63', teamName='Gregory Linford', teamType='Individual', username='greglin19@gmail.com', isFreeProvisioningTeam='0'>\">\n\t<IDEDistributionContext: 0x3231a3910; archive = \"<IDEArchive: 0x600008e05380>\", distributionMethod=\"<IDEDistributionMethodDeveloperID: 0x60000a9d6ab0>\", team=\"(null)\">\n\t<IDEDistributionContext: 0x362b199e0; archive = \"<IDEArchive: 0x600008e05380>\", distributionMethod=\"<IDEDistributionMethodDeveloperID: 0x60000a9d6ab0>\", team=\"(null)\">\n\t<IDEDistributionContext: 0x323321b70; archive = \"<IDEArchive: 0x600008e05380>\", distributionMethod=\"(null)\", team=\"(null)\">\n\t<IDEDistributionContext: 0x33f8d9800; archive = \"<IDEArchive: 0x600008e05380>\", distributionMethod=\"(null)\", team=\"(null)\">\n</IDEDistributionProcessingPipelineContext: 0x12ff20ce0>\n2025-02-25 22:00:11 +0000  Processing step: IDEDistributionCreateDestRootStep\n2025-02-25 22:00:11 +0000  Processing step: IDEDistributionCopyItemStep\n2025-02-25 22:00:11 +0000  Running /usr/bin/ditto '-V' '/Users/glinf/Library/Developer/Xcode/Archives/2025-02-25/DNS Easy Switcher 25-02-2025, 22.59.xcarchive/Products/Applications/DNS Easy Switcher.app' '/var/folders/33/r3mtzdn102x40vpjzrzm9kyh0000gn/T/XcodeDistPipeline.~~~8zKmE7/Root/Applications/DNS Easy Switcher.app'\n2025-02-25 22:00:11 +0000  >>> Copying /Users/glinf/Library/Developer/Xcode/Archives/2025-02-25/DNS Easy Switcher 25-02-2025, 22.59.xcarchive/Products/Applications/DNS Easy Switcher.app \n2025-02-25 22:00:11 +0000  copying file ./Contents/_CodeSignature/CodeResources ... \n2025-02-25 22:00:11 +0000  2672 bytes for ./Contents/_CodeSignature/CodeResources\n2025-02-25 22:00:11 +0000  copying file ./Contents/MacOS/DNS Easy Switcher ... \n2025-02-25 22:00:11 +0000  664176 bytes for ./Contents/MacOS/DNS Easy Switcher\n2025-02-25 22:00:11 +0000  copying file ./Contents/Resources/AppIcon.icns ... \n2025-02-25 22:00:11 +0000  67535 bytes for ./Contents/Resources/AppIcon.icns\n2025-02-25 22:00:11 +0000  copying file ./Contents/Resources/Assets.car ... \n2025-02-25 22:00:11 +0000  745832 bytes for ./Contents/Resources/Assets.car\n2025-02-25 22:00:11 +0000  copying file ./Contents/Info.plist ... \n2025-02-25 22:00:11 +0000  1572 bytes for ./Contents/Info.plist\n2025-02-25 22:00:11 +0000  copying file ./Contents/PkgInfo ... \n2025-02-25 22:00:11 +0000  8 bytes for ./Contents/PkgInfo\n2025-02-25 22:00:11 +0000  /usr/bin/ditto exited with 0\n2025-02-25 22:00:11 +0000  Processing step: IDEDistributionEmbedProfileStep\n2025-02-25 22:00:11 +0000  Skipping profile for item: <IDEDistributionItem: 0x6000041be5e0; bundleID='com.linfordsoftware.dnseasyswitcher', path='<DVTFilePath:0x60000400ba30:'/Users/glinf/Library/Developer/Xcode/Archives/2025-02-25/DNS Easy Switcher 25-02-2025, 22.59.xcarchive/Products/Applications/DNS Easy Switcher.app'>', codeSigningInfo='<_DVTCodeSigningInformation_Path: 0x60000ca58eb0; isSigned='1', isAdHocSigned='0', signingCertificate='<DVTSigningCertificate: 0x6000011c8000; name='Apple Development: Gregory Linford (XGV4H982AX)', hash='75EA596AB87130E42C8EC49DCDCA8469458315F6', serialNumber='148CC429E2C0F0690B09BCCED6AB40F3', certificateKinds='(\n    \"1.2.840.113635.100.6.1.12\",\n    \"1.2.840.113635.100.6.1.2\"\n), issueDate='2025-02-23 14:00:58 +0000''>', entitlements='{\n}', teamID='6645MJMX63', identifier='com.linfordsoftware.dnseasyswitcher', executablePath='<DVTFilePath:0x600004009180:'/Users/glinf/Library/Developer/Xcode/Archives/2025-02-25/DNS Easy Switcher 25-02-2025, 22.59.xcarchive/Products/Applications/DNS Easy Switcher.app/Contents/MacOS/DNS Easy Switcher'>', hardenedRuntime='1'>'>\n2025-02-25 22:00:11 +0000  Processing step: IDEDistributionInfoPlistStep\n2025-02-25 22:00:11 +0000  Skipping step: IDEDistributionInfoPlistStep because it said so\n2025-02-25 22:00:11 +0000  Processing step: IDEDistributionAppThinningPlistStep\n2025-02-25 22:00:11 +0000  Processing step: IDEDistributionCompileBitcodeStep\n2025-02-25 22:00:11 +0000  Skipping step: IDEDistributionCompileBitcodeStep because it said so\n2025-02-25 22:00:11 +0000  Processing step: IDEDistributionCodeSlimmingStep\n2025-02-25 22:00:11 +0000  Processing step: IDEDistributionCopyBCSymbolMapsStep\n2025-02-25 22:00:11 +0000  Skipping step: IDEDistributionCopyBCSymbolMapsStep because it said so\n2025-02-25 22:00:11 +0000  Processing step: IDEDistributionSymbolsStep\n2025-02-25 22:00:11 +0000  Skipping step: IDEDistributionSymbolsStep because it said so\n2025-02-25 22:00:11 +0000  Processing step: IDEDistributionAppThinningStep\n2025-02-25 22:00:11 +0000  Skipping step: IDEDistributionAppThinningStep because it said so\n2025-02-25 22:00:11 +0000  Processing step: IDEDistributionArchThinningStep\n2025-02-25 22:00:11 +0000  Running /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/lipo '/var/folders/33/r3mtzdn102x40vpjzrzm9kyh0000gn/T/XcodeDistPipeline.~~~8zKmE7/Root/Applications/DNS Easy Switcher.app/Contents/MacOS/DNS Easy Switcher' '-verify_arch' 'arm64e'\n2025-02-25 22:00:11 +0000  /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/lipo exited with 1\n2025-02-25 22:00:11 +0000  Skipping architecture thinning for item \"DNS Easy Switcher\" because arch \"arm64e\" wasn't found\n2025-02-25 22:00:11 +0000  Processing step: IDEDistributionODRStep\n2025-02-25 22:00:11 +0000  Processing step: IDEDistributionStripXattrsStep\n2025-02-25 22:00:11 +0000  Skipping stripping extended attributes because the codesign step will strip them.\n2025-02-25 22:00:11 +0000  Processing step: IDEDistributionCodesignStep\n2025-02-25 22:00:11 +0000  Entitlements for <IDEDistributionItem: 0x6000041be5e0; bundleID='com.linfordsoftware.dnseasyswitcher', path='<DVTFilePath:0x60000400ba30:'/Users/glinf/Library/Developer/Xcode/Archives/2025-02-25/DNS Easy Switcher 25-02-2025, 22.59.xcarchive/Products/Applications/DNS Easy Switcher.app'>', codeSigningInfo='<_DVTCodeSigningInformation_Path: 0x60000ca58eb0; isSigned='1', isAdHocSigned='0', signingCertificate='<DVTSigningCertificate: 0x600001e7cf00; name='Apple Development: Gregory Linford (XGV4H982AX)', hash='75EA596AB87130E42C8EC49DCDCA8469458315F6', serialNumber='148CC429E2C0F0690B09BCCED6AB40F3', certificateKinds='(\n    \"1.2.840.113635.100.6.1.12\",\n    \"1.2.840.113635.100.6.1.2\"\n), issueDate='2025-02-23 14:00:58 +0000''>', entitlements='{\n}', teamID='6645MJMX63', identifier='com.linfordsoftware.dnseasyswitcher', executablePath='<DVTFilePath:0x600004009180:'/Users/glinf/Library/Developer/Xcode/Archives/2025-02-25/DNS Easy Switcher 25-02-2025, 22.59.xcarchive/Products/Applications/DNS Easy Switcher.app/Contents/MacOS/DNS Easy Switcher'>', hardenedRuntime='1'>'>: {\n}\n2025-02-25 22:00:11 +0000  Associated App Clip Identifiers Filter: Skipping because \"com.apple.developer.associated-appclip-app-identifiers\" is not present\n2025-02-25 22:00:11 +0000  Entitlements for <IDEDistributionItem: 0x6000041be5e0; bundleID='com.linfordsoftware.dnseasyswitcher', path='<DVTFilePath:0x60000400ba30:'/Users/glinf/Library/Developer/Xcode/Archives/2025-02-25/DNS Easy Switcher 25-02-2025, 22.59.xcarchive/Products/Applications/DNS Easy Switcher.app'>', codeSigningInfo='<_DVTCodeSigningInformation_Path: 0x60000ca58eb0; isSigned='1', isAdHocSigned='0', signingCertificate='<DVTSigningCertificate: 0x600001e7d980; name='Apple Development: Gregory Linford (XGV4H982AX)', hash='75EA596AB87130E42C8EC49DCDCA8469458315F6', serialNumber='148CC429E2C0F0690B09BCCED6AB40F3', certificateKinds='(\n    \"1.2.840.113635.100.6.1.12\",\n    \"1.2.840.113635.100.6.1.2\"\n), issueDate='2025-02-23 14:00:58 +0000''>', entitlements='{\n}', teamID='6645MJMX63', identifier='com.linfordsoftware.dnseasyswitcher', executablePath='<DVTFilePath:0x600004009180:'/Users/glinf/Library/Developer/Xcode/Archives/2025-02-25/DNS Easy Switcher 25-02-2025, 22.59.xcarchive/Products/Applications/DNS Easy Switcher.app/Contents/MacOS/DNS Easy Switcher'>', hardenedRuntime='1'>'> are: {\n}\n2025-02-25 22:00:11 +0000  Writing entitlements for <IDEDistributionItem: 0x6000041be5e0; bundleID='com.linfordsoftware.dnseasyswitcher', path='<DVTFilePath:0x60000400ba30:'/Users/glinf/Library/Developer/Xcode/Archives/2025-02-25/DNS Easy Switcher 25-02-2025, 22.59.xcarchive/Products/Applications/DNS Easy Switcher.app'>', codeSigningInfo='<_DVTCodeSigningInformation_Path: 0x60000ca58eb0; isSigned='1', isAdHocSigned='0', signingCertificate='<DVTSigningCertificate: 0x600001e7d380; name='Apple Development: Gregory Linford (XGV4H982AX)', hash='75EA596AB87130E42C8EC49DCDCA8469458315F6', serialNumber='148CC429E2C0F0690B09BCCED6AB40F3', certificateKinds='(\n    \"1.2.840.113635.100.6.1.12\",\n    \"1.2.840.113635.100.6.1.2\"\n), issueDate='2025-02-23 14:00:58 +0000''>', entitlements='{\n}', teamID='6645MJMX63', identifier='com.linfordsoftware.dnseasyswitcher', executablePath='<DVTFilePath:0x600004009180:'/Users/glinf/Library/Developer/Xcode/Archives/2025-02-25/DNS Easy Switcher 25-02-2025, 22.59.xcarchive/Products/Applications/DNS Easy Switcher.app/Contents/MacOS/DNS Easy Switcher'>', hardenedRuntime='1'>'> to: /var/folders/33/r3mtzdn102x40vpjzrzm9kyh0000gn/T/XcodeDistPipeline.~~~8zKmE7/entitlements~~~Eyl0xd\n2025-02-25 22:00:11 +0000  Running /usr/bin/codesign '-vvv' '--force' '--sign' '8FB842802AF0A81CD08194DB5E6CA6B5FB771823' '--entitlements' '/var/folders/33/r3mtzdn102x40vpjzrzm9kyh0000gn/T/XcodeDistPipeline.~~~8zKmE7/entitlements~~~Eyl0xd' '--generate-entitlement-der' '--preserve-metadata=identifier,flags,runtime' '--requirements' '=designated => anchor apple generic  and identifier \"$self.identifier\" and ((cert leaf[field.1.2.840.113635.100.6.1.9] exists) or ( certificate 1[field.1.2.840.113635.100.6.2.6] exists and certificate leaf[field.1.2.840.113635.100.6.1.13] exists  and certificate leaf[subject.OU] = \"6645MJMX63\" ))' '/var/folders/33/r3mtzdn102x40vpjzrzm9kyh0000gn/T/XcodeDistPipeline.~~~8zKmE7/Root/Applications/DNS Easy Switcher.app'\n2025-02-25 22:00:11 +0000  /var/folders/33/r3mtzdn102x40vpjzrzm9kyh0000gn/T/XcodeDistPipeline.~~~8zKmE7/Root/Applications/DNS Easy Switcher.app: replacing existing signature\n2025-02-25 22:00:23 +0000  /var/folders/33/r3mtzdn102x40vpjzrzm9kyh0000gn/T/XcodeDistPipeline.~~~8zKmE7/Root/Applications/DNS Easy Switcher.app: signed app bundle with Mach-O universal (x86_64 arm64) [com.linfordsoftware.dnseasyswitcher]\n2025-02-25 22:00:23 +0000  /usr/bin/codesign exited with 0\n2025-02-25 22:00:23 +0000  Processing step: IDEDistributionZipODRItemStep\n2025-02-25 22:00:23 +0000  Skipping step: IDEDistributionZipODRItemStep because it said so\n2025-02-25 22:00:23 +0000  Processing step: IDEDistributionSkipPackagingStep\n2025-02-25 22:00:23 +0000  Processing step: IDEDistributionAppStoreInformationStep\n2025-02-25 22:00:23 +0000  Skipping step: IDEDistributionAppStoreInformationStep because it said so\n2025-02-25 22:00:23 +0000  Processing step: IDEDistributionGenerateProcessedDistributionItems\n2025-02-25 22:00:23 +0000  IDEDistributionItem init <DVTFilePath:0x60000438c460:'/var/folders/33/r3mtzdn102x40vpjzrzm9kyh0000gn/T/XcodeDistPipeline.~~~8zKmE7/Root/Applications/DNS Easy Switcher.app'>\n2025-02-25 22:00:23 +0000  [OPTIONAL] Didn't find embedded provisioning profile for <DVTFilePath:0x60000438c460:'/var/folders/33/r3mtzdn102x40vpjzrzm9kyh0000gn/T/XcodeDistPipeline.~~~8zKmE7/Root/Applications/DNS Easy Switcher.app'>: Error Domain=NSCocoaErrorDomain Code=4 \"No file at <DVTFilePath:0x6000047c8700:'/var/folders/33/r3mtzdn102x40vpjzrzm9kyh0000gn/T/XcodeDistPipeline.~~~8zKmE7/Root/Applications/DNS Easy Switcher.app/Contents/embedded.provisionprofile'>\" UserInfo={NSLocalizedDescription=No file at <DVTFilePath:0x6000047c8700:'/var/folders/33/r3mtzdn102x40vpjzrzm9kyh0000gn/T/XcodeDistPipeline.~~~8zKmE7/Root/Applications/DNS Easy Switcher.app/Contents/embedded.provisionprofile'>}\n2025-02-25 22:00:23 +0000  Processing step: IDEDistributionCreateManifestStep\n2025-02-25 22:00:23 +0000  Skipping step: IDEDistributionCreateManifestStep because it said so\n"
  },
  {
    "path": "Releases/DNS Easy Switcher v1.0.4/DNS Easy Switcher.app/Contents/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>BuildMachineOSBuild</key>\n\t<string>23F79</string>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>en</string>\n\t<key>CFBundleDisplayName</key>\n\t<string>DNS Easy Switcher</string>\n\t<key>CFBundleExecutable</key>\n\t<string>DNS Easy Switcher</string>\n\t<key>CFBundleIconFile</key>\n\t<string>AppIcon</string>\n\t<key>CFBundleIconName</key>\n\t<string>AppIcon</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>com.linfordsoftware.dnseasyswitcher</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>DNS Easy Switcher</string>\n\t<key>CFBundlePackageType</key>\n\t<string>APPL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>1.0.4</string>\n\t<key>CFBundleSupportedPlatforms</key>\n\t<array>\n\t\t<string>MacOSX</string>\n\t</array>\n\t<key>CFBundleVersion</key>\n\t<string>4</string>\n\t<key>DTCompiler</key>\n\t<string>com.apple.compilers.llvm.clang.1_0</string>\n\t<key>DTPlatformBuild</key>\n\t<string></string>\n\t<key>DTPlatformName</key>\n\t<string>macosx</string>\n\t<key>DTPlatformVersion</key>\n\t<string>14.0</string>\n\t<key>DTSDKBuild</key>\n\t<string>23A334</string>\n\t<key>DTSDKName</key>\n\t<string>macosx14.0</string>\n\t<key>DTXcode</key>\n\t<string>1501</string>\n\t<key>DTXcodeBuild</key>\n\t<string>15A507</string>\n\t<key>LSApplicationCategoryType</key>\n\t<string>public.app-category.utilities</string>\n\t<key>LSMinimumSystemVersion</key>\n\t<string>14.0</string>\n</dict>\n</plist>\n"
  },
  {
    "path": "Releases/DNS Easy Switcher v1.0.4/DNS Easy Switcher.app/Contents/PkgInfo",
    "content": "APPL????"
  },
  {
    "path": "Releases/DNS Easy Switcher v1.0.4/DNS Easy Switcher.app/Contents/_CodeSignature/CodeResources",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>files</key>\n\t<dict>\n\t\t<key>Resources/AppIcon.icns</key>\n\t\t<data>\n\t\tF6YGlmox4KixBMRrSRhTusxdld8=\n\t\t</data>\n\t\t<key>Resources/Assets.car</key>\n\t\t<data>\n\t\tIhhuUihlv8TNfeE5CB9OZcOX21w=\n\t\t</data>\n\t</dict>\n\t<key>files2</key>\n\t<dict>\n\t\t<key>Resources/AppIcon.icns</key>\n\t\t<dict>\n\t\t\t<key>hash2</key>\n\t\t\t<data>\n\t\t\tI0wlcCvBzQjHkKQ1llwB0poCp2bmfglbZW45inQqQV0=\n\t\t\t</data>\n\t\t</dict>\n\t\t<key>Resources/Assets.car</key>\n\t\t<dict>\n\t\t\t<key>hash2</key>\n\t\t\t<data>\n\t\t\t/sNzrOXugwAIyPdIJZkIv1275OZELTMDgWfU3DNwkwQ=\n\t\t\t</data>\n\t\t</dict>\n\t</dict>\n\t<key>rules</key>\n\t<dict>\n\t\t<key>^Resources/</key>\n\t\t<true/>\n\t\t<key>^Resources/.*\\.lproj/</key>\n\t\t<dict>\n\t\t\t<key>optional</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>1000</real>\n\t\t</dict>\n\t\t<key>^Resources/.*\\.lproj/locversion.plist$</key>\n\t\t<dict>\n\t\t\t<key>omit</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>1100</real>\n\t\t</dict>\n\t\t<key>^Resources/Base\\.lproj/</key>\n\t\t<dict>\n\t\t\t<key>weight</key>\n\t\t\t<real>1010</real>\n\t\t</dict>\n\t\t<key>^version.plist$</key>\n\t\t<true/>\n\t</dict>\n\t<key>rules2</key>\n\t<dict>\n\t\t<key>.*\\.dSYM($|/)</key>\n\t\t<dict>\n\t\t\t<key>weight</key>\n\t\t\t<real>11</real>\n\t\t</dict>\n\t\t<key>^(.*/)?\\.DS_Store$</key>\n\t\t<dict>\n\t\t\t<key>omit</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>2000</real>\n\t\t</dict>\n\t\t<key>^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/</key>\n\t\t<dict>\n\t\t\t<key>nested</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>10</real>\n\t\t</dict>\n\t\t<key>^.*</key>\n\t\t<true/>\n\t\t<key>^Info\\.plist$</key>\n\t\t<dict>\n\t\t\t<key>omit</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>20</real>\n\t\t</dict>\n\t\t<key>^PkgInfo$</key>\n\t\t<dict>\n\t\t\t<key>omit</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>20</real>\n\t\t</dict>\n\t\t<key>^Resources/</key>\n\t\t<dict>\n\t\t\t<key>weight</key>\n\t\t\t<real>20</real>\n\t\t</dict>\n\t\t<key>^Resources/.*\\.lproj/</key>\n\t\t<dict>\n\t\t\t<key>optional</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>1000</real>\n\t\t</dict>\n\t\t<key>^Resources/.*\\.lproj/locversion.plist$</key>\n\t\t<dict>\n\t\t\t<key>omit</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>1100</real>\n\t\t</dict>\n\t\t<key>^Resources/Base\\.lproj/</key>\n\t\t<dict>\n\t\t\t<key>weight</key>\n\t\t\t<real>1010</real>\n\t\t</dict>\n\t\t<key>^[^/]+$</key>\n\t\t<dict>\n\t\t\t<key>nested</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>10</real>\n\t\t</dict>\n\t\t<key>^embedded\\.provisionprofile$</key>\n\t\t<dict>\n\t\t\t<key>weight</key>\n\t\t\t<real>20</real>\n\t\t</dict>\n\t\t<key>^version\\.plist$</key>\n\t\t<dict>\n\t\t\t<key>weight</key>\n\t\t\t<real>20</real>\n\t\t</dict>\n\t</dict>\n</dict>\n</plist>\n"
  },
  {
    "path": "Releases/DNS Easy Switcher v1.0.5/DNS Easy Switcher.app/Contents/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>BuildMachineOSBuild</key>\n\t<string>23F79</string>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>en</string>\n\t<key>CFBundleDisplayName</key>\n\t<string>DNS Easy Switcher</string>\n\t<key>CFBundleExecutable</key>\n\t<string>DNS Easy Switcher</string>\n\t<key>CFBundleIconFile</key>\n\t<string>AppIcon</string>\n\t<key>CFBundleIconName</key>\n\t<string>AppIcon</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>com.linfordsoftware.dnseasyswitcher</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>DNS Easy Switcher</string>\n\t<key>CFBundlePackageType</key>\n\t<string>APPL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>1.0.5</string>\n\t<key>CFBundleSupportedPlatforms</key>\n\t<array>\n\t\t<string>MacOSX</string>\n\t</array>\n\t<key>CFBundleVersion</key>\n\t<string>5</string>\n\t<key>DTCompiler</key>\n\t<string>com.apple.compilers.llvm.clang.1_0</string>\n\t<key>DTPlatformBuild</key>\n\t<string></string>\n\t<key>DTPlatformName</key>\n\t<string>macosx</string>\n\t<key>DTPlatformVersion</key>\n\t<string>14.0</string>\n\t<key>DTSDKBuild</key>\n\t<string>23A334</string>\n\t<key>DTSDKName</key>\n\t<string>macosx14.0</string>\n\t<key>DTXcode</key>\n\t<string>1501</string>\n\t<key>DTXcodeBuild</key>\n\t<string>15A507</string>\n\t<key>LSApplicationCategoryType</key>\n\t<string>public.app-category.utilities</string>\n\t<key>LSMinimumSystemVersion</key>\n\t<string>14.0</string>\n</dict>\n</plist>\n"
  },
  {
    "path": "Releases/DNS Easy Switcher v1.0.5/DNS Easy Switcher.app/Contents/PkgInfo",
    "content": "APPL????"
  },
  {
    "path": "Releases/DNS Easy Switcher v1.0.5/DNS Easy Switcher.app/Contents/_CodeSignature/CodeResources",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>files</key>\n\t<dict>\n\t\t<key>Resources/AppIcon.icns</key>\n\t\t<data>\n\t\tF6YGlmox4KixBMRrSRhTusxdld8=\n\t\t</data>\n\t\t<key>Resources/Assets.car</key>\n\t\t<data>\n\t\tIhhuUihlv8TNfeE5CB9OZcOX21w=\n\t\t</data>\n\t</dict>\n\t<key>files2</key>\n\t<dict>\n\t\t<key>Resources/AppIcon.icns</key>\n\t\t<dict>\n\t\t\t<key>hash2</key>\n\t\t\t<data>\n\t\t\tI0wlcCvBzQjHkKQ1llwB0poCp2bmfglbZW45inQqQV0=\n\t\t\t</data>\n\t\t</dict>\n\t\t<key>Resources/Assets.car</key>\n\t\t<dict>\n\t\t\t<key>hash2</key>\n\t\t\t<data>\n\t\t\t/sNzrOXugwAIyPdIJZkIv1275OZELTMDgWfU3DNwkwQ=\n\t\t\t</data>\n\t\t</dict>\n\t</dict>\n\t<key>rules</key>\n\t<dict>\n\t\t<key>^Resources/</key>\n\t\t<true/>\n\t\t<key>^Resources/.*\\.lproj/</key>\n\t\t<dict>\n\t\t\t<key>optional</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>1000</real>\n\t\t</dict>\n\t\t<key>^Resources/.*\\.lproj/locversion.plist$</key>\n\t\t<dict>\n\t\t\t<key>omit</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>1100</real>\n\t\t</dict>\n\t\t<key>^Resources/Base\\.lproj/</key>\n\t\t<dict>\n\t\t\t<key>weight</key>\n\t\t\t<real>1010</real>\n\t\t</dict>\n\t\t<key>^version.plist$</key>\n\t\t<true/>\n\t</dict>\n\t<key>rules2</key>\n\t<dict>\n\t\t<key>.*\\.dSYM($|/)</key>\n\t\t<dict>\n\t\t\t<key>weight</key>\n\t\t\t<real>11</real>\n\t\t</dict>\n\t\t<key>^(.*/)?\\.DS_Store$</key>\n\t\t<dict>\n\t\t\t<key>omit</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>2000</real>\n\t\t</dict>\n\t\t<key>^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/</key>\n\t\t<dict>\n\t\t\t<key>nested</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>10</real>\n\t\t</dict>\n\t\t<key>^.*</key>\n\t\t<true/>\n\t\t<key>^Info\\.plist$</key>\n\t\t<dict>\n\t\t\t<key>omit</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>20</real>\n\t\t</dict>\n\t\t<key>^PkgInfo$</key>\n\t\t<dict>\n\t\t\t<key>omit</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>20</real>\n\t\t</dict>\n\t\t<key>^Resources/</key>\n\t\t<dict>\n\t\t\t<key>weight</key>\n\t\t\t<real>20</real>\n\t\t</dict>\n\t\t<key>^Resources/.*\\.lproj/</key>\n\t\t<dict>\n\t\t\t<key>optional</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>1000</real>\n\t\t</dict>\n\t\t<key>^Resources/.*\\.lproj/locversion.plist$</key>\n\t\t<dict>\n\t\t\t<key>omit</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>1100</real>\n\t\t</dict>\n\t\t<key>^Resources/Base\\.lproj/</key>\n\t\t<dict>\n\t\t\t<key>weight</key>\n\t\t\t<real>1010</real>\n\t\t</dict>\n\t\t<key>^[^/]+$</key>\n\t\t<dict>\n\t\t\t<key>nested</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>10</real>\n\t\t</dict>\n\t\t<key>^embedded\\.provisionprofile$</key>\n\t\t<dict>\n\t\t\t<key>weight</key>\n\t\t\t<real>20</real>\n\t\t</dict>\n\t\t<key>^version\\.plist$</key>\n\t\t<dict>\n\t\t\t<key>weight</key>\n\t\t\t<real>20</real>\n\t\t</dict>\n\t</dict>\n</dict>\n</plist>\n"
  },
  {
    "path": "Releases/DNS Easy Switcher v1.0.6/DNS Easy Switcher.app/Contents/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>BuildMachineOSBuild</key>\n\t<string>23F79</string>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>en</string>\n\t<key>CFBundleDisplayName</key>\n\t<string>DNS Easy Switcher</string>\n\t<key>CFBundleExecutable</key>\n\t<string>DNS Easy Switcher</string>\n\t<key>CFBundleIconFile</key>\n\t<string>AppIcon</string>\n\t<key>CFBundleIconName</key>\n\t<string>AppIcon</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>com.linfordsoftware.dnseasyswitcher</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>DNS Easy Switcher</string>\n\t<key>CFBundlePackageType</key>\n\t<string>APPL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>1.0.5</string>\n\t<key>CFBundleSupportedPlatforms</key>\n\t<array>\n\t\t<string>MacOSX</string>\n\t</array>\n\t<key>CFBundleVersion</key>\n\t<string>7</string>\n\t<key>DTCompiler</key>\n\t<string>com.apple.compilers.llvm.clang.1_0</string>\n\t<key>DTPlatformBuild</key>\n\t<string></string>\n\t<key>DTPlatformName</key>\n\t<string>macosx</string>\n\t<key>DTPlatformVersion</key>\n\t<string>14.0</string>\n\t<key>DTSDKBuild</key>\n\t<string>23A334</string>\n\t<key>DTSDKName</key>\n\t<string>macosx14.0</string>\n\t<key>DTXcode</key>\n\t<string>1501</string>\n\t<key>DTXcodeBuild</key>\n\t<string>15A507</string>\n\t<key>LSApplicationCategoryType</key>\n\t<string>public.app-category.utilities</string>\n\t<key>LSMinimumSystemVersion</key>\n\t<string>14.0</string>\n</dict>\n</plist>\n"
  },
  {
    "path": "Releases/DNS Easy Switcher v1.0.6/DNS Easy Switcher.app/Contents/PkgInfo",
    "content": "APPL????"
  },
  {
    "path": "Releases/DNS Easy Switcher v1.0.6/DNS Easy Switcher.app/Contents/_CodeSignature/CodeResources",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>files</key>\n\t<dict>\n\t\t<key>Resources/AppIcon.icns</key>\n\t\t<data>\n\t\tF6YGlmox4KixBMRrSRhTusxdld8=\n\t\t</data>\n\t\t<key>Resources/Assets.car</key>\n\t\t<data>\n\t\tIhhuUihlv8TNfeE5CB9OZcOX21w=\n\t\t</data>\n\t</dict>\n\t<key>files2</key>\n\t<dict>\n\t\t<key>Resources/AppIcon.icns</key>\n\t\t<dict>\n\t\t\t<key>hash2</key>\n\t\t\t<data>\n\t\t\tI0wlcCvBzQjHkKQ1llwB0poCp2bmfglbZW45inQqQV0=\n\t\t\t</data>\n\t\t</dict>\n\t\t<key>Resources/Assets.car</key>\n\t\t<dict>\n\t\t\t<key>hash2</key>\n\t\t\t<data>\n\t\t\t/sNzrOXugwAIyPdIJZkIv1275OZELTMDgWfU3DNwkwQ=\n\t\t\t</data>\n\t\t</dict>\n\t</dict>\n\t<key>rules</key>\n\t<dict>\n\t\t<key>^Resources/</key>\n\t\t<true/>\n\t\t<key>^Resources/.*\\.lproj/</key>\n\t\t<dict>\n\t\t\t<key>optional</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>1000</real>\n\t\t</dict>\n\t\t<key>^Resources/.*\\.lproj/locversion.plist$</key>\n\t\t<dict>\n\t\t\t<key>omit</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>1100</real>\n\t\t</dict>\n\t\t<key>^Resources/Base\\.lproj/</key>\n\t\t<dict>\n\t\t\t<key>weight</key>\n\t\t\t<real>1010</real>\n\t\t</dict>\n\t\t<key>^version.plist$</key>\n\t\t<true/>\n\t</dict>\n\t<key>rules2</key>\n\t<dict>\n\t\t<key>.*\\.dSYM($|/)</key>\n\t\t<dict>\n\t\t\t<key>weight</key>\n\t\t\t<real>11</real>\n\t\t</dict>\n\t\t<key>^(.*/)?\\.DS_Store$</key>\n\t\t<dict>\n\t\t\t<key>omit</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>2000</real>\n\t\t</dict>\n\t\t<key>^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/</key>\n\t\t<dict>\n\t\t\t<key>nested</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>10</real>\n\t\t</dict>\n\t\t<key>^.*</key>\n\t\t<true/>\n\t\t<key>^Info\\.plist$</key>\n\t\t<dict>\n\t\t\t<key>omit</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>20</real>\n\t\t</dict>\n\t\t<key>^PkgInfo$</key>\n\t\t<dict>\n\t\t\t<key>omit</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>20</real>\n\t\t</dict>\n\t\t<key>^Resources/</key>\n\t\t<dict>\n\t\t\t<key>weight</key>\n\t\t\t<real>20</real>\n\t\t</dict>\n\t\t<key>^Resources/.*\\.lproj/</key>\n\t\t<dict>\n\t\t\t<key>optional</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>1000</real>\n\t\t</dict>\n\t\t<key>^Resources/.*\\.lproj/locversion.plist$</key>\n\t\t<dict>\n\t\t\t<key>omit</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>1100</real>\n\t\t</dict>\n\t\t<key>^Resources/Base\\.lproj/</key>\n\t\t<dict>\n\t\t\t<key>weight</key>\n\t\t\t<real>1010</real>\n\t\t</dict>\n\t\t<key>^[^/]+$</key>\n\t\t<dict>\n\t\t\t<key>nested</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>10</real>\n\t\t</dict>\n\t\t<key>^embedded\\.provisionprofile$</key>\n\t\t<dict>\n\t\t\t<key>weight</key>\n\t\t\t<real>20</real>\n\t\t</dict>\n\t\t<key>^version\\.plist$</key>\n\t\t<dict>\n\t\t\t<key>weight</key>\n\t\t\t<real>20</real>\n\t\t</dict>\n\t</dict>\n</dict>\n</plist>\n"
  },
  {
    "path": "Releases/DNS Easy Switcher v1.0.7/DNS Easy Switcher.app/Contents/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>BuildMachineOSBuild</key>\n\t<string>24F74</string>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>en</string>\n\t<key>CFBundleDisplayName</key>\n\t<string>DNS Easy Switcher</string>\n\t<key>CFBundleExecutable</key>\n\t<string>DNS Easy Switcher</string>\n\t<key>CFBundleIconFile</key>\n\t<string>AppIcon</string>\n\t<key>CFBundleIconName</key>\n\t<string>AppIcon</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>com.linfordsoftware.dnseasyswitcher</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>DNS Easy Switcher</string>\n\t<key>CFBundlePackageType</key>\n\t<string>APPL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>1.0.7</string>\n\t<key>CFBundleSupportedPlatforms</key>\n\t<array>\n\t\t<string>MacOSX</string>\n\t</array>\n\t<key>CFBundleVersion</key>\n\t<string>1</string>\n\t<key>DTCompiler</key>\n\t<string>com.apple.compilers.llvm.clang.1_0</string>\n\t<key>DTPlatformBuild</key>\n\t<string>24F74</string>\n\t<key>DTPlatformName</key>\n\t<string>macosx</string>\n\t<key>DTPlatformVersion</key>\n\t<string>15.5</string>\n\t<key>DTSDKBuild</key>\n\t<string>24F74</string>\n\t<key>DTSDKName</key>\n\t<string>macosx15.5</string>\n\t<key>DTXcode</key>\n\t<string>1640</string>\n\t<key>DTXcodeBuild</key>\n\t<string>16F6</string>\n\t<key>LSApplicationCategoryType</key>\n\t<string>public.app-category.utilities</string>\n\t<key>LSMinimumSystemVersion</key>\n\t<string>14.0</string>\n</dict>\n</plist>\n"
  },
  {
    "path": "Releases/DNS Easy Switcher v1.0.7/DNS Easy Switcher.app/Contents/PkgInfo",
    "content": "APPL????"
  },
  {
    "path": "Releases/DNS Easy Switcher v1.0.7/DNS Easy Switcher.app/Contents/_CodeSignature/CodeResources",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>files</key>\n\t<dict>\n\t\t<key>Resources/AppIcon.icns</key>\n\t\t<data>\n\t\tF6YGlmox4KixBMRrSRhTusxdld8=\n\t\t</data>\n\t\t<key>Resources/Assets.car</key>\n\t\t<data>\n\t\t3jqFr5HGKA9n2WOV5/Xl44NZRrQ=\n\t\t</data>\n\t</dict>\n\t<key>files2</key>\n\t<dict>\n\t\t<key>Resources/AppIcon.icns</key>\n\t\t<dict>\n\t\t\t<key>hash2</key>\n\t\t\t<data>\n\t\t\tI0wlcCvBzQjHkKQ1llwB0poCp2bmfglbZW45inQqQV0=\n\t\t\t</data>\n\t\t</dict>\n\t\t<key>Resources/Assets.car</key>\n\t\t<dict>\n\t\t\t<key>hash2</key>\n\t\t\t<data>\n\t\t\tYYZb1v3omIkmYQEJ3ZIxWpYeBvtIZn01EGvVrO8Dau4=\n\t\t\t</data>\n\t\t</dict>\n\t</dict>\n\t<key>rules</key>\n\t<dict>\n\t\t<key>^Resources/</key>\n\t\t<true/>\n\t\t<key>^Resources/.*\\.lproj/</key>\n\t\t<dict>\n\t\t\t<key>optional</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>1000</real>\n\t\t</dict>\n\t\t<key>^Resources/.*\\.lproj/locversion.plist$</key>\n\t\t<dict>\n\t\t\t<key>omit</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>1100</real>\n\t\t</dict>\n\t\t<key>^Resources/Base\\.lproj/</key>\n\t\t<dict>\n\t\t\t<key>weight</key>\n\t\t\t<real>1010</real>\n\t\t</dict>\n\t\t<key>^version.plist$</key>\n\t\t<true/>\n\t</dict>\n\t<key>rules2</key>\n\t<dict>\n\t\t<key>.*\\.dSYM($|/)</key>\n\t\t<dict>\n\t\t\t<key>weight</key>\n\t\t\t<real>11</real>\n\t\t</dict>\n\t\t<key>^(.*/)?\\.DS_Store$</key>\n\t\t<dict>\n\t\t\t<key>omit</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>2000</real>\n\t\t</dict>\n\t\t<key>^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/</key>\n\t\t<dict>\n\t\t\t<key>nested</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>10</real>\n\t\t</dict>\n\t\t<key>^.*</key>\n\t\t<true/>\n\t\t<key>^Info\\.plist$</key>\n\t\t<dict>\n\t\t\t<key>omit</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>20</real>\n\t\t</dict>\n\t\t<key>^PkgInfo$</key>\n\t\t<dict>\n\t\t\t<key>omit</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>20</real>\n\t\t</dict>\n\t\t<key>^Resources/</key>\n\t\t<dict>\n\t\t\t<key>weight</key>\n\t\t\t<real>20</real>\n\t\t</dict>\n\t\t<key>^Resources/.*\\.lproj/</key>\n\t\t<dict>\n\t\t\t<key>optional</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>1000</real>\n\t\t</dict>\n\t\t<key>^Resources/.*\\.lproj/locversion.plist$</key>\n\t\t<dict>\n\t\t\t<key>omit</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>1100</real>\n\t\t</dict>\n\t\t<key>^Resources/Base\\.lproj/</key>\n\t\t<dict>\n\t\t\t<key>weight</key>\n\t\t\t<real>1010</real>\n\t\t</dict>\n\t\t<key>^[^/]+$</key>\n\t\t<dict>\n\t\t\t<key>nested</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>10</real>\n\t\t</dict>\n\t\t<key>^embedded\\.provisionprofile$</key>\n\t\t<dict>\n\t\t\t<key>weight</key>\n\t\t\t<real>20</real>\n\t\t</dict>\n\t\t<key>^version\\.plist$</key>\n\t\t<dict>\n\t\t\t<key>weight</key>\n\t\t\t<real>20</real>\n\t\t</dict>\n\t</dict>\n</dict>\n</plist>\n"
  }
]