chemistry-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From f...@apache.org
Subject svn commit: r1628709 - 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/ test/java/org/apac...
Date Wed, 01 Oct 2014 14:14:13 GMT
Author: fmui
Date: Wed Oct  1 14:14:13 2014
New Revision: 1628709

URL: http://svn.apache.org/r1628709
Log:
simple reimplementation of the form data parser including _charset_ field support

Modified:
    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/test/java/org/apache/chemistry/opencmis/server/impl/CheckServletInputStreamTest.java
    chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/test/java/org/apache/chemistry/opencmis/server/impl/HttpRequestMockHelper.java
    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/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=1628709&r1=1628708&r2=1628709&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
Wed Oct  1 14:14:13 2014
@@ -20,12 +20,16 @@ package org.apache.chemistry.opencmis.se
 
 import java.io.IOException;
 import java.io.InputStream;
-import java.io.InputStreamReader;
 import java.math.BigInteger;
+import java.net.URLDecoder;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 
 import javax.servlet.http.HttpServletRequest;
 
+import org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException;
 import org.apache.chemistry.opencmis.commons.impl.Constants;
 import org.apache.chemistry.opencmis.commons.impl.IOUtils;
 import org.apache.chemistry.opencmis.server.shared.HttpUtils;
@@ -33,19 +37,24 @@ import org.apache.chemistry.opencmis.ser
 import org.apache.chemistry.opencmis.server.shared.ThresholdOutputStreamFactory;
 
 public final class POSTHttpServletRequestWrapper extends QueryStringHttpServletRequestWrapper
{
+
+    public static final String FORM_URLENCODED = "application/x-www-form-urlencoded";
+    private static final int MAX_CONTENT_BYTES = 10 * 1024 * 1024;
+    private static final int BUFFER_SIZE = 64 * 1024;
+    private static final String CHARSET_FIELD = "_charset_";
+
     private String filename;
     private String contentType;
     private BigInteger size;
     private InputStream stream;
 
+    @SuppressWarnings("unchecked")
     public POSTHttpServletRequestWrapper(HttpServletRequest request, ThresholdOutputStreamFactory
streamFactory)
             throws IOException {
         super(request);
 
-        // check multipart
-        boolean isMultipart = MultipartParser.isMultipartContent(request);
-
-        if (isMultipart) {
+        if (MultipartParser.isMultipartContent(request)) {
+            // multipart processing
             MultipartParser parser = new MultipartParser(request, streamFactory);
             parser.parse();
 
@@ -69,18 +78,14 @@ public final class POSTHttpServletReques
             if ((contentTypeControl != null) && (contentTypeControl.trim().length()
> 0)) {
                 contentType = contentTypeControl;
             }
-        } else {
+        } else if (isFormUrlencodedContent(request)) {
             // form data processing
-            StringBuilder sb = new StringBuilder();
-
-            InputStreamReader sr = new InputStreamReader(request.getInputStream(), IOUtils.UTF8);
-            char[] buffer = new char[4096];
-            int c = 0;
-            while ((c = sr.read(buffer)) > -1) {
-                sb.append(buffer, 0, c);
+            if (!parseFormUrlEncodedData(request)) {
+                parameters.putAll(request.getParameterMap());
             }
-
-            parseFormData(sb.toString());
+        } else {
+            // spec incompliant form encoding
+            throw new CmisInvalidArgumentException("Invalid form encoding!");
         }
     }
 
@@ -99,4 +104,167 @@ public final class POSTHttpServletReques
     public InputStream getStream() {
         return stream;
     }
+
+    /**
+     * Parses a form data request
+     * 
+     * @param request
+     *            the request
+     * @return {@code true} if the body contained data, {@code false} otherwise
+     */
+    protected boolean parseFormUrlEncodedData(HttpServletRequest request) throws IOException
{
+        byte data[] = new byte[BUFFER_SIZE];
+        int dataPos = 0;
+
+        InputStream stream = request.getInputStream();
+        int b;
+        byte buffer[] = new byte[BUFFER_SIZE];
+
+        // read stream
+        while ((b = stream.read(buffer)) != -1) {
+            if (dataPos + b > MAX_CONTENT_BYTES) {
+                throw new CmisInvalidArgumentException("Limit exceeded!");
+            }
+
+            if (data.length - dataPos < b) {
+                // expand buffer
+                int newSize = ((data.length + b) * 2 < MAX_CONTENT_BYTES ? (data.length
+ b * 2) : MAX_CONTENT_BYTES);
+                byte[] newbuf = new byte[newSize];
+                System.arraycopy(data, 0, newbuf, 0, dataPos);
+                data = newbuf;
+            }
+
+            System.arraycopy(buffer, 0, data, dataPos, b);
+            dataPos += b;
+        }
+
+        if (dataPos == 0) {
+            // empty stream
+            return false;
+        }
+
+        // parse parameters
+        boolean parseName = true;
+        boolean parseCharset = false;
+        int startPos = 0;
+
+        List<String[]> rawParameters = new ArrayList<String[]>();
+        String rawName = null;
+        String rawValue = null;
+
+        String charset = null;
+
+        for (int i = 0; i < dataPos; i++) {
+            switch (data[i]) {
+            case '=':
+                if (startPos < i) {
+                    rawName = new String(data, startPos, i - startPos, IOUtils.ISO_8859_1);
+                    if (CHARSET_FIELD.equalsIgnoreCase(rawName)) {
+                        parseCharset = true;
+                    }
+                }
+
+                parseName = false;
+                startPos = i + 1;
+                break;
+
+            case '&':
+                if (parseName) {
+                    if (startPos < i) {
+                        rawName = new String(data, startPos, i - startPos, IOUtils.ISO_8859_1);
+                        rawParameters.add(new String[] { rawName, null });
+                    }
+                } else {
+                    if (rawName != null) {
+                        rawValue = new String(data, startPos, i - startPos, IOUtils.ISO_8859_1);
+                        rawParameters.add(new String[] { rawName, rawValue });
+                        if (parseCharset) {
+                            charset = rawValue;
+                        }
+                    }
+                }
+
+                rawName = null;
+                rawValue = null;
+
+                parseName = true;
+                parseCharset = false;
+                startPos = i + 1;
+                break;
+
+            default:
+                break;
+            }
+        }
+
+        if (startPos < dataPos) {
+            // there is a final parameter after the last '&'
+            if (parseName) {
+                rawName = new String(data, startPos, dataPos - startPos, IOUtils.ISO_8859_1);
+                rawParameters.add(new String[] { rawName, null });
+            } else {
+                if (rawName != null) {
+                    rawValue = new String(data, startPos, dataPos - startPos, IOUtils.ISO_8859_1);
+                    rawParameters.add(new String[] { rawName, rawValue });
+                    if (parseCharset) {
+                        charset = rawValue;
+                    }
+                }
+            }
+        } else if (!parseName) {
+            // the stream ended with '='
+            rawParameters.add(new String[] { rawName, "" });
+        }
+
+        data = null;
+
+        // find charset
+        if (charset == null) {
+            // check charset in content type
+            String contentType = request.getContentType();
+            if (contentType != null) {
+                String[] parts = contentType.split(";");
+                for (int i = 1; i < parts.length; i++) {
+                    String part = parts[i].trim().toLowerCase(Locale.ENGLISH);
+                    if (part.startsWith("charset")) {
+                        int x = part.indexOf('=');
+                        charset = part.substring(x + 1).trim();
+                        break;
+                    }
+                }
+            }
+        }
+
+        if (charset == null) {
+            // set default charset
+            charset = IOUtils.UTF8;
+        }
+
+        // decode parameters
+        for (String[] rawParameter : rawParameters) {
+            String name = URLDecoder.decode(rawParameter[0], charset);
+
+            String value = null;
+            if (rawParameter[1] != null) {
+                value = URLDecoder.decode(rawParameter[1], charset);
+            }
+
+            addParameter(name, value);
+        }
+
+        return true;
+    }
+
+    /**
+     * Returns if the request is a form-urlencoded request.
+     */
+    public static final boolean isFormUrlencodedContent(HttpServletRequest request) {
+        String contentType = request.getContentType();
+
+        if (contentType != null && contentType.toLowerCase(Locale.ENGLISH).startsWith(FORM_URLENCODED))
{
+            return true;
+        }
+
+        return false;
+    }
 }

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=1628709&r1=1628708&r2=1628709&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
Wed Oct  1 14:14:13 2014
@@ -35,7 +35,7 @@ import org.apache.chemistry.opencmis.com
  */
 public class QueryStringHttpServletRequestWrapper extends HttpServletRequestWrapper {
 
-    private Map<String, String[]> parameters;
+    protected Map<String, String[]> parameters;
 
     public QueryStringHttpServletRequestWrapper(HttpServletRequest request) throws IOException
{
         super(request);

Modified: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/test/java/org/apache/chemistry/opencmis/server/impl/CheckServletInputStreamTest.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/CheckServletInputStreamTest.java?rev=1628709&r1=1628708&r2=1628709&view=diff
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/test/java/org/apache/chemistry/opencmis/server/impl/CheckServletInputStreamTest.java
(original)
+++ chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/test/java/org/apache/chemistry/opencmis/server/impl/CheckServletInputStreamTest.java
Wed Oct  1 14:14:13 2014
@@ -106,8 +106,8 @@ public class CheckServletInputStreamTest
         ByteArrayInputStream originStream = new ByteArrayInputStream(byteBuffer);
 
         try {
-            ProtectionRequestWrapper prw = new ProtectionRequestWrapper(HttpRequestMockHelper.createRequest(BOUNDARY,
-                    originStream), max);
+            ProtectionRequestWrapper prw = new ProtectionRequestWrapper(HttpRequestMockHelper.createMultipartRequest(
+                    BOUNDARY, originStream), max);
             InputStream stream = prw.getInputStream();
 
             int countS = 0;
@@ -143,8 +143,8 @@ public class CheckServletInputStreamTest
         originStream = new ByteArrayInputStream(byteBuffer);
 
         try {
-            ProtectionRequestWrapper prw = new ProtectionRequestWrapper(HttpRequestMockHelper.createRequest(BOUNDARY,
-                    originStream), max);
+            ProtectionRequestWrapper prw = new ProtectionRequestWrapper(HttpRequestMockHelper.createMultipartRequest(
+                    BOUNDARY, originStream), max);
             InputStream stream = prw.getInputStream();
 
             int countS = 0;

Modified: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/test/java/org/apache/chemistry/opencmis/server/impl/HttpRequestMockHelper.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/HttpRequestMockHelper.java?rev=1628709&r1=1628708&r2=1628709&view=diff
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/test/java/org/apache/chemistry/opencmis/server/impl/HttpRequestMockHelper.java
(original)
+++ chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/test/java/org/apache/chemistry/opencmis/server/impl/HttpRequestMockHelper.java
Wed Oct  1 14:14:13 2014
@@ -29,7 +29,7 @@ import org.mockito.Mockito;
 
 public class HttpRequestMockHelper {
 
-    public static HttpServletRequest createRequest(String boundary, byte[] content) throws
IOException {
+    public static HttpServletRequest createMultipartRequest(String boundary, byte[] content)
throws IOException {
         FakeServletInputStream stream = new FakeServletInputStream(content);
 
         HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
@@ -39,7 +39,8 @@ public class HttpRequestMockHelper {
         return request;
     }
 
-    public static HttpServletRequest createRequest(String boundary, InputStream inputStream)
throws IOException {
+    public static HttpServletRequest createMultipartRequest(String boundary, InputStream
inputStream)
+            throws IOException {
         FakeServletInputStream stream = new FakeServletInputStream(inputStream);
 
         HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
@@ -49,6 +50,17 @@ public class HttpRequestMockHelper {
         return request;
     }
 
+    public static HttpServletRequest createFormRequest(String encoding, byte[] content) throws
IOException {
+        FakeServletInputStream stream = new FakeServletInputStream(content);
+
+        HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
+        Mockito.when(request.getContentType()).thenReturn(
+                "application/x-www-form-urlencoded" + (encoding == null ? "" : ";charset="
+ encoding));
+        Mockito.when(request.getInputStream()).thenReturn(stream);
+
+        return request;
+    }
+
     private static class FakeServletInputStream extends ServletInputStream {
 
         private InputStream stream;

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=1628709&r1=1628708&r2=1628709&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
Wed Oct  1 14:14:13 2014
@@ -408,7 +408,7 @@ public class MultipartParserTest {
     // ---- helpers ----
 
     private MultipartParser prepareParser(String boundary, byte[] content) throws Exception
{
-        HttpServletRequest request = HttpRequestMockHelper.createRequest(boundary, content);
+        HttpServletRequest request = HttpRequestMockHelper.createMultipartRequest(boundary,
content);
 
         ThresholdOutputStreamFactory streamFactory = ThresholdOutputStreamFactory.newInstance(null,
THRESHOLD,
                 MAX_SIZE, false);



Mime
View raw message