1package com.peachpasswords.shared23import okhttp3.HttpUrl.Companion.toHttpUrlOrNull4import java.util.Locale567891011121314151617fun extractDomain(url: String): String? {18 return try {19 val candidate = url.trim()20 if (candidate.isEmpty()) return null21 val normalized = if (22 candidate.startsWith("http://", ignoreCase = true) ||23 candidate.startsWith("https://", ignoreCase = true)24 ) {25 candidate26 } else {27 "https://$candidate"28 }29 val parsed = normalized.toHttpUrlOrNull() ?: return null30 val host = parsed.host.lowercase(Locale.ROOT)31 32 33 34 35 if (36 host.isEmpty() ||37 !host.contains('.') ||38 host == "localhost" ||39 host.endsWith(".localhost") ||40 host == "local" ||41 host.endsWith(".local") ||42 host.contains(':') ||43 host.matches(Regex("\\d+(?:\\.\\d+){3}"))44 ) return null45 parsed.topPrivateDomain()?.lowercase(Locale.ROOT)46 } catch (_: Exception) {47 null48 }49}5051fun getDisplayDomain(url: String): String {52 return try {53 val normalized = if (url.startsWith("http")) url else "https://$url"54 java.net.URL(normalized).host55 } catch (_: Exception) {56 url57 }58}59606162636465fun detectHomograph(url: String): Boolean {66 return try {67 val normalized = if (url.contains("://")) url else "https://$url"68 val host = java.net.URL(normalized).host69 host.any { it.code > 0x7F } || host.split('.').any { it.startsWith("xn--", ignoreCase = true) }70 } catch (_: Exception) {71 false72 }73}