diff --git a/V2rayNG/app/build.gradle b/V2rayNG/app/build.gradle index 31aef9550..5e71f5e22 100644 --- a/V2rayNG/app/build.gradle +++ b/V2rayNG/app/build.gradle @@ -19,8 +19,8 @@ android { minSdkVersion 21 targetSdkVersion Integer.parseInt("$targetSdkVer") multiDexEnabled true - versionCode 5100543 //hiddify when comes to version 5 change it - versionName "4.3.0" //hiddify + versionCode 5100544 //hiddify when comes to version 5 change it + versionName "4.4.0" //hiddify } signingConfigs { diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/AngApplication.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/AngApplication.kt index 6150b3491..d4daa8659 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/AngApplication.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/AngApplication.kt @@ -34,7 +34,7 @@ class AngApplication : MultiDexApplication() { // LeakCanary.install(this) FirebaseApp.initializeApp(this); FirebaseCrashlytics.getInstance().setCrashlyticsCollectionEnabled(true) - Thread.setDefaultUncaughtExceptionHandler(ExceptionHandler(this)) +// Thread.setDefaultUncaughtExceptionHandler(ExceptionHandler(this)) Firebase.messaging.subscribeToTopic("all") val defaultSharedPreferences = PreferenceManager.getDefaultSharedPreferences(this) diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/VmessQRCode.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/VmessQRCode.kt index 044bac61e..3c0253297 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/VmessQRCode.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/VmessQRCode.kt @@ -15,5 +15,6 @@ data class VmessQRCode(var v: String = "", var sni: String = "", var alpn: String = "", var fp: String = "", - var fragment: String="" + var fragment: String="", + var fragment_v1: String="" ) \ No newline at end of file diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/service/V2RayServiceManager.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/service/V2RayServiceManager.kt index 37e73ef64..a1f380b17 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/service/V2RayServiceManager.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/service/V2RayServiceManager.kt @@ -7,6 +7,7 @@ import android.content.Intent import android.content.IntentFilter import android.graphics.Color import android.os.Build +import android.os.Debug import android.os.Handler import android.os.Looper import android.util.Log @@ -126,6 +127,7 @@ object V2RayServiceManager { } fun startV2rayPoint() { + //Debug.waitForDebugger(); val service = serviceControl?.get()?.getService() ?: return val guid = mainStorage?.decodeString(MmkvManager.KEY_SELECTED_SERVER) ?: return val config = MmkvManager.decodeServerConfig(guid) ?: return @@ -153,8 +155,10 @@ object V2RayServiceManager { v2rayPoint.runLoop(settingsStorage?.decodeBool(AppConfig.PREF_PREFER_IPV6) ?: false) } catch (e: Exception) { Log.d(ANG_PACKAGE, e.toString()) + Log.d(ANG_PACKAGE, e.stackTraceToString()) + Log.d(ANG_PACKAGE, result.content) if (!v2rayPoint.isRunning) - MessageUtil.sendMsg2UI(service, AppConfig.MSG_STATE_START_FAILURE_CONFIG_ERROR, "") + MessageUtil.sendMsg2UI(service, AppConfig.MSG_STATE_START_FAILURE_CONFIG_ERROR, e.toString()) } if (v2rayPoint.isRunning) { diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/HiddifyUtils.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/HiddifyUtils.kt deleted file mode 100644 index 70e86e545..000000000 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/HiddifyUtils.kt +++ /dev/null @@ -1,73 +0,0 @@ -package com.v2ray.ang.util - -import android.content.Context -import android.text.SpannableString -import com.v2ray.ang.R -import com.v2ray.ang.extension.* -import com.v2ray.ang.util.Utils.getLocale -import java.util.Locale - -object HiddifyUtils1 { - fun toTotalUsedGig(totalInBytes: Long, usedInBytes: Long, context: Context): String { - val total = totalInBytes.toDouble() / 1073741824 - val used = usedInBytes.toDouble() / 1073741824 - return String.format("%.0f/%.0f G", used, total).toPersianDigit(context) - } - - fun timeToRelativeDate(time: Long, totalInBytes: Long, usedInBytes: Long, context: Context): SpannableString { - if (time < 0) - return "".bold("") - - val now = System.currentTimeMillis() / 1000 - val diffInMillis = (time - now) / 86400 - if (diffInMillis <= 0) - return if (getLocale(context) == Locale("fa") || getLocale(context).toString() == "fa_IR") - "منقضی شده".bold("") - else "Expired".bold("") - - if (totalInBytes == usedInBytes) - return if (getLocale(context) == Locale("fa") || getLocale(context).toString() == "fa_IR") - "اتمام حجم".bold("") - else "Completion of the volume".bold("") - - - return if (getLocale(context) == Locale("fa") || getLocale(context).toString() == "fa_IR") { - if (diffInMillis > 10) - "$diffInMillis روز \n باقیمانده".toPersianDigit() - .colorlessTextPart("باقیمانده", context.getColorEx(R.color.colorBorder)) - else - "$diffInMillis روز \n باقیمانده".toPersianDigit() - .colorlessTextPart("باقیمانده", context.getColorEx(R.color.colorBorder)) - .colorlessTextPart( - "${diffInMillis.toString().toPersianDigit()} روز ", - context.getColorEx(R.color.colorRed) - ) - } else { - if (diffInMillis > 10) - "$diffInMillis days \n Remain".colorlessTextPart( - "Remain", - context.getColorEx(R.color.colorBorder) - ) - else - "$diffInMillis days \n Remain".colorlessTextPart( - "Remain", - context.getColorEx(R.color.colorBorder) - ).colorlessTextPart("$diffInMillis days ", context.getColorEx(R.color.colorRed)) - } - } - - fun checkState(time: Long, totalInBytes: Long, usedInBytes: Long): String { - if (time < 0) - return "disable" - - val now = System.currentTimeMillis() / 1000 - val diffInMillis = (time - now) / 86400 - if (diffInMillis <= 0) - return "disable" - - if (totalInBytes == usedInBytes) - return "disable" - - return "enable" - } -} diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/ServerActivity.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/ServerActivity.kt index 957291bfc..855d219ad 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/ServerActivity.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/ServerActivity.kt @@ -16,6 +16,8 @@ import com.v2ray.ang.dto.ServerConfig import com.v2ray.ang.dto.V2rayConfig import com.v2ray.ang.dto.V2rayConfig.Companion.DEFAULT_PORT import com.v2ray.ang.dto.V2rayConfig.Companion.TLS +import com.v2ray.ang.extension.gone +import com.v2ray.ang.extension.show import com.v2ray.ang.extension.toast import com.v2ray.ang.util.MmkvManager import com.v2ray.ang.util.MmkvManager.ID_MAIN @@ -99,6 +101,7 @@ class ServerActivity : BaseActivity() { private val container_fingerprint: LinearLayout? by lazy { findViewById(R.id.l3) } private val sp_network: Spinner? by lazy { findViewById(R.id.sp_network) } private val sp_fragment: Spinner? by lazy { findViewById(R.id.sp_fragment) } + private val sp_fragment_label: LinearLayout? by lazy { findViewById(R.id.hiddifyl4) } private val sp_fragment_new: Spinner? by lazy { findViewById(R.id.sp_fragment_new) } private val sp_header_type: Spinner? by lazy { findViewById(R.id.sp_header_type) } private val sp_header_type_title: TextView? by lazy { findViewById(R.id.sp_header_type_title) } @@ -271,10 +274,19 @@ class ServerActivity : BaseActivity() { sp_network?.setSelection(network) } if(streamSetting?.sockopt?.dialer_proxy!=null) { - sp_fragment?.setSelection(Utils.arrayFind(fragmentNewTypes, streamSetting?.sockopt?.dialer_proxy!!.replace("fragment_",""))) + sp_fragment_new?.setSelection(Utils.arrayFind(fragmentNewTypes, streamSetting?.sockopt?.dialer_proxy!!.substringAfter("_",""))) + }else{ + sp_fragment_new?.setSelection(0) + } + if(streamSetting?.wsSettings?.fragmentation?.enabled==true){ + sp_fragment?.setSelection(Utils.arrayFind(fragmentTypes, streamSetting?.wsSettings?.fragmentation?.strategy?:"")) }else{ sp_fragment?.setSelection(0) } + if(streamSetting.network!="ws") + sp_fragment_label?.gone() + else + sp_fragment_label?.show() return true } 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 7e7a88cec..0be353154 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 @@ -210,7 +210,7 @@ object AngConfigManager { ) { return R.string.toast_incorrect_protocol } - + addFragmentOutbound(config.outboundBean?.streamSettings,vmessQRCode.fragment) config.remarks = vmessQRCode.ps config.outboundBean?.settings?.vnext?.get(0)?.let { vnext -> vnext.address = vmessQRCode.add @@ -220,7 +220,7 @@ object AngConfigManager { vnext.users[0].alterId = Utils.parseInt(vmessQRCode.aid) } val sni = streamSetting.populateTransportSettings(vmessQRCode.net, vmessQRCode.type, vmessQRCode.host, - vmessQRCode.path, vmessQRCode.path, vmessQRCode.host, vmessQRCode.path, vmessQRCode.type, vmessQRCode.path,vmessQRCode.fragment) + vmessQRCode.path, vmessQRCode.path, vmessQRCode.host, vmessQRCode.path, vmessQRCode.type, vmessQRCode.path,vmessQRCode.fragment_v1) val fingerprint = vmessQRCode.fp ?: streamSetting.tlsSettings?.fingerprint streamSetting.populateTlsSettings(vmessQRCode.tls, allowInsecure, @@ -298,16 +298,17 @@ object AngConfigManager { val uri = URI(Utils.fixIllegalUrl(str)) config = ServerConfig.create(EConfigType.TROJAN) config.remarks = Utils.urlDecode(uri.fragment ?: "") - + var flow = "" var fingerprint = config.outboundBean?.streamSettings?.tlsSettings?.fingerprint if (uri.rawQuery != null) { val queryParam = uri.rawQuery.split("&") .associate { it.split("=").let { (k, v) -> k to Utils.urlDecode(v) } } + addFragmentOutbound(config.outboundBean?.streamSettings,queryParam["fragment"]) var allowInsecure=(queryParam["allowInsecure"]?:"")=="true" val sni = config.outboundBean?.streamSettings?.populateTransportSettings(queryParam["type"] ?: "tcp", queryParam["headerType"], queryParam["host"], queryParam["path"], queryParam["seed"], queryParam["quicSecurity"], queryParam["key"], - queryParam["mode"], queryParam["serviceName"], queryParam["fragment"]) + queryParam["mode"], queryParam["serviceName"], queryParam["fragment_v1"]) fingerprint = queryParam["fp"] ?: "" config.outboundBean?.streamSettings?.populateTlsSettings(queryParam["security"] ?: TLS, allowInsecure, queryParam["sni"] ?: sni!!, fingerprint, queryParam["alpn"], @@ -331,7 +332,7 @@ object AngConfigManager { config = ServerConfig.create(EConfigType.VLESS) val streamSetting = config.outboundBean?.streamSettings ?: return -1 var fingerprint = streamSetting.tlsSettings?.fingerprint - + addFragmentOutbound(config.outboundBean?.streamSettings, queryParam["fragment"]) config.remarks = Utils.urlDecode(uri.fragment ?: "") config.outboundBean?.settings?.vnext?.get(0)?.let { vnext -> vnext.address = uri.idnHost @@ -340,10 +341,10 @@ object AngConfigManager { vnext.users[0].encryption = queryParam["encryption"] ?: "none" vnext.users[0].flow =queryParam["flow"] ?: "" } - + var allowInsecure=(queryParam["allowInsecure"]?:"")=="true" val sni = streamSetting.populateTransportSettings(queryParam["type"] ?: "tcp", queryParam["headerType"], queryParam["host"], queryParam["path"], queryParam["seed"], queryParam["quicSecurity"], queryParam["key"], - queryParam["mode"], queryParam["serviceName"], queryParam["fragment"]) + queryParam["mode"], queryParam["serviceName"], queryParam["fragment_v1"]) fingerprint = queryParam["fp"] ?: "" val pbk = queryParam["pbk"] ?: "" val sid = queryParam["sid"] ?: "" @@ -370,7 +371,14 @@ object AngConfigManager { } return 0 } + private fun addFragmentOutbound(streamSettingsBean: V2rayConfig.OutboundBean.StreamSettingsBean?,mode:String?){ + if(mode.isNullOrEmpty()||streamSettingsBean==null) + return + if(!arrayListOf("sni","random").contains("mode")) + return + streamSettingsBean.sockopt=V2rayConfig.Sockopt(dialer_proxy = "fragment_$mode") + } private fun tryParseNewVmess(uriString: String, config: ServerConfig, allowInsecure_: Boolean): Boolean { return runCatching { val uri = URI(uriString) @@ -382,7 +390,7 @@ object AngConfigManager { val tls = tlsStr.isNotBlank() val queryParam = uri.rawQuery.split("&") .associate { it.split("=").let { (k, v) -> k to Utils.urlDecode(v) } } - + addFragmentOutbound(config.outboundBean?.streamSettings,queryParam["fragment"]) val streamSetting = config.outboundBean?.streamSettings ?: return false config.remarks = Utils.urlDecode(uri.fragment ?: "") config.outboundBean.settings?.vnext?.get(0)?.let { vnext -> @@ -393,12 +401,12 @@ object AngConfigManager { vnext.users[0].alterId = alterId.toInt() } var fingerprint = streamSetting.tlsSettings?.fingerprint - var allowInsecure=(queryParam["allowInsecure"]?:"")=="true" + var allowInsecure2=allowInsecure_ ||(queryParam["allowInsecure"]?:"")=="true" val sni = streamSetting.populateTransportSettings(protocol, queryParam["type"], queryParam["host"]?.split("|")?.get(0) ?: "", queryParam["path"]?.takeIf { it.trim() != "/" } ?: "", queryParam["seed"], queryParam["security"], - queryParam["key"], queryParam["mode"], queryParam["serviceName"], queryParam["fragment"]) - streamSetting.populateTlsSettings(if (tls) TLS else "", allowInsecure, sni, fingerprint, null, + queryParam["key"], queryParam["mode"], queryParam["serviceName"], queryParam["fragment_v1"]) + streamSetting.populateTlsSettings(if (tls) TLS else "", allowInsecure2, sni, fingerprint, null, null, null, null) true }.getOrElse { false } @@ -494,12 +502,13 @@ object AngConfigManager { vmessQRCode.sni = streamSetting.tlsSettings?.serverName.orEmpty() vmessQRCode.alpn = Utils.removeWhiteSpace(streamSetting.tlsSettings?.alpn?.joinToString()).orEmpty() vmessQRCode.fp = streamSetting.tlsSettings?.fingerprint.orEmpty() + vmessQRCode.fragment=streamSetting.sockopt?.dialer_proxy?.substringAfter("_")?:"" outbound.getTransportSettingDetails()?.let { transportDetails -> vmessQRCode.type = transportDetails[0] vmessQRCode.host = transportDetails[1] vmessQRCode.path = transportDetails[2] if (transportDetails.count()>3) - vmessQRCode.fragment = transportDetails[3] + vmessQRCode.fragment_v1 = transportDetails[3] } val json = Gson().toJson(vmessQRCode) Utils.encode(json) @@ -545,7 +554,7 @@ object AngConfigManager { } } } - + dicQuery["fragment"] =streamSetting.sockopt?.dialer_proxy?.substringAfter("_")?:"" dicQuery["security"] = streamSetting.security.ifEmpty { "none" } (streamSetting.tlsSettings?: streamSetting.realitySettings)?.let { tlsSetting -> if (!TextUtils.isEmpty(tlsSetting.serverName)) { @@ -592,7 +601,7 @@ object AngConfigManager { dicQuery["path"] = Utils.urlEncode(transportDetails[2]) } if (transportDetails.count()>3 && !TextUtils.isEmpty(transportDetails[3])) { - dicQuery["fragment"] = transportDetails[3] + dicQuery["fragment_v1"] = transportDetails[3] } } "http", "h2" -> { diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/HiddifyUtils.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/HiddifyUtils.kt index 0419cbbd3..7447c1b65 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/HiddifyUtils.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/HiddifyUtils.kt @@ -247,7 +247,6 @@ class HiddifyUtils { return settingsStorage?.decodeString(AppConfig.PREF_COUNTRY)!! } - fun getPerAppProxyMode(): PerAppProxyMode { if(!defaultSharedPreferences.getBoolean(AppConfig.PREF_PER_APP_PROXY, false)) return PerAppProxyMode.Global diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/V2rayConfigUtil.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/V2rayConfigUtil.kt index 8045f68b8..8cb5abc79 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/V2rayConfigUtil.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/V2rayConfigUtil.kt @@ -1,6 +1,7 @@ package com.v2ray.ang.util import android.content.Context +import android.os.Debug import android.text.TextUtils import android.util.Log import com.google.gson.Gson @@ -441,11 +442,11 @@ object V2rayConfigUtil { private fun dns(v2rayConfig: V2rayConfig,balancerTag:String?=null): Boolean { try { +// Debug.waitForDebugger() val hosts = mutableMapOf() val servers = ArrayList() val remoteDns = Utils.getRemoteDnsServers() - val proxyDomain = userRule2Domian(settingsStorage?.decodeString(AppConfig.PREF_V2RAY_ROUTING_AGENT) - ?: "") + val proxyDomain = userRule2Domian(settingsStorage?.decodeString(AppConfig.PREF_V2RAY_ROUTING_AGENT) ?: "") remoteDns.forEach { servers.add(it) @@ -455,13 +456,12 @@ object V2rayConfigUtil { } // domestic DNS - val directDomain = userRule2Domian(settingsStorage?.decodeString(AppConfig.PREF_V2RAY_ROUTING_DIRECT) - ?: "") + val directDomain = userRule2Domian(settingsStorage?.decodeString(AppConfig.PREF_V2RAY_ROUTING_DIRECT)?: "") val routingMode = settingsStorage?.decodeString(AppConfig.PREF_ROUTING_MODE) ?: ERoutingMode.GLOBAL_PROXY.value if (directDomain.size > 0 || routingMode == ERoutingMode.BYPASS_MAINLAND.value || routingMode == ERoutingMode.BYPASS_LAN_MAINLAND.value) { val domesticDns = Utils.getDomesticDnsServers() - val geositeCn = arrayListOf("geosite:cn") - val geoipCn = arrayListOf("geoip:cn") + val geositeCn = arrayListOf("geosite:"+HiddifyUtils.getCountry()) + val geoipCn = arrayListOf("geoip:"+HiddifyUtils.getCountry()) if (directDomain.size > 0) { servers.add(V2rayConfig.DnsBean.ServersBean(domesticDns.first(), 53, directDomain, geoipCn)) } @@ -479,8 +479,7 @@ object V2rayConfigUtil { } } - val blkDomain = userRule2Domian(settingsStorage?.decodeString(AppConfig.PREF_V2RAY_ROUTING_BLOCKED) - ?: "") + val blkDomain = userRule2Domian(settingsStorage?.decodeString(AppConfig.PREF_V2RAY_ROUTING_BLOCKED)?: "") if (blkDomain.size > 0) { hosts.putAll(blkDomain.map { it to "127.0.0.1" }) } @@ -494,7 +493,7 @@ object V2rayConfigUtil { hosts = hosts) // DNS routing - if (Utils.isPureIpAddress(remoteDns.first())) { + if (false&&Utils.isPureIpAddress(remoteDns.first())) { v2rayConfig.routing.rules.add(0, V2rayConfig.RoutingBean.RulesBean( type = "field", diff --git a/V2rayNG/app/src/main/res/layout/activity_server_shadowsocks.xml b/V2rayNG/app/src/main/res/layout/activity_server_shadowsocks.xml index dba1c1427..989ac3d16 100644 --- a/V2rayNG/app/src/main/res/layout/activity_server_shadowsocks.xml +++ b/V2rayNG/app/src/main/res/layout/activity_server_shadowsocks.xml @@ -124,6 +124,22 @@ android:layout_marginBottom="@dimen/layout_margin_top_height" android:layout_marginTop="@dimen/layout_margin_top_height" android:orientation="vertical" /> + + + + + \ No newline at end of file diff --git a/V2rayNG/app/src/main/res/layout/activity_server_socks.xml b/V2rayNG/app/src/main/res/layout/activity_server_socks.xml index 5f34c37cd..4d4c11b81 100644 --- a/V2rayNG/app/src/main/res/layout/activity_server_socks.xml +++ b/V2rayNG/app/src/main/res/layout/activity_server_socks.xml @@ -117,6 +117,23 @@ android:inputType="text" /> + + + + + + + + + + + + + android:textColor="@color/colorRed" + android:text="@string/fragment_old" /> + + + + + + android:textColor="@color/colorRed" + android:text="@string/fragment_old" /> + android:text="@string/fragment_old" /> برنامه های باز دانلود بدون فیلترشکن با خطا مواجه شد. در حال دانلود با فیلترشکن... ارائه دهنده لینک ساب، یک آدرس جدید را پیشنهاد کرد! آدرس را تغییر دادیم. + فرگمنت v1 (قدیمی) \ No newline at end of file diff --git a/V2rayNG/app/src/main/res/values/hiddify.xml b/V2rayNG/app/src/main/res/values/hiddify.xml index 68d10e1e8..31a02aa4d 100644 --- a/V2rayNG/app/src/main/res/values/hiddify.xml +++ b/V2rayNG/app/src/main/res/values/hiddify.xml @@ -47,5 +47,6 @@ Opened Apps Download failed without proxy! Trying with proxy... Subscription Provider suggest a new address! Changing the Address + Fragment v1 (old) \ No newline at end of file