You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2012/11/03 19:55:00 UTC

svn commit: r1405399 - in /tomcat/trunk/java/org/apache/tomcat/util/http/parser: HttpParser2.java MediaType.java

Author: markt
Date: Sat Nov  3 18:55:00 2012
New Revision: 1405399

URL: http://svn.apache.org/viewvc?rev=1405399&view=rev
Log:
First cut at a replacement for HttpParser. Includes a work-around for the Adode Reader 9 on IE bug. Currently untested.

Added:
    tomcat/trunk/java/org/apache/tomcat/util/http/parser/MediaType.java   (with props)
Modified:
    tomcat/trunk/java/org/apache/tomcat/util/http/parser/HttpParser2.java

Modified: tomcat/trunk/java/org/apache/tomcat/util/http/parser/HttpParser2.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/http/parser/HttpParser2.java?rev=1405399&r1=1405398&r2=1405399&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/http/parser/HttpParser2.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/http/parser/HttpParser2.java Sat Nov  3 18:55:00 2012
@@ -36,13 +36,11 @@ import java.util.Map;
  *
  * Provides parsing of the following HTTP header values as per RFC 2616:
  * - Authorization for DIGEST authentication
+ * - MediaType (used for Content-Type header)
  *
  * Support for additional headers will be provided as required.
  *
- * TODO: Check the performance of this parser against the current Digest header
- *       parsing code.
- *
- * TODO: Add support for parsing content-type and replace HttpParser
+ * TODO: Replace HttpParser
  */
 public class HttpParser2 {
 
@@ -112,7 +110,7 @@ public class HttpParser2 {
 
         Map<String,String> result = new HashMap<>();
 
-        if (!skipConstant(input, "Digest", false)) {
+        if (skipConstant(input, "Digest") != SkipConstantResult.FOUND) {
             return null;
         }
         skipLws(input);
@@ -123,7 +121,7 @@ public class HttpParser2 {
         }
         while (!field.equals("")) {
             skipLws(input);
-            if (!skipConstant(input, "=", false)) {
+            if (skipConstant(input, "=") != SkipConstantResult.FOUND) {
                 return null;
             }
             skipLws(input);
@@ -140,11 +138,11 @@ public class HttpParser2 {
                     break;
                 case 1:
                     // FIELD_TYPE_QUOTED_STRING
-                    value = readQuotedString(input);
+                    value = readQuotedString(input, false);
                     break;
                 case 2:
                     // FIELD_TYPE_TOKEN_OR_QUOTED_STRING
-                    value = readTokenOrQuotedString(input);
+                    value = readTokenOrQuotedString(input, false);
                     break;
                 case 3:
                     // FIELD_TYPE_LHEX
@@ -166,7 +164,7 @@ public class HttpParser2 {
             result.put(field, value);
 
             skipLws(input);
-            if (!skipConstant(input, ",", true)) {
+            if (skipConstant(input, ",") == SkipConstantResult.NOT_FOUND) {
                 return null;
             }
             skipLws(input);
@@ -179,24 +177,90 @@ public class HttpParser2 {
         return result;
     }
 
-    /**
-     * @return  <code>true</code> if the constant is found or if no data is
-     *          present and EOF is allowed otherwise returns <code>false</code>
-     */
-    private static boolean skipConstant(StringReader input, String constant,
-            boolean eofOk) throws IOException {
+    public static MediaType parseMediaType(StringReader input)
+            throws IOException {
+
+        // Type (required)
+        String type = readToken(input);
+        if (type == null || type.length() == 0) {
+            return null;
+        }
+
+        skipLws(input);
+        if (skipConstant(input, "/") == SkipConstantResult.NOT_FOUND) {
+            return null;
+        }
+        skipLws(input);
+
+        // Subtype (required)
+        String subtype = readToken(input);
+        if (subtype == null || subtype.length() == 0) {
+            return null;
+        }
+
+        skipLws(input);
+
+        Map<String,String> parameters = new HashMap<>();
+
+        SkipConstantResult lookForSemiColon = skipConstant(input, ";");
+        if (lookForSemiColon == SkipConstantResult.NOT_FOUND) {
+            return null;
+        }
+        while (lookForSemiColon == SkipConstantResult.FOUND) {
+            skipLws(input);
+            String attribute = readToken(input);
+            skipLws(input);
+
+            if (skipConstant(input, "=") != SkipConstantResult.FOUND) {
+                return null;
+            }
+
+            skipLws(input);
+            String value = readTokenOrQuotedString(input, true);
+            skipLws(input);
+
+            parameters.put(attribute.toLowerCase(), value);
+
+            lookForSemiColon = skipConstant(input, ";");
+            if (lookForSemiColon == SkipConstantResult.NOT_FOUND) {
+                return null;
+            }
+        }
+
+        String charset = parameters.remove("charset");
+        StringBuilder noCharSet = new StringBuilder();
+        noCharSet.append(type);
+        noCharSet.append('/');
+        noCharSet.append(subtype);
+        for (Map.Entry<String, String> entry : parameters.entrySet()) {
+            noCharSet.append(';');
+            // Workaround for Adobe Read 9 plug-in on IE bug
+            // Can be removed after 26 June 2013 (EOL of Reader 9)
+            // See BZ 53814
+            noCharSet.append(' ');
+            noCharSet.append(entry.getKey());
+            noCharSet.append('=');
+            noCharSet.append(entry.getValue());
+        }
+
+        return new MediaType(noCharSet.toString(), charset);
+    }
+
+    private static SkipConstantResult skipConstant(StringReader input,
+            String constant) throws IOException {
         int len = constant.length();
 
         for (int i = 0; i < len; i++) {
             int c = input.read();
-            if (i == 0 && c == -1 && eofOk) {
-                return true;
+            if (i == 0 && c == -1) {
+                return SkipConstantResult.EOF;
             }
             if (c != constant.charAt(i)) {
-                return false;
+                input.skip(-(i + 1));
+                return SkipConstantResult.NOT_FOUND;
             }
         }
-        return true;
+        return SkipConstantResult.FOUND;
     }
 
     private static void skipLws(StringReader input) throws IOException {
@@ -237,8 +301,8 @@ public class HttpParser2 {
      *         quoted string was found or null if the end of data was reached
      *         before the quoted string was terminated
      */
-    private static String readQuotedString(StringReader input)
-            throws IOException {
+    private static String readQuotedString(StringReader input,
+            boolean returnQuoted) throws IOException {
 
         int c = input.read();
         if (c != '"') {
@@ -246,30 +310,38 @@ public class HttpParser2 {
         }
 
         StringBuilder result = new StringBuilder();
-
+        if (returnQuoted) {
+            result.append('\"');
+        }
         c = input.read();
         while (c != '"') {
             if (c == -1) {
                 return null;
             } else if (c == '\\') {
                 c = input.read();
+                if (returnQuoted) {
+                    result.append('\\');
+                }
                 result.append(c);
             } else {
                 result.append((char) c);
             }
             c = input.read();
         }
+        if (returnQuoted) {
+            result.append('\"');
+        }
 
         return result.toString();
     }
 
-    private static String readTokenOrQuotedString(StringReader input)
-            throws IOException {
+    private static String readTokenOrQuotedString(StringReader input,
+            boolean returnQuoted) throws IOException {
         int c = input.read();
         input.skip(-1);
 
         if (c == '"') {
-            return readQuotedString(input);
+            return readQuotedString(input, returnQuoted);
         } else {
             return readToken(input);
         }
@@ -303,10 +375,20 @@ public class HttpParser2 {
     private static String readQuotedLhex(StringReader input)
             throws IOException {
 
-        skipConstant(input, "\"", false);
+        if (skipConstant(input, "\"") != SkipConstantResult.FOUND) {
+            return null;
+        }
         String result = readLhex(input);
-        skipConstant(input, "\"", false);
+        if (skipConstant(input, "\"") == SkipConstantResult.NOT_FOUND) {
+            return null;
+        }
 
         return result;
     }
+
+    private static enum SkipConstantResult {
+        FOUND,
+        NOT_FOUND,
+        EOF
+    }
 }

Added: tomcat/trunk/java/org/apache/tomcat/util/http/parser/MediaType.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/http/parser/MediaType.java?rev=1405399&view=auto
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/http/parser/MediaType.java (added)
+++ tomcat/trunk/java/org/apache/tomcat/util/http/parser/MediaType.java Sat Nov  3 18:55:00 2012
@@ -0,0 +1,36 @@
+/*
+ *  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.tomcat.util.http.parser;
+
+public class MediaType {
+
+    private final String noCharset;
+    private final String charset;
+
+    protected MediaType(String noCharset, String charset) {
+        this.noCharset = noCharset;
+        this.charset = charset;
+    }
+
+    public String toStringNoCharset() {
+        return noCharset;
+    }
+
+    public String getCharSet() {
+        return charset;
+    }
+}

Propchange: tomcat/trunk/java/org/apache/tomcat/util/http/parser/MediaType.java
------------------------------------------------------------------------------
    svn:eol-style = native



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org