mirror of
https://github.com/gotson/komga.git
synced 2026-02-15 03:43:05 +01:00
fix(rar): unsupported rar archives are marked as such
solid, encrypted, and multi-volumes rar4 archives are not supported closes #147
This commit is contained in:
parent
d275506eac
commit
6c0ebbeee1
8 changed files with 24 additions and 13 deletions
|
|
@ -1,6 +1,7 @@
|
||||||
package org.gotson.komga.domain.model
|
package org.gotson.komga.domain.model
|
||||||
|
|
||||||
class MediaNotReadyException : Exception()
|
class MediaNotReadyException : Exception()
|
||||||
|
class MediaUnsupportedException(message: String) : Exception(message)
|
||||||
class ImageConversionException(message: String) : Exception(message)
|
class ImageConversionException(message: String) : Exception(message)
|
||||||
class DirectoryNotFoundException(message: String) : Exception(message)
|
class DirectoryNotFoundException(message: String) : Exception(message)
|
||||||
class DuplicateNameException(message: String) : Exception(message)
|
class DuplicateNameException(message: String) : Exception(message)
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import org.gotson.komga.domain.model.Book
|
||||||
import org.gotson.komga.domain.model.BookPage
|
import org.gotson.komga.domain.model.BookPage
|
||||||
import org.gotson.komga.domain.model.Media
|
import org.gotson.komga.domain.model.Media
|
||||||
import org.gotson.komga.domain.model.MediaNotReadyException
|
import org.gotson.komga.domain.model.MediaNotReadyException
|
||||||
|
import org.gotson.komga.domain.model.MediaUnsupportedException
|
||||||
import org.gotson.komga.infrastructure.image.ImageConverter
|
import org.gotson.komga.infrastructure.image.ImageConverter
|
||||||
import org.gotson.komga.infrastructure.mediacontainer.ContentDetector
|
import org.gotson.komga.infrastructure.mediacontainer.ContentDetector
|
||||||
import org.gotson.komga.infrastructure.mediacontainer.MediaContainerExtractor
|
import org.gotson.komga.infrastructure.mediacontainer.MediaContainerExtractor
|
||||||
|
|
@ -36,6 +37,8 @@ class BookAnalyzer(
|
||||||
|
|
||||||
val entries = try {
|
val entries = try {
|
||||||
supportedMediaTypes.getValue(mediaType).getEntries(book.path())
|
supportedMediaTypes.getValue(mediaType).getEntries(book.path())
|
||||||
|
} catch (ex: MediaUnsupportedException) {
|
||||||
|
return Media(mediaType = mediaType, status = Media.Status.UNSUPPORTED, comment = ex.message)
|
||||||
} catch (ex: Exception) {
|
} catch (ex: Exception) {
|
||||||
logger.error(ex) { "Error while analyzing book: $book" }
|
logger.error(ex) { "Error while analyzing book: $book" }
|
||||||
return Media(mediaType = mediaType, status = Media.Status.ERROR, comment = ex.message)
|
return Media(mediaType = mediaType, status = Media.Status.ERROR, comment = ex.message)
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,14 @@
|
||||||
package org.gotson.komga.infrastructure.mediacontainer
|
package org.gotson.komga.infrastructure.mediacontainer
|
||||||
|
|
||||||
import org.gotson.komga.domain.model.MediaContainerEntry
|
import org.gotson.komga.domain.model.MediaContainerEntry
|
||||||
|
import org.gotson.komga.domain.model.MediaUnsupportedException
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
|
|
||||||
interface MediaContainerExtractor {
|
interface MediaContainerExtractor {
|
||||||
fun mediaTypes(): List<String>
|
fun mediaTypes(): List<String>
|
||||||
|
|
||||||
|
@Throws(MediaUnsupportedException::class)
|
||||||
fun getEntries(path: Path): List<MediaContainerEntry>
|
fun getEntries(path: Path): List<MediaContainerEntry>
|
||||||
|
|
||||||
fun getEntryStream(path: Path, entryName: String): ByteArray
|
fun getEntryStream(path: Path, entryName: String): ByteArray
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import com.github.junrar.Archive
|
||||||
import mu.KotlinLogging
|
import mu.KotlinLogging
|
||||||
import net.greypanther.natsort.CaseInsensitiveSimpleNaturalComparator
|
import net.greypanther.natsort.CaseInsensitiveSimpleNaturalComparator
|
||||||
import org.gotson.komga.domain.model.MediaContainerEntry
|
import org.gotson.komga.domain.model.MediaContainerEntry
|
||||||
|
import org.gotson.komga.domain.model.MediaUnsupportedException
|
||||||
import org.springframework.stereotype.Service
|
import org.springframework.stereotype.Service
|
||||||
import java.nio.file.Files
|
import java.nio.file.Files
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
|
|
@ -22,6 +23,9 @@ class RarExtractor(
|
||||||
|
|
||||||
override fun getEntries(path: Path): List<MediaContainerEntry> =
|
override fun getEntries(path: Path): List<MediaContainerEntry> =
|
||||||
Archive(Files.newInputStream(path)).use { rar ->
|
Archive(Files.newInputStream(path)).use { rar ->
|
||||||
|
if (rar.mainHeader.isEncrypted) throw MediaUnsupportedException("Encrypted RAR archives are not supported")
|
||||||
|
if (rar.mainHeader.isSolid) throw MediaUnsupportedException("Solid RAR archives are not supported")
|
||||||
|
if (rar.mainHeader.isMultiVolume) throw MediaUnsupportedException("Multi-Volume RAR archives are not supported")
|
||||||
rar.fileHeaders
|
rar.fileHeaders
|
||||||
.filter { !it.isDirectory }
|
.filter { !it.isDirectory }
|
||||||
.map {
|
.map {
|
||||||
|
|
@ -38,6 +42,6 @@ class RarExtractor(
|
||||||
override fun getEntryStream(path: Path, entryName: String): ByteArray =
|
override fun getEntryStream(path: Path, entryName: String): ByteArray =
|
||||||
Archive(Files.newInputStream(path)).use { rar ->
|
Archive(Files.newInputStream(path)).use { rar ->
|
||||||
val header = rar.fileHeaders.find { it.fileNameString == entryName }
|
val header = rar.fileHeaders.find { it.fileNameString == entryName }
|
||||||
rar.getInputStream(header).readBytes()
|
rar.getInputStream(header).readBytes()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,30 +21,30 @@ class BookAnalyzerTest(
|
||||||
@Autowired private val bookAnalyzer: BookAnalyzer
|
@Autowired private val bookAnalyzer: BookAnalyzer
|
||||||
) {
|
) {
|
||||||
|
|
||||||
@ParameterizedTest
|
@Test
|
||||||
@ValueSource(strings = [
|
fun `given rar4 archive when analyzing then media status is READY`() {
|
||||||
"rar4.rar", "rar4-solid.rar"
|
val file = ClassPathResource("archives/rar4.rar")
|
||||||
])
|
|
||||||
fun `given rar4 archive when analyzing then media status is READY`(fileName: String) {
|
|
||||||
val file = ClassPathResource("archives/$fileName")
|
|
||||||
val book = Book("book", file.url, LocalDateTime.now())
|
val book = Book("book", file.url, LocalDateTime.now())
|
||||||
|
|
||||||
val media = bookAnalyzer.analyze(book)
|
val media = bookAnalyzer.analyze(book)
|
||||||
|
|
||||||
assertThat(media.mediaType).isEqualTo("application/x-rar-compressed; version=4")
|
assertThat(media.mediaType).isEqualTo("application/x-rar-compressed; version=4")
|
||||||
assertThat(media.status).isEqualTo(Media.Status.READY)
|
assertThat(media.status).isEqualTo(Media.Status.READY)
|
||||||
assertThat(media.pages).hasSize(1)
|
assertThat(media.pages).hasSize(3)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@ParameterizedTest
|
||||||
fun `given rar4 encrypted archive when analyzing then media status is ERROR`() {
|
@ValueSource(strings = [
|
||||||
val file = ClassPathResource("archives/rar4-encrypted.rar")
|
"rar4-solid.rar", "rar4-encrypted.rar"
|
||||||
|
])
|
||||||
|
fun `given rar4 solid or encrypted archive when analyzing then media status is UNSUPPORTED`(fileName: String) {
|
||||||
|
val file = ClassPathResource("archives/rar4-solid.rar")
|
||||||
val book = Book("book", file.url, LocalDateTime.now())
|
val book = Book("book", file.url, LocalDateTime.now())
|
||||||
|
|
||||||
val media = bookAnalyzer.analyze(book)
|
val media = bookAnalyzer.analyze(book)
|
||||||
|
|
||||||
assertThat(media.mediaType).isEqualTo("application/x-rar-compressed; version=4")
|
assertThat(media.mediaType).isEqualTo("application/x-rar-compressed; version=4")
|
||||||
assertThat(media.status).isEqualTo(Media.Status.ERROR)
|
assertThat(media.status).isEqualTo(Media.Status.UNSUPPORTED)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
|
|
@ -112,5 +112,4 @@ class BookAnalyzerTest(
|
||||||
assertThat(media.status).isEqualTo(Media.Status.READY)
|
assertThat(media.status).isEqualTo(Media.Status.READY)
|
||||||
assertThat(media.pages).hasSize(1)
|
assertThat(media.pages).hasSize(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in a new issue