DomainUtils.kt

1.7 KB · raw

1package com.peachpasswords.shared23import okhttp3.HttpUrl.Companion.toHttpUrlOrNull45/**6 * eTLD+1 ("bank.co.uk", not "co.uk"), the key everything from autofill matching to7 * vault health compares on.8 *9 * [okhttp3.HttpUrl.topPrivateDomain] is OkHttp's *public* API over the same public10 * suffix list its internal `PublicSuffixDatabase` exposes, so this keeps real PSL11 * accuracy without depending on an `okhttp3.internal` class. Accuracy is not12 * optional here: a "last two labels" heuristic would collapse `evil.co.uk` and13 * `bank.co.uk` to the same key and hand credentials to the wrong site.14 * Returns null for IP literals and bare public suffixes, as before.15 */16fun extractDomain(url: String): String? {17    return try {18        val normalized = if (url.startsWith("http")) url else "https://$url"19        normalized.toHttpUrlOrNull()?.topPrivateDomain()20    } catch (_: Exception) {21        null22    }23}2425fun getDisplayDomain(url: String): String {26    return try {27        val normalized = if (url.startsWith("http")) url else "https://$url"28        java.net.URL(normalized).host29    } catch (_: Exception) {30        url31    }32}3334/**35 * Browser parity with `shared/domain.ts::detectHomograph`: true when the host36 * contains non-ASCII characters or a punycode `xn--` label. This is warning-only;37 * matching/keying remains handled by [extractDomain].38 */39fun detectHomograph(url: String): Boolean {40    return try {41        val normalized = if (url.contains("://")) url else "https://$url"42        val host = java.net.URL(normalized).host43        host.any { it.code > 0x7F } || host.split('.').any { it.startsWith("xn--", ignoreCase = true) }44    } catch (_: Exception) {45        false46    }47}