comparison 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
comparison
equal deleted inserted replaced
-1:000000000000 0:7ecd1a4ef557
1
2 package nabble.view.web.user;
3
4 import fschmidt.util.java.HtmlUtils;
5 import fschmidt.util.java.ImageUtils;
6 import fschmidt.util.servlet.JtpContext;
7 import nabble.model.FileUpload;
8 import nabble.model.Init;
9 import nabble.model.Message;
10 import nabble.model.ModelException;
11 import nabble.model.User;
12 import nabble.view.lib.Jtp;
13 import nabble.view.lib.Shared;
14 import org.apache.commons.fileupload.FileItem;
15 import org.apache.commons.fileupload.FileUploadException;
16 import org.slf4j.Logger;
17 import org.slf4j.LoggerFactory;
18
19 import javax.imageio.ImageIO;
20 import javax.servlet.ServletException;
21 import javax.servlet.http.HttpServlet;
22 import javax.servlet.http.HttpServletRequest;
23 import javax.servlet.http.HttpServletResponse;
24 import java.awt.image.BufferedImage;
25 import java.io.FileOutputStream;
26 import java.io.IOException;
27 import java.io.InputStream;
28 import java.io.PrintWriter;
29 import java.util.Map;
30 import java.util.Random;
31
32
33 public final class ChangeAvatar2 extends HttpServlet {
34
35 private static final Logger logger = LoggerFactory.getLogger(ChangeAvatar2.class);
36
37 private static final long SIZE_LIMIT = 4194304; // 4 Mb
38
39 private void handleError(HttpServletRequest request, String errorMessage, PrintWriter out) {
40
41 out.print( "\r\n<html>\r\n <head>\r\n " );
42 Shared.loadJavascript(request, out);
43 out.print( "\r\n <script type=\"text/javascript\">\r\n function say() {\r\n alert(\"" );
44 out.print( (HtmlUtils.javascriptStringEncode(errorMessage)) );
45 out.print( "\");\r\n location.replace(\"" );
46 out.print( (request.getContextPath()) );
47 out.print( "/user/ChangeAvatar.jtp\");\r\n };\r\n </script>\r\n </head>\r\n <body onload=\"say()\"></body>\r\n</html>\r\n" );
48
49 }
50
51 protected void service(HttpServletRequest request, HttpServletResponse response)
52 throws ServletException, IOException {
53 JtpContext jtpContext = (JtpContext)getServletContext().getAttribute(JtpContext.attrName);
54 jtpContext.setTimeLimit(request,0L);
55 PrintWriter out = response.getWriter();
56 String context = request.getContextPath();
57 User user = Jtp.getUser(request, response);
58 if (user == null) {
59 Jtp.login("You must login to change your avatar.", request, response);
60 return;
61 }
62
63 String errorMessage = null;
64
65 String action = request.getParameter("action");
66 if ("crop".equals(action)) {
67 String imageName = request.getParameter("image");
68 int x = Jtp.getInt(request, "crop_x");
69 int y = Jtp.getInt(request, "crop_y");
70 int width = Jtp.getInt(request, "crop_width");
71 int height = Jtp.getInt(request, "crop_height");
72 try {
73 Message.Source srcTemp = Message.SourceType.getType('t').getSource(user.getSite(),user.getId());
74 InputStream in = FileUpload.getFileContent(srcTemp, imageName);
75 if (in == null) {
76 handleError(request, "Error uploading image. Please try again.", out);
77 return;
78 }
79 BufferedImage originalImage = ImageIO.read(in);
80 in.close();
81 if (originalImage.getWidth() < 100 || originalImage.getHeight() < 100) {
82 handleError(request, "The width and height must be greater than 100 pixels.", out);
83 return;
84 }
85
86 BufferedImage croppedImage100 = ImageUtils.cropImage(originalImage, x, y, width, height);
87 croppedImage100 = ImageUtils.getThumbnail(croppedImage100, 100, 100);
88
89 BufferedImage croppedImage24 = ImageUtils.blurImage(croppedImage100);
90 croppedImage24 = ImageUtils.resizeImage(croppedImage24, 24, 24);
91
92 user.saveAvatar(croppedImage24,croppedImage100);
93 FileUpload.deleteFile(imageName, srcTemp);
94 } catch (ModelException e) {
95 logger.error(toString(), e);
96 errorMessage = e.getMessage();
97 }
98
99 if (errorMessage == null) {
100 response.sendRedirect("/user/ChangeAvatar2$ReloadAvatars.jtp");
101 return;
102 } else {
103 handleError(request, errorMessage, out);
104 return;
105 }
106 } else if ("delete".equals(action)) {
107 user.deleteAvatar();
108 response.sendRedirect("/user/ChangeAvatar2$ReloadAvatars.jtp");
109 return;
110 }
111
112 int imageWidth = 0;
113 int imageHeight = 0;
114 String fileName = "_user" + user.getId() + ".png";
115 try {
116 final Map<String, FileItem> map;
117 try {
118 map = Jtp.getFileItems(request);
119 } catch (FileUploadException e) {
120 logger.warn("",e);
121 throw ModelException.newInstance("upload_avatar_failed","upload failed - " + e.getMessage());
122 }
123 FileItem fi = map.get("image");
124
125 if (fi == null) {
126 handleError(request, "Image upload failed.", out);
127 return;
128 } else if (fi.getSize() > SIZE_LIMIT) {
129 handleError(request, "The file you uploaded is too big. Please upload a smaller image (less than 4Mb).", out);
130 return;
131 }
132
133 InputStream in = fi.getInputStream();
134 BufferedImage image;
135 try {
136 image = ImageIO.read(in);
137 } catch (javax.imageio.IIOException e) {
138 handleError(request, "The uploaded image is broken.", out);
139 return;
140 } finally {
141 in.close();
142 }
143 if (image == null) {
144 handleError(request, "Please upload the image again.", out);
145 return;
146 } else if (image.getWidth() < 100 || image.getHeight() < 100) {
147 handleError(request, "The width and height must be greater than 100 pixels.", out);
148 return;
149 } else if (image.getWidth() > 800 || image.getHeight() > 800) {
150 try {
151 image = ImageUtils.getThumbnail(image, 800, 800);
152 } catch (RuntimeException e) {
153 // This catch block will be improved later when I discover the exact line that throws
154 // a RuntimeException in ImageUtils [Hugo - April/2010]
155 if (fi.getSize() <= FileUpload.MAX_IMAGE_SIZE) {
156 if( Init.tempDir == null ) {
157 logger.info("Init.tempDir == null");
158 } else {
159 FileOutputStream fos = new FileOutputStream(Init.tempDir + FileUpload.getName(fi));
160 fos.write(fi.get());
161 fos.close();
162 }
163 }
164 handleError(request, "Unable to handle this image.", out);
165 return;
166 }
167 }
168
169 imageWidth = image.getWidth();
170 imageHeight = image.getHeight();
171
172 Message.Source tempSrc = Message.SourceType.getType('t').getSource(user.getSite(),user.getId());
173 FileUpload.saveImage(image, fileName, tempSrc);
174 } catch (ModelException e) {
175 errorMessage = e.getMessage();
176 logger.warn("image upload failed", e);
177 }
178
179 if (errorMessage != null) {
180 handleError(request, errorMessage, out);
181 return;
182 }
183
184 out.print( "\r\n<html>\r\n<head>\r\n " );
185 Shared.title(request,response,"Change Avatar");
186 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 = " );
187 out.print( (imageWidth) );
188 out.print( ";\r\n var crop_imageHeight = " );
189 out.print( (imageHeight) );
190 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=\"" );
191 out.print( (context) );
192 out.print( "/util/image-crop.js\" type=\"text/javascript\"></script>\r\n</head>\r\n<body>\r\n" );
193
194 Shared.minHeaderGlobal(request, response);
195 Shared.profileHeading(request,out,user,"Change Avatar - Crop Image");
196
197 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=\"" );
198 out.print( (fileName) );
199 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 " );
200
201 // Here I create a random number that is appended to the end
202 // of the image URL. This prevents the browser from showing an
203 // old cached image.
204 Random random = new Random();
205 int any = random.nextInt(1000);
206
207 out.print( "\r\n<img src=\"/file/t" );
208 out.print( (user.getId()) );
209 out.print( "/" );
210 out.print( (fileName) );
211 out.print( "?" );
212 out.print( (any) );
213 out.print( "\"/>\r\n</div>\r\n</div>\r\n\r\n<script type=\"text/javascript\">\r\ninit_imageCrop('http://" );
214 out.print( (request.getHeader("host")) );
215 out.print( "');\r\n\r\nif (Nabble.isEmbedded) {\r\n$(window).load(Nabble.resizeFrames);\r\n}\r\n</script>\r\n\r\n" );
216 Shared.footer(request,response);
217 out.print( "\r\n" );
218 Shared.analytics(request,response);
219 out.print( "\r\n</body>\r\n</html>\r\n" );
220
221 }
222
223 public static class ReloadAvatars extends HttpServlet {
224
225 protected void service(HttpServletRequest request, HttpServletResponse response)
226 throws ServletException, IOException
227 {
228 /*
229 This servlet is a tricky way to force the browser to reload the user avatars.
230 Since we don't specify cache headers for images, browsers cache them using
231 internal algorithms. The only way to update those images is by refreshing the page
232 either by pressing F5 or using location.reload(true).
233 */
234 PrintWriter out = response.getWriter();
235 User user = Jtp.getUser(request, response);
236 if (user == null)
237 return;
238 Jtp.dontCache(response);
239
240 out.print( "\r\n<html>\r\n <head>\r\n " );
241 Shared.loadJavascript(request, out);
242 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=\"" );
243 out.print( (Shared.getAvatarImageURL(user, false)) );
244 out.print( "\"/>\r\n <img src=\"" );
245 out.print( (Shared.getAvatarImageURL(user, true)) );
246 out.print( "\"/>\r\n </div>\r\n </body>\r\n</html>\r\n" );
247
248 }
249
250 }
251 }
252