From 4c38acd66446b55740d773bb7a4c92051d8fe7de Mon Sep 17 00:00:00 2001 From: kunfei Date: Sun, 24 Apr 2022 22:55:12 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../io/legado/app/help/storage/AppWebDav.kt | 57 ++++---- .../io/legado/app/lib/webdav/Authorization.kt | 19 +++ .../java/io/legado/app/lib/webdav/HttpAuth.kt | 9 -- .../java/io/legado/app/lib/webdav/WebDav.kt | 132 ++++++++---------- 4 files changed, 106 insertions(+), 111 deletions(-) create mode 100644 app/src/main/java/io/legado/app/lib/webdav/Authorization.kt delete mode 100644 app/src/main/java/io/legado/app/lib/webdav/HttpAuth.kt diff --git a/app/src/main/java/io/legado/app/help/storage/AppWebDav.kt b/app/src/main/java/io/legado/app/help/storage/AppWebDav.kt index 4a93e0066..c7e139c8d 100644 --- a/app/src/main/java/io/legado/app/help/storage/AppWebDav.kt +++ b/app/src/main/java/io/legado/app/help/storage/AppWebDav.kt @@ -12,7 +12,7 @@ import io.legado.app.exception.NoStackTraceException import io.legado.app.help.config.AppConfig import io.legado.app.help.coroutine.Coroutine import io.legado.app.lib.dialogs.selector -import io.legado.app.lib.webdav.HttpAuth +import io.legado.app.lib.webdav.Authorization import io.legado.app.lib.webdav.WebDav import io.legado.app.utils.* import kotlinx.coroutines.Dispatchers.IO @@ -31,7 +31,9 @@ object AppWebDav { val syncBookProgress get() = appCtx.getPrefBoolean(PreferKey.syncBookProgress, true) - var isOk = false + var authorization: Authorization? = null + + val isOk get() = authorization != null init { runBlocking { @@ -61,14 +63,15 @@ object AppWebDav { suspend fun upConfig() { kotlin.runCatching { - isOk = false + authorization = null val account = appCtx.getPrefString(PreferKey.webDavAccount) val password = appCtx.getPrefString(PreferKey.webDavPassword) if (!account.isNullOrBlank() && !password.isNullOrBlank()) { - HttpAuth.auth = HttpAuth.Auth(account, password) - WebDav(rootWebDavUrl).makeAsDir() - WebDav(bookProgressUrl).makeAsDir() - isOk = true + val mAuthorization = Authorization(account, password) + WebDav(rootWebDavUrl, mAuthorization).makeAsDir() + WebDav(bookProgressUrl, mAuthorization).makeAsDir() + + authorization = mAuthorization } } } @@ -77,18 +80,16 @@ object AppWebDav { private suspend fun getWebDavFileNames(): ArrayList { val url = rootWebDavUrl val names = arrayListOf() - if (isOk) { - var files = WebDav(url).listFiles() + authorization?.let { + var files = WebDav(url, it).listFiles() files = files.reversed() - files.forEach { - val name = it.displayName + files.forEach { webDav -> + val name = webDav.displayName if (name?.startsWith("backup") == true) { names.add(name) } } - } else { - throw NoStackTraceException("webDav没有配置") - } + } ?: throw NoStackTraceException("webDav没有配置") return names } @@ -115,8 +116,8 @@ object AppWebDav { } private suspend fun restoreWebDav(name: String) { - rootWebDavUrl.let { - val webDav = WebDav(it + name) + authorization?.let { + val webDav = WebDav(rootWebDavUrl + name, it) webDav.downloadTo(zipFilePath, true) @Suppress("BlockingMethodInNonBlockingContext") ZipUtils.unzipFile(zipFilePath, Backup.backupPath) @@ -126,16 +127,16 @@ object AppWebDav { } suspend fun hasBackUp(): Boolean { - if (isOk) { + authorization?.let { val url = "${rootWebDavUrl}${backupFileName}" - return WebDav(url).exists() + return WebDav(url, it).exists() } return false } suspend fun backUpWebDav(path: String) { try { - if (isOk && NetworkUtils.isAvailable()) { + authorization?.let { val paths = arrayListOf(*Backup.backupFileNames) for (i in 0 until paths.size) { paths[i] = path + File.separator + paths[i] @@ -143,7 +144,7 @@ object AppWebDav { FileUtils.delete(zipFilePath) if (ZipUtils.zipFiles(paths, zipFilePath)) { val putUrl = "${rootWebDavUrl}${backupFileName}" - WebDav(putUrl).upload(zipFilePath) + WebDav(putUrl, it).upload(zipFilePath) } } } catch (e: Exception) { @@ -153,14 +154,14 @@ object AppWebDav { suspend fun exportWebDav(byteArray: ByteArray, fileName: String) { try { - if (isOk && NetworkUtils.isAvailable()) { + authorization?.let { // 默认导出到legado文件夹下exports目录 val exportsWebDavUrl = rootWebDavUrl + EncoderUtils.escape("exports") + "/" // 在legado文件夹创建exports目录,如果不存在的话 - WebDav(exportsWebDavUrl).makeAsDir() + WebDav(exportsWebDavUrl, it).makeAsDir() // 如果导出的本地文件存在,开始上传 val putUrl = exportsWebDavUrl + fileName - WebDav(putUrl).upload(byteArray, "text/plain") + WebDav(putUrl, it).upload(byteArray, "text/plain") } } catch (e: Exception) { Handler(Looper.getMainLooper()).post { @@ -170,14 +171,14 @@ object AppWebDav { } fun uploadBookProgress(book: Book) { - if (!isOk) return + val authorization = authorization ?: return if (!syncBookProgress) return if (!NetworkUtils.isAvailable()) return Coroutine.async { val bookProgress = BookProgress(book) val json = GSON.toJson(bookProgress) val url = getProgressUrl(book) - WebDav(url).upload(json.toByteArray(), "application/json") + WebDav(url, authorization).upload(json.toByteArray(), "application/json") } } @@ -189,9 +190,9 @@ object AppWebDav { * 获取书籍进度 */ suspend fun getBookProgress(book: Book): BookProgress? { - if (isOk && NetworkUtils.isAvailable()) { + authorization?.let { val url = getProgressUrl(book) - WebDav(url).download()?.let { byteArray -> + WebDav(url, it).download()?.let { byteArray -> val json = String(byteArray) if (json.isJson()) { return GSON.fromJsonObject(json).getOrNull() @@ -202,7 +203,7 @@ object AppWebDav { } suspend fun downloadAllBookProgress() { - if (!isOk) return + authorization ?: return appDb.bookDao.all.forEach { book -> getBookProgress(book)?.let { bookProgress -> if (bookProgress.durChapterIndex > book.durChapterIndex || diff --git a/app/src/main/java/io/legado/app/lib/webdav/Authorization.kt b/app/src/main/java/io/legado/app/lib/webdav/Authorization.kt new file mode 100644 index 000000000..f03d1ec88 --- /dev/null +++ b/app/src/main/java/io/legado/app/lib/webdav/Authorization.kt @@ -0,0 +1,19 @@ +package io.legado.app.lib.webdav + +import okhttp3.Credentials +import java.nio.charset.Charset +import java.nio.charset.StandardCharsets + +data class Authorization( + val username: String, + val password: String, + val charset: Charset = StandardCharsets.ISO_8859_1 +) { + + val data: String = Credentials.basic(username, password, charset) + + override fun toString(): String { + return data + } + +} \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/lib/webdav/HttpAuth.kt b/app/src/main/java/io/legado/app/lib/webdav/HttpAuth.kt deleted file mode 100644 index d2f604a80..000000000 --- a/app/src/main/java/io/legado/app/lib/webdav/HttpAuth.kt +++ /dev/null @@ -1,9 +0,0 @@ -package io.legado.app.lib.webdav - -object HttpAuth { - - var auth: Auth? = null - - class Auth internal constructor(val user: String, val pass: String) - -} \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/lib/webdav/WebDav.kt b/app/src/main/java/io/legado/app/lib/webdav/WebDav.kt index 6e2d9de8b..fa0f66a4a 100644 --- a/app/src/main/java/io/legado/app/lib/webdav/WebDav.kt +++ b/app/src/main/java/io/legado/app/lib/webdav/WebDav.kt @@ -1,17 +1,17 @@ package io.legado.app.lib.webdav +import android.util.Log import io.legado.app.constant.AppLog +import io.legado.app.help.http.newCallResponse import io.legado.app.help.http.newCallResponseBody import io.legado.app.help.http.okHttpClient import io.legado.app.help.http.text import io.legado.app.utils.printOnDebug -import okhttp3.Credentials import okhttp3.MediaType.Companion.toMediaType import okhttp3.RequestBody.Companion.asRequestBody import okhttp3.RequestBody.Companion.toRequestBody import org.intellij.lang.annotations.Language import org.jsoup.Jsoup - import java.io.File import java.io.InputStream import java.net.MalformedURLException @@ -19,7 +19,7 @@ import java.net.URL import java.net.URLEncoder @Suppress("unused", "MemberVisibilityCanBePrivate") -class WebDav(urlStr: String) { +class WebDav(urlStr: String, val authorization: Authorization) { companion object { // 指定返回哪些属性 @Language("xml") @@ -88,24 +88,20 @@ class WebDav(urlStr: String) { } else { String.format(DIR, requestProps.toString() + "\n") } - val url = httpUrl - val auth = HttpAuth.auth - if (url != null && auth != null) { - return kotlin.runCatching { - okHttpClient.newCallResponseBody { - url(url) - addHeader("Authorization", Credentials.basic(auth.user, auth.pass)) - addHeader("Depth", "1") - // 添加RequestBody对象,可以只返回的属性。如果设为null,则会返回全部属性 - // 注意:尽量手动指定需要返回的属性。若返回全部属性,可能后由于Prop.java里没有该属性名,而崩溃。 - val requestBody = requestPropsStr.toRequestBody("text/plain".toMediaType()) - method("PROPFIND", requestBody) - }.text() - }.onFailure { e -> - e.printOnDebug() - }.getOrNull() - } - return null + val url = httpUrl ?: return null + return kotlin.runCatching { + okHttpClient.newCallResponseBody { + url(url) + addHeader("Authorization", authorization.data) + addHeader("Depth", "1") + // 添加RequestBody对象,可以只返回的属性。如果设为null,则会返回全部属性 + // 注意:尽量手动指定需要返回的属性。若返回全部属性,可能后由于Prop.java里没有该属性名,而崩溃。 + val requestBody = requestPropsStr.toRequestBody("text/plain".toMediaType()) + method("PROPFIND", requestBody) + }.text() + }.onFailure { e -> + e.printOnDebug() + }.getOrNull() } private fun parseDir(s: String): List { @@ -120,7 +116,7 @@ class WebDav(urlStr: String) { val fileName = href.substring(href.lastIndexOf("/") + 1) val webDavFile: WebDav try { - webDavFile = WebDav(baseUrl + fileName) + webDavFile = WebDav(baseUrl + fileName, authorization) webDavFile.displayName = fileName webDavFile.contentType = element .getElementsByTag("d:getcontenttype") @@ -157,23 +153,19 @@ class WebDav(urlStr: String) { * @return 是否创建成功 */ suspend fun makeAsDir(): Boolean { - val url = httpUrl - val auth = HttpAuth.auth - if (url != null && auth != null) { - //防止报错 - return kotlin.runCatching { - if (!exists()) { - okHttpClient.newCallResponseBody { - url(url) - method("MKCOL", null) - addHeader("Authorization", Credentials.basic(auth.user, auth.pass)) - }.close() - } - }.onFailure { - AppLog.put(it.localizedMessage) - }.isSuccess - } - return false + val url = httpUrl ?: return false + //防止报错 + return kotlin.runCatching { + if (!exists()) { + okHttpClient.newCallResponseBody { + url(url) + method("MKCOL", null) + addHeader("Authorization", authorization.data) + }.close() + } + }.onFailure { + AppLog.put(it.localizedMessage) + }.isSuccess } /** @@ -208,49 +200,41 @@ class WebDav(urlStr: String) { if (!file.exists()) return false // 务必注意RequestBody不要嵌套,不然上传时内容可能会被追加多余的文件信息 val fileBody = file.asRequestBody(contentType.toMediaType()) - val url = httpUrl - val auth = HttpAuth.auth - if (url != null && auth != null) { - return kotlin.runCatching { - okHttpClient.newCallResponseBody { - url(url) - put(fileBody) - addHeader("Authorization", Credentials.basic(auth.user, auth.pass)) - }.close() - }.isSuccess - } - return false + val url = httpUrl ?: return false + return kotlin.runCatching { + okHttpClient.newCallResponse { + url(url) + put(fileBody) + addHeader("Authorization", authorization.data) + }.body?.string()?.let { + Log.d("webDav", it) + } + }.onFailure { + it.printOnDebug() + }.isSuccess } suspend fun upload(byteArray: ByteArray, contentType: String): Boolean { // 务必注意RequestBody不要嵌套,不然上传时内容可能会被追加多余的文件信息 val fileBody = byteArray.toRequestBody(contentType.toMediaType()) - val url = httpUrl - val auth = HttpAuth.auth - if (url != null && auth != null) { - return kotlin.runCatching { - okHttpClient.newCallResponseBody { - url(url) - put(fileBody) - addHeader("Authorization", Credentials.basic(auth.user, auth.pass)) - }.close() - }.isSuccess - } - return false + val url = httpUrl ?: return false + return kotlin.runCatching { + okHttpClient.newCallResponseBody { + url(url) + put(fileBody) + addHeader("Authorization", authorization.data) + }.close() + }.isSuccess } private suspend fun getInputStream(): InputStream? { - val url = httpUrl - val auth = HttpAuth.auth - if (url != null && auth != null) { - return kotlin.runCatching { - okHttpClient.newCallResponseBody { - url(url) - addHeader("Authorization", Credentials.basic(auth.user, auth.pass)) - }.byteStream() - }.getOrNull() - } - return null + val url = httpUrl ?: return null + return kotlin.runCatching { + okHttpClient.newCallResponseBody { + url(url) + addHeader("Authorization", authorization.data) + }.byteStream() + }.getOrNull() } } \ No newline at end of file