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