Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5daef71147 | ||
|
|
5ffc5ec502 | ||
|
|
35063db3e6 | ||
|
|
868c24bb8b |
@@ -11,8 +11,8 @@ android {
|
||||
applicationId = "com.v2ray.ang"
|
||||
minSdk = 21
|
||||
targetSdk = 34
|
||||
versionCode = 601
|
||||
versionName = "1.9.7"
|
||||
versionCode = 602
|
||||
versionName = "1.9.8"
|
||||
multiDexEnabled = true
|
||||
splits {
|
||||
abi {
|
||||
|
||||
@@ -1,12 +1,4 @@
|
||||
[
|
||||
{
|
||||
"remarks": "Google cn",
|
||||
"outboundTag": "proxy",
|
||||
"domain": [
|
||||
"domain:googleapis.cn",
|
||||
"domain:gstatic.com"
|
||||
]
|
||||
},
|
||||
{
|
||||
"remarks": "阻断udp443",
|
||||
"outboundTag": "block",
|
||||
@@ -34,44 +26,27 @@
|
||||
"geosite:private"
|
||||
]
|
||||
},
|
||||
{
|
||||
"remarks": "绕过中国IP",
|
||||
"outboundTag": "direct",
|
||||
"ip": [
|
||||
"geoip:cn"
|
||||
]
|
||||
},
|
||||
{
|
||||
"remarks": "绕过中国域名",
|
||||
"outboundTag": "direct",
|
||||
"domain": [
|
||||
"domain:dns.alidns.com",
|
||||
"domain:dns.pub",
|
||||
"domain:doh.pub",
|
||||
"domain:dot.pub",
|
||||
"domain:doh.360.cn",
|
||||
"domain:dot.360.cn",
|
||||
"geosite:cn",
|
||||
"geosite:geolocation-cn"
|
||||
]
|
||||
},
|
||||
{
|
||||
"remarks": "绕过中国IP",
|
||||
"outboundTag": "direct",
|
||||
"ip": [
|
||||
"223.5.5.5/32",
|
||||
"223.6.6.6/32",
|
||||
"2400:3200::1/128",
|
||||
"2400:3200:baba::1/128",
|
||||
"119.29.29.29/32",
|
||||
"1.12.12.12/32",
|
||||
"120.53.53.53/32",
|
||||
"2402:4e00::/128",
|
||||
"2402:4e00:1::/128",
|
||||
"180.76.76.76/32",
|
||||
"2400:da00::6666/128",
|
||||
"114.114.114.114/32",
|
||||
"114.114.115.115/32",
|
||||
"180.184.1.1/32",
|
||||
"180.184.2.2/32",
|
||||
"101.226.4.6/32",
|
||||
"218.30.118.6/32",
|
||||
"123.125.81.6/32",
|
||||
"140.207.198.6/32",
|
||||
"geoip:cn"
|
||||
"remarks": "Google CN",
|
||||
"outboundTag": "proxy",
|
||||
"domain": [
|
||||
"domain:googleapis.cn",
|
||||
"domain:gstatic.com"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
49
V2rayNG/app/src/main/assets/custom_routing_white_iran
Normal file
49
V2rayNG/app/src/main/assets/custom_routing_white_iran
Normal file
@@ -0,0 +1,49 @@
|
||||
[
|
||||
{
|
||||
"remarks": "Block udp443",
|
||||
"outboundTag": "block",
|
||||
"port": "443",
|
||||
"network": "udp"
|
||||
},
|
||||
{
|
||||
"remarks": "Block ads and trackers",
|
||||
"outboundTag": "block",
|
||||
"domain": [
|
||||
"geosite:category-ads-all"
|
||||
]
|
||||
},
|
||||
{
|
||||
"remarks": "Direct LAN IP",
|
||||
"outboundTag": "direct",
|
||||
"ip": [
|
||||
"geoip:private"
|
||||
]
|
||||
},
|
||||
{
|
||||
"remarks": "Direct LAN domains",
|
||||
"outboundTag": "direct",
|
||||
"domain": [
|
||||
"geosite:private"
|
||||
]
|
||||
},
|
||||
{
|
||||
"remarks": "Bypass Iran domains",
|
||||
"outboundTag": "direct",
|
||||
"domain": [
|
||||
"domain:ir",
|
||||
"geosite:category-ir"
|
||||
]
|
||||
},
|
||||
{
|
||||
"remarks": "Bypass Iran IP",
|
||||
"outboundTag": "direct",
|
||||
"ip": [
|
||||
"geoip:ir"
|
||||
]
|
||||
},
|
||||
{
|
||||
"remarks": "Final Agent",
|
||||
"port": "0-65535",
|
||||
"outboundTag": "proxy"
|
||||
}
|
||||
]
|
||||
@@ -31,6 +31,7 @@ object SettingsManager {
|
||||
0 -> "custom_routing_white"
|
||||
1 -> "custom_routing_black"
|
||||
2 -> "custom_routing_global"
|
||||
3 -> "custom_routing_white_iran"
|
||||
else -> "custom_routing_white"
|
||||
}
|
||||
val assets = Utils.readTextFromAssets(context, fileName)
|
||||
|
||||
104
V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/fmt/FmtBase.kt
Normal file
104
V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/fmt/FmtBase.kt
Normal file
@@ -0,0 +1,104 @@
|
||||
package com.v2ray.ang.util.fmt
|
||||
|
||||
import android.text.TextUtils
|
||||
import com.v2ray.ang.dto.V2rayConfig
|
||||
import com.v2ray.ang.util.Utils
|
||||
|
||||
open class FmtBase {
|
||||
fun toUri(address: String?, port: Int?, userInfo: String?, dicQuery: HashMap<String, String>?, remark: String): String {
|
||||
val query = if (dicQuery != null)
|
||||
("?" + dicQuery.toList().joinToString(
|
||||
separator = "&",
|
||||
transform = { it.first + "=" + Utils.urlEncode(it.second) }))
|
||||
else ""
|
||||
|
||||
val url = String.format(
|
||||
"%s@%s:%s",
|
||||
Utils.urlEncode(userInfo ?: ""),
|
||||
Utils.getIpv6Address(address),
|
||||
port
|
||||
)
|
||||
|
||||
return "${url}${query}#${Utils.urlEncode(remark)}"
|
||||
}
|
||||
|
||||
fun getStdTransport(outbound: V2rayConfig.OutboundBean, streamSetting: V2rayConfig.OutboundBean.StreamSettingsBean): HashMap<String, String> {
|
||||
val dicQuery = HashMap<String, String>()
|
||||
|
||||
dicQuery["security"] = streamSetting.security.ifEmpty { "none" }
|
||||
(streamSetting.tlsSettings
|
||||
?: streamSetting.realitySettings)?.let { tlsSetting ->
|
||||
if (!TextUtils.isEmpty(tlsSetting.serverName)) {
|
||||
dicQuery["sni"] = tlsSetting.serverName
|
||||
}
|
||||
if (!tlsSetting.alpn.isNullOrEmpty() && tlsSetting.alpn.isNotEmpty()) {
|
||||
dicQuery["alpn"] =
|
||||
Utils.removeWhiteSpace(tlsSetting.alpn.joinToString(",")).orEmpty()
|
||||
}
|
||||
if (!TextUtils.isEmpty(tlsSetting.fingerprint)) {
|
||||
dicQuery["fp"] = tlsSetting.fingerprint.orEmpty()
|
||||
}
|
||||
if (!TextUtils.isEmpty(tlsSetting.publicKey)) {
|
||||
dicQuery["pbk"] = tlsSetting.publicKey.orEmpty()
|
||||
}
|
||||
if (!TextUtils.isEmpty(tlsSetting.shortId)) {
|
||||
dicQuery["sid"] = tlsSetting.shortId.orEmpty()
|
||||
}
|
||||
if (!TextUtils.isEmpty(tlsSetting.spiderX)) {
|
||||
dicQuery["spx"] = tlsSetting.spiderX.orEmpty()
|
||||
}
|
||||
}
|
||||
dicQuery["type"] =
|
||||
streamSetting.network.ifEmpty { V2rayConfig.DEFAULT_NETWORK }
|
||||
|
||||
outbound.getTransportSettingDetails()?.let { transportDetails ->
|
||||
when (streamSetting.network) {
|
||||
"tcp" -> {
|
||||
dicQuery["headerType"] = transportDetails[0].ifEmpty { "none" }
|
||||
if (!TextUtils.isEmpty(transportDetails[1])) {
|
||||
dicQuery["host"] = transportDetails[1]
|
||||
}
|
||||
}
|
||||
|
||||
"kcp" -> {
|
||||
dicQuery["headerType"] = transportDetails[0].ifEmpty { "none" }
|
||||
if (!TextUtils.isEmpty(transportDetails[2])) {
|
||||
dicQuery["seed"] = transportDetails[2]
|
||||
}
|
||||
}
|
||||
|
||||
"ws", "httpupgrade", "splithttp" -> {
|
||||
if (!TextUtils.isEmpty(transportDetails[1])) {
|
||||
dicQuery["host"] = transportDetails[1]
|
||||
}
|
||||
if (!TextUtils.isEmpty(transportDetails[2])) {
|
||||
dicQuery["path"] = transportDetails[2]
|
||||
}
|
||||
}
|
||||
|
||||
"http", "h2" -> {
|
||||
dicQuery["type"] = "http"
|
||||
if (!TextUtils.isEmpty(transportDetails[1])) {
|
||||
dicQuery["host"] = transportDetails[1]
|
||||
}
|
||||
if (!TextUtils.isEmpty(transportDetails[2])) {
|
||||
dicQuery["path"] = transportDetails[2]
|
||||
}
|
||||
}
|
||||
|
||||
"quic" -> {
|
||||
dicQuery["headerType"] = transportDetails[0].ifEmpty { "none" }
|
||||
dicQuery["quicSecurity"] = transportDetails[1]
|
||||
dicQuery["key"] = transportDetails[2]
|
||||
}
|
||||
|
||||
"grpc" -> {
|
||||
dicQuery["mode"] = transportDetails[0]
|
||||
dicQuery["authority"] = transportDetails[1]
|
||||
dicQuery["serviceName"] = transportDetails[2]
|
||||
}
|
||||
}
|
||||
}
|
||||
return dicQuery
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,7 @@ import com.v2ray.ang.util.MmkvManager.settingsStorage
|
||||
import com.v2ray.ang.util.Utils
|
||||
import java.net.URI
|
||||
|
||||
object Hysteria2Fmt {
|
||||
object Hysteria2Fmt : FmtBase() {
|
||||
|
||||
fun parse(str: String): ServerConfig {
|
||||
var allowInsecure = settingsStorage?.decodeBool(AppConfig.PREF_ALLOW_INSECURE) ?: false
|
||||
@@ -51,7 +51,7 @@ object Hysteria2Fmt {
|
||||
val outbound = config.getProxyOutbound() ?: return ""
|
||||
val streamSetting = outbound.streamSettings ?: V2rayConfig.OutboundBean.StreamSettingsBean()
|
||||
|
||||
val remark = "#" + Utils.urlEncode(config.remarks)
|
||||
|
||||
val dicQuery = HashMap<String, String>()
|
||||
dicQuery["security"] = streamSetting.security.ifEmpty { "none" }
|
||||
streamSetting.tlsSettings?.let { tlsSetting ->
|
||||
@@ -68,17 +68,7 @@ object Hysteria2Fmt {
|
||||
dicQuery["obfs-password"] = outbound.settings?.obfsPassword ?: ""
|
||||
}
|
||||
|
||||
val query = "?" + dicQuery.toList().joinToString(
|
||||
separator = "&",
|
||||
transform = { it.first + "=" + it.second })
|
||||
|
||||
val url = String.format(
|
||||
"%s@%s:%s",
|
||||
outbound.getPassword(),
|
||||
Utils.getIpv6Address(outbound.getServerAddress()),
|
||||
outbound.getServerPort()
|
||||
)
|
||||
return url + query + remark
|
||||
return toUri(outbound.getServerAddress(), outbound.getServerPort(), outbound.getPassword(), dicQuery, config.remarks)
|
||||
}
|
||||
|
||||
fun toNativeConfig(config: ServerConfig, socksPort: Int): Hysteria2Bean? {
|
||||
|
||||
@@ -8,7 +8,7 @@ import com.v2ray.ang.extension.idnHost
|
||||
import com.v2ray.ang.util.Utils
|
||||
import java.net.URI
|
||||
|
||||
object ShadowsocksFmt {
|
||||
object ShadowsocksFmt : FmtBase() {
|
||||
fun parse(str: String): ServerConfig? {
|
||||
val config = ServerConfig.create(EConfigType.SHADOWSOCKS)
|
||||
if (!tryResolveResolveSip002(str, config)) {
|
||||
@@ -52,16 +52,10 @@ object ShadowsocksFmt {
|
||||
|
||||
fun toUri(config: ServerConfig): String {
|
||||
val outbound = config.getProxyOutbound() ?: return ""
|
||||
val remark = "#" + Utils.urlEncode(config.remarks)
|
||||
val pw =
|
||||
Utils.encode("${outbound.getSecurityEncryption()}:${outbound.getPassword()}")
|
||||
val url = String.format(
|
||||
"%s@%s:%s",
|
||||
pw,
|
||||
Utils.getIpv6Address(outbound.getServerAddress()),
|
||||
outbound.getServerPort()
|
||||
)
|
||||
return url + remark
|
||||
|
||||
val pw = Utils.encode("${outbound.getSecurityEncryption()}:${outbound.getPassword()}")
|
||||
|
||||
return toUri(outbound.getServerAddress(), outbound.getServerPort(), pw, null, config.remarks)
|
||||
}
|
||||
|
||||
private fun tryResolveResolveSip002(str: String, config: ServerConfig): Boolean {
|
||||
|
||||
@@ -5,7 +5,7 @@ import com.v2ray.ang.dto.ServerConfig
|
||||
import com.v2ray.ang.dto.V2rayConfig
|
||||
import com.v2ray.ang.util.Utils
|
||||
|
||||
object SocksFmt {
|
||||
object SocksFmt : FmtBase() {
|
||||
fun parse(str: String): ServerConfig? {
|
||||
val config = ServerConfig.create(EConfigType.SOCKS)
|
||||
var result = str.replace(EConfigType.SOCKS.protocolScheme, "")
|
||||
@@ -52,18 +52,13 @@ object SocksFmt {
|
||||
|
||||
fun toUri(config: ServerConfig): String {
|
||||
val outbound = config.getProxyOutbound() ?: return ""
|
||||
val remark = "#" + Utils.urlEncode(config.remarks)
|
||||
|
||||
val pw =
|
||||
if (outbound.settings?.servers?.get(0)?.users?.get(0)?.user != null)
|
||||
"${outbound.settings?.servers?.get(0)?.users?.get(0)?.user}:${outbound.getPassword()}"
|
||||
else
|
||||
":"
|
||||
val url = String.format(
|
||||
"%s@%s:%s",
|
||||
Utils.encode(pw),
|
||||
Utils.getIpv6Address(outbound.getServerAddress()),
|
||||
outbound.getServerPort()
|
||||
)
|
||||
return url + remark
|
||||
|
||||
return toUri(outbound.getServerAddress(), outbound.getServerPort(), pw, null, config.remarks)
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,7 @@ import com.v2ray.ang.util.MmkvManager.settingsStorage
|
||||
import com.v2ray.ang.util.Utils
|
||||
import java.net.URI
|
||||
|
||||
object TrojanFmt {
|
||||
object TrojanFmt : FmtBase() {
|
||||
|
||||
fun parse(str: String): ServerConfig {
|
||||
var allowInsecure = settingsStorage?.decodeBool(AppConfig.PREF_ALLOW_INSECURE) ?: false
|
||||
@@ -76,98 +76,15 @@ object TrojanFmt {
|
||||
val outbound = config.getProxyOutbound() ?: return ""
|
||||
val streamSetting = outbound.streamSettings ?: V2rayConfig.OutboundBean.StreamSettingsBean()
|
||||
|
||||
val remark = "#" + Utils.urlEncode(config.remarks)
|
||||
val dicQuery = HashMap<String, String>()
|
||||
|
||||
val dicQuery = getStdTransport(outbound, streamSetting)
|
||||
|
||||
config.outboundBean?.settings?.servers?.get(0)?.flow?.let {
|
||||
if (!TextUtils.isEmpty(it)) {
|
||||
dicQuery["flow"] = it
|
||||
}
|
||||
}
|
||||
|
||||
dicQuery["security"] = streamSetting.security.ifEmpty { "none" }
|
||||
(streamSetting.tlsSettings
|
||||
?: streamSetting.realitySettings)?.let { tlsSetting ->
|
||||
if (!TextUtils.isEmpty(tlsSetting.serverName)) {
|
||||
dicQuery["sni"] = tlsSetting.serverName
|
||||
}
|
||||
if (!tlsSetting.alpn.isNullOrEmpty() && tlsSetting.alpn.isNotEmpty()) {
|
||||
dicQuery["alpn"] =
|
||||
Utils.removeWhiteSpace(tlsSetting.alpn.joinToString(",")).orEmpty()
|
||||
}
|
||||
if (!TextUtils.isEmpty(tlsSetting.fingerprint)) {
|
||||
dicQuery["fp"] = tlsSetting.fingerprint.orEmpty()
|
||||
}
|
||||
if (!TextUtils.isEmpty(tlsSetting.publicKey)) {
|
||||
dicQuery["pbk"] = tlsSetting.publicKey.orEmpty()
|
||||
}
|
||||
if (!TextUtils.isEmpty(tlsSetting.shortId)) {
|
||||
dicQuery["sid"] = tlsSetting.shortId.orEmpty()
|
||||
}
|
||||
if (!TextUtils.isEmpty(tlsSetting.spiderX)) {
|
||||
dicQuery["spx"] = Utils.urlEncode(tlsSetting.spiderX.orEmpty())
|
||||
}
|
||||
}
|
||||
dicQuery["type"] =
|
||||
streamSetting.network.ifEmpty { V2rayConfig.DEFAULT_NETWORK }
|
||||
|
||||
outbound.getTransportSettingDetails()?.let { transportDetails ->
|
||||
when (streamSetting.network) {
|
||||
"tcp" -> {
|
||||
dicQuery["headerType"] = transportDetails[0].ifEmpty { "none" }
|
||||
if (!TextUtils.isEmpty(transportDetails[1])) {
|
||||
dicQuery["host"] = Utils.urlEncode(transportDetails[1])
|
||||
}
|
||||
}
|
||||
|
||||
"kcp" -> {
|
||||
dicQuery["headerType"] = transportDetails[0].ifEmpty { "none" }
|
||||
if (!TextUtils.isEmpty(transportDetails[2])) {
|
||||
dicQuery["seed"] = Utils.urlEncode(transportDetails[2])
|
||||
}
|
||||
}
|
||||
|
||||
"ws", "httpupgrade", "splithttp" -> {
|
||||
if (!TextUtils.isEmpty(transportDetails[1])) {
|
||||
dicQuery["host"] = Utils.urlEncode(transportDetails[1])
|
||||
}
|
||||
if (!TextUtils.isEmpty(transportDetails[2])) {
|
||||
dicQuery["path"] = Utils.urlEncode(transportDetails[2])
|
||||
}
|
||||
}
|
||||
|
||||
"http", "h2" -> {
|
||||
dicQuery["type"] = "http"
|
||||
if (!TextUtils.isEmpty(transportDetails[1])) {
|
||||
dicQuery["host"] = Utils.urlEncode(transportDetails[1])
|
||||
}
|
||||
if (!TextUtils.isEmpty(transportDetails[2])) {
|
||||
dicQuery["path"] = Utils.urlEncode(transportDetails[2])
|
||||
}
|
||||
}
|
||||
|
||||
"quic" -> {
|
||||
dicQuery["headerType"] = transportDetails[0].ifEmpty { "none" }
|
||||
dicQuery["quicSecurity"] = Utils.urlEncode(transportDetails[1])
|
||||
dicQuery["key"] = Utils.urlEncode(transportDetails[2])
|
||||
}
|
||||
|
||||
"grpc" -> {
|
||||
dicQuery["mode"] = transportDetails[0]
|
||||
dicQuery["authority"] = Utils.urlEncode(transportDetails[1])
|
||||
dicQuery["serviceName"] = Utils.urlEncode(transportDetails[2])
|
||||
}
|
||||
}
|
||||
}
|
||||
val query = "?" + dicQuery.toList().joinToString(
|
||||
separator = "&",
|
||||
transform = { it.first + "=" + it.second })
|
||||
|
||||
val url = String.format(
|
||||
"%s@%s:%s",
|
||||
outbound.getPassword(),
|
||||
Utils.getIpv6Address(outbound.getServerAddress()),
|
||||
outbound.getServerPort()
|
||||
)
|
||||
return url + query + remark
|
||||
return toUri(outbound.getServerAddress(), outbound.getServerPort(), outbound.getPassword(), dicQuery, config.remarks)
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,7 @@ import com.v2ray.ang.util.MmkvManager.settingsStorage
|
||||
import com.v2ray.ang.util.Utils
|
||||
import java.net.URI
|
||||
|
||||
object VlessFmt {
|
||||
object VlessFmt : FmtBase() {
|
||||
|
||||
fun parse(str: String): ServerConfig? {
|
||||
var allowInsecure = settingsStorage?.decodeBool(AppConfig.PREF_ALLOW_INSECURE) ?: false
|
||||
@@ -63,8 +63,9 @@ object VlessFmt {
|
||||
val outbound = config.getProxyOutbound() ?: return ""
|
||||
val streamSetting = outbound.streamSettings ?: V2rayConfig.OutboundBean.StreamSettingsBean()
|
||||
|
||||
val remark = "#" + Utils.urlEncode(config.remarks)
|
||||
val dicQuery = HashMap<String, String>()
|
||||
|
||||
val dicQuery = getStdTransport(outbound, streamSetting)
|
||||
|
||||
outbound.settings?.vnext?.get(0)?.users?.get(0)?.flow?.let {
|
||||
if (!TextUtils.isEmpty(it)) {
|
||||
dicQuery["flow"] = it
|
||||
@@ -74,91 +75,6 @@ object VlessFmt {
|
||||
if (outbound.getSecurityEncryption().isNullOrEmpty()) "none"
|
||||
else outbound.getSecurityEncryption().orEmpty()
|
||||
|
||||
|
||||
dicQuery["security"] = streamSetting.security.ifEmpty { "none" }
|
||||
(streamSetting.tlsSettings
|
||||
?: streamSetting.realitySettings)?.let { tlsSetting ->
|
||||
if (!TextUtils.isEmpty(tlsSetting.serverName)) {
|
||||
dicQuery["sni"] = tlsSetting.serverName
|
||||
}
|
||||
if (!tlsSetting.alpn.isNullOrEmpty() && tlsSetting.alpn.isNotEmpty()) {
|
||||
dicQuery["alpn"] =
|
||||
Utils.removeWhiteSpace(tlsSetting.alpn.joinToString(",")).orEmpty()
|
||||
}
|
||||
if (!TextUtils.isEmpty(tlsSetting.fingerprint)) {
|
||||
dicQuery["fp"] = tlsSetting.fingerprint.orEmpty()
|
||||
}
|
||||
if (!TextUtils.isEmpty(tlsSetting.publicKey)) {
|
||||
dicQuery["pbk"] = tlsSetting.publicKey.orEmpty()
|
||||
}
|
||||
if (!TextUtils.isEmpty(tlsSetting.shortId)) {
|
||||
dicQuery["sid"] = tlsSetting.shortId.orEmpty()
|
||||
}
|
||||
if (!TextUtils.isEmpty(tlsSetting.spiderX)) {
|
||||
dicQuery["spx"] = Utils.urlEncode(tlsSetting.spiderX.orEmpty())
|
||||
}
|
||||
}
|
||||
dicQuery["type"] =
|
||||
streamSetting.network.ifEmpty { V2rayConfig.DEFAULT_NETWORK }
|
||||
|
||||
outbound.getTransportSettingDetails()?.let { transportDetails ->
|
||||
when (streamSetting.network) {
|
||||
"tcp" -> {
|
||||
dicQuery["headerType"] = transportDetails[0].ifEmpty { "none" }
|
||||
if (!TextUtils.isEmpty(transportDetails[1])) {
|
||||
dicQuery["host"] = Utils.urlEncode(transportDetails[1])
|
||||
}
|
||||
}
|
||||
|
||||
"kcp" -> {
|
||||
dicQuery["headerType"] = transportDetails[0].ifEmpty { "none" }
|
||||
if (!TextUtils.isEmpty(transportDetails[2])) {
|
||||
dicQuery["seed"] = Utils.urlEncode(transportDetails[2])
|
||||
}
|
||||
}
|
||||
|
||||
"ws", "httpupgrade", "splithttp" -> {
|
||||
if (!TextUtils.isEmpty(transportDetails[1])) {
|
||||
dicQuery["host"] = Utils.urlEncode(transportDetails[1])
|
||||
}
|
||||
if (!TextUtils.isEmpty(transportDetails[2])) {
|
||||
dicQuery["path"] = Utils.urlEncode(transportDetails[2])
|
||||
}
|
||||
}
|
||||
|
||||
"http", "h2" -> {
|
||||
dicQuery["type"] = "http"
|
||||
if (!TextUtils.isEmpty(transportDetails[1])) {
|
||||
dicQuery["host"] = Utils.urlEncode(transportDetails[1])
|
||||
}
|
||||
if (!TextUtils.isEmpty(transportDetails[2])) {
|
||||
dicQuery["path"] = Utils.urlEncode(transportDetails[2])
|
||||
}
|
||||
}
|
||||
|
||||
"quic" -> {
|
||||
dicQuery["headerType"] = transportDetails[0].ifEmpty { "none" }
|
||||
dicQuery["quicSecurity"] = Utils.urlEncode(transportDetails[1])
|
||||
dicQuery["key"] = Utils.urlEncode(transportDetails[2])
|
||||
}
|
||||
|
||||
"grpc" -> {
|
||||
dicQuery["mode"] = transportDetails[0]
|
||||
dicQuery["authority"] = Utils.urlEncode(transportDetails[1])
|
||||
dicQuery["serviceName"] = Utils.urlEncode(transportDetails[2])
|
||||
}
|
||||
}
|
||||
}
|
||||
val query = "?" + dicQuery.toList().joinToString(
|
||||
separator = "&",
|
||||
transform = { it.first + "=" + it.second })
|
||||
|
||||
val url = String.format(
|
||||
"%s@%s:%s",
|
||||
outbound.getPassword(),
|
||||
Utils.getIpv6Address(outbound.getServerAddress()),
|
||||
outbound.getServerPort()
|
||||
)
|
||||
return url + query + remark
|
||||
return toUri(outbound.getServerAddress(), outbound.getServerPort(), outbound.getPassword(), dicQuery, config.remarks)
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,7 @@ import com.v2ray.ang.util.MmkvManager.settingsStorage
|
||||
import com.v2ray.ang.util.Utils
|
||||
import java.net.URI
|
||||
|
||||
object VmessFmt {
|
||||
object VmessFmt : FmtBase() {
|
||||
|
||||
fun parse(str: String): ServerConfig? {
|
||||
if (str.indexOf('?') > 0 && str.indexOf('&') > 0) {
|
||||
|
||||
@@ -8,7 +8,7 @@ import com.v2ray.ang.extension.removeWhiteSpace
|
||||
import com.v2ray.ang.util.Utils
|
||||
import java.net.URI
|
||||
|
||||
object WireguardFmt {
|
||||
object WireguardFmt : FmtBase() {
|
||||
fun parse(str: String): ServerConfig? {
|
||||
val uri = URI(Utils.fixIllegalUrl(str))
|
||||
if (uri.rawQuery != null) {
|
||||
@@ -71,37 +71,22 @@ object WireguardFmt {
|
||||
}
|
||||
|
||||
|
||||
|
||||
fun toUri(config: ServerConfig): String {
|
||||
val outbound = config.getProxyOutbound() ?: return ""
|
||||
|
||||
val remark = "#" + Utils.urlEncode(config.remarks)
|
||||
|
||||
val dicQuery = HashMap<String, String>()
|
||||
dicQuery["publickey"] =
|
||||
Utils.urlEncode(outbound.settings?.peers?.get(0)?.publicKey.toString())
|
||||
dicQuery["publickey"] = outbound.settings?.peers?.get(0)?.publicKey.toString()
|
||||
if (outbound.settings?.reserved != null) {
|
||||
dicQuery["reserved"] = Utils.urlEncode(
|
||||
Utils.removeWhiteSpace(outbound.settings?.reserved?.joinToString(","))
|
||||
.toString()
|
||||
)
|
||||
dicQuery["reserved"] = Utils.removeWhiteSpace(outbound.settings?.reserved?.joinToString(",")).toString()
|
||||
|
||||
}
|
||||
dicQuery["address"] = Utils.urlEncode(
|
||||
Utils.removeWhiteSpace((outbound.settings?.address as List<*>).joinToString(","))
|
||||
.toString()
|
||||
)
|
||||
dicQuery["address"] = Utils.removeWhiteSpace((outbound.settings?.address as List<*>).joinToString(",")).toString()
|
||||
|
||||
if (outbound.settings?.mtu != null) {
|
||||
dicQuery["mtu"] = outbound.settings?.mtu.toString()
|
||||
}
|
||||
val query = "?" + dicQuery.toList().joinToString(
|
||||
separator = "&",
|
||||
transform = { it.first + "=" + it.second })
|
||||
|
||||
val url = String.format(
|
||||
"%s@%s:%s",
|
||||
Utils.urlEncode(outbound.getPassword().toString()),
|
||||
Utils.getIpv6Address(outbound.getServerAddress()),
|
||||
outbound.getServerPort()
|
||||
)
|
||||
return url + query + remark
|
||||
return toUri(outbound.getServerAddress(), outbound.getServerPort(), outbound.getPassword(), dicQuery, config.remarks)
|
||||
}
|
||||
}
|
||||
@@ -301,4 +301,11 @@
|
||||
<item>Dark</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="preset_rulesets">
|
||||
<item>لیست سفید چین</item>
|
||||
<item>لیست سیاه چین</item>
|
||||
<item>جهانی(Global)</item>
|
||||
<item>ایران</item>
|
||||
</string-array>
|
||||
|
||||
</resources>
|
||||
|
||||
@@ -306,6 +306,7 @@
|
||||
<item>绕过大陆(Whitelist)</item>
|
||||
<item>黑名单(Blacklist)</item>
|
||||
<item>全局(Global)</item>
|
||||
<item>伊朗(Iran)</item>
|
||||
</string-array>
|
||||
|
||||
</resources>
|
||||
|
||||
@@ -308,6 +308,7 @@
|
||||
<item>繞過大陸(Whitelist)</item>
|
||||
<item>黑名單(Blacklist)</item>
|
||||
<item>全域(Global)</item>
|
||||
<item>伊朗(Iran)</item>
|
||||
</string-array>
|
||||
|
||||
</resources>
|
||||
|
||||
@@ -318,6 +318,7 @@
|
||||
<item>China Whitelist</item>
|
||||
<item>China Blacklist</item>
|
||||
<item>Global</item>
|
||||
<item>Iran Whitelist</item>
|
||||
</string-array>
|
||||
|
||||
</resources>
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
[versions]
|
||||
activityKtx = "1.9.2"
|
||||
activityKtx = "1.9.3"
|
||||
appcompat = "1.7.0"
|
||||
cardview = "1.0.0"
|
||||
constraintlayout = "2.1.4"
|
||||
core = "3.5.3"
|
||||
editorkit = "2.9.0"
|
||||
flexbox = "3.0.0"
|
||||
fragmentKtx = "1.8.3"
|
||||
fragmentKtx = "1.8.4"
|
||||
gson = "2.11.0"
|
||||
junit = "4.13.2"
|
||||
kotlinReflect = "2.0.20"
|
||||
kotlinxCoroutinesCore = "1.9.0"
|
||||
legacySupportV4 = "1.0.0"
|
||||
lifecycleViewmodelKtx = "2.8.5"
|
||||
lifecycleViewmodelKtx = "2.8.6"
|
||||
material = "1.12.0"
|
||||
mmkvStatic = "1.3.9"
|
||||
multidex = "2.0.1"
|
||||
|
||||
Reference in New Issue
Block a user