Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: generate correct filenames when series name or book filename contain UTF-8 #941

Merged
merged 3 commits into from
Aug 9, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ import org.springframework.web.server.ResponseStatusException
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody
import java.io.FileNotFoundException
import java.io.OutputStream
import java.nio.charset.StandardCharsets.UTF_8
import java.nio.file.NoSuchFileException
import java.time.LocalDate
import java.time.ZoneOffset
Expand Down Expand Up @@ -386,7 +387,7 @@ class BookController(
.headers(
HttpHeaders().apply {
contentDisposition = ContentDisposition.builder("attachment")
.filename(book.path.name)
.filename(book.path.name, UTF_8)
.build()
},
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ import org.springframework.web.multipart.MultipartFile
import org.springframework.web.server.ResponseStatusException
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody
import java.io.OutputStream
import java.nio.charset.StandardCharsets.UTF_8
import java.util.concurrent.TimeUnit
import java.util.zip.Deflater
import javax.validation.Valid
Expand Down Expand Up @@ -422,7 +423,7 @@ class ReadListController(
.headers(
HttpHeaders().apply {
contentDisposition = ContentDisposition.builder("attachment")
.filename(readList.name + ".zip")
.filename(readList.name + ".zip", UTF_8)
.build()
},
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ import org.springframework.web.multipart.MultipartFile
import org.springframework.web.server.ResponseStatusException
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody
import java.io.OutputStream
import java.nio.charset.StandardCharsets.UTF_8
import java.util.zip.Deflater
import javax.validation.Valid

Expand Down Expand Up @@ -672,7 +673,7 @@ class SeriesController(
.headers(
HttpHeaders().apply {
contentDisposition = ContentDisposition.builder("attachment")
.filename(seriesMetadataRepository.findById(seriesId).title + ".zip")
.filename(seriesMetadataRepository.findById(seriesId).title + ".zip", UTF_8)
.build()
},
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import org.gotson.komga.domain.service.LibraryLifecycle
import org.gotson.komga.domain.service.SeriesLifecycle
import org.gotson.komga.infrastructure.security.KomgaPrincipal
import org.hamcrest.Matchers
import org.hamcrest.Matchers.containsString
import org.hamcrest.core.IsNull
import org.junit.jupiter.api.AfterAll
import org.junit.jupiter.api.AfterEach
Expand All @@ -49,6 +50,9 @@ import org.springframework.test.web.servlet.get
import org.springframework.test.web.servlet.patch
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders
import org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath
import java.net.URLEncoder
import java.nio.charset.StandardCharsets
import java.nio.file.Files
import java.time.LocalDate
import kotlin.random.Random

Expand Down Expand Up @@ -1346,4 +1350,26 @@ class BookControllerTest(
jsonPath("$.totalElements").value(2),
)
}

@Test
@WithMockCustomUser
fun `given book with Unicode name when getting book file then attachment name is correct`() {
val bookName = "アキラ"
val tempFile = Files.createTempFile(bookName, ".cbz")
.also { it.toFile().deleteOnExit() }
makeSeries(name = "series", libraryId = library.id).let { series ->
seriesLifecycle.createSeries(series).let { created ->
val books = listOf(makeBook(bookName, libraryId = library.id, url = tempFile.toUri().toURL()))
seriesLifecycle.addBooks(created, books)
}
}

val book = bookRepository.findAll().first()

mockMvc.get("/api/v1/books/${book.id}/file")
.andExpect {
status { isOk() }
header { string("Content-Disposition", containsString(URLEncoder.encode(bookName, StandardCharsets.UTF_8.name()))) }
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import org.gotson.komga.domain.service.LibraryLifecycle
import org.gotson.komga.domain.service.ReadListLifecycle
import org.gotson.komga.domain.service.SeriesLifecycle
import org.gotson.komga.language.toIndexedMap
import org.hamcrest.Matchers
import org.junit.jupiter.api.AfterAll
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.BeforeAll
Expand All @@ -29,6 +30,9 @@ import org.springframework.test.web.servlet.delete
import org.springframework.test.web.servlet.get
import org.springframework.test.web.servlet.patch
import org.springframework.test.web.servlet.post
import java.net.URLEncoder
import java.nio.charset.StandardCharsets
import java.nio.file.Files

@ExtendWith(SpringExtension::class)
@SpringBootTest
Expand Down Expand Up @@ -979,4 +983,32 @@ class ReadListControllerTest(
}
}
}

@Test
@WithMockCustomUser
fun `given readlist with Unicode name when getting readlist file then attachment name is correct`() {
val name = "アキラ"
val tempFile = Files.createTempFile(name, ".cbz")
.also { it.toFile().deleteOnExit() }
val book = makeBook(name, libraryId = library1.id, url = tempFile.toUri().toURL())
makeSeries(name = "series", libraryId = library1.id).let { series ->
seriesLifecycle.createSeries(series).let { created ->
val books = listOf(book)
seriesLifecycle.addBooks(created, books)
}
}

val readlist = readListLifecycle.addReadList(
ReadList(
name = name,
bookIds = listOf(book.id).toIndexedMap(),
),
)

mockMvc.get("/api/v1/readlists/${readlist.id}/file")
.andExpect {
status { isOk() }
header { string("Content-Disposition", Matchers.containsString(URLEncoder.encode(name, StandardCharsets.UTF_8.name()))) }
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ import org.springframework.test.web.servlet.delete
import org.springframework.test.web.servlet.get
import org.springframework.test.web.servlet.patch
import org.springframework.test.web.servlet.post
import java.net.URLEncoder
import java.nio.charset.StandardCharsets
import java.nio.file.Files
import kotlin.random.Random

@ExtendWith(SpringExtension::class)
Expand Down Expand Up @@ -1075,4 +1078,25 @@ class SeriesControllerTest(
}
}
}

@Test
@WithMockCustomUser
fun `given series with Unicode name when getting series file then attachment name is correct`() {
val name = "アキラ"
val tempFile = Files.createTempFile(name, ".cbz")
.also { it.toFile().deleteOnExit() }
val series = makeSeries(name = name, libraryId = library.id).let { series ->
seriesLifecycle.createSeries(series).let { created ->
val books = listOf(makeBook(name, libraryId = library.id, url = tempFile.toUri().toURL()))
seriesLifecycle.addBooks(created, books)
}
series
}

mockMvc.get("/api/v1/series/${series.id}/file")
.andExpect {
status { isOk() }
header { string("Content-Disposition", Matchers.containsString(URLEncoder.encode(name, StandardCharsets.UTF_8.name()))) }
}
}
}