diff --git a/app/src/androidTest/java/org/kiwix/kiwixmobile/mimetype/MimeTypeTest.kt b/app/src/androidTest/java/org/kiwix/kiwixmobile/mimetype/MimeTypeTest.kt new file mode 100644 index 000000000..1b29b90b1 --- /dev/null +++ b/app/src/androidTest/java/org/kiwix/kiwixmobile/mimetype/MimeTypeTest.kt @@ -0,0 +1,82 @@ +/* + * Kiwix Android + * Copyright (c) 2022 Kiwix + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package org.kiwix.kiwixmobile.mimetype + +import androidx.core.content.edit +import androidx.preference.PreferenceManager +import androidx.test.rule.ActivityTestRule +import org.junit.Assert +import org.junit.Test +import org.kiwix.kiwixlib.JNIKiwixReader +import org.kiwix.kiwixmobile.BaseActivityTest +import org.kiwix.kiwixmobile.core.NightModeConfig +import org.kiwix.kiwixmobile.core.reader.ZimFileReader +import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil +import org.kiwix.kiwixmobile.main.KiwixMainActivity +import java.io.File +import java.io.FileOutputStream +import java.io.OutputStream + +class MimeTypeTest : BaseActivityTest() { + + override var activityRule: ActivityTestRule = activityTestRule { + PreferenceManager.getDefaultSharedPreferences(context).edit { + putBoolean(SharedPreferenceUtil.PREF_SHOW_INTRO, false) + putBoolean(SharedPreferenceUtil.PREF_WIFI_ONLY, false) + } + } + + @Test + fun testMimeType() { + val loadFileStream = MimeTypeTest::class.java.classLoader.getResourceAsStream("testzim.zim") + val zimFile = File(context.cacheDir, "testzim.zim") + if (zimFile.exists()) zimFile.delete() + zimFile.createNewFile() + loadFileStream.use { inputStream -> + val outputStream: OutputStream = FileOutputStream(zimFile) + outputStream.use { it -> + val buffer = ByteArray(1024) + var length: Int + while (inputStream.read(buffer).also { length = it } > 0) { + it.write(buffer, 0, length) + } + } + } + val zimFileReader = ZimFileReader( + zimFile, + JNIKiwixReader(zimFile.canonicalPath), + NightModeConfig(SharedPreferenceUtil(context), context) + ) + zimFileReader.getRandomArticleUrl()?.let { + val mimeType = zimFileReader.readContentAndMimeType(it) + if (mimeType.contains("^([^ ]+).*$") || mimeType.contains(";")) { + Assert.fail( + "Unable to get mime type from zim file. File = " + + " $zimFile and url of article = $it" + ) + } + }.also { + zimFileReader.dispose() + } ?: kotlin.run { + Assert.fail("Unable to get article from zim file $zimFile") + }.also { + zimFileReader.dispose() + } + } +} diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/reader/ZimFileReader.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/reader/ZimFileReader.kt index 83e806e36..d687f5da3 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/reader/ZimFileReader.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/reader/ZimFileReader.kt @@ -21,7 +21,6 @@ import android.content.res.AssetFileDescriptor import android.net.Uri import android.os.ParcelFileDescriptor import android.util.Log -import android.webkit.MimeTypeMap import androidx.core.net.toUri import io.reactivex.Completable import io.reactivex.schedulers.Schedulers @@ -127,13 +126,10 @@ class ZimFileReader constructor( return loadContent(uri) } - fun readMimeType(uri: String) = uri.filePath.let { - it.mimeType?.takeIf(String::isNotEmpty) ?: mimeTypeFromReader(it) ?: DEFAULT_MIME_TYPE - }.also { Log.d(TAG, "getting mimetype for $uri = $it") } - - private fun mimeTypeFromReader(it: String) = - // Truncate mime-type (everything after the first space and semi-colon(if exists) - jniKiwixReader.getMimeType(it.filePath)?.replace("^([^ ]+).*$", "$1")?.substringBefore(";") + fun readContentAndMimeType(uri: String): String = getContentAndMimeType(uri) + .second.truncateMimeType.also { + Log.d(TAG, "getting mimetype for $uri = $it") + } fun getRedirect(url: String) = "${toRedirect(url)}" @@ -264,7 +260,6 @@ class ZimFileReader constructor( """.trimIndent() private val assetExtensions = listOf("3gp", "mp4", "m4a", "webm", "mkv", "ogg", "ogv", "svg", "warc") - private const val DEFAULT_MIME_TYPE = "application/octet-stream" } } @@ -272,9 +267,10 @@ private val Uri.filePath: String get() = toString().filePath private val String.filePath: String get() = substringAfter(CONTENT_PREFIX).substringBefore("#").substringBefore("?") -private val String.mimeType: String? - get() = MimeTypeMap.getSingleton().getMimeTypeFromExtension( - MimeTypeMap.getFileExtensionFromUrl(this) - ) + +// Truncate mime-type (everything after the first space and semi-colon(if exists) +val String.truncateMimeType: String + get() = replace("^([^ ]+).*$", "$1").substringBefore(";") + private val Pair.parcelFileDescriptor: ParcelFileDescriptor? get() = ParcelFileDescriptor.open(File(filename), ParcelFileDescriptor.MODE_READ_ONLY) diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/reader/ZimReaderContainer.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/reader/ZimReaderContainer.kt index 97814856c..ad91cf3cc 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/reader/ZimReaderContainer.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/reader/ZimReaderContainer.kt @@ -48,7 +48,11 @@ class ZimReaderContainer @Inject constructor(private val zimFileReaderFactory: F fun getRedirect(url: String): String = zimFileReader?.getRedirect(url) ?: "" fun load(url: String, requestHeaders: Map): WebResourceResponse { val data = zimFileReader?.load(url) - return WebResourceResponse(zimFileReader?.readMimeType(url), Charsets.UTF_8.name(), data) + return WebResourceResponse( + zimFileReader?.readContentAndMimeType(url), + Charsets.UTF_8.name(), + data + ) .apply { val headers = mutableMapOf("Accept-Ranges" to "bytes") if ("Range" in requestHeaders.keys) { diff --git a/core/src/sharedTestFunctions/java/org/kiwix/kiwixmobile/core/reader/ZimFileReaderTest.kt b/core/src/sharedTestFunctions/java/org/kiwix/kiwixmobile/core/reader/ZimFileReaderTest.kt new file mode 100644 index 000000000..04c49467a --- /dev/null +++ b/core/src/sharedTestFunctions/java/org/kiwix/kiwixmobile/core/reader/ZimFileReaderTest.kt @@ -0,0 +1,42 @@ +/* + * Kiwix Android + * Copyright (c) 2022 Kiwix + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package org.kiwix.kiwixmobile.core.reader + +import org.junit.Test +import org.junit.jupiter.api.Assertions.assertEquals + +class ZimFileReaderTest { + @Test + fun checkMimeTypeWithSemicolon() { + val mimeTypeHtml = "text/html;" + assertEquals("text/html", mimeTypeHtml.truncateMimeType) + } + + @Test + fun checkMimeTypeWithSpecialCharacters() { + val mimeTypeCss = "text/css^([^ ]+).*\$" + assertEquals("text/css$1", mimeTypeCss.truncateMimeType) + } + + @Test + fun checkMimeTypeWithSemicolonBeforeSpecialCharacters() { + val mimeTypeCss = "text/application;^([^ ]+).*\$;" + assertEquals("text/application", mimeTypeCss.truncateMimeType) + } +}