4aa35ac33a647c77736f5a4612e71240f51c74c0
[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.FreenetRequest
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
20 /**
21  * Page implementation that lets the user upload an image.
22  */
23 class UploadImagePage(template: Template, webInterface: WebInterface):
24                 LoggedInPage("uploadImage.html", template, "Page.UploadImage.Title", webInterface) {
25
26         override fun handleRequest(freenetRequest: FreenetRequest, currentSone: Sone, templateContext: TemplateContext) {
27                 if (freenetRequest.isPOST) {
28                         val parentAlbum = freenetRequest.parameters["parent"]!!.let(webInterface.core::getAlbum) ?: throw RedirectException("noPermission.html")
29                         if (parentAlbum.sone != currentSone) {
30                                 throw RedirectException("noPermission.html")
31                         }
32                         val title = freenetRequest.parameters["title", 200].emptyToNull ?: throw RedirectException("emptyImageTitle.html")
33
34                         val uploadedFile = freenetRequest.httpRequest.getUploadedFile("image")
35                         val bytes = uploadedFile.data.use { it.toByteArray() }
36                         val bufferedImage = bytes.toImage()
37                         if (bufferedImage == null) {
38                                 templateContext["messages"] = webInterface.l10n.getString("Page.UploadImage.Error.InvalidImage")
39                                 return
40                         }
41
42                         val temporaryImage = webInterface.core.createTemporaryImage(bytes.mimeType, bytes)
43                         webInterface.core.createImage(currentSone, parentAlbum, temporaryImage).modify().apply {
44                                 setWidth(bufferedImage.width)
45                                 setHeight(bufferedImage.height)
46                                 setTitle(title)
47                                 setDescription(TextFilter.filter(freenetRequest.headers["Host"], freenetRequest.parameters["description", 4000]))
48                         }.update()
49                         throw RedirectException("imageBrowser.html?album=${parentAlbum.id}")
50                 }
51         }
52
53         private fun Bucket.toByteArray(): ByteArray = ByteArrayOutputStream(size().toInt()).use { outputStream ->
54                 inputStream.copyTo(outputStream)
55                 outputStream.toByteArray()
56         }
57
58         private fun ByteArray.toImage(): BufferedImage? = ByteArrayInputStream(this).use {
59                 ImageIO.read(it)
60         }
61
62         private val ByteArray.mimeType get() = ByteArrayInputStream(this).use {
63                 ImageIO.createImageInputStream(it).use {
64                         ImageIO.getImageReaders(it).asSequence()
65                                         .firstOrNull()?.originatingProvider?.mimeTypes?.firstOrNull()
66                                         ?: UNKNOWN_MIME_TYPE
67                 }
68         }
69
70 }
71
72 private const val UNKNOWN_MIME_TYPE = "application/octet-stream"