view src/nabble/view/web/user/ChangeAvatar2.java @ 19:18cf4872fd7f

remove anonymous posting
author Franklin Schmidt <fschmidt@gmail.com>
date Fri, 29 May 2020 22:58:25 -0600
parents 7ecd1a4ef557
children
line wrap: on
line source


package nabble.view.web.user;

import fschmidt.util.java.HtmlUtils;
import fschmidt.util.java.ImageUtils;
import fschmidt.util.servlet.JtpContext;
import nabble.model.FileUpload;
import nabble.model.Init;
import nabble.model.Message;
import nabble.model.ModelException;
import nabble.model.User;
import nabble.view.lib.Jtp;
import nabble.view.lib.Shared;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Map;
import java.util.Random;


public final class ChangeAvatar2 extends HttpServlet {

	private static final Logger logger = LoggerFactory.getLogger(ChangeAvatar2.class);

	private static final long SIZE_LIMIT = 4194304; // 4 Mb

	private void handleError(HttpServletRequest request, String errorMessage, PrintWriter out) {
		
		out.print( "\r\n<html>\r\n	<head>\r\n		" );
 Shared.loadJavascript(request, out); 
		out.print( "\r\n		<script type=\"text/javascript\">\r\n			function say() {\r\n				alert(\"" );
		out.print( (HtmlUtils.javascriptStringEncode(errorMessage)) );
		out.print( "\");\r\n				location.replace(\"" );
		out.print( (request.getContextPath()) );
		out.print( "/user/ChangeAvatar.jtp\");\r\n			};\r\n		</script>\r\n	</head>\r\n	<body onload=\"say()\"></body>\r\n</html>\r\n" );

	}

	protected void service(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		JtpContext jtpContext = (JtpContext)getServletContext().getAttribute(JtpContext.attrName);
		jtpContext.setTimeLimit(request,0L);
		PrintWriter out = response.getWriter();
		String context = request.getContextPath();
		User user = Jtp.getUser(request);
		if (user == null) {
			Jtp.login("You must login to change your avatar.", request, response);
			return;
		}

		String errorMessage = null;

		String action = request.getParameter("action");
		if ("crop".equals(action)) {
			String imageName = request.getParameter("image");
			int x = Jtp.getInt(request, "crop_x");
			int y = Jtp.getInt(request, "crop_y");
			int width = Jtp.getInt(request, "crop_width");
			int height = Jtp.getInt(request, "crop_height");
			try {
				Message.Source srcTemp = Message.SourceType.getType('t').getSource(user.getSite(),user.getId());
				InputStream in = FileUpload.getFileContent(srcTemp, imageName);
				if (in == null) {
					handleError(request, "Error uploading image. Please try again.", out);
					return;
				}				
				BufferedImage originalImage = ImageIO.read(in);
				in.close();
				if (originalImage.getWidth() < 100 || originalImage.getHeight() < 100) {
					handleError(request, "The width and height must be greater than 100 pixels.", out);
					return;
				}

				BufferedImage croppedImage100 = ImageUtils.cropImage(originalImage, x, y, width, height);
				croppedImage100 = ImageUtils.getThumbnail(croppedImage100, 100, 100);

				BufferedImage croppedImage24 = ImageUtils.blurImage(croppedImage100);
				croppedImage24 = ImageUtils.resizeImage(croppedImage24, 24, 24);

				user.saveAvatar(croppedImage24,croppedImage100);
				FileUpload.deleteFile(imageName, srcTemp);
			} catch (ModelException e) {
				logger.error(toString(), e);
				errorMessage = e.getMessage();
			}

			if (errorMessage == null) {
				response.sendRedirect("/user/ChangeAvatar2$ReloadAvatars.jtp");
				return;
			} else {
				handleError(request, errorMessage, out);
				return;
			}
		} else if ("delete".equals(action)) {
			user.deleteAvatar();
			response.sendRedirect("/user/ChangeAvatar2$ReloadAvatars.jtp");
			return;
		}

		int imageWidth = 0;
		int imageHeight = 0;
		String fileName = "_user" + user.getId() + ".png";
		try {
			final Map<String, FileItem> map;
			try {
				map = Jtp.getFileItems(request);
			} catch (FileUploadException e) {
				logger.warn("",e);
				throw ModelException.newInstance("upload_avatar_failed","upload failed - " + e.getMessage());
			}
			FileItem fi = map.get("image");

			if (fi == null) {
				handleError(request, "Image upload failed.", out);
				return;
			} else if (fi.getSize() > SIZE_LIMIT) {
				handleError(request, "The file you uploaded is too big. Please upload a smaller image (less than 4Mb).", out);
				return;
			}

			InputStream in = fi.getInputStream();
			BufferedImage image;
			try {
				image = ImageIO.read(in);
			} catch (javax.imageio.IIOException e) {
				handleError(request, "The uploaded image is broken.", out);
				return;
			} finally {
				in.close();
			}
			if (image == null) {
				handleError(request, "Please upload the image again.", out);
				return;
			} else if (image.getWidth() < 100 || image.getHeight() < 100) {
				handleError(request, "The width and height must be greater than 100 pixels.", out);
				return;
			} else if (image.getWidth() > 800 || image.getHeight() > 800) {
				try {
					image = ImageUtils.getThumbnail(image, 800, 800);
				} catch (RuntimeException e) {
					// This catch block will be improved later when I discover the exact line that throws
					// a RuntimeException in ImageUtils [Hugo - April/2010]
					if (fi.getSize() <= FileUpload.MAX_IMAGE_SIZE) {
						if( Init.tempDir == null ) {
							logger.info("Init.tempDir == null");
						} else {
							FileOutputStream fos = new FileOutputStream(Init.tempDir + FileUpload.getName(fi));
							fos.write(fi.get());
							fos.close();
						}
					}
					handleError(request, "Unable to handle this image.", out);
					return;
				}
			}

			imageWidth = image.getWidth();
			imageHeight = image.getHeight();

			Message.Source tempSrc = Message.SourceType.getType('t').getSource(user.getSite(),user.getId());
			FileUpload.saveImage(image, fileName, tempSrc);
		} catch (ModelException e) {
			errorMessage = e.getMessage();
			logger.warn("image upload failed", e);
		}

		if (errorMessage != null) {
			handleError(request, errorMessage, out);
			return;
		}
		
		out.print( "\r\n<html>\r\n<head>\r\n	" );
 Shared.title(request,response,"Change Avatar"); 
		out.print( "\r\n	<style type=\"text/css\">\r\n		#imageContainer{\r\n			margin:15px;\r\n			left:0px;\r\n			top:0px;\r\n			position:relative;\r\n		}\r\n\r\n		.crop_transparentDiv{\r\n			background-color:#FFF;\r\n			filter:alpha(opacity=80);\r\n			-khtml-opacity: 0.8;\r\n			-moz-opacity: 0.8;\r\n			opacity:0.8;\r\n			position:absolute;\r\n		}\r\n		.crop_dottedDiv{\r\n			position:absolute;\r\n			border:1px dotted red;\r\n			z-index:10000;\r\n		}\r\n\r\n		.crop_dottedDiv div{\r\n			filter:alpha(opacity=0);\r\n			opacity:0;\r\n			-khtml-opacity: 0;\r\n			-moz-opacity: 0;\r\n			width:100%;\r\n			height:100%;\r\n			background-color:#FFF;\r\n		}\r\n	</style>\r\n	<script type=\"text/javascript\">\r\n		var crop_script_alwaysPreserveAspectRatio = true; // Always preserve aspect ratio\r\n		var crop_script_fixedRatio = 1; // Width relative to height 2 = ratio 2:1\r\n\r\n		var cropToolBorderWidth = 1; // Width of dotted border around crop rectangle\r\n		var smallSquareWidth = 7; // Size of small squares used to resize crop rectangle\r\n\r\n		// Size of image shown in crop tool\r\n		var crop_imageWidth = " );
		out.print( (imageWidth) );
		out.print( ";\r\n		var crop_imageHeight = " );
		out.print( (imageHeight) );
		out.print( ";\r\n\r\n		// Size of original image\r\n		var crop_originalImageWidth = crop_imageWidth;\r\n		var crop_originalImageHeight = crop_imageHeight;\r\n\r\n		var crop_minimumPercent = 10; // Minimum percent - resize\r\n		var crop_maximumPercent = 100; // Maximum percent -resize\r\n\r\n		var crop_minimumWidthHeight = 100; // Minimum width and height of crop area\r\n\r\n		var updateFormValuesAsYouDrag = true; // This variable indicates if form values should be updated as we drag. This process could make the script work a little bit slow. That's why this option is set as a variable.\r\n		if(!document.all)updateFormValuesAsYouDrag = false; // Enable this feature only in IE\r\n	</script>\r\n	<script src=\"" );
		out.print( (context) );
		out.print( "/util/image-crop.js\" type=\"text/javascript\"></script>\r\n</head>\r\n<body>\r\n" );

		Shared.minHeaderGlobal(request, response);
		Shared.profileHeading(request,out,user,"Change Avatar - Crop Image");
		
		out.print( "\r\n<b>Please select a square region on the image below.</b><br/>\r\nYou can drag the red handles to resize the square or drag the whole selected area.\r\n<br/><br/>\r\n<form action=\"/user/ChangeAvatar2.jtp\" method=\"POST\" accept-charset=\"UTF-8\">\r\n	<input type=\"hidden\" name=\"action\" value=\"crop\">\r\n	<input type=\"hidden\" name=\"image\" value=\"" );
		out.print( (fileName) );
		out.print( "\">\r\n	<input type=\"hidden\" name=\"crop_x\" id=\"input_crop_x\">\r\n	<input type=\"hidden\" name=\"crop_y\" id=\"input_crop_y\">\r\n	<input type=\"hidden\" name=\"crop_width\" id=\"input_crop_width\">\r\n	<input type=\"hidden\" name=\"crop_height\" id=\"input_crop_height\">\r\n	<input type=\"hidden\" name=\"crop_percent_size\" id=\"crop_percent_size\">\r\n	<input type=\"submit\" value=\"Crop Image\">\r\n</form>\r\n<div class=\"crop_content\">\r\n	<div id=\"imageContainer\">\r\n		" );

					// Here I create a random number that is appended to the end
					// of the image URL. This prevents the browser from showing an
					// old cached image.
					Random random = new Random();
					int any = random.nextInt(1000);
				
		out.print( "\r\n<img src=\"/file/t" );
		out.print( (user.getId()) );
		out.print( "/" );
		out.print( (fileName) );
		out.print( "?" );
		out.print( (any) );
		out.print( "\"/>\r\n</div>\r\n</div>\r\n\r\n<script type=\"text/javascript\">\r\ninit_imageCrop('http://" );
		out.print( (request.getHeader("host")) );
		out.print( "');\r\n\r\nif (Nabble.isEmbedded) {\r\n$(window).load(Nabble.resizeFrames);\r\n}\r\n</script>\r\n\r\n" );
 Shared.footer(request,response); 
		out.print( "\r\n" );
 Shared.analytics(request,response); 
		out.print( "\r\n</body>\r\n</html>\r\n" );

	}

	public static class ReloadAvatars extends HttpServlet {

		protected void service(HttpServletRequest request, HttpServletResponse response)
				throws ServletException, IOException
		{
			/*
			This servlet is a tricky way to force the browser to reload the user avatars.
			Since we don't specify cache headers for images, browsers cache them using
			internal algorithms. The only way to update those images is by refreshing the page
			either by pressing F5 or using location.reload(true).
			*/
			PrintWriter out = response.getWriter();
			User user = Jtp.getUser(request);
			if (user == null)
				return;
			Jtp.dontCache(response);
			
		out.print( "\r\n<html>\r\n	<head>\r\n		" );
 Shared.loadJavascript(request, out); 
		out.print( "\r\n		<script type=\"text/javascript\">\r\n			function init() {\r\n				var done = Nabble.getCookie('done');\r\n				if (done) {\r\n					Nabble.deleteCookie('done');\r\n					location = '/template/NamlServlet.jtp?macro=user_profile';\r\n				} else {\r\n					Nabble.setCookie('done','y');\r\n					location.reload(true);\r\n				}\r\n			};\r\n		</script>\r\n	</head>\r\n	<body onload=\"init()\">\r\n		<div style=\"display:none\">\r\n			<img src=\"" );
		out.print( (Shared.getAvatarImageURL(user, false)) );
		out.print( "\"/>\r\n			<img src=\"" );
		out.print( (Shared.getAvatarImageURL(user, true)) );
		out.print( "\"/>\r\n		</div>\r\n	</body>\r\n</html>\r\n" );

		}

	}
}