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