Merge pull request #1555 from yuhan6665/ss-fix

Fix ss2022 import for multi clients format
This commit is contained in:
2dust
2022-06-19 08:39:08 +08:00
committed by GitHub
4 changed files with 107 additions and 55 deletions

View File

@@ -6,6 +6,7 @@ import android.widget.Toast
import com.v2ray.ang.AngApplication import com.v2ray.ang.AngApplication
import me.drakeet.support.toast.ToastCompat import me.drakeet.support.toast.ToastCompat
import org.json.JSONObject import org.json.JSONObject
import java.net.URI
import java.net.URLConnection import java.net.URLConnection
/** /**
@@ -74,3 +75,6 @@ private fun Float.toShortString(): String {
val URLConnection.responseLength: Long val URLConnection.responseLength: Long
get() = if (Build.VERSION.SDK_INT >= 24) contentLengthLong else contentLength.toLong() get() = if (Build.VERSION.SDK_INT >= 24) contentLengthLong else contentLength.toLong()
val URI.idnHost: String
get() = (host!!).replace("[", "").replace("]", "")

View File

@@ -18,6 +18,7 @@ import com.v2ray.ang.dto.V2rayConfig.Companion.TLS
import com.v2ray.ang.util.MmkvManager.KEY_SELECTED_SERVER import com.v2ray.ang.util.MmkvManager.KEY_SELECTED_SERVER
import java.net.URI import java.net.URI
import java.util.* import java.util.*
import com.v2ray.ang.extension.idnHost
object AngConfigManager { object AngConfigManager {
private val mainStorage by lazy { MMKV.mmkvWithID(MmkvManager.ID_MAIN, MMKV.MULTI_PROCESS_MODE) } private val mainStorage by lazy { MMKV.mmkvWithID(MmkvManager.ID_MAIN, MMKV.MULTI_PROCESS_MODE) }
@@ -53,27 +54,31 @@ object AngConfigManager {
} }
private fun copyLegacySettings(sharedPreferences: SharedPreferences) { private fun copyLegacySettings(sharedPreferences: SharedPreferences) {
listOf(AppConfig.PREF_MODE, listOf(
AppConfig.PREF_REMOTE_DNS, AppConfig.PREF_MODE,
AppConfig.PREF_DOMESTIC_DNS, AppConfig.PREF_REMOTE_DNS,
// AppConfig.PREF_LOCAL_DNS_PORT, AppConfig.PREF_DOMESTIC_DNS,
// AppConfig.PREF_SOCKS_PORT, AppConfig.PREF_LOCAL_DNS_PORT,
// AppConfig.PREF_HTTP_PORT, // AppConfig.PREF_SOCKS_PORT,
// AppConfig.PREF_LOGLEVEL, // AppConfig.PREF_HTTP_PORT,
AppConfig.PREF_ROUTING_DOMAIN_STRATEGY, // AppConfig.PREF_LOGLEVEL,
AppConfig.PREF_ROUTING_MODE, AppConfig.PREF_ROUTING_DOMAIN_STRATEGY,
AppConfig.PREF_V2RAY_ROUTING_AGENT, AppConfig.PREF_ROUTING_MODE,
AppConfig.PREF_V2RAY_ROUTING_BLOCKED, AppConfig.PREF_V2RAY_ROUTING_AGENT,
AppConfig.PREF_V2RAY_ROUTING_DIRECT,).forEach { key -> AppConfig.PREF_V2RAY_ROUTING_BLOCKED,
AppConfig.PREF_V2RAY_ROUTING_DIRECT,
).forEach { key ->
settingsStorage?.encode(key, sharedPreferences.getString(key, null)) settingsStorage?.encode(key, sharedPreferences.getString(key, null))
} }
listOf(AppConfig.PREF_SPEED_ENABLED, listOf(
AppConfig.PREF_PROXY_SHARING, AppConfig.PREF_SPEED_ENABLED,
AppConfig.PREF_LOCAL_DNS_ENABLED, AppConfig.PREF_PROXY_SHARING,
// AppConfig.PREF_ALLOW_INSECURE, AppConfig.PREF_LOCAL_DNS_ENABLED,
// AppConfig.PREF_PREFER_IPV6, // AppConfig.PREF_ALLOW_INSECURE,
AppConfig.PREF_PER_APP_PROXY, // AppConfig.PREF_PREFER_IPV6,
AppConfig.PREF_BYPASS_APPS,).forEach { key -> AppConfig.PREF_PER_APP_PROXY,
AppConfig.PREF_BYPASS_APPS,
).forEach { key ->
settingsStorage?.encode(key, sharedPreferences.getBoolean(key, false)) settingsStorage?.encode(key, sharedPreferences.getBoolean(key, false))
} }
settingsStorage?.encode(AppConfig.PREF_SNIFFING_ENABLED, sharedPreferences.getBoolean(AppConfig.PREF_SNIFFING_ENABLED, true)) settingsStorage?.encode(AppConfig.PREF_SNIFFING_ENABLED, sharedPreferences.getBoolean(AppConfig.PREF_SNIFFING_ENABLED, true))
@@ -213,35 +218,37 @@ object AngConfigManager {
} }
} }
} else if (str.startsWith(EConfigType.SHADOWSOCKS.protocolScheme)) { } else if (str.startsWith(EConfigType.SHADOWSOCKS.protocolScheme)) {
var result = str.replace(EConfigType.SHADOWSOCKS.protocolScheme, "")
val indexSplit = result.indexOf("#")
config = ServerConfig.create(EConfigType.SHADOWSOCKS) config = ServerConfig.create(EConfigType.SHADOWSOCKS)
if (indexSplit > 0) { if (!tryResolveResolveSip002(str, config)) {
try { var result = str.replace(EConfigType.SHADOWSOCKS.protocolScheme, "")
config.remarks = Utils.urlDecode(result.substring(indexSplit + 1, result.length)) val indexSplit = result.indexOf("#")
} catch (e: Exception) { if (indexSplit > 0) {
e.printStackTrace() try {
config.remarks = Utils.urlDecode(result.substring(indexSplit + 1, result.length))
} catch (e: Exception) {
e.printStackTrace()
}
result = result.substring(0, indexSplit)
} }
result = result.substring(0, indexSplit) //part decode
} val indexS = result.indexOf("@")
result = if (indexS > 0) {
Utils.decode(result.substring(0, indexS)) + result.substring(indexS, result.length)
} else {
Utils.decode(result)
}
//part decode val legacyPattern = "^(.+?):(.*)@(.+?):(\\d+?)/?$".toRegex()
val indexS = result.indexOf("@") val match = legacyPattern.matchEntire(result) ?: return R.string.toast_incorrect_protocol
result = if (indexS > 0) {
Utils.decode(result.substring(0, indexS)) + result.substring(indexS, result.length)
} else {
Utils.decode(result)
}
val legacyPattern = "^(.+?):(.*)@(.+?):(\\d+?)/?$".toRegex() config.outboundBean?.settings?.servers?.get(0)?.let { server ->
val match = legacyPattern.matchEntire(result) ?: return R.string.toast_incorrect_protocol server.address = match.groupValues[3].removeSurrounding("[", "]")
server.port = match.groupValues[4].toInt()
config.outboundBean?.settings?.servers?.get(0)?.let { server -> server.password = match.groupValues[2]
server.address = match.groupValues[3].removeSurrounding("[", "]") server.method = match.groupValues[1].lowercase()
server.port = match.groupValues[4].toInt() }
server.password = match.groupValues[2]
server.method = match.groupValues[1].lowercase()
} }
} else if (str.startsWith(EConfigType.SOCKS.protocolScheme)) { } else if (str.startsWith(EConfigType.SOCKS.protocolScheme)) {
var result = str.replace(EConfigType.SOCKS.protocolScheme, "") var result = str.replace(EConfigType.SOCKS.protocolScheme, "")
@@ -279,9 +286,9 @@ object AngConfigManager {
} else if (str.startsWith(EConfigType.TROJAN.protocolScheme)) { } else if (str.startsWith(EConfigType.TROJAN.protocolScheme)) {
val uri = URI(str) val uri = URI(str)
config = ServerConfig.create(EConfigType.TROJAN) config = ServerConfig.create(EConfigType.TROJAN)
config.remarks = uri.fragment ?: "" config.remarks = Utils.urlDecode(uri.fragment ?: "")
config.outboundBean?.settings?.servers?.get(0)?.let { server -> config.outboundBean?.settings?.servers?.get(0)?.let { server ->
server.address = uri.host server.address = uri.idnHost
server.port = uri.port server.port = uri.port
server.password = uri.userInfo server.password = uri.userInfo
} }
@@ -298,9 +305,9 @@ object AngConfigManager {
.associate { it.split("=").let { (k, v) -> k to Utils.urlDecode(v) } } .associate { it.split("=").let { (k, v) -> k to Utils.urlDecode(v) } }
config = ServerConfig.create(EConfigType.VLESS) config = ServerConfig.create(EConfigType.VLESS)
val streamSetting = config.outboundBean?.streamSettings ?: return -1 val streamSetting = config.outboundBean?.streamSettings ?: return -1
config.remarks = uri.fragment ?: "" config.remarks = Utils.urlDecode(uri.fragment ?: "")
config.outboundBean?.settings?.vnext?.get(0)?.let { vnext -> config.outboundBean?.settings?.vnext?.get(0)?.let { vnext ->
vnext.address = uri.host vnext.address = uri.idnHost
vnext.port = uri.port vnext.port = uri.port
vnext.users[0].id = uri.userInfo vnext.users[0].id = uri.userInfo
vnext.users[0].encryption = queryParam["encryption"] ?: "none" vnext.users[0].encryption = queryParam["encryption"] ?: "none"
@@ -342,9 +349,9 @@ object AngConfigManager {
.associate { it.split("=").let { (k, v) -> k to Utils.urlDecode(v) } } .associate { it.split("=").let { (k, v) -> k to Utils.urlDecode(v) } }
val streamSetting = config.outboundBean?.streamSettings ?: return false val streamSetting = config.outboundBean?.streamSettings ?: return false
config.remarks = uri.fragment config.remarks = Utils.urlDecode(uri.fragment ?: "")
config.outboundBean.settings?.vnext?.get(0)?.let { vnext -> config.outboundBean.settings?.vnext?.get(0)?.let { vnext ->
vnext.address = uri.host vnext.address = uri.idnHost
vnext.port = uri.port vnext.port = uri.port
vnext.users[0].id = uuid vnext.users[0].id = uuid
vnext.users[0].encryption = DEFAULT_SECURITY vnext.users[0].encryption = DEFAULT_SECURITY
@@ -388,6 +395,38 @@ object AngConfigManager {
return true return true
} }
private fun tryResolveResolveSip002(str: String, config: ServerConfig): Boolean {
val uri = URI(str.replace(" ", "%20"))
config.remarks = Utils.urlDecode(uri.fragment ?: "")
val method: String
val password: String
if (uri.userInfo.contains(":")) {
val arrUserInfo = uri.userInfo.split(":").map { it.trim() }
if (arrUserInfo.count() != 2) {
return false
}
method = arrUserInfo[0]
password = Utils.urlDecode(arrUserInfo[1])
} else {
val base64Decode = Utils.decode(uri.userInfo)
val arrUserInfo = base64Decode.split(":").map { it.trim() }
if (arrUserInfo.count() != 2 && arrUserInfo.count() != 3) {
return false
}
method = arrUserInfo[0]
password = base64Decode.substringAfter(":")
}
config.outboundBean?.settings?.servers?.get(0)?.let { server ->
server.address = uri.idnHost
server.port = uri.port
server.password = password
server.method = method
}
return true
}
/** /**
* share config * share config
*/ */
@@ -501,7 +540,7 @@ object AngConfigManager {
val url = String.format("%s@%s:%s", val url = String.format("%s@%s:%s",
outbound.getPassword(), outbound.getPassword(),
outbound.getServerAddress(), Utils.getIpv6Address(outbound.getServerAddress()!!),
outbound.getServerPort()) outbound.getServerPort())
url + query + remark url + query + remark
} }
@@ -515,7 +554,7 @@ object AngConfigManager {
} }
val url = String.format("%s@%s:%s", val url = String.format("%s@%s:%s",
outbound.getPassword(), outbound.getPassword(),
outbound.getServerAddress(), Utils.getIpv6Address(outbound.getServerAddress()!!),
outbound.getServerPort()) outbound.getServerPort())
url + query + remark url + query + remark
} }

View File

@@ -477,5 +477,13 @@ object Utils {
it.bufferedReader().readText() it.bufferedReader().readText()
} }
} }
fun getIpv6Address(address: String): String {
return if (isIpv6Address(address)) {
String.format("[%s]", address)
} else {
address
}
}
} }

View File

@@ -8,14 +8,15 @@
<item>zero</item> <item>zero</item>
</string-array> </string-array>
<string-array name="ss_securitys" translatable="false"> <string-array name="ss_securitys" translatable="false">
<item>aes-256-cfb</item>
<item>aes-128-cfb</item>
<item>chacha20</item>
<item>chacha20-ietf</item>
<item>aes-256-gcm</item> <item>aes-256-gcm</item>
<item>aes-128-gcm</item> <item>aes-128-gcm</item>
<item>chacha20-poly1305</item> <item>chacha20-poly1305</item>
<item>chacha20-ietf-poly1305</item> <item>chacha20-ietf-poly1305</item>
<item>none</item>
<item>plain</item>
<item>2022-blake3-aes-128-gcm</item>
<item>2022-blake3-aes-256-gcm</item>
<item>2022-blake3-chacha20-poly1305</item>
</string-array> </string-array>
<string-array name="networks" translatable="false"> <string-array name="networks" translatable="false">