diff --git a/core/src/main/java/org/apache/struts2/interceptor/FileUploadInterceptor.java b/core/src/main/java/org/apache/struts2/interceptor/FileUploadInterceptor.java deleted file mode 100644 index 7065fed1d2..0000000000 --- a/core/src/main/java/org/apache/struts2/interceptor/FileUploadInterceptor.java +++ /dev/null @@ -1,273 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.struts2.interceptor; - -import com.opensymphony.xwork2.ActionContext; -import com.opensymphony.xwork2.ActionInvocation; -import com.opensymphony.xwork2.ActionProxy; -import com.opensymphony.xwork2.interceptor.ValidationAware; -import jakarta.servlet.http.HttpServletRequest; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.apache.struts2.action.UploadedFilesAware; -import org.apache.struts2.dispatcher.Parameter; -import org.apache.struts2.dispatcher.multipart.MultiPartRequestWrapper; -import org.apache.struts2.dispatcher.multipart.UploadedFile; - -import java.util.ArrayList; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * - *

- * Interceptor that is based off of {@link MultiPartRequestWrapper}, which is automatically applied for any request that - * includes a file. It adds the following parameters, where [File Name] is the name given to the file uploaded by the - * HTML form: - *

- * - * - *

You can get access to these files by merely providing setters in your action that correspond to any of the three - * patterns above, such as setDocument(File document), setDocumentContentType(String contentType), etc. - *
See the example code section. - *

- * - *

This interceptor will add several field errors, assuming that the action implements {@link ValidationAware}. - * These error messages are based on several i18n values stored in struts-messages.properties, a default i18n file - * processed for all i18n requests. You can override the text of these messages by providing text for the following - * keys: - *

- * - * - *

- * - * - *

Interceptor parameters:

- *

- * - * - *

- *

- *

- * - * - *

Extending the interceptor:

- *

- *

- *

- * - *

- * You can extend this interceptor and override the acceptFile method to provide more control over which files - * are supported and which are not. - *

- * - * - *

Example code:

- * - *
- * 
- * <action name="doUpload" class="com.example.UploadAction">
- *     <interceptor-ref name="fileUpload"/>
- *     <interceptor-ref name="basicStack"/>
- *     <result name="success">good_result.jsp</result>
- * </action>
- * 
- * 
- *

- * - *

- * You must set the encoding to multipart/form-data in the form where the user selects the file to upload. - *

- * - * - *
- * 
- *   <s:form action="doUpload" method="post" enctype="multipart/form-data">
- *       <s:file name="upload" label="File"/>
- *       <s:submit/>
- *   </s:form>
- * 
- * 
- *

- * And then in your action code you'll have access to the File object if you provide setters according to the - * naming convention documented in the start. - *

- * - *
- * 
- *    package com.example;
- *
- *    import java.io.File;
- *    import com.opensymphony.xwork2.ActionSupport;
- *
- *    public UploadAction extends ActionSupport {
- *       private File file;
- *       private String contentType;
- *       private String filename;
- *
- *       public void setUpload(File file) {
- *          this.file = file;
- *       }
- *
- *       public void setUploadContentType(String contentType) {
- *          this.contentType = contentType;
- *       }
- *
- *       public void setUploadFileName(String filename) {
- *          this.filename = filename;
- *       }
- *
- *       public String execute() {
- *          //...
- *          return SUCCESS;
- *       }
- *  }
- * 
- * 
- * - * @deprecated since Struts 6.4.0, use {@link ActionFileUploadInterceptor} instead - */ -@Deprecated -public class FileUploadInterceptor extends AbstractFileUploadInterceptor { - - private static final long serialVersionUID = -4764627478894962478L; - - protected static final Logger LOG = LogManager.getLogger(FileUploadInterceptor.class); - - /* (non-Javadoc) - * @see com.opensymphony.xwork2.interceptor.Interceptor#intercept(com.opensymphony.xwork2.ActionInvocation) - */ - - public String intercept(ActionInvocation invocation) throws Exception { - ActionContext ac = invocation.getInvocationContext(); - - HttpServletRequest request = ac.getServletRequest(); - - if (!(request instanceof MultiPartRequestWrapper multiWrapper)) { - if (LOG.isDebugEnabled()) { - ActionProxy proxy = invocation.getProxy(); - LOG.debug(getTextMessage(STRUTS_MESSAGES_BYPASS_REQUEST_KEY, - new String[]{proxy.getNamespace(), proxy.getActionName()}) - ); - } - - return invocation.invoke(); - } - - Object action = invocation.getAction(); - if (action instanceof UploadedFilesAware) { - LOG.debug("Ignoring action: {} implementing: {} as it will be handled by: {}", - invocation.getProxy().getActionName(), - UploadedFilesAware.class.getSimpleName(), - ActionFileUploadInterceptor.class.getSimpleName() - ); - return invocation.invoke(); - } - - applyValidation(action, multiWrapper); - - // bind allowed Files - Enumeration fileParameterNames = multiWrapper.getFileParameterNames(); - while (fileParameterNames != null && fileParameterNames.hasMoreElements()) { - // get the value of this input tag - String inputName = fileParameterNames.nextElement(); - - // get the content type - String[] contentType = multiWrapper.getContentTypes(inputName); - - if (isNonEmpty(contentType)) { - // get the name of the file from the input tag - String[] fileName = multiWrapper.getFileNames(inputName); - - if (isNonEmpty(fileName)) { - // get a File object for the uploaded File - UploadedFile[] files = multiWrapper.getFiles(inputName); - if (files != null && files.length > 0) { - List acceptedFiles = new ArrayList<>(files.length); - List acceptedContentTypes = new ArrayList<>(files.length); - List acceptedFileNames = new ArrayList<>(files.length); - String contentTypeName = inputName + "ContentType"; - String fileNameName = inputName + "FileName"; - - for (int index = 0; index < files.length; index++) { - if (acceptFile(action, files[index], fileName[index], contentType[index], inputName)) { - acceptedFiles.add(files[index]); - acceptedContentTypes.add(contentType[index]); - acceptedFileNames.add(fileName[index]); - } - } - - if (!acceptedFiles.isEmpty()) { - Map newParams = new HashMap<>(); - newParams.put(inputName, new Parameter.File(inputName, acceptedFiles.toArray(new UploadedFile[0]))); - newParams.put(contentTypeName, new Parameter.File(contentTypeName, acceptedContentTypes.toArray(new String[0]))); - newParams.put(fileNameName, new Parameter.File(fileNameName, acceptedFileNames.toArray(new String[0]))); - ac.getParameters().appendAll(newParams); - } - } - } else { - if (LOG.isWarnEnabled()) { - LOG.warn(getTextMessage(action, STRUTS_MESSAGES_INVALID_FILE_KEY, new String[]{inputName})); - } - } - } else { - if (LOG.isWarnEnabled()) { - LOG.warn(getTextMessage(action, STRUTS_MESSAGES_INVALID_CONTENT_TYPE_KEY, new String[]{inputName})); - } - } - } - - // invoke action - return invocation.invoke(); - } - -} diff --git a/core/src/main/resources/struts-default.xml b/core/src/main/resources/struts-default.xml index 70e06ce5c4..9365e83480 100644 --- a/core/src/main/resources/struts-default.xml +++ b/core/src/main/resources/struts-default.xml @@ -57,7 +57,6 @@ - @@ -114,12 +113,6 @@ - - - - - - @@ -169,7 +162,6 @@ - @@ -208,7 +200,6 @@ - diff --git a/core/src/test/java/org/apache/struts2/interceptor/FileUploadInterceptorTest.java b/core/src/test/java/org/apache/struts2/interceptor/FileUploadInterceptorTest.java deleted file mode 100644 index 872122066a..0000000000 --- a/core/src/test/java/org/apache/struts2/interceptor/FileUploadInterceptorTest.java +++ /dev/null @@ -1,659 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.struts2.interceptor; - -import com.opensymphony.xwork2.ActionContext; -import com.opensymphony.xwork2.ActionSupport; -import com.opensymphony.xwork2.DefaultLocaleProvider; -import com.opensymphony.xwork2.ValidationAwareSupport; -import com.opensymphony.xwork2.mock.MockActionInvocation; -import com.opensymphony.xwork2.mock.MockActionProxy; -import com.opensymphony.xwork2.util.ClassLoaderUtil; -import org.apache.commons.fileupload2.jakarta.servlet6.JakartaServletFileUpload; -import org.apache.struts2.StrutsInternalTestCase; -import org.apache.struts2.action.UploadedFilesAware; -import org.apache.struts2.dispatcher.HttpParameters; -import org.apache.struts2.dispatcher.multipart.JakartaMultiPartRequest; -import org.apache.struts2.dispatcher.multipart.MultiPartRequestWrapper; -import org.apache.struts2.dispatcher.multipart.StrutsUploadedFile; -import org.apache.struts2.dispatcher.multipart.UploadedFile; -import org.assertj.core.util.Files; -import org.springframework.mock.web.MockHttpServletRequest; - -import java.io.File; -import java.net.URI; -import java.net.URL; -import java.nio.charset.StandardCharsets; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Test case for FileUploadInterceptor. - */ -public class FileUploadInterceptorTest extends StrutsInternalTestCase { - - private static final UploadedFile EMPTY_FILE = new UploadedFile() { - @Override - public Long length() { - return 0L; - } - - @Override - public String getName() { - return ""; - } - - @Override - public boolean isFile() { - return false; - } - - @Override - public boolean delete() { - return false; - } - - @Override - public String getAbsolutePath() { - return null; - } - - @Override - public File getContent() { - return Files.newTemporaryFile(); - } - - @Override - public String getOriginalName() { - return null; - } - - @Override - public String getContentType() { - return null; - } - }; - - private FileUploadInterceptor interceptor; - private File tempDir; - private MockHttpServletRequest request; - - public void testAcceptFileWithEmptyAllowedTypesAndExtensions() { - // when allowed type is empty - ValidationAwareSupport validation = new ValidationAwareSupport(); - boolean ok = interceptor.acceptFile(validation, EMPTY_FILE, "filename", "text/plain", "inputName"); - - assertTrue(ok); - assertTrue(validation.getFieldErrors().isEmpty()); - assertFalse(validation.hasErrors()); - } - - public void testAcceptFileWithoutEmptyTypes() { - interceptor.setAllowedTypes("text/plain"); - - // when file is of allowed types - ValidationAwareSupport validation = new ValidationAwareSupport(); - boolean ok = interceptor.acceptFile(validation, EMPTY_FILE, "filename.txt", "text/plain", "inputName"); - - assertTrue(ok); - assertTrue(validation.getFieldErrors().isEmpty()); - assertFalse(validation.hasErrors()); - - // when file is not of allowed types - validation = new ValidationAwareSupport(); - boolean notOk = interceptor.acceptFile(validation, EMPTY_FILE, "filename.html", "text/html", "inputName"); - - assertFalse(notOk); - assertFalse(validation.getFieldErrors().isEmpty()); - assertTrue(validation.hasErrors()); - } - - - public void testAcceptFileWithWildcardContent() { - interceptor.setAllowedTypes("text/*"); - - ValidationAwareSupport validation = new ValidationAwareSupport(); - boolean ok = interceptor.acceptFile(validation, EMPTY_FILE, "filename.txt", "text/plain", "inputName"); - - assertTrue(ok); - assertTrue(validation.getFieldErrors().isEmpty()); - assertFalse(validation.hasErrors()); - - interceptor.setAllowedTypes("text/h*"); - validation = new ValidationAwareSupport(); - boolean notOk = interceptor.acceptFile(validation, EMPTY_FILE, "filename.html", "text/plain", "inputName"); - - assertFalse(notOk); - assertFalse(validation.getFieldErrors().isEmpty()); - assertTrue(validation.hasErrors()); - } - - public void testAcceptFileWithoutEmptyExtensions() { - interceptor.setAllowedExtensions(".txt"); - - // when file is of allowed extensions - ValidationAwareSupport validation = new ValidationAwareSupport(); - boolean ok = interceptor.acceptFile(validation, EMPTY_FILE, "filename.txt", "text/plain", "inputName"); - - assertTrue(ok); - assertTrue(validation.getFieldErrors().isEmpty()); - assertFalse(validation.hasErrors()); - - // when file is not of allowed extensions - validation = new ValidationAwareSupport(); - boolean notOk = interceptor.acceptFile(validation, EMPTY_FILE, "filename.html", "text/html", "inputName"); - - assertFalse(notOk); - assertFalse(validation.getFieldErrors().isEmpty()); - assertTrue(validation.hasErrors()); - - //test with multiple extensions - interceptor.setAllowedExtensions(".txt,.lol"); - validation = new ValidationAwareSupport(); - ok = interceptor.acceptFile(validation, EMPTY_FILE, "filename.lol", "text/plain", "inputName"); - - assertTrue(ok); - assertTrue(validation.getFieldErrors().isEmpty()); - assertFalse(validation.hasErrors()); - } - - public void testAcceptFileWithNoFile() { - interceptor.setAllowedTypes("text/plain"); - - // when file is not of allowed types - ValidationAwareSupport validation = new ValidationAwareSupport(); - boolean notOk = interceptor.acceptFile(validation, null, "filename.html", "text/html", "inputName"); - - assertFalse(notOk); - assertFalse(validation.getFieldErrors().isEmpty()); - assertTrue(validation.hasErrors()); - List errors = validation.getFieldErrors().get("inputName"); - assertEquals(1, errors.size()); - String msg = errors.get(0); - assertTrue(msg.startsWith("Error uploading:")); - assertTrue(msg.indexOf("inputName") > 0); - } - - public void testAcceptFileWithMaxSize() throws Exception { - interceptor.setMaximumSize(10L); - - // when file is not of allowed types - ValidationAwareSupport validation = new ValidationAwareSupport(); - - URL url = ClassLoaderUtil.getResource("log4j2.xml", FileUploadInterceptorTest.class); - File file = new File(new URI(url.toString())); - assertTrue("log4j2.xml should be in src/test folder", file.exists()); - UploadedFile uploadedFile = StrutsUploadedFile.Builder.create(file) - .withContentType("text/html") - .withOriginalName("filename") - .build(); - - boolean notOk = interceptor.acceptFile(validation, uploadedFile, "filename", "text/html", "inputName"); - - assertFalse(notOk); - assertFalse(validation.getFieldErrors().isEmpty()); - assertTrue(validation.hasErrors()); - List errors = validation.getFieldErrors().get("inputName"); - assertEquals(1, errors.size()); - String msg = errors.get(0); - // the error message should contain at least this test - assertThat(msg).contains( - "The file is too large to be uploaded", - "inputName", - "log4j2.xml", - "allowed mx size is 10" - ); - } - - public void testNoMultipartRequest() throws Exception { - MyFileupAction action = new MyFileupAction(); - - MockActionInvocation mai = new MockActionInvocation(); - mai.setAction(action); - mai.setResultCode("NoMultipart"); - mai.setInvocationContext(ActionContext.getContext()); - - // if no multipart request it will bypass and execute it - assertEquals("NoMultipart", interceptor.intercept(mai)); - } - - public void testInvalidContentTypeMultipartRequest() throws Exception { - request.setContentType("multipart/form-data"); // not a multipart contentype - request.setMethod("post"); - - MyFileupAction action = container.inject(MyFileupAction.class); - MockActionInvocation mai = new MockActionInvocation(); - mai.setAction(action); - mai.setResultCode("success"); - mai.setInvocationContext(ActionContext.getContext()); - - ActionContext.getContext().withParameters(HttpParameters.create().build()); - ActionContext.getContext().withServletRequest(createMultipartRequestMaxSize(2000)); - - interceptor.intercept(mai); - - assertTrue(action.hasErrors()); - } - - public void testNoContentMultipartRequest() throws Exception { - request.setCharacterEncoding(StandardCharsets.UTF_8.name()); - request.setMethod("post"); - request.addHeader("Content-type", "multipart/form-data"); - request.setContent(null); // there is no content - - MyFileupAction action = container.inject(MyFileupAction.class); - MockActionInvocation mai = new MockActionInvocation(); - mai.setAction(action); - mai.setResultCode("success"); - mai.setInvocationContext(ActionContext.getContext()); - - ActionContext.getContext().withParameters(HttpParameters.create().build()); - ActionContext.getContext().withServletRequest(createMultipartRequestMaxSize(2000)); - - interceptor.intercept(mai); - - assertTrue(action.hasErrors()); - } - - public void testSuccessUploadOfATextFileMultipartRequest() throws Exception { - request.setCharacterEncoding(StandardCharsets.UTF_8.name()); - request.setMethod("post"); - request.addHeader("Content-type", "multipart/form-data; boundary=---1234"); - - // inspired by the unit tests for jakarta commons fileupload - String content = ("-----1234\r\n" + - "Content-Disposition: form-data; name=\"file\"; filename=\"deleteme.txt\"\r\n" + - "Content-Type: text/html\r\n" + - "\r\n" + - "Unit test of FileUploadInterceptor" + - "\r\n" + - "-----1234--\r\n"); - request.setContent(content.getBytes(StandardCharsets.US_ASCII)); - - MyFileupAction action = new MyFileupAction(); - - MockActionInvocation mai = new MockActionInvocation(); - mai.setAction(action); - mai.setResultCode("success"); - mai.setInvocationContext(ActionContext.getContext()); - Map param = new HashMap<>(); - ActionContext.getContext().withParameters(HttpParameters.create(param).build()); - ActionContext.getContext().withServletRequest(createMultipartRequestMaxSize(2000)); - - interceptor.intercept(mai); - - assertFalse(action.hasErrors()); - - HttpParameters parameters = mai.getInvocationContext().getParameters(); - assertEquals(3, parameters.keySet().size()); - UploadedFile[] files = (UploadedFile[]) parameters.get("file").getObject(); - String[] fileContentTypes = parameters.get("fileContentType").getMultipleValues(); - String[] fileRealFilenames = parameters.get("fileFileName").getMultipleValues(); - - assertNotNull(files); - assertNotNull(fileContentTypes); - assertNotNull(fileRealFilenames); - assertEquals(1, files.length); - assertEquals(1, fileContentTypes.length); - assertEquals(1, fileRealFilenames.length); - assertEquals("text/html", fileContentTypes[0]); - assertNotNull("deleteme.txt", fileRealFilenames[0]); - } - - /** - * tests whether with multiple files sent with the same name, the ones with forbiddenTypes (see - * FileUploadInterceptor.setAllowedTypes(...) ) are sorted out. - */ - public void testMultipleAccept() throws Exception { - final String htmlContent = "html content"; - final String plainContent = "plain content"; - final String bondary = "simple boundary"; - final String endline = "\r\n"; - - request.setCharacterEncoding(StandardCharsets.UTF_8.name()); - request.setMethod("POST"); - request.addHeader("Content-type", "multipart/form-data; boundary=" + bondary); - String content = encodeTextFile("test.html", "text/plain", plainContent) + - encodeTextFile("test1.html", "text/html", htmlContent) + - encodeTextFile("test2.html", "text/html", htmlContent) + - endline + - endline + - endline + - "--" + - bondary + - "--" + - endline; - request.setContent(content.getBytes()); - - assertTrue(JakartaServletFileUpload.isMultipartContent(request)); - - MyFileupAction action = new MyFileupAction(); - container.inject(action); - MockActionInvocation mai = new MockActionInvocation(); - mai.setAction(action); - mai.setResultCode("success"); - mai.setInvocationContext(ActionContext.getContext()); - Map param = new HashMap<>(); - ActionContext.getContext().withParameters(HttpParameters.create(param).build()); - ActionContext.getContext().withServletRequest(createMultipartRequestMaxSize(2000)); - - interceptor.setAllowedTypes("text/html"); - interceptor.intercept(mai); - - HttpParameters parameters = mai.getInvocationContext().getParameters(); - assertEquals(3, parameters.keySet().size()); - UploadedFile[] files = (UploadedFile[]) parameters.get("file").getObject(); - String[] fileContentTypes = parameters.get("fileContentType").getMultipleValues(); - String[] fileRealFilenames = parameters.get("fileFileName").getMultipleValues(); - - assertNotNull(files); - assertNotNull(fileContentTypes); - assertNotNull(fileRealFilenames); - assertEquals("files accepted ", 2, files.length); - assertEquals(2, fileContentTypes.length); - assertEquals(2, fileRealFilenames.length); - assertEquals("text/html", fileContentTypes[0]); - assertNotNull("test1.html", fileRealFilenames[0]); - } - - public void testUnacceptedNumberOfFiles() throws Exception { - final String htmlContent = "html content"; - final String plainContent = "plain content"; - final String boundary = "simple boundary"; - final String endline = "\r\n"; - - request.setCharacterEncoding(StandardCharsets.UTF_8.name()); - request.setMethod("POST"); - request.addHeader("Content-type", "multipart/form-data; boundary=" + boundary); - String content = encodeTextFile("test.html", "text/plain", plainContent) + - encodeTextFile("test1.html", "text/html", htmlContent) + - encodeTextFile("test2.html", "text/html", htmlContent) + - encodeTextFile("test3.html", "text/html", htmlContent) + - endline + - "--" + - boundary + - "--" + - endline; - request.setContent(content.getBytes()); - - assertTrue(JakartaServletFileUpload.isMultipartContent(request)); - - MyFileupAction action = new MyFileupAction(); - container.inject(action); - MockActionInvocation mai = new MockActionInvocation(); - mai.setAction(action); - mai.setResultCode("success"); - mai.setInvocationContext(ActionContext.getContext()); - Map param = new HashMap<>(); - ActionContext.getContext() - .withParameters(HttpParameters.create(param).build()) - .withServletRequest(createMultipartRequestMaxFiles()); - - interceptor.setAllowedTypes("text/html"); - interceptor.intercept(mai); - - HttpParameters parameters = mai.getInvocationContext().getParameters(); - assertEquals(0, parameters.keySet().size()); - assertEquals(1, action.getActionErrors().size()); - assertEquals( - "Request exceeded allowed number of files! Permitted number of files is: 3!", - action.getActionErrors().iterator().next() - ); - } - - public void testMultipartRequestMaxFileSize() throws Exception { - request.setCharacterEncoding(StandardCharsets.UTF_8.name()); - request.setMethod("post"); - request.addHeader("Content-type", "multipart/form-data; boundary=---1234"); - - // inspired by the unit tests for jakarta commons fileupload - String content = ("-----1234\r\n" + - "Content-Disposition: form-data; name=\"file\"; filename=\"deleteme.txt\"\r\n" + - "Content-Type: text/html\r\n" + - "\r\n" + - "Unit test of FileUploadInterceptor" + - "\r\n" + - "-----1234--\r\n"); - request.setContent(content.getBytes(StandardCharsets.US_ASCII)); - - MyFileupAction action = container.inject(MyFileupAction.class); - - MockActionInvocation mai = new MockActionInvocation(); - mai.setAction(action); - mai.setResultCode("success"); - mai.setInvocationContext(ActionContext.getContext()); - Map param = new HashMap<>(); - ActionContext.getContext() - .withParameters(HttpParameters.create(param).build()) - .withServletRequest(createMultipartRequestMaxFileSize()); - - interceptor.intercept(mai); - - assertTrue(action.hasActionErrors()); - - Collection errors = action.getActionErrors(); - assertEquals(1, errors.size()); - String msg = errors.iterator().next(); - // FIXME: the expected size is 40 - length of the string - assertEquals( - "File deleteme.txt assigned to file exceeded allowed size limit! Max size allowed is: 10 but file was: 11!", - msg); - } - - public void testMultipartRequestMaxStringLength() throws Exception { - request.setCharacterEncoding(StandardCharsets.UTF_8.name()); - request.setMethod("post"); - request.addHeader("Content-type", "multipart/form-data; boundary=---1234"); - - // inspired by the unit tests for jakarta commons fileupload - String content = ("-----1234\r\n" + - "Content-Disposition: form-data; name=\"file\"; filename=\"deleteme.txt\"\r\n" + - "Content-Type: text/html\r\n" + - "\r\n" + - "Unit test of FileUploadInterceptor" + - "\r\n" + - "-----1234\r\n" + - "Content-Disposition: form-data; name=\"normalFormField1\"\r\n" + - "\r\n" + - "it works" + - "\r\n" + - "-----1234\r\n" + - "Content-Disposition: form-data; name=\"normalFormField2\"\r\n" + - "\r\n" + - "long string should not work" + - "\r\n" + - "-----1234--\r\n"); - request.setContent(content.getBytes(StandardCharsets.US_ASCII)); - - MyFileupAction action = container.inject(MyFileupAction.class); - - MockActionInvocation mai = new MockActionInvocation(); - mai.setAction(action); - mai.setResultCode("success"); - mai.setInvocationContext(ActionContext.getContext()); - Map param = new HashMap<>(); - ActionContext.getContext() - .withParameters(HttpParameters.create(param).build()) - .withServletRequest(createMultipartRequestMaxStringLength()); - - interceptor.intercept(mai); - - assertTrue(action.hasActionErrors()); - - Collection errors = action.getActionErrors(); - assertEquals(1, errors.size()); - String msg = errors.iterator().next(); - assertEquals( - "The request parameter \"normalFormField2\" was too long. Max length allowed is 20, but found 27!", - msg); - } - - public void testMultipartRequestLocalizedError() throws Exception { - request.setCharacterEncoding(StandardCharsets.UTF_8.name()); - request.setMethod("post"); - request.addHeader("Content-type", "multipart/form-data; boundary=---1234"); - - // inspired by the unit tests for jakarta commons fileupload - String content = ("-----1234\r\n" + - "Content-Disposition: form-data; name=\"file\"; filename=\"deleteme.txt\"\r\n" + - "Content-Type: text/html\r\n" + - "\r\n" + - "Unit test of FileUploadInterceptor" + - "\r\n" + - "-----1234--\r\n"); - request.setContent(content.getBytes(StandardCharsets.US_ASCII)); - - MyFileupAction action = container.inject(MyFileupAction.class); - - MockActionInvocation mai = new MockActionInvocation(); - mai.setAction(action); - mai.setResultCode("success"); - mai.setInvocationContext(ActionContext.getContext()); - Map param = new HashMap<>(); - ActionContext.getContext() - .withParameters(HttpParameters.create(param).build()) - .withLocale(Locale.GERMAN) - .withServletRequest(createMultipartRequestMaxSize(10)); - - interceptor.intercept(mai); - - assertTrue(action.hasActionErrors()); - - Collection errors = action.getActionErrors(); - assertEquals(1, errors.size()); - String msg = errors.iterator().next(); - // the error message should contain at least this test - assertTrue(msg.startsWith("Der Request übertraf die maximal erlaubte Größe")); - } - - public void testSkippingUploadedFileAware() throws Exception { - request.setCharacterEncoding(StandardCharsets.UTF_8.name()); - request.setMethod("post"); - request.addHeader("Content-type", "multipart/form-data; boundary=---1234"); - - // inspired by the unit tests for jakarta commons fileupload - String content = ("-----1234\r\n" + - "Content-Disposition: form-data; name=\"file\"; filename=\"deleteme.txt\"\r\n" + - "Content-Type: text/html\r\n" + - "\r\n" + - "Unit test of FileUploadInterceptor" + - "\r\n" + - "-----1234--\r\n"); - request.setContent(content.getBytes(StandardCharsets.US_ASCII)); - - MyFileUploadAction action = container.inject(MyFileUploadAction.class); - - MockActionInvocation mai = new MockActionInvocation(); - mai.setInvocationContext(ActionContext.getContext()); - mai.setAction(action); - MockActionProxy map = new MockActionProxy(); - map.setActionName("uploadedFiles"); - mai.setProxy(map); - ActionContext.getContext() - .withParameters(HttpParameters.create(new HashMap()).build()) - .withServletRequest(createMultipartRequestMaxSize(10)); - - interceptor.intercept(mai); - - assertFalse(action.hasActionErrors()); - } - - private String encodeTextFile(String filename, String contentType, String content) { - return "\r\n" + - "--" + - "simple boundary" + - "\r\n" + - "Content-Disposition: form-data; name=\"" + - "file" + - "\"; filename=\"" + - filename + - "\r\n" + - "Content-Type: " + - contentType + - "\r\n" + - "\r\n" + - content; - } - - private MultiPartRequestWrapper createMultipartRequestMaxFileSize() { - return createMultipartRequest(-1, 10, -1, -1); - } - - private MultiPartRequestWrapper createMultipartRequestMaxFiles() { - return createMultipartRequest(-1, -1, 3, -1); - } - - private MultiPartRequestWrapper createMultipartRequestMaxSize(int maxsize) { - return createMultipartRequest(maxsize, -1, -1, -1); - } - - private MultiPartRequestWrapper createMultipartRequestMaxStringLength() { - return createMultipartRequest(-1, -1, -1, 20); - } - - private MultiPartRequestWrapper createMultipartRequest(int maxsize, int maxfilesize, int maxfiles, int maxStringLength) { - JakartaMultiPartRequest jak = new JakartaMultiPartRequest(); - jak.setMaxSize(String.valueOf(maxsize)); - jak.setMaxFileSize(String.valueOf(maxfilesize)); - jak.setMaxFiles(String.valueOf(maxfiles)); - jak.setMaxStringLength(String.valueOf(maxStringLength)); - jak.setDefaultEncoding(StandardCharsets.UTF_8.name()); - return new MultiPartRequestWrapper(jak, request, tempDir.getAbsolutePath(), new DefaultLocaleProvider()); - } - - @Override - protected void setUp() throws Exception { - super.setUp(); - - request = new MockHttpServletRequest(); - interceptor = new FileUploadInterceptor(); - container.inject(interceptor); - tempDir = File.createTempFile("struts", "fileupload"); - assertThat(tempDir.delete()).isTrue(); - assertThat(tempDir.mkdirs()).isTrue(); - } - - @Override - protected void tearDown() throws Exception { - interceptor.destroy(); - super.tearDown(); - } - - public static class MyFileupAction extends ActionSupport { - } - - public static class MyFileUploadAction extends ActionSupport implements UploadedFilesAware { - private List uploadedFiles; - - @Override - public void withUploadedFiles(List uploadedFiles) { - this.uploadedFiles = uploadedFiles; - } - - public List getUploadFiles() { - return this.uploadedFiles; - } - } - -} diff --git a/plugins/bean-validation/src/main/resources/struts-plugin.xml b/plugins/bean-validation/src/main/resources/struts-plugin.xml index 326be2f4c9..530366af5c 100644 --- a/plugins/bean-validation/src/main/resources/struts-plugin.xml +++ b/plugins/bean-validation/src/main/resources/struts-plugin.xml @@ -47,7 +47,7 @@ - + diff --git a/plugins/rest/src/main/resources/struts-plugin.xml b/plugins/rest/src/main/resources/struts-plugin.xml index f680489924..88ec44b6fe 100644 --- a/plugins/rest/src/main/resources/struts-plugin.xml +++ b/plugins/rest/src/main/resources/struts-plugin.xml @@ -86,7 +86,7 @@ true - +