Implement DNS protocol in network settings
Hide HTTPS/TLS before iOS 14 and macOS 11. Fixes #91
This commit is contained in:
parent
7e4a0cdbfd
commit
7763e368b9
|
@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
### Added
|
||||
|
||||
- Support `--data-ciphers` from OpenVPN 2.5 [tunnelkit#193](https://github.com/passepartoutvpn/tunnelkit/issues/193)
|
||||
- Support DNS over HTTPS/TLS in "Network settings". [#91](https://github.com/passepartoutvpn/passepartout-apple/issues/91)
|
||||
|
||||
### Changed
|
||||
|
||||
|
|
|
@ -32,6 +32,8 @@ import Convenience
|
|||
private let log = SwiftyBeaver.self
|
||||
|
||||
private enum FieldTag: Int {
|
||||
case dnsCustom = 50
|
||||
|
||||
case dnsAddress = 100
|
||||
|
||||
case dnsDomain = 200
|
||||
|
@ -76,7 +78,14 @@ class NetworkSettingsViewController: UITableViewController {
|
|||
sections.append(.manualGateway)
|
||||
}
|
||||
if networkChoices.dns != .server {
|
||||
sections.append(.manualDNSServers)
|
||||
sections.append(.manualDNSProtocol)
|
||||
switch networkSettings.dnsProtocol {
|
||||
case .https, .tls:
|
||||
break
|
||||
|
||||
default:
|
||||
sections.append(.manualDNSServers)
|
||||
}
|
||||
sections.append(.manualDNSDomains)
|
||||
}
|
||||
if networkChoices.proxy != .server {
|
||||
|
@ -100,6 +109,16 @@ class NetworkSettingsViewController: UITableViewController {
|
|||
model.set([.gatewayIPv4, .gatewayIPv6], forSection: .manualGateway)
|
||||
model.set([.mtuBytes], forSection: .manualMTU)
|
||||
|
||||
var dnsProtocolRows: [RowType] = [.dnsProtocol]
|
||||
switch networkSettings.dnsProtocol {
|
||||
case .https, .tls:
|
||||
dnsProtocolRows.append(.dnsCustom)
|
||||
|
||||
default:
|
||||
break
|
||||
}
|
||||
model.set(dnsProtocolRows, forSection: .manualDNSProtocol)
|
||||
|
||||
var dnsServers: [RowType] = Array(repeating: .dnsAddress, count: networkSettings.dnsServers?.count ?? 0)
|
||||
if networkChoices.dns == .manual {
|
||||
dnsServers.append(.dnsAddAddress)
|
||||
|
@ -111,7 +130,7 @@ class NetworkSettingsViewController: UITableViewController {
|
|||
dnsDomains.append(.dnsAddDomain)
|
||||
}
|
||||
model.set(dnsDomains, forSection: .manualDNSDomains)
|
||||
|
||||
|
||||
var proxyRows: [RowType] = Array(repeating: .proxyBypass, count: networkSettings.proxyBypassDomains?.count ?? 0)
|
||||
proxyRows.insert(.proxyAddress, at: 0)
|
||||
proxyRows.insert(.proxyPort, at: 1)
|
||||
|
@ -122,11 +141,10 @@ class NetworkSettingsViewController: UITableViewController {
|
|||
model.set(proxyRows, forSection: .manualProxy)
|
||||
|
||||
// refine sections before add (DNS is tricky)
|
||||
model.setHeader(L10n.Core.NetworkSettings.Dns.title, forSection: .manualDNSProtocol)
|
||||
if !dnsServers.isEmpty {
|
||||
model.setHeader(L10n.Core.NetworkSettings.Dns.title, forSection: .manualDNSServers)
|
||||
} else if !dnsDomains.isEmpty {
|
||||
sections.removeAll { $0 == .manualDNSServers }
|
||||
model.setHeader(L10n.Core.NetworkSettings.Dns.title, forSection: .manualDNSDomains)
|
||||
} else {
|
||||
sections.removeAll { $0 == .manualDNSServers }
|
||||
sections.removeAll { $0 == .manualDNSDomains }
|
||||
|
@ -241,7 +259,21 @@ class NetworkSettingsViewController: UITableViewController {
|
|||
|
||||
let text = field.text ?? ""
|
||||
|
||||
if field.tag >= FieldTag.dnsAddress.rawValue && field.tag < FieldTag.dnsDomain.rawValue {
|
||||
if field.tag == FieldTag.dnsCustom.rawValue {
|
||||
switch networkSettings.dnsProtocol {
|
||||
case .https:
|
||||
guard let string = field.text, let url = URL(string: string) else {
|
||||
break
|
||||
}
|
||||
networkSettings.dnsHTTPSURL = url
|
||||
|
||||
case .tls:
|
||||
networkSettings.dnsTLSServerName = field.text
|
||||
|
||||
default:
|
||||
break
|
||||
}
|
||||
} else if field.tag >= FieldTag.dnsAddress.rawValue && field.tag < FieldTag.dnsDomain.rawValue {
|
||||
let i = field.tag - FieldTag.dnsAddress.rawValue
|
||||
if let _ = networkSettings.dnsServers {
|
||||
networkSettings.dnsServers?[i] = text
|
||||
|
@ -304,6 +336,8 @@ extension NetworkSettingsViewController {
|
|||
|
||||
case manualGateway
|
||||
|
||||
case manualDNSProtocol
|
||||
|
||||
case manualDNSServers
|
||||
|
||||
case manualDNSDomains
|
||||
|
@ -326,6 +360,10 @@ extension NetworkSettingsViewController {
|
|||
|
||||
case gatewayIPv6
|
||||
|
||||
case dnsProtocol
|
||||
|
||||
case dnsCustom
|
||||
|
||||
case dnsAddress
|
||||
|
||||
case dnsAddAddress
|
||||
|
@ -409,6 +447,34 @@ extension NetworkSettingsViewController {
|
|||
cell.isOn = networkSettings.gatewayPolicies?.contains(.IPv6) ?? false
|
||||
return cell
|
||||
|
||||
case .dnsProtocol:
|
||||
let cell = Cells.setting.dequeue(from: tableView, for: indexPath)
|
||||
cell.leftText = L10n.Core.Global.Captions.protocol
|
||||
cell.rightText = (networkSettings.dnsProtocol ?? .fallback)?.description
|
||||
return cell
|
||||
|
||||
case .dnsCustom:
|
||||
let cell = Cells.field.dequeue(from: tableView, for: indexPath)
|
||||
cell.caption = nil
|
||||
cell.field.tag = FieldTag.dnsCustom.rawValue
|
||||
switch networkSettings.dnsProtocol {
|
||||
case .https:
|
||||
cell.field.placeholder = AppConstants.Placeholders.dohURL
|
||||
cell.field.text = networkSettings.dnsHTTPSURL?.absoluteString
|
||||
|
||||
case .tls:
|
||||
cell.field.placeholder = AppConstants.Placeholders.dotServerName
|
||||
cell.field.text = networkSettings.dnsTLSServerName
|
||||
|
||||
default:
|
||||
break
|
||||
}
|
||||
cell.field.clearButtonMode = .always
|
||||
cell.field.keyboardType = .asciiCapable
|
||||
cell.captionWidth = 0.0
|
||||
cell.delegate = self
|
||||
return cell
|
||||
|
||||
case .dnsAddress:
|
||||
let i = indexPath.row - Offsets.dnsAddress
|
||||
|
||||
|
@ -579,6 +645,24 @@ extension NetworkSettingsViewController {
|
|||
}
|
||||
navigationController?.pushViewController(vc, animated: true)
|
||||
|
||||
case .dnsProtocol:
|
||||
let vc = SingleOptionViewController<DNSProtocol>()
|
||||
vc.applyTint(.current)
|
||||
vc.title = (cell as? SettingTableViewCell)?.leftText
|
||||
if #available(iOS 14, macOS 11, *) {
|
||||
vc.options = [.plain, .https, .tls]
|
||||
} else {
|
||||
vc.options = [.plain]
|
||||
}
|
||||
vc.descriptionBlock = { $0.description }
|
||||
|
||||
vc.selectedOption = networkSettings.dnsProtocol ?? .fallback
|
||||
vc.selectionBlock = { [weak self] in
|
||||
self?.networkSettings.dnsProtocol = $0
|
||||
self?.navigationController?.popViewController(animated: true)
|
||||
}
|
||||
navigationController?.pushViewController(vc, animated: true)
|
||||
|
||||
case .dnsAddAddress:
|
||||
tableView.deselectRow(at: indexPath, animated: true)
|
||||
|
||||
|
|
|
@ -136,14 +136,14 @@
|
|||
<objects>
|
||||
<viewController title="DNS" id="mbI-Io-BZh" userLabel="DNS" customClass="DNSViewController" customModule="Passepartout" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<view key="view" id="We2-9p-1Vt">
|
||||
<rect key="frame" x="0.0" y="0.0" width="520" height="400"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="514" height="440"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<customView translatesAutoresizingMaskIntoConstraints="NO" id="Zao-dc-fzq">
|
||||
<rect key="frame" x="0.0" y="20" width="500" height="360"/>
|
||||
<rect key="frame" x="0.0" y="20" width="494" height="400"/>
|
||||
<subviews>
|
||||
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="bFA-yD-Roy">
|
||||
<rect key="frame" x="147" y="336" width="247" height="25"/>
|
||||
<rect key="frame" x="147" y="376" width="247" height="25"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="240" id="euy-38-pqL"/>
|
||||
</constraints>
|
||||
|
@ -163,28 +163,74 @@
|
|||
</connections>
|
||||
</popUpButton>
|
||||
<customView translatesAutoresizingMaskIntoConstraints="NO" id="Zfd-mA-qV9">
|
||||
<rect key="frame" x="0.0" y="0.0" width="500" height="330"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="494" height="370"/>
|
||||
<subviews>
|
||||
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="CSz-iK-Imy">
|
||||
<rect key="frame" x="147" y="346" width="247" height="25"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="240" id="2y9-wd-q0g"/>
|
||||
</constraints>
|
||||
<popUpButtonCell key="cell" type="push" title="Item 1" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="210-ZR-L2J" id="KD6-ly-ONG">
|
||||
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="menu"/>
|
||||
<menu key="menu" id="Kvm-gz-uaS">
|
||||
<items>
|
||||
<menuItem title="Item 1" state="on" id="210-ZR-L2J"/>
|
||||
<menuItem title="Item 2" id="sVf-le-KwE"/>
|
||||
<menuItem title="Item 3" id="VbS-Rk-gsh"/>
|
||||
</items>
|
||||
</menu>
|
||||
</popUpButtonCell>
|
||||
<connections>
|
||||
<action selector="pickProtocol:" target="mbI-Io-BZh" id="ik0-nd-ODu"/>
|
||||
</connections>
|
||||
</popUpButton>
|
||||
<textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="oRM-XY-fH6">
|
||||
<rect key="frame" x="150" y="309" width="344" height="21"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" borderStyle="bezel" drawsBackground="YES" id="pa5-Wv-hRq">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<customView translatesAutoresizingMaskIntoConstraints="NO" id="L6f-kb-mEG">
|
||||
<rect key="frame" x="150" y="170" width="350" height="160"/>
|
||||
<rect key="frame" x="150" y="170" width="344" height="160"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="160" id="zCq-d8-x9i"/>
|
||||
</constraints>
|
||||
</customView>
|
||||
<customView translatesAutoresizingMaskIntoConstraints="NO" id="Baa-Z1-JJJ">
|
||||
<rect key="frame" x="150" y="0.0" width="350" height="160"/>
|
||||
<rect key="frame" x="150" y="0.0" width="344" height="160"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="160" id="BTk-TZ-Dat"/>
|
||||
</constraints>
|
||||
</customView>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="ef3-Zx-nCS">
|
||||
<rect key="frame" x="-2" y="352" width="144" height="16"/>
|
||||
<textFieldCell key="cell" lineBreakMode="clipping" alignment="right" title="PROTO" id="lpP-C3-tYW">
|
||||
<font key="font" usesAppearanceFont="YES"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstAttribute="bottom" secondItem="Baa-Z1-JJJ" secondAttribute="bottom" id="DZf-vr-lkr"/>
|
||||
<constraint firstItem="CSz-iK-Imy" firstAttribute="top" secondItem="Zfd-mA-qV9" secondAttribute="top" id="0rT-Xa-fsr"/>
|
||||
<constraint firstItem="CSz-iK-Imy" firstAttribute="leading" secondItem="Baa-Z1-JJJ" secondAttribute="leading" id="4NK-b5-pOE"/>
|
||||
<constraint firstItem="ef3-Zx-nCS" firstAttribute="leading" secondItem="Zfd-mA-qV9" secondAttribute="leading" id="9hc-Mm-7v7"/>
|
||||
<constraint firstAttribute="trailing" secondItem="Baa-Z1-JJJ" secondAttribute="trailing" id="Kc3-oq-1nC"/>
|
||||
<constraint firstItem="Baa-Z1-JJJ" firstAttribute="leading" secondItem="L6f-kb-mEG" secondAttribute="leading" id="OAq-vY-0dj"/>
|
||||
<constraint firstItem="ef3-Zx-nCS" firstAttribute="centerY" secondItem="CSz-iK-Imy" secondAttribute="centerY" id="PLm-Ng-tlW"/>
|
||||
<constraint firstItem="oRM-XY-fH6" firstAttribute="trailing" secondItem="L6f-kb-mEG" secondAttribute="trailing" id="U5i-6g-z66"/>
|
||||
<constraint firstAttribute="trailing" secondItem="L6f-kb-mEG" secondAttribute="trailing" id="Ufy-l9-JnV"/>
|
||||
<constraint firstItem="L6f-kb-mEG" firstAttribute="top" secondItem="Zfd-mA-qV9" secondAttribute="top" id="ht1-Z0-GZL"/>
|
||||
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="CSz-iK-Imy" secondAttribute="trailing" id="Z6g-uk-L7s"/>
|
||||
<constraint firstItem="L6f-kb-mEG" firstAttribute="top" secondItem="CSz-iK-Imy" secondAttribute="bottom" constant="20" id="Z8n-Jh-qIx"/>
|
||||
<constraint firstAttribute="bottom" secondItem="Baa-Z1-JJJ" secondAttribute="bottom" id="ciR-fE-0Bj"/>
|
||||
<constraint firstItem="Baa-Z1-JJJ" firstAttribute="top" secondItem="oRM-XY-fH6" secondAttribute="bottom" priority="250" constant="10" id="ljr-hl-Iip"/>
|
||||
<constraint firstItem="CSz-iK-Imy" firstAttribute="leading" secondItem="ef3-Zx-nCS" secondAttribute="trailing" constant="10" id="nOE-xl-CUa"/>
|
||||
<constraint firstItem="Baa-Z1-JJJ" firstAttribute="top" secondItem="L6f-kb-mEG" secondAttribute="bottom" constant="10" id="qwn-Pc-7xS"/>
|
||||
<constraint firstItem="oRM-XY-fH6" firstAttribute="leading" secondItem="L6f-kb-mEG" secondAttribute="leading" id="wE8-Cr-8A8"/>
|
||||
<constraint firstItem="oRM-XY-fH6" firstAttribute="top" secondItem="L6f-kb-mEG" secondAttribute="top" id="xUI-3F-09L"/>
|
||||
</constraints>
|
||||
</customView>
|
||||
</subviews>
|
||||
|
@ -209,9 +255,14 @@
|
|||
</constraints>
|
||||
</view>
|
||||
<connections>
|
||||
<outlet property="constraintAddressesBottom" destination="qwn-Pc-7xS" id="f8K-7g-9N2"/>
|
||||
<outlet property="constraintChoiceBottom" destination="0mN-72-zeu" id="Lf7-4v-Gae"/>
|
||||
<outlet property="constraintCustomBottom" destination="ljr-hl-Iip" id="JQK-dK-cqy"/>
|
||||
<outlet property="constraintSettingsTop" destination="ymz-zd-mjc" id="sN1-KM-hgC"/>
|
||||
<outlet property="labelDNSProtocol" destination="ef3-Zx-nCS" id="nec-BT-J2J"/>
|
||||
<outlet property="popupChoice" destination="bFA-yD-Roy" id="lYe-Ho-P0K"/>
|
||||
<outlet property="popupDNSProtocol" destination="CSz-iK-Imy" id="gIh-zq-W3E"/>
|
||||
<outlet property="textDNSCustom" destination="oRM-XY-fH6" id="rmb-Ue-MZR"/>
|
||||
<outlet property="viewDNSAddresses" destination="L6f-kb-mEG" id="cbb-T7-MeD"/>
|
||||
<outlet property="viewDNSDomains" destination="Baa-Z1-JJJ" id="msU-UP-bJZ"/>
|
||||
<outlet property="viewSettings" destination="Zfd-mA-qV9" id="831-9h-AXu"/>
|
||||
|
@ -219,7 +270,7 @@
|
|||
</viewController>
|
||||
<customObject id="Gxf-Bl-2bj" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="579" y="2339"/>
|
||||
<point key="canvasLocation" x="631" y="2362"/>
|
||||
</scene>
|
||||
<!--Service View Controller-->
|
||||
<scene sceneID="5Tf-QF-BT2">
|
||||
|
|
|
@ -5,11 +5,12 @@ All notable changes to this project will be documented in this file.
|
|||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## 1.14.0 (2021-01-08)
|
||||
## Unreleased
|
||||
|
||||
### Added
|
||||
|
||||
- Country flags in provider infrastructure menu.
|
||||
- Support DNS over HTTPS/TLS in "Network settings". [#91](https://github.com/passepartoutvpn/passepartout-apple/issues/91)
|
||||
|
||||
### Changed
|
||||
|
||||
|
|
|
@ -25,32 +25,35 @@
|
|||
|
||||
import Cocoa
|
||||
import PassepartoutCore
|
||||
import TunnelKit
|
||||
|
||||
class DNSViewController: NSViewController, ProfileCustomization {
|
||||
private struct Templates {
|
||||
static let server = "0.0.0.0"
|
||||
|
||||
static let domain = ""
|
||||
}
|
||||
|
||||
@IBOutlet private weak var popupChoice: NSPopUpButton!
|
||||
|
||||
@IBOutlet private weak var viewSettings: NSView!
|
||||
|
||||
@IBOutlet private weak var textDNSCustom: NSTextField!
|
||||
|
||||
@IBOutlet private weak var viewDNSAddresses: NSView!
|
||||
|
||||
@IBOutlet private weak var viewDNSDomains: NSView!
|
||||
|
||||
@IBOutlet private weak var labelDNSProtocol: NSTextField!
|
||||
|
||||
@IBOutlet private weak var popupDNSProtocol: NSPopUpButton!
|
||||
|
||||
@IBOutlet private var constraintChoiceBottom: NSLayoutConstraint!
|
||||
|
||||
@IBOutlet private var constraintSettingsTop: NSLayoutConstraint!
|
||||
|
||||
@IBOutlet private var constraintCustomBottom: NSLayoutConstraint!
|
||||
|
||||
@IBOutlet private var constraintAddressesBottom: NSLayoutConstraint!
|
||||
|
||||
private lazy var tableDNSDomains: TextTableView = .get()
|
||||
|
||||
private lazy var tableDNSAddresses: TextTableView = .get()
|
||||
|
||||
private lazy var choices = NetworkChoice.choices(for: profile)
|
||||
|
||||
private lazy var currentChoice = profile?.networkChoices?.dns ?? ProfileNetworkChoices.with(profile: profile).dns
|
||||
|
||||
private lazy var clientNetworkSettings = profile?.clientNetworkSettings
|
||||
|
@ -66,6 +69,8 @@ class DNSViewController: NSViewController, ProfileCustomization {
|
|||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
labelDNSProtocol.stringValue = L10n.Core.Global.Captions.protocol.asCaption
|
||||
|
||||
tableDNSAddresses.title = L10n.App.NetworkSettings.Dns.Cells.Addresses.title.asCaption
|
||||
viewDNSAddresses.addSubview(tableDNSAddresses)
|
||||
tableDNSAddresses.translatesAutoresizingMaskIntoConstraints = false
|
||||
|
@ -89,31 +94,80 @@ class DNSViewController: NSViewController, ProfileCustomization {
|
|||
loadSettings(from: currentChoice)
|
||||
|
||||
popupChoice.removeAllItems()
|
||||
for choice in choices {
|
||||
popupChoice.addItem(withTitle: choice.description)
|
||||
popupDNSProtocol.removeAllItems()
|
||||
let menuChoice = NSMenu()
|
||||
var indexOfChoice = 0
|
||||
for (i, choice) in NetworkChoice.choices(for: profile).enumerated() {
|
||||
let item = NSMenuItem(title: choice.description, action: nil, keyEquivalent: "")
|
||||
item.representedObject = choice
|
||||
menuChoice.addItem(item)
|
||||
if choice == currentChoice {
|
||||
popupChoice.selectItem(at: popupChoice.numberOfItems - 1)
|
||||
indexOfChoice = i
|
||||
}
|
||||
}
|
||||
tableDNSAddresses.rowTemplate = Templates.server
|
||||
tableDNSDomains.rowTemplate = Templates.domain
|
||||
popupChoice.menu = menuChoice
|
||||
tableDNSAddresses.rowTemplate = AppConstants.Placeholders.dnsAddress
|
||||
tableDNSDomains.rowTemplate = AppConstants.Placeholders.dnsDomain
|
||||
let menuProtocol = NSMenu()
|
||||
var availableProtocols: [DNSProtocol] = [.plain]
|
||||
if #available(iOS 14, macOS 11, *) {
|
||||
availableProtocols.append(.https)
|
||||
availableProtocols.append(.tls)
|
||||
}
|
||||
var indexOfDNSProtocol = 0
|
||||
for (i, proto) in availableProtocols.enumerated() {
|
||||
let item = NSMenuItem(title: proto.description, action: nil, keyEquivalent: "")
|
||||
item.representedObject = proto
|
||||
menuProtocol.addItem(item)
|
||||
if proto == networkSettings.dnsProtocol {
|
||||
indexOfDNSProtocol = i
|
||||
}
|
||||
}
|
||||
popupChoice.menu = menuChoice
|
||||
popupChoice.selectItem(at: indexOfChoice)
|
||||
popupDNSProtocol.menu = menuProtocol
|
||||
popupDNSProtocol.selectItem(at: indexOfDNSProtocol)
|
||||
}
|
||||
|
||||
// MARK: Actions
|
||||
|
||||
@IBAction private func pickChoice(_ sender: Any?) {
|
||||
let choice = choices[popupChoice.indexOfSelectedItem]
|
||||
guard let choice = popupChoice.selectedItem?.representedObject as? NetworkChoice else {
|
||||
return
|
||||
}
|
||||
loadSettings(from: choice)
|
||||
|
||||
delegate?.profileCustomization(self, didUpdateDNS: choice, withManualSettings: networkSettings)
|
||||
}
|
||||
|
||||
@IBAction private func pickProtocol(_ sender: Any?) {
|
||||
guard let choice = popupChoice.selectedItem?.representedObject as? NetworkChoice else {
|
||||
return
|
||||
}
|
||||
guard let proto = popupDNSProtocol.selectedItem?.representedObject as? DNSProtocol else {
|
||||
return
|
||||
}
|
||||
networkSettings.dnsProtocol = proto
|
||||
updateProtocolVisibility()
|
||||
|
||||
delegate?.profileCustomization(self, didUpdateDNS: choice, withManualSettings: networkSettings)
|
||||
}
|
||||
|
||||
func commitManualSettings() {
|
||||
guard currentChoice == .manual else {
|
||||
return
|
||||
}
|
||||
view.endEditing()
|
||||
networkSettings.dnsServers = tableDNSAddresses.rows
|
||||
switch networkSettings.dnsProtocol {
|
||||
case .https:
|
||||
networkSettings.dnsHTTPSURL = URL(string: textDNSCustom.stringValue)
|
||||
|
||||
case .tls:
|
||||
networkSettings.dnsTLSServerName = textDNSCustom.stringValue
|
||||
|
||||
default:
|
||||
networkSettings.dnsServers = tableDNSAddresses.rows
|
||||
}
|
||||
networkSettings.dnsSearchDomains = tableDNSDomains.rows
|
||||
|
||||
delegate?.profileCustomization(self, didUpdateDNS: .manual, withManualSettings: networkSettings)
|
||||
|
@ -145,5 +199,30 @@ class DNSViewController: NSViewController, ProfileCustomization {
|
|||
constraintChoiceBottom.priority = isServer ? .defaultHigh : .defaultLow
|
||||
constraintSettingsTop.priority = isServer ? .defaultLow : .defaultHigh
|
||||
viewSettings.isHidden = isServer
|
||||
|
||||
updateProtocolVisibility()
|
||||
}
|
||||
|
||||
private func updateProtocolVisibility() {
|
||||
let isCustom: Bool
|
||||
switch networkSettings.dnsProtocol {
|
||||
case .https:
|
||||
isCustom = true
|
||||
textDNSCustom.placeholderString = AppConstants.Placeholders.dohURL
|
||||
textDNSCustom.stringValue = networkSettings.dnsHTTPSURL?.absoluteString ?? ""
|
||||
|
||||
case .tls:
|
||||
isCustom = true
|
||||
textDNSCustom.placeholderString = AppConstants.Placeholders.dotServerName
|
||||
textDNSCustom.stringValue = networkSettings.dnsTLSServerName ?? ""
|
||||
|
||||
default:
|
||||
isCustom = false
|
||||
}
|
||||
|
||||
constraintCustomBottom.priority = isCustom ? .defaultHigh : .defaultLow
|
||||
constraintAddressesBottom.priority = isCustom ? .defaultLow : .defaultHigh
|
||||
textDNSCustom.isHidden = !isCustom
|
||||
viewDNSAddresses.isHidden = isCustom
|
||||
}
|
||||
}
|
||||
|
|
|
@ -201,8 +201,11 @@ extension ProfileCustomizationContainerViewController: ProfileCustomizationDeleg
|
|||
|
||||
func profileCustomization(_ profileCustomization: ProfileCustomization, didUpdateDNS choice: NetworkChoice, withManualSettings newSettings: ProfileNetworkSettings) {
|
||||
pendingChoices?.dns = choice
|
||||
pendingManualNetworkSettings.dnsSearchDomains = newSettings.dnsSearchDomains
|
||||
pendingManualNetworkSettings.dnsProtocol = newSettings.dnsProtocol
|
||||
pendingManualNetworkSettings.dnsHTTPSURL = newSettings.dnsHTTPSURL
|
||||
pendingManualNetworkSettings.dnsTLSServerName = newSettings.dnsTLSServerName
|
||||
pendingManualNetworkSettings.dnsServers = newSettings.dnsServers
|
||||
pendingManualNetworkSettings.dnsSearchDomains = newSettings.dnsSearchDomains
|
||||
}
|
||||
|
||||
func profileCustomization(_ profileCustomization: ProfileCustomization, didUpdateProxy choice: NetworkChoice, withManualSettings newSettings: ProfileNetworkSettings) {
|
||||
|
|
|
@ -79,7 +79,8 @@ class ProxyViewController: NSViewController, ProfileCustomization {
|
|||
tableProxyBypass.leftAnchor.constraint(equalTo: viewProxyBypass.leftAnchor),
|
||||
tableProxyBypass.rightAnchor.constraint(equalTo: viewProxyBypass.rightAnchor),
|
||||
])
|
||||
|
||||
tableProxyBypass.rowTemplate = Templates.bypass
|
||||
|
||||
loadSettings(from: currentChoice)
|
||||
|
||||
popupChoice.removeAllItems()
|
||||
|
@ -89,7 +90,6 @@ class ProxyViewController: NSViewController, ProfileCustomization {
|
|||
popupChoice.selectItem(at: popupChoice.numberOfItems - 1)
|
||||
}
|
||||
}
|
||||
tableProxyBypass.rowTemplate = Templates.bypass
|
||||
}
|
||||
|
||||
// MARK: Actions
|
||||
|
|
|
@ -268,6 +268,22 @@ public class AppConstants {
|
|||
public static let api = githubRaw(repo: "api")
|
||||
}
|
||||
|
||||
public struct Placeholders {
|
||||
public static let empty = ""
|
||||
|
||||
public static let address = "0.0.0.0"
|
||||
|
||||
public static let hostname = "example.com"
|
||||
|
||||
public static let dohURL = "https://example.com/dns-query"
|
||||
|
||||
public static let dotServerName = hostname
|
||||
|
||||
public static let dnsAddress = address
|
||||
|
||||
public static let dnsDomain = empty
|
||||
}
|
||||
|
||||
public struct Credits {
|
||||
public static let author = "Davide De Rosa"
|
||||
|
||||
|
|
|
@ -75,8 +75,14 @@ public class ProfileNetworkSettings: Codable, CustomStringConvertible {
|
|||
|
||||
public var gatewayPolicies: [OpenVPN.RoutingPolicy]?
|
||||
|
||||
public var dnsProtocol: DNSProtocol?
|
||||
|
||||
public var dnsServers: [String]?
|
||||
|
||||
public var dnsHTTPSURL: URL?
|
||||
|
||||
public var dnsTLSServerName: String?
|
||||
|
||||
public var dnsSearchDomains: [String]?
|
||||
|
||||
public var proxyAddress: String?
|
||||
|
@ -102,8 +108,11 @@ public class ProfileNetworkSettings: Codable, CustomStringConvertible {
|
|||
|
||||
public init(from configuration: OpenVPN.Configuration) {
|
||||
gatewayPolicies = configuration.routingPolicies
|
||||
dnsSearchDomains = configuration.searchDomains
|
||||
dnsProtocol = configuration.dnsProtocol
|
||||
dnsServers = configuration.dnsServers
|
||||
dnsHTTPSURL = configuration.dnsHTTPSURL
|
||||
dnsTLSServerName = configuration.dnsTLSServerName
|
||||
dnsSearchDomains = configuration.searchDomains
|
||||
proxyAddress = configuration.httpProxy?.address
|
||||
proxyPort = configuration.httpProxy?.port
|
||||
proxyAutoConfigurationURL = configuration.proxyAutoConfigurationURL
|
||||
|
@ -123,8 +132,11 @@ public class ProfileNetworkSettings: Codable, CustomStringConvertible {
|
|||
}
|
||||
|
||||
public func copyDNS(from settings: ProfileNetworkSettings) {
|
||||
dnsSearchDomains = settings.dnsSearchDomains
|
||||
dnsProtocol = settings.dnsProtocol
|
||||
dnsServers = settings.dnsServers?.filter { !$0.isEmpty }
|
||||
dnsHTTPSURL = settings.dnsHTTPSURL
|
||||
dnsTLSServerName = settings.dnsTLSServerName
|
||||
dnsSearchDomains = settings.dnsSearchDomains
|
||||
}
|
||||
|
||||
public func copyProxy(from settings: ProfileNetworkSettings) {
|
||||
|
@ -143,7 +155,7 @@ public class ProfileNetworkSettings: Codable, CustomStringConvertible {
|
|||
public var description: String {
|
||||
let comps: [String] = [
|
||||
"gw: \(gatewayPolicies?.description ?? "")",
|
||||
"dns: {domains: \(dnsSearchDomains?.description ?? "[]"), servers: \(dnsServers?.description ?? "[]")}",
|
||||
"dns: {protocol: \(dnsProtocol ?? .fallback), https: \(dnsHTTPSURL?.absoluteString ?? ""), tls: \(dnsTLSServerName?.description ?? ""), servers: \(dnsServers?.description ?? "[]"), domains: \(dnsSearchDomains?.description ?? "[]")}",
|
||||
"proxy: {address: \(proxyAddress ?? ""), port: \(proxyPort?.description ?? ""), PAC: \(proxyAutoConfigurationURL?.absoluteString ?? ""), bypass: \(proxyBypassDomains?.description ?? "[]")}",
|
||||
"mtu: {bytes: \(mtuBytes?.description ?? "default")}"
|
||||
]
|
||||
|
@ -171,11 +183,17 @@ extension OpenVPN.ConfigurationBuilder {
|
|||
break
|
||||
|
||||
case .server:
|
||||
dnsProtocol = nil
|
||||
dnsServers = nil
|
||||
dnsHTTPSURL = nil
|
||||
dnsTLSServerName = nil
|
||||
searchDomains = nil
|
||||
|
||||
case .manual:
|
||||
dnsProtocol = settings.dnsProtocol
|
||||
dnsServers = settings.dnsServers?.filter { !$0.isEmpty }
|
||||
dnsHTTPSURL = settings.dnsHTTPSURL
|
||||
dnsTLSServerName = settings.dnsTLSServerName
|
||||
searchDomains = settings.dnsSearchDomains
|
||||
}
|
||||
}
|
||||
|
|
2
Podfile
2
Podfile
|
@ -8,7 +8,7 @@ $tunnelkit_specs = ['Protocols/OpenVPN', 'Extra/LZO']
|
|||
|
||||
def shared_pods
|
||||
#pod_version $tunnelkit_name, $tunnelkit_specs, '~> 3.1.0'
|
||||
pod_git $tunnelkit_name, $tunnelkit_specs, 'e388842'
|
||||
pod_git $tunnelkit_name, $tunnelkit_specs, '5014e65'
|
||||
#pod_path $tunnelkit_name, $tunnelkit_specs, '..'
|
||||
pod 'SSZipArchive'
|
||||
pod 'Kvitto', :git => 'https://github.com/keeshux/Kvitto', :branch => 'enable-macos-spec'
|
||||
|
|
10
Podfile.lock
10
Podfile.lock
|
@ -52,8 +52,8 @@ DEPENDENCIES:
|
|||
- Kvitto (from `https://github.com/keeshux/Kvitto`, branch `enable-macos-spec`)
|
||||
- MBProgressHUD
|
||||
- SSZipArchive
|
||||
- TunnelKit/Extra/LZO (from `https://github.com/passepartoutvpn/tunnelkit`, commit `e388842`)
|
||||
- TunnelKit/Protocols/OpenVPN (from `https://github.com/passepartoutvpn/tunnelkit`, commit `e388842`)
|
||||
- TunnelKit/Extra/LZO (from `https://github.com/passepartoutvpn/tunnelkit`, commit `5014e65`)
|
||||
- TunnelKit/Protocols/OpenVPN (from `https://github.com/passepartoutvpn/tunnelkit`, commit `5014e65`)
|
||||
|
||||
SPEC REPOS:
|
||||
https://github.com/cocoapods/specs.git:
|
||||
|
@ -71,7 +71,7 @@ EXTERNAL SOURCES:
|
|||
:branch: enable-macos-spec
|
||||
:git: https://github.com/keeshux/Kvitto
|
||||
TunnelKit:
|
||||
:commit: e388842
|
||||
:commit: '5014e65'
|
||||
:git: https://github.com/passepartoutvpn/tunnelkit
|
||||
|
||||
CHECKOUT OPTIONS:
|
||||
|
@ -82,7 +82,7 @@ CHECKOUT OPTIONS:
|
|||
:commit: e263fcd1f40a6a482a0f1e424ba98009c4ad2b96
|
||||
:git: https://github.com/keeshux/Kvitto
|
||||
TunnelKit:
|
||||
:commit: e388842
|
||||
:commit: '5014e65'
|
||||
:git: https://github.com/passepartoutvpn/tunnelkit
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
|
@ -95,6 +95,6 @@ SPEC CHECKSUMS:
|
|||
SwiftyBeaver: 2e8acd6fc90c6d0a27055867a290794926d57c02
|
||||
TunnelKit: 2a6aadea2d772a2760b153aee27d1c334c9ca6db
|
||||
|
||||
PODFILE CHECKSUM: d6449ccbaad5d2ca50f6a27a651baaa17ef9db1a
|
||||
PODFILE CHECKSUM: 90f34e726cde9553212321b6f95cd79f284e0dca
|
||||
|
||||
COCOAPODS: 1.10.0
|
||||
|
|
Loading…
Reference in New Issue