mirror of
https://github.com/MatsuriDayo/NekoBoxForAndroid.git
synced 2025-12-18 22:20:06 +08:00
update
This commit is contained in:
parent
3270d7e282
commit
dfb81814d1
@ -255,7 +255,7 @@ data class ProxyEntity(
|
||||
|
||||
return with(requireBean()) {
|
||||
StringBuilder().apply {
|
||||
val config = buildConfig(this@ProxyEntity)
|
||||
val config = buildConfig(this@ProxyEntity, forExport = true)
|
||||
append(config.config)
|
||||
|
||||
if (!config.externalIndex.all { it.chain.isEmpty() }) {
|
||||
|
||||
@ -26,9 +26,10 @@ import io.nekohasekai.sagernet.fmt.wireguard.buildSingBoxOutboundWireguardBean
|
||||
import io.nekohasekai.sagernet.ktx.isIpAddress
|
||||
import io.nekohasekai.sagernet.ktx.mkPort
|
||||
import io.nekohasekai.sagernet.utils.PackageCache
|
||||
import moe.matsuri.nb4a.DNS.applyDNSNetworkSettings
|
||||
import moe.matsuri.nb4a.DNS.makeSingBoxRule
|
||||
import moe.matsuri.nb4a.SingBoxOptions.*
|
||||
import moe.matsuri.nb4a.applyDNSNetworkSettings
|
||||
import moe.matsuri.nb4a.checkEmpty
|
||||
import moe.matsuri.nb4a.makeSingBoxRule
|
||||
import moe.matsuri.nb4a.plugin.Plugins
|
||||
import moe.matsuri.nb4a.proxy.config.ConfigBean
|
||||
import moe.matsuri.nb4a.proxy.shadowtls.ShadowTLSBean
|
||||
@ -77,7 +78,7 @@ fun mergeJSON(j: String, to: MutableMap<String, Any>) {
|
||||
}
|
||||
|
||||
fun buildConfig(
|
||||
proxy: ProxyEntity, forTest: Boolean = false
|
||||
proxy: ProxyEntity, forTest: Boolean = false, forExport: Boolean = false
|
||||
): ConfigBuildResult {
|
||||
|
||||
if (proxy.type == TYPE_CONFIG) {
|
||||
@ -98,6 +99,7 @@ fun buildConfig(
|
||||
val trafficMap = HashMap<String, List<ProxyEntity>>()
|
||||
val tagMap = HashMap<Long, String>()
|
||||
val globalOutbounds = ArrayList<Long>()
|
||||
val selectorNames = ArrayList<String>()
|
||||
val group = SagerDatabase.groupDao.getById(proxy.groupId)
|
||||
var optionsToMerge = ""
|
||||
|
||||
@ -116,6 +118,17 @@ fun buildConfig(
|
||||
return mutableListOf(this)
|
||||
}
|
||||
|
||||
fun selectorName(name_: String): String {
|
||||
var name = name_
|
||||
var count = 0
|
||||
while (selectorNames.contains(name)) {
|
||||
count++
|
||||
name = "$name_-$count"
|
||||
}
|
||||
selectorNames.add(name)
|
||||
return name
|
||||
}
|
||||
|
||||
fun ProxyEntity.resolveChain(): MutableList<ProxyEntity> {
|
||||
val frontProxy = group?.frontProxy?.let { SagerDatabase.proxyDao.getById(it) }
|
||||
val landingProxy = group?.landingProxy?.let { SagerDatabase.proxyDao.getById(it) }
|
||||
@ -133,8 +146,8 @@ fun buildConfig(
|
||||
val extraProxies =
|
||||
if (forTest) mapOf() else SagerDatabase.proxyDao.getEntities(extraRules.mapNotNull { rule ->
|
||||
rule.outbound.takeIf { it > 0 && it != proxy.id }
|
||||
}.toHashSet().toList()).associate { it.id to it }
|
||||
val buildSelector = !forTest && group?.isSelector == true
|
||||
}.toHashSet().toList()).associateBy { it.id }
|
||||
val buildSelector = !forTest && group?.isSelector == true && !forExport
|
||||
val uidListDNSRemote = mutableListOf<Int>()
|
||||
val uidListDNSDirect = mutableListOf<Int>()
|
||||
val domainListDNSRemote = mutableListOf<String>()
|
||||
@ -328,6 +341,11 @@ fun buildConfig(
|
||||
tagOut = TAG_PROXY
|
||||
}
|
||||
|
||||
// selector human readable name
|
||||
if (buildSelector && index == 0) {
|
||||
tagOut = selectorName(bean.displayName())
|
||||
}
|
||||
|
||||
// chain rules
|
||||
if (index > 0) {
|
||||
// chain route/proxy rules
|
||||
@ -495,26 +513,25 @@ fun buildConfig(
|
||||
|
||||
// apply user rules
|
||||
for (rule in extraRules) {
|
||||
val _uidList = rule.packages.map {
|
||||
if (rule.packages.isNotEmpty()) {
|
||||
PackageCache.awaitLoadSync()
|
||||
}
|
||||
val uidList2 = rule.packages.map {
|
||||
if (!isVPN) {
|
||||
alerts.add(0 to rule.displayName())
|
||||
}
|
||||
PackageCache[it]?.takeIf { uid -> uid >= 1000 }
|
||||
}.toHashSet().filterNotNull()
|
||||
|
||||
if (rule.packages.isNotEmpty()) {
|
||||
if (!isVPN) {
|
||||
alerts.add(0 to rule.displayName())
|
||||
continue
|
||||
}
|
||||
}
|
||||
route.rules.add(Rule_DefaultOptions().apply {
|
||||
if (rule.packages.isNotEmpty()) {
|
||||
val ruleObj = Rule_DefaultOptions().apply {
|
||||
if (uidList2.isNotEmpty()) {
|
||||
PackageCache.awaitLoadSync()
|
||||
user_id = _uidList
|
||||
user_id = uidList2
|
||||
}
|
||||
|
||||
var _domainList: List<String>? = null
|
||||
var domainList2: List<String>? = null
|
||||
if (rule.domains.isNotBlank()) {
|
||||
_domainList = rule.domains.split("\n")
|
||||
makeSingBoxRule(_domainList, false)
|
||||
domainList2 = rule.domains.split("\n")
|
||||
makeSingBoxRule(domainList2, false)
|
||||
}
|
||||
if (rule.ip.isNotBlank()) {
|
||||
makeSingBoxRule(rule.ip.split("\n"), true)
|
||||
@ -554,13 +571,13 @@ fun buildConfig(
|
||||
// also bypass lookup
|
||||
// cannot use other outbound profile to lookup...
|
||||
if (rule.outbound == -1L) {
|
||||
uidListDNSDirect += _uidList
|
||||
if (_domainList != null) domainListDNSDirect += _domainList
|
||||
uidListDNSDirect += uidList2
|
||||
if (domainList2 != null) domainListDNSDirect += domainList2
|
||||
} else if (rule.outbound == 0L) {
|
||||
uidListDNSRemote += _uidList
|
||||
if (_domainList != null) domainListDNSRemote += _domainList
|
||||
uidListDNSRemote += uidList2
|
||||
if (domainList2 != null) domainListDNSRemote += domainList2
|
||||
} else if (rule.outbound == -2L) {
|
||||
if (_domainList != null) domainListDNSBlock += _domainList
|
||||
if (domainList2 != null) domainListDNSBlock += domainList2
|
||||
}
|
||||
|
||||
outbound = when (val outId = rule.outbound) {
|
||||
@ -570,7 +587,11 @@ fun buildConfig(
|
||||
else -> if (outId == proxy.id) TAG_PROXY else tagMap[outId]
|
||||
?: throw Exception("invalid rule")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
if (!ruleObj.checkEmpty()) {
|
||||
route.rules.add(ruleObj)
|
||||
}
|
||||
}
|
||||
|
||||
for (freedom in arrayOf(TAG_DIRECT, TAG_BYPASS)) outbounds.add(Outbound().apply {
|
||||
@ -683,8 +704,9 @@ fun buildConfig(
|
||||
|
||||
// dns object user rules
|
||||
if (enableDnsRouting) {
|
||||
val dnsRuleObj = mutableListOf<DNSRule_DefaultOptions>()
|
||||
if (uidListDNSRemote.isNotEmpty()) {
|
||||
dns.rules.add(
|
||||
dnsRuleObj.add(
|
||||
DNSRule_DefaultOptions().apply {
|
||||
user_id = uidListDNSRemote.toHashSet().toList()
|
||||
server = if (useFakeDns) "dns-fake" else "dns-remote"
|
||||
@ -692,7 +714,7 @@ fun buildConfig(
|
||||
)
|
||||
}
|
||||
if (domainListDNSRemote.isNotEmpty()) {
|
||||
dns.rules.add(
|
||||
dnsRuleObj.add(
|
||||
DNSRule_DefaultOptions().apply {
|
||||
makeSingBoxRule(domainListDNSRemote.toHashSet().toList())
|
||||
server = if (useFakeDns) "dns-fake" else "dns-remote"
|
||||
@ -700,7 +722,7 @@ fun buildConfig(
|
||||
)
|
||||
}
|
||||
if (uidListDNSDirect.isNotEmpty()) {
|
||||
dns.rules.add(
|
||||
dnsRuleObj.add(
|
||||
DNSRule_DefaultOptions().apply {
|
||||
user_id = uidListDNSDirect.toHashSet().toList()
|
||||
server = "dns-direct"
|
||||
@ -708,7 +730,7 @@ fun buildConfig(
|
||||
)
|
||||
}
|
||||
if (domainListDNSDirect.isNotEmpty()) {
|
||||
dns.rules.add(
|
||||
dnsRuleObj.add(
|
||||
DNSRule_DefaultOptions().apply {
|
||||
makeSingBoxRule(domainListDNSDirect.toHashSet().toList())
|
||||
server = "dns-direct"
|
||||
@ -716,7 +738,7 @@ fun buildConfig(
|
||||
)
|
||||
}
|
||||
if (domainListDNSBlock.isNotEmpty()) {
|
||||
dns.rules.add(
|
||||
dnsRuleObj.add(
|
||||
DNSRule_DefaultOptions().apply {
|
||||
makeSingBoxRule(domainListDNSBlock.toHashSet().toList())
|
||||
server = "dns-block"
|
||||
@ -724,6 +746,9 @@ fun buildConfig(
|
||||
}
|
||||
)
|
||||
}
|
||||
dnsRuleObj.forEach {
|
||||
if (!it.checkEmpty()) dns.rules.add(it)
|
||||
}
|
||||
}
|
||||
|
||||
// Disable DNS for test
|
||||
@ -774,6 +799,7 @@ fun buildConfig(
|
||||
dns.rules.add(DNSRule_DefaultOptions().apply {
|
||||
inbound = listOf("tun-in")
|
||||
server = "dns-fake"
|
||||
disable_cache = true
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@ -199,7 +199,7 @@ object RawUpdater : GroupUpdater() {
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
suspend fun parseRaw(text: String): List<AbstractBean>? {
|
||||
suspend fun parseRaw(text: String, fileName: String = ""): List<AbstractBean>? {
|
||||
|
||||
val proxies = mutableListOf<AbstractBean>()
|
||||
|
||||
@ -399,7 +399,10 @@ object RawUpdater : GroupUpdater() {
|
||||
} else if (text.contains("[Interface]")) {
|
||||
// wireguard
|
||||
try {
|
||||
proxies.addAll(parseWireGuard(text))
|
||||
proxies.addAll(parseWireGuard(text).map {
|
||||
if (fileName.isNotBlank()) it.name = fileName
|
||||
it
|
||||
})
|
||||
return proxies
|
||||
} catch (e: Exception) {
|
||||
Logs.w(e)
|
||||
@ -442,9 +445,7 @@ object RawUpdater : GroupUpdater() {
|
||||
val bean = WireGuardBean().applyDefaultValues()
|
||||
val localAddresses = iface.getAll("Address")
|
||||
if (localAddresses.isNullOrEmpty()) error("Empty address in 'Interface' selection")
|
||||
bean.localAddress = localAddresses.flatMap { it.split(",") }.let { address ->
|
||||
address.joinToString("\n") { it.substringBefore("/") }
|
||||
}
|
||||
bean.localAddress = localAddresses.flatMap { it.split(",") }.joinToString("\n")
|
||||
bean.privateKey = iface["PrivateKey"]
|
||||
val peers = ini.getAll("Peer")
|
||||
if (peers.isNullOrEmpty()) error("Missing 'Peer' selections")
|
||||
|
||||
@ -225,51 +225,52 @@ class ConfigurationFragment @JvmOverloads constructor(
|
||||
return super.onKeyDown(ketCode, event)
|
||||
}
|
||||
|
||||
val importFile = registerForActivityResult(ActivityResultContracts.GetContent()) { file ->
|
||||
if (file != null) runOnDefaultDispatcher {
|
||||
try {
|
||||
val fileName = requireContext().contentResolver.query(file, null, null, null, null)
|
||||
?.use { cursor ->
|
||||
cursor.moveToFirst()
|
||||
cursor.getColumnIndexOrThrow(OpenableColumns.DISPLAY_NAME)
|
||||
.let(cursor::getString)
|
||||
private val importFile =
|
||||
registerForActivityResult(ActivityResultContracts.GetContent()) { file ->
|
||||
if (file != null) runOnDefaultDispatcher {
|
||||
try {
|
||||
val fileName =
|
||||
requireContext().contentResolver.query(file, null, null, null, null)
|
||||
?.use { cursor ->
|
||||
cursor.moveToFirst()
|
||||
cursor.getColumnIndexOrThrow(OpenableColumns.DISPLAY_NAME)
|
||||
.let(cursor::getString)
|
||||
}
|
||||
val proxies = mutableListOf<AbstractBean>()
|
||||
if (fileName != null && fileName.endsWith(".zip")) {
|
||||
// try parse wireguard zip
|
||||
val zip =
|
||||
ZipInputStream(requireContext().contentResolver.openInputStream(file)!!)
|
||||
while (true) {
|
||||
val entry = zip.nextEntry ?: break
|
||||
if (entry.isDirectory) continue
|
||||
val fileText = zip.bufferedReader().readText()
|
||||
RawUpdater.parseRaw(fileText, entry.name)
|
||||
?.let { pl -> proxies.addAll(pl) }
|
||||
zip.closeEntry()
|
||||
}
|
||||
zip.closeQuietly()
|
||||
} else {
|
||||
val fileText =
|
||||
requireContext().contentResolver.openInputStream(file)!!.use {
|
||||
it.bufferedReader().readText()
|
||||
}
|
||||
RawUpdater.parseRaw(fileText, fileName ?: "")
|
||||
?.let { pl -> proxies.addAll(pl) }
|
||||
}
|
||||
|
||||
val proxies = mutableListOf<AbstractBean>()
|
||||
if (fileName != null && fileName.endsWith(".zip")) {
|
||||
// try parse wireguard zip
|
||||
|
||||
val zip =
|
||||
ZipInputStream(requireContext().contentResolver.openInputStream(file)!!)
|
||||
while (true) {
|
||||
val entry = zip.nextEntry ?: break
|
||||
if (entry.isDirectory) continue
|
||||
val fileText = zip.bufferedReader().readText()
|
||||
RawUpdater.parseRaw(fileText)?.let { pl -> proxies.addAll(pl) }
|
||||
zip.closeEntry()
|
||||
if (proxies.isEmpty()) onMainDispatcher {
|
||||
snackbar(getString(R.string.no_proxies_found_in_file)).show()
|
||||
} else import(proxies)
|
||||
} catch (e: SubscriptionFoundException) {
|
||||
(requireActivity() as MainActivity).importSubscription(Uri.parse(e.link))
|
||||
} catch (e: Exception) {
|
||||
Logs.w(e)
|
||||
onMainDispatcher {
|
||||
snackbar(e.readableMessage).show()
|
||||
}
|
||||
zip.closeQuietly()
|
||||
} else {
|
||||
val fileText = requireContext().contentResolver.openInputStream(file)!!.use {
|
||||
it.bufferedReader().readText()
|
||||
}
|
||||
RawUpdater.parseRaw(fileText)?.let { pl -> proxies.addAll(pl) }
|
||||
}
|
||||
|
||||
if (proxies.isEmpty()) onMainDispatcher {
|
||||
snackbar(getString(R.string.no_proxies_found_in_file)).show()
|
||||
} else import(proxies)
|
||||
} catch (e: SubscriptionFoundException) {
|
||||
(requireActivity() as MainActivity).importSubscription(Uri.parse(e.link))
|
||||
} catch (e: Exception) {
|
||||
Logs.w(e)
|
||||
|
||||
onMainDispatcher {
|
||||
snackbar(e.readableMessage).show()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun import(proxies: List<AbstractBean>) {
|
||||
val targetId = DataStore.selectedGroupForImport()
|
||||
|
||||
@ -9,6 +9,7 @@ import android.webkit.*
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import com.afollestad.materialdialogs.MaterialDialog
|
||||
import com.afollestad.materialdialogs.input.input
|
||||
import io.nekohasekai.sagernet.BuildConfig
|
||||
import io.nekohasekai.sagernet.R
|
||||
import io.nekohasekai.sagernet.database.DataStore
|
||||
import io.nekohasekai.sagernet.databinding.LayoutWebviewBinding
|
||||
@ -32,6 +33,7 @@ class WebviewFragment : ToolbarFragment(R.layout.layout_webview), Toolbar.OnMenu
|
||||
val binding = LayoutWebviewBinding.bind(view)
|
||||
|
||||
// webview
|
||||
WebView.setWebContentsDebuggingEnabled(BuildConfig.DEBUG)
|
||||
mWebView = binding.webview
|
||||
mWebView.settings.domStorageEnabled = true
|
||||
mWebView.settings.javaScriptEnabled = true
|
||||
|
||||
@ -1,86 +0,0 @@
|
||||
package moe.matsuri.nb4a
|
||||
|
||||
import io.nekohasekai.sagernet.database.DataStore
|
||||
|
||||
object DNS {
|
||||
fun SingBoxOptions.DNSServerOptions.applyDNSNetworkSettings(isDirect: Boolean) {
|
||||
if (isDirect) {
|
||||
if (DataStore.dnsNetwork.contains("NoDirectIPv4")) this.strategy = "ipv6_only"
|
||||
if (DataStore.dnsNetwork.contains("NoDirectIPv6")) this.strategy = "ipv4_only"
|
||||
} else {
|
||||
if (DataStore.dnsNetwork.contains("NoRemoteIPv4")) this.strategy = "ipv6_only"
|
||||
if (DataStore.dnsNetwork.contains("NoRemoteIPv6")) this.strategy = "ipv4_only"
|
||||
}
|
||||
}
|
||||
|
||||
fun SingBoxOptions.DNSRule_DefaultOptions.makeSingBoxRule(list: List<String>) {
|
||||
geosite = mutableListOf<String>()
|
||||
domain = mutableListOf<String>()
|
||||
domain_suffix = mutableListOf<String>()
|
||||
domain_regex = mutableListOf<String>()
|
||||
domain_keyword = mutableListOf<String>()
|
||||
list.forEach {
|
||||
if (it.startsWith("geosite:")) {
|
||||
geosite.plusAssign(it.removePrefix("geosite:"))
|
||||
} else if (it.startsWith("full:")) {
|
||||
domain.plusAssign(it.removePrefix("full:"))
|
||||
} else if (it.startsWith("domain:")) {
|
||||
domain_suffix.plusAssign(it.removePrefix("domain:"))
|
||||
} else if (it.startsWith("regexp:")) {
|
||||
domain_regex.plusAssign(it.removePrefix("regexp:"))
|
||||
} else if (it.startsWith("keyword:")) {
|
||||
domain_keyword.plusAssign(it.removePrefix("keyword:"))
|
||||
} else {
|
||||
domain.plusAssign(it)
|
||||
}
|
||||
}
|
||||
if (geosite?.isEmpty() == true) geosite = null
|
||||
if (domain?.isEmpty() == true) domain = null
|
||||
if (domain_suffix?.isEmpty() == true) domain_suffix = null
|
||||
if (domain_regex?.isEmpty() == true) domain_regex = null
|
||||
if (domain_keyword?.isEmpty() == true) domain_keyword = null
|
||||
}
|
||||
|
||||
fun SingBoxOptions.Rule_DefaultOptions.makeSingBoxRule(list: List<String>, isIP: Boolean) {
|
||||
if (isIP) {
|
||||
ip_cidr = mutableListOf<String>()
|
||||
geoip = mutableListOf<String>()
|
||||
} else {
|
||||
geosite = mutableListOf<String>()
|
||||
domain = mutableListOf<String>()
|
||||
domain_suffix = mutableListOf<String>()
|
||||
domain_regex = mutableListOf<String>()
|
||||
domain_keyword = mutableListOf<String>()
|
||||
}
|
||||
list.forEach {
|
||||
if (isIP) {
|
||||
if (it.startsWith("geoip:")) {
|
||||
geoip.plusAssign(it.removePrefix("geoip:"))
|
||||
} else {
|
||||
ip_cidr.plusAssign(it)
|
||||
}
|
||||
return@forEach
|
||||
}
|
||||
if (it.startsWith("geosite:")) {
|
||||
geosite.plusAssign(it.removePrefix("geosite:"))
|
||||
} else if (it.startsWith("full:")) {
|
||||
domain.plusAssign(it.removePrefix("full:"))
|
||||
} else if (it.startsWith("domain:")) {
|
||||
domain_suffix.plusAssign(it.removePrefix("domain:"))
|
||||
} else if (it.startsWith("regexp:")) {
|
||||
domain_regex.plusAssign(it.removePrefix("regexp:"))
|
||||
} else if (it.startsWith("keyword:")) {
|
||||
domain_keyword.plusAssign(it.removePrefix("keyword:"))
|
||||
} else {
|
||||
domain.plusAssign(it)
|
||||
}
|
||||
}
|
||||
if (ip_cidr?.isEmpty() == true) ip_cidr = null
|
||||
if (geoip?.isEmpty() == true) geoip = null
|
||||
if (geosite?.isEmpty() == true) geosite = null
|
||||
if (domain?.isEmpty() == true) domain = null
|
||||
if (domain_suffix?.isEmpty() == true) domain_suffix = null
|
||||
if (domain_regex?.isEmpty() == true) domain_regex = null
|
||||
if (domain_keyword?.isEmpty() == true) domain_keyword = null
|
||||
}
|
||||
}
|
||||
106
app/src/main/java/moe/matsuri/nb4a/SingBoxOptionsUtil.kt
Normal file
106
app/src/main/java/moe/matsuri/nb4a/SingBoxOptionsUtil.kt
Normal file
@ -0,0 +1,106 @@
|
||||
package moe.matsuri.nb4a
|
||||
|
||||
import io.nekohasekai.sagernet.database.DataStore
|
||||
|
||||
fun SingBoxOptions.DNSServerOptions.applyDNSNetworkSettings(isDirect: Boolean) {
|
||||
if (isDirect) {
|
||||
if (DataStore.dnsNetwork.contains("NoDirectIPv4")) this.strategy = "ipv6_only"
|
||||
if (DataStore.dnsNetwork.contains("NoDirectIPv6")) this.strategy = "ipv4_only"
|
||||
} else {
|
||||
if (DataStore.dnsNetwork.contains("NoRemoteIPv4")) this.strategy = "ipv6_only"
|
||||
if (DataStore.dnsNetwork.contains("NoRemoteIPv6")) this.strategy = "ipv4_only"
|
||||
}
|
||||
}
|
||||
|
||||
fun SingBoxOptions.DNSRule_DefaultOptions.makeSingBoxRule(list: List<String>) {
|
||||
geosite = mutableListOf<String>()
|
||||
domain = mutableListOf<String>()
|
||||
domain_suffix = mutableListOf<String>()
|
||||
domain_regex = mutableListOf<String>()
|
||||
domain_keyword = mutableListOf<String>()
|
||||
list.forEach {
|
||||
if (it.startsWith("geosite:")) {
|
||||
geosite.plusAssign(it.removePrefix("geosite:"))
|
||||
} else if (it.startsWith("full:")) {
|
||||
domain.plusAssign(it.removePrefix("full:"))
|
||||
} else if (it.startsWith("domain:")) {
|
||||
domain_suffix.plusAssign(it.removePrefix("domain:"))
|
||||
} else if (it.startsWith("regexp:")) {
|
||||
domain_regex.plusAssign(it.removePrefix("regexp:"))
|
||||
} else if (it.startsWith("keyword:")) {
|
||||
domain_keyword.plusAssign(it.removePrefix("keyword:"))
|
||||
} else {
|
||||
domain.plusAssign(it)
|
||||
}
|
||||
}
|
||||
if (geosite?.isEmpty() == true) geosite = null
|
||||
if (domain?.isEmpty() == true) domain = null
|
||||
if (domain_suffix?.isEmpty() == true) domain_suffix = null
|
||||
if (domain_regex?.isEmpty() == true) domain_regex = null
|
||||
if (domain_keyword?.isEmpty() == true) domain_keyword = null
|
||||
}
|
||||
|
||||
fun SingBoxOptions.DNSRule_DefaultOptions.checkEmpty(): Boolean {
|
||||
if (geosite?.isNotEmpty() == true) return false
|
||||
if (domain?.isNotEmpty() == true) return false
|
||||
if (domain_suffix?.isNotEmpty() == true) return false
|
||||
if (domain_regex?.isNotEmpty() == true) return false
|
||||
if (domain_keyword?.isNotEmpty() == true) return false
|
||||
if (user_id?.isNotEmpty() == true) return false
|
||||
return true
|
||||
}
|
||||
|
||||
fun SingBoxOptions.Rule_DefaultOptions.makeSingBoxRule(list: List<String>, isIP: Boolean) {
|
||||
if (isIP) {
|
||||
ip_cidr = mutableListOf<String>()
|
||||
geoip = mutableListOf<String>()
|
||||
} else {
|
||||
geosite = mutableListOf<String>()
|
||||
domain = mutableListOf<String>()
|
||||
domain_suffix = mutableListOf<String>()
|
||||
domain_regex = mutableListOf<String>()
|
||||
domain_keyword = mutableListOf<String>()
|
||||
}
|
||||
list.forEach {
|
||||
if (isIP) {
|
||||
if (it.startsWith("geoip:")) {
|
||||
geoip.plusAssign(it.removePrefix("geoip:"))
|
||||
} else {
|
||||
ip_cidr.plusAssign(it)
|
||||
}
|
||||
return@forEach
|
||||
}
|
||||
if (it.startsWith("geosite:")) {
|
||||
geosite.plusAssign(it.removePrefix("geosite:"))
|
||||
} else if (it.startsWith("full:")) {
|
||||
domain.plusAssign(it.removePrefix("full:"))
|
||||
} else if (it.startsWith("domain:")) {
|
||||
domain_suffix.plusAssign(it.removePrefix("domain:"))
|
||||
} else if (it.startsWith("regexp:")) {
|
||||
domain_regex.plusAssign(it.removePrefix("regexp:"))
|
||||
} else if (it.startsWith("keyword:")) {
|
||||
domain_keyword.plusAssign(it.removePrefix("keyword:"))
|
||||
} else {
|
||||
domain.plusAssign(it)
|
||||
}
|
||||
}
|
||||
if (ip_cidr?.isEmpty() == true) ip_cidr = null
|
||||
if (geoip?.isEmpty() == true) geoip = null
|
||||
if (geosite?.isEmpty() == true) geosite = null
|
||||
if (domain?.isEmpty() == true) domain = null
|
||||
if (domain_suffix?.isEmpty() == true) domain_suffix = null
|
||||
if (domain_regex?.isEmpty() == true) domain_regex = null
|
||||
if (domain_keyword?.isEmpty() == true) domain_keyword = null
|
||||
}
|
||||
|
||||
fun SingBoxOptions.Rule_DefaultOptions.checkEmpty(): Boolean {
|
||||
if (ip_cidr?.isNotEmpty() == true) return false
|
||||
if (geoip?.isNotEmpty() == true) return false
|
||||
if (geosite?.isNotEmpty() == true) return false
|
||||
if (domain?.isNotEmpty() == true) return false
|
||||
if (domain_suffix?.isNotEmpty() == true) return false
|
||||
if (domain_regex?.isNotEmpty() == true) return false
|
||||
if (domain_keyword?.isNotEmpty() == true) return false
|
||||
if (user_id?.isNotEmpty() == true) return false
|
||||
return true
|
||||
}
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
source ../buildScript/init/env_ndk.sh
|
||||
|
||||
[ $rel ] || sed -i "s/buildDate .*/buildDate := \"`date +'%Y%m%d'`\"/g" date.go
|
||||
[ $rel ] || sed -i "s/buildDate .*/buildDate := `date +'%Y%m%d'`/g" date.go
|
||||
|
||||
BUILD=".build"
|
||||
|
||||
|
||||
@ -1,14 +1,15 @@
|
||||
package libcore
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
var outdated string
|
||||
|
||||
func GetBuildTime() int64 {
|
||||
buildDate := "20230327"
|
||||
buildTime, _ := time.Parse("20060102", buildDate)
|
||||
buildDate := 20230330
|
||||
buildTime, _ := time.Parse("20060102", strconv.Itoa(buildDate))
|
||||
return buildTime.Unix()
|
||||
}
|
||||
|
||||
|
||||
@ -105,11 +105,11 @@ func verifyAPK() {
|
||||
for sc.Scan() {
|
||||
line := sc.Text()
|
||||
if strings.HasSuffix(line, "/base.apk") {
|
||||
apkPath = line[strings.Index(line, "/data/"):]
|
||||
apkPath = line[strings.Index(line, "/"):]
|
||||
break
|
||||
}
|
||||
}
|
||||
//
|
||||
|
||||
certs, err := apkverifier.ExtractCerts(apkPath, nil)
|
||||
if certs == nil || err != nil {
|
||||
outdated = fmt.Sprintf("verifyAPK: no certificate: %v", err)
|
||||
@ -128,7 +128,7 @@ func verifyAPK() {
|
||||
}
|
||||
|
||||
if !ok {
|
||||
outdated = fmt.Sprintf("verifyAPK: unknown signer")
|
||||
outdated = "verifyAPK: unknown signer"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user