From b901f38c588c4b10e5ac04b117cb0aac476e05bd Mon Sep 17 00:00:00 2001 From: Kohei Tamura Date: Thu, 2 Mar 2017 19:10:15 +0900 Subject: [PATCH] Add a servlet which does not validate upload files --- .../troubles/UnrestrictedUploadServlet.java | 126 ++++++++++++++++++ src/main/resources/messages_en.properties | 2 + src/main/resources/messages_ja.properties | 4 +- 3 files changed, 131 insertions(+), 1 deletion(-) create mode 100644 src/main/java/org/t246osslab/easybuggy/troubles/UnrestrictedUploadServlet.java diff --git a/src/main/java/org/t246osslab/easybuggy/troubles/UnrestrictedUploadServlet.java b/src/main/java/org/t246osslab/easybuggy/troubles/UnrestrictedUploadServlet.java new file mode 100644 index 00000000..a558f9f4 --- /dev/null +++ b/src/main/java/org/t246osslab/easybuggy/troubles/UnrestrictedUploadServlet.java @@ -0,0 +1,126 @@ +package org.t246osslab.easybuggy.troubles; + +import java.awt.image.BufferedImage; +import java.awt.image.WritableRaster; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Locale; + +import javax.imageio.ImageIO; +import javax.servlet.ServletException; +import javax.servlet.annotation.MultipartConfig; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.Part; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.t246osslab.easybuggy.utils.Closer; +import org.t246osslab.easybuggy.utils.HTTPResponseCreator; +import org.t246osslab.easybuggy.utils.MessageUtils; + +@SuppressWarnings("serial") +@WebServlet(urlPatterns = { "/urupload" }) +// 2MB, 10MB, 50MB +// @MultipartConfig(fileSizeThreshold = 1024 * 1024 * 2, maxFileSize = 1024 * 1024 * 10, maxRequestSize = 1024 * 1024 * +// 50) +@MultipartConfig +public class UnrestrictedUploadServlet extends HttpServlet { + + private static Logger log = LoggerFactory.getLogger(DBConnectionLeakServlet.class); + + // Name of the directory where uploaded files is saved + private static final String SAVE_DIR = "uploadFiles"; + + protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { + StringBuilder bodyHtml = new StringBuilder(); + bodyHtml.append("
"); + bodyHtml.append("Select file to upload:
"); + bodyHtml.append("
"); + bodyHtml.append("
"); + HTTPResponseCreator.createSimpleResponse(res, "File Upload", bodyHtml.toString()); + } + + protected void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { + + Locale locale = req.getLocale(); + + // Get absolute path of the web application + String appPath = req.getServletContext().getRealPath(""); + + // Create directory to save uploaded file if it does not exists + String savePath = appPath + File.separator + SAVE_DIR; + File fileSaveDir = new File(savePath); + if (!fileSaveDir.exists()) { + fileSaveDir.mkdir(); + } + + OutputStream out = null; + InputStream in = null; + final Part filePart = req.getPart("file"); + try { + String fileName = getFileName(filePart); + out = new FileOutputStream(savePath + File.separator + fileName); + in = filePart.getInputStream(); + int read = 0; + final byte[] bytes = new byte[1024]; + while ((read = in.read(bytes)) != -1) { + out.write(bytes, 0, read); + } + + // Revere color of the upload image + revereColor(new File(savePath + File.separator + fileName).getAbsolutePath()); + + StringBuilder bodyHtml = new StringBuilder(); + bodyHtml.append(MessageUtils.getMsg("msg.reverse.color.complete", locale)); + bodyHtml.append("

"); + bodyHtml.append(""); + bodyHtml.append("

"); + bodyHtml.append(""); + HTTPResponseCreator.createSimpleResponse(res, "Upload", bodyHtml.toString()); + + } catch (Exception e) { + log.error("Exception occurs: ", e); + } finally { + Closer.close(out, in); + } + } + + private String getFileName(final Part part) { + for (String content : part.getHeader("content-disposition").split(";")) { + if (content.trim().startsWith("filename")) { + return content.substring(content.indexOf('=') + 1).trim().replace("\"", ""); + } + } + return null; + } + + // Revere color of the image file + private void revereColor(String fileName) throws IOException { + try { + BufferedImage image = ImageIO.read(new File(fileName)); + WritableRaster raster = image.getRaster(); + int[] pixelBuffer = new int[raster.getNumDataElements()]; + for (int y = 0; y < raster.getHeight(); y++) { + for (int x = 0; x < raster.getWidth(); x++) { + raster.getPixel(x, y, pixelBuffer); + pixelBuffer[0] = ~pixelBuffer[0]; + pixelBuffer[1] = ~pixelBuffer[1]; + pixelBuffer[2] = ~pixelBuffer[2]; + raster.setPixel(x, y, pixelBuffer); + } + } + // Output the image + ImageIO.write(image, "png", new File(fileName)); + } catch (Exception e) { + // Log and ignore the exception + log.error("Exception occurs: ", e); + } + } +} diff --git a/src/main/resources/messages_en.properties b/src/main/resources/messages_en.properties index 9ee7c45e..a743b2fb 100644 --- a/src/main/resources/messages_en.properties +++ b/src/main/resources/messages_en.properties @@ -7,6 +7,7 @@ label.calculate=Calculate label.character.count=Character Count label.desc=desc label.execution.result=Execution Result: +label.history.back=Back label.json.string=JSON String label.name=Name label.obelus=/ @@ -70,6 +71,7 @@ JavaScript is executed if you set name to >tpircs/<;)\"!SSX\"(trela>tpircs< msg.permgen.space.leak.occur=Memory leak occurs in PermGen space every time you load this page.

\   If keeping on loading this page, OutOfMemoryError is finally thrown. msg.question.reach.the.moon=How many times would you have to fold a piece of paper (thickness 0.1mm) for it to be thick enough to reach the moon (384,400 km)? +msg.reverse.color.complete=The color reversal of the image has completed. msg.socket.leak.occur=Network socket leak occurs every time you load this page. msg.unknown.exception.occur=Unknown exception occurs. msg.update.records=Updated {0} records. diff --git a/src/main/resources/messages_ja.properties b/src/main/resources/messages_ja.properties index ce25bf1a..50def812 100644 --- a/src/main/resources/messages_ja.properties +++ b/src/main/resources/messages_ja.properties @@ -7,9 +7,10 @@ label.calculate=\u8a08\u7b97\u3059\u308b label.character.count=\u6587\u5b57\u6570 label.desc=\u964d\u9806 label.execution.result=\u5b9f\u884c\u7d50\u679c: +label.history.back=\u623b\u308b label.json.string=JSON\u6587\u5b57\u5217 label.name=\u540d\u524d -label.obelus=\u00f7 +label.obelus=÷ label.order=\u9806\u5e8f label.password=\u30d1\u30b9\u30ef\u30fc\u30c9 label.reversed.name=\u9006\u8ee2\u3057\u305f\u540d\u524d @@ -70,6 +71,7 @@ msg.match.regular.expression=\u5165\u529b\u6587\u5b57\u5217\u306f\u6b63\u898f\u8 msg.permgen.space.leak.occur=\u3053\u306e\u30da\u30fc\u30b8\u3092\u8aad\u307f\u8fbc\u3080\u305f\u3073\u306b\u3001Permanent\u9818\u57df\u306e\u30e1\u30e2\u30ea\u30ea\u30fc\u30af\u304c\u767a\u751f\u3057\u307e\u3059\u3002

\   \u753b\u9762\u3092\u30ed\u30fc\u30c9\u3057\u7d9a\u3051\u308b\u3068\u3001\u6700\u7d42\u7684\u306bOutOfMemoryError\u304c\u30b9\u30ed\u30fc\u3055\u308c\u307e\u3059\u3002 msg.question.reach.the.moon=0.1mm\u306e\u539a\u3055\u306e\u7d19\u3092\u4f55\u56de\u6298\u308a\u305f\u305f\u3080\u3068\u3001\u5730\u7403\u304b\u3089\u6708\u306e\u8ddd\u96e2(384,400 km)\u306b\u5230\u9054\u3059\u308b\u3067\u3057\u3087\u3046\u304b\uff1f +msg.reverse.color.complete=\u753b\u50cf\u306e\u8272\u53cd\u8ee2\u304c\u5b8c\u4e86\u3057\u307e\u3057\u305f\u3002 msg.socket.leak.occur=\u3053\u306e\u30da\u30fc\u30b8\u3092\u8aad\u307f\u8fbc\u3080\u305f\u3073\u306b\u3001\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u30bd\u30b1\u30c3\u30c8\u30ea\u30fc\u30af\u304c\u767a\u751f\u3057\u307e\u3059\u3002 msg.unknown.exception.occur=\u4e0d\u660e\u306a\u4f8b\u5916\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 msg.update.records={0}\u4ef6\u66f4\u65b0\u3057\u307e\u3057\u305f\u3002