mirror of
https://github.com/mihonapp/mihon.git
synced 2025-08-25 23:51:32 +02:00
Compare commits
5 Commits
1bff2ffdf7
...
f847390354
Author | SHA1 | Date | |
---|---|---|---|
|
f847390354 | ||
|
64503fcec9 | ||
|
d6b58e9267 | ||
|
9ffb16ed9f | ||
|
8f63e82b71 |
@@ -313,6 +313,7 @@ object SettingsAdvancedScreen : SearchableSettings {
|
||||
),
|
||||
Preference.PreferenceItem.TextPreference(
|
||||
title = stringResource(MR.strings.pref_proxy_configuration),
|
||||
subtitle = stringResource(MR.strings.pref_proxy_configuration_subtitle),
|
||||
onClick = { showProxyDialog = true },
|
||||
),
|
||||
Preference.PreferenceItem.EditTextPreference(
|
||||
@@ -591,57 +592,53 @@ private fun ProxyConfigDialog(
|
||||
isError = !port.text.isDigitsOnly(),
|
||||
)
|
||||
}
|
||||
if (proxyTypes[checked] != ProxyType.SOCKS) {
|
||||
OutlinedTextField(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
value = username,
|
||||
onValueChange = {
|
||||
newProxy.username = it.text
|
||||
proxyChanged = newProxy != proxy
|
||||
OutlinedTextField(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
value = username,
|
||||
onValueChange = {
|
||||
newProxy.username = it.text
|
||||
proxyChanged = newProxy != proxy
|
||||
|
||||
username = it
|
||||
},
|
||||
label = { Text(text = stringResource(MR.strings.username)) },
|
||||
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next),
|
||||
singleLine = true,
|
||||
enabled = proxyTypes[checked] != ProxyType.SOCKS,
|
||||
)
|
||||
var hidePassword by remember { mutableStateOf(true) }
|
||||
OutlinedTextField(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
value = password,
|
||||
onValueChange = {
|
||||
newProxy.password = it.text
|
||||
proxyChanged = newProxy != proxy
|
||||
username = it
|
||||
},
|
||||
label = { Text(text = stringResource(MR.strings.username)) },
|
||||
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next),
|
||||
singleLine = true,
|
||||
)
|
||||
var hidePassword by remember { mutableStateOf(true) }
|
||||
OutlinedTextField(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
value = password,
|
||||
onValueChange = {
|
||||
newProxy.password = it.text
|
||||
proxyChanged = newProxy != proxy
|
||||
|
||||
password = it
|
||||
},
|
||||
label = { Text(text = stringResource(MR.strings.password)) },
|
||||
trailingIcon = {
|
||||
IconButton(onClick = { hidePassword = !hidePassword }) {
|
||||
Icon(
|
||||
imageVector = if (hidePassword) {
|
||||
Icons.Filled.Visibility
|
||||
} else {
|
||||
Icons.Filled.VisibilityOff
|
||||
},
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
},
|
||||
visualTransformation = if (hidePassword) {
|
||||
PasswordVisualTransformation()
|
||||
} else {
|
||||
VisualTransformation.None
|
||||
},
|
||||
keyboardOptions = KeyboardOptions(
|
||||
keyboardType = KeyboardType.Password,
|
||||
imeAction = ImeAction.Done,
|
||||
),
|
||||
singleLine = true,
|
||||
enabled = proxyTypes[checked] != ProxyType.SOCKS,
|
||||
)
|
||||
}
|
||||
password = it
|
||||
},
|
||||
label = { Text(text = stringResource(MR.strings.password)) },
|
||||
trailingIcon = {
|
||||
IconButton(onClick = { hidePassword = !hidePassword }) {
|
||||
Icon(
|
||||
imageVector = if (hidePassword) {
|
||||
Icons.Filled.Visibility
|
||||
} else {
|
||||
Icons.Filled.VisibilityOff
|
||||
},
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
},
|
||||
visualTransformation = if (hidePassword) {
|
||||
PasswordVisualTransformation()
|
||||
} else {
|
||||
VisualTransformation.None
|
||||
},
|
||||
keyboardOptions = KeyboardOptions(
|
||||
keyboardType = KeyboardType.Password,
|
||||
imeAction = ImeAction.Done,
|
||||
),
|
||||
singleLine = true,
|
||||
)
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
|
@@ -12,6 +12,7 @@ import okhttp3.brotli.BrotliInterceptor
|
||||
import okhttp3.logging.HttpLoggingInterceptor
|
||||
import java.io.File
|
||||
import java.util.concurrent.TimeUnit
|
||||
import java.net.Proxy.Type as ProxyType
|
||||
|
||||
class NetworkHelper(
|
||||
private val context: Context,
|
||||
@@ -71,8 +72,18 @@ class NetworkHelper(
|
||||
if (proxy.enabled) {
|
||||
builder.proxy(proxy.getProxy() ?: Proxy.getBlackHoleProxy(context))
|
||||
|
||||
proxy.getAuthenticator()?.let { proxyAuthenticator ->
|
||||
builder.proxyAuthenticator(proxyAuthenticator)
|
||||
when (proxy.proxyType) {
|
||||
ProxyType.HTTP -> {
|
||||
proxy.getOkhttpAuthenticator()?.let { proxyAuthenticator ->
|
||||
builder.proxyAuthenticator(proxyAuthenticator)
|
||||
}
|
||||
}
|
||||
|
||||
ProxyType.SOCKS -> {
|
||||
proxy.setSocksAuthentication()
|
||||
}
|
||||
|
||||
else -> Unit
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -12,8 +12,10 @@ import tachiyomi.i18n.MR
|
||||
import java.net.Inet6Address
|
||||
import java.net.InetAddress
|
||||
import java.net.InetSocketAddress
|
||||
import java.net.PasswordAuthentication
|
||||
import java.net.Proxy.Type
|
||||
import java.net.UnknownHostException
|
||||
import java.net.Authenticator as JavaAuthenticator
|
||||
import java.net.Proxy as JavaProxy
|
||||
|
||||
@Serializable
|
||||
@@ -33,7 +35,7 @@ data class Proxy(
|
||||
}
|
||||
}
|
||||
|
||||
fun getAuthenticator(): Authenticator? {
|
||||
fun getOkhttpAuthenticator(): Authenticator? {
|
||||
if (username?.isBlank() == true && password?.isBlank() == true) return null
|
||||
return Authenticator { _, response ->
|
||||
val credential: String = Credentials.basic(username ?: "", password ?: "")
|
||||
@@ -43,7 +45,35 @@ data class Proxy(
|
||||
}
|
||||
}
|
||||
|
||||
fun setSocksAuthentication() {
|
||||
if (username?.isBlank() == true && password?.isBlank() == true) return
|
||||
|
||||
System.setProperty("java.net.socks.username", username ?: "")
|
||||
System.setProperty("java.net.socks.password", password ?: "")
|
||||
|
||||
JavaAuthenticator.setDefault(
|
||||
object : JavaAuthenticator() {
|
||||
override fun getPasswordAuthentication(): PasswordAuthentication? {
|
||||
return if (
|
||||
requestingHost.equals(host, ignoreCase = true) &&
|
||||
requestingPort == port
|
||||
) {
|
||||
PasswordAuthentication(
|
||||
username ?: "",
|
||||
password?.toCharArray() ?: "".toCharArray(),
|
||||
)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val BLACK_HOLE_HOST = "100::"
|
||||
private const val BLACK_HOLE_PORT = 65534
|
||||
|
||||
suspend fun testHostValidity(host: String): Boolean = withIOContext {
|
||||
return@withIOContext try {
|
||||
InetAddress.getByName(host)
|
||||
@@ -59,7 +89,7 @@ data class Proxy(
|
||||
*/
|
||||
fun getBlackHoleProxy(context: Context): JavaProxy {
|
||||
context.toast(MR.strings.proxy_host_invalid_warning)
|
||||
return JavaProxy(Type.SOCKS, InetSocketAddress(Inet6Address.getByName("100::"), 1))
|
||||
return JavaProxy(Type.SOCKS, InetSocketAddress(Inet6Address.getByName(BLACK_HOLE_HOST), BLACK_HOLE_PORT))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -584,6 +584,7 @@
|
||||
<string name="pref_verbose_logging_summary">Print verbose logs to system log (reduces app performance)</string>
|
||||
<string name="pref_debug_info">Debug info</string>
|
||||
<string name="pref_proxy_configuration">Proxy configuration</string>
|
||||
<string name="pref_proxy_configuration_subtitle">Webview will not use this proxy</string>
|
||||
<string name="pref_enable_proxy">Enable Proxy</string>
|
||||
<string name="port">Port</string>
|
||||
<string name="host">Host</string>
|
||||
|
Reference in New Issue
Block a user