You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by lu...@apache.org on 2003/10/13 23:53:45 UTC

cvs commit: jakarta-tomcat-connectors/coyote/src/java/org/apache/coyote Response.java

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: tomcat-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tomcat-dev-help@jakarta.apache.org


Re: cvs commit: jakarta-tomcat-connectors/coyote/src/java/org/apache/coyote Response.java

Posted by Bill Barker <wb...@wilshire.com>.
>   +        /*
>   +         * 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++;
>   +        }

Of course, this doesn't work if I do setContentType("text/html;
charset=utf-8");.

>   +        if (beginCharsetParam == -1) {
>   +            // no charset
>   +            this.contentType = contentType;
>   +            return;
>   +        }