001    /**
002     * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.upload;
016    
017    import com.liferay.portal.kernel.io.ByteArrayFileInputStream;
018    import com.liferay.portal.kernel.log.Log;
019    import com.liferay.portal.kernel.log.LogFactoryUtil;
020    import com.liferay.portal.kernel.upload.FileItem;
021    import com.liferay.portal.kernel.upload.UploadException;
022    import com.liferay.portal.kernel.upload.UploadServletRequest;
023    import com.liferay.portal.kernel.util.ArrayUtil;
024    import com.liferay.portal.kernel.util.FileUtil;
025    import com.liferay.portal.kernel.util.ProgressTracker;
026    import com.liferay.portal.kernel.util.PropsKeys;
027    import com.liferay.portal.kernel.util.StringBundler;
028    import com.liferay.portal.kernel.util.SystemProperties;
029    import com.liferay.portal.kernel.util.Validator;
030    import com.liferay.portal.util.PrefsPropsUtil;
031    import com.liferay.portal.util.WebKeys;
032    
033    import java.io.File;
034    import java.io.IOException;
035    import java.io.InputStream;
036    
037    import java.util.ArrayList;
038    import java.util.Collections;
039    import java.util.Enumeration;
040    import java.util.HashMap;
041    import java.util.LinkedHashMap;
042    import java.util.LinkedHashSet;
043    import java.util.List;
044    import java.util.Map;
045    import java.util.Set;
046    
047    import javax.servlet.ServletInputStream;
048    import javax.servlet.http.HttpServletRequest;
049    import javax.servlet.http.HttpServletRequestWrapper;
050    import javax.servlet.http.HttpSession;
051    
052    import org.apache.commons.fileupload.FileUploadBase;
053    import org.apache.commons.fileupload.servlet.ServletFileUpload;
054    
055    /**
056     * @author Brian Wing Shun Chan
057     * @author Zongliang Li
058     * @author Harry Mark
059     * @author Raymond Aug??
060     */
061    public class UploadServletRequestImpl
062            extends HttpServletRequestWrapper implements UploadServletRequest {
063    
064            public static File getTempDir() {
065                    if (_tempDir == null) {
066                            _tempDir = new File(
067                                    PrefsPropsUtil.getString(
068                                            PropsKeys.UPLOAD_SERVLET_REQUEST_IMPL_TEMP_DIR,
069                                            SystemProperties.get(SystemProperties.TMP_DIR)));
070                    }
071    
072                    return _tempDir;
073            }
074    
075            public static void setTempDir(File tempDir) {
076                    _tempDir = tempDir;
077            }
078    
079            public UploadServletRequestImpl(HttpServletRequest request) {
080                    super(request);
081    
082                    _fileParameters = new LinkedHashMap<>();
083                    _regularParameters = new LinkedHashMap<>();
084    
085                    LiferayServletRequest liferayServletRequest = null;
086    
087                    try {
088                            HttpSession session = request.getSession();
089    
090                            session.removeAttribute(ProgressTracker.PERCENT);
091    
092                            ServletFileUpload servletFileUpload = new ServletFileUpload(
093                                    new LiferayFileItemFactory(getTempDir()));
094    
095                            servletFileUpload.setSizeMax(
096                                    PrefsPropsUtil.getLong(
097                                            PropsKeys.UPLOAD_SERVLET_REQUEST_IMPL_MAX_SIZE));
098    
099                            liferayServletRequest = new LiferayServletRequest(request);
100    
101                            List<org.apache.commons.fileupload.FileItem> fileItems =
102                                    servletFileUpload.parseRequest(liferayServletRequest);
103    
104                            liferayServletRequest.setFinishedReadingOriginalStream(true);
105    
106                            for (org.apache.commons.fileupload.FileItem fileItem : fileItems) {
107                                    LiferayFileItem liferayFileItem = (LiferayFileItem)fileItem;
108    
109                                    if (liferayFileItem.isFormField()) {
110                                            liferayFileItem.setString(request.getCharacterEncoding());
111    
112                                            String fieldName = liferayFileItem.getFieldName();
113    
114                                            if (!_regularParameters.containsKey(fieldName)) {
115                                                    _regularParameters.put(
116                                                            fieldName, new ArrayList<String>());
117                                            }
118    
119                                            List<String> values = _regularParameters.get(fieldName);
120    
121                                            if (liferayFileItem.getSize() >
122                                                            LiferayFileItem.THRESHOLD_SIZE) {
123    
124                                                    StringBundler sb = new StringBundler(5);
125    
126                                                    sb.append("The field ");
127                                                    sb.append(fieldName);
128                                                    sb.append(" exceeds its maximum permitted size of ");
129                                                    sb.append(LiferayFileItem.THRESHOLD_SIZE);
130                                                    sb.append(" bytes");
131    
132                                                    UploadException uploadException = new UploadException(
133                                                            sb.toString());
134    
135                                                    uploadException.setExceededLiferayFileItemSizeLimit(
136                                                            true);
137                                                    uploadException.setExceededSizeLimit(true);
138    
139                                                    request.setAttribute(
140                                                            WebKeys.UPLOAD_EXCEPTION, uploadException);
141                                            }
142    
143                                            values.add(liferayFileItem.getEncodedString());
144    
145                                            continue;
146                                    }
147    
148                                    FileItem[] liferayFileItems = _fileParameters.get(
149                                            liferayFileItem.getFieldName());
150    
151                                    if (liferayFileItems == null) {
152                                            liferayFileItems = new LiferayFileItem[] {liferayFileItem};
153                                    }
154                                    else {
155                                            LiferayFileItem[] newLiferayFileItems =
156                                                    new LiferayFileItem[liferayFileItems.length + 1];
157    
158                                            System.arraycopy(
159                                                    liferayFileItems, 0, newLiferayFileItems, 0,
160                                                    liferayFileItems.length);
161    
162                                            newLiferayFileItems[newLiferayFileItems.length - 1] =
163                                                    liferayFileItem;
164    
165                                            liferayFileItems = newLiferayFileItems;
166                                    }
167    
168                                    _fileParameters.put(
169                                            liferayFileItem.getFieldName(), liferayFileItems);
170                            }
171                    }
172                    catch (Exception e) {
173                            UploadException uploadException = new UploadException(e);
174    
175                            if (e instanceof FileUploadBase.FileSizeLimitExceededException ||
176                                    e instanceof FileUploadBase.SizeLimitExceededException ) {
177    
178                                    uploadException.setExceededSizeLimit(true);
179                            }
180    
181                            request.setAttribute(WebKeys.UPLOAD_EXCEPTION, uploadException);
182    
183                            if (_log.isDebugEnabled()) {
184                                    _log.debug(e, e);
185                            }
186                    }
187    
188                    _liferayServletRequest = liferayServletRequest;
189            }
190    
191            public UploadServletRequestImpl(
192                    HttpServletRequest request, Map<String, FileItem[]> fileParams,
193                    Map<String, List<String>> regularParams) {
194    
195                    super(request);
196    
197                    _fileParameters = new LinkedHashMap<>();
198                    _regularParameters = new LinkedHashMap<>();
199    
200                    if (fileParams != null) {
201                            _fileParameters.putAll(fileParams);
202                    }
203    
204                    if (regularParams != null) {
205                            _regularParameters.putAll(regularParams);
206                    }
207    
208                    _liferayServletRequest = null;
209            }
210    
211            @Override
212            public void cleanUp() {
213                    if ((_fileParameters != null) && !_fileParameters.isEmpty()) {
214                            for (FileItem[] liferayFileItems : _fileParameters.values()) {
215                                    for (FileItem liferayFileItem : liferayFileItems) {
216                                            liferayFileItem.delete();
217                                    }
218                            }
219                    }
220    
221                    _liferayServletRequest.cleanUp();
222            }
223    
224            @Override
225            public String getContentType(String name) {
226                    FileItem[] liferayFileItems = _fileParameters.get(name);
227    
228                    if (ArrayUtil.isNotEmpty(liferayFileItems)) {
229                            FileItem liferayFileItem = liferayFileItems[0];
230    
231                            return liferayFileItem.getContentType();
232                    }
233    
234                    return null;
235            }
236    
237            @Override
238            public File getFile(String name) {
239                    return getFile(name, false);
240            }
241    
242            @Override
243            public File getFile(String name, boolean forceCreate) {
244                    if (getFileName(name) == null) {
245                            return null;
246                    }
247    
248                    FileItem[] liferayFileItems = _fileParameters.get(name);
249    
250                    if (ArrayUtil.isEmpty(liferayFileItems)) {
251                            return null;
252                    }
253    
254                    FileItem liferayFileItem = liferayFileItems[0];
255    
256                    long size = liferayFileItem.getSize();
257    
258                    if ((size > 0) && (size <= liferayFileItem.getSizeThreshold())) {
259                            forceCreate = true;
260                    }
261    
262                    File file = liferayFileItem.getStoreLocation();
263    
264                    if (liferayFileItem.isInMemory() && forceCreate) {
265                            try {
266                                    FileUtil.write(file, liferayFileItem.getInputStream());
267                            }
268                            catch (IOException ioe) {
269                                    if (_log.isWarnEnabled()) {
270                                            _log.warn(
271                                                    "Unable to write temporary file " +
272                                                            file.getAbsolutePath(),
273                                                    ioe);
274                                    }
275                            }
276                    }
277    
278                    return file;
279            }
280    
281            @Override
282            public InputStream getFileAsStream(String name) throws IOException {
283                    return getFileAsStream(name, true);
284            }
285    
286            @Override
287            public InputStream getFileAsStream(String name, boolean deleteOnClose)
288                    throws IOException {
289    
290                    if (getFileName(name) == null) {
291                            return null;
292                    }
293    
294                    InputStream inputStream = null;
295    
296                    FileItem[] liferayFileItems = _fileParameters.get(name);
297    
298                    if (ArrayUtil.isNotEmpty(liferayFileItems)) {
299                            FileItem liferayFileItem = liferayFileItems[0];
300    
301                            inputStream = getInputStream(liferayFileItem, deleteOnClose);
302                    }
303    
304                    return inputStream;
305            }
306    
307            @Override
308            public String getFileName(String name) {
309                    FileItem[] liferayFileItems = _fileParameters.get(name);
310    
311                    if (ArrayUtil.isNotEmpty(liferayFileItems)) {
312                            FileItem liferayFileItem = liferayFileItems[0];
313    
314                            return liferayFileItem.getFileName();
315                    }
316    
317                    return null;
318            }
319    
320            @Override
321            public String[] getFileNames(String name) {
322                    FileItem[] liferayFileItems = _fileParameters.get(name);
323    
324                    if (ArrayUtil.isNotEmpty(liferayFileItems)) {
325                            String[] fileNames = new String[liferayFileItems.length];
326    
327                            for (int i = 0; i < liferayFileItems.length; i++) {
328                                    FileItem liferayFileItem = liferayFileItems[i];
329    
330                                    fileNames[i] = liferayFileItem.getFileName();
331                            }
332    
333                            return fileNames;
334                    }
335    
336                    return null;
337            }
338    
339            @Override
340            public File[] getFiles(String name) {
341                    String[] fileNames = getFileNames(name);
342    
343                    if (fileNames == null) {
344                            return null;
345                    }
346    
347                    FileItem[] liferayFileItems = _fileParameters.get(name);
348    
349                    if (ArrayUtil.isNotEmpty(liferayFileItems)) {
350                            File[] files = new File[liferayFileItems.length];
351    
352                            for (int i = 0; i < liferayFileItems.length; i++) {
353                                    FileItem liferayFileItem = liferayFileItems[i];
354    
355                                    if (Validator.isNotNull(liferayFileItem.getFileName())) {
356                                            files[i] = liferayFileItem.getStoreLocation();
357                                    }
358                            }
359    
360                            return files;
361                    }
362    
363                    return null;
364            }
365    
366            @Override
367            public InputStream[] getFilesAsStream(String name) throws IOException {
368                    return getFilesAsStream(name, true);
369            }
370    
371            @Override
372            public InputStream[] getFilesAsStream(String name, boolean deleteOnClose)
373                    throws IOException {
374    
375                    String[] fileNames = getFileNames(name);
376    
377                    if (fileNames == null) {
378                            return null;
379                    }
380    
381                    InputStream[] inputStreams = null;
382    
383                    FileItem[] liferayFileItems = _fileParameters.get(name);
384    
385                    if (ArrayUtil.isNotEmpty(liferayFileItems)) {
386                            inputStreams = new InputStream[liferayFileItems.length];
387    
388                            for (int i = 0; i < liferayFileItems.length; i++) {
389                                    FileItem liferayFileItem = liferayFileItems[i];
390    
391                                    if (Validator.isNotNull(liferayFileItem.getFileName())) {
392                                            inputStreams[i] = getInputStream(
393                                                    liferayFileItem, deleteOnClose);
394                                    }
395                            }
396                    }
397    
398                    return inputStreams;
399            }
400    
401            @Override
402            public String getFullFileName(String name) {
403                    FileItem[] liferayFileItems = _fileParameters.get(name);
404    
405                    if (ArrayUtil.isNotEmpty(liferayFileItems)) {
406                            FileItem liferayFileItem = liferayFileItems[0];
407    
408                            return liferayFileItem.getFullFileName();
409                    }
410    
411                    return null;
412            }
413    
414            @Override
415            public ServletInputStream getInputStream() throws IOException {
416                    if (_liferayServletRequest != null) {
417                            return _liferayServletRequest.getInputStream();
418                    }
419    
420                    return super.getInputStream();
421            }
422    
423            @Override
424            public Map<String, FileItem[]> getMultipartParameterMap() {
425                    return _fileParameters;
426            }
427    
428            @Override
429            public String getParameter(String name) {
430                    List<String> values = _regularParameters.get(name);
431    
432                    if ((values != null) && !values.isEmpty()) {
433                            return values.get(0);
434                    }
435    
436                    return super.getParameter(name);
437            }
438    
439            @Override
440            public Map<String, String[]> getParameterMap() {
441                    Map<String, String[]> map = new HashMap<>();
442    
443                    Enumeration<String> enu = getParameterNames();
444    
445                    while (enu.hasMoreElements()) {
446                            String name = enu.nextElement();
447    
448                            String[] values = getParameterValues(name);
449    
450                            if (values != null) {
451                                    map.put(name, values);
452                            }
453                    }
454    
455                    return map;
456            }
457    
458            @Override
459            public Enumeration<String> getParameterNames() {
460                    Set<String> parameterNames = new LinkedHashSet<>();
461    
462                    Enumeration<String> enu = super.getParameterNames();
463    
464                    while (enu.hasMoreElements()) {
465                            parameterNames.add(enu.nextElement());
466                    }
467    
468                    parameterNames.addAll(_regularParameters.keySet());
469                    parameterNames.addAll(_fileParameters.keySet());
470    
471                    return Collections.enumeration(parameterNames);
472            }
473    
474            @Override
475            public String[] getParameterValues(String name) {
476                    String[] parameterValues = null;
477    
478                    List<String> values = _regularParameters.get(name);
479    
480                    if (values != null) {
481                            parameterValues = values.toArray(new String[values.size()]);
482                    }
483    
484                    String[] parentParameterValues = super.getParameterValues(name);
485    
486                    if (parameterValues == null) {
487                            return parentParameterValues;
488                    }
489                    else if (parentParameterValues == null) {
490                            return parameterValues;
491                    }
492    
493                    return ArrayUtil.append(parameterValues, parentParameterValues);
494            }
495    
496            @Override
497            public Map<String, List<String>> getRegularParameterMap() {
498                    return _regularParameters;
499            }
500    
501            @Override
502            public Long getSize(String name) {
503                    FileItem[] liferayFileItems = _fileParameters.get(name);
504    
505                    if (ArrayUtil.isNotEmpty(liferayFileItems)) {
506                            FileItem liferayFileItem = liferayFileItems[0];
507    
508                            return Long.valueOf(liferayFileItem.getSize());
509                    }
510    
511                    return null;
512            }
513    
514            @Override
515            public Boolean isFormField(String name) {
516                    FileItem[] liferayFileItems = _fileParameters.get(name);
517    
518                    if (ArrayUtil.isNotEmpty(liferayFileItems)) {
519                            FileItem liferayFileItem = liferayFileItems[0];
520    
521                            return liferayFileItem.isFormField();
522                    }
523    
524                    return null;
525            }
526    
527            protected InputStream getInputStream(
528                            FileItem liferayFileItem, boolean deleteOnClose)
529                    throws IOException {
530    
531                    InputStream inputStream = null;
532    
533                    if (liferayFileItem.isInMemory() && (liferayFileItem.getSize() > 0)) {
534                            inputStream = liferayFileItem.getInputStream();
535                    }
536                    else if (!liferayFileItem.isInMemory()) {
537                            inputStream = new ByteArrayFileInputStream(
538                                    liferayFileItem.getStoreLocation(),
539                                    liferayFileItem.getSizeThreshold(), deleteOnClose);
540                    }
541    
542                    return inputStream;
543            }
544    
545            private static final Log _log = LogFactoryUtil.getLog(
546                    UploadServletRequestImpl.class);
547    
548            private static File _tempDir;
549    
550            private final Map<String, FileItem[]> _fileParameters;
551            private final LiferayServletRequest _liferayServletRequest;
552            private final Map<String, List<String>> _regularParameters;
553    
554    }