Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ object DataStore : OnPreferenceDataStoreChangeListener {

var rulesGeositeUrl by configurationStore.string(Key.RULES_GEOSITE_URL) { "https://github.com/SagerNet/sing-geosite/releases/latest/download/geosite.db" }
var rulesGeoipUrl by configurationStore.string(Key.RULES_GEOIP_URL) { "https://github.com/SagerNet/sing-geoip/releases/latest/download/geoip.db" }
var rulesUpdateInterval by configurationStore.string(Key.RULES_UPDATE_INTERVAL) { "0" } // 默认为0,不自动更新
var rulesUpdateInterval by configurationStore.string(Key.RULES_UPDATE_INTERVAL) { "0" } // defaults to 0, no automatic update

// hopefully hashCode = mHandle doesn't change, currently this is true from KitKat to Nougat
private val userIndex by lazy { Binder.getCallingUserHandle().hashCode() }
Expand Down Expand Up @@ -320,7 +320,7 @@ object DataStore : OnPreferenceDataStoreChangeListener {
set(value) = configurationStore.putString("webdavPassword", value)

var webdavPath: String?
get() = configurationStore.getString("webdavPath") ?: "NekoBox" // 设置默认值
get() = configurationStore.getString("webdavPath") ?: "NekoBox" // set default value
set(value) = configurationStore.putString("webdavPath", value)

var globalMode by configurationStore.boolean(Key.GLOBAL_MODE)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ object ProfileManager {
)
val fuckedCountry = mutableListOf("cn:中国")
if (Locale.getDefault().country != Locale.CHINA.country) {
// 非中文用户
// non-Chinese users
fuckedCountry += "ir:Iran"
fuckedCountry += "ru:Russia"
}
Expand Down
20 changes: 10 additions & 10 deletions app/src/main/java/io/nekohasekai/sagernet/fmt/ConfigBuilder.kt
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ fun buildConfig(
rules = mutableListOf()
rule_set = mutableListOf()

// 添加并发拨号设置
// add concurrent dial setting
concurrent_dial = DataStore.concurrentDial
}

Expand Down Expand Up @@ -534,11 +534,11 @@ fun buildConfig(

val mainProxyTag = (if (buildSelector) TAG_PROXY else tagMap[proxy.id]) ?: TAG_PROXY

// 在应用用户规则之前检查全局模式
// check global mode before applying user rules
if (!forTest && DataStore.globalMode) {
// 全局模式下的规则处理
// rule handling in global mode

// 绕过内部网络(如果启用)
// bypass internal networks (if enabled)
if (DataStore.bypassLan) {
route.rules.add(Rule_DefaultOptions().apply {
ip_cidr = listOf(
Expand Down Expand Up @@ -568,7 +568,7 @@ fun buildConfig(

route.final_ = mainProxyTag
} else {
// 应用用户规则
// apply user rules
for (rule in extraRules) {
if (rule.packages.isNotEmpty()) {
PackageCache.awaitLoadSync()
Expand Down Expand Up @@ -601,10 +601,10 @@ fun buildConfig(

if (rule_set != null) generateRuleSet(rule_set, ruleSets)

// 存储ruleset标签和类型信息
// store ruleset tag and type info
val rulesetTags = mutableListOf<Pair<String, Boolean>>()

// 处理远程ruleset
// handle remote ruleset
if (rule.ruleset.isNotBlank()) {
val rulesetUrls = rule.ruleset.listByLineOrComma()
rulesetUrls.forEach { origUrl ->
Expand Down Expand Up @@ -665,7 +665,7 @@ fun buildConfig(

if (rule_set != null && rulesetTags.isNotEmpty()) {
for (tag in rule_set) {
// 只处理ruleset标签,且必须是非IP类型
// only handle ruleset tags, and they must be non-IP type
val tagInfo = rulesetTags.find { it.first == tag }
if (tag.startsWith("ruleset-") && tagInfo != null && !tagInfo.second) {
userDNSRuleList += DNSRule_DefaultOptions().apply {
Expand Down Expand Up @@ -749,7 +749,7 @@ fun buildConfig(
Toast.LENGTH_LONG
).show()
} else {
// block 改用新的写法
// block now uses the new approach
if (ruleObj.outbound == TAG_BLOCK) {
ruleObj.outbound = null
ruleObj.action = "reject"
Expand All @@ -761,7 +761,7 @@ fun buildConfig(
}
}

// rule_set tag 去重
// deduplicate rule_set tags
if (route.rule_set != null) {
route.rule_set = route.rule_set.distinctBy { it.tag }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import io.nekohasekai.sagernet.ktx.urlSafe
import io.nekohasekai.sagernet.ktx.unUrlSafe
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull

// URI 格式: snell://base64(psk)@server:port?version=4&obfs-mode=http&obfs-host=bing.com&reuse=true&network=tcp#name
// URI format: snell://base64(psk)@server:port?version=4&obfs-mode=http&obfs-host=bing.com&reuse=true&network=tcp#name
fun parseSnell(url: String): SnellBean {
val link = url.replace("snell://", "https://").toHttpUrlOrNull()
?: error("Invalid snell URL")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,63 +14,65 @@
public class TrojanGoBean extends AbstractBean {

/**
* Trojan 的密码。
* 不可省略,不能为空字符串,不建议含有非 ASCII 可打印字符。
* 必须使用 encodeURIComponent 编码。
* Trojan password.
* Must not be omitted or empty; non-ASCII printable characters are discouraged.
* Must be encoded with encodeURIComponent.
*/
public String password;

/**
* 自定义 TLS SNI
* 省略时默认与 trojan-host 同值。不得为空字符串。
* Custom TLS SNI.
* Defaults to the same value as trojan-host when omitted. Must not be empty.
* <p>
* 必须使用 encodeURIComponent 编码。
* Must be encoded with encodeURIComponent.
*/
public String sni;

/**
* 传输类型。
* 省略时默认为 original,但不可为空字符串。
* 目前可选值只有 original 和 ws,未来可能会有 h2、h2+ws 等取值。
* Transport type.
* Defaults to "original" when omitted, but must not be an empty string.
* Currently only "original" and "ws" are valid; future values may include h2, h2+ws, etc.
* <p>
* 当取值为 original 时,使用原始 Trojan 传输方式,无法方便通过 CDN
* 当取值为 ws 时,使用 wss 作为传输层。
* "original" uses the raw Trojan transport, which is not easily served via a CDN.
* "ws" uses wss as the transport layer.
*/
public String type;

/**
* 自定义 HTTP Host 头。
* 可以省略,省略时值同 trojan-host
* 可以为空字符串,但可能带来非预期情形。
* Custom HTTP Host header.
* May be omitted; defaults to trojan-host when omitted.
* May be an empty string, but that can lead to unexpected behavior.
* <p>
* 警告:若你的端口非标准端口(不是 80 / 443),RFC 标准规定 Host 应在主机名后附上端口号,例如 example.com:44333。至于是否遵守,请自行斟酌。
* Warning: if your port is non-standard (not 80 / 443), the RFC requires the Host to
* include the port after the hostname, e.g. example.com:44333. Whether to follow this
* is up to you.
* <p>
* 必须使用 encodeURIComponent 编码。
* Must be encoded with encodeURIComponent.
*/
public String host;

/**
* 当传输类型 type ws、h2、h2+ws 时,此项有效。
* 不可省略,不可为空。
* 必须以 / 开头。
* 可以使用 URL 中的 & # ? 等字符,但应当是合法的 URL 路径。
* Effective when the transport type is ws, h2, or h2+ws.
* Must not be omitted or empty.
* Must start with "/".
* May use URL characters such as & # ?, but must be a valid URL path.
* <p>
* 必须使用 encodeURIComponent 编码。
* Must be encoded with encodeURIComponent.
*/
public String path;

/**
* 用于保证 Trojan 流量密码学安全的加密层。
* 可省略,默认为 none,即不使用加密。
* 不可以为空字符串。
* Encryption layer used to cryptographically secure Trojan traffic.
* May be omitted; defaults to "none" (no encryption).
* Must not be an empty string.
* <p>
* 必须使用 encodeURIComponent 编码。
* Must be encoded with encodeURIComponent.
* <p>
* 使用 Shadowsocks 算法进行流量加密时,其格式为:
* When using the Shadowsocks algorithm for traffic encryption, the format is:
* <p>
* ss;method:password
* <p>
* 其中 ss 是固定内容,method 是加密方法,必须为下列之一:
* where "ss" is fixed and "method" is the encryption method, which must be one of:
* <p>
* aes-128-gcm
* aes-256-gcm
Expand All @@ -79,8 +81,8 @@ public class TrojanGoBean extends AbstractBean {
public String encryption;

/**
* 额外的插件选项。本字段保留。
* 可省略,但不可以为空字符串。
* Extra plugin options. This field is reserved.
* May be omitted, but must not be an empty string.
*/
// not used in NB4A
public String plugin;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ public void initializeDefaultValues() {

if (JavaUtil.isNullOrBlank(mKcpSeed)) mKcpSeed = "";
if (JavaUtil.isNullOrBlank(headerType)) headerType = "none";
// kcpMtukcpTti kcpCwndMultiplier 保持 null,不设置默认值
// kcpMtu, kcpTti and kcpCwndMultiplier stay null, no default values set
}

@Override
Expand Down Expand Up @@ -265,7 +265,7 @@ public void deserialize(ByteBufferInput input) {
case "grpc": {
path = input.readString();
if (version < 4) {
// 解决老版本数据的读取问题
// fix the reading issue with old version data
input.readString();
input.readString();
}
Expand Down Expand Up @@ -327,13 +327,13 @@ public void deserialize(ByteBufferInput input) {
}
}
} else if (version == 0) {
// 从老版本升级上来但是 version == 0, 可能有 enableECH 也可能没有,需要做判断
int position = input.getByteBuffer().position(); // 当前位置
// upgraded from an old version but version == 0; may or may not have enableECH, so a check is needed
int position = input.getByteBuffer().position(); // current position

boolean tmpEnableECH = input.readBoolean();
int tmpPacketEncoding = input.readInt();

input.setPosition(position); // 读后归位
input.setPosition(position); // reset position after reading

if (tmpPacketEncoding != 1 && tmpPacketEncoding != 2) {
enableECH = tmpEnableECH;
Expand All @@ -342,7 +342,7 @@ public void deserialize(ByteBufferInput input) {
input.readBoolean();
echConfig = input.readString();
}
} // 否则后一位就是 packetEncoding
} // otherwise the next field is packetEncoding
}

packetEncoding = input.readInt();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ fun StandardV2RayBean.parseDuckSoft(url: HttpUrl) {
}
}

// 不确定是谁的格式
// not sure whose format this is
private fun tryResolveVmess4Kitsunebi(server: String): VMessBean {
// vmess://YXV0bzo1YWY1ZDBlYy02ZWEwLTNjNDMtOTNkYi1jYTMwMDg1MDNiZGJAMTgzLjIzMi41Ni4xNjE6MTIwMg
// ?remarks=*%F0%9F%87%AF%F0%9F%87%B5JP%20-355%20TG@moon365free&obfsParam=%7B%22Host%22:%22183.232.56.161%22%7D&path=/v2ray&obfs=websocket&alterId=0
Expand Down Expand Up @@ -772,7 +772,7 @@ fun buildSingBoxOutboundTLS(bean: StandardV2RayBean): OutboundTLSOptions? {
insecure = bean.allowInsecure || DataStore.globalAllowInsecure
if (bean.sni.isNotBlank()) server_name = bean.sni
if (bean.alpn.isNotBlank()) {
// 当传输协议为WebSocket时,过滤掉h2和h3
// when the transport protocol is WebSocket, filter out h2 and h3
val alpnList = bean.alpn.listByLineOrComma()
if (bean.type == "ws") {
val filtered = alpnList.filter { it == "http/1.1" }
Expand Down
4 changes: 2 additions & 2 deletions app/src/main/java/io/nekohasekai/sagernet/group/RawUpdater.kt
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ object RawUpdater : GroupUpdater() {
subscription.subscriptionUserinfo =
Util.getStringBox(response.getHeader("Subscription-Userinfo"))

// 修改默认名字
// modify the default name
if (proxyGroup.name?.startsWith("Subscription #") == true) {
var remoteName = Util.getStringBox(response.getHeader("content-disposition"))
if (remoteName.isNotBlank()) {
Expand Down Expand Up @@ -182,7 +182,7 @@ object RawUpdater : GroupUpdater() {
if (toReplace.contains(name)) {
val entity = toReplace[name]!!
val existsBean = entity.requireBean()
// 更新订阅,保留自定义覆写设置
// update subscription, preserving custom override settings
bean.customOutboundJson = existsBean.customOutboundJson
bean.customConfigJson = existsBean.customConfigJson
when {
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/java/io/nekohasekai/sagernet/ktx/Formats.kt
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ fun JSONObject.getBool(name: String): Boolean? {
}


// 重名了喵
// name collision, nya
fun JSONObject.getIntNya(name: String): Int? {
return try {
getInt(name)
Expand Down
Loading
Loading