Skip to content

Commit 8dc2b50

Browse files
authored
Merge pull request #32 from hawkff/feat/sanitize-dns-inputs
fix: sanitize DNS preference inputs
2 parents b4fc248 + 5e2876c commit 8dc2b50

2 files changed

Lines changed: 30 additions & 4 deletions

File tree

app/src/main/java/io/nekohasekai/sagernet/fmt/ConfigBuilder.kt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ import moe.matsuri.nb4a.utils.Util
4747
import moe.matsuri.nb4a.utils.listByLineOrComma
4848
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
4949

50+
private fun sanitizeDnsEntry(value: String): String {
51+
return value.filterNot { it.isISOControl() }.trim()
52+
}
53+
5054
const val TAG_MIXED = "mixed-in"
5155

5256
const val TAG_PROXY = "proxy"
@@ -144,9 +148,9 @@ fun buildConfig(
144148
val isVPN = DataStore.serviceMode == Key.MODE_VPN
145149
val bind = if (!forTest && DataStore.allowAccess) "0.0.0.0" else LOCALHOST
146150
val remoteDns = DataStore.remoteDns.split("\n")
147-
.mapNotNull { dns -> dns.trim().takeIf { it.isNotBlank() && !it.startsWith("#") } }
151+
.mapNotNull { dns -> sanitizeDnsEntry(dns).takeIf { it.isNotBlank() && !it.startsWith("#") } }
148152
val directDNS = DataStore.directDns.split("\n")
149-
.mapNotNull { dns -> dns.trim().takeIf { it.isNotBlank() && !it.startsWith("#") } }
153+
.mapNotNull { dns -> sanitizeDnsEntry(dns).takeIf { it.isNotBlank() && !it.startsWith("#") } }
150154
val enableDnsRouting = DataStore.enableDnsRouting
151155
val useFakeDns = DataStore.enableFakeDns && !forTest
152156
val needSniff = DataStore.trafficSniffing > 0

app/src/main/java/io/nekohasekai/sagernet/ui/SettingsPreferenceFragment.kt

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,24 @@ class SettingsPreferenceFragment : PreferenceFragmentCompat() {
4141
true
4242
}
4343

44+
private fun sanitizeDnsPreferenceValue(value: String): String {
45+
return value.lines().joinToString("\n") { line ->
46+
line.filterNot { it.isISOControl() }.trim()
47+
}
48+
}
49+
50+
private fun dnsReloadListener(preference: EditTextPreference, newValue: Any?): Boolean {
51+
val rawValue = newValue as? String ?: return reloadListener.onPreferenceChange(preference, newValue)
52+
val sanitizedValue = sanitizeDnsPreferenceValue(rawValue)
53+
if (sanitizedValue != rawValue) {
54+
preference.text = sanitizedValue
55+
needReload()
56+
return false
57+
}
58+
needReload()
59+
return true
60+
}
61+
4462
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
4563
preferenceManager.preferenceDataStore = DataStore.configurationStore
4664
DataStore.initGlobal()
@@ -203,8 +221,12 @@ class SettingsPreferenceFragment : PreferenceFragmentCompat() {
203221
concurrentDial.onPreferenceChangeListener = reloadListener
204222

205223
enableFakeDns.onPreferenceChangeListener = reloadListener
206-
remoteDns.onPreferenceChangeListener = reloadListener
207-
directDns.onPreferenceChangeListener = reloadListener
224+
remoteDns.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue ->
225+
dnsReloadListener(remoteDns, newValue)
226+
}
227+
directDns.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue ->
228+
dnsReloadListener(directDns, newValue)
229+
}
208230
enableDnsRouting.onPreferenceChangeListener = reloadListener
209231

210232
ipv6Mode.onPreferenceChangeListener = reloadListener

0 commit comments

Comments
 (0)