1 /*******************************************************************************
2  * Copyright (c) 2016, 2019 Raymond Augé and others.
3  *
4  * This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License 2.0
6  * which accompanies this distribution, and is available at
7  * https://www.eclipse.org/legal/epl-2.0/
8  *
9  * SPDX-License-Identifier: EPL-2.0
10  *
11  * Contributors:
12  *     Raymond Augé <raymond.auge@liferay.com> - Bug 497271
13  *******************************************************************************/
14 package org.eclipse.equinox.http.servlet.internal.multipart;
15 
16 import java.io.*;
17 import java.security.AccessControlContext;
18 import java.util.HashMap;
19 import java.util.Map;
20 import javax.servlet.ServletContext;
21 import javax.servlet.ServletException;
22 import javax.servlet.http.HttpServletRequest;
23 import javax.servlet.http.Part;
24 import org.apache.commons.fileupload.FileUploadException;
25 import org.apache.commons.fileupload.disk.DiskFileItem;
26 import org.apache.commons.fileupload.disk.DiskFileItemFactory;
27 import org.apache.commons.fileupload.servlet.ServletFileUpload;
28 import org.osgi.framework.Bundle;
29 import org.osgi.framework.BundleContext;
30 import org.osgi.service.http.runtime.dto.ServletDTO;
31 
32 public class MultipartSupportImpl implements MultipartSupport {
33 
MultipartSupportImpl(ServletDTO servletDTO, ServletContext servletContext)34 	public MultipartSupportImpl(ServletDTO servletDTO, ServletContext servletContext) {
35 		this.servletDTO = servletDTO;
36 
37 		// Must return non-null File. See Servlet 3.1 §4.8.1
38 		File baseStorage = (File)servletContext.getAttribute(ServletContext.TEMPDIR);
39 
40 		if (servletDTO.multipartLocation.length() > 0) {
41 			File storage = new File(servletDTO.multipartLocation);
42 
43 			if (!storage.isAbsolute()) {
44 				storage = new File(baseStorage, storage.getPath());
45 			}
46 
47 			baseStorage = storage;
48 		}
49 
50 		checkPermission(baseStorage, servletContext);
51 
52 		baseStorage.mkdirs();
53 
54 		DiskFileItemFactory factory = new DiskFileItemFactory();
55 
56 		factory.setRepository(baseStorage);
57 
58 		if (servletDTO.multipartFileSizeThreshold > 0) {
59 			factory.setSizeThreshold(servletDTO.multipartFileSizeThreshold);
60 		}
61 
62 		upload = new ServletFileUpload(factory);
63 
64 		if (servletDTO.multipartMaxFileSize > -1L) {
65 			upload.setFileSizeMax(servletDTO.multipartMaxFileSize);
66 		}
67 
68 		if (servletDTO.multipartMaxRequestSize > -1L) {
69 			upload.setSizeMax(servletDTO.multipartMaxRequestSize);
70 		}
71 	}
72 
checkPermission(File baseStorage, ServletContext servletContext)73 	private void checkPermission(File baseStorage, ServletContext servletContext) {
74 		BundleContext bundleContext = (BundleContext)servletContext.getAttribute("osgi-bundlecontext"); //$NON-NLS-1$
75 		Bundle bundle = bundleContext.getBundle();
76 		AccessControlContext accessControlContext = bundle.adapt(AccessControlContext.class);
77 		if (accessControlContext == null) return;
78 		accessControlContext.checkPermission(new FilePermission(baseStorage.getAbsolutePath(), "read,write")); //$NON-NLS-1$
79 	}
80 
81 	@Override
parseRequest(HttpServletRequest request)82 	public Map<String, Part> parseRequest(HttpServletRequest request) throws IOException, ServletException {
83 		if (upload == null) {
84 			throw new IllegalStateException("Servlet was not configured for multipart!"); //$NON-NLS-1$
85 		}
86 
87 		if (!servletDTO.multipartEnabled) {
88 			throw new IllegalStateException("No multipart config on " + servletDTO); //$NON-NLS-1$
89 		}
90 
91 		if (!ServletFileUpload.isMultipartContent(request)) {
92 			throw new ServletException("Not a multipart request!"); //$NON-NLS-1$
93 		}
94 
95 		Map<String, Part> parts = new HashMap<String, Part>();
96 
97 		try {
98 			for (Object item : upload.parseRequest(request)) {
99 				DiskFileItem diskFileItem = (DiskFileItem)item;
100 
101 				parts.put(diskFileItem.getFieldName(), new MultipartSupportPart(diskFileItem));
102 			}
103 		}
104 		catch (FileUploadException fnfe) {
105 			throw new IOException(fnfe);
106 		}
107 
108 		return parts;
109 	}
110 
111 	private final ServletDTO servletDTO;
112 	private final ServletFileUpload upload;
113 
114 
115 }