diff src/nabble/view/web/user/ChangeAvatar2.java @ 0:7ecd1a4ef557

add content
author Franklin Schmidt <fschmidt@gmail.com>
date Thu, 21 Mar 2019 19:15:52 -0600
parents
children 18cf4872fd7f
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/nabble/view/web/user/ChangeAvatar2.java	Thu Mar 21 19:15:52 2019 -0600
@@ -0,0 +1,252 @@
+
+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, response);
+		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, response);
+			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" );
+
+		}
+
+	}
+}
+