1   /**
2    * Copyright (c) 2000-2009 Liferay, Inc. All rights reserved.
3    *
4    *
5    *
6    *
7    * The contents of this file are subject to the terms of the Liferay Enterprise
8    * Subscription License ("License"). You may not use this file except in
9    * compliance with the License. You can obtain a copy of the License by
10   * contacting Liferay, Inc. See the License for the specific language governing
11   * permissions and limitations under the License, including but not limited to
12   * distribution rights of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package com.liferay.util.servlet;
24  
25  import com.liferay.portal.kernel.log.Log;
26  import com.liferay.portal.kernel.log.LogFactoryUtil;
27  import com.liferay.portal.kernel.servlet.HttpHeaders;
28  import com.liferay.portal.kernel.util.ArrayUtil;
29  import com.liferay.portal.kernel.util.FileUtil;
30  import com.liferay.portal.kernel.util.GetterUtil;
31  import com.liferay.portal.kernel.util.PropsUtil;
32  import com.liferay.portal.kernel.util.StreamUtil;
33  import com.liferay.portal.kernel.util.StringPool;
34  import com.liferay.portal.kernel.util.StringUtil;
35  import com.liferay.portal.kernel.util.Validator;
36  
37  import java.io.IOException;
38  import java.io.InputStream;
39  import java.io.OutputStream;
40  
41  import javax.portlet.MimeResponse;
42  import javax.portlet.ResourceResponse;
43  
44  import org.apache.commons.codec.net.URLCodec;
45  import org.apache.commons.lang.CharUtils;
46  
47  /**
48   * <a href="PortletResponseUtil.java.html"><b><i>View Source</i></b></a>
49   *
50   * @author Brian Wing Shun Chan
51   */
52  public class PortletResponseUtil {
53  
54      public static void sendFile(
55              MimeResponse mimeResponse, String fileName, byte[] bytes)
56          throws IOException {
57  
58          sendFile(mimeResponse, fileName, bytes, null);
59      }
60  
61      public static void sendFile(
62              MimeResponse mimeResponse, String fileName, byte[] bytes,
63              String contentType)
64          throws IOException {
65  
66          setHeaders(mimeResponse, fileName, contentType);
67  
68          write(mimeResponse, bytes);
69      }
70  
71      public static void sendFile(
72              MimeResponse mimeResponse, String fileName, InputStream is)
73          throws IOException {
74  
75          sendFile(mimeResponse, fileName, is, null);
76      }
77  
78      public static void sendFile(
79              MimeResponse mimeResponse, String fileName, InputStream is,
80              String contentType)
81          throws IOException {
82  
83          sendFile(mimeResponse, fileName, is, 0, contentType);
84      }
85  
86      public static void sendFile(
87              MimeResponse mimeResponse, String fileName, InputStream is,
88              int contentLength, String contentType)
89          throws IOException {
90  
91          setHeaders(mimeResponse, fileName, contentType);
92  
93          write(mimeResponse, is, contentLength);
94      }
95  
96      public static void write(MimeResponse mimeResponse, String s)
97          throws IOException {
98  
99          write(mimeResponse, s.getBytes(StringPool.UTF8));
100     }
101 
102     public static void write(MimeResponse mimeResponse, byte[] bytes)
103         throws IOException {
104 
105         write(mimeResponse, bytes, 0);
106     }
107 
108     public static void write(
109             MimeResponse mimeResponse, byte[] bytes, int contentLength)
110         throws IOException {
111 
112         // LEP-3122
113 
114         if (!mimeResponse.isCommitted()) {
115 
116             // LEP-536
117 
118             if (contentLength == 0) {
119                 contentLength = bytes.length;
120             }
121 
122             if (mimeResponse instanceof ResourceResponse) {
123                 ResourceResponse resourceResponse =
124                     (ResourceResponse)mimeResponse;
125 
126                 resourceResponse.setContentLength(contentLength);
127             }
128 
129             OutputStream outputStream = mimeResponse.getPortletOutputStream();
130 
131             outputStream.write(bytes, 0, contentLength);
132         }
133     }
134 
135     public static void write(MimeResponse mimeResponse, InputStream is)
136         throws IOException {
137 
138         write(mimeResponse, is, 0);
139     }
140 
141     public static void write(
142             MimeResponse mimeResponse, InputStream is, int contentLength)
143         throws IOException {
144 
145         if (mimeResponse.isCommitted()) {
146             return;
147         }
148 
149         if (contentLength > 0) {
150             if (mimeResponse instanceof ResourceResponse) {
151                 ResourceResponse resourceResponse =
152                     (ResourceResponse)mimeResponse;
153 
154                 resourceResponse.setContentLength(contentLength);
155             }
156         }
157 
158         StreamUtil.transfer(is, mimeResponse.getPortletOutputStream());
159     }
160 
161     protected static void setHeaders(
162         MimeResponse mimeResponse, String fileName, String contentType) {
163 
164         if (_log.isDebugEnabled()) {
165             _log.debug("Sending file of type " + contentType);
166         }
167 
168         // LEP-2201
169 
170         if (Validator.isNotNull(contentType)) {
171             mimeResponse.setContentType(contentType);
172         }
173 
174         mimeResponse.setProperty(
175             HttpHeaders.CACHE_CONTROL, HttpHeaders.CACHE_CONTROL_PUBLIC_VALUE);
176         mimeResponse.setProperty(
177             HttpHeaders.PRAGMA, HttpHeaders.PRAGMA_PUBLIC_VALUE);
178 
179         if (Validator.isNotNull(fileName)) {
180             String contentDisposition =
181                 "attachment; filename=\"" + fileName + "\"";
182 
183             // If necessary for non-ASCII characters, encode based on RFC 2184.
184             // However, not all browsers support RFC 2184. See LEP-3127.
185 
186             boolean ascii = true;
187 
188             for (int i = 0; i < fileName.length(); i++) {
189                 if (!CharUtils.isAscii(fileName.charAt(i))) {
190                     ascii = false;
191 
192                     break;
193                 }
194             }
195 
196             try {
197                 if (!ascii) {
198                     URLCodec codec = new URLCodec(StringPool.UTF8);
199 
200                     String encodedFileName =
201                         StringUtil.replace(codec.encode(fileName), "+", "%20");
202 
203                     contentDisposition =
204                         "attachment; filename*=UTF-8''" + encodedFileName;
205                 }
206             }
207             catch (Exception e) {
208                 if (_log.isWarnEnabled()) {
209                     _log.warn(e);
210                 }
211             }
212 
213             String extension = GetterUtil.getString(
214                 FileUtil.getExtension(fileName)).toLowerCase();
215 
216             String[] mimeTypesContentDispositionInline = null;
217 
218             try {
219                 mimeTypesContentDispositionInline = PropsUtil.getArray(
220                     "mime.types.content.disposition.inline");
221             }
222             catch (Exception e) {
223                 mimeTypesContentDispositionInline = new String[0];
224             }
225 
226             if (ArrayUtil.contains(
227                     mimeTypesContentDispositionInline, extension)) {
228 
229                 contentDisposition = StringUtil.replace(
230                     contentDisposition, "attachment; ", "inline; ");
231             }
232 
233             mimeResponse.setProperty(
234                 HttpHeaders.CONTENT_DISPOSITION, contentDisposition);
235         }
236     }
237 
238     private static Log _log = LogFactoryUtil.getLog(PortletResponseUtil.class);
239 
240 }