comparison src/nabble/view/web/user/ChangeAvatar2.jtp @ 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 <html>
42 <head>
43 <% Shared.loadJavascript(request, out); %>
44 <script type="text/javascript">
45 function say() {
46 alert("<%=HtmlUtils.javascriptStringEncode(errorMessage)%>");
47 location.replace("<%=request.getContextPath()%>/user/ChangeAvatar.jtp");
48 };
49 </script>
50 </head>
51 <body onload="say()"></body>
52 </html>
53 <%
54 }
55
56 protected void service(HttpServletRequest request, HttpServletResponse response)
57 throws ServletException, IOException {
58 JtpContext jtpContext = (JtpContext)getServletContext().getAttribute(JtpContext.attrName);
59 jtpContext.setTimeLimit(request,0L);
60 PrintWriter out = response.getWriter();
61 String context = request.getContextPath();
62 User user = Jtp.getUser(request, response);
63 if (user == null) {
64 Jtp.login("You must login to change your avatar.", request, response);
65 return;
66 }
67
68 String errorMessage = null;
69
70 String action = request.getParameter("action");
71 if ("crop".equals(action)) {
72 String imageName = request.getParameter("image");
73 int x = Jtp.getInt(request, "crop_x");
74 int y = Jtp.getInt(request, "crop_y");
75 int width = Jtp.getInt(request, "crop_width");
76 int height = Jtp.getInt(request, "crop_height");
77 try {
78 Message.Source srcTemp = Message.SourceType.getType('t').getSource(user.getSite(),user.getId());
79 InputStream in = FileUpload.getFileContent(srcTemp, imageName);
80 if (in == null) {
81 handleError(request, "Error uploading image. Please try again.", out);
82 return;
83 }
84 BufferedImage originalImage = ImageIO.read(in);
85 in.close();
86 if (originalImage.getWidth() < 100 || originalImage.getHeight() < 100) {
87 handleError(request, "The width and height must be greater than 100 pixels.", out);
88 return;
89 }
90
91 BufferedImage croppedImage100 = ImageUtils.cropImage(originalImage, x, y, width, height);
92 croppedImage100 = ImageUtils.getThumbnail(croppedImage100, 100, 100);
93
94 BufferedImage croppedImage24 = ImageUtils.blurImage(croppedImage100);
95 croppedImage24 = ImageUtils.resizeImage(croppedImage24, 24, 24);
96
97 user.saveAvatar(croppedImage24,croppedImage100);
98 FileUpload.deleteFile(imageName, srcTemp);
99 } catch (ModelException e) {
100 logger.error(toString(), e);
101 errorMessage = e.getMessage();
102 }
103
104 if (errorMessage == null) {
105 response.sendRedirect("/user/ChangeAvatar2$ReloadAvatars.jtp");
106 return;
107 } else {
108 handleError(request, errorMessage, out);
109 return;
110 }
111 } else if ("delete".equals(action)) {
112 user.deleteAvatar();
113 response.sendRedirect("/user/ChangeAvatar2$ReloadAvatars.jtp");
114 return;
115 }
116
117 int imageWidth = 0;
118 int imageHeight = 0;
119 String fileName = "_user" + user.getId() + ".png";
120 try {
121 final Map<String, FileItem> map;
122 try {
123 map = Jtp.getFileItems(request);
124 } catch (FileUploadException e) {
125 logger.warn("",e);
126 throw ModelException.newInstance("upload_avatar_failed","upload failed - " + e.getMessage());
127 }
128 FileItem fi = map.get("image");
129
130 if (fi == null) {
131 handleError(request, "Image upload failed.", out);
132 return;
133 } else if (fi.getSize() > SIZE_LIMIT) {
134 handleError(request, "The file you uploaded is too big. Please upload a smaller image (less than 4Mb).", out);
135 return;
136 }
137
138 InputStream in = fi.getInputStream();
139 BufferedImage image;
140 try {
141 image = ImageIO.read(in);
142 } catch (javax.imageio.IIOException e) {
143 handleError(request, "The uploaded image is broken.", out);
144 return;
145 } finally {
146 in.close();
147 }
148 if (image == null) {
149 handleError(request, "Please upload the image again.", out);
150 return;
151 } else if (image.getWidth() < 100 || image.getHeight() < 100) {
152 handleError(request, "The width and height must be greater than 100 pixels.", out);
153 return;
154 } else if (image.getWidth() > 800 || image.getHeight() > 800) {
155 try {
156 image = ImageUtils.getThumbnail(image, 800, 800);
157 } catch (RuntimeException e) {
158 // This catch block will be improved later when I discover the exact line that throws
159 // a RuntimeException in ImageUtils [Hugo - April/2010]
160 if (fi.getSize() <= FileUpload.MAX_IMAGE_SIZE) {
161 if( Init.tempDir == null ) {
162 logger.info("Init.tempDir == null");
163 } else {
164 FileOutputStream fos = new FileOutputStream(Init.tempDir + FileUpload.getName(fi));
165 fos.write(fi.get());
166 fos.close();
167 }
168 }
169 handleError(request, "Unable to handle this image.", out);
170 return;
171 }
172 }
173
174 imageWidth = image.getWidth();
175 imageHeight = image.getHeight();
176
177 Message.Source tempSrc = Message.SourceType.getType('t').getSource(user.getSite(),user.getId());
178 FileUpload.saveImage(image, fileName, tempSrc);
179 } catch (ModelException e) {
180 errorMessage = e.getMessage();
181 logger.warn("image upload failed", e);
182 }
183
184 if (errorMessage != null) {
185 handleError(request, errorMessage, out);
186 return;
187 }
188 %>
189 <html>
190 <head>
191 <% Shared.title(request,response,"Change Avatar"); %>
192 <style type="text/css">
193 #imageContainer{
194 margin:15px;
195 left:0px;
196 top:0px;
197 position:relative;
198 }
199
200 .crop_transparentDiv{
201 background-color:#FFF;
202 filter:alpha(opacity=80);
203 -khtml-opacity: 0.8;
204 -moz-opacity: 0.8;
205 opacity:0.8;
206 position:absolute;
207 }
208 .crop_dottedDiv{
209 position:absolute;
210 border:1px dotted red;
211 z-index:10000;
212 }
213
214 .crop_dottedDiv div{
215 filter:alpha(opacity=0);
216 opacity:0;
217 -khtml-opacity: 0;
218 -moz-opacity: 0;
219 width:100%;
220 height:100%;
221 background-color:#FFF;
222 }
223 </style>
224 <script type="text/javascript">
225 var crop_script_alwaysPreserveAspectRatio = true; // Always preserve aspect ratio
226 var crop_script_fixedRatio = 1; // Width relative to height 2 = ratio 2:1
227
228 var cropToolBorderWidth = 1; // Width of dotted border around crop rectangle
229 var smallSquareWidth = 7; // Size of small squares used to resize crop rectangle
230
231 // Size of image shown in crop tool
232 var crop_imageWidth = <%=imageWidth%>;
233 var crop_imageHeight = <%=imageHeight%>;
234
235 // Size of original image
236 var crop_originalImageWidth = crop_imageWidth;
237 var crop_originalImageHeight = crop_imageHeight;
238
239 var crop_minimumPercent = 10; // Minimum percent - resize
240 var crop_maximumPercent = 100; // Maximum percent -resize
241
242 var crop_minimumWidthHeight = 100; // Minimum width and height of crop area
243
244 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.
245 if(!document.all)updateFormValuesAsYouDrag = false; // Enable this feature only in IE
246 </script>
247 <script src="<%=context%>/util/image-crop.js" type="text/javascript"></script>
248 </head>
249 <body>
250 <%
251 Shared.minHeaderGlobal(request, response);
252 Shared.profileHeading(request,out,user,"Change Avatar - Crop Image");
253 %>
254 <b>Please select a square region on the image below.</b><br/>
255 You can drag the red handles to resize the square or drag the whole selected area.
256 <br/><br/>
257 <form action="/user/ChangeAvatar2.jtp" method="POST" accept-charset="UTF-8">
258 <input type="hidden" name="action" value="crop">
259 <input type="hidden" name="image" value="<%=fileName%>">
260 <input type="hidden" name="crop_x" id="input_crop_x">
261 <input type="hidden" name="crop_y" id="input_crop_y">
262 <input type="hidden" name="crop_width" id="input_crop_width">
263 <input type="hidden" name="crop_height" id="input_crop_height">
264 <input type="hidden" name="crop_percent_size" id="crop_percent_size">
265 <input type="submit" value="Crop Image">
266 </form>
267 <div class="crop_content">
268 <div id="imageContainer">
269 <%
270 // Here I create a random number that is appended to the end
271 // of the image URL. This prevents the browser from showing an
272 // old cached image.
273 Random random = new Random();
274 int any = random.nextInt(1000);
275 %>
276 <img src="/file/t<%=user.getId()%>/<%=fileName%>?<%=any%>"/>
277 </div>
278 </div>
279
280 <script type="text/javascript">
281 init_imageCrop('http://<%=request.getHeader("host")%>');
282
283 if (Nabble.isEmbedded) {
284 $(window).load(Nabble.resizeFrames);
285 }
286 </script>
287
288 <% Shared.footer(request,response); %>
289 <% Shared.analytics(request,response); %>
290 </body>
291 </html>
292 <%
293 }
294
295 public static class ReloadAvatars extends HttpServlet {
296
297 protected void service(HttpServletRequest request, HttpServletResponse response)
298 throws ServletException, IOException
299 {
300 /*
301 This servlet is a tricky way to force the browser to reload the user avatars.
302 Since we don't specify cache headers for images, browsers cache them using
303 internal algorithms. The only way to update those images is by refreshing the page
304 either by pressing F5 or using location.reload(true).
305 */
306 PrintWriter out = response.getWriter();
307 User user = Jtp.getUser(request, response);
308 if (user == null)
309 return;
310 Jtp.dontCache(response);
311 %>
312 <html>
313 <head>
314 <% Shared.loadJavascript(request, out); %>
315 <script type="text/javascript">
316 function init() {
317 var done = Nabble.getCookie('done');
318 if (done) {
319 Nabble.deleteCookie('done');
320 location = '/template/NamlServlet.jtp?macro=user_profile';
321 } else {
322 Nabble.setCookie('done','y');
323 location.reload(true);
324 }
325 };
326 </script>
327 </head>
328 <body onload="init()">
329 <div style="display:none">
330 <img src="<%=Shared.getAvatarImageURL(user, false)%>"/>
331 <img src="<%=Shared.getAvatarImageURL(user, true)%>"/>
332 </div>
333 </body>
334 </html>
335 <%
336 }
337
338 }
339 }
340 %>