Files

70 lines
2.7 KiB
Swift
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import Darwin
import Foundation
import Localization
/// 常用公共 DNS。只用 IPv4 地址:没有 IPv6 的网络里写入 IPv6 服务器会拖慢解析
public enum DNSPreset: String, CaseIterable, Identifiable, Sendable {
case automatic, cloudflare, google, tencent, aliyun
public var id: String { rawValue }
public var title: String {
switch self {
case .automatic: tr("自动")
case .cloudflare: "Cloudflare"
case .google: "Google"
case .tencent: tr("腾讯 DNSPod")
case .aliyun: tr("阿里云")
}
}
public var servers: [String] {
switch self {
case .automatic: []
case .cloudflare: ["1.1.1.1", "1.0.0.1"]
case .google: ["8.8.8.8", "8.8.4.4"]
case .tencent: ["119.29.29.29", "182.254.116.116"]
case .aliyun: ["223.5.5.5", "223.6.6.6"]
}
}
/// 当前手动设置的地址与哪个预设一致;无手动地址即“自动”
public static func matching(_ servers: [String]) -> DNSPreset? {
allCases.first { $0.servers == servers }
}
}
public enum DNSConfiguration {
public static let maxServers = 6
/// 只接受数字形式的 IPv4 / IPv6 地址
public static func isValidAddress(_ text: String) -> Bool {
var v4 = in_addr()
var v6 = in6_addr()
return inet_pton(AF_INET, text, &v4) == 1 || inet_pton(AF_INET6, text, &v6) == 1
}
/// 把用户输入(逗号、空格或换行分隔)拆成地址列表;有无效地址时返回 nil
public static func parse(_ input: String) -> [String]? {
let parts = input.split { $0 == "," || $0 == "," || $0.isWhitespace }.map(String.init)
guard parts.count <= maxServers, parts.allSatisfy(isValidAddress) else { return nil }
return parts
}
/// 服务名来自系统,可能包含空格或引号;只拒绝控制字符
public static func isValidServiceName(_ name: String) -> Bool {
!name.isEmpty && name.count <= 128 && !name.unicodeScalars.contains { CharacterSet.controlCharacters.contains($0) }
}
public static func networksetupArguments(service: String, servers: [String]) -> [String] {
["-setdnsservers", service] + (servers.isEmpty ? ["Empty"] : servers)
}
/// 未安装辅助工具时通过管理员授权执行的 shell 命令。服务名按单引号转义,地址已校验为纯数字形式
public static func shellCommand(service: String, servers: [String]) -> String {
let quoted = "'" + service.replacingOccurrences(of: "'", with: "'\\''") + "'"
let arguments = ["-setdnsservers", quoted] + (servers.isEmpty ? ["Empty"] : servers)
return (["/usr/sbin/networksetup"] + arguments).joined(separator: " ")
}
}