diff options
author | Harsh Shandilya <me@msfjarvis.dev> | 2021-03-09 14:53:11 +0530 |
---|---|---|
committer | Harsh Shandilya <me@msfjarvis.dev> | 2021-03-18 11:40:30 +0530 |
commit | 774fda83ac276a635e3402034b1eedbd10be916f (patch) | |
tree | 57783a953fcd193d32f1e3dc8df26e07f03df328 /autofill-parser/src/main/java/mozilla | |
parent | be31ae37f443982b377d027cd613f04d0926568d (diff) |
all: reformat with ktfmt
Signed-off-by: Harsh Shandilya <me@msfjarvis.dev>
Diffstat (limited to 'autofill-parser/src/main/java/mozilla')
4 files changed, 259 insertions, 274 deletions
diff --git a/autofill-parser/src/main/java/mozilla/components/lib/publicsuffixlist/PublicSuffixList.kt b/autofill-parser/src/main/java/mozilla/components/lib/publicsuffixlist/PublicSuffixList.kt index f50d0d5a..c31df752 100644 --- a/autofill-parser/src/main/java/mozilla/components/lib/publicsuffixlist/PublicSuffixList.kt +++ b/autofill-parser/src/main/java/mozilla/components/lib/publicsuffixlist/PublicSuffixList.kt @@ -22,52 +22,48 @@ import kotlinx.coroutines.async /** * API for reading and accessing the public suffix list. * - * > A "public suffix" is one under which Internet users can (or historically could) directly register names. Some - * > examples of public suffixes are .com, .co.uk and pvt.k12.ma.us. The Public Suffix List is a list of all known - * > public suffixes. + * > A "public suffix" is one under which Internet users can (or historically could) directly + * register names. Some > examples of public suffixes are .com, .co.uk and pvt.k12.ma.us. The Public + * Suffix List is a list of all known > public suffixes. * - * Note that this implementation applies the rules of the public suffix list only and does not validate domains. + * Note that this implementation applies the rules of the public suffix list only and does not + * validate domains. * - * https://publicsuffix.org/ - * https://github.com/publicsuffix/list + * https://publicsuffix.org/ https://github.com/publicsuffix/list */ internal class PublicSuffixList( - context: Context, - dispatcher: CoroutineDispatcher = Dispatchers.IO, - private val scope: CoroutineScope = CoroutineScope(dispatcher) + context: Context, + dispatcher: CoroutineDispatcher = Dispatchers.IO, + private val scope: CoroutineScope = CoroutineScope(dispatcher) ) { - private val data: PublicSuffixListData by lazy(LazyThreadSafetyMode.PUBLICATION) { PublicSuffixListLoader.load(context) } + private val data: PublicSuffixListData by lazy(LazyThreadSafetyMode.PUBLICATION) { + PublicSuffixListLoader.load(context) + } - /** - * Prefetch the public suffix list from disk so that it is available in memory. - */ - fun prefetch(): Deferred<Unit> = scope.async { - data.run { Unit } - } + /** Prefetch the public suffix list from disk so that it is available in memory. */ + fun prefetch(): Deferred<Unit> = scope.async { data.run { Unit } } - /** - * Returns the public suffix and one more level; known as the registrable domain. Returns `null` if - * [domain] is a public suffix itself. - * - * E.g.: - * ``` - * wwww.mozilla.org -> mozilla.org - * www.bcc.co.uk -> bbc.co.uk - * a.b.ide.kyoto.jp -> b.ide.kyoto.jp - * ``` - * - * @param [domain] _must_ be a valid domain. [PublicSuffixList] performs no validation, and if any unexpected values - * are passed (e.g., a full URL, a domain with a trailing '/', etc) this may return an incorrect result. - */ - fun getPublicSuffixPlusOne(domain: String): Deferred<String?> = scope.async { - when (val offset = data.getPublicSuffixOffset(domain)) { - is PublicSuffixOffset.Offset -> domain - .split('.') - .drop(offset.value) - .joinToString(separator = ".") - else -> null - } + /** + * Returns the public suffix and one more level; known as the registrable domain. Returns `null` + * if [domain] is a public suffix itself. + * + * E.g.: + * ``` + * wwww.mozilla.org -> mozilla.org + * www.bcc.co.uk -> bbc.co.uk + * a.b.ide.kyoto.jp -> b.ide.kyoto.jp + * ``` + * + * @param [domain] _must_ be a valid domain. [PublicSuffixList] performs no validation, and if any + * unexpected values are passed (e.g., a full URL, a domain with a trailing '/', etc) this may + * return an incorrect result. + */ + fun getPublicSuffixPlusOne(domain: String): Deferred<String?> = + scope.async { + when (val offset = data.getPublicSuffixOffset(domain)) { + is PublicSuffixOffset.Offset -> domain.split('.').drop(offset.value).joinToString(separator = ".") + else -> null + } } - } diff --git a/autofill-parser/src/main/java/mozilla/components/lib/publicsuffixlist/PublicSuffixListData.kt b/autofill-parser/src/main/java/mozilla/components/lib/publicsuffixlist/PublicSuffixListData.kt index 47816ea0..eb59f3d3 100644 --- a/autofill-parser/src/main/java/mozilla/components/lib/publicsuffixlist/PublicSuffixListData.kt +++ b/autofill-parser/src/main/java/mozilla/components/lib/publicsuffixlist/PublicSuffixListData.kt @@ -15,154 +15,148 @@ package mozilla.components.lib.publicsuffixlist import java.net.IDN import mozilla.components.lib.publicsuffixlist.ext.binarySearch -/** - * Class wrapping the public suffix list data and offering methods for accessing rules in it. - */ -internal class PublicSuffixListData( - private val rules: ByteArray, - private val exceptions: ByteArray -) { - - private fun binarySearchRules(labels: List<ByteArray>, labelIndex: Int): String? { - return rules.binarySearch(labels, labelIndex) - } +/** Class wrapping the public suffix list data and offering methods for accessing rules in it. */ +internal class PublicSuffixListData(private val rules: ByteArray, private val exceptions: ByteArray) { - private fun binarySearchExceptions(labels: List<ByteArray>, labelIndex: Int): String? { - return exceptions.binarySearch(labels, labelIndex) - } + private fun binarySearchRules(labels: List<ByteArray>, labelIndex: Int): String? { + return rules.binarySearch(labels, labelIndex) + } - @Suppress("ReturnCount") - fun getPublicSuffixOffset(domain: String): PublicSuffixOffset? { - if (domain.isEmpty()) { - return null - } + private fun binarySearchExceptions(labels: List<ByteArray>, labelIndex: Int): String? { + return exceptions.binarySearch(labels, labelIndex) + } - val domainLabels = IDN.toUnicode(domain).split('.') - if (domainLabels.find { it.isEmpty() } != null) { - // At least one of the labels is empty: Bail out. - return null - } + @Suppress("ReturnCount") + fun getPublicSuffixOffset(domain: String): PublicSuffixOffset? { + if (domain.isEmpty()) { + return null + } - val rule = findMatchingRule(domainLabels) + val domainLabels = IDN.toUnicode(domain).split('.') + if (domainLabels.find { it.isEmpty() } != null) { + // At least one of the labels is empty: Bail out. + return null + } - if (domainLabels.size == rule.size && rule[0][0] != PublicSuffixListData.EXCEPTION_MARKER) { - // The domain is a public suffix. - return if (rule == PublicSuffixListData.PREVAILING_RULE) { - PublicSuffixOffset.PrevailingRule - } else { - PublicSuffixOffset.PublicSuffix - } - } + val rule = findMatchingRule(domainLabels) - return if (rule[0][0] == PublicSuffixListData.EXCEPTION_MARKER) { - // Exception rules hold the effective TLD plus one. - PublicSuffixOffset.Offset(domainLabels.size - rule.size) - } else { - // Otherwise the rule is for a public suffix, so we must take one more label. - PublicSuffixOffset.Offset(domainLabels.size - (rule.size + 1)) - } + if (domainLabels.size == rule.size && rule[0][0] != PublicSuffixListData.EXCEPTION_MARKER) { + // The domain is a public suffix. + return if (rule == PublicSuffixListData.PREVAILING_RULE) { + PublicSuffixOffset.PrevailingRule + } else { + PublicSuffixOffset.PublicSuffix + } } - /** - * Find a matching rule for the given domain labels. - * - * This algorithm is based on OkHttp's PublicSuffixDatabase class: - * https://github.com/square/okhttp/blob/master/okhttp/src/main/java/okhttp3/internal/publicsuffix/PublicSuffixDatabase.java - */ - private fun findMatchingRule(domainLabels: List<String>): List<String> { - // Break apart the domain into UTF-8 labels, i.e. foo.bar.com turns into [foo, bar, com]. - val domainLabelsBytes = domainLabels.map { it.toByteArray(Charsets.UTF_8) } - - val exactMatch = findExactMatch(domainLabelsBytes) - val wildcardMatch = findWildcardMatch(domainLabelsBytes) - val exceptionMatch = findExceptionMatch(domainLabelsBytes, wildcardMatch) - - if (exceptionMatch != null) { - return ("${PublicSuffixListData.EXCEPTION_MARKER}$exceptionMatch").split('.') - } + return if (rule[0][0] == PublicSuffixListData.EXCEPTION_MARKER) { + // Exception rules hold the effective TLD plus one. + PublicSuffixOffset.Offset(domainLabels.size - rule.size) + } else { + // Otherwise the rule is for a public suffix, so we must take one more label. + PublicSuffixOffset.Offset(domainLabels.size - (rule.size + 1)) + } + } + + /** + * Find a matching rule for the given domain labels. + * + * This algorithm is based on OkHttp's PublicSuffixDatabase class: + * https://github.com/square/okhttp/blob/master/okhttp/src/main/java/okhttp3/internal/publicsuffix/PublicSuffixDatabase.java + */ + private fun findMatchingRule(domainLabels: List<String>): List<String> { + // Break apart the domain into UTF-8 labels, i.e. foo.bar.com turns into [foo, bar, com]. + val domainLabelsBytes = domainLabels.map { it.toByteArray(Charsets.UTF_8) } + + val exactMatch = findExactMatch(domainLabelsBytes) + val wildcardMatch = findWildcardMatch(domainLabelsBytes) + val exceptionMatch = findExceptionMatch(domainLabelsBytes, wildcardMatch) + + if (exceptionMatch != null) { + return ("${PublicSuffixListData.EXCEPTION_MARKER}$exceptionMatch").split('.') + } - if (exactMatch == null && wildcardMatch == null) { - return PublicSuffixListData.PREVAILING_RULE - } + if (exactMatch == null && wildcardMatch == null) { + return PublicSuffixListData.PREVAILING_RULE + } - val exactRuleLabels = exactMatch?.split('.') ?: PublicSuffixListData.EMPTY_RULE - val wildcardRuleLabels = wildcardMatch?.split('.') ?: PublicSuffixListData.EMPTY_RULE + val exactRuleLabels = exactMatch?.split('.') ?: PublicSuffixListData.EMPTY_RULE + val wildcardRuleLabels = wildcardMatch?.split('.') ?: PublicSuffixListData.EMPTY_RULE - return if (exactRuleLabels.size > wildcardRuleLabels.size) { - exactRuleLabels - } else { - wildcardRuleLabels - } + return if (exactRuleLabels.size > wildcardRuleLabels.size) { + exactRuleLabels + } else { + wildcardRuleLabels } + } - /** - * Returns an exact match or null. - */ - private fun findExactMatch(labels: List<ByteArray>): String? { - // Start by looking for exact matches. We start at the leftmost label. For example, foo.bar.com - // will look like: [foo, bar, com], [bar, com], [com]. The longest matching rule wins. - - for (i in 0 until labels.size) { - val rule = binarySearchRules(labels, i) + /** Returns an exact match or null. */ + private fun findExactMatch(labels: List<ByteArray>): String? { + // Start by looking for exact matches. We start at the leftmost label. For example, + // foo.bar.com + // will look like: [foo, bar, com], [bar, com], [com]. The longest matching rule wins. - if (rule != null) { - return rule - } - } + for (i in 0 until labels.size) { + val rule = binarySearchRules(labels, i) - return null + if (rule != null) { + return rule + } } - /** - * Returns a wildcard match or null. - */ - private fun findWildcardMatch(labels: List<ByteArray>): String? { - // In theory, wildcard rules are not restricted to having the wildcard in the leftmost position. - // In practice, wildcards are always in the leftmost position. For now, this implementation - // cheats and does not attempt every possible permutation. Instead, it only considers wildcards - // in the leftmost position. We assert this fact when we generate the public suffix file. If - // this assertion ever fails we'll need to refactor this implementation. - if (labels.size > 1) { - val labelsWithWildcard = labels.toMutableList() - for (labelIndex in 0 until labelsWithWildcard.size) { - labelsWithWildcard[labelIndex] = PublicSuffixListData.WILDCARD_LABEL - val rule = binarySearchRules(labelsWithWildcard, labelIndex) - if (rule != null) { - return rule - } - } + return null + } + + /** Returns a wildcard match or null. */ + private fun findWildcardMatch(labels: List<ByteArray>): String? { + // In theory, wildcard rules are not restricted to having the wildcard in the leftmost + // position. + // In practice, wildcards are always in the leftmost position. For now, this implementation + // cheats and does not attempt every possible permutation. Instead, it only considers + // wildcards + // in the leftmost position. We assert this fact when we generate the public suffix file. If + // this assertion ever fails we'll need to refactor this implementation. + if (labels.size > 1) { + val labelsWithWildcard = labels.toMutableList() + for (labelIndex in 0 until labelsWithWildcard.size) { + labelsWithWildcard[labelIndex] = PublicSuffixListData.WILDCARD_LABEL + val rule = binarySearchRules(labelsWithWildcard, labelIndex) + if (rule != null) { + return rule } - - return null + } } - private fun findExceptionMatch(labels: List<ByteArray>, wildcardMatch: String?): String? { - // Exception rules only apply to wildcard rules, so only try it if we matched a wildcard. - if (wildcardMatch == null) { - return null - } + return null + } - for (labelIndex in 0 until labels.size) { - val rule = binarySearchExceptions(labels, labelIndex) - if (rule != null) { - return rule - } - } + private fun findExceptionMatch(labels: List<ByteArray>, wildcardMatch: String?): String? { + // Exception rules only apply to wildcard rules, so only try it if we matched a wildcard. + if (wildcardMatch == null) { + return null + } - return null + for (labelIndex in 0 until labels.size) { + val rule = binarySearchExceptions(labels, labelIndex) + if (rule != null) { + return rule + } } - companion object { + return null + } - val WILDCARD_LABEL = byteArrayOf('*'.toByte()) - val PREVAILING_RULE = listOf("*") - val EMPTY_RULE = listOf<String>() - const val EXCEPTION_MARKER = '!' - } + companion object { + + val WILDCARD_LABEL = byteArrayOf('*'.toByte()) + val PREVAILING_RULE = listOf("*") + val EMPTY_RULE = listOf<String>() + const val EXCEPTION_MARKER = '!' + } } internal sealed class PublicSuffixOffset { - data class Offset(val value: Int) : PublicSuffixOffset() - object PublicSuffix : PublicSuffixOffset() - object PrevailingRule : PublicSuffixOffset() + data class Offset(val value: Int) : PublicSuffixOffset() + object PublicSuffix : PublicSuffixOffset() + object PrevailingRule : PublicSuffixOffset() } diff --git a/autofill-parser/src/main/java/mozilla/components/lib/publicsuffixlist/PublicSuffixListLoader.kt b/autofill-parser/src/main/java/mozilla/components/lib/publicsuffixlist/PublicSuffixListLoader.kt index 785ee342..9fede799 100644 --- a/autofill-parser/src/main/java/mozilla/components/lib/publicsuffixlist/PublicSuffixListLoader.kt +++ b/autofill-parser/src/main/java/mozilla/components/lib/publicsuffixlist/PublicSuffixListLoader.kt @@ -20,38 +20,34 @@ private const val PUBLIC_SUFFIX_LIST_FILE = "publicsuffixes" internal object PublicSuffixListLoader { - fun load(context: Context): PublicSuffixListData = context.assets.open( - PUBLIC_SUFFIX_LIST_FILE - ).buffered().use { stream -> - val publicSuffixSize = stream.readInt() - val publicSuffixBytes = stream.readFully(publicSuffixSize) + fun load(context: Context): PublicSuffixListData = + context.assets.open(PUBLIC_SUFFIX_LIST_FILE).buffered().use { stream -> + val publicSuffixSize = stream.readInt() + val publicSuffixBytes = stream.readFully(publicSuffixSize) - val exceptionSize = stream.readInt() - val exceptionBytes = stream.readFully(exceptionSize) + val exceptionSize = stream.readInt() + val exceptionBytes = stream.readFully(exceptionSize) - PublicSuffixListData(publicSuffixBytes, exceptionBytes) + PublicSuffixListData(publicSuffixBytes, exceptionBytes) } } @Suppress("MagicNumber") private fun BufferedInputStream.readInt(): Int { - return (read() and 0xff shl 24 - or (read() and 0xff shl 16) - or (read() and 0xff shl 8) - or (read() and 0xff)) + return (read() and 0xff shl 24 or (read() and 0xff shl 16) or (read() and 0xff shl 8) or (read() and 0xff)) } private fun BufferedInputStream.readFully(size: Int): ByteArray { - val bytes = ByteArray(size) - - var offset = 0 - while (offset < size) { - val read = read(bytes, offset, size - offset) - if (read == -1) { - throw IOException("Unexpected end of stream") - } - offset += read + val bytes = ByteArray(size) + + var offset = 0 + while (offset < size) { + val read = read(bytes, offset, size - offset) + if (read == -1) { + throw IOException("Unexpected end of stream") } + offset += read + } - return bytes + return bytes } diff --git a/autofill-parser/src/main/java/mozilla/components/lib/publicsuffixlist/ext/ByteArray.kt b/autofill-parser/src/main/java/mozilla/components/lib/publicsuffixlist/ext/ByteArray.kt index 735cf21d..8a8f3e94 100644 --- a/autofill-parser/src/main/java/mozilla/components/lib/publicsuffixlist/ext/ByteArray.kt +++ b/autofill-parser/src/main/java/mozilla/components/lib/publicsuffixlist/ext/ByteArray.kt @@ -24,107 +24,106 @@ private const val BITMASK = 0xff.toByte() */ @Suppress("ComplexMethod", "NestedBlockDepth") internal fun ByteArray.binarySearch(labels: List<ByteArray>, labelIndex: Int): String? { - var low = 0 - var high = size - var match: String? = null - - while (low < high) { - val mid = (low + high) / 2 - val start = findStartOfLineFromIndex(mid) - val end = findEndOfLineFromIndex(start) - - val publicSuffixLength = start + end - start - - var compareResult: Int - var currentLabelIndex = labelIndex - var currentLabelByteIndex = 0 - var publicSuffixByteIndex = 0 - - var expectDot = false - while (true) { - val byte0 = if (expectDot) { - expectDot = false - '.'.toByte() - } else { - labels[currentLabelIndex][currentLabelByteIndex] and BITMASK - } - - val byte1 = this[start + publicSuffixByteIndex] and BITMASK - - // Compare the bytes. Note that the file stores UTF-8 encoded bytes, so we must compare the - // unsigned bytes. - @Suppress("EXPERIMENTAL_API_USAGE") - compareResult = (byte0.toUByte() - byte1.toUByte()).toInt() - if (compareResult != 0) { - break - } - - publicSuffixByteIndex++ - currentLabelByteIndex++ - - if (publicSuffixByteIndex == publicSuffixLength) { - break - } - - if (labels[currentLabelIndex].size == currentLabelByteIndex) { - // We've exhausted our current label. Either there are more labels to compare, in which - // case we expect a dot as the next character. Otherwise, we've checked all our labels. - if (currentLabelIndex == labels.size - 1) { - break - } else { - currentLabelIndex++ - currentLabelByteIndex = -1 - expectDot = true - } - } + var low = 0 + var high = size + var match: String? = null + + while (low < high) { + val mid = (low + high) / 2 + val start = findStartOfLineFromIndex(mid) + val end = findEndOfLineFromIndex(start) + + val publicSuffixLength = start + end - start + + var compareResult: Int + var currentLabelIndex = labelIndex + var currentLabelByteIndex = 0 + var publicSuffixByteIndex = 0 + + var expectDot = false + while (true) { + val byte0 = + if (expectDot) { + expectDot = false + '.'.toByte() + } else { + labels[currentLabelIndex][currentLabelByteIndex] and BITMASK } - if (compareResult < 0) { - high = start - 1 - } else if (compareResult > 0) { - low = start + end + 1 + val byte1 = this[start + publicSuffixByteIndex] and BITMASK + + // Compare the bytes. Note that the file stores UTF-8 encoded bytes, so we must compare + // the + // unsigned bytes. + @Suppress("EXPERIMENTAL_API_USAGE") compareResult = (byte0.toUByte() - byte1.toUByte()).toInt() + if (compareResult != 0) { + break + } + + publicSuffixByteIndex++ + currentLabelByteIndex++ + + if (publicSuffixByteIndex == publicSuffixLength) { + break + } + + if (labels[currentLabelIndex].size == currentLabelByteIndex) { + // We've exhausted our current label. Either there are more labels to compare, in + // which + // case we expect a dot as the next character. Otherwise, we've checked all our + // labels. + if (currentLabelIndex == labels.size - 1) { + break } else { - // We found a match, but are the lengths equal? - val publicSuffixBytesLeft = publicSuffixLength - publicSuffixByteIndex - var labelBytesLeft = labels[currentLabelIndex].size - currentLabelByteIndex - for (i in currentLabelIndex + 1 until labels.size) { - labelBytesLeft += labels[i].size - } - - if (labelBytesLeft < publicSuffixBytesLeft) { - high = start - 1 - } else if (labelBytesLeft > publicSuffixBytesLeft) { - low = start + end + 1 - } else { - // Found a match. - match = String(this, start, publicSuffixLength, Charsets.UTF_8) - break - } + currentLabelIndex++ + currentLabelByteIndex = -1 + expectDot = true } + } + } + + if (compareResult < 0) { + high = start - 1 + } else if (compareResult > 0) { + low = start + end + 1 + } else { + // We found a match, but are the lengths equal? + val publicSuffixBytesLeft = publicSuffixLength - publicSuffixByteIndex + var labelBytesLeft = labels[currentLabelIndex].size - currentLabelByteIndex + for (i in currentLabelIndex + 1 until labels.size) { + labelBytesLeft += labels[i].size + } + + if (labelBytesLeft < publicSuffixBytesLeft) { + high = start - 1 + } else if (labelBytesLeft > publicSuffixBytesLeft) { + low = start + end + 1 + } else { + // Found a match. + match = String(this, start, publicSuffixLength, Charsets.UTF_8) + break + } } + } - return match + return match } -/** - * Search for a '\n' that marks the start of a value. Don't go back past the start of the array. - */ +/** Search for a '\n' that marks the start of a value. Don't go back past the start of the array. */ private fun ByteArray.findStartOfLineFromIndex(start: Int): Int { - var index = start - while (index > -1 && this[index] != '\n'.toByte()) { - index-- - } - index++ - return index + var index = start + while (index > -1 && this[index] != '\n'.toByte()) { + index-- + } + index++ + return index } -/** - * Search for a '\n' that marks the end of a value. - */ +/** Search for a '\n' that marks the end of a value. */ private fun ByteArray.findEndOfLineFromIndex(start: Int): Int { - var end = 1 - while (this[start + end] != '\n'.toByte()) { - end++ - } - return end + var end = 1 + while (this[start + end] != '\n'.toByte()) { + end++ + } + return end } |