Handle invalid proxy settings

master
Koitharu 2 years ago
parent 5ba6b81fac
commit 20f357cb12
Signed by: Koitharu
GPG Key ID: 676DEE768C17A9D7

@ -0,0 +1,5 @@
package org.koitharu.kotatsu.core.exceptions
import java.net.ProtocolException
class ProxyConfigException : ProtocolException("Wrong proxy configuration")

@ -15,6 +15,7 @@ import org.koitharu.kotatsu.alternatives.ui.AlternativesActivity
import org.koitharu.kotatsu.browser.BrowserActivity import org.koitharu.kotatsu.browser.BrowserActivity
import org.koitharu.kotatsu.browser.cloudflare.CloudFlareActivity import org.koitharu.kotatsu.browser.cloudflare.CloudFlareActivity
import org.koitharu.kotatsu.core.exceptions.CloudFlareProtectedException import org.koitharu.kotatsu.core.exceptions.CloudFlareProtectedException
import org.koitharu.kotatsu.core.exceptions.ProxyConfigException
import org.koitharu.kotatsu.core.exceptions.UnsupportedSourceException import org.koitharu.kotatsu.core.exceptions.UnsupportedSourceException
import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.prefs.AppSettings
import org.koitharu.kotatsu.core.ui.BaseActivity.BaseActivityEntryPoint import org.koitharu.kotatsu.core.ui.BaseActivity.BaseActivityEntryPoint
@ -25,6 +26,7 @@ import org.koitharu.kotatsu.parsers.exception.AuthRequiredException
import org.koitharu.kotatsu.parsers.exception.NotFoundException import org.koitharu.kotatsu.parsers.exception.NotFoundException
import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.Manga
import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.parsers.model.MangaSource
import org.koitharu.kotatsu.settings.SettingsActivity
import org.koitharu.kotatsu.settings.sources.auth.SourceAuthActivity import org.koitharu.kotatsu.settings.sources.auth.SourceAuthActivity
import java.security.cert.CertPathValidatorException import java.security.cert.CertPathValidatorException
import javax.net.ssl.SSLException import javax.net.ssl.SSLException
@ -74,6 +76,13 @@ class ExceptionResolver : ActivityResultCallback<TaggedActivityResult> {
false false
} }
is ProxyConfigException -> {
context?.run {
startActivity(SettingsActivity.newProxySettingsIntent(this))
}
false
}
is NotFoundException -> { is NotFoundException -> {
openInBrowser(e.url) openInBrowser(e.url)
false false
@ -144,6 +153,8 @@ class ExceptionResolver : ActivityResultCallback<TaggedActivityResult> {
is SSLException, is SSLException,
is CertPathValidatorException -> R.string.fix is CertPathValidatorException -> R.string.fix
is ProxyConfigException -> R.string.settings
else -> 0 else -> 0
} }

@ -1,8 +1,9 @@
package org.koitharu.kotatsu.core.network package org.koitharu.kotatsu.core.network
import okio.IOException
import org.koitharu.kotatsu.core.exceptions.ProxyConfigException
import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.prefs.AppSettings
import org.koitharu.kotatsu.core.util.ext.printStackTraceDebug import org.koitharu.kotatsu.core.util.ext.printStackTraceDebug
import java.io.IOException
import java.net.InetSocketAddress import java.net.InetSocketAddress
import java.net.Proxy import java.net.Proxy
import java.net.ProxySelector import java.net.ProxySelector
@ -31,9 +32,12 @@ class AppProxySelector(
val type = settings.proxyType val type = settings.proxyType
val address = settings.proxyAddress val address = settings.proxyAddress
val port = settings.proxyPort val port = settings.proxyPort
if (type == Proxy.Type.DIRECT || address.isNullOrEmpty() || port == 0) { if (type == Proxy.Type.DIRECT) {
return Proxy.NO_PROXY return Proxy.NO_PROXY
} }
if (address.isNullOrEmpty() || port == 0) {
throw ProxyConfigException()
}
cachedProxy?.let { cachedProxy?.let {
val addr = it.address() as? InetSocketAddress val addr = it.address() as? InetSocketAddress
if (addr != null && it.type() == type && addr.port == port && addr.hostString == address) { if (addr != null && it.type() == type && addr.port == port && addr.hostString == address) {

@ -7,6 +7,7 @@ import androidx.collection.arraySetOf
import coil.network.HttpException import coil.network.HttpException
import okio.FileNotFoundException import okio.FileNotFoundException
import okio.IOException import okio.IOException
import okio.ProtocolException
import org.acra.ktx.sendWithAcra import org.acra.ktx.sendWithAcra
import org.jsoup.HttpStatusException import org.jsoup.HttpStatusException
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
@ -17,6 +18,7 @@ import org.koitharu.kotatsu.core.exceptions.CloudFlareProtectedException
import org.koitharu.kotatsu.core.exceptions.EmptyHistoryException import org.koitharu.kotatsu.core.exceptions.EmptyHistoryException
import org.koitharu.kotatsu.core.exceptions.IncompatiblePluginException import org.koitharu.kotatsu.core.exceptions.IncompatiblePluginException
import org.koitharu.kotatsu.core.exceptions.NoDataReceivedException import org.koitharu.kotatsu.core.exceptions.NoDataReceivedException
import org.koitharu.kotatsu.core.exceptions.ProxyConfigException
import org.koitharu.kotatsu.core.exceptions.SyncApiException import org.koitharu.kotatsu.core.exceptions.SyncApiException
import org.koitharu.kotatsu.core.exceptions.TooManyRequestExceptions import org.koitharu.kotatsu.core.exceptions.TooManyRequestExceptions
import org.koitharu.kotatsu.core.exceptions.UnsupportedFileException import org.koitharu.kotatsu.core.exceptions.UnsupportedFileException
@ -43,7 +45,7 @@ fun Throwable.getDisplayMessage(resources: Resources): String = when (this) {
is CloudFlareBlockedException -> resources.getString(R.string.blocked_by_server_message) is CloudFlareBlockedException -> resources.getString(R.string.blocked_by_server_message)
is ActivityNotFoundException, is ActivityNotFoundException,
is UnsupportedOperationException, is UnsupportedOperationException,
-> resources.getString(R.string.operation_not_supported) -> resources.getString(R.string.operation_not_supported)
is TooManyRequestExceptions -> resources.getString(R.string.too_many_requests_message) is TooManyRequestExceptions -> resources.getString(R.string.too_many_requests_message)
is UnsupportedFileException -> resources.getString(R.string.text_file_not_supported) is UnsupportedFileException -> resources.getString(R.string.text_file_not_supported)
@ -51,14 +53,13 @@ fun Throwable.getDisplayMessage(resources: Resources): String = when (this) {
is FileNotFoundException -> resources.getString(R.string.file_not_found) is FileNotFoundException -> resources.getString(R.string.file_not_found)
is AccessDeniedException -> resources.getString(R.string.no_access_to_file) is AccessDeniedException -> resources.getString(R.string.no_access_to_file)
is EmptyHistoryException -> resources.getString(R.string.history_is_empty) is EmptyHistoryException -> resources.getString(R.string.history_is_empty)
is ProxyConfigException -> resources.getString(R.string.invalid_proxy_configuration)
is SyncApiException, is SyncApiException,
is ContentUnavailableException, is ContentUnavailableException -> message
-> message
is ParseException -> shortMessage is ParseException -> shortMessage
is UnknownHostException, is UnknownHostException,
is SocketTimeoutException, is SocketTimeoutException -> resources.getString(R.string.network_error)
-> resources.getString(R.string.network_error)
is NoDataReceivedException -> resources.getString(R.string.error_no_data_received) is NoDataReceivedException -> resources.getString(R.string.error_no_data_received)
is IncompatiblePluginException -> resources.getString(R.string.plugin_incompatible) is IncompatiblePluginException -> resources.getString(R.string.plugin_incompatible)
@ -80,7 +81,7 @@ fun Throwable.getDisplayIcon() = when (this) {
is CloudFlareProtectedException -> R.drawable.ic_bot_large is CloudFlareProtectedException -> R.drawable.ic_bot_large
is UnknownHostException, is UnknownHostException,
is SocketTimeoutException, is SocketTimeoutException,
-> R.drawable.ic_plug_large is ProtocolException -> R.drawable.ic_plug_large
is CloudFlareBlockedException -> R.drawable.ic_denied_large is CloudFlareBlockedException -> R.drawable.ic_denied_large

@ -63,10 +63,10 @@ class NetworkSettingsFragment :
val type = settings.proxyType val type = settings.proxyType
val address = settings.proxyAddress val address = settings.proxyAddress
val port = settings.proxyPort val port = settings.proxyPort
summary = if (type == Proxy.Type.DIRECT || address.isNullOrEmpty() || port == 0) { summary = when {
context.getString(R.string.disabled) type == Proxy.Type.DIRECT -> context.getString(R.string.disabled)
} else { address.isNullOrEmpty() || port == 0 -> context.getString(R.string.invalid_proxy_configuration)
"$address:$port" else -> "$address:$port"
} }
} }
} }

@ -112,6 +112,7 @@ class SettingsActivity :
ACTION_HISTORY -> UserDataSettingsFragment() ACTION_HISTORY -> UserDataSettingsFragment()
ACTION_TRACKER -> TrackerSettingsFragment() ACTION_TRACKER -> TrackerSettingsFragment()
ACTION_SOURCES -> SourcesSettingsFragment() ACTION_SOURCES -> SourcesSettingsFragment()
ACTION_PROXY -> ProxySettingsFragment()
ACTION_MANAGE_DOWNLOADS -> DownloadsSettingsFragment() ACTION_MANAGE_DOWNLOADS -> DownloadsSettingsFragment()
ACTION_SOURCE -> SourceSettingsFragment.newInstance( ACTION_SOURCE -> SourceSettingsFragment.newInstance(
MangaSource(intent.getStringExtra(EXTRA_SOURCE)), MangaSource(intent.getStringExtra(EXTRA_SOURCE)),
@ -144,6 +145,7 @@ class SettingsActivity :
private const val ACTION_SOURCES = "${BuildConfig.APPLICATION_ID}.action.MANAGE_SOURCES" private const val ACTION_SOURCES = "${BuildConfig.APPLICATION_ID}.action.MANAGE_SOURCES"
private const val ACTION_MANAGE_SOURCES = "${BuildConfig.APPLICATION_ID}.action.MANAGE_SOURCES_LIST" private const val ACTION_MANAGE_SOURCES = "${BuildConfig.APPLICATION_ID}.action.MANAGE_SOURCES_LIST"
private const val ACTION_MANAGE_DOWNLOADS = "${BuildConfig.APPLICATION_ID}.action.MANAGE_DOWNLOADS" private const val ACTION_MANAGE_DOWNLOADS = "${BuildConfig.APPLICATION_ID}.action.MANAGE_DOWNLOADS"
private const val ACTION_PROXY = "${BuildConfig.APPLICATION_ID}.action.MANAGE_PROXY"
private const val EXTRA_SOURCE = "source" private const val EXTRA_SOURCE = "source"
private const val HOST_ABOUT = "about" private const val HOST_ABOUT = "about"
private const val HOST_SYNC_SETTINGS = "sync-settings" private const val HOST_SYNC_SETTINGS = "sync-settings"
@ -162,6 +164,10 @@ class SettingsActivity :
Intent(context, SettingsActivity::class.java) Intent(context, SettingsActivity::class.java)
.setAction(ACTION_TRACKER) .setAction(ACTION_TRACKER)
fun newProxySettingsIntent(context: Context) =
Intent(context, SettingsActivity::class.java)
.setAction(ACTION_PROXY)
fun newHistorySettingsIntent(context: Context) = fun newHistorySettingsIntent(context: Context) =
Intent(context, SettingsActivity::class.java) Intent(context, SettingsActivity::class.java)
.setAction(ACTION_HISTORY) .setAction(ACTION_HISTORY)

@ -672,4 +672,5 @@
<string name="external_source">External/plugin</string> <string name="external_source">External/plugin</string>
<string name="plugin_incompatible">Incompatible plugin or internal error. Make sure you are using the latest version of the plugin and Kotatsu</string> <string name="plugin_incompatible">Incompatible plugin or internal error. Make sure you are using the latest version of the plugin and Kotatsu</string>
<string name="connection_ok">Connection is OK</string> <string name="connection_ok">Connection is OK</string>
<string name="invalid_proxy_configuration">Invalid proxy configuration</string>
</resources> </resources>

Loading…
Cancel
Save