1 /* 2 * ==================================================================== 3 * 4 * Licensed to the Apache Software Foundation (ASF) under one or more 5 * contributor license agreements. See the NOTICE file distributed with 6 * this work for additional information regarding copyright ownership. 7 * The ASF licenses this file to You under the Apache License, Version 2.0 8 * (the "License"); you may not use this file except in compliance with 9 * the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 * ==================================================================== 19 * 20 * This software consists of voluntary contributions made by many 21 * individuals on behalf of the Apache Software Foundation. For more 22 * information on the Apache Software Foundation, please see 23 * <http://www.apache.org/>. 24 * 25 * [Additional notices, if required by prior licensing conditions] 26 * 27 */ 28 29 package org.apache.commons.httpclient; 30 31 import junit.framework.Test; 32 import junit.framework.TestSuite; 33 34 import java.io.ByteArrayInputStream; 35 import java.io.ByteArrayOutputStream; 36 import java.io.IOException; 37 import java.io.InputStream; 38 import java.util.HashMap; 39 import java.util.Map; 40 import java.util.StringTokenizer; 41 42 import org.apache.commons.httpclient.methods.GetMethod; 43 import org.apache.commons.httpclient.methods.PostMethod; 44 import org.apache.commons.httpclient.methods.RequestEntity; 45 import org.apache.commons.httpclient.methods.StringRequestEntity; 46 import org.apache.commons.httpclient.util.URIUtil; 47 48 /** 49 * @author <a href="mailto:oleg@ural.ru">Oleg Kalnichevski</a> 50 * @author <a href="mailto:ajmas@bigfoot.com">Andre John Mas</a> 51 * @author <a href="mailto:laura@lwerner.org">Laura Werner</a> 52 */ 53 54 public class TestMethodCharEncoding extends HttpClientTestBase { 55 56 static final String CHARSET_DEFAULT = "ISO-8859-1"; 57 static final String CHARSET_ASCII = "US-ASCII"; 58 static final String CHARSET_UTF8 = "UTF-8"; 59 static final String CHARSET_KOI8_R = "KOI8_R"; 60 static final String CHARSET_WIN1251 = "Cp1251"; 61 62 static final int SWISS_GERMAN_STUFF_UNICODE [] = { 63 0x47, 0x72, 0xFC, 0x65, 0x7A, 0x69, 0x5F, 0x7A, 0xE4, 0x6D, 0xE4 64 }; 65 66 static final int SWISS_GERMAN_STUFF_ISO8859_1 [] = { 67 0x47, 0x72, 0xFC, 0x65, 0x7A, 0x69, 0x5F, 0x7A, 0xE4, 0x6D, 0xE4 68 }; 69 70 static final int SWISS_GERMAN_STUFF_UTF8 [] = { 71 0x47, 0x72, 0xC3, 0xBC, 0x65, 0x7A, 0x69, 0x5F, 0x7A, 0xC3, 0xA4, 72 0x6D, 0xC3, 0xA4 73 }; 74 75 static final int RUSSIAN_STUFF_UNICODE [] = { 76 0x412, 0x441, 0x435, 0x43C, 0x5F, 0x43F, 0x440, 0x438, 77 0x432, 0x435, 0x442 78 }; 79 80 static final int RUSSIAN_STUFF_UTF8 [] = { 81 0xD0, 0x92, 0xD1, 0x81, 0xD0, 0xB5, 0xD0, 0xBC, 0x5F, 82 0xD0, 0xBF, 0xD1, 0x80, 0xD0, 0xB8, 0xD0, 0xB2, 0xD0, 83 0xB5, 0xD1, 0x82 84 }; 85 86 static final int RUSSIAN_STUFF_KOI8R [] = { 87 0xF7, 0xD3, 0xC5, 0xCD, 0x5F, 0xD0, 0xD2, 0xC9, 0xD7, 88 0xC5, 0xD4 89 }; 90 91 static final int RUSSIAN_STUFF_WIN1251 [] = { 92 0xC2, 0xF1, 0xE5, 0xEC, 0x5F, 0xEF, 0xF0, 0xE8, 0xE2, 93 0xE5, 0xF2 94 }; 95 96 // ------------------------------------------------------------ Constructor 97 TestMethodCharEncoding(final String testName)98 public TestMethodCharEncoding(final String testName) throws IOException { 99 super(testName); 100 } 101 102 // ------------------------------------------------------- TestCase Methods 103 suite()104 public static Test suite() { 105 return new TestSuite(TestMethodCharEncoding.class); 106 } 107 108 // ----------------------------------------------------------------- Tests 109 110 testRequestCharEncoding()111 public void testRequestCharEncoding() throws IOException { 112 113 GetMethod httpget = new GetMethod("/"); 114 assertEquals(CHARSET_DEFAULT, httpget.getRequestCharSet()); 115 httpget.setRequestHeader("Content-Type", "text/plain; charset=" + CHARSET_ASCII); 116 assertEquals(CHARSET_ASCII, httpget.getRequestCharSet()); 117 httpget.setRequestHeader("Content-Type", "text/plain; charset=" + CHARSET_UTF8); 118 assertEquals(CHARSET_UTF8, httpget.getRequestCharSet()); 119 120 } 121 testNoExplicitCharEncoding()122 public void testNoExplicitCharEncoding() throws Exception { 123 this.server.setHttpService(new EchoService()); 124 125 GetMethod httpget = new GetMethod("/test/"); 126 httpget.setRequestHeader("Content-Type", "text/plain"); 127 try { 128 this.client.executeMethod(httpget); 129 assertEquals(HttpStatus.SC_OK, httpget.getStatusCode()); 130 assertEquals(CHARSET_DEFAULT, httpget.getResponseCharSet()); 131 } finally { 132 httpget.releaseConnection(); 133 } 134 } 135 testExplicitCharEncoding()136 public void testExplicitCharEncoding() throws Exception { 137 this.server.setHttpService(new EchoService()); 138 139 GetMethod httpget = new GetMethod("/test/"); 140 httpget.setRequestHeader("Content-Type", "text/plain; charset=" + CHARSET_UTF8); 141 try { 142 this.client.executeMethod(httpget); 143 assertEquals(HttpStatus.SC_OK, httpget.getStatusCode()); 144 assertEquals(CHARSET_UTF8, httpget.getResponseCharSet()); 145 } finally { 146 httpget.releaseConnection(); 147 } 148 } 149 constructString(int [] unicodeChars)150 private String constructString(int [] unicodeChars) { 151 StringBuffer buffer = new StringBuffer(); 152 if (unicodeChars != null) { 153 for (int i = 0; i < unicodeChars.length; i++) { 154 buffer.append((char)unicodeChars[i]); 155 } 156 } 157 return buffer.toString(); 158 } 159 160 verifyEncoding(RequestEntity entity, int[] sample)161 private void verifyEncoding(RequestEntity entity, int[] sample) 162 throws IOException { 163 164 assertNotNull("Request body", entity); 165 166 ByteArrayOutputStream bos = new ByteArrayOutputStream(); 167 entity.writeRequest(bos); 168 169 InputStream instream = new ByteArrayInputStream(bos.toByteArray()); 170 for (int i = 0; i < sample.length; i++) { 171 int b = instream.read(); 172 assertTrue("Unexpected end of stream", b != -1); 173 if (sample[i] != b) { 174 fail("Invalid request body encoding"); 175 } 176 } 177 assertTrue("End of stream expected", instream.read() == -1); 178 } 179 testLatinAccentInRequestBody()180 public void testLatinAccentInRequestBody() throws IOException { 181 PostMethod httppost = new PostMethod("/"); 182 String s = constructString(SWISS_GERMAN_STUFF_UNICODE); 183 // Test default encoding ISO-8859-1 184 httppost.setRequestEntity( 185 new StringRequestEntity(s, "text/plain", CHARSET_DEFAULT)); 186 verifyEncoding(httppost.getRequestEntity(), SWISS_GERMAN_STUFF_ISO8859_1); 187 // Test UTF-8 encoding 188 httppost.setRequestEntity( 189 new StringRequestEntity(s, "text/plain", CHARSET_UTF8)); 190 verifyEncoding(httppost.getRequestEntity(), SWISS_GERMAN_STUFF_UTF8); 191 192 } 193 testRussianInRequestBody()194 public void testRussianInRequestBody() throws IOException { 195 PostMethod httppost = new PostMethod("/"); 196 String s = constructString(RUSSIAN_STUFF_UNICODE); 197 // Test UTF-8 encoding 198 httppost.setRequestEntity( 199 new StringRequestEntity(s, "text/plain", CHARSET_UTF8)); 200 verifyEncoding(httppost.getRequestEntity(), RUSSIAN_STUFF_UTF8); 201 // Test KOI8-R 202 httppost.setRequestEntity( 203 new StringRequestEntity(s, "text/plain", CHARSET_KOI8_R)); 204 verifyEncoding(httppost.getRequestEntity(), RUSSIAN_STUFF_KOI8R); 205 // Test WIN1251 206 httppost.setRequestEntity( 207 new StringRequestEntity(s, "text/plain", CHARSET_WIN1251)); 208 verifyEncoding(httppost.getRequestEntity(), RUSSIAN_STUFF_WIN1251); 209 } 210 testQueryParams()211 public void testQueryParams() throws Exception { 212 213 GetMethod get = new GetMethod("/"); 214 215 String ru_msg = constructString(RUSSIAN_STUFF_UNICODE); 216 String ch_msg = constructString(SWISS_GERMAN_STUFF_UNICODE); 217 218 get.setQueryString(new NameValuePair[] { 219 new NameValuePair("ru", ru_msg), 220 new NameValuePair("ch", ch_msg) 221 }); 222 223 Map params = new HashMap(); 224 StringTokenizer tokenizer = new StringTokenizer( 225 get.getQueryString(), "&"); 226 while (tokenizer.hasMoreTokens()) { 227 String s = tokenizer.nextToken(); 228 int i = s.indexOf('='); 229 assertTrue("Invalid url-encoded parameters", i != -1); 230 String name = s.substring(0, i).trim(); 231 String value = s.substring(i + 1, s.length()).trim(); 232 value = URIUtil.decode(value, CHARSET_UTF8); 233 params.put(name, value); 234 } 235 assertEquals(ru_msg, params.get("ru")); 236 assertEquals(ch_msg, params.get("ch")); 237 } 238 testUrlEncodedRequestBody()239 public void testUrlEncodedRequestBody() throws Exception { 240 241 PostMethod httppost = new PostMethod("/"); 242 243 String ru_msg = constructString(RUSSIAN_STUFF_UNICODE); 244 String ch_msg = constructString(SWISS_GERMAN_STUFF_UNICODE); 245 246 httppost.setRequestBody(new NameValuePair[] { 247 new NameValuePair("ru", ru_msg), 248 new NameValuePair("ch", ch_msg) 249 }); 250 251 httppost.setRequestHeader("Content-Type", PostMethod.FORM_URL_ENCODED_CONTENT_TYPE 252 + "; charset=" + CHARSET_UTF8); 253 254 ByteArrayOutputStream bos = new ByteArrayOutputStream(); 255 httppost.getRequestEntity().writeRequest(bos); 256 257 Map params = new HashMap(); 258 StringTokenizer tokenizer = new StringTokenizer( 259 new String(bos.toByteArray(), CHARSET_UTF8), "&"); 260 while (tokenizer.hasMoreTokens()) { 261 String s = tokenizer.nextToken(); 262 int i = s.indexOf('='); 263 assertTrue("Invalid url-encoded parameters", i != -1); 264 String name = s.substring(0, i).trim(); 265 String value = s.substring(i + 1, s.length()).trim(); 266 value = URIUtil.decode(value, CHARSET_UTF8); 267 params.put(name, value); 268 } 269 assertEquals(ru_msg, params.get("ru")); 270 assertEquals(ch_msg, params.get("ch")); 271 } 272 testRequestEntityLength()273 public void testRequestEntityLength() throws IOException { 274 String s = constructString(SWISS_GERMAN_STUFF_UNICODE); 275 RequestEntity requestentity = 276 new StringRequestEntity(s, "text/plain", CHARSET_UTF8); 277 assertEquals( 278 s.getBytes(CHARSET_UTF8).length, 279 requestentity.getContentLength()); 280 } 281 282 } 283