luehe 2003/10/13 14:53:45 Modified: coyote/src/java/org/apache/coyote Response.java Log: Fixed Bugtraq 4934442 ("Response Content-Type has no charset even though setCharacterEncoding was called") This fixes the problem where a response char setting via response.setCharacterEncoding() or response.setLocale() is not preserved by a call to response.setContentType() with a content type that has no charset, ie., response.getContentType(), following this sequence of calls: response.setCharacterEncoding("Shift_Jis"); response.setContentType("text/html") used to return "text/html" instead of "text/html;charset=Shift_Jis", which violates the servlet spec. Revision Changes Path 1.27 +59 -34 jakarta-tomcat-connectors/coyote/src/java/org/apache/coyote/Response.java Index: Response.java =================================================================== RCS file: /home/cvs/jakarta-tomcat-connectors/coyote/src/java/org/apache/coyote/Response.java,v retrieving revision 1.26 retrieving revision 1.27 diff -u -r1.26 -r1.27 --- Response.java 2 Sep 2003 21:34:38 -0000 1.26 +++ Response.java 13 Oct 2003 21:53:45 -0000 1.27 @@ -64,7 +64,6 @@ import java.util.Locale; import org.apache.tomcat.util.buf.ByteChunk; -import org.apache.tomcat.util.http.ContentType; import org.apache.tomcat.util.http.MimeHeaders; /** @@ -87,15 +86,18 @@ } - // ----------------------------------------------------- Instance Variables - - - /** + // ----------------------------------------------------- Class Variables + + /** * Default locale as mandated by the spec. */ private static Locale DEFAULT_LOCALE = Locale.getDefault(); - - + + private static final int BEGIN_CHARSET_VALUE = "charset=".length(); + + + // ----------------------------------------------------- Instance Variables + /** * Status code. */ @@ -471,44 +473,67 @@ return; characterEncoding = charset; - - String type = this.contentType; - if (type != null) { - int start = type.indexOf("charset="); - if ( start != -1 ) { - int end = type.indexOf(';', start+8); - if (end >= 0) - type = type.substring(0,start+8) - + charset + type.substring(end-1); - else - type = type.substring(0,start+8) + charset; - this.contentType = type; - } else { - int end = type.indexOf(';'); - if (end >= 0) { - type = type.substring(0, end) + ";charset=" + charset; - } else { - type = type + ";charset=" + charset; - } - } - setContentType( type ); - } } public String getCharacterEncoding() { return characterEncoding; } + /** + * Sets the content type. + * + * @param contentType the content type + */ public void setContentType(String contentType) { - this.contentType = contentType; - String encoding = ContentType.getCharsetFromContentType(contentType); - if (encoding != null) { - characterEncoding = encoding; + + if (contentType == null) { + this.contentType = null; + return; } + + /* + * Remove the charset param (if any) from the Content-Type, and use it + * to set the response encoding. + * The most recent response encoding setting will be appended to the + * response Content-Type (as its charset param) by getContentType(); + */ + int beginCharsetValue = BEGIN_CHARSET_VALUE; + int beginCharsetParam = contentType.indexOf(";charset="); + if (beginCharsetParam == -1) { + beginCharsetParam = contentType.indexOf("; charset="); + beginCharsetValue++; + } + if (beginCharsetParam == -1) { + // no charset + this.contentType = contentType; + return; + } + + this.contentType = contentType.substring(0, beginCharsetParam); + String tail = contentType.substring(beginCharsetParam + 1); + int nextParam = tail.indexOf(';'); + String charsetValue = null; + if (nextParam != -1) { + this.contentType += tail.substring(nextParam); + charsetValue = tail.substring(beginCharsetValue, nextParam); + } else { + charsetValue = tail.substring(beginCharsetValue); + } + // The charset value may be quoted, but must not contain any quotes. + charsetValue = charsetValue.replace('"', ' '); + this.characterEncoding = charsetValue.trim(); } public String getContentType() { - return contentType; + + String ret = contentType; + + if (ret != null && characterEncoding != null) { + ret += ";charset="; + ret += characterEncoding; + } + + return ret; } public void setContentLength(int contentLength) {
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]