From 51ab1ab2da27d02a884295cea31c4f6d30b5211b Mon Sep 17 00:00:00 2001 From: =?utf8?q?David=20=E2=80=98Bombe=E2=80=99=20Roden?= Date: Sun, 4 Jun 2017 19:12:35 +0200 Subject: [PATCH] Replace upload image page with Kotlin version --- .../sone/web/pages/UploadImagePage.java | 170 --------------------- .../sone/web/pages/UploadImagePage.kt | 72 +++++++++ 2 files changed, 72 insertions(+), 170 deletions(-) delete mode 100644 src/main/java/net/pterodactylus/sone/web/pages/UploadImagePage.java create mode 100644 src/main/kotlin/net/pterodactylus/sone/web/pages/UploadImagePage.kt diff --git a/src/main/java/net/pterodactylus/sone/web/pages/UploadImagePage.java b/src/main/java/net/pterodactylus/sone/web/pages/UploadImagePage.java deleted file mode 100644 index 6b77132..0000000 --- a/src/main/java/net/pterodactylus/sone/web/pages/UploadImagePage.java +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Sone - UploadImagePage.java - Copyright © 2011–2016 David Roden - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package net.pterodactylus.sone.web.pages; - -import static com.google.common.base.Optional.fromNullable; -import static java.util.logging.Logger.getLogger; - -import java.awt.Image; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.Iterator; -import java.util.logging.Level; -import java.util.logging.Logger; - -import javax.imageio.ImageIO; -import javax.imageio.ImageReader; -import javax.imageio.stream.ImageInputStream; - -import net.pterodactylus.sone.data.Album; -import net.pterodactylus.sone.data.Image.Modifier.ImageTitleMustNotBeEmpty; -import net.pterodactylus.sone.data.Sone; -import net.pterodactylus.sone.data.TemporaryImage; -import net.pterodactylus.sone.text.TextFilter; -import net.pterodactylus.sone.web.WebInterface; -import net.pterodactylus.sone.web.page.FreenetRequest; -import net.pterodactylus.util.io.Closer; -import net.pterodactylus.util.template.Template; -import net.pterodactylus.util.template.TemplateContext; -import net.pterodactylus.util.web.Method; - -import com.google.common.io.ByteStreams; - -import freenet.support.api.Bucket; -import freenet.support.api.HTTPUploadedFile; - -/** - * Page implementation that lets the user upload an image. - * - * @author David ‘Bombe’ Roden - */ -public class UploadImagePage extends SoneTemplatePage { - - private static final Logger logger = getLogger(UploadImagePage.class.getName()); - private static final String UNKNOWN_MIME_TYPE = "application/octet-stream"; - - /** - * Creates a new “upload image” page. - * - * @param template - * The template to render - * @param webInterface - * The Sone web interface - */ - public UploadImagePage(Template template, WebInterface webInterface) { - super("uploadImage.html", template, "Page.UploadImage.Title", webInterface, true); - } - - // - // SONETEMPLATEPAGE METHODS - // - - /** - * {@inheritDoc} - */ - @Override - protected void handleRequest(FreenetRequest request, TemplateContext templateContext) throws RedirectException { - if (request.getMethod() == Method.POST) { - Sone currentSone = getCurrentSone(request.getToadletContext()); - String parentId = request.getHttpRequest().getPartAsStringFailsafe("parent", 36); - Album parent = webInterface.getCore().getAlbum(parentId); - if (parent == null) { - throw new RedirectException("noPermission.html"); - } - if (!currentSone.equals(parent.getSone())) { - throw new RedirectException("noPermission.html"); - } - String name = request.getHttpRequest().getPartAsStringFailsafe("title", 200).trim(); - if (name.length() == 0) { - throw new RedirectException("emptyImageTitle.html"); - } - String description = request.getHttpRequest().getPartAsStringFailsafe("description", 4000); - HTTPUploadedFile uploadedFile = request.getHttpRequest().getUploadedFile("image"); - Bucket fileBucket = uploadedFile.getData(); - InputStream imageInputStream = null; - ByteArrayOutputStream imageDataOutputStream = null; - try { - imageInputStream = fileBucket.getInputStream(); - /* TODO - check length */ - imageDataOutputStream = new ByteArrayOutputStream((int) fileBucket.size()); - ByteStreams.copy(imageInputStream, imageDataOutputStream); - } catch (IOException ioe1) { - logger.log(Level.WARNING, "Could not read uploaded image!", ioe1); - return; - } finally { - fileBucket.free(); - Closer.close(imageInputStream); - Closer.close(imageDataOutputStream); - } - byte[] imageData = imageDataOutputStream.toByteArray(); - ByteArrayInputStream imageDataInputStream = null; - Image uploadedImage = null; - try { - imageDataInputStream = new ByteArrayInputStream(imageData); - uploadedImage = ImageIO.read(imageDataInputStream); - if (uploadedImage == null) { - templateContext.set("messages", webInterface.getL10n().getString("Page.UploadImage.Error.InvalidImage")); - return; - } - String mimeType = getMimeType(imageData); - TemporaryImage temporaryImage = webInterface.getCore().createTemporaryImage(mimeType, imageData); - net.pterodactylus.sone.data.Image image = webInterface.getCore().createImage(currentSone, parent, temporaryImage); - image.modify().setTitle(name).setDescription(TextFilter.filter(request.getHttpRequest().getHeader("host"), description)).setWidth(uploadedImage.getWidth(null)).setHeight(uploadedImage.getHeight(null)).update(); - } catch (IOException ioe1) { - logger.log(Level.WARNING, "Could not read uploaded image!", ioe1); - return; - } catch (ImageTitleMustNotBeEmpty itmnbe) { - throw new RedirectException("emptyImageTitle.html"); - } finally { - Closer.close(imageDataInputStream); - Closer.flush(uploadedImage); - } - throw new RedirectException("imageBrowser.html?album=" + parent.getId()); - } - } - - // - // PRIVATE METHODS - // - - /** - * Tries to detect the MIME type of the encoded image. - * - * @param imageData - * The encoded image - * @return The MIME type of the image, or “application/octet-stream” if the - * image type could not be detected - */ - private static String getMimeType(byte[] imageData) { - ByteArrayInputStream imageDataInputStream = new ByteArrayInputStream(imageData); - try { - ImageInputStream imageInputStream = ImageIO.createImageInputStream(imageDataInputStream); - Iterator imageReaders = ImageIO.getImageReaders(imageInputStream); - if (imageReaders.hasNext()) { - return fromNullable(imageReaders.next().getOriginatingProvider().getMIMETypes()) - .or(new String[] { UNKNOWN_MIME_TYPE })[0]; - } - } catch (IOException ioe1) { - logger.log(Level.FINE, "Could not detect MIME type for image.", ioe1); - } - return UNKNOWN_MIME_TYPE; - } - -} diff --git a/src/main/kotlin/net/pterodactylus/sone/web/pages/UploadImagePage.kt b/src/main/kotlin/net/pterodactylus/sone/web/pages/UploadImagePage.kt new file mode 100644 index 0000000..774a179 --- /dev/null +++ b/src/main/kotlin/net/pterodactylus/sone/web/pages/UploadImagePage.kt @@ -0,0 +1,72 @@ +package net.pterodactylus.sone.web.pages + +import freenet.support.api.Bucket +import net.pterodactylus.sone.text.TextFilter +import net.pterodactylus.sone.utils.emptyToNull +import net.pterodactylus.sone.utils.headers +import net.pterodactylus.sone.utils.isPOST +import net.pterodactylus.sone.utils.parameters +import net.pterodactylus.sone.utils.use +import net.pterodactylus.sone.web.WebInterface +import net.pterodactylus.sone.web.page.FreenetRequest +import net.pterodactylus.util.template.Template +import net.pterodactylus.util.template.TemplateContext +import org.bouncycastle.asn1.x500.style.RFC4519Style.title +import java.awt.image.BufferedImage +import java.io.ByteArrayInputStream +import java.io.ByteArrayOutputStream +import javax.imageio.ImageIO + +/** + * Page implementation that lets the user upload an image. + */ +class UploadImagePage(template: Template, webInterface: WebInterface): + SoneTemplatePage("uploadImage.html", template, "Page.UploadImage.Title", webInterface, true) { + + override fun handleRequest(request: FreenetRequest, templateContext: TemplateContext) { + if (request.isPOST) { + val parentAlbum = request.parameters["parent"]!!.let(webInterface.core::getAlbum) ?: throw RedirectException("noPermission.html") + if (parentAlbum.sone != getCurrentSone(request.toadletContext)) { + throw RedirectException("noPermission.html") + } + val title = request.parameters["title", 200].emptyToNull ?: throw RedirectException("emptyImageTitle.html") + + val uploadedFile = request.httpRequest.getUploadedFile("image") + val bytes = uploadedFile.data.use { it.toByteArray() } + val bufferedImage = bytes.toImage() + if (bufferedImage == null) { + templateContext["messages"] = webInterface.l10n.getString("Page.UploadImage.Error.InvalidImage") + return + } + + val temporaryImage = webInterface.core.createTemporaryImage(bytes.mimeType, bytes) + webInterface.core.createImage(getCurrentSone(request.toadletContext), parentAlbum, temporaryImage).modify().apply { + setWidth(bufferedImage.width) + setHeight(bufferedImage.height) + setTitle(title) + setDescription(TextFilter.filter(request.headers["Host"], request.parameters["description", 4000])) + }.update() + throw RedirectException("imageBrowser.html?album=${parentAlbum.id}") + } + } + + private fun Bucket.toByteArray(): ByteArray = ByteArrayOutputStream(size().toInt()).use { outputStream -> + inputStream.copyTo(outputStream) + outputStream.toByteArray() + } + + private fun ByteArray.toImage(): BufferedImage? = ByteArrayInputStream(this).use { + ImageIO.read(it) + } + + private val ByteArray.mimeType get() = ByteArrayInputStream(this).use { + ImageIO.createImageInputStream(it).use { + ImageIO.getImageReaders(it).asSequence() + .firstOrNull()?.originatingProvider?.mimeTypes?.firstOrNull() + ?: UNKNOWN_MIME_TYPE + } + } + +} + +private const val UNKNOWN_MIME_TYPE = "application/octet-stream" -- 2.7.4