Fix GitHub authorization and clean up code
This commit is contained in:
1 parent
b1afe9bcd1
commit
fded0fd08d
20 files changed
+33
-125
No files matched your search
@@ -55,11 +55,12 @@ import com.hippo.ehviewer.dailycheck.showEventNotification
|
||||
import com.hippo.ehviewer.dailycheck.today
|
||||
import com.hippo.ehviewer.util.AppConfig
|
||||
import com.hippo.ehviewer.util.ReadableTime
|
||||
import com.hippo.ehviewer.util.StatusCodeException
|
||||
import com.hippo.ehviewer.util.bodyAsUtf8Text
|
||||
import com.hippo.ehviewer.util.ensureSuccess
|
||||
import eu.kanade.tachiyomi.util.system.logcat
|
||||
import io.ktor.client.statement.HttpStatement
|
||||
import io.ktor.client.statement.bodyAsChannel
|
||||
import io.ktor.http.HttpStatusCode
|
||||
import io.ktor.utils.io.pool.DirectByteBufferPool
|
||||
import io.ktor.utils.io.pool.useInstance
|
||||
import java.io.File
|
||||
@@ -96,7 +97,7 @@ fun Either<String, ByteBuffer>.saveParseError(e: Throwable) {
|
||||
}
|
||||
}
|
||||
|
||||
fun rethrowExactly(code: Int, body: Either<String, ByteBuffer>, e: Throwable): Nothing {
|
||||
fun rethrowExactly(status: HttpStatusCode, body: Either<String, ByteBuffer>, e: Throwable): Nothing {
|
||||
// Don't translate coroutine cancellation
|
||||
if (e is CancellationException) throw e
|
||||
|
||||
@@ -124,9 +125,7 @@ fun rethrowExactly(code: Int, body: Either<String, ByteBuffer>, e: Throwable): N
|
||||
}
|
||||
|
||||
// Check bad response code
|
||||
if (code >= 400) {
|
||||
throw StatusCodeException(code)
|
||||
}
|
||||
status.ensureSuccess()
|
||||
|
||||
if (e is ParseException || e is SerializationException) {
|
||||
body.onLeft { if ("<" !in it) throw EhException(it) }
|
||||
@@ -151,7 +150,7 @@ suspend inline fun <T> HttpStatement.fetchUsingAsText(crossinline block: suspend
|
||||
runSuspendCatching {
|
||||
block(body)
|
||||
}.onFailure {
|
||||
rethrowExactly(response.status.value, body.left(), it)
|
||||
rethrowExactly(response.status, body.left(), it)
|
||||
}.getOrThrow()
|
||||
}
|
||||
|
||||
@@ -163,7 +162,7 @@ suspend inline fun <T> HttpStatement.fetchUsingAsByteBuffer(crossinline block: s
|
||||
block(buffer)
|
||||
}.onFailure {
|
||||
buffer.rewind()
|
||||
rethrowExactly(response.status.value, buffer.right(), it)
|
||||
rethrowExactly(response.status, buffer.right(), it)
|
||||
}.getOrThrow()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import com.hippo.ehviewer.EhApplication.Companion.ktorClient
|
||||
import com.hippo.ehviewer.EhApplication.Companion.noRedirectKtorClient
|
||||
import com.hippo.ehviewer.Settings
|
||||
import com.hippo.ehviewer.util.bodyAsUtf8Text
|
||||
import com.hippo.ehviewer.util.ensureSuccess
|
||||
import eu.kanade.tachiyomi.util.system.logcat
|
||||
import io.ktor.client.request.HttpRequestBuilder
|
||||
import io.ktor.client.request.forms.FormDataContent
|
||||
@@ -45,7 +46,11 @@ import okio.BufferedSource
|
||||
|
||||
inline fun JsonObjectBuilder.array(name: String, builder: JsonArrayBuilder.() -> Unit) = put(name, buildJsonArray(builder))
|
||||
|
||||
suspend inline fun <reified T> HttpStatement.executeAndParseAs() = executeSafely { it.bodyAsUtf8Text().parseAs<T>() }
|
||||
suspend inline fun <reified T> HttpStatement.executeAndParseAs() = executeSafely {
|
||||
it.status.ensureSuccess()
|
||||
it.bodyAsUtf8Text().parseAs<T>()
|
||||
}
|
||||
|
||||
inline fun <reified T> BufferedSource.parseAs(): T = json.decodeFromBufferedSource(this)
|
||||
inline fun <reified T> String.parseAs(): T = json.decodeFromString(this)
|
||||
|
||||
|
||||
@@ -24,14 +24,13 @@ import com.hippo.ehviewer.R
|
||||
import com.hippo.ehviewer.client.data.TagNamespace
|
||||
import com.hippo.ehviewer.util.AppConfig
|
||||
import com.hippo.ehviewer.util.FileUtils
|
||||
import com.hippo.ehviewer.util.StatusCodeException
|
||||
import com.hippo.ehviewer.util.copyTo
|
||||
import com.hippo.ehviewer.util.ensureSuccess
|
||||
import com.hippo.ehviewer.util.sha1
|
||||
import eu.kanade.tachiyomi.util.system.logcat
|
||||
import io.ktor.client.HttpClient
|
||||
import io.ktor.client.request.prepareGet
|
||||
import io.ktor.client.statement.bodyAsChannel
|
||||
import io.ktor.http.isSuccess
|
||||
import java.io.File
|
||||
import java.nio.charset.StandardCharsets
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
@@ -143,11 +142,8 @@ object EhTagDatabase : CoroutineScope {
|
||||
private suspend fun save(client: HttpClient, url: String, file: File) {
|
||||
runCatching {
|
||||
client.prepareGet(url).executeSafely {
|
||||
if (it.status.isSuccess()) {
|
||||
it.bodyAsChannel().copyTo(file)
|
||||
} else {
|
||||
throw StatusCodeException(it.status.value)
|
||||
}
|
||||
it.status.ensureSuccess()
|
||||
it.bodyAsChannel().copyTo(file)
|
||||
}
|
||||
}.onFailure {
|
||||
file.delete()
|
||||
|
||||
@@ -6,10 +6,10 @@ import com.hippo.ehviewer.Settings
|
||||
import com.hippo.ehviewer.client.executeAndParseAs
|
||||
import com.hippo.ehviewer.client.executeSafely
|
||||
import com.hippo.ehviewer.util.copyTo
|
||||
import com.hippo.ehviewer.util.ensureSuccess
|
||||
import io.ktor.client.request.header
|
||||
import io.ktor.client.request.prepareGet
|
||||
import io.ktor.client.statement.bodyAsChannel
|
||||
import io.ktor.client.statement.bodyAsText
|
||||
import io.ktor.utils.io.jvm.javaio.toInputStream
|
||||
import java.io.File
|
||||
import java.util.zip.ZipInputStream
|
||||
@@ -17,10 +17,10 @@ import kotlin.time.Duration.Companion.days
|
||||
import kotlinx.datetime.Clock
|
||||
import kotlinx.datetime.Instant
|
||||
import moe.tarsin.coroutines.runSuspendCatching
|
||||
import org.json.JSONObject
|
||||
import tachiyomi.data.release.GithubArtifacts
|
||||
import tachiyomi.data.release.GithubCommitComparison
|
||||
import tachiyomi.data.release.GithubRelease
|
||||
import tachiyomi.data.release.GithubRepo
|
||||
import tachiyomi.data.release.GithubWorkflowRuns
|
||||
|
||||
private const val API_URL = "https://api.github.com/repos/${BuildConfig.REPO_NAME}"
|
||||
@@ -35,7 +35,7 @@ object AppUpdater {
|
||||
Settings.lastUpdateTime = now.epochSeconds
|
||||
if (Settings.useCIUpdateChannel) {
|
||||
val curSha = BuildConfig.COMMIT_SHA
|
||||
val branch = ghStatement(API_URL).executeSafely { JSONObject(it.bodyAsText()).getString("default_branch") }
|
||||
val branch = ghStatement(API_URL).executeAndParseAs<GithubRepo>().defaultBranch
|
||||
val workflowRunsUrl = "$API_URL/actions/workflows/ci.yml/runs?branch=$branch&event=push&status=success&per_page=1"
|
||||
val workflowRun = ghStatement(workflowRunsUrl).executeAndParseAs<GithubWorkflowRuns>().workflowRuns[0]
|
||||
val shortSha = workflowRun.headSha.take(7)
|
||||
@@ -68,6 +68,7 @@ object AppUpdater {
|
||||
|
||||
suspend fun downloadUpdate(url: String, file: File) =
|
||||
ghStatement(url).executeSafely { response ->
|
||||
response.status.ensureSuccess()
|
||||
if (url.endsWith("zip")) {
|
||||
response.bodyAsChannel().toInputStream().use { stream ->
|
||||
ZipInputStream(stream).use { zip ->
|
||||
@@ -84,14 +85,14 @@ object AppUpdater {
|
||||
}
|
||||
|
||||
private suspend inline fun ghStatement(url: String) = ktorClient.prepareGet(url) {
|
||||
header("Authorization", GithubTokenParts.joinToString("_"))
|
||||
header("Authorization", GithubTokenParts.joinToString("_", prefix = "Bearer "))
|
||||
}
|
||||
|
||||
private val GithubTokenParts = arrayOf(
|
||||
"github",
|
||||
"pat",
|
||||
"11A4H2ACI04oacouUsibSx",
|
||||
"QYqH5WhdRjJUSmezj3vex9sQLZC8vSrL4VXPxDcwfhcWLQFH6H3L0tDYupr",
|
||||
"11A4H2ACI0XXTRsYkt1Mps",
|
||||
"uJ5n8UbLv20j6Ue4k1x25Z7u63EaCdDNYooxSeI4GJaQYKXWDZEtTmDVwnh",
|
||||
)
|
||||
|
||||
data class Release(
|
||||
|
||||
@@ -39,12 +39,6 @@ private fun getReadableStringInternal(e: Throwable) = when (e) {
|
||||
is MalformedURLException -> appCtx.getString(R.string.error_invalid_url)
|
||||
is SocketTimeoutException -> appCtx.getString(R.string.error_timeout)
|
||||
is UnknownHostException -> appCtx.getString(R.string.error_unknown_host)
|
||||
is StatusCodeException -> buildString {
|
||||
append(appCtx.getString(R.string.error_bad_status_code, e.responseCode))
|
||||
if (e.isIdentifiedResponseCode) {
|
||||
append(", ").append(e.message)
|
||||
}
|
||||
}
|
||||
is ProtocolException -> if (e.message!!.startsWith("Too many follow-up requests:")) {
|
||||
appCtx.getString(R.string.error_redirection)
|
||||
} else {
|
||||
|
||||
@@ -2,6 +2,8 @@ package com.hippo.ehviewer.util
|
||||
|
||||
import io.ktor.client.call.body
|
||||
import io.ktor.client.statement.HttpResponse
|
||||
import io.ktor.http.HttpStatusCode
|
||||
import io.ktor.http.isSuccess
|
||||
import io.ktor.utils.io.charsets.decode
|
||||
import io.ktor.utils.io.core.ByteReadPacket
|
||||
import java.nio.charset.CodingErrorAction
|
||||
@@ -15,3 +17,7 @@ suspend fun HttpResponse.bodyAsUtf8Text(): String {
|
||||
|
||||
return decoder.decode(input)
|
||||
}
|
||||
|
||||
fun HttpStatusCode.ensureSuccess() {
|
||||
if (!isSuccess()) throw Exception(toString())
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.hippo.ehviewer.util
|
||||
|
||||
import android.util.SparseArray
|
||||
import com.hippo.ehviewer.R
|
||||
import splitties.init.appCtx
|
||||
|
||||
class StatusCodeException(val responseCode: Int) : Exception() {
|
||||
override val message: String = ERROR_MESSAGE_ARRAY[responseCode, DEFAULT_ERROR_MESSAGE]
|
||||
|
||||
val isIdentifiedResponseCode: Boolean
|
||||
get() = DEFAULT_ERROR_MESSAGE != message
|
||||
|
||||
override fun getLocalizedMessage(): String = message
|
||||
|
||||
companion object {
|
||||
private val ERROR_MESSAGE_ARRAY = SparseArray<String>(24)
|
||||
private const val DEFAULT_ERROR_MESSAGE = "Error response code"
|
||||
|
||||
init {
|
||||
val resources = appCtx.resources
|
||||
ERROR_MESSAGE_ARRAY.append(400, resources.getString(R.string.error_status_code_400))
|
||||
ERROR_MESSAGE_ARRAY.append(401, resources.getString(R.string.error_status_code_401))
|
||||
ERROR_MESSAGE_ARRAY.append(402, resources.getString(R.string.error_status_code_402))
|
||||
ERROR_MESSAGE_ARRAY.append(403, resources.getString(R.string.error_status_code_403))
|
||||
ERROR_MESSAGE_ARRAY.append(404, resources.getString(R.string.error_status_code_404))
|
||||
ERROR_MESSAGE_ARRAY.append(405, resources.getString(R.string.error_status_code_405))
|
||||
ERROR_MESSAGE_ARRAY.append(406, resources.getString(R.string.error_status_code_406))
|
||||
ERROR_MESSAGE_ARRAY.append(407, resources.getString(R.string.error_status_code_407))
|
||||
ERROR_MESSAGE_ARRAY.append(408, resources.getString(R.string.error_status_code_408))
|
||||
ERROR_MESSAGE_ARRAY.append(409, resources.getString(R.string.error_status_code_409))
|
||||
ERROR_MESSAGE_ARRAY.append(410, resources.getString(R.string.error_status_code_410))
|
||||
ERROR_MESSAGE_ARRAY.append(411, resources.getString(R.string.error_status_code_411))
|
||||
ERROR_MESSAGE_ARRAY.append(412, resources.getString(R.string.error_status_code_412))
|
||||
ERROR_MESSAGE_ARRAY.append(413, resources.getString(R.string.error_status_code_413))
|
||||
ERROR_MESSAGE_ARRAY.append(414, resources.getString(R.string.error_status_code_414))
|
||||
ERROR_MESSAGE_ARRAY.append(415, resources.getString(R.string.error_status_code_415))
|
||||
ERROR_MESSAGE_ARRAY.append(416, resources.getString(R.string.error_status_code_416))
|
||||
ERROR_MESSAGE_ARRAY.append(417, resources.getString(R.string.error_status_code_417))
|
||||
ERROR_MESSAGE_ARRAY.append(500, resources.getString(R.string.error_status_code_500))
|
||||
ERROR_MESSAGE_ARRAY.append(501, resources.getString(R.string.error_status_code_501))
|
||||
ERROR_MESSAGE_ARRAY.append(502, resources.getString(R.string.error_status_code_502))
|
||||
ERROR_MESSAGE_ARRAY.append(503, resources.getString(R.string.error_status_code_503))
|
||||
ERROR_MESSAGE_ARRAY.append(504, resources.getString(R.string.error_status_code_504))
|
||||
ERROR_MESSAGE_ARRAY.append(505, resources.getString(R.string.error_status_code_505))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,11 @@ import com.hippo.ehviewer.util.AppConfig
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class GithubRepo(
|
||||
@SerialName("default_branch") val defaultBranch: String,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class GithubWorkflowRuns(
|
||||
@SerialName("workflow_runs") val workflowRuns: List<GithubWorkflowRun>,
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
<string name="text_is_empty">Der Text wird nicht eingegeben</string>
|
||||
<string name="waring">Achtung</string>
|
||||
<string name="invalid_download_location">Der Downloadpfad ist nicht verfügbar. Geh zu die Einstellungen und stelle einen neue Pfad fest.</string>
|
||||
<string name="error_bad_status_code">Inkorrekter Statuscode: %d</string>
|
||||
<string name="error_timeout">Timeout</string>
|
||||
<string name="error_unknown_host">Unbekannter Hostcomputer</string>
|
||||
<string name="error_redirection">Zu viele Umleitungen</string>
|
||||
|
||||
@@ -39,7 +39,6 @@
|
||||
|
||||
<string name="invalid_download_location">Parece que la ubicación de descarga no está disponible. Establece la ubicación en Configuración.</string>
|
||||
|
||||
<string name="error_bad_status_code">Bad status code: %d</string>
|
||||
<string name="error_timeout">Sin tiempo</string>
|
||||
<string name="error_unknown_host">Host desconocido</string>
|
||||
<string name="error_redirection">Demasiadas redirecciones</string>
|
||||
|
||||
@@ -39,7 +39,6 @@
|
||||
|
||||
<string name="invalid_download_location">La location de téléchargement actuelle n\'est pas disponible. Choissez-en une à nouveau dans les Paramétres.</string>
|
||||
|
||||
<string name="error_bad_status_code">Code d\'état inconnu : %d</string>
|
||||
<string name="error_timeout">Time-out</string>
|
||||
<string name="error_unknown_host">Hôte inconnu</string>
|
||||
<string name="error_redirection">Trop de redirections</string>
|
||||
|
||||
@@ -37,7 +37,6 @@
|
||||
|
||||
<string name="invalid_download_location">ダウンロードパスは現在利用できません。ダウンロードパスを設定してください。</string>
|
||||
|
||||
<string name="error_bad_status_code">無効なステータスコード:%d</string>
|
||||
<string name="error_timeout">タイムアウト</string>
|
||||
<string name="error_unknown_host">不明なホスト</string>
|
||||
<string name="error_redirection">リダイレクトが多すぎます</string>
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
<string name="clipboard_gallery_url_snack_message">클립보드에 갤러리 주소가 있습니다.</string>
|
||||
<string name="clipboard_gallery_url_snack_action">보기</string>
|
||||
|
||||
<string name="error_bad_status_code">비정상 상태 코드: %d</string>
|
||||
<string name="error_timeout">시간 초과</string>
|
||||
<string name="error_unknown_host">알 수 없는 호스트</string>
|
||||
<string name="error_redirection">너무 많은 서버 리디렉션</string>
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
<string name="text_is_empty">Tekst tom</string>
|
||||
<string name="waring">Advarsel</string>
|
||||
<string name="clipboard_gallery_url_snack_action">Vis</string>
|
||||
<string name="error_bad_status_code">Feil statuskode: %d</string>
|
||||
<string name="error_timeout">Tidsavbrudd</string>
|
||||
<string name="error_unknown_host">Ukjent vert</string>
|
||||
<string name="error_redirection">For mange videresendinger</string>
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
<string name="clipboard_gallery_url_snack_message">มีลิงค์ของเว็บแกลเลอรี่อยู่ในคลิปบอร์ด</string>
|
||||
<string name="clipboard_gallery_url_snack_action">ดู</string>
|
||||
|
||||
<string name="error_bad_status_code">รหัสข้อผิดพลาด: %d</string>
|
||||
<string name="error_timeout">หมดเวลา</string>
|
||||
<string name="error_unknown_host">ไม่รู้จักโฮสต์</string>
|
||||
<string name="error_redirection">มีการเปลี่ยนทางเยอะเกินไป</string>
|
||||
|
||||
@@ -64,7 +64,6 @@
|
||||
<string name="image_search_not_quick_search">Görsel arama, hızlı arama olarak eklenemez</string>
|
||||
<string name="duplicate_name">Ad zaten kullanımda.</string>
|
||||
<string name="text_is_empty">Yazı boş</string>
|
||||
<string name="error_bad_status_code">Kötü durum kodu: %d</string>
|
||||
<string name="error_unknown_host">Bilinmeyen host</string>
|
||||
<string name="app_waring">Bu uygulamadaki içerikler internetten alınmaktadır. Bazı içerikler fiziksel veya zihinsel olarak size zararlı gelebilir.Yukarıda, riskleri öğrendiniz ve üstleneceksiniz.
|
||||
\nKullanmaya devam ederek, yukarıdaki koşulları kabul edersiniz.</string>
|
||||
|
||||
@@ -33,7 +33,6 @@
|
||||
<string name="invalid_download_location">似乎下载路径不可用。请到重新设置下载路径。</string>
|
||||
<string name="clipboard_gallery_url_snack_message">剪切板里有画廊链接</string>
|
||||
<string name="clipboard_gallery_url_snack_action">查看</string>
|
||||
<string name="error_bad_status_code">错误状态码:%d</string>
|
||||
<string name="error_timeout">超时</string>
|
||||
<string name="error_unknown_host">未知主机</string>
|
||||
<string name="error_redirection">太多重定向</string>
|
||||
|
||||
@@ -42,7 +42,6 @@
|
||||
<string name="clipboard_gallery_url_snack_message">剪切板裏有畫廊鏈接</string>
|
||||
<string name="clipboard_gallery_url_snack_action">查看</string>
|
||||
|
||||
<string name="error_bad_status_code">錯誤狀態碼:%d</string>
|
||||
<string name="error_timeout">超時</string>
|
||||
<string name="error_unknown_host">未知主機</string>
|
||||
<string name="error_redirection">太多重定向</string>
|
||||
|
||||
@@ -33,7 +33,6 @@
|
||||
<string name="invalid_download_location">看來下載路徑似乎沒辦法使用。請至設定重新設定下載路徑。</string>
|
||||
<string name="clipboard_gallery_url_snack_message">剪貼簿裡有圖庫連結</string>
|
||||
<string name="clipboard_gallery_url_snack_action">檢視</string>
|
||||
<string name="error_bad_status_code">錯誤狀態碼:%d</string>
|
||||
<string name="error_timeout">逾時</string>
|
||||
<string name="error_unknown_host">未知的主機</string>
|
||||
<string name="error_redirection">重新導向迴圈</string>
|
||||
|
||||
@@ -47,31 +47,6 @@
|
||||
<string name="invalid_download_location">It seems download location is not available. Please set it in Settings.</string>
|
||||
<string name="clipboard_gallery_url_snack_message">There is a gallery URL in the clipboard</string>
|
||||
<string name="clipboard_gallery_url_snack_action">View</string>
|
||||
<string name="error_status_code_400" translatable="false">Bad Request</string>
|
||||
<string name="error_status_code_401" translatable="false">Unauthorized</string>
|
||||
<string name="error_status_code_402" translatable="false">Payment Required</string>
|
||||
<string name="error_status_code_403" translatable="false">Forbidden</string>
|
||||
<string name="error_status_code_404" translatable="false">Not Found</string>
|
||||
<string name="error_status_code_405" translatable="false">Method Not Allowed</string>
|
||||
<string name="error_status_code_406" translatable="false">Not Acceptable</string>
|
||||
<string name="error_status_code_407" translatable="false">Proxy Authentication Required</string>
|
||||
<string name="error_status_code_408" translatable="false">Request Timeout</string>
|
||||
<string name="error_status_code_409" translatable="false">Conflict</string>
|
||||
<string name="error_status_code_410" translatable="false">Gone</string>
|
||||
<string name="error_status_code_411" translatable="false">Length Required</string>
|
||||
<string name="error_status_code_412" translatable="false">Precondition Failed</string>
|
||||
<string name="error_status_code_413" translatable="false">Request Entity Too Large</string>
|
||||
<string name="error_status_code_414" translatable="false">Request-URI Too Long</string>
|
||||
<string name="error_status_code_415" translatable="false">Unsupported Media Type</string>
|
||||
<string name="error_status_code_416" translatable="false">Requested Range Not Satisfiable</string>
|
||||
<string name="error_status_code_417" translatable="false">Expectation Failed</string>
|
||||
<string name="error_status_code_500" translatable="false">Internal Server Error</string>
|
||||
<string name="error_status_code_501" translatable="false">Not Implemented</string>
|
||||
<string name="error_status_code_502" translatable="false">Bad Gateway</string>
|
||||
<string name="error_status_code_503" translatable="false">Service Unavailable</string>
|
||||
<string name="error_status_code_504" translatable="false">Gateway Timeout</string>
|
||||
<string name="error_status_code_505" translatable="false">HTTP Version Not Supported</string>
|
||||
<string name="error_bad_status_code">Bad status code: %d</string>
|
||||
<string name="error_timeout">Timeout</string>
|
||||
<string name="error_unknown_host">Unknown host</string>
|
||||
<string name="error_redirection">Too many redirections</string>
|
||||
|
||||
Reference in new issue
Block a user