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