1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * This library is free software; you can redistribute it and/or modify it under
5    * the terms of the GNU Lesser General Public License as published by the Free
6    * Software Foundation; either version 2.1 of the License, or (at your option)
7    * any later version.
8    *
9    * This library is distributed in the hope that it will be useful, but WITHOUT
10   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11   * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12   * details.
13   */
14  
15  package com.liferay.portal.servlet;
16  
17  import com.liferay.portal.NoSuchImageException;
18  import com.liferay.portal.kernel.exception.PortalException;
19  import com.liferay.portal.kernel.exception.SystemException;
20  import com.liferay.portal.kernel.image.ImageBag;
21  import com.liferay.portal.kernel.image.ImageProcessorUtil;
22  import com.liferay.portal.kernel.log.Log;
23  import com.liferay.portal.kernel.log.LogFactoryUtil;
24  import com.liferay.portal.kernel.servlet.HttpHeaders;
25  import com.liferay.portal.kernel.util.GetterUtil;
26  import com.liferay.portal.kernel.util.MimeTypesUtil;
27  import com.liferay.portal.kernel.util.ParamUtil;
28  import com.liferay.portal.kernel.util.PropsKeys;
29  import com.liferay.portal.kernel.util.Validator;
30  import com.liferay.portal.model.Company;
31  import com.liferay.portal.model.Image;
32  import com.liferay.portal.model.ImageConstants;
33  import com.liferay.portal.model.User;
34  import com.liferay.portal.security.auth.PrincipalException;
35  import com.liferay.portal.security.auth.PrincipalThreadLocal;
36  import com.liferay.portal.security.permission.PermissionChecker;
37  import com.liferay.portal.security.permission.PermissionCheckerFactoryUtil;
38  import com.liferay.portal.security.permission.PermissionThreadLocal;
39  import com.liferay.portal.service.CompanyLocalServiceUtil;
40  import com.liferay.portal.service.ImageLocalServiceUtil;
41  import com.liferay.portal.service.ImageServiceUtil;
42  import com.liferay.portal.service.UserLocalServiceUtil;
43  import com.liferay.portal.util.PortalUtil;
44  import com.liferay.portal.util.PrefsPropsUtil;
45  import com.liferay.portal.util.PropsValues;
46  import com.liferay.portlet.imagegallery.model.IGImage;
47  import com.liferay.portlet.imagegallery.service.IGImageLocalServiceUtil;
48  import com.liferay.util.servlet.ServletResponseUtil;
49  
50  import java.awt.image.RenderedImage;
51  
52  import java.io.IOException;
53  
54  import java.util.Date;
55  
56  import javax.portlet.PortletPreferences;
57  
58  import javax.servlet.ServletConfig;
59  import javax.servlet.ServletException;
60  import javax.servlet.http.HttpServlet;
61  import javax.servlet.http.HttpServletRequest;
62  import javax.servlet.http.HttpServletResponse;
63  
64  /**
65   * <a href="ImageServlet.java.html"><b><i>View Source</i></b></a>
66   *
67   * @author Brian Wing Shun Chan
68   * @author Brett Randall
69   */
70  public class ImageServlet extends HttpServlet {
71  
72      public void init(ServletConfig servletConfig) throws ServletException {
73          super.init(servletConfig);
74  
75          _lastModified = GetterUtil.getBoolean(
76              servletConfig.getInitParameter("last_modified"), true);
77      }
78  
79      public void service(
80              HttpServletRequest request, HttpServletResponse response)
81          throws IOException, ServletException {
82  
83          try {
84              long companyId = PortalUtil.getCompanyId(request);
85  
86              User user = PortalUtil.getUser(request);
87  
88              if (user == null) {
89                  Company company = CompanyLocalServiceUtil.getCompany(companyId);
90  
91                  user = company.getDefaultUser();
92              }
93  
94              PrincipalThreadLocal.setName(user.getUserId());
95  
96              PermissionChecker permissionChecker =
97                  PermissionCheckerFactoryUtil.create(user, true);
98  
99              PermissionThreadLocal.setPermissionChecker(permissionChecker);
100 
101             if (_lastModified) {
102                 long lastModified = getLastModified(request);
103 
104                 if (lastModified > 0) {
105                     long ifModifiedSince = request.getDateHeader(
106                         HttpHeaders.IF_MODIFIED_SINCE);
107 
108                     if ((ifModifiedSince > 0) &&
109                         (ifModifiedSince == lastModified)) {
110 
111                         response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
112 
113                         return;
114                     }
115                 }
116 
117                 if (lastModified > 0) {
118                     response.setDateHeader(
119                         HttpHeaders.LAST_MODIFIED, lastModified);
120                 }
121             }
122 
123             writeImage(request, response);
124         }
125         catch (Exception e) {
126             PortalUtil.sendError(
127                 HttpServletResponse.SC_NOT_FOUND, e, request, response);
128         }
129     }
130 
131     protected boolean checkIGImageThumbnailMaxDimensions(
132             Image image, long igImageId)
133         throws PortalException, SystemException {
134 
135         PortletPreferences preferences = PrefsPropsUtil.getPreferences();
136 
137         long igThumbnailMaxDimension = GetterUtil.getLong(
138             preferences.getValue(
139                 PropsKeys.IG_IMAGE_THUMBNAIL_MAX_DIMENSION, null));
140 
141         if ((image.getHeight() > igThumbnailMaxDimension) ||
142             (image.getWidth() > igThumbnailMaxDimension)) {
143 
144             IGImage igImage = IGImageLocalServiceUtil.getImage(
145                 igImageId);
146 
147             IGImageLocalServiceUtil.updateSmallImage(
148                 igImage.getSmallImageId(), igImage.getLargeImageId());
149 
150             return true;
151         }
152 
153         return false;
154     }
155 
156     protected boolean checkUserImageMaxDimensions(Image image, long imageId)
157         throws PortalException, SystemException {
158 
159         if ((image.getHeight() > PropsValues.USERS_IMAGE_MAX_HEIGHT) ||
160             (image.getWidth() > PropsValues.USERS_IMAGE_MAX_WIDTH)) {
161 
162             User user = UserLocalServiceUtil.getUserByPortraitId(imageId);
163 
164             UserLocalServiceUtil.updatePortrait(
165                 user.getUserId(), image.getTextObj());
166 
167             return true;
168         }
169 
170         return false;
171     }
172 
173     protected Image getDefaultImage(HttpServletRequest request, long imageId)
174         throws NoSuchImageException {
175 
176         String path = GetterUtil.getString(request.getPathInfo());
177 
178         if (path.startsWith("/company_logo")) {
179             return ImageLocalServiceUtil.getDefaultCompanyLogo();
180         }
181         else if (path.startsWith("/organization_logo")) {
182             return ImageLocalServiceUtil.getDefaultOrganizationLogo();
183         }
184         else if (path.startsWith("/user_female_portrait")) {
185             return ImageLocalServiceUtil.getDefaultUserFemalePortrait();
186         }
187         else if (path.startsWith("/user_male_portrait")) {
188             return ImageLocalServiceUtil.getDefaultUserMalePortrait();
189         }
190         else if (path.startsWith("/user_portrait")) {
191             return ImageLocalServiceUtil.getDefaultUserMalePortrait();
192         }
193         else {
194             throw new NoSuchImageException(
195                 "No default image exists for " + imageId);
196         }
197     }
198 
199     protected Image getImage(HttpServletRequest request, boolean getDefault)
200         throws PortalException, SystemException {
201 
202         long imageId = getImageId(request);
203 
204         Image image = null;
205 
206         if (imageId > 0) {
207             image = ImageServiceUtil.getImage(imageId);
208 
209             String path = GetterUtil.getString(request.getPathInfo());
210 
211             if (path.startsWith("/user_female_portrait") ||
212                 path.startsWith("/user_male_portrait") ||
213                 path.startsWith("/user_portrait")) {
214 
215                 if (checkUserImageMaxDimensions(image, imageId)) {
216                     image = ImageLocalServiceUtil.getImage(imageId);
217                 }
218             }
219             else {
220                 long igImageId = ParamUtil.getLong(request, "igImageId");
221                 boolean igSmallImage = ParamUtil.getBoolean(
222                     request, "igSmallImage");
223 
224                 if ((igImageId > 0) && igSmallImage) {
225                     if (checkIGImageThumbnailMaxDimensions(image, igImageId)) {
226                         image = ImageLocalServiceUtil.getImage(imageId);
227                     }
228                 }
229             }
230         }
231         else {
232             String uuid = ParamUtil.getString(request, "uuid");
233             long groupId = ParamUtil.getLong(request, "groupId");
234 
235             try {
236                 if (Validator.isNotNull(uuid) && (groupId > 0)) {
237                     IGImage igImage =
238                         IGImageLocalServiceUtil.getImageByUuidAndGroupId(
239                             uuid, groupId);
240 
241                     image = ImageLocalServiceUtil.getImage(
242                         igImage.getLargeImageId());
243                 }
244             }
245             catch (Exception e) {
246             }
247         }
248 
249         if (getDefault) {
250             if (image == null) {
251                 if (_log.isWarnEnabled()) {
252                     _log.warn("Get a default image for " + imageId);
253                 }
254 
255                 image = getDefaultImage(request, imageId);
256             }
257         }
258 
259         return image;
260     }
261 
262     protected byte[] getImageBytes(HttpServletRequest request, Image image) {
263         int height = ParamUtil.getInteger(request, "height", image.getHeight());
264         int width = ParamUtil.getInteger(request, "width", image.getWidth());
265 
266         if ((height > image.getHeight()) && (width > image.getWidth())) {
267             return image.getTextObj();
268         }
269 
270         try {
271             ImageBag imageBag = ImageProcessorUtil.read(image.getTextObj());
272 
273             RenderedImage renderedImage = ImageProcessorUtil.scale(
274                 imageBag.getRenderedImage(), height, width);
275 
276             return ImageProcessorUtil.getBytes(
277                 renderedImage, imageBag.getType());
278         }
279         catch (Exception e) {
280             if (_log.isWarnEnabled()) {
281                 _log.warn("Error scaling image " + image.getImageId(), e);
282             }
283         }
284 
285         return image.getTextObj();
286     }
287 
288     protected long getImageId(HttpServletRequest request) {
289 
290         // The image id may be passed in as image_id, img_id, or i_id
291 
292         long imageId = ParamUtil.getLong(request, "image_id");
293 
294         if (imageId <= 0) {
295             imageId = ParamUtil.getLong(request, "img_id");
296         }
297 
298         if (imageId <= 0) {
299             imageId = ParamUtil.getLong(request, "i_id");
300         }
301 
302         if (imageId <= 0) {
303             long companyId = ParamUtil.getLong(request, "companyId");
304             String screenName = ParamUtil.getString(request, "screenName");
305 
306             try {
307                 if ((companyId > 0) && Validator.isNotNull(screenName)) {
308                     User user = UserLocalServiceUtil.getUserByScreenName(
309                         companyId, screenName);
310 
311                     imageId = user.getPortraitId();
312                 }
313             }
314             catch (Exception e) {
315             }
316         }
317 
318         return imageId;
319     }
320 
321     protected long getLastModified(HttpServletRequest request) {
322         try {
323             Image image = getImage(request, false);
324 
325             if (image == null) {
326                 return -1;
327             }
328 
329             Date modifiedDate = image.getModifiedDate();
330 
331             if (modifiedDate == null) {
332                 modifiedDate = PortalUtil.getUptime();
333             }
334 
335             // Round down and remove milliseconds
336 
337             return (modifiedDate.getTime() / 1000) * 1000;
338         }
339         catch (PrincipalException pe) {
340             if (_log.isWarnEnabled()) {
341                 _log.warn(pe, pe);
342             }
343         }
344         catch (Exception e) {
345             _log.error(e, e);
346         }
347 
348         return -1;
349     }
350 
351     protected void writeImage(
352             HttpServletRequest request, HttpServletResponse response)
353         throws PortalException, SystemException {
354 
355         Image image = getImage(request, true);
356 
357         if (image == null) {
358             throw new NoSuchImageException("Image is null");
359         }
360         else {
361             String contentType = null;
362 
363             if (!image.getType().equals(ImageConstants.TYPE_NOT_AVAILABLE)) {
364                 contentType = MimeTypesUtil.getContentType(image.getType());
365 
366                 response.setContentType(contentType);
367             }
368 
369             String fileName = ParamUtil.getString(request, "fileName");
370 
371             try {
372                 byte[] bytes = getImageBytes(request, image);
373 
374                 if (Validator.isNotNull(fileName)) {
375                     ServletResponseUtil.sendFile(
376                         request, response, fileName, bytes, contentType);
377                 }
378                 else {
379                     ServletResponseUtil.write(response, bytes);
380                 }
381             }
382             catch (Exception e) {
383                 if (_log.isWarnEnabled()) {
384                     _log.warn(e, e);
385                 }
386             }
387         }
388     }
389 
390     private static Log _log = LogFactoryUtil.getLog(ImageServlet.class);
391 
392     private boolean _lastModified = true;
393 
394 }