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.util.servlet;
16  
17  import com.liferay.portal.kernel.log.Log;
18  import com.liferay.portal.kernel.log.LogFactoryUtil;
19  import com.liferay.portal.kernel.servlet.BrowserSnifferUtil;
20  import com.liferay.portal.kernel.servlet.HttpHeaders;
21  import com.liferay.portal.kernel.util.ArrayUtil;
22  import com.liferay.portal.kernel.util.FileUtil;
23  import com.liferay.portal.kernel.util.GetterUtil;
24  import com.liferay.portal.kernel.util.PropsUtil;
25  import com.liferay.portal.kernel.util.StreamUtil;
26  import com.liferay.portal.kernel.util.StringPool;
27  import com.liferay.portal.kernel.util.StringUtil;
28  import com.liferay.portal.kernel.util.Validator;
29  import com.liferay.portal.util.PortalUtil;
30  
31  import java.io.IOException;
32  import java.io.InputStream;
33  import java.io.OutputStream;
34  
35  import javax.portlet.MimeResponse;
36  import javax.portlet.PortletRequest;
37  import javax.portlet.ResourceResponse;
38  
39  import javax.servlet.http.HttpServletRequest;
40  
41  import org.apache.commons.codec.net.URLCodec;
42  import org.apache.commons.lang.CharUtils;
43  
44  /**
45   * <a href="PortletResponseUtil.java.html"><b><i>View Source</i></b></a>
46   *
47   * @author Brian Wing Shun Chan
48   */
49  public class PortletResponseUtil {
50  
51      /**
52       * @deprecated
53       */
54      public static void sendFile(
55              MimeResponse mimeResponse, String fileName, byte[] bytes)
56          throws IOException {
57  
58          sendFile(null, mimeResponse, fileName, bytes);
59      }
60  
61      /**
62       * @deprecated
63       */
64      public static void sendFile(
65              MimeResponse mimeResponse, String fileName, byte[] bytes,
66              String contentType)
67          throws IOException {
68  
69          sendFile(null, mimeResponse, fileName, bytes, contentType);
70      }
71  
72      /**
73       * @deprecated
74       */
75      public static void sendFile(
76              MimeResponse mimeResponse, String fileName, InputStream is)
77          throws IOException {
78  
79          sendFile(null, mimeResponse, fileName, is);
80      }
81  
82      /**
83       * @deprecated
84       */
85      public static void sendFile(
86              MimeResponse mimeResponse, String fileName, InputStream is,
87              int contentLength, String contentType)
88          throws IOException {
89  
90          sendFile(null, mimeResponse, fileName, is, contentLength, contentType);
91      }
92  
93      /**
94       * @deprecated
95       */
96      public static void sendFile(
97              MimeResponse mimeResponse, String fileName, InputStream is,
98              String contentType)
99          throws IOException {
100 
101         sendFile(null, mimeResponse, fileName, is, contentType);
102     }
103 
104     public static void sendFile(
105             PortletRequest portletRequest, MimeResponse mimeResponse,
106             String fileName, byte[] bytes)
107         throws IOException {
108 
109         sendFile(portletRequest, mimeResponse, fileName, bytes, null);
110     }
111 
112     public static void sendFile(
113             PortletRequest portletRequest, MimeResponse mimeResponse,
114             String fileName, byte[] bytes, String contentType)
115         throws IOException {
116 
117         setHeaders(portletRequest, mimeResponse, fileName, contentType);
118 
119         write(mimeResponse, bytes);
120     }
121 
122     public static void sendFile(
123             PortletRequest portletRequest, MimeResponse mimeResponse,
124             String fileName, InputStream is)
125         throws IOException {
126 
127         sendFile(portletRequest, mimeResponse, fileName, is, null);
128     }
129 
130     public static void sendFile(
131             PortletRequest portletRequest, MimeResponse mimeResponse,
132             String fileName, InputStream is, int contentLength,
133             String contentType)
134         throws IOException {
135 
136         setHeaders(portletRequest, mimeResponse, fileName, contentType);
137 
138         write(mimeResponse, is, contentLength);
139     }
140 
141     public static void sendFile(
142             PortletRequest portletRequest, MimeResponse mimeResponse,
143             String fileName, InputStream is, String contentType)
144         throws IOException {
145 
146         sendFile(portletRequest, mimeResponse, fileName, is, 0, contentType);
147     }
148 
149     public static void write(MimeResponse mimeResponse, byte[] bytes)
150         throws IOException {
151 
152         write(mimeResponse, bytes, 0);
153     }
154 
155     public static void write(
156             MimeResponse mimeResponse, byte[] bytes, int contentLength)
157         throws IOException {
158 
159         // LEP-3122
160 
161         if (!mimeResponse.isCommitted()) {
162 
163             // LEP-536
164 
165             if (contentLength == 0) {
166                 contentLength = bytes.length;
167             }
168 
169             if (mimeResponse instanceof ResourceResponse) {
170                 ResourceResponse resourceResponse =
171                     (ResourceResponse)mimeResponse;
172 
173                 resourceResponse.setContentLength(contentLength);
174             }
175 
176             OutputStream outputStream = mimeResponse.getPortletOutputStream();
177 
178             outputStream.write(bytes, 0, contentLength);
179         }
180     }
181 
182     public static void write(MimeResponse mimeResponse, InputStream is)
183         throws IOException {
184 
185         write(mimeResponse, is, 0);
186     }
187 
188     public static void write(
189             MimeResponse mimeResponse, InputStream is, int contentLength)
190         throws IOException {
191 
192         if (mimeResponse.isCommitted()) {
193             return;
194         }
195 
196         if (contentLength > 0) {
197             if (mimeResponse instanceof ResourceResponse) {
198                 ResourceResponse resourceResponse =
199                     (ResourceResponse)mimeResponse;
200 
201                 resourceResponse.setContentLength(contentLength);
202             }
203         }
204 
205         StreamUtil.transfer(is, mimeResponse.getPortletOutputStream());
206     }
207 
208     public static void write(MimeResponse mimeResponse, String s)
209         throws IOException {
210 
211         write(mimeResponse, s.getBytes(StringPool.UTF8));
212     }
213 
214     protected static void setHeaders(
215         PortletRequest portletRequest, MimeResponse mimeResponse,
216         String fileName, String contentType) {
217 
218         if (_log.isDebugEnabled()) {
219             _log.debug("Sending file of type " + contentType);
220         }
221 
222         // LEP-2201
223 
224         if (Validator.isNotNull(contentType)) {
225             mimeResponse.setContentType(contentType);
226         }
227 
228         mimeResponse.setProperty(
229             HttpHeaders.CACHE_CONTROL, HttpHeaders.CACHE_CONTROL_PUBLIC_VALUE);
230         mimeResponse.setProperty(
231             HttpHeaders.PRAGMA, HttpHeaders.PRAGMA_PUBLIC_VALUE);
232 
233         if (Validator.isNotNull(fileName)) {
234             String contentDisposition =
235                 "attachment; filename=\"" + fileName + "\"";
236 
237             // If necessary for non-ASCII characters, encode based on RFC 2184.
238             // However, not all browsers support RFC 2184. See LEP-3127.
239 
240             boolean ascii = true;
241 
242             for (int i = 0; i < fileName.length(); i++) {
243                 if (!CharUtils.isAscii(fileName.charAt(i))) {
244                     ascii = false;
245 
246                     break;
247                 }
248             }
249 
250             try {
251                 if (!ascii) {
252                     URLCodec codec = new URLCodec(StringPool.UTF8);
253 
254                     String encodedFileName =
255                         StringUtil.replace(codec.encode(fileName), "+", "%20");
256 
257                     HttpServletRequest request =
258                         PortalUtil.getHttpServletRequest(portletRequest);
259 
260                     if (BrowserSnifferUtil.isIe(request)) {
261                         contentDisposition =
262                             "attachment; filename=\"" + encodedFileName + "\"";
263                     }
264                     else {
265                         contentDisposition =
266                             "attachment; filename*=UTF-8''" + encodedFileName;
267                     }
268                 }
269             }
270             catch (Exception e) {
271                 if (_log.isWarnEnabled()) {
272                     _log.warn(e);
273                 }
274             }
275 
276             String extension = GetterUtil.getString(
277                 FileUtil.getExtension(fileName)).toLowerCase();
278 
279             String[] mimeTypesContentDispositionInline = null;
280 
281             try {
282                 mimeTypesContentDispositionInline = PropsUtil.getArray(
283                     "mime.types.content.disposition.inline");
284             }
285             catch (Exception e) {
286                 mimeTypesContentDispositionInline = new String[0];
287             }
288 
289             if (ArrayUtil.contains(
290                     mimeTypesContentDispositionInline, extension)) {
291 
292                 contentDisposition = StringUtil.replace(
293                     contentDisposition, "attachment; ", "inline; ");
294             }
295 
296             mimeResponse.setProperty(
297                 HttpHeaders.CONTENT_DISPOSITION, contentDisposition);
298         }
299     }
300 
301     private static Log _log = LogFactoryUtil.getLog(PortletResponseUtil.class);
302 
303 }