|
|
|
|
@ -1,21 +1,22 @@
|
|
|
|
|
package com.utun.chat.data |
|
|
|
|
|
|
|
|
|
import java.net.URI |
|
|
|
|
import java.net.URL |
|
|
|
|
|
|
|
|
|
/** Границы UTF-16 и полный адрес; разбор не меняет текст и не открывает ссылки. */ |
|
|
|
|
data class MessageLink(val start: Int, val end: Int, val url: String) |
|
|
|
|
|
|
|
|
|
object MessageLinks { |
|
|
|
|
private val pattern = Regex("utun://[A-Za-z0-9+/]+={0,2}|(?i:https?://)[^\\s\\p{Z}\\p{Cc}<>\"'`«»“”‘’]+") |
|
|
|
|
private val invalidEscape = Regex("%(?![0-9A-Fa-f]{2})") |
|
|
|
|
|
|
|
|
|
/** Некорректные URL в пользовательском тексте остаются обычным текстом. */ |
|
|
|
|
fun isWebUrl(url: String): Boolean = try { |
|
|
|
|
val uri = URI(url) |
|
|
|
|
(uri.scheme.equals("http", true) || uri.scheme.equals("https", true)) && |
|
|
|
|
uri.toURL().let { it.host.isNotEmpty() && it.port in -1..65535 } |
|
|
|
|
} catch (_: IllegalArgumentException) { false } |
|
|
|
|
catch (_: java.net.URISyntaxException) { false } |
|
|
|
|
catch (_: java.net.MalformedURLException) { false } |
|
|
|
|
fun isWebUrl(url: String): Boolean { |
|
|
|
|
if (!pattern.matches(url) || invalidEscape.containsMatchIn(url)) return false |
|
|
|
|
return try { |
|
|
|
|
val parsed = URL(url) |
|
|
|
|
(parsed.protocol == "http" || parsed.protocol == "https") && parsed.host.isNotEmpty() && parsed.port in -1..65535 |
|
|
|
|
} catch (_: java.net.MalformedURLException) { false } |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fun parse(text: String): List<MessageLink> = pattern.findAll(text).mapNotNull { match -> |
|
|
|
|
var url = match.value |
|
|
|
|
|