chemistry-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From f...@apache.org
Subject svn commit: r1412477 - in /chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src: main/java/org/apache/chemistry/opencmis/server/impl/browser/ main/java/org/apache/chemistry/opencmis/server/shared/ main/webapp/web/ t...
Date Thu, 22 Nov 2012 09:49:15 GMT
Author: fmui
Date: Thu Nov 22 09:49:12 2012
New Revision: 1412477

URL: http://svn.apache.org/viewvc?rev=1412477&view=rev
Log:
Server: Improved charset control to Browser Binding POST calls

Modified:
    chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/MultipartParser.java
    chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/POSTHttpServletRequestWrapper.java
    chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/shared/QueryStringHttpServletRequestWrapper.java
    chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/webapp/web/index.html
    chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/test/java/org/apache/chemistry/opencmis/server/impl/MultipartParserTest.java

Modified: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/MultipartParser.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/MultipartParser.java?rev=1412477&r1=1412476&r2=1412477&view=diff
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/MultipartParser.java
(original)
+++ chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/MultipartParser.java
Thu Nov 22 09:49:12 2012
@@ -44,8 +44,9 @@ public class MultipartParser {
 
     public static final String MULTIPART = "multipart/";
 
-    private static final int MAX_FIELD_BYTES = 10 * 1024 * 1024;
+    private static final String CHARSET_FIELD = "_charset_";
 
+    private static final int MAX_FIELD_BYTES = 10 * 1024 * 1024;
     private static final int BUFFER_SIZE = 64 * 1024;
 
     private static final byte CR = 0x0D;
@@ -74,13 +75,14 @@ public class MultipartParser {
 
     private Map<String, String> headers;
 
-    private boolean isContent;
-    private String name;
     private String filename;
     private String contentType;
     private BigInteger contentSize;
     private InputStream contentStream;
-    private String value;
+
+    private Map<String, String[]> fields;
+    private Map<String, byte[][]> rawFields;
+    private String charset = "ISO-8859-1";
 
     public MultipartParser(HttpServletRequest request, File tempDir, int memoryThreshold,
long maxContentSize)
             throws IOException {
@@ -102,9 +104,38 @@ public class MultipartParser {
         hasContent = false;
         fieldBytes = 0;
 
+        fields = new HashMap<String, String[]>();
+        rawFields = new HashMap<String, byte[][]>();
+
         skipPreamble();
     }
 
+    private void addField(String name, String value) {
+        String[] values = fields.get(name);
+
+        if (values == null) {
+            fields.put(name, new String[] { value });
+        } else {
+            String[] newValues = new String[values.length + 1];
+            System.arraycopy(values, 0, newValues, 0, values.length);
+            newValues[newValues.length - 1] = value;
+            fields.put(name, newValues);
+        }
+    }
+
+    private void addRawField(String name, byte[] value) {
+        byte[][] values = rawFields.get(name);
+
+        if (values == null) {
+            rawFields.put(name, new byte[][] { value });
+        } else {
+            byte[][] newValues = new byte[values.length + 1][];
+            System.arraycopy(values, 0, newValues, 0, values.length);
+            newValues[newValues.length - 1] = value;
+            rawFields.put(name, newValues);
+        }
+    }
+
     private void extractBoundary() {
         String contentType = request.getContentType();
 
@@ -229,7 +260,7 @@ public class MultipartParser {
         }
 
         if (bufferCount > bufferPosition) {
-            return buffer[bufferPosition++];
+            return buffer[bufferPosition++] & 0xff;
         }
 
         readBuffer();
@@ -290,38 +321,65 @@ public class MultipartParser {
         }
     }
 
-    public void readBodyAsString(String charset) throws IOException {
-        ByteArrayOutputStream bos = new ByteArrayOutputStream();
+    private byte[] readBodyBytes() throws IOException {
+        readBuffer();
+
+        int boundaryPosition = findBoundary();
+
+        if (boundaryPosition > -1) {
+            // the body bytes are completely in the buffer
+            int len = boundaryPosition - bufferPosition;
+            addFieldBytes(len);
 
+            byte[] body = new byte[len];
+            System.arraycopy(buffer, bufferPosition, body, 0, len);
+            bufferPosition = boundaryPosition + boundary.length;
+            return body;
+        }
+
+        // the body bytes are not completely in the buffer
+        // read all available bytes
+        int len = Math.min(BUFFER_SIZE, bufferCount) - bufferPosition;
+        addFieldBytes(len);
+
+        ByteArrayOutputStream bos = new ByteArrayOutputStream(len + 32);
+
+        bos.write(buffer, bufferPosition, len);
+        bufferPosition = bufferPosition + len;
+
+        // read next chunk
         while (true) {
             readBuffer();
 
-            int boundaryPosition = findBoundary();
+            boundaryPosition = findBoundary();
 
             if (boundaryPosition > -1) {
-                bos.write(buffer, bufferPosition, boundaryPosition - bufferPosition);
+                len = boundaryPosition - bufferPosition;
+                addFieldBytes(len);
+
+                bos.write(buffer, bufferPosition, len);
                 bufferPosition = boundaryPosition + boundary.length;
                 break;
             } else {
-                int len = Math.min(BUFFER_SIZE, bufferCount) - bufferPosition;
+                len = Math.min(BUFFER_SIZE, bufferCount) - bufferPosition;
+                addFieldBytes(len);
+
                 bos.write(buffer, bufferPosition, len);
                 bufferPosition = bufferPosition + len;
             }
-
-            fieldBytes += bos.size();
-            if (fieldBytes > MAX_FIELD_BYTES) {
-                throw new CmisInvalidArgumentException("Limit exceeded!");
-            }
         }
 
-        try {
-            value = bos.toString(charset);
-        } catch (UnsupportedEncodingException uee) {
-            throw new CmisInvalidArgumentException("Unknown endcoding!");
+        return bos.toByteArray();
+    }
+
+    private void addFieldBytes(int len) {
+        fieldBytes += len;
+        if (fieldBytes > MAX_FIELD_BYTES) {
+            throw new CmisInvalidArgumentException("Limit exceeded!");
         }
     }
 
-    public void readBodyAsStream() throws Exception {
+    private void readBodyAsStream() throws IOException {
         ThresholdOutputStream stream = new ThresholdOutputStream(tempDir, memoryThreshold,
maxContentSize);
 
         try {
@@ -345,7 +403,7 @@ public class MultipartParser {
 
             contentSize = BigInteger.valueOf(stream.getSize());
             contentStream = stream.getInputStream();
-        } catch (Exception e) {
+        } catch (IOException e) {
             // if something went wrong, make sure the temp file will
             // be deleted
             stream.destroy();
@@ -353,7 +411,7 @@ public class MultipartParser {
         }
     }
 
-    private void readBody() throws Exception {
+    private void readBody() throws IOException {
         String contentDisposition = headers.get("content-disposition");
 
         if (contentDisposition == null) {
@@ -362,11 +420,7 @@ public class MultipartParser {
 
         Map<String, String> params = new HashMap<String, String>();
         MimeHelper.decodeContentDisposition(contentDisposition, params);
-
-        name = params.get(MimeHelper.DISPOSITION_NAME);
-        filename = params.get(MimeHelper.DISPOSITION_FILENAME);
-        isContent = (filename != null);
-        contentType = headers.get("content-type");
+        boolean isContent = params.containsKey(MimeHelper.DISPOSITION_FILENAME);
 
         if (isContent) {
             if (hasContent) {
@@ -375,25 +429,33 @@ public class MultipartParser {
 
             hasContent = true;
 
+            filename = params.get(MimeHelper.DISPOSITION_FILENAME);
+
+            contentType = headers.get("content-type");
             if (contentType == null) {
                 contentType = Constants.MEDIATYPE_OCTETSTREAM;
             }
 
             readBodyAsStream();
         } else {
-            contentSize = BigInteger.ZERO;
-
-            String charset = null;
+            String name = params.get(MimeHelper.DISPOSITION_NAME);
+            byte[] rawValue = readBodyBytes();
 
-            if (contentType != null) {
-                charset = MimeHelper.getCharsetFromContentType(contentType);
+            if (CHARSET_FIELD.equalsIgnoreCase(name)) {
+                charset = new String(rawValue, "ISO-8859-1");
+                return;
             }
 
-            if (charset == null) {
-                charset = "ISO-8859-1";
+            String fieldContentType = headers.get("content-type");
+            if (fieldContentType != null) {
+                String fieldCharset = MimeHelper.getCharsetFromContentType(fieldContentType);
+                if (fieldCharset != null) {
+                    addField(name, new String(rawValue, fieldCharset));
+                    return;
+                }
             }
 
-            readBodyAsString(charset);
+            addRawField(name, rawValue);
         }
     }
 
@@ -441,7 +503,7 @@ public class MultipartParser {
         }
     }
 
-    public boolean readNext() throws Exception {
+    private boolean readNext() throws IOException {
         try {
             readHeaders();
 
@@ -454,7 +516,7 @@ public class MultipartParser {
             readBody();
 
             return true;
-        } catch (Exception e) {
+        } catch (IOException e) {
             if (contentStream != null) {
                 try {
                     contentStream.close();
@@ -469,16 +531,52 @@ public class MultipartParser {
         }
     }
 
-    public boolean isContent() {
-        return isContent;
-    }
+    public void parse() throws IOException {
+        try {
+
+            while (readNext()) {
+                // nothing to do here, just read
+            }
+
+            // apply charset
+            for (Map.Entry<String, byte[][]> e : rawFields.entrySet()) {
+
+                String[] otherValues = fields.get(e.getKey());
+                int index = (otherValues != null ? otherValues.length : 0);
+
+                String[] values = new String[e.getValue().length + index];
+
+                if (otherValues != null) {
+                    System.arraycopy(otherValues, 0, values, 0, otherValues.length);
+                }
+
+                for (byte[] rawValue : e.getValue()) {
+                    values[index++] = new String(rawValue, charset);
+                }
 
-    public String getName() {
-        return name;
+                fields.put(e.getKey(), values);
+            }
+        } catch (UnsupportedEncodingException uee) {
+            if (contentStream != null) {
+                try {
+                    contentStream.close();
+                } catch (Exception e2) {
+                    // ignore
+                }
+            }
+
+            skipEpilogue();
+
+            fields = null;
+
+            throw new CmisInvalidArgumentException("Encoding not supported!");
+        } finally {
+            rawFields = null;
+        }
     }
 
-    public String getValue() {
-        return value;
+    public boolean hasContent() {
+        return hasContent;
     }
 
     public String getFilename() {
@@ -497,6 +595,10 @@ public class MultipartParser {
         return contentStream;
     }
 
+    public Map<String, String[]> getFields() {
+        return fields;
+    }
+
     /**
      * Returns if the request is a multi-part request
      */

Modified: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/POSTHttpServletRequestWrapper.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/POSTHttpServletRequestWrapper.java?rev=1412477&r1=1412476&r2=1412477&view=diff
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/POSTHttpServletRequestWrapper.java
(original)
+++ chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/POSTHttpServletRequestWrapper.java
Thu Nov 22 09:49:12 2012
@@ -22,6 +22,7 @@ import java.io.File;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.math.BigInteger;
+import java.util.Map;
 
 import javax.servlet.http.HttpServletRequest;
 
@@ -45,16 +46,17 @@ public class POSTHttpServletRequestWrapp
 
         if (isMultipart) {
             MultipartParser parser = new MultipartParser(request, tempDir, memoryThreshold,
maxContentSize);
+            parser.parse();
 
-            while (parser.readNext()) {
-                if (parser.isContent()) {
-                    filename = parser.getFilename();
-                    contentType = parser.getContentType();
-                    size = parser.getSize();
-                    stream = parser.getStream();
-                } else {
-                    addParameter(parser.getName(), parser.getValue());
-                }
+            if (parser.hasContent()) {
+                filename = parser.getFilename();
+                contentType = parser.getContentType();
+                size = parser.getSize();
+                stream = parser.getStream();
+            }
+
+            for (Map.Entry<String, String[]> e : parser.getFields().entrySet()) {
+                addParameter(e.getKey(), e.getValue());
             }
 
             String filenameControl = HttpUtils.getStringParameter(this, Constants.CONTROL_FILENAME);

Modified: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/shared/QueryStringHttpServletRequestWrapper.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/shared/QueryStringHttpServletRequestWrapper.java?rev=1412477&r1=1412476&r2=1412477&view=diff
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/shared/QueryStringHttpServletRequestWrapper.java
(original)
+++ chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/shared/QueryStringHttpServletRequestWrapper.java
Thu Nov 22 09:49:12 2012
@@ -63,7 +63,7 @@ public class QueryStringHttpServletReque
                 addParameter(name, value);
             } else {
                 String name = URLDecoder.decode(nameValuePair, "UTF-8");
-                addParameter(name, null);
+                addParameter(name, (String) null);
             }
         }
     }
@@ -84,6 +84,22 @@ public class QueryStringHttpServletReque
         }
     }
 
+    /**
+     * Adds an array of values to a parameter.
+     */
+    protected void addParameter(String name, String[] additionalValues) {
+        String[] values = parameters.get(name);
+
+        if (values == null) {
+            parameters.put(name, additionalValues);
+        } else {
+            String[] newValues = new String[values.length + additionalValues.length];
+            System.arraycopy(values, 0, newValues, 0, values.length);
+            System.arraycopy(additionalValues, 0, newValues, values.length, additionalValues.length);
+            parameters.put(name, newValues);
+        }
+    }
+
     @Override
     public String getParameter(String name) {
         String[] values = parameters.get(name);

Modified: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/webapp/web/index.html
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/webapp/web/index.html?rev=1412477&r1=1412476&r2=1412477&view=diff
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/webapp/web/index.html
(original)
+++ chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/webapp/web/index.html
Thu Nov 22 09:49:12 2012
@@ -487,6 +487,7 @@ function showNewId(result) {
 <div id="folder" class="box">
 <h2>Create Folder</h2>
 <form id="createFolderForm" action="" method="POST" target="createResult">
+	<input name="_charset_" type="hidden" />
 	<input name="cmisaction" type="hidden" value="createFolder" />
 	<input name="token" type="hidden" value="" />
 	<table>
@@ -517,6 +518,7 @@ function showNewId(result) {
 
 
 <form id="createDocumentForm" action="" method="POST" target="createResult" enctype="multipart/form-data">
+	<input name="_charset_" type="hidden" />
 	<input name="cmisaction" type="hidden" value="createDocument" />
 	<input name="token" type="hidden" value="" />
 	<table>

Modified: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/test/java/org/apache/chemistry/opencmis/server/impl/MultipartParserTest.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/test/java/org/apache/chemistry/opencmis/server/impl/MultipartParserTest.java?rev=1412477&r1=1412476&r2=1412477&view=diff
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/test/java/org/apache/chemistry/opencmis/server/impl/MultipartParserTest.java
(original)
+++ chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/test/java/org/apache/chemistry/opencmis/server/impl/MultipartParserTest.java
Thu Nov 22 09:49:12 2012
@@ -20,6 +20,9 @@ package org.apache.chemistry.opencmis.se
 
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
 
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
@@ -56,7 +59,7 @@ public class MultipartParserTest {
                 + boundary + "\r\n"
                 + "Content-Disposition: form-data; name=\"content\"; filename=test-filename.txt\r\n"
                 + "Content-Type: text/plain\r\n" + "Content-Transfer-Encoding: binary\r\n"
+ "\r\n"
-                + new String(content) + "\r\n" + "--" + boundary + "--").getBytes();
+                + new String(content) + "\r\n" + "--" + boundary + "--").getBytes("ISO-8859-1");
 
         MultipartParser parser = prepareParser(boundary, formdata);
 
@@ -69,6 +72,41 @@ public class MultipartParserTest {
     }
 
     @Test
+    public void testMultipartParser2() throws Exception {
+        String boundary = "-----------------------------1294919323195";
+        byte[] content = "Test content!".getBytes("ISO-8859-1");
+        byte[] formdata = ("\r\n--"
+                + boundary
+                + "\r\nContent-Disposition: form-data; name=\"fileUploader\"; filename=\"ä.txt\"\r\nContent-Type:
text/plain\r\n\r\n"
+                + new String(content) + "\r\n--" + boundary
+                + "\r\nContent-Disposition: form-data; name=\"fileUploader-data\"\r\n\r\n\r\n--"
+ boundary
+                + "\r\nContent-Disposition: form-data; name=\"objectid\"\r\n\r\nf6bad54b4696bf2ac9249805\r\n--"
+                + boundary + "\r\nContent-Disposition: form-data; name=\"cmisaction\"\r\n\r\ncreateDocument\r\n--"
+                + boundary + "\r\nContent-Disposition: form-data; name=\"propertyId[0]\"\r\n\r\ncmis:name\r\n--"
+                + boundary + "\r\nContent-Disposition: form-data; name=\"propertyValue[0]\"\r\n\r\nä.txt\r\n--"
+                + boundary
+                + "\r\nContent-Disposition: form-data; name=\"propertyId[1]\"\r\n\r\ncmis:objectTypeId\r\n--"
+                + boundary + "\r\nContent-Disposition: form-data; name=\"propertyValue[1]\"\r\n\r\ncmis:document\r\n--"
+                + boundary
+                + "\r\nContent-Disposition: form-data; name=\"token\"\r\n\r\n855475d8a6169b5f57111f5921f56136\r\n--"
+                + boundary + "--").getBytes("ISO-8859-1");
+
+        MultipartParser parser = prepareParser(boundary, formdata);
+
+        Map<String, String> values = new HashMap<String, String>();
+        values.put("fileUploader-data", "");
+        values.put("objectid", "f6bad54b4696bf2ac9249805");
+        values.put("cmisaction", "createDocument");
+        values.put("propertyId[0]", "cmis:name");
+        values.put("propertyValue[0]", "ä.txt");
+        values.put("propertyId[1]", "cmis:objectTypeId");
+        values.put("propertyValue[1]", "cmis:document");
+        values.put("token", "855475d8a6169b5f57111f5921f56136");
+
+        assertMultipartBasics(parser, 9, values, true, "ä.txt", "text/plain", content);
+    }
+
+    @Test
     public void testNoPreamble() throws Exception {
         String boundary = "BoUnDaRy--987654320";
         byte[] formdata = ("--" + boundary + "\r\n" + "Content-Disposition: form-data; name=\"field1\"\r\n"
+ "\r\n"
@@ -126,7 +164,7 @@ public class MultipartParserTest {
     @Test
     public void testContentOnly() throws Exception {
         String boundary = "ABCD-1234";
-        byte[] content = "abcŠšŸ".getBytes();
+        byte[] content = "abcäöü".getBytes();
         byte[] formdata = ("\r\n--" + boundary + "\r\n"
                 + "Content-Disposition: form-data; name=\"content\"; filename=\"a new file\"\r\n"
                 + "Content-Type: application/something\r\n" + "Content-Transfer-Encoding:
binary\r\n" + "\r\n"
@@ -193,7 +231,36 @@ public class MultipartParserTest {
     }
 
     @Test
-    public void testCharsets() throws Exception {
+    public void testCharsetsInContentType() throws Exception {
+        String[] charsets = new String[] { "utf-8", "iso-8859-1", "utf-16" };
+
+        String boundary = "ldchqeriuvoqeirbvxipu  eckqnqklwjcnqwklcqwncqewlciqecqwecevoipooei
cqwcoewcq";
+        StringBuilder value = new StringBuilder();
+
+        for (int i = 1; i < 255; i++) {
+            value.append((char) i);
+        }
+
+        Map<String, String> values = new HashMap<String, String>();
+        values.put("field1", value.toString());
+
+        for (String charset : charsets) {
+            ByteArrayOutputStream bos = new ByteArrayOutputStream();
+            bos.write(("\r\n--" + boundary + "\r\n").getBytes("ISO-8859-1"));
+            bos.write(("Content-Disposition: form-data; name=\"field1\"\r\n").getBytes("ISO-8859-1"));
+            bos.write(("Content-Type: text/plain; charset=" + charset + "\r\n\r\n").getBytes("ISO-8859-1"));
+            bos.write(value.toString().getBytes(charset));
+            bos.write(("\r\n--" + boundary + "--\r\n").getBytes("ISO-8859-1"));
+            bos.write(("This is an epilogue.").getBytes("ISO-8859-1"));
+
+            MultipartParser parser = prepareParser(boundary, bos.toByteArray());
+
+            assertMultipartBasics(parser, 1, values, false, null, null, null);
+        }
+    }
+
+    @Test
+    public void testCharsetsAsExtraField() throws Exception {
         String[] charsets = new String[] { "utf-8", "iso-8859-1", "utf-16" };
 
         String boundary = "ldchqeriuvoqeirbvxipu  eckqnqklwjcnqwklcqwncqewlciqecqwecevoipooei
cqwcoewcq";
@@ -208,10 +275,14 @@ public class MultipartParserTest {
 
         for (String charset : charsets) {
             ByteArrayOutputStream bos = new ByteArrayOutputStream();
-            bos.write(("\r\n--" + boundary + "\r\n" + "Content-Disposition: form-data; name=\"field1\"\r\n"
-                    + "Content-Type: text/plain; charset=" + charset + "\r\n" + "\r\n").getBytes());
+            bos.write(("\r\n--" + boundary + "\r\n").getBytes("ISO-8859-1"));
+            bos.write(("Content-Disposition: form-data; name=\"field1\"\r\n\r\n").getBytes("ISO-8859-1"));
             bos.write(value.toString().getBytes(charset));
-            bos.write(("\r\n" + "--" + boundary + "--This is an epilogue.").getBytes());
+            bos.write(("\r\n--" + boundary + "\r\n").getBytes("ISO-8859-1"));
+            bos.write(("Content-Disposition: form-data; name=\"_charset_\"\r\n\r\n").getBytes("ISO-8859-1"));
+            bos.write(charset.getBytes("ISO-8859-1"));
+            bos.write(("\r\n--" + boundary + "--\r\n").getBytes("ISO-8859-1"));
+            bos.write(("This is an epilogue.").getBytes("ISO-8859-1"));
 
             MultipartParser parser = prepareParser(boundary, bos.toByteArray());
 
@@ -219,6 +290,45 @@ public class MultipartParserTest {
         }
     }
 
+    @Test
+    public void testCharsetsMixed() throws Exception {
+        String[] charsets = new String[] { "utf-8", "iso-8859-1", "utf-16" };
+
+        String boundary = "ldchqeriuvoqeirbvxipu  eckqnqklwjcnqwklcqwncqewlciqecqwecevoipooei
cqwcoewcq";
+        StringBuilder value = new StringBuilder();
+
+        for (int i = 1; i < 255; i++) {
+            value.append((char) i);
+        }
+
+        Map<String, String> values = new HashMap<String, String>();
+        values.put("field1", value.toString());
+        values.put("field2", value.toString());
+        values.put("field3", value.toString());
+
+        for (String charset : charsets) {
+            ByteArrayOutputStream bos = new ByteArrayOutputStream();
+            bos.write(("\r\n--" + boundary + "\r\n").getBytes("ISO-8859-1"));
+            bos.write(("Content-Disposition: form-data; name=\"field1\"\r\n").getBytes("ISO-8859-1"));
+            bos.write(("Content-Type: text/plain; charset=\"utf-8\"\r\n\r\n").getBytes("ISO-8859-1"));
+            bos.write(value.toString().getBytes("utf-8"));
+            bos.write(("\r\n--" + boundary + "\r\n").getBytes("ISO-8859-1"));
+            bos.write(("Content-Disposition: form-data; name=\"field2\"\r\n\r\n").getBytes("ISO-8859-1"));
+            bos.write(value.toString().getBytes(charset));
+            bos.write(("\r\n--" + boundary + "\r\n").getBytes("ISO-8859-1"));
+            bos.write(("Content-Disposition: form-data; name=\"_charset_\"\r\n\r\n").getBytes("ISO-8859-1"));
+            bos.write(charset.getBytes("ISO-8859-1"));
+            bos.write(("\r\n--" + boundary + "\r\n").getBytes("ISO-8859-1"));
+            bos.write(("Content-Disposition: form-data; name=\"field3\"\r\n\r\n").getBytes("ISO-8859-1"));
+            bos.write(value.toString().getBytes(charset));
+            bos.write(("\r\n--" + boundary + "--\r\n").getBytes("ISO-8859-1"));
+
+            MultipartParser parser = prepareParser(boundary, bos.toByteArray());
+
+            assertMultipartBasics(parser, 3, values, false, null, null, null);
+        }
+    }
+
     @Test(expected = CmisInvalidArgumentException.class)
     public void testNoBoundary() throws Exception {
         String boundary = "";
@@ -243,7 +353,7 @@ public class MultipartParserTest {
     @Test(expected = CmisInvalidArgumentException.class)
     public void testTwoContentParts() throws Exception {
         String boundary = "-?-";
-        byte[] content = "abcŠšŸ".getBytes();
+        byte[] content = "abcäöü".getBytes();
         byte[] formdata = ("\r\n--" + boundary + "\r\n"
                 + "Content-Disposition: form-data; name=\"content1\"; filename=\"file1\"\r\n"
                 + "Content-Type: application/something\r\n" + "Content-Transfer-Encoding:
binary\r\n" + "\r\n"
@@ -285,31 +395,36 @@ public class MultipartParserTest {
 
     private void assertMultipartBasics(MultipartParser parser, int count, Map<String,
String> values,
             boolean hasContent, String filename, String contentType, byte[] content) throws
Exception {
-        Map<String, String> parameters = new HashMap<String, String>();
-
         int counter = 0;
-        while (parser.readNext()) {
+
+        parser.parse();
+
+        if (parser.hasContent()) {
             counter++;
+            assertTrue(hasContent);
+            assertEquals(filename, parser.getFilename());
+            assertEquals(contentType, parser.getContentType());
+            assertEquals(content.length, parser.getSize().intValue());
+            assertArrayEquals(content, readBytesFromStream(parser.getStream()));
+        } else {
+            assertFalse(hasContent);
+        }
+
+        Map<String, String[]> fields = parser.getFields();
+        for (Map.Entry<String, String[]> e : fields.entrySet()) {
+            assertNotNull(e.getValue());
+            assertEquals(1, e.getValue().length);
 
-            if (parser.isContent()) {
-                assertEquals(filename, parser.getFilename());
-                assertEquals(contentType, parser.getContentType());
-                assertEquals(content.length, parser.getSize().intValue());
-                assertArrayEquals(content, readBytesFromStream(parser.getStream()));
-            } else {
-                parameters.put(parser.getName(), parser.getValue());
-            }
-        }
+            String fieldName = e.getKey();
+            String fieldValue = e.getValue()[0];
 
-        assertEquals(count, counter);
-        assertEquals(counter - (hasContent ? 1 : 0), parameters.size());
+            assertEquals(fieldValue, values.get(fieldName));
 
-        if (values != null) {
-            assertEquals(values.size(), parameters.size());
-            for (Map.Entry<String, String> e : values.entrySet()) {
-                assertEquals(e.getValue(), parameters.get(e.getKey()));
-            }
+            counter++;
         }
+
+        assertEquals(count, counter);
+        assertEquals(counter - (hasContent ? 1 : 0), fields.size());
     }
 
     private static class FakeServletInputStream extends ServletInputStream {



Mime
View raw message