diff --git a/app/src/main/cpp/archive.c b/app/src/main/cpp/archive.c index 209adc2e7..7508f030b 100644 --- a/app/src/main/cpp/archive.c +++ b/app/src/main/cpp/archive.c @@ -98,6 +98,20 @@ static inline int filename_is_playable_file(const char *name) { return false; } +static inline const char *archive_entry_pathname2(struct archive_entry *entry) { + const char *name = archive_entry_pathname_utf8(entry); + return name ? name : archive_entry_pathname(entry); +} + +static inline bool archive_entry_is_file(struct archive_entry *entry) { + return archive_entry_filetype(entry) == AE_IFREG; +} + +static inline bool archive_entry_is_playable(struct archive_entry *entry) { + return archive_entry_is_file(entry) && + filename_is_playable_file(archive_entry_pathname2(entry)); +} + static inline int compare_entries(const void *a, const void *b) { const char *fa = ((entry *) a)->filename; const char *fb = ((entry *) b)->filename; @@ -107,8 +121,8 @@ static inline int compare_entries(const void *a, const void *b) { static long archive_map_entries_index(archive_ctx *ctx) { long count = 0; while (archive_read_next_header(ctx->arc, &ctx->entry) == ARCHIVE_OK) { - const char *name = archive_entry_pathname_utf8(ctx->entry); - if (filename_is_playable_file(name)) { + const char *name = archive_entry_pathname2(ctx->entry); + if (archive_entry_is_file(ctx->entry) && filename_is_playable_file(name)) { entries[count].filename = strdup(name); entries[count].index = count; entries[count].size = archive_entry_size(ctx->entry); @@ -166,7 +180,7 @@ static void mempool_release_pages(void *addr, size_t size) { static long archive_list_all_entries(archive_ctx *ctx) { long count = 0; while (archive_read_next_header(ctx->arc, &ctx->entry) == ARCHIVE_OK) - if (filename_is_playable_file(archive_entry_pathname_utf8(ctx->entry))) + if (archive_entry_is_playable(ctx->entry)) count++; if (!count) LOGE("%s", archive_error_string(ctx->arc)); @@ -214,7 +228,7 @@ static int archive_alloc_ctx(archive_ctx **ctxptr) { static int archive_skip_to_index(archive_ctx *ctx, int index) { while (archive_read_next_header(ctx->arc, &ctx->entry) == ARCHIVE_OK) { - if (!filename_is_playable_file(archive_entry_pathname_utf8(ctx->entry))) + if (!archive_entry_is_playable(ctx->entry)) continue; if (ctx->next_index++ == index) { return ctx->next_index - 1; @@ -433,7 +447,7 @@ Java_com_hippo_ehviewer_jni_ArchiveKt_providePassword(JNIEnv *env, jclass thiz, archive_alloc_ctx(&ctx); void *tmpBuf = alloca(4096); while (archive_read_next_header(ctx->arc, &entry) == ARCHIVE_OK) { - if (!filename_is_playable_file(archive_entry_pathname_utf8(entry))) + if (!archive_entry_is_playable(entry)) continue; if (!archive_entry_is_encrypted(entry)) continue; @@ -448,22 +462,15 @@ Java_com_hippo_ehviewer_jni_ArchiveKt_providePassword(JNIEnv *env, jclass thiz, } JNIEXPORT jstring JNICALL -Java_com_hippo_ehviewer_jni_ArchiveKt_getFilename(JNIEnv *env, jclass thiz, +Java_com_hippo_ehviewer_jni_ArchiveKt_getExtension(JNIEnv *env, jclass thiz, jint index) { EH_UNUSED(env); EH_UNUSED(thiz); - index = entries[index].index; - archive_ctx *ctx = NULL; - int ret; - ret = archive_get_ctx(&ctx, index); - if (ret) - return NULL; - jstring str = (*env)->NewStringUTF(env, archive_entry_pathname_utf8(ctx->entry)); - ctx->using = 0; - return str; + const char *ext = strrchr(entries[index].filename, '.') + 1; + return (*env)->NewStringUTF(env, ext); } -JNIEXPORT void JNICALL +JNIEXPORT jboolean JNICALL Java_com_hippo_ehviewer_jni_ArchiveKt_extractToFd(JNIEnv *env, jclass thiz, jint index, jint fd) { EH_UNUSED(env); @@ -473,9 +480,10 @@ Java_com_hippo_ehviewer_jni_ArchiveKt_extractToFd(JNIEnv *env, jclass thiz, int ret; ret = archive_get_ctx(&ctx, index); if (!ret) { - archive_read_data_into_fd(ctx->arc, fd); + ret = archive_read_data_into_fd(ctx->arc, fd); ctx->using = 0; } + return ret == ARCHIVE_OK; } JNIEXPORT void JNICALL diff --git a/app/src/main/kotlin/com/hippo/ehviewer/gallery/ArchivePageLoader.kt b/app/src/main/kotlin/com/hippo/ehviewer/gallery/ArchivePageLoader.kt index d742a098f..da76f9f6b 100644 --- a/app/src/main/kotlin/com/hippo/ehviewer/gallery/ArchivePageLoader.kt +++ b/app/src/main/kotlin/com/hippo/ehviewer/gallery/ArchivePageLoader.kt @@ -23,7 +23,7 @@ import com.hippo.ehviewer.image.Image import com.hippo.ehviewer.jni.closeArchive import com.hippo.ehviewer.jni.extractToByteBuffer import com.hippo.ehviewer.jni.extractToFd -import com.hippo.ehviewer.jni.getFilename +import com.hippo.ehviewer.jni.getExtension import com.hippo.ehviewer.jni.needPassword import com.hippo.ehviewer.jni.openArchive import com.hippo.ehviewer.jni.providePassword @@ -144,28 +144,25 @@ class ArchivePageLoader(private val file: UniFile, passwdProvider: PasswdProvide mJobMap[index]?.cancel() } - override fun getImageFilename(index: Int): String { - return FileUtils.getNameFromFilename(getImageFilenameWithExtension(index))!! + override val title by lazy { + FileUtils.getNameFromFilename(file.name)!! } - override fun getImageFilenameWithExtension(index: Int): String { - return FileUtils.sanitizeFilename(getFilename(index)) + override fun getImageExtension(index: Int): String { + return getExtension(index) } override fun save(index: Int, file: UniFile): Boolean { - runCatching { + return runCatching { file.openFileDescriptor("w").use { extractToFd(index, it.fd) } - }.onFailure { + }.getOrElse { it.printStackTrace() - return false + false } - return true } - override fun save(index: Int, dir: UniFile, filename: String) = (dir / filename).apply { save(index, this) } - override fun preloadPages(pages: List, pair: Pair) {} } diff --git a/app/src/main/kotlin/com/hippo/ehviewer/gallery/EhPageLoader.kt b/app/src/main/kotlin/com/hippo/ehviewer/gallery/EhPageLoader.kt index 791648c90..90df5af69 100644 --- a/app/src/main/kotlin/com/hippo/ehviewer/gallery/EhPageLoader.kt +++ b/app/src/main/kotlin/com/hippo/ehviewer/gallery/EhPageLoader.kt @@ -15,6 +15,7 @@ */ package com.hippo.ehviewer.gallery +import com.hippo.ehviewer.client.EhUtils import com.hippo.ehviewer.client.data.GalleryInfo import com.hippo.ehviewer.image.Image import com.hippo.ehviewer.spider.SpiderQueen @@ -23,7 +24,6 @@ import com.hippo.ehviewer.spider.SpiderQueen.Companion.releaseSpiderQueen import com.hippo.ehviewer.spider.SpiderQueen.OnSpiderListener import com.hippo.ehviewer.util.SimpleHandler import com.hippo.unifile.UniFile -import java.util.Locale class EhPageLoader(private val mGalleryInfo: GalleryInfo) : PageLoader2(), OnSpiderListener { private lateinit var mSpiderQueen: SpiderQueen @@ -44,29 +44,18 @@ class EhPageLoader(private val mGalleryInfo: GalleryInfo) : PageLoader2(), OnSpi override val startPage get() = mSpiderQueen.startPage - override fun getImageFilename(index: Int): String { - return String.format( - Locale.US, - "%d-%s-%08d", - mGalleryInfo.gid, - mGalleryInfo.token, - index + 1, - ) + override val title by lazy { + EhUtils.getSuitableTitle(mGalleryInfo) } - override fun getImageFilenameWithExtension(index: Int): String { - val filename = getImageFilename(index) - return mSpiderQueen.getExtension(index)?.let { "$filename.$it" } ?: filename + override fun getImageExtension(index: Int): String { + return mSpiderQueen.getExtension(index)!! } override fun save(index: Int, file: UniFile): Boolean { return mSpiderQueen.save(index, file) } - override fun save(index: Int, dir: UniFile, filename: String): UniFile? { - return mSpiderQueen.save(index, dir, filename) - } - override fun putStartPage(page: Int) { mSpiderQueen.putStartPage(page) } diff --git a/app/src/main/kotlin/com/hippo/ehviewer/gallery/PageLoader2.kt b/app/src/main/kotlin/com/hippo/ehviewer/gallery/PageLoader2.kt index 140fffd0c..3db556479 100644 --- a/app/src/main/kotlin/com/hippo/ehviewer/gallery/PageLoader2.kt +++ b/app/src/main/kotlin/com/hippo/ehviewer/gallery/PageLoader2.kt @@ -24,19 +24,18 @@ abstract class PageLoader2 : PageLoader() { open fun putStartPage(page: Int) {} - /** - * @return without extension - */ - abstract fun getImageFilename(index: Int): String + protected abstract val title: String + + protected abstract fun getImageExtension(index: Int): String + + fun getImageFilename(index: Int): String { + return "$title - ${index + 1}.${getImageExtension(index)}" + } - /** - * @return with extension - */ - abstract fun getImageFilenameWithExtension(index: Int): String abstract fun save(index: Int, file: UniFile): Boolean - /** - * @param filename with extension - */ - abstract fun save(index: Int, dir: UniFile, filename: String): UniFile? + fun saveToDir(index: Int, dir: UniFile): UniFile? { + val filename = getImageFilename(index) + return (dir / filename).takeIf { save(index, it) } + } } diff --git a/app/src/main/kotlin/com/hippo/ehviewer/jni/Archive.kt b/app/src/main/kotlin/com/hippo/ehviewer/jni/Archive.kt index f5b5b83a7..3abe38354 100644 --- a/app/src/main/kotlin/com/hippo/ehviewer/jni/Archive.kt +++ b/app/src/main/kotlin/com/hippo/ehviewer/jni/Archive.kt @@ -5,8 +5,8 @@ import java.nio.ByteBuffer external fun releaseByteBuffer(buffer: ByteBuffer) external fun openArchive(fd: Int, size: Long): Int external fun extractToByteBuffer(index: Int): ByteBuffer? -external fun extractToFd(index: Int, fd: Int) -external fun getFilename(index: Int): String +external fun extractToFd(index: Int, fd: Int): Boolean +external fun getExtension(index: Int): String external fun needPassword(): Boolean external fun providePassword(str: String): Boolean external fun closeArchive() diff --git a/app/src/main/kotlin/com/hippo/ehviewer/spider/SpiderQueen.kt b/app/src/main/kotlin/com/hippo/ehviewer/spider/SpiderQueen.kt index ba8c65a3f..27a340ec4 100644 --- a/app/src/main/kotlin/com/hippo/ehviewer/spider/SpiderQueen.kt +++ b/app/src/main/kotlin/com/hippo/ehviewer/spider/SpiderQueen.kt @@ -309,12 +309,6 @@ class SpiderQueen private constructor(val galleryInfo: GalleryInfo) : CoroutineS } } - fun save(index: Int, dir: UniFile, filename: String): UniFile? { - val state = getPageState(index) - if (STATE_FINISHED != state) return null - return (dir / filename).takeIf { mSpiderDen.saveToUniFile(index, it) } - } - fun getExtension(index: Int): String? { val state = getPageState(index) return if (STATE_FINISHED != state) { diff --git a/app/src/main/kotlin/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt b/app/src/main/kotlin/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt index 44711e9f2..ad22ce94c 100644 --- a/app/src/main/kotlin/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt +++ b/app/src/main/kotlin/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt @@ -384,11 +384,7 @@ class ReaderActivity : EhActivity() { Toast.makeText(this, R.string.error_cant_create_temp_file, Toast.LENGTH_SHORT).show() return } - val file = mGalleryProvider!!.save( - page, - dir.asUniFile(), - mGalleryProvider!!.getImageFilenameWithExtension(page), - ) + val file = mGalleryProvider!!.saveToDir(page, dir.asUniFile()) if (file == null) { Toast.makeText(this, R.string.error_cant_save_image, Toast.LENGTH_SHORT).show() return @@ -399,12 +395,8 @@ class ReaderActivity : EhActivity() { return } - var mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension( - MimeTypeMap.getFileExtensionFromUrl(filename), - ) - if (mimeType.isNullOrEmpty()) { - mimeType = "image/jpeg" - } + val extension = FileUtils.getExtensionFromFilename(filename) + val mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension) ?: "image/jpeg" val uri = FileProvider.getUriForFile( this, @@ -442,11 +434,7 @@ class ReaderActivity : EhActivity() { Toast.makeText(this, R.string.error_cant_create_temp_file, Toast.LENGTH_SHORT).show() return } - val file = mGalleryProvider!!.save( - page, - dir.asUniFile(), - mGalleryProvider!!.getImageFilenameWithExtension(page), - ) + val file = mGalleryProvider!!.saveToDir(page, dir.asUniFile()) if (file == null) { Toast.makeText(this, R.string.error_cant_save_image, Toast.LENGTH_SHORT).show() return @@ -474,13 +462,9 @@ class ReaderActivity : EhActivity() { lifecycleScope.launchUI { val granted = isAtLeastQ || requestPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) if (granted) { - val filename = mGalleryProvider!!.getImageFilenameWithExtension(page) - var mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension( - MimeTypeMap.getFileExtensionFromUrl(filename), - ) - if (mimeType.isNullOrEmpty()) { - mimeType = "image/jpeg" - } + val filename = mGalleryProvider!!.getImageFilename(page) + val extension = FileUtils.getExtensionFromFilename(filename) + val mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension) ?: "image/jpeg" val realPath: String val resolver = contentResolver @@ -547,11 +531,7 @@ class ReaderActivity : EhActivity() { Toast.makeText(this, R.string.error_cant_create_temp_file, Toast.LENGTH_SHORT).show() return } - val file = mGalleryProvider!!.save( - page, - dir.asUniFile(), - mGalleryProvider!!.getImageFilenameWithExtension(page), - ) + val file = mGalleryProvider!!.saveToDir(page, dir.asUniFile()) if (file == null) { Toast.makeText(this, R.string.error_cant_save_image, Toast.LENGTH_SHORT).show() return