Add test for DI constructability of UploadImagePage
[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 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(freenetRequest: FreenetRequest, currentSone: Sone, templateContext: TemplateContext) {
28                 if (freenetRequest.isPOST) {
29                         val parentAlbum = freenetRequest.parameters["parent"]!!.let(webInterface.core::getAlbum) ?: throw RedirectException("noPermission.html")
30                         if (parentAlbum.sone != currentSone) {
31                                 throw RedirectException("noPermission.html")
32                         }
33                         val title = freenetRequest.parameters["title", 200].emptyToNull ?: throw RedirectException("emptyImageTitle.html")
34
35                         val uploadedFile = freenetRequest.httpRequest.getUploadedFile("image")
36                         val bytes = uploadedFile.data.use { it.toByteArray() }
37                         val bufferedImage = bytes.toImage()
38                         if (bufferedImage == null) {
39                                 templateContext["messages"] = webInterface.l10n.getString("Page.UploadImage.Error.InvalidImage")
40                                 return
41                         }
42
43                         val temporaryImage = webInterface.core.createTemporaryImage(bytes.mimeType, bytes)
44                         webInterface.core.createImage(currentSone, parentAlbum, temporaryImage).modify().apply {
45                                 setWidth(bufferedImage.width)
46                                 setHeight(bufferedImage.height)
47                                 setTitle(title)
48                                 setDescription(TextFilter.filter(freenetRequest.headers["Host"], freenetRequest.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"