Compare commits
5 commits
9f30f9f686
...
634b4d26e8
| Author | SHA1 | Date | |
|---|---|---|---|
| 634b4d26e8 | |||
| 6b253a6843 | |||
| 3ec25bc247 | |||
| 9d016eea17 | |||
| 9d78a3aacf |
8 changed files with 147 additions and 95 deletions
|
|
@ -8,6 +8,9 @@
|
||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
069DCCFA2F8C0DCE00F1EB16 /* dns.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = dns.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
069DCCFA2F8C0DCE00F1EB16 /* dns.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = dns.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
A06A74772F8E95410093A9E4 /* .gitignore */ = {isa = PBXFileReference; lastKnownFileType = text; path = .gitignore; sourceTree = "<group>"; };
|
||||||
|
A06A74782F8E95410093A9E4 /* LICENCE */ = {isa = PBXFileReference; lastKnownFileType = text; path = LICENCE; sourceTree = "<group>"; };
|
||||||
|
A06A74792F8E95410093A9E4 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFileSystemSynchronizedRootGroup section */
|
/* Begin PBXFileSystemSynchronizedRootGroup section */
|
||||||
|
|
@ -32,6 +35,9 @@
|
||||||
069DCCF12F8C0DCD00F1EB16 = {
|
069DCCF12F8C0DCD00F1EB16 = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
A06A74772F8E95410093A9E4 /* .gitignore */,
|
||||||
|
A06A74782F8E95410093A9E4 /* LICENCE */,
|
||||||
|
A06A74792F8E95410093A9E4 /* README.md */,
|
||||||
069DCCFC2F8C0DCE00F1EB16 /* dns */,
|
069DCCFC2F8C0DCE00F1EB16 /* dns */,
|
||||||
069DCCFB2F8C0DCE00F1EB16 /* Products */,
|
069DCCFB2F8C0DCE00F1EB16 /* Products */,
|
||||||
);
|
);
|
||||||
|
|
@ -251,6 +257,7 @@
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||||
|
CODE_SIGN_ENTITLEMENTS = dns/dns.entitlements;
|
||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
|
|
@ -262,6 +269,7 @@
|
||||||
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
|
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
|
||||||
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
|
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
|
||||||
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
|
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 16.0;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
|
|
@ -285,6 +293,7 @@
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||||
|
CODE_SIGN_ENTITLEMENTS = dns/dns.entitlements;
|
||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
|
|
@ -296,6 +305,7 @@
|
||||||
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
|
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
|
||||||
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
|
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
|
||||||
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
|
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 16.0;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,10 @@ import Foundation
|
||||||
|
|
||||||
struct BlockedCount: View {
|
struct BlockedCount: View {
|
||||||
|
|
||||||
@State private var txtRecord: String = "..."
|
@EnvironmentObject
|
||||||
|
private var viewModel: ViewModel
|
||||||
|
|
||||||
|
@State private var txtRecord: String = "…"
|
||||||
|
|
||||||
private static let startIndex = 44
|
private static let startIndex = 44
|
||||||
|
|
||||||
|
|
@ -44,33 +47,29 @@ struct BlockedCount: View {
|
||||||
}
|
}
|
||||||
|
|
||||||
func fetchTXTRecord() {
|
func fetchTXTRecord() {
|
||||||
let dohURL = URL(string: "https://dns.sr2.uk/dns-query?dns=DoQBAAABAAAAAAAABXN0YXRzB2ludmFsaWQAABAAAQ")!
|
let dohURL = URL(string: "https://\(viewModel.blocklist.server)/dns-query?dns=DoQBAAABAAAAAAAABXN0YXRzB2ludmFsaWQAABAAAQ")!
|
||||||
|
|
||||||
let request = URLRequest(url: dohURL)
|
let request = URLRequest(url: dohURL)
|
||||||
|
|
||||||
URLSession.shared.dataTask(with: request) { data, response, error in
|
Task {
|
||||||
DispatchQueue.main.async {
|
do {
|
||||||
if error != nil {
|
let (data, _) = try await URLSession.shared.data(for: request)
|
||||||
txtRecord = "Error"
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
guard let data = data else {
|
if let count = parseResponse(data: data) {
|
||||||
txtRecord = "Error"
|
txtRecord = count
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
guard let count = parseResponse(data: data) else {
|
|
||||||
txtRecord = "Error"
|
txtRecord = "Error"
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
txtRecord = count
|
|
||||||
}
|
}
|
||||||
}.resume()
|
catch {
|
||||||
|
txtRecord = "Error"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#Preview {
|
#Preview {
|
||||||
BlockedCount()
|
BlockedCount()
|
||||||
|
.environmentObject(ViewModel())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
69
dns/BlocklistOption.swift
Normal file
69
dns/BlocklistOption.swift
Normal file
|
|
@ -0,0 +1,69 @@
|
||||||
|
//
|
||||||
|
// BlocklistOption.swift
|
||||||
|
// dns
|
||||||
|
//
|
||||||
|
// Created by Benjamin Erhart on 14.04.26.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
enum BlocklistOption: String, CaseIterable, Identifiable {
|
||||||
|
case secure = "Secure"
|
||||||
|
case securePlusAdblock = "Secure + Adblock"
|
||||||
|
|
||||||
|
var id: String { rawValue }
|
||||||
|
|
||||||
|
var enabled: Bool {
|
||||||
|
switch self {
|
||||||
|
case .secure:
|
||||||
|
return true
|
||||||
|
case .securePlusAdblock:
|
||||||
|
return true //false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var description: String {
|
||||||
|
switch self {
|
||||||
|
case .secure:
|
||||||
|
return "Malware and phishing protection"
|
||||||
|
case .securePlusAdblock:
|
||||||
|
return "Security plus ad and tracker blocking"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var icon: String {
|
||||||
|
switch self {
|
||||||
|
case .secure:
|
||||||
|
return "shield"
|
||||||
|
case .securePlusAdblock:
|
||||||
|
return "shield.righthalf.filled"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var server: String {
|
||||||
|
switch self {
|
||||||
|
case .secure:
|
||||||
|
return "dns.sr2.uk"
|
||||||
|
case .securePlusAdblock:
|
||||||
|
return "dnsplus.sr2.uk"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var ipv4: String {
|
||||||
|
switch self {
|
||||||
|
case .secure:
|
||||||
|
return "144.76.160.194"
|
||||||
|
case .securePlusAdblock:
|
||||||
|
return "192.0.2.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var ipv6: String {
|
||||||
|
switch self {
|
||||||
|
case .secure:
|
||||||
|
return "2a01:4f8:2210:23ea::4"
|
||||||
|
case .securePlusAdblock:
|
||||||
|
return "2001:db8::1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
16
dns/DnsApp.swift
Normal file
16
dns/DnsApp.swift
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
@main
|
||||||
|
struct DnsApp: App {
|
||||||
|
|
||||||
|
@StateObject
|
||||||
|
var viewModel = ViewModel()
|
||||||
|
|
||||||
|
var body: some Scene {
|
||||||
|
WindowGroup {
|
||||||
|
HomeView()
|
||||||
|
.environmentObject(viewModel)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,67 +1,6 @@
|
||||||
|
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
enum BlocklistOption: String, CaseIterable, Identifiable {
|
|
||||||
case secure = "Secure"
|
|
||||||
case securePlusAdblock = "Secure + Adblock"
|
|
||||||
|
|
||||||
var id: String { rawValue }
|
|
||||||
|
|
||||||
var enabled: Bool {
|
|
||||||
switch self {
|
|
||||||
case .secure:
|
|
||||||
return true
|
|
||||||
case .securePlusAdblock:
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var description: String {
|
|
||||||
switch self {
|
|
||||||
case .secure:
|
|
||||||
return "Malware and phishing protection"
|
|
||||||
case .securePlusAdblock:
|
|
||||||
return "Security plus ad and tracker blocking"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var icon: String {
|
|
||||||
switch self {
|
|
||||||
case .secure:
|
|
||||||
return "shield"
|
|
||||||
case .securePlusAdblock:
|
|
||||||
return "shield.righthalf.filled"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var server: String {
|
|
||||||
switch self {
|
|
||||||
case .secure:
|
|
||||||
return "dns.sr2.uk"
|
|
||||||
case .securePlusAdblock:
|
|
||||||
return "dnsplus.sr2.uk"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var ipv4: String {
|
|
||||||
switch self {
|
|
||||||
case .secure:
|
|
||||||
return "144.76.160.194"
|
|
||||||
case .securePlusAdblock:
|
|
||||||
return "192.0.2.1"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var ipv6: String {
|
|
||||||
switch self {
|
|
||||||
case .secure:
|
|
||||||
return "2a01:4f8:2210:23ea::4"
|
|
||||||
case .securePlusAdblock:
|
|
||||||
return "2001:db8::1"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
enum ServiceStatus {
|
enum ServiceStatus {
|
||||||
case pending
|
case pending
|
||||||
case operational
|
case operational
|
||||||
|
|
@ -96,8 +35,11 @@ enum ServiceStatus {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct HomeView: View {
|
struct HomeView: View {
|
||||||
|
|
||||||
|
@EnvironmentObject
|
||||||
|
private var viewModel: ViewModel
|
||||||
|
|
||||||
@State private var isEnabled = false
|
@State private var isEnabled = false
|
||||||
@State private var selectedBlocklist: BlocklistOption = .secure
|
|
||||||
@State private var serviceStatus: ServiceStatus = .operational
|
@State private var serviceStatus: ServiceStatus = .operational
|
||||||
|
|
||||||
private let falsePositiveURL = URL(string: "https://www.sr2.uk/contact")!
|
private let falsePositiveURL = URL(string: "https://www.sr2.uk/contact")!
|
||||||
|
|
@ -135,13 +77,13 @@ struct HomeView: View {
|
||||||
ForEach(BlocklistOption.allCases) { option in
|
ForEach(BlocklistOption.allCases) { option in
|
||||||
BlocklistRow(
|
BlocklistRow(
|
||||||
option: option,
|
option: option,
|
||||||
isSelected: selectedBlocklist == option
|
isSelected: viewModel.blocklist == option
|
||||||
)
|
)
|
||||||
.contentShape(Rectangle())
|
.contentShape(Rectangle())
|
||||||
.onTapGesture {
|
.onTapGesture {
|
||||||
guard option.enabled else { return }
|
guard option.enabled else { return }
|
||||||
withAnimation(.spring(duration: 0.3)) {
|
withAnimation(.spring(duration: 0.3)) {
|
||||||
selectedBlocklist = option
|
viewModel.blocklist = option
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.opacity(option.enabled ? 1 : 0.6)
|
.opacity(option.enabled ? 1 : 0.6)
|
||||||
|
|
@ -166,7 +108,7 @@ struct HomeView: View {
|
||||||
HStack {
|
HStack {
|
||||||
Label("Server", systemImage: "server.rack")
|
Label("Server", systemImage: "server.rack")
|
||||||
Spacer()
|
Spacer()
|
||||||
Text(selectedBlocklist.server)
|
Text(viewModel.blocklist.server)
|
||||||
.foregroundStyle(.secondary)
|
.foregroundStyle(.secondary)
|
||||||
.font(.system(.body, design: .monospaced))
|
.font(.system(.body, design: .monospaced))
|
||||||
}
|
}
|
||||||
|
|
@ -174,7 +116,7 @@ struct HomeView: View {
|
||||||
HStack {
|
HStack {
|
||||||
Label("IPv4", systemImage: "globe")
|
Label("IPv4", systemImage: "globe")
|
||||||
Spacer()
|
Spacer()
|
||||||
Text(selectedBlocklist.ipv4)
|
Text(viewModel.blocklist.ipv4)
|
||||||
.foregroundStyle(.secondary)
|
.foregroundStyle(.secondary)
|
||||||
.font(.system(.body, design: .monospaced))
|
.font(.system(.body, design: .monospaced))
|
||||||
}
|
}
|
||||||
|
|
@ -182,7 +124,7 @@ struct HomeView: View {
|
||||||
HStack {
|
HStack {
|
||||||
Label("IPv6", systemImage: "globe")
|
Label("IPv6", systemImage: "globe")
|
||||||
Spacer()
|
Spacer()
|
||||||
Text(selectedBlocklist.ipv6)
|
Text(viewModel.blocklist.ipv6)
|
||||||
.foregroundStyle(.secondary)
|
.foregroundStyle(.secondary)
|
||||||
.font(.system(.body, design: .monospaced))
|
.font(.system(.body, design: .monospaced))
|
||||||
}
|
}
|
||||||
|
|
@ -278,4 +220,5 @@ struct HomeView: View {
|
||||||
|
|
||||||
#Preview {
|
#Preview {
|
||||||
HomeView()
|
HomeView()
|
||||||
|
.environmentObject(ViewModel())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
16
dns/ViewModel.swift
Normal file
16
dns/ViewModel.swift
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
//
|
||||||
|
// ViewModel.swift
|
||||||
|
// dns
|
||||||
|
//
|
||||||
|
// Created by Benjamin Erhart on 14.04.26.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import Combine
|
||||||
|
|
||||||
|
class ViewModel: NSObject, ObservableObject {
|
||||||
|
|
||||||
|
@Published
|
||||||
|
var blocklist: BlocklistOption = .secure
|
||||||
|
|
||||||
|
}
|
||||||
10
dns/dns.entitlements
Normal file
10
dns/dns.entitlements
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>com.apple.developer.networking.networkextension</key>
|
||||||
|
<array>
|
||||||
|
<string>dns-settings</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
|
|
||||||
import SwiftUI
|
|
||||||
|
|
||||||
@main
|
|
||||||
struct dnsApp: App {
|
|
||||||
var body: some Scene {
|
|
||||||
WindowGroup {
|
|
||||||
HomeView()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue