Author: markt
Date: Mon Jun 19 18:34:02 2017
New Revision: 1799253

URL: http://svn.apache.org/viewvc?rev=1799253&view=rev
Log:
Fix https://bz.apache.org/bugzilla/show_bug.cgi?id=61197
Ensure that the charset name used in the Content-Type header has exactly the 
same form as that provided by the application. This reverts a behavioural 
change in 9.0.0.M21 that caused problems for some clients.

Added:
    tomcat/trunk/test/org/apache/coyote/TestResponse.java   (with props)
Modified:
    tomcat/trunk/java/org/apache/catalina/connector/Response.java
    tomcat/trunk/java/org/apache/coyote/Response.java
    tomcat/trunk/webapps/docs/changelog.xml

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=1799253&r1=1799252&r2=1799253&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/connector/Response.java (original)
+++ tomcat/trunk/java/org/apache/catalina/connector/Response.java Mon Jun 19 
18:34:02 2017
@@ -56,7 +56,6 @@ import org.apache.catalina.util.SessionC
 import org.apache.coyote.ActionCode;
 import org.apache.juli.logging.Log;
 import org.apache.juli.logging.LogFactory;
-import org.apache.tomcat.util.buf.B2CConverter;
 import org.apache.tomcat.util.buf.CharChunk;
 import org.apache.tomcat.util.buf.UEncoder;
 import org.apache.tomcat.util.buf.UEncoder.SafeCharsSet;
@@ -553,9 +552,9 @@ public class Response implements HttpSer
      */
     @Override
     public String getCharacterEncoding() {
-        Charset charset = getCoyoteResponse().getCharset();
+        String charset = getCoyoteResponse().getCharsetName();
         if (charset != null) {
-            return charset.name();
+            return charset;
         }
 
         Context context = getContext();
@@ -804,7 +803,7 @@ public class Response implements HttpSer
             // Ignore charset if getWriter() has already been called
             if (!usingWriter) {
                 try {
-                    
getCoyoteResponse().setCharset(B2CConverter.getCharset(m[1]));
+                    getCoyoteResponse().setCharset(m[1]);
                 } catch (UnsupportedEncodingException e) {
                     log.warn(sm.getString("coyoteResponse.encoding.invalid", 
m[1]), e);
                 }
@@ -841,7 +840,7 @@ public class Response implements HttpSer
         }
 
         try {
-            getCoyoteResponse().setCharset(B2CConverter.getCharset(charset));
+            getCoyoteResponse().setCharset(charset);
         } catch (UnsupportedEncodingException e) {
             log.warn(sm.getString("coyoteResponse.encoding.invalid", charset), 
e);
             return;
@@ -883,7 +882,7 @@ public class Response implements HttpSer
         String charset = getContext().getCharset(locale);
         if (charset != null) {
             try {
-                
getCoyoteResponse().setCharset(B2CConverter.getCharset(charset));
+                getCoyoteResponse().setCharset(charset);
             } catch (UnsupportedEncodingException e) {
                 log.warn(sm.getString("coyoteResponse.encoding.invalid", 
charset), e);
             }

Modified: tomcat/trunk/java/org/apache/coyote/Response.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/Response.java?rev=1799253&r1=1799252&r2=1799253&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/Response.java (original)
+++ tomcat/trunk/java/org/apache/coyote/Response.java Mon Jun 19 18:34:02 2017
@@ -112,6 +112,10 @@ public final class Response {
     String contentType = null;
     String contentLanguage = null;
     Charset charset = null;
+    // Retain the original name used to set the charset so exactly that name is
+    // used in the ContentType header. Some (arguably non-specification
+    // compliant) user agents are very particular
+    String charsetName = null;
     long contentLength = -1;
     private Locale locale = DEFAULT_LOCALE;
 
@@ -415,17 +419,21 @@ public final class Response {
      * Overrides the character encoding used in the body of the response. This
      * method must be called prior to writing output using getWriter().
      *
-     * @param charset The character encoding.
+     * @param charsetName The name of character encoding.
+     *
+     * @throws UnsupportedEncodingException If the specified name is not
+     *         recognised
      */
-    public void setCharset(Charset charset) {
+    public void setCharset(String charsetName) throws 
UnsupportedEncodingException {
         if (isCommitted()) {
             return;
         }
-        if (charset == null) {
+        if (charsetName == null) {
             return;
         }
 
-        this.charset = charset;
+        this.charset = B2CConverter.getCharset(charsetName);
+        this.charsetName = charsetName;
     }
 
 
@@ -434,6 +442,11 @@ public final class Response {
     }
 
 
+    public String getCharsetName() {
+        return charsetName;
+    }
+
+
     /**
      * Sets the content type.
      *
@@ -489,7 +502,7 @@ public final class Response {
 
         if (ret != null
             && charset != null) {
-            ret = ret + ";charset=" + charset.name();
+            ret = ret + ";charset=" + charsetName;
         }
 
         return ret;
@@ -534,6 +547,7 @@ public final class Response {
         contentLanguage = null;
         locale = DEFAULT_LOCALE;
         charset = null;
+        charsetName = null;
         contentLength = -1;
         status = 200;
         message = null;

Added: tomcat/trunk/test/org/apache/coyote/TestResponse.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/coyote/TestResponse.java?rev=1799253&view=auto
==============================================================================
--- tomcat/trunk/test/org/apache/coyote/TestResponse.java (added)
+++ tomcat/trunk/test/org/apache/coyote/TestResponse.java Mon Jun 19 18:34:02 
2017
@@ -0,0 +1,81 @@
+/*
+ *  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.coyote;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import org.apache.catalina.Context;
+import org.apache.catalina.startup.Tomcat;
+import org.apache.catalina.startup.TomcatBaseTest;
+import org.apache.tomcat.util.buf.ByteChunk;
+
+public class TestResponse extends TomcatBaseTest {
+
+    /*
+     * https://bz.apache.org/bugzilla/show_bug.cgi?id=61197
+     */
+    @Test
+    public void testUserCharsetIsRetained() throws Exception {
+        Tomcat tomcat = getTomcatInstance();
+
+        // No file system docBase required
+        Context ctx = tomcat.addContext("", null);
+
+        // Add  servlet
+        Tomcat.addServlet(ctx, "CharsetServlet", new CharsetServlet());
+        ctx.addServletMappingDecoded("/*", "CharsetServlet");
+
+        tomcat.start();
+
+        ByteChunk responseBody = new ByteChunk();
+        Map<String,List<String>> responseHeaders = new HashMap<>();
+        int rc = getUrl("http://localhost:"; + getPort() + 
"/test?charset=uTf-8", responseBody,
+                responseHeaders);
+
+        Assert.assertEquals(HttpServletResponse.SC_OK, rc);
+        Assert.assertTrue(responseHeaders.containsKey("Content-Type"));
+        List<String> contentType = responseHeaders.get("Content-Type");
+        Assert.assertEquals(1, contentType.size());
+        Assert.assertEquals("text/plain;charset=uTf-8", contentType.get(0));
+    }
+
+
+    private static class CharsetServlet extends HttpServlet {
+
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        protected void doGet(HttpServletRequest req, HttpServletResponse resp)
+                throws ServletException, IOException {
+            resp.setContentType("text/plain");
+            resp.setCharacterEncoding(req.getParameter("charset"));
+
+            resp.getWriter().print("OK");
+        }
+    }
+}

Propchange: tomcat/trunk/test/org/apache/coyote/TestResponse.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: tomcat/trunk/webapps/docs/changelog.xml
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/changelog.xml?rev=1799253&r1=1799252&r2=1799253&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/trunk/webapps/docs/changelog.xml Mon Jun 19 18:34:02 2017
@@ -125,6 +125,12 @@
         <code>getRequestURI()</code> for the dispatched request matches that of
         the original request. (markt)
       </fix>
+      <fix>
+        <bug>61197</bug>: Ensure that the charset name used in the
+        <code>Content-Type</code> header has exactly the same form as that
+        provided by the application. This reverts a behavioural change in
+        9.0.0.M21 that caused problems for some clients. (markt)
+      </fix>
     </changelog>
   </subsection>
   <subsection name="Coyote">



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

Reply via email to