♻️ Use SoneRequest instead of FreenetRequest
[Sone.git] / src / main / kotlin / net / pterodactylus / sone / web / pages / UploadImagePage.kt
1 package net.pterodactylus.sone.web.pages
2
3 import freenet.support.api.Bucket
4 import net.pterodactylus.sone.data.Sone
5 import net.pterodactylus.sone.text.TextFilter
6 import net.pterodactylus.sone.utils.emptyToNull
7 import net.pterodactylus.sone.utils.headers
8 import net.pterodactylus.sone.utils.isPOST
9 import net.pterodactylus.sone.utils.parameters
10 import net.pterodactylus.sone.utils.use
11 import net.pterodactylus.sone.web.WebInterface
12 import net.pterodactylus.sone.web.page.*
13 import net.pterodactylus.util.template.Template
14 import net.pterodactylus.util.template.TemplateContext
15 import java.awt.image.BufferedImage
16 import java.io.ByteArrayInputStream
17 import java.io.ByteArrayOutputStream
18 import javax.imageio.ImageIO
19 import javax.inject.Inject
20
21 /**
22  * Page implementation that lets the user upload an image.
23  */
24 class UploadImagePage @Inject constructor(template: Template, webInterface: WebInterface):
25                 LoggedInPage("uploadImage.html", template, "Page.UploadImage.Title", webInterface) {
26
27         override fun handleRequest(soneRequest: SoneRequest, currentSone: Sone, templateContext: TemplateContext) {
28                 if (soneRequest.isPOST) {
29                         val parentAlbum = soneRequest.parameters["parent"]!!.let(soneRequest.core::getAlbum) ?: throw RedirectException("noPermission.html")
30                         if (parentAlbum.sone != currentSone) {
31                                 throw RedirectException("noPermission.html")
32                         }
33                         val title = soneRequest.parameters["title", 200].emptyToNull ?: throw RedirectException("emptyImageTitle.html")
34
35                         val uploadedFile = soneRequest.httpRequest.getUploadedFile("image")
36                         val bytes = uploadedFile.data.use { it.toByteArray() }
37                         val bufferedImage = bytes.toImage()
38                         if (bufferedImage == null) {
39                                 templateContext["messages"] = soneRequest.l10n.getString("Page.UploadImage.Error.InvalidImage")
40                                 return
41                         }
42
43                         val temporaryImage = soneRequest.core.createTemporaryImage(bytes.mimeType, bytes)
44                         soneRequest.core.createImage(currentSone, parentAlbum, temporaryImage).modify().apply {
45                                 setWidth(bufferedImage.width)
46                                 setHeight(bufferedImage.height)
47                                 setTitle(title)
48                                 setDescription(TextFilter.filter(soneRequest.headers["Host"], soneRequest.parameters["description", 4000]))
49                         }.update()
50                         throw RedirectException("imageBrowser.html?album=${parentAlbum.id}")
51                 }
52         }
53
54         private fun Bucket.toByteArray(): ByteArray = ByteArrayOutputStream(size().toInt()).use { outputStream ->
55                 inputStream.copyTo(outputStream)
56                 outputStream.toByteArray()
57         }
58
59         private fun ByteArray.toImage(): BufferedImage? = ByteArrayInputStream(this).use {
60                 ImageIO.read(it)
61         }
62
63         private val ByteArray.mimeType get() = ByteArrayInputStream(this).use {
64                 ImageIO.createImageInputStream(it).use {
65                         ImageIO.getImageReaders(it).asSequence()
66                                         .firstOrNull()?.originatingProvider?.mimeTypes?.firstOrNull()
67                                         ?: UNKNOWN_MIME_TYPE
68                 }
69         }
70
71 }
72
73 private const val UNKNOWN_MIME_TYPE = "application/octet-stream"