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