This is an automated email from the ASF dual-hosted git repository. lukaszlenart pushed a commit to branch fix/WW-5501-revert-s7 in repository https://gitbox.apache.org/repos/asf/struts.git
commit 2db4479e7375f173bbd86355e05e47ad9e854c54 Author: Lukasz Lenart <lukaszlen...@apache.org> AuthorDate: Sun Feb 16 08:20:47 2025 +0100 WW-5501 Reverts changes related to WW-5501 --- .../multipart/AbstractMultiPartRequest.java | 62 +---------------- .../multipart/JakartaMultiPartRequest.java | 26 ++------ .../multipart/JakartaStreamMultiPartRequest.java | 27 ++------ .../org/apache/struts2/struts-messages.properties | 4 -- .../multipart/AbstractMultiPartRequestTest.java | 57 +--------------- .../AbstractMultiPartRequestWithDMITest.java | 69 ------------------- .../JakartaMultiPartRequestWithDMITest.java | 28 -------- .../JakartaStreamMultiPartRequestWithDMITest.java | 28 -------- .../ActionFileUploadInterceptorTest.java | 78 +++------------------- .../DefaultExcludedPatternsCheckerTest.java | 2 +- 10 files changed, 24 insertions(+), 357 deletions(-) diff --git a/core/src/main/java/org/apache/struts2/dispatcher/multipart/AbstractMultiPartRequest.java b/core/src/main/java/org/apache/struts2/dispatcher/multipart/AbstractMultiPartRequest.java index 00e774a72..90ecbe816 100644 --- a/core/src/main/java/org/apache/struts2/dispatcher/multipart/AbstractMultiPartRequest.java +++ b/core/src/main/java/org/apache/struts2/dispatcher/multipart/AbstractMultiPartRequest.java @@ -18,6 +18,8 @@ */ package org.apache.struts2.dispatcher.multipart; +import org.apache.struts2.inject.Inject; +import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.fileupload2.core.FileUploadByteCountLimitException; import org.apache.commons.fileupload2.core.FileUploadContentTypeException; import org.apache.commons.fileupload2.core.FileUploadException; @@ -30,11 +32,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.struts2.StrutsConstants; import org.apache.struts2.dispatcher.LocalizedMessage; -import org.apache.struts2.inject.Inject; -import org.apache.struts2.security.DefaultExcludedPatternsChecker; -import org.apache.struts2.security.ExcludedPatternsChecker; -import jakarta.servlet.http.HttpServletRequest; import java.io.IOException; import java.nio.charset.Charset; import java.nio.file.Path; @@ -45,8 +43,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import static org.apache.commons.lang3.StringUtils.normalizeSpace; - /** * Abstract class with some helper methods, it should be used * when starting development of another implementation of {@link MultiPartRequest} @@ -54,14 +50,9 @@ import static org.apache.commons.lang3.StringUtils.normalizeSpace; public abstract class AbstractMultiPartRequest implements MultiPartRequest { protected static final String STRUTS_MESSAGES_UPLOAD_ERROR_PARAMETER_TOO_LONG_KEY = "struts.messages.upload.error.parameter.too.long"; - protected static final String STRUTS_MESSAGES_UPLOAD_ERROR_ILLEGAL_CHARACTERS_FIELD = "struts.messages.upload.error.illegal.characters.field"; - protected static final String STRUTS_MESSAGES_UPLOAD_ERROR_ILLEGAL_CHARACTERS_NAME = "struts.messages.upload.error.illegal.characters.name"; private static final Logger LOG = LogManager.getLogger(AbstractMultiPartRequest.class); - private static final String EXCLUDED_FILE_PATTERN = "^(.*[<>&\"'|;\\\\/?*:]+.*|.*\\.\\..*)$"; - private static final String EXCLUDED_FILE_PATTERN_WITH_DMI_SUPPORT = "^(?!action:[^<>&\"'|;\\\\/?*:]+(![^<>&\"'|;\\\\/?*:]+)?$)(.*[<>&\"'|;\\\\/?*:]+.*|.*\\.\\..*)$\n"; - /** * Defines the internal buffer size used during streaming operations. */ @@ -117,19 +108,6 @@ public abstract class AbstractMultiPartRequest implements MultiPartRequest { */ protected Map<String, List<String>> parameters = new HashMap<>(); - - private final ExcludedPatternsChecker patternsChecker; - - protected AbstractMultiPartRequest() { - this(false); - } - - protected AbstractMultiPartRequest(boolean dmiValue) { - var patternsChecker = new DefaultExcludedPatternsChecker(); - patternsChecker.setAdditionalExcludePatterns(dmiValue ? EXCLUDED_FILE_PATTERN_WITH_DMI_SUPPORT : EXCLUDED_FILE_PATTERN); - this.patternsChecker = patternsChecker; - } - /** * @param bufferSize Sets the buffer size to be used. */ @@ -431,40 +409,4 @@ public abstract class AbstractMultiPartRequest implements MultiPartRequest { } } - /** - * @param fileName file name to check - * @return true if the file name is excluded - */ - protected boolean isExcluded(String fileName) { - return patternsChecker.isExcluded(fileName).isExcluded(); - } - - protected boolean isInvalidInput(String fieldName, String fileName) { - // Skip file uploads that don't have a file name - meaning that no file was selected. - if (fileName == null || fileName.isBlank()) { - LOG.debug(() -> "No file has been uploaded for the field: " + normalizeSpace(fieldName)); - return true; - } - - if (isExcluded(fileName)) { - var normalizedFileName = normalizeSpace(fileName); - LOG.debug("File name [{}] is not accepted", normalizedFileName); - errors.add(new LocalizedMessage(getClass(), STRUTS_MESSAGES_UPLOAD_ERROR_ILLEGAL_CHARACTERS_NAME, null, - new String[]{normalizedFileName})); - return true; - } - - return isInvalidInput(fieldName); - } - - protected boolean isInvalidInput(String fieldName) { - if (isExcluded(fieldName)) { - var normalizedFieldName = normalizeSpace(fieldName); - LOG.debug("Form field [{}}] is rejected!", normalizedFieldName); - errors.add(new LocalizedMessage(getClass(), STRUTS_MESSAGES_UPLOAD_ERROR_ILLEGAL_CHARACTERS_FIELD, null, - new String[]{normalizedFieldName})); - return true; - } - return false; - } } diff --git a/core/src/main/java/org/apache/struts2/dispatcher/multipart/JakartaMultiPartRequest.java b/core/src/main/java/org/apache/struts2/dispatcher/multipart/JakartaMultiPartRequest.java index a61ced6da..d2ef13b1d 100644 --- a/core/src/main/java/org/apache/struts2/dispatcher/multipart/JakartaMultiPartRequest.java +++ b/core/src/main/java/org/apache/struts2/dispatcher/multipart/JakartaMultiPartRequest.java @@ -18,17 +18,14 @@ */ package org.apache.struts2.dispatcher.multipart; +import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.fileupload2.core.DiskFileItem; import org.apache.commons.fileupload2.core.DiskFileItemFactory; import org.apache.commons.fileupload2.jakarta.servlet6.JakartaServletDiskFileUpload; -import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.apache.struts2.StrutsConstants; -import org.apache.struts2.inject.Inject; -import jakarta.servlet.http.HttpServletRequest; import java.io.IOException; import java.nio.charset.Charset; import java.nio.file.Path; @@ -44,15 +41,6 @@ public class JakartaMultiPartRequest extends AbstractMultiPartRequest { private static final Logger LOG = LogManager.getLogger(JakartaMultiPartRequest.class); - public JakartaMultiPartRequest() { - super(); - } - - @Inject(value = StrutsConstants.STRUTS_ENABLE_DYNAMIC_METHOD_INVOCATION, required = false) - public JakartaMultiPartRequest(String dmiValue) { - super(BooleanUtils.toBoolean(dmiValue)); - } - @Override protected void processUpload(HttpServletRequest request, String saveDir) throws IOException { Charset charset = readCharsetEncoding(request); @@ -89,14 +77,10 @@ public class JakartaMultiPartRequest extends AbstractMultiPartRequest { } protected void processNormalFormField(DiskFileItem item, Charset charset) throws IOException { - var fieldName = item.getFieldName(); - LOG.debug("Item: {} is a normal form field", fieldName); - - if (isInvalidInput(fieldName)) { - return; - } + LOG.debug("Item: {} is a normal form field", normalizeSpace(item.getName())); List<String> values; + String fieldName = item.getFieldName(); if (parameters.get(fieldName) != null) { values = parameters.get(fieldName); } else { @@ -116,7 +100,9 @@ public class JakartaMultiPartRequest extends AbstractMultiPartRequest { } protected void processFileField(DiskFileItem item) { - if (isInvalidInput(item.getFieldName(), item.getName())) { + // Skip file uploads that don't have a file name - meaning that no file was selected. + if (item.getName() == null || item.getName().trim().isEmpty()) { + LOG.debug(() -> "No file has been uploaded for the field: " + normalizeSpace(item.getFieldName())); return; } diff --git a/core/src/main/java/org/apache/struts2/dispatcher/multipart/JakartaStreamMultiPartRequest.java b/core/src/main/java/org/apache/struts2/dispatcher/multipart/JakartaStreamMultiPartRequest.java index 76c0e3654..17b6f377b 100644 --- a/core/src/main/java/org/apache/struts2/dispatcher/multipart/JakartaStreamMultiPartRequest.java +++ b/core/src/main/java/org/apache/struts2/dispatcher/multipart/JakartaStreamMultiPartRequest.java @@ -18,19 +18,16 @@ */ package org.apache.struts2.dispatcher.multipart; +import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.fileupload2.core.DiskFileItemFactory; import org.apache.commons.fileupload2.core.FileItemInput; import org.apache.commons.fileupload2.core.FileUploadFileCountLimitException; import org.apache.commons.fileupload2.core.FileUploadSizeException; import org.apache.commons.fileupload2.jakarta.servlet6.JakartaServletDiskFileUpload; -import org.apache.commons.lang3.BooleanUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.apache.struts2.StrutsConstants; import org.apache.struts2.dispatcher.LocalizedMessage; -import org.apache.struts2.inject.Inject; -import jakarta.servlet.http.HttpServletRequest; import java.io.BufferedOutputStream; import java.io.ByteArrayOutputStream; import java.io.File; @@ -59,15 +56,6 @@ public class JakartaStreamMultiPartRequest extends AbstractMultiPartRequest { private static final Logger LOG = LogManager.getLogger(JakartaStreamMultiPartRequest.class); - public JakartaStreamMultiPartRequest() { - super(); - } - - @Inject(value = StrutsConstants.STRUTS_ENABLE_DYNAMIC_METHOD_INVOCATION, required = false) - public JakartaStreamMultiPartRequest(String dmiValue) { - super(BooleanUtils.toBoolean(dmiValue)); - } - /** * Processes the upload. * @@ -126,11 +114,8 @@ public class JakartaStreamMultiPartRequest extends AbstractMultiPartRequest { */ protected void processFileItemAsFormField(FileItemInput fileItemInput) throws IOException { String fieldName = fileItemInput.getFieldName(); - if (isInvalidInput(fieldName)) { - return; - } - String fieldValue = readStream(fileItemInput.getInputStream()); + if (exceedsMaxStringLength(fieldName, fieldValue)) { return; } @@ -202,7 +187,9 @@ public class JakartaStreamMultiPartRequest extends AbstractMultiPartRequest { * @param location location */ protected void processFileItemAsFileField(FileItemInput fileItemInput, Path location) throws IOException { - if (isInvalidInput(fileItemInput.getFieldName(), fileItemInput.getName())) { + // Skip file uploads that don't have a file name - meaning that no file was selected. + if (fileItemInput.getName() == null || fileItemInput.getName().trim().isEmpty()) { + LOG.debug(() -> "No file has been uploaded for the field: " + normalizeSpace(fileItemInput.getFieldName())); return; } @@ -245,9 +232,7 @@ public class JakartaStreamMultiPartRequest extends AbstractMultiPartRequest { InputStream input = fileItemInput.getInputStream(); try (OutputStream output = new BufferedOutputStream(Files.newOutputStream(file.toPath()), bufferSize)) { byte[] buffer = new byte[bufferSize]; - if (LOG.isDebugEnabled()) { - LOG.debug("Streaming file: {} using buffer size: {}", normalizeSpace(fileItemInput.getName()), bufferSize); - } + LOG.debug("Streaming file: {} using buffer size: {}", normalizeSpace(fileItemInput.getName()), bufferSize); for (int length; ((length = input.read(buffer)) > 0); ) { output.write(buffer, 0, length); } diff --git a/core/src/main/resources/org/apache/struts2/struts-messages.properties b/core/src/main/resources/org/apache/struts2/struts-messages.properties index e802b5cc4..7c418f75c 100644 --- a/core/src/main/resources/org/apache/struts2/struts-messages.properties +++ b/core/src/main/resources/org/apache/struts2/struts-messages.properties @@ -40,10 +40,6 @@ struts.messages.error.file.too.large=The file is too large to be uploaded: {0} " # 1 - max string length # 2 - actual size struts.messages.upload.error.parameter.too.long=The request parameter "{0}" was too long. Max length allowed is {1}, but found {2}! -# 0 - field name -struts.messages.upload.error.illegal.characters.field=The multipart upload field name "{0}" contains illegal characters! -# 0 - file name -struts.messages.upload.error.illegal.characters.name=The multipart upload filename "{0}" contains illegal characters! # 0 - input name # 1 - original filename # 2 - file name after uploading the file diff --git a/core/src/test/java/org/apache/struts2/dispatcher/multipart/AbstractMultiPartRequestTest.java b/core/src/test/java/org/apache/struts2/dispatcher/multipart/AbstractMultiPartRequestTest.java index 699d0b66c..22625cdf9 100644 --- a/core/src/test/java/org/apache/struts2/dispatcher/multipart/AbstractMultiPartRequestTest.java +++ b/core/src/test/java/org/apache/struts2/dispatcher/multipart/AbstractMultiPartRequestTest.java @@ -19,13 +19,7 @@ package org.apache.struts2.dispatcher.multipart; import org.apache.commons.fileupload2.jakarta.servlet6.JakartaServletDiskFileUpload; -import org.apache.struts2.config.Configuration; -import org.apache.struts2.config.ConfigurationManager; -import org.apache.struts2.dispatcher.Dispatcher; import org.apache.struts2.dispatcher.LocalizedMessage; -import org.apache.struts2.inject.Container; -import org.apache.struts2.util.StrutsTestCaseHelper; -import org.apache.struts2.views.jsp.StrutsMockServletContext; import org.assertj.core.api.InstanceOfAssertFactories; import org.junit.After; import org.junit.Before; @@ -37,7 +31,6 @@ import java.io.File; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Objects; @@ -54,7 +47,6 @@ abstract class AbstractMultiPartRequestTest { protected final String endline = "\r\n"; protected AbstractMultiPartRequest multiPart; - protected Container container; abstract protected AbstractMultiPartRequest createMultipartRequest(); @@ -67,13 +59,7 @@ abstract class AbstractMultiPartRequestTest { } @Before - public void before() throws Exception { - StrutsMockServletContext servletContext = new StrutsMockServletContext(); - Dispatcher dispatcher = StrutsTestCaseHelper.initDispatcher(servletContext, Collections.emptyMap()); - ConfigurationManager configurationManager = dispatcher.getConfigurationManager(); - Configuration configuration = configurationManager.getConfiguration(); - container = configuration.getContainer(); - + public void before() { mockRequest = new MockHttpServletRequest(); mockRequest.setCharacterEncoding(StandardCharsets.UTF_8.name()); mockRequest.setMethod("post"); @@ -506,47 +492,6 @@ abstract class AbstractMultiPartRequestTest { .containsExactly("struts.messages.upload.error.FileUploadException"); } - @Test - public void maliciousFields() throws IOException { - String content = formFile("file1", "test1.csv", "1,2,3,4") + - formField("top.param", "expression") + - endline + "--" + boundary + "--"; - - mockRequest.setContent(content.getBytes(StandardCharsets.UTF_8)); - - assertThat(JakartaServletDiskFileUpload.isMultipartContent(mockRequest)).isTrue(); - - multiPart.parse(mockRequest, tempDir); - - assertThat(multiPart.getErrors()).extracting(LocalizedMessage::getTextKey) - .containsExactly(AbstractMultiPartRequest.STRUTS_MESSAGES_UPLOAD_ERROR_ILLEGAL_CHARACTERS_FIELD); - - assertThat(multiPart.getParameterNames().asIterator()).toIterable() - .isEmpty(); - } - - @Test - public void maliciousFilename() throws IOException { - String content = formFile("file1", "../test1.csv", "1,2,3,4") + - formField("param", "expression") + - endline + "--" + boundary + "--"; - - mockRequest.setContent(content.getBytes(StandardCharsets.UTF_8)); - - assertThat(JakartaServletDiskFileUpload.isMultipartContent(mockRequest)).isTrue(); - - multiPart.parse(mockRequest, tempDir); - - assertThat(multiPart.getErrors()).extracting(LocalizedMessage::getTextKey) - .containsExactly(AbstractMultiPartRequest.STRUTS_MESSAGES_UPLOAD_ERROR_ILLEGAL_CHARACTERS_NAME); - - assertThat(multiPart.getParameterNames().asIterator()).toIterable() - .hasSize(1); - assertThat(multiPart.getParameterNames().asIterator()).toIterable() - .containsOnly("param"); - assertThat(multiPart.getFileNames("file1")).isEmpty(); - } - protected String formFile(String fieldName, String filename, String content) { return endline + "--" + boundary + endline + diff --git a/core/src/test/java/org/apache/struts2/dispatcher/multipart/AbstractMultiPartRequestWithDMITest.java b/core/src/test/java/org/apache/struts2/dispatcher/multipart/AbstractMultiPartRequestWithDMITest.java deleted file mode 100644 index fcec29ddf..000000000 --- a/core/src/test/java/org/apache/struts2/dispatcher/multipart/AbstractMultiPartRequestWithDMITest.java +++ /dev/null @@ -1,69 +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.dispatcher.multipart; - -import org.apache.commons.fileupload2.jakarta.servlet6.JakartaServletDiskFileUpload; -import org.junit.Test; - -import java.io.IOException; -import java.nio.charset.StandardCharsets; - -import static org.assertj.core.api.Assertions.assertThat; - -abstract class AbstractMultiPartRequestWithDMITest extends AbstractMultiPartRequestTest { - - @Test - public void actionField() throws IOException { - String content = formFile("file1", "test1.csv", "1,2,3,4") + - formField("action:myUploads", "") + - endline + "--" + boundary + "--"; - - mockRequest.setContent(content.getBytes(StandardCharsets.UTF_8)); - - assertThat(JakartaServletDiskFileUpload.isMultipartContent(mockRequest)).isTrue(); - - multiPart.parse(mockRequest, tempDir); - - assertThat(multiPart.getErrors()) - .isEmpty(); - - assertThat(multiPart.getParameterNames().asIterator()).toIterable() - .containsOnly("action:myUploads"); - } - - @Test - public void actionFieldWithBang() throws IOException { - String content = formFile("file1", "test1.csv", "1,2,3,4") + - formField("action:myUploads!upload", "") + - endline + "--" + boundary + "--"; - - mockRequest.setContent(content.getBytes(StandardCharsets.UTF_8)); - - assertThat(JakartaServletDiskFileUpload.isMultipartContent(mockRequest)).isTrue(); - - multiPart.parse(mockRequest, tempDir); - - assertThat(multiPart.getErrors()) - .isEmpty(); - - assertThat(multiPart.getParameterNames().asIterator()).toIterable() - .containsOnly("action:myUploads!upload"); - } - -} diff --git a/core/src/test/java/org/apache/struts2/dispatcher/multipart/JakartaMultiPartRequestWithDMITest.java b/core/src/test/java/org/apache/struts2/dispatcher/multipart/JakartaMultiPartRequestWithDMITest.java deleted file mode 100644 index 6aecba01b..000000000 --- a/core/src/test/java/org/apache/struts2/dispatcher/multipart/JakartaMultiPartRequestWithDMITest.java +++ /dev/null @@ -1,28 +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.dispatcher.multipart; - -public class JakartaMultiPartRequestWithDMITest extends AbstractMultiPartRequestWithDMITest { - - @Override - protected AbstractMultiPartRequest createMultipartRequest() { - return new JakartaMultiPartRequest(Boolean.TRUE.toString()); - } - -} diff --git a/core/src/test/java/org/apache/struts2/dispatcher/multipart/JakartaStreamMultiPartRequestWithDMITest.java b/core/src/test/java/org/apache/struts2/dispatcher/multipart/JakartaStreamMultiPartRequestWithDMITest.java deleted file mode 100644 index f93d42f33..000000000 --- a/core/src/test/java/org/apache/struts2/dispatcher/multipart/JakartaStreamMultiPartRequestWithDMITest.java +++ /dev/null @@ -1,28 +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.dispatcher.multipart; - -public class JakartaStreamMultiPartRequestWithDMITest extends AbstractMultiPartRequestWithDMITest { - - @Override - protected AbstractMultiPartRequest createMultipartRequest() { - return new JakartaStreamMultiPartRequest(Boolean.TRUE.toString()); - } - -} diff --git a/core/src/test/java/org/apache/struts2/interceptor/ActionFileUploadInterceptorTest.java b/core/src/test/java/org/apache/struts2/interceptor/ActionFileUploadInterceptorTest.java index 41b4fee07..b8761a8a4 100644 --- a/core/src/test/java/org/apache/struts2/interceptor/ActionFileUploadInterceptorTest.java +++ b/core/src/test/java/org/apache/struts2/interceptor/ActionFileUploadInterceptorTest.java @@ -18,21 +18,21 @@ */ package org.apache.struts2.interceptor; -import org.apache.commons.fileupload2.jakarta.servlet6.JakartaServletDiskFileUpload; -import org.apache.commons.fileupload2.jakarta.servlet6.JakartaServletFileUpload; import org.apache.struts2.ActionContext; import org.apache.struts2.ActionSupport; -import org.apache.struts2.StrutsInternalTestCase; +import org.apache.struts2.locale.DefaultLocaleProvider; import org.apache.struts2.ValidationAwareSupport; +import org.apache.struts2.mock.MockActionInvocation; +import org.apache.struts2.mock.MockActionProxy; +import org.apache.struts2.util.ClassLoaderUtil; +import org.apache.commons.fileupload2.jakarta.servlet6.JakartaServletDiskFileUpload; +import org.apache.commons.fileupload2.jakarta.servlet6.JakartaServletFileUpload; +import org.apache.struts2.StrutsInternalTestCase; import org.apache.struts2.action.UploadedFilesAware; 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.apache.struts2.locale.DefaultLocaleProvider; -import org.apache.struts2.mock.MockActionInvocation; -import org.apache.struts2.mock.MockActionProxy; -import org.apache.struts2.util.ClassLoaderUtil; import org.assertj.core.util.Files; import org.springframework.mock.web.MockHttpServletRequest; @@ -514,73 +514,11 @@ public class ActionFileUploadInterceptorTest extends StrutsInternalTestCase { assertTrue(msg.startsWith("Der Request übertraf die maximal erlaubte Größe")); } - public void testUnacceptedFieldName() 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=\"top.file\"; filename=\"deleteme.txt\"\r\n" + - "Content-Type: text/html\r\n" + - "\r\n" + - "Unit test of ActionFileUploadInterceptor" + - "\r\n" + - "-----1234--\r\n"); - request.setContent(content.getBytes(StandardCharsets.US_ASCII)); - - MyFileUploadAction action = container.inject(MyFileUploadAction.class); - - MockActionInvocation mai = new MockActionInvocation(); - mai.setAction(action); - mai.setResultCode("success"); - mai.setInvocationContext(ActionContext.getContext()); - ActionContext.getContext() - .withServletRequest(createMultipartRequestMaxSize(2000)); - - interceptor.intercept(mai); - - assertThat(action.getActionErrors()) - .containsExactly("The multipart upload field name \"top.file\" contains illegal characters!"); - assertNull(action.getUploadFiles()); - } - - public void testUnacceptedFileName() 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 ActionFileUploadInterceptor" + - "\r\n" + - "-----1234--\r\n"); - request.setContent(content.getBytes(StandardCharsets.US_ASCII)); - - MyFileUploadAction action = container.inject(MyFileUploadAction.class); - - MockActionInvocation mai = new MockActionInvocation(); - mai.setAction(action); - mai.setResultCode("success"); - mai.setInvocationContext(ActionContext.getContext()); - ActionContext.getContext() - .withServletRequest(createMultipartRequestMaxSize(2000)); - - interceptor.intercept(mai); - - assertThat(action.getActionErrors()) - .containsExactly("The multipart upload filename \"../deleteme.txt\" contains illegal characters!"); - assertNull(action.getUploadFiles()); - } - private String encodeTextFile(String filename, String contentType, String content) { return endline + "--" + boundary + endline + - "Content-Disposition: form-data; name=\"" + "file" + "\"; filename=\"" + filename + "\"" + + "Content-Disposition: form-data; name=\"" + "file" + "\"; filename=\"" + filename + endline + "Content-Type: " + contentType + endline + diff --git a/core/src/test/java/org/apache/struts2/security/DefaultExcludedPatternsCheckerTest.java b/core/src/test/java/org/apache/struts2/security/DefaultExcludedPatternsCheckerTest.java index 06889302a..1f549e011 100644 --- a/core/src/test/java/org/apache/struts2/security/DefaultExcludedPatternsCheckerTest.java +++ b/core/src/test/java/org/apache/struts2/security/DefaultExcludedPatternsCheckerTest.java @@ -93,7 +93,7 @@ public class DefaultExcludedPatternsCheckerTest extends XWorkTestCase { public void testDefaultExcludePatterns() throws Exception { // given - List<String> prefixes = Arrays.asList("#[0].%s", "[0].%s", "top.%s", "%{[0].%s}", "%{#[0].%s}", "%{top.%s}", "%{#top.%s}", "%{#%s}", "%{%s}", "#%s", "top.param", "%{top.request}", "#top.param"); + List<String> prefixes = Arrays.asList("#[0].%s", "[0].%s", "top.%s", "%{[0].%s}", "%{#[0].%s}", "%{top.%s}", "%{#top.%s}", "%{#%s}", "%{%s}", "#%s"); List<String> inners = Arrays.asList("servletRequest", "servletResponse", "servletContext", "application", "session", "struts", "request", "response", "dojo", "parameters"); List<String> suffixes = Arrays.asList("['test']", "[\"test\"]", ".test");