Cleaned up host file configuration parsing
parent
6eee42cb35
commit
924fbb5e5d
|
@ -22,4 +22,24 @@ import java.net.Inet6Address
|
|||
/**
|
||||
* A container of hosts file entries
|
||||
*/
|
||||
data class HostsFileEntries(val ipv4Entries: Map<String, Inet4Address> = emptyMap(), val ipv6Entries: Map<String, Inet6Address> = emptyMap())
|
||||
data class HostsFileEntries(val ipv4Entries: Map<String, Inet4Address> = emptyMap(),
|
||||
val ipv6Entries: Map<String, Inet6Address> = emptyMap()) {
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
|
||||
other as HostsFileEntries
|
||||
|
||||
if (ipv4Entries != other.ipv4Entries) return false
|
||||
if (ipv6Entries != other.ipv6Entries) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = ipv4Entries.hashCode()
|
||||
result = 31 * result + ipv6Entries.hashCode()
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,8 @@ package dorkbox.netUtil.dnsUtils
|
|||
|
||||
import dorkbox.netUtil.Common.OS_WINDOWS
|
||||
import dorkbox.netUtil.Common.logger
|
||||
import dorkbox.netUtil.IP.toBytes
|
||||
import dorkbox.netUtil.IPv4
|
||||
import dorkbox.netUtil.IPv6
|
||||
import java.io.*
|
||||
import java.net.Inet4Address
|
||||
import java.net.Inet6Address
|
||||
|
@ -89,12 +90,14 @@ object HostsFileParser {
|
|||
* @return a [HostsFileEntries]
|
||||
*/
|
||||
fun parse(file: File, vararg charsets: Charset): HostsFileEntries {
|
||||
val hostsFileEntries = HostsFileEntries()
|
||||
|
||||
try {
|
||||
if (file.exists() && file.isFile) {
|
||||
for (charset in charsets) {
|
||||
BufferedReader(InputStreamReader(FileInputStream(file), charset)).use { reader ->
|
||||
val entries = parse(reader)
|
||||
if (entries != HostsFileEntries()) {
|
||||
if (entries != hostsFileEntries) {
|
||||
return entries
|
||||
}
|
||||
}
|
||||
|
@ -104,7 +107,7 @@ object HostsFileParser {
|
|||
logger.warn("Failed to load and parse hosts file at " + file.path, e)
|
||||
}
|
||||
|
||||
return HostsFileEntries()
|
||||
return hostsFileEntries
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -115,74 +118,70 @@ object HostsFileParser {
|
|||
* @return a [HostsFileEntries]
|
||||
*/
|
||||
fun parse(reader: Reader): HostsFileEntries {
|
||||
val buff = BufferedReader(reader)
|
||||
|
||||
return try {
|
||||
val ipv4Entries = mutableMapOf<String, Inet4Address>()
|
||||
val ipv6Entries = mutableMapOf<String, Inet6Address>()
|
||||
val ipv4Entries = mutableMapOf<String, Inet4Address>()
|
||||
val ipv6Entries = mutableMapOf<String, Inet6Address>()
|
||||
|
||||
var line: String
|
||||
while (buff.readLine().also { line = it } != null) {
|
||||
// remove comment
|
||||
reader.useLines { lines ->
|
||||
lines.map { line ->
|
||||
// remove comments
|
||||
val commentPosition = line.indexOf('#')
|
||||
if (commentPosition != -1) {
|
||||
line = line.substring(0, commentPosition)
|
||||
line.substring(0, commentPosition)
|
||||
} else {
|
||||
line
|
||||
}
|
||||
}.map { line ->
|
||||
// trim lines
|
||||
line.trim()
|
||||
}.filter { line ->
|
||||
// skip empty lines
|
||||
line = line.trim { it <= ' ' }
|
||||
if (line.isEmpty()) {
|
||||
continue
|
||||
}
|
||||
|
||||
line.isNotEmpty()
|
||||
}.map { line ->
|
||||
// split
|
||||
val lineParts: MutableList<String> = ArrayList()
|
||||
val lineParts = mutableListOf<String>()
|
||||
for (s in WHITESPACES.split(line)) {
|
||||
if (s.isNotEmpty()) {
|
||||
lineParts.add(s)
|
||||
}
|
||||
}
|
||||
|
||||
lineParts
|
||||
}.filter { lineParts ->
|
||||
// a valid line should be [IP, hostname, alias*]
|
||||
if (lineParts.size < 2) {
|
||||
// skip invalid line
|
||||
continue
|
||||
// skip invalid lines!
|
||||
lineParts.size >= 2
|
||||
}.forEach { lineParts ->
|
||||
val ip = lineParts[0]
|
||||
val ipBytes = when {
|
||||
IPv4.isValid(ip) -> IPv4.toBytes(ip)
|
||||
IPv6.isValid(ip) -> IPv6.toBytes(ip)
|
||||
else -> null
|
||||
}
|
||||
|
||||
val ipBytes = toBytes(lineParts[0])
|
||||
if (ipBytes.isEmpty()) {
|
||||
// skip invalid IP
|
||||
continue
|
||||
}
|
||||
|
||||
// loop over hostname and aliases
|
||||
for (i in 1 until lineParts.size) {
|
||||
val hostname = lineParts[i]
|
||||
val hostnameLower = hostname.toLowerCase(Locale.ENGLISH)
|
||||
val address = InetAddress.getByAddress(hostname, ipBytes)
|
||||
if (address is Inet4Address) {
|
||||
val previous = ipv4Entries.put(hostnameLower, address)
|
||||
if (previous != null) {
|
||||
// restore, we want to keep the first entry
|
||||
ipv4Entries[hostnameLower] = previous
|
||||
}
|
||||
} else {
|
||||
val previous = ipv6Entries.put(hostnameLower, address as Inet6Address)
|
||||
if (previous != null) {
|
||||
// restore, we want to keep the first entry
|
||||
ipv6Entries[hostnameLower] = previous
|
||||
if (ipBytes != null) {
|
||||
// loop over hostname and aliases, skip invalid IP
|
||||
for (i in 1 until lineParts.size) {
|
||||
val hostname = lineParts[i]
|
||||
val hostnameLower = hostname.toLowerCase(Locale.ENGLISH)
|
||||
val address = InetAddress.getByAddress(hostname, ipBytes)
|
||||
if (address is Inet4Address) {
|
||||
val previous = ipv4Entries.put(hostnameLower, address)
|
||||
if (previous != null) {
|
||||
// restore, we want to keep the first entry
|
||||
ipv4Entries[hostnameLower] = previous
|
||||
}
|
||||
} else {
|
||||
val previous = ipv6Entries.put(hostnameLower, address as Inet6Address)
|
||||
if (previous != null) {
|
||||
// restore, we want to keep the first entry
|
||||
ipv6Entries[hostnameLower] = previous
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HostsFileEntries(ipv4Entries, ipv6Entries)
|
||||
} finally {
|
||||
try {
|
||||
buff.close()
|
||||
} catch (e: IOException) {
|
||||
logger
|
||||
.warn("Failed to close a reader", e)
|
||||
}
|
||||
}
|
||||
|
||||
return HostsFileEntries(ipv4Entries, ipv6Entries)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,8 +5,7 @@ import com.sun.jna.Pointer
|
|||
import com.sun.jna.platform.win32.WinError
|
||||
import dorkbox.netUtil.Common
|
||||
import dorkbox.netUtil.Dns
|
||||
import dorkbox.netUtil.IPv4
|
||||
import dorkbox.netUtil.IPv6
|
||||
import dorkbox.netUtil.IP
|
||||
import dorkbox.netUtil.jna.windows.IPHlpAPI
|
||||
import dorkbox.netUtil.jna.windows.structs.IP_ADAPTER_ADDRESSES_LH
|
||||
import dorkbox.netUtil.jna.windows.structs.IP_ADAPTER_DNS_SERVER_ADDRESS_XP
|
||||
|
@ -189,7 +188,7 @@ object ResolveConf {
|
|||
var maybeIP = line.substring(i)
|
||||
|
||||
// There MIGHT be a port appended onto the IP address so we attempt to extract it.
|
||||
if (!IPv4.isValid(maybeIP) && !IPv6.isValid(maybeIP)) {
|
||||
if (!IP.isValid(maybeIP)) {
|
||||
i = maybeIP.lastIndexOf('.')
|
||||
require(i + 1 >= maybeIP.length) {
|
||||
"error parsing label ${NAMESERVER_ROW_LABEL} in file $path. invalid IP value: $line"
|
||||
|
|
Loading…
Reference in New Issue