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

markt pushed a commit to branch 1.x
in repository https://gitbox.apache.org/repos/asf/commons-fileupload.git

commit 2c5e872b42e1a956b8e6eb8d962001c774eb225d
Author: Merbin J Anselm <merbin.j.ans...@sap.com>
AuthorDate: Tue Dec 10 12:00:25 2019 +0530

    Detect asterisk only if is at end & added tests
---
 .../apache/commons/fileupload/ParameterParser.java |  9 ++---
 .../fileupload/util/mime/RFC2231Utility.java       | 28 +++++++++++++++
 .../commons/fileupload/ParameterParserTest.java    | 22 ++++++++++++
 .../util/mime/RFC2231UtilityTestCase.java          | 40 +++++++++++++++++++---
 4 files changed, 87 insertions(+), 12 deletions(-)

diff --git a/src/main/java/org/apache/commons/fileupload/ParameterParser.java 
b/src/main/java/org/apache/commons/fileupload/ParameterParser.java
index 1a0ca851..96ed2e87 100644
--- a/src/main/java/org/apache/commons/fileupload/ParameterParser.java
+++ b/src/main/java/org/apache/commons/fileupload/ParameterParser.java
@@ -306,12 +306,10 @@ public class ParameterParser {
 
         String paramName = null;
         String paramValue = null;
-        boolean hasExtendedParams = false;
         while (hasChar()) {
             paramName = parseToken(new char[] {
                     '=', separator });
             paramValue = null;
-            hasExtendedParams = (paramName != null) ? paramName.contains("*") 
: false; //TODO: Check only if delimiter is at end
             if (hasChar() && (charArray[pos] == '=')) {
                 pos++; // skip '='
                 paramValue = parseQuotedToken(new char[] {
@@ -319,7 +317,7 @@ public class ParameterParser {
 
                 if (paramValue != null) {
                     try {
-                        paramValue = hasExtendedParams ? 
RFC2231Utility.decodeText(paramValue)
+                        paramValue = RFC2231Utility.hasEncodedValue(paramName) 
? RFC2231Utility.decodeText(paramValue)
                                 : MimeUtility.decodeText(paramValue);
                     } catch (final UnsupportedEncodingException e) {
                         // let's keep the original value in this case
@@ -330,13 +328,10 @@ public class ParameterParser {
                 pos++; // skip separator
             }
             if ((paramName != null) && (paramName.length() > 0)) {
-                if (hasExtendedParams) {
-                    paramName = paramName.replace("*", ""); //strip of the * 
from the name //TODO: Replace the last character alone
-                }
+                paramName = RFC2231Utility.stripDelimiter(paramName);
                 if (this.lowerCaseNames) {
                     paramName = paramName.toLowerCase(Locale.ENGLISH);
                 }
-
                 params.put(paramName, paramValue);
             }
         }
diff --git 
a/src/main/java/org/apache/commons/fileupload/util/mime/RFC2231Utility.java 
b/src/main/java/org/apache/commons/fileupload/util/mime/RFC2231Utility.java
index f625494b..af77227d 100644
--- a/src/main/java/org/apache/commons/fileupload/util/mime/RFC2231Utility.java
+++ b/src/main/java/org/apache/commons/fileupload/util/mime/RFC2231Utility.java
@@ -43,6 +43,34 @@ public final class RFC2231Utility {
         }
     }
 
+    /**
+     * Checks if Asterisk (*) at the end of parameter name to indicate,
+     * if it has charset and language information to decode the value
+     * @param paramName
+     * @return {@code true}, if encoded as per RFC 2231, {@code false} 
otherwise
+     */
+    public static boolean hasEncodedValue(String paramName) {
+        if (paramName != null) {
+            return paramName.lastIndexOf("*") == (paramName.length() - 1);
+        }
+        return false;
+    }
+
+    /**
+     * If {@code paramName} has Asterisk (*) at the end, it will be stripped 
off, 
+     * else the passed value will be returned
+     * @param paramName
+     * @return stripped {@code paramName} of Asterisk (*), if RFC2231 encoded
+     */
+    public static String stripDelimiter(String paramName) {
+        if (hasEncodedValue(paramName)) {
+            StringBuilder paramBuilder = new StringBuilder(paramName);
+            paramBuilder.deleteCharAt(paramName.lastIndexOf("*"));
+            return paramBuilder.toString();
+        }
+        return paramName;
+    }
+
     /**
      * Decode a string of text obtained from a HTTP header as per RFC 2231
      *
diff --git 
a/src/test/java/org/apache/commons/fileupload/ParameterParserTest.java 
b/src/test/java/org/apache/commons/fileupload/ParameterParserTest.java
index a97cac9b..efefdf0f 100644
--- a/src/test/java/org/apache/commons/fileupload/ParameterParserTest.java
+++ b/src/test/java/org/apache/commons/fileupload/ParameterParserTest.java
@@ -125,9 +125,31 @@ public class ParameterParserTest {
     @Test
     public void testFileUpload274() {
         ParameterParser parser = new ParameterParser();
+
+        // Should parse a UTF-8 charset
         String s = "Content-Disposition: form-data; name=\"file\"; 
filename*=UTF-8\'\'%E3%81%93%E3%82%93%E3%81%AB%E3%81%A1%E3%81%AF\r\n";
         Map<String, String> params = parser.parse(s, new char[] { ',', ';' });
         assertEquals("\u3053\u3093\u306B\u3061\u306F", 
params.get("filename")); //filename = "こんにちは" in japanese
+
+        // Should parse ISO-8859-1 charset
+        s = "Content-Disposition: form-data; name=\"file\"; 
filename*=UTF-8\'\'%70%C3%A2%74%C3%A9\r\n";
+        params = parser.parse(s, new char[] { ',', ';' });
+        assertEquals("\u0070\u00e2\u0074\u00e9", params.get("filename")); 
//filename = "pâté" in french
+
+        // Should not decode if '*' is not at the end of param-name
+        s = "Content-Disposition: form-data; name=\"file\"; 
file*name=UTF-8\'\'%61%62%63\r\n";
+        params = parser.parse(s, new char[] { ',', ';' });
+        assertEquals("UTF-8\'\'%61%62%63", params.get("file*name"));
+
+        // Should not decode if param-value does not follow 
<charset>'<lang>'<encoded>
+        s = "Content-Disposition: form-data; name=\"file\"; 
filename*=a\'bc\r\n";
+        params = parser.parse(s, new char[] { ',', ';' });
+        assertEquals("a\'bc", params.get("filename"));
+
+        // Should not decode if param-name doesn't have '*' at end
+        s = "Content-Disposition: form-data; name=\"file\"; 
filename=a\'b\'c\r\n";
+        params = parser.parse(s, new char[] { ',', ';' });
+        assertEquals("a\'b\'c", params.get("filename"));
     }
 
 }
diff --git 
a/src/test/java/org/apache/commons/fileupload/util/mime/RFC2231UtilityTestCase.java
 
b/src/test/java/org/apache/commons/fileupload/util/mime/RFC2231UtilityTestCase.java
index 6502be76..a9c09f52 100644
--- 
a/src/test/java/org/apache/commons/fileupload/util/mime/RFC2231UtilityTestCase.java
+++ 
b/src/test/java/org/apache/commons/fileupload/util/mime/RFC2231UtilityTestCase.java
@@ -18,7 +18,10 @@ package org.apache.commons.fileupload.util.mime;
 
 import java.io.UnsupportedEncodingException;
 
-import org.junit.Assert;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
 import org.junit.Test;
 
 /**
@@ -28,6 +31,33 @@ import org.junit.Test;
  */
 public final class RFC2231UtilityTestCase {
 
+    @Test
+    public void testHasEncodedValue() {
+        String nameWithAsteriskAtEnd = "paramname*";
+        assertTrue(RFC2231Utility.hasEncodedValue(nameWithAsteriskAtEnd));
+
+        String nameWithAsteriskNotAtEnd = "param*name";
+        assertFalse(RFC2231Utility.hasEncodedValue(nameWithAsteriskNotAtEnd));
+
+        String nameWithoutAsterisk = "paramname";
+        assertFalse(RFC2231Utility.hasEncodedValue(nameWithoutAsterisk));
+    }
+
+    @Test
+    public void testStripDelimiter() {
+        String nameWithAsteriskAtEnd = "paramname*";
+        assertEquals("paramname", 
RFC2231Utility.stripDelimiter(nameWithAsteriskAtEnd));
+
+        String nameWithAsteriskNotAtEnd = "param*name";
+        assertEquals("param*name", 
RFC2231Utility.stripDelimiter(nameWithAsteriskNotAtEnd));
+
+        String nameWithTwoAsterisks = "param*name*";
+        assertEquals("param*name", 
RFC2231Utility.stripDelimiter(nameWithTwoAsterisks));
+
+        String nameWithoutAsterisk = "paramname";
+        assertEquals("paramname", 
RFC2231Utility.stripDelimiter(nameWithoutAsterisk));
+    }
+
     @Test
     public void noNeedToDecode() throws Exception {
         assertEncoded("abc", "abc");
@@ -43,12 +73,12 @@ public final class RFC2231UtilityTestCase {
         assertEncoded("\u00A3 rate", "iso-8859-1'en'%A3%20rate"); //"£ rate"
     }
 
-    private static void assertEncoded(String expected, String encoded) throws 
Exception {
-        Assert.assertEquals(expected, RFC2231Utility.decodeText(encoded));
-    }
-
     @Test(expected = UnsupportedEncodingException.class)
     public void decodeInvalidEncoding() throws Exception {
         RFC2231Utility.decodeText("abc'en'hello");
     }
+
+    private static void assertEncoded(String expected, String encoded) throws 
Exception {
+        assertEquals(expected, RFC2231Utility.decodeText(encoded));
+    }
 }

Reply via email to