Mercurial Hosting > nabble
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 |