diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/AngConfigManager.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/AngConfigManager.kt index 06d4f438..73dde7c0 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/AngConfigManager.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/AngConfigManager.kt @@ -2,7 +2,6 @@ package com.v2ray.ang.util import android.graphics.Bitmap import android.text.TextUtils -import android.util.Log import com.google.gson.Gson import com.v2ray.ang.AngApplication import com.v2ray.ang.AppConfig @@ -16,12 +15,9 @@ import com.v2ray.ang.AppConfig.VMESS_PROTOCOL import com.v2ray.ang.R import com.v2ray.ang.dto.AngConfig import com.v2ray.ang.dto.VmessQRCode -import com.v2ray.ang.extension.defaultDPreference -import org.jetbrains.anko.toast +import java.net.URI import java.net.URLDecoder import java.util.* -import java.net.* -import java.math.BigInteger object AngConfigManager { private lateinit var app: AngApplication @@ -256,7 +252,11 @@ object AngConfigManager { if (server.startsWith(VMESS_PROTOCOL)) { val indexSplit = server.indexOf("?") - if (indexSplit > 0) { + val newVmess = tryParseNewVmess(server) + if (newVmess != null) { + vmess = newVmess + vmess.subid = subid + } else if (indexSplit > 0) { vmess = ResolveVmess4Kitsunebi(server) } else { @@ -378,6 +378,60 @@ object AngConfigManager { return 0 } + fun tryParseNewVmess(uri: String): AngConfig.VmessBean? { + return runCatching { + val uri = URI(uri) + check(uri.scheme == "vmess") + val (_, protocol, tlsStr, uuid, alterId) = + Regex("(tcp|http|ws|kcp|quic)(\\+tls)?:([0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12})-([0-9]+)") + .matchEntire(uri.userInfo)?.groupValues + ?: error("parse user info fail.") + val tls = tlsStr.isNotBlank() + val queryParam = uri.rawQuery.split("&") + .map { it.split("=").let { (k, v) -> k to URLDecoder.decode(v, "utf-8")!! } } + .toMap() + val vmess = AngConfig.VmessBean() + vmess.address = uri.host + vmess.port = uri.port + vmess.guid = uuid + vmess.alterId = alterId.toInt() + vmess.streamSecurity = if (tls) "tls" else "" + vmess.remarks = uri.fragment + + // TODO: allowInsecure not supported + + when (protocol) { + "tcp" -> { + vmess.network = "tcp" + vmess.headerType = queryParam["type"] ?: "none" + vmess.requestHost = queryParam["host"] ?: "" + } + "http" -> { + vmess.network = "h2" + vmess.path = queryParam["path"]?.takeIf { it.trim() != "/" } ?: "" + vmess.requestHost = queryParam["host"]?.split("|")?.get(0) ?: "" + } + "ws" -> { + vmess.network = "ws" + vmess.path = queryParam["path"]?.takeIf { it.trim() != "/" } ?: "" + vmess.requestHost = queryParam["host"]?.split("|")?.get(0) ?: "" + } + "kcp" -> { + vmess.network = "kcp" + vmess.headerType = queryParam["type"] ?: "none" + vmess.path = queryParam["seed"] ?: "" + } + "quic" -> { + vmess.network = "quic" + vmess.security = queryParam["security"] ?: "none" + vmess.headerType = queryParam["type"] ?: "none" + vmess.path = queryParam["key"] ?: "" + } + } + vmess + }.getOrNull() + } + private fun ResolveVmess4Kitsunebi(server: String): AngConfig.VmessBean { val vmess = AngConfig.VmessBean()