From 924fbb5e5d4304e924a46d3485ae6b4b5ac92a5d Mon Sep 17 00:00:00 2001 From: Robinson Date: Thu, 8 Apr 2021 19:58:31 +0200 Subject: [PATCH] Cleaned up host file configuration parsing --- .../netUtil/dnsUtils/HostsFileEntries.kt | 22 +++- .../netUtil/dnsUtils/HostsFileParser.kt | 103 +++++++++--------- src/dorkbox/netUtil/dnsUtils/ResolveConf.kt | 5 +- 3 files changed, 74 insertions(+), 56 deletions(-) diff --git a/src/dorkbox/netUtil/dnsUtils/HostsFileEntries.kt b/src/dorkbox/netUtil/dnsUtils/HostsFileEntries.kt index c3b1307..40f2ee9 100644 --- a/src/dorkbox/netUtil/dnsUtils/HostsFileEntries.kt +++ b/src/dorkbox/netUtil/dnsUtils/HostsFileEntries.kt @@ -22,4 +22,24 @@ import java.net.Inet6Address /** * A container of hosts file entries */ -data class HostsFileEntries(val ipv4Entries: Map = emptyMap(), val ipv6Entries: Map = emptyMap()) +data class HostsFileEntries(val ipv4Entries: Map = emptyMap(), + val ipv6Entries: Map = 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 + } +} diff --git a/src/dorkbox/netUtil/dnsUtils/HostsFileParser.kt b/src/dorkbox/netUtil/dnsUtils/HostsFileParser.kt index d102486..6399c84 100644 --- a/src/dorkbox/netUtil/dnsUtils/HostsFileParser.kt +++ b/src/dorkbox/netUtil/dnsUtils/HostsFileParser.kt @@ -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() - val ipv6Entries = mutableMapOf() + val ipv4Entries = mutableMapOf() + val ipv6Entries = mutableMapOf() - 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 = ArrayList() + val lineParts = mutableListOf() 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) } } diff --git a/src/dorkbox/netUtil/dnsUtils/ResolveConf.kt b/src/dorkbox/netUtil/dnsUtils/ResolveConf.kt index a4c1dea..5d97cfa 100644 --- a/src/dorkbox/netUtil/dnsUtils/ResolveConf.kt +++ b/src/dorkbox/netUtil/dnsUtils/ResolveConf.kt @@ -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"