This is an automated email from the ASF dual-hosted git repository.

kusal pushed a commit to branch issue-85/CONFSRVDEV-37138-merge-upstream
in repository https://gitbox.apache.org/repos/asf/struts.git

commit 98348790e54c3855190879a303677d248a974878
Author: Kusal Kithul-Godage <g...@kusal.io>
AuthorDate: Mon Feb 3 11:10:13 2025 +1100

    CONFSRVDEV-37099 Backport of CVE-2024-53677 fix from 7.0
---
 .../struts2/interceptor/FileUploadInterceptor.java | 263 -------
 core/src/main/resources/struts-default.xml         |   9 -
 .../interceptor/FileUploadInterceptorTest.java     | 806 ---------------------
 3 files changed, 1078 deletions(-)

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 86f8a64be..000000000
--- 
a/core/src/main/java/org/apache/struts2/interceptor/FileUploadInterceptor.java
+++ /dev/null
@@ -1,263 +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 org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
-import org.apache.struts2.dispatcher.Parameter;
-import org.apache.struts2.dispatcher.multipart.MultiPartRequestWrapper;
-import org.apache.struts2.dispatcher.multipart.UploadedFile;
-
-import javax.servlet.http.HttpServletRequest;
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * <!-- START SNIPPET: description -->
- * <p>
- * 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:
- * </p>
- * <ul>
- *
- * <li>[File Name] : File - the actual File</li>
- *
- * <li>[File Name]ContentType : String - the content type of the file</li>
- *
- * <li>[File Name]FileName : String - the actual name of the file uploaded 
(not the HTML name)</li>
- *
- * </ul>
- *
- * <p>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.
- * <br>See the example code section.
- * </p>
- *
- * <p> 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:
- * </p>
- *
- * <ul>
- *
- * <li>struts.messages.error.uploading - a general error that occurs when the 
file could not be uploaded</li>
- *
- * <li>struts.messages.error.file.too.large - occurs when the uploaded file is 
too large</li>
- *
- * <li>struts.messages.error.content.type.not.allowed - occurs when the 
uploaded file does not match the expected
- * content types specified</li>
- *
- * <li>struts.messages.error.file.extension.not.allowed - occurs when the 
uploaded file does not match the expected
- * file extensions specified</li>
- *
- * </ul>
- * <p>
- * <!-- END SNIPPET: description -->
- *
- * <p><u>Interceptor parameters:</u></p>
- * <p>
- * <!-- START SNIPPET: parameters -->
- *
- * <ul>
- *
- * <li>maximumSize (optional) - the maximum size (in bytes) that the 
interceptor will allow a file reference to be set
- * on the action. Note, this is <b>not</b> related to the various properties 
found in struts.properties.
- * Default to approximately 2MB.</li>
- *
- * <li>allowedTypes (optional) - a comma separated list of content types (ie: 
text/html) that the interceptor will allow
- * a file reference to be set on the action. If none is specified allow all 
types to be uploaded.</li>
- *
- * <li>allowedExtensions (optional) - a comma separated list of file 
extensions (ie: .html) that the interceptor will allow
- * a file reference to be set on the action. If none is specified allow all 
extensions to be uploaded.</li>
- * </ul>
- * <p>
- * <p>
- * <!-- END SNIPPET: parameters -->
- *
- * <p><u>Extending the interceptor:</u></p>
- * <p>
- * <p>
- * <p>
- * <!-- START SNIPPET: extending -->
- * <p>
- * You can extend this interceptor and override the acceptFile method to 
provide more control over which files
- * are supported and which are not.
- * </p>
- * <!-- END SNIPPET: extending -->
- *
- * <p><u>Example code:</u></p>
- *
- * <pre>
- * <!-- START SNIPPET: example-configuration -->
- * &lt;action name="doUpload" class="com.example.UploadAction"&gt;
- *     &lt;interceptor-ref name="fileUpload"/&gt;
- *     &lt;interceptor-ref name="basicStack"/&gt;
- *     &lt;result name="success"&gt;good_result.jsp&lt;/result&gt;
- * &lt;/action&gt;
- * <!-- END SNIPPET: example-configuration -->
- * </pre>
- * <p>
- * <!-- START SNIPPET: multipart-note -->
- * <p>
- * You must set the encoding to <code>multipart/form-data</code> in the form 
where the user selects the file to upload.
- * </p>
- * <!-- END SNIPPET: multipart-note -->
- *
- * <pre>
- * <!-- START SNIPPET: example-form -->
- *   &lt;s:form action="doUpload" method="post" 
enctype="multipart/form-data"&gt;
- *       &lt;s:file name="upload" label="File"/&gt;
- *       &lt;s:submit/&gt;
- *   &lt;/s:form&gt;
- * <!-- END SNIPPET: example-form -->
- * </pre>
- * <p>
- * 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.
- * </p>
- *
- * <pre>
- * <!-- START SNIPPET: example-action -->
- *    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;
- *       }
- *  }
- * <!-- END SNIPPET: example-action -->
- * </pre>
- *
- * @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)) {
-            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();
-        MultiPartRequestWrapper multiWrapper = (MultiPartRequestWrapper) 
request;
-
-        applyValidation(action, multiWrapper);
-
-        // bind allowed Files
-        Enumeration<String> 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<UploadedFile> acceptedFiles = new 
ArrayList<>(files.length);
-                        List<String> acceptedContentTypes = new 
ArrayList<>(files.length);
-                        List<String> 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<String, Parameter> 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 326477bc4..19fda0237 100644
--- a/core/src/main/resources/struts-default.xml
+++ b/core/src/main/resources/struts-default.xml
@@ -57,7 +57,6 @@
             <interceptor name="debugging" 
class="org.apache.struts2.interceptor.debugging.DebuggingInterceptor"/>
             <interceptor name="execAndWait" 
class="org.apache.struts2.interceptor.ExecuteAndWaitInterceptor"/>
             <interceptor name="exception" 
class="com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor"/>
-            <interceptor name="fileUpload" 
class="org.apache.struts2.interceptor.FileUploadInterceptor"/>
             <interceptor name="actionFileUpload" 
class="org.apache.struts2.interceptor.ActionFileUploadInterceptor"/>
             <interceptor name="i18n" 
class="org.apache.struts2.interceptor.I18nInterceptor"/>
             <interceptor name="logger" 
class="com.opensymphony.xwork2.interceptor.LoggingInterceptor"/>
@@ -116,12 +115,6 @@
                 <interceptor-ref name="workflow"/>
             </interceptor-stack>
 
-            <!-- Sample file upload stack -->
-            <interceptor-stack name="fileUploadStack">
-                <interceptor-ref name="fileUpload"/>
-                <interceptor-ref name="basicStack"/>
-            </interceptor-stack>
-
             <!-- Action based file upload stack -->
             <interceptor-stack name="actionFileUploadStack">
                 <interceptor-ref name="actionFileUpload"/>
@@ -171,7 +164,6 @@
                 <interceptor-ref name="prepare"/>
                 <interceptor-ref name="chain"/>
                 <interceptor-ref name="modelDriven"/>
-                <interceptor-ref name="fileUpload"/>
                 <interceptor-ref name="actionFileUpload"/>
                 <interceptor-ref name="staticParams"/>
                 <interceptor-ref name="actionMappingParams"/>
@@ -210,7 +202,6 @@
                 <interceptor-ref name="chain"/>
                 <interceptor-ref name="scopedModelDriven"/>
                 <interceptor-ref name="modelDriven"/>
-                <interceptor-ref name="fileUpload"/>
                 <interceptor-ref name="actionFileUpload"/>
                 <interceptor-ref name="checkbox"/>
                 <interceptor-ref name="datetime"/>
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 36fad5847..000000000
--- 
a/core/src/test/java/org/apache/struts2/interceptor/FileUploadInterceptorTest.java
+++ /dev/null
@@ -1,806 +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.util.ClassLoaderUtil;
-import org.apache.commons.fileupload.servlet.ServletFileUpload;
-import org.apache.struts2.ServletActionContext;
-import org.apache.struts2.StrutsInternalTestCase;
-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.springframework.mock.web.MockHttpServletRequest;
-
-import javax.servlet.http.HttpServletRequest;
-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 {
-
-    public 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 byte[] getContent() {
-            return new byte[0];
-        }
-
-        @Override
-        public String getOriginalName() {
-            return null;
-        }
-
-        @Override
-        public String getContentType() {
-            return null;
-        }
-
-        @Override
-        public String getInputName() {
-            return null;
-        }
-    };
-
-    private FileUploadInterceptor interceptor;
-    private File tempDir;
-
-    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() {
-        FileUploadInterceptor interceptor = new FileUploadInterceptor();
-        interceptor.setContainer(container);
-
-        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<String> 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<String> 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 {
-        MockHttpServletRequest req = new MockHttpServletRequest();
-
-        req.setContentType("multipart/form-data"); // not a multipart 
contentype
-        req.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().put(ServletActionContext.HTTP_REQUEST, 
createMultipartRequestMaxSize(req, 2000));
-
-        interceptor.intercept(mai);
-
-        assertTrue(action.hasErrors());
-    }
-
-    public void testNoContentMultipartRequest() throws Exception {
-        MockHttpServletRequest req = new MockHttpServletRequest();
-
-        req.setCharacterEncoding(StandardCharsets.UTF_8.name());
-        req.setMethod("post");
-        req.addHeader("Content-type", "multipart/form-data");
-        req.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().put(ServletActionContext.HTTP_REQUEST, 
createMultipartRequestMaxSize(req, 2000));
-
-        interceptor.intercept(mai);
-
-        assertTrue(action.hasErrors());
-    }
-
-    public void testSuccessUploadOfATextFileMultipartRequest() throws 
Exception {
-        MockHttpServletRequest req = new MockHttpServletRequest();
-        req.setCharacterEncoding(StandardCharsets.UTF_8.name());
-        req.setMethod("post");
-        req.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");
-        req.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<String, Object> param = new HashMap<>();
-        
ActionContext.getContext().withParameters(HttpParameters.create(param).build());
-        ActionContext.getContext().put(ServletActionContext.HTTP_REQUEST, 
createMultipartRequestMaxSize(req, 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]);
-    }
-
-    public void testSuccessUploadOfATextFileMultipartRequestNoMaxParamsSet() 
throws Exception {
-        MockHttpServletRequest req = new MockHttpServletRequest();
-        req.setCharacterEncoding(StandardCharsets.UTF_8.name());
-        req.setMethod("post");
-        req.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");
-        req.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<String, Object> param = new HashMap<>();
-        
ActionContext.getContext().withParameters(HttpParameters.create(param).build());
-        
ActionContext.getContext().withServletRequest(createMultipartRequestNoMaxParamsSet(req));
-
-        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]);
-    }
-
-    public void 
testSuccessUploadOfATextFileMultipartRequestWithNormalFieldsMaxParamsSet() 
throws Exception {
-        MockHttpServletRequest req = new MockHttpServletRequest();
-        req.setCharacterEncoding(StandardCharsets.UTF_8.name());
-        req.setMethod("post");
-        req.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" +
-                "normal field 1" +
-                "\r\n" +
-                "-----1234\r\n" +
-                "Content-Disposition: form-data; 
name=\"normalFormField2\"\r\n" +
-                "\r\n" +
-                "normal field 2" +
-                "\r\n" +
-                "-----1234--\r\n");
-        req.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<String, Object> param = new HashMap<>();
-        
ActionContext.getContext().withParameters(HttpParameters.create(param).build());
-        
ActionContext.getContext().withServletRequest(createMultipartRequest(req, 2000, 
2000, 5, 100));
-
-        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]);
-
-        // Confirm normalFormField1, normalFormField2 were processed by the 
MultiPartRequestWrapper.
-        HttpServletRequest invocationServletRequest = 
mai.getInvocationContext().getServletRequest();
-        assertTrue("invocation servelt request is not a 
MultiPartRequestWrapper ?", invocationServletRequest instanceof 
MultiPartRequestWrapper);
-        MultiPartRequestWrapper multipartRequestWrapper = 
(MultiPartRequestWrapper) invocationServletRequest;
-        assertNotNull("normalFormField1 missing from MultiPartRequestWrapper 
parameters ?", multipartRequestWrapper.getParameter("normalFormField1"));
-        assertNotNull("normalFormField2 missing from MultiPartRequestWrapper 
parameters ?", multipartRequestWrapper.getParameter("normalFormField2"));
-    }
-
-    public void 
testSuccessUploadOfATextFileMultipartRequestWithNormalFieldsNoMaxParamsSet() 
throws Exception {
-        MockHttpServletRequest req = new MockHttpServletRequest();
-        req.setCharacterEncoding(StandardCharsets.UTF_8.name());
-        req.setMethod("post");
-        req.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" +
-                "normal field 1 with no max parameters set" +
-                "\r\n" +
-                "-----1234\r\n" +
-                "Content-Disposition: form-data; 
name=\"normalFormField2\"\r\n" +
-                "\r\n" +
-                "normal field 2 with no max parameters set" +
-                "\r\n" +
-                "-----1234--\r\n");
-        req.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<String, Object> param = new HashMap<>();
-        
ActionContext.getContext().withParameters(HttpParameters.create(param).build());
-        
ActionContext.getContext().withServletRequest(createMultipartRequestNoMaxParamsSet(req));
-
-        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]);
-
-        // Confirm normalFormField1, normalFormField2 were processed by the 
MultiPartRequestWrapper.
-        HttpServletRequest invocationServletRequest = 
mai.getInvocationContext().getServletRequest();
-        assertTrue("invocation servelt request is not a 
MultiPartRequestWrapper ?", invocationServletRequest instanceof 
MultiPartRequestWrapper);
-        MultiPartRequestWrapper multipartRequestWrapper = 
(MultiPartRequestWrapper) invocationServletRequest;
-        assertNotNull("normalFormField1 missing from MultiPartRequestWrapper 
parameters ?", multipartRequestWrapper.getParameter("normalFormField1"));
-        assertNotNull("normalFormField2 missing from MultiPartRequestWrapper 
parameters ?", multipartRequestWrapper.getParameter("normalFormField2"));
-    }
-
-    /**
-     * 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><head></head><body>html 
content</body></html>";
-        final String plainContent = "plain content";
-        final String bondary = "simple boundary";
-        final String endline = "\r\n";
-
-        MockHttpServletRequest req = new MockHttpServletRequest();
-        req.setCharacterEncoding(StandardCharsets.UTF_8.name());
-        req.setMethod("POST");
-        req.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;
-        req.setContent(content.getBytes());
-
-        assertTrue(ServletFileUpload.isMultipartContent(req));
-
-        MyFileupAction action = new MyFileupAction();
-        container.inject(action);
-        MockActionInvocation mai = new MockActionInvocation();
-        mai.setAction(action);
-        mai.setResultCode("success");
-        mai.setInvocationContext(ActionContext.getContext());
-        Map<String, Object> param = new HashMap<>();
-        
ActionContext.getContext().withParameters(HttpParameters.create(param).build());
-        ActionContext.getContext().put(ServletActionContext.HTTP_REQUEST, 
createMultipartRequestMaxSize(req, 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><head></head><body>html 
content</body></html>";
-        final String plainContent = "plain content";
-        final String boundary = "simple boundary";
-        final String endline = "\r\n";
-
-        MockHttpServletRequest req = new MockHttpServletRequest();
-        req.setCharacterEncoding(StandardCharsets.UTF_8.name());
-        req.setMethod("POST");
-        req.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;
-        req.setContent(content.getBytes());
-
-        assertTrue(ServletFileUpload.isMultipartContent(req));
-
-        MyFileupAction action = new MyFileupAction();
-        container.inject(action);
-        MockActionInvocation mai = new MockActionInvocation();
-        mai.setAction(action);
-        mai.setResultCode("success");
-        mai.setInvocationContext(ActionContext.getContext());
-        Map<String, Object> param = new HashMap<>();
-        
ActionContext.getContext().withParameters(HttpParameters.create(param).build());
-        ActionContext.getContext().put(ServletActionContext.HTTP_REQUEST, 
createMultipartRequestMaxFiles(req));
-
-        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! Max allowed 
files number is: 3!", action.getActionErrors().iterator().next());
-    }
-
-    public void testMultipartRequestMaxFileSize() throws Exception {
-        MockHttpServletRequest req = new MockHttpServletRequest();
-        req.setCharacterEncoding(StandardCharsets.UTF_8.name());
-        req.setMethod("post");
-        req.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");
-        req.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<String, Object> param = new HashMap<>();
-        ActionContext.getContext()
-                .withParameters(HttpParameters.create(param).build())
-                .withServletRequest(createMultipartRequestMaxFileSize(req));
-
-        interceptor.intercept(mai);
-
-        assertTrue(action.hasActionErrors());
-
-        Collection<String> errors = action.getActionErrors();
-        assertEquals(1, errors.size());
-        String msg = errors.iterator().next();
-        assertEquals(
-                "File in request exceeded allowed file size limit! Max file 
size allowed is: 10 but file deleteme.txt was: 34!",
-                msg);
-    }
-
-    public void testMultipartRequestMaxStringLength() throws Exception {
-        MockHttpServletRequest req = new MockHttpServletRequest();
-        req.setCharacterEncoding(StandardCharsets.UTF_8.name());
-        req.setMethod("post");
-        req.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");
-        req.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<String, Object> param = new HashMap<>();
-        ActionContext.getContext()
-                .withParameters(HttpParameters.create(param).build())
-                
.withServletRequest(createMultipartRequestMaxStringLength(req));
-
-        interceptor.intercept(mai);
-
-        assertTrue(action.hasActionErrors());
-
-        Collection<String> 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 {
-        MockHttpServletRequest req = new MockHttpServletRequest();
-        req.setCharacterEncoding(StandardCharsets.UTF_8.name());
-        req.setMethod("post");
-        req.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");
-        req.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<String, Object> param = new HashMap<>();
-        ActionContext.getContext()
-            .withParameters(HttpParameters.create(param).build())
-            .withLocale(Locale.GERMAN)
-            .withServletRequest(createMultipartRequestMaxSize(req, 10));
-
-        interceptor.intercept(mai);
-
-        assertTrue(action.hasActionErrors());
-
-        Collection<String> 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"));
-    }
-
-    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(HttpServletRequest req) {
-        return createMultipartRequest(req, -1, 10, -1, -1);
-    }
-
-    private MultiPartRequestWrapper 
createMultipartRequestMaxFiles(HttpServletRequest req) {
-        return createMultipartRequest(req, -1, -1, 3, -1);
-    }
-
-    private MultiPartRequestWrapper 
createMultipartRequestMaxSize(HttpServletRequest req, int maxsize) {
-        return createMultipartRequest(req, maxsize, -1, -1, -1);
-    }
-
-    private MultiPartRequestWrapper 
createMultipartRequestMaxStringLength(HttpServletRequest req) {
-        return createMultipartRequest(req, -1, -1, -1, 20);
-    }
-
-    private MultiPartRequestWrapper createMultipartRequest(HttpServletRequest 
req, 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));
-        return new MultiPartRequestWrapper(jak, req, 
tempDir.getAbsolutePath(), new DefaultLocaleProvider());
-    }
-
-    private MultiPartRequestWrapper 
createMultipartRequestNoMaxParamsSet(HttpServletRequest req) {
-
-        JakartaMultiPartRequest jak = new JakartaMultiPartRequest();
-        return new MultiPartRequestWrapper(jak, req, 
tempDir.getAbsolutePath(), new DefaultLocaleProvider());
-    }
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-
-        interceptor = new FileUploadInterceptor();
-        container.inject(interceptor);
-        tempDir = File.createTempFile("struts", "fileupload");
-        tempDir.delete();
-        tempDir.mkdirs();
-    }
-
-    @Override
-    protected void tearDown() throws Exception {
-        tempDir.delete();
-        interceptor.destroy();
-        super.tearDown();
-    }
-
-    public static class MyFileupAction extends ActionSupport {
-
-        private static final long serialVersionUID = 6255238895447968889L;
-
-        // no methods
-        // Note: We do not currently need fields/getters/setters for 
normalFormField1, normalFormField2 since
-        //       the upload interceptor only prepares the normal field 
parameters.
-    }
-
-}

Reply via email to