fix(import): percent-decode share-link names preserving '+'; reject ambiguous bare IPv6
This commit is contained in:
parent
fbeb15be88
commit
9b5a3dee1d
1 changed files with 13 additions and 2 deletions
|
|
@ -55,6 +55,10 @@ private fun splitHostPort(hostPort: String): Pair<String, Int>? {
|
||||||
val port = hp.substringAfterLast(':').toIntOrNull() ?: return null
|
val port = hp.substringAfterLast(':').toIntOrNull() ?: return null
|
||||||
host to port
|
host to port
|
||||||
} else {
|
} else {
|
||||||
|
// A bare (unbracketed) IPv6 literal has multiple colons and can't carry a port
|
||||||
|
// unambiguously — RFC 3986/5952 require brackets for IPv6+port. Reject rather than
|
||||||
|
// mis-split "fe80::1:8388" into a wrong host/port.
|
||||||
|
if (hp.count { it == ':' } > 1) return null
|
||||||
val host = hp.substringBeforeLast(':')
|
val host = hp.substringBeforeLast(':')
|
||||||
val port = hp.substringAfterLast(':').toIntOrNull() ?: return null
|
val port = hp.substringAfterLast(':').toIntOrNull() ?: return null
|
||||||
host to port
|
host to port
|
||||||
|
|
@ -62,7 +66,12 @@ private fun splitHostPort(hostPort: String): Pair<String, Int>? {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun parseSs(s: String): ProxyConfig? {
|
private fun parseSs(s: String): ProxyConfig? {
|
||||||
val name = s.substringAfter('#', "").let { runCatching { URLDecoder.decode(it, "UTF-8") }.getOrDefault(it) }
|
// Percent-decode the #fragment name. URLDecoder does form-decoding, so it would turn a
|
||||||
|
// literal '+' into a space (mangling names like "C++ box"); escape '+' first so only real
|
||||||
|
// %XX escapes are decoded — matching java.net.URI.getFragment() used by parseUri.
|
||||||
|
val name = s.substringAfter('#', "").let {
|
||||||
|
runCatching { URLDecoder.decode(it.replace("+", "%2B"), "UTF-8") }.getOrDefault(it)
|
||||||
|
}
|
||||||
// SIP002 transport plugins (v2ray-plugin, obfs, …) aren't supported — a
|
// SIP002 transport plugins (v2ray-plugin, obfs, …) aren't supported — a
|
||||||
// config that needs one won't tunnel, so reject it rather than import a
|
// config that needs one won't tunnel, so reject it rather than import a
|
||||||
// silently-broken server.
|
// silently-broken server.
|
||||||
|
|
@ -114,7 +123,9 @@ private fun parseUri(s: String, type: ProxyType, defaultPort: Int): ProxyConfig?
|
||||||
val port = if (uri.port > 0) uri.port else defaultPort
|
val port = if (uri.port > 0) uri.port else defaultPort
|
||||||
val user = uri.userInfo?.substringBefore(':').orEmpty()
|
val user = uri.userInfo?.substringBefore(':').orEmpty()
|
||||||
val pass = uri.userInfo?.substringAfter(':', "").orEmpty()
|
val pass = uri.userInfo?.substringAfter(':', "").orEmpty()
|
||||||
val name = uri.fragment?.let { runCatching { URLDecoder.decode(it, "UTF-8") }.getOrDefault(it) }.orEmpty()
|
// URI.getFragment() is already percent-decoded; decoding again would turn '+'
|
||||||
|
// into a space and mangle names like "C++ box".
|
||||||
|
val name = uri.fragment.orEmpty()
|
||||||
return ProxyConfig(
|
return ProxyConfig(
|
||||||
name = name.ifBlank { host },
|
name = name.ifBlank { host },
|
||||||
type = type,
|
type = type,
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue