Author: markt
Date: Fri Oct 10 14:28:52 2014
New Revision: 1630910
URL: http://svn.apache.org/r1630910
Log:
Allow HTTP headers to be sent using encodings other than ISO-8859-1
Modified:
tomcat/trunk/java/org/apache/catalina/connector/Response.java
tomcat/trunk/java/org/apache/coyote/Response.java
tomcat/trunk/java/org/apache/coyote/ajp/AjpMessage.java
tomcat/trunk/java/org/apache/coyote/http11/AbstractOutputBuffer.java
tomcat/trunk/test/org/apache/coyote/ajp/TesterAjpMessage.java
Modified: tomcat/trunk/java/org/apache/catalina/connector/Response.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/connector/Response.java?rev=1630910&r1=1630909&r2=1630910&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/connector/Response.java (original)
+++ tomcat/trunk/java/org/apache/catalina/connector/Response.java Fri Oct 10
14:28:52 2014
@@ -19,6 +19,7 @@ package org.apache.catalina.connector;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.MalformedURLException;
+import java.nio.charset.Charset;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
@@ -1000,6 +1001,11 @@ public class Response
*/
@Override
public void addHeader(String name, String value) {
+ addHeader(name, value, null);
+ }
+
+
+ private void addHeader(String name, String value, Charset charset) {
if (name == null || name.length() == 0 || value == null) {
return;
@@ -1020,7 +1026,7 @@ public class Response
return;
}
- coyoteResponse.addHeader(name, value);
+ coyoteResponse.addHeader(name, value, charset);
}
Modified: tomcat/trunk/java/org/apache/coyote/Response.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/Response.java?rev=1630910&r1=1630909&r2=1630910&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/Response.java (original)
+++ tomcat/trunk/java/org/apache/coyote/Response.java Fri Oct 10 14:28:52 2014
@@ -18,12 +18,14 @@ package org.apache.coyote;
import java.io.IOException;
import java.io.StringReader;
+import java.nio.charset.Charset;
import java.util.Locale;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.servlet.WriteListener;
import org.apache.tomcat.util.buf.ByteChunk;
+import org.apache.tomcat.util.buf.MessageBytes;
import org.apache.tomcat.util.http.MimeHeaders;
import org.apache.tomcat.util.http.parser.MediaType;
import org.apache.tomcat.util.res.StringManager;
@@ -297,12 +299,21 @@ public final class Response {
public void addHeader(String name, String value) {
+ addHeader(name, value, null);
+ }
+
+
+ public void addHeader(String name, String value, Charset charset) {
char cc=name.charAt(0);
if( cc=='C' || cc=='c' ) {
if( checkSpecialHeader(name, value) )
return;
}
- headers.addValue(name).setString( value );
+ MessageBytes mb = headers.addValue(name);
+ if (charset != null) {
+ mb.getByteChunk().setCharset(charset);
+ }
+ mb.setString(value);
}
Modified: tomcat/trunk/java/org/apache/coyote/ajp/AjpMessage.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/ajp/AjpMessage.java?rev=1630910&r1=1630909&r2=1630910&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/ajp/AjpMessage.java (original)
+++ tomcat/trunk/java/org/apache/coyote/ajp/AjpMessage.java Fri Oct 10 14:28:52
2014
@@ -20,7 +20,6 @@ package org.apache.coyote.ajp;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.util.buf.ByteChunk;
-import org.apache.tomcat.util.buf.CharChunk;
import org.apache.tomcat.util.buf.HexUtils;
import org.apache.tomcat.util.buf.MessageBytes;
import org.apache.tomcat.util.res.StringManager;
@@ -159,15 +158,21 @@ public class AjpMessage {
appendByte(0);
return;
}
- if (mb.getType() == MessageBytes.T_BYTES) {
+ if (mb.getType() != MessageBytes.T_BYTES) {
+ mb.toBytes();
ByteChunk bc = mb.getByteChunk();
- appendByteChunk(bc);
- } else if (mb.getType() == MessageBytes.T_CHARS) {
- CharChunk cc = mb.getCharChunk();
- appendCharChunk(cc);
- } else {
- appendString(mb.toString());
+ // Need to filter out CTLs excluding TAB. ISO-8859-1 and UTF-8
+ // values will be OK. Strings using other encodings may be
+ // corrupted.
+ byte[] buffer = bc.getBuffer();
+ for (int i = bc.getOffset(); i < bc.getLength(); i++) {
+ if (((buffer[i] <= 31) && (buffer[i] != 9)) ||
+ buffer[i] == 127 || buffer[i] > 255) {
+ buffer[i] = ' ';
+ }
+ }
}
+ appendByteChunk(mb.getByteChunk());
}
@@ -188,70 +193,6 @@ public class AjpMessage {
/**
- * Write a CharChunk out at the current write position.
- * A null CharChunk is encoded as a string with length 0.
- */
- public void appendCharChunk(CharChunk cc) {
- if (cc == null) {
- log.error(sm.getString("ajpmessage.null"),
- new NullPointerException());
- appendInt(0);
- appendByte(0);
- return;
- }
- int start = cc.getStart();
- int end = cc.getEnd();
- appendInt(end - start);
- char[] cbuf = cc.getBuffer();
- for (int i = start; i < end; i++) {
- char c = cbuf[i];
- // Note: This is clearly incorrect for many strings,
- // but is the only consistent approach within the current
- // servlet framework. It must suffice until servlet output
- // streams properly encode their output.
- if (((c <= 31) && (c != 9)) || c == 127 || c > 255) {
- c = ' ';
- }
- appendByte(c);
- }
- appendByte(0);
- }
-
-
- /**
- * Write a String out at the current write position. Strings are
- * encoded with the length in two bytes first, then the string, and
- * then a terminating \0 (which is <B>not</B> included in the
- * encoded length). The terminator is for the convenience of the C
- * code, where it saves a round of copying. A null string is
- * encoded as a string with length 0.
- */
- public void appendString(String str) {
- if (str == null) {
- log.error(sm.getString("ajpmessage.null"),
- new NullPointerException());
- appendInt(0);
- appendByte(0);
- return;
- }
- int len = str.length();
- appendInt(len);
- for (int i = 0; i < len; i++) {
- char c = str.charAt (i);
- // Note: This is clearly incorrect for many strings,
- // but is the only consistent approach within the current
- // servlet framework. It must suffice until servlet output
- // streams properly encode their output.
- if (((c <= 31) && (c != 9)) || c == 127 || c > 255) {
- c = ' ';
- }
- appendByte(c);
- }
- appendByte(0);
- }
-
-
- /**
* Copy a chunk of bytes into the packet, starting at the current
* write position. The chunk of bytes is encoded with the length
* in two bytes first, then the data itself, and finally a
Modified: tomcat/trunk/java/org/apache/coyote/http11/AbstractOutputBuffer.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http11/AbstractOutputBuffer.java?rev=1630910&r1=1630909&r2=1630910&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http11/AbstractOutputBuffer.java
(original)
+++ tomcat/trunk/java/org/apache/coyote/http11/AbstractOutputBuffer.java Fri
Oct 10 14:28:52 2014
@@ -28,7 +28,6 @@ import org.apache.coyote.OutputBuffer;
import org.apache.coyote.Response;
import org.apache.coyote.http11.filters.GzipOutputFilter;
import org.apache.tomcat.util.buf.ByteChunk;
-import org.apache.tomcat.util.buf.CharChunk;
import org.apache.tomcat.util.buf.MessageBytes;
import org.apache.tomcat.util.http.HttpMessages;
import org.apache.tomcat.util.net.AbstractEndpoint;
@@ -488,16 +487,21 @@ public abstract class AbstractOutputBuff
*/
protected void write(MessageBytes mb) {
- if (mb.getType() == MessageBytes.T_BYTES) {
+ if (mb.getType() != MessageBytes.T_BYTES) {
+ mb.toBytes();
ByteChunk bc = mb.getByteChunk();
- write(bc);
- } else if (mb.getType() == MessageBytes.T_CHARS) {
- CharChunk cc = mb.getCharChunk();
- write(cc);
- } else {
- write(mb.toString());
+ // Need to filter out CTLs excluding TAB. ISO-8859-1 and UTF-8
+ // values will be OK. Strings using other encodings may be
+ // corrupted.
+ byte[] buffer = bc.getBuffer();
+ for (int i = bc.getOffset(); i < bc.getLength(); i++) {
+ if (((buffer[i] <= 31) && (buffer[i] != 9)) ||
+ buffer[i] == 127 || buffer[i] > 255) {
+ buffer[i] = ' ';
+ }
+ }
}
-
+ write(mb.getByteChunk());
}
@@ -520,34 +524,6 @@ public abstract class AbstractOutputBuff
/**
- * This method will write the contents of the specified char
- * buffer to the output stream, without filtering. This method is meant to
- * be used to write the response header.
- *
- * @param cc data to be written
- */
- protected void write(CharChunk cc) {
-
- int start = cc.getStart();
- int end = cc.getEnd();
- checkLengthBeforeWrite(end-start);
- char[] cbuf = cc.getBuffer();
- for (int i = start; i < end; i++) {
- char c = cbuf[i];
- // Note: This is clearly incorrect for many strings,
- // but is the only consistent approach within the current
- // servlet framework. It must suffice until servlet output
- // streams properly encode their output.
- if (((c <= 31) && (c != 9)) || c == 127 || c > 255) {
- c = ' ';
- }
- headerBuffer[pos++] = (byte) c;
- }
-
- }
-
-
- /**
* This method will write the contents of the specified byte
* buffer to the output stream, without filtering. This method is meant to
* be used to write the response header.
Modified: tomcat/trunk/test/org/apache/coyote/ajp/TesterAjpMessage.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/coyote/ajp/TesterAjpMessage.java?rev=1630910&r1=1630909&r2=1630910&view=diff
==============================================================================
--- tomcat/trunk/test/org/apache/coyote/ajp/TesterAjpMessage.java (original)
+++ tomcat/trunk/test/org/apache/coyote/ajp/TesterAjpMessage.java Fri Oct 10
14:28:52 2014
@@ -16,6 +16,7 @@
*/
package org.apache.coyote.ajp;
+import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
@@ -114,6 +115,11 @@ public class TesterAjpMessage extends Aj
}
+ public void appendString(String string) {
+ byte[] bytes = string.getBytes(StandardCharsets.ISO_8859_1);
+ appendBytes(bytes, 0, bytes.length);
+ }
+
private static class Header {
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]