0
|
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 %>
|