diff --git a/module-client/src/examples/org/apache/http/examples/client/ClientFormLogin.java b/module-client/src/examples/org/apache/http/examples/client/ClientFormLogin.java index 6182d9381..36743864d 100644 --- a/module-client/src/examples/org/apache/http/examples/client/ClientFormLogin.java +++ b/module-client/src/examples/org/apache/http/examples/client/ClientFormLogin.java @@ -29,8 +29,8 @@ package org.apache.http.examples.client; +import java.util.ArrayList; import java.util.List; - import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.NameValuePair; @@ -45,7 +45,7 @@ import org.apache.http.message.BasicNameValuePair; import org.apache.http.protocol.HTTP; /** - * A example that demonstrates how HttpClient APIs can be used to perform + * A example that demonstrates how HttpClient APIs can be used to perform * form-based logon. */ public class ClientFormLogin { @@ -60,48 +60,47 @@ public class ClientFormLogin { HttpResponse response = httpclient.execute(httpget); HttpEntity entity = response.getEntity(); - - System.out.println("Login form get: " + response.getStatusLine()); + + System.out.println("Login form get: " + response.getStatusLine()); if (entity != null) { entity.consumeContent(); } - System.out.println("Initial set of cookies:"); + System.out.println("Initial set of cookies:"); List cookies = httpclient.getCookieStore().getCookies(); if (cookies.isEmpty()) { - System.out.println("None"); + System.out.println("None"); } else { for (int i = 0; i < cookies.size(); i++) { - System.out.println("- " + cookies.get(i).toString()); + System.out.println("- " + cookies.get(i).toString()); } } - + HttpPost httpost = new HttpPost("https://portal.sun.com/amserver/UI/Login?" + "org=self_registered_users&" + "goto=/portal/dt&" + "gotoOnFail=/portal/dt?error=true"); - - NameValuePair[] nvps = new NameValuePair[] { - new BasicNameValuePair("IDToken1", "username"), - new BasicNameValuePair("IDToken2", "password") - }; - + + List nvps = new ArrayList (); + nvps.add(new BasicNameValuePair("IDToken1", "username")); + nvps.add(new BasicNameValuePair("IDToken2", "password")); + httpost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8)); - + response = httpclient.execute(httpost); entity = response.getEntity(); - - System.out.println("Login form get: " + response.getStatusLine()); + + System.out.println("Login form get: " + response.getStatusLine()); if (entity != null) { entity.consumeContent(); } - - System.out.println("Post logon cookies:"); + + System.out.println("Post logon cookies:"); cookies = httpclient.getCookieStore().getCookies(); if (cookies.isEmpty()) { - System.out.println("None"); + System.out.println("None"); } else { for (int i = 0; i < cookies.size(); i++) { - System.out.println("- " + cookies.get(i).toString()); + System.out.println("- " + cookies.get(i).toString()); } } } diff --git a/module-client/src/main/java/org/apache/http/client/methods/UrlEncodedFormEntity.java b/module-client/src/main/java/org/apache/http/client/methods/UrlEncodedFormEntity.java index 4929b35e6..9cd0513e9 100644 --- a/module-client/src/main/java/org/apache/http/client/methods/UrlEncodedFormEntity.java +++ b/module-client/src/main/java/org/apache/http/client/methods/UrlEncodedFormEntity.java @@ -1,5 +1,5 @@ /* - * $Header$ + * $HeadURL$ * $Revision$ * $Date$ * @@ -32,43 +32,26 @@ package org.apache.http.client.methods; import java.io.UnsupportedEncodingException; import java.util.List; -import java.util.Map; - import org.apache.http.NameValuePair; -import org.apache.http.client.utils.URLUtils; +import org.apache.http.client.utils.URLEncodedUtils; import org.apache.http.entity.StringEntity; import org.apache.http.protocol.HTTP; public class UrlEncodedFormEntity extends StringEntity { - - /** The Content-Type for www-form-urlencoded. */ - public static final String FORM_URL_ENCODED_CONTENT_TYPE = - "application/x-www-form-urlencoded"; - - public UrlEncodedFormEntity( - final NameValuePair[] fields, - final String charset) throws UnsupportedEncodingException { - super(URLUtils.formUrlEncode(fields, charset), charset); - setContentType(FORM_URL_ENCODED_CONTENT_TYPE); - } - - public UrlEncodedFormEntity( - final NameValuePair[] fields) throws UnsupportedEncodingException { - super(URLUtils.formUrlEncode(fields, HTTP.UTF_8), HTTP.US_ASCII); - setContentType(FORM_URL_ENCODED_CONTENT_TYPE); - } - + public UrlEncodedFormEntity ( - final Map> parameters, - final String charset) throws UnsupportedEncodingException { - super(URLUtils.format(parameters, charset), HTTP.US_ASCII); - setContentType(FORM_URL_ENCODED_CONTENT_TYPE); + final List parameters, + final String encoding) throws UnsupportedEncodingException { + super(URLEncodedUtils.format(parameters, encoding), + encoding); + setContentType(URLEncodedUtils.CONTENT_TYPE); } - + public UrlEncodedFormEntity ( - final Map> parameters) throws UnsupportedEncodingException { - super(URLUtils.format(parameters, HTTP.UTF_8), HTTP.US_ASCII); - setContentType(FORM_URL_ENCODED_CONTENT_TYPE); + final List parameters) throws UnsupportedEncodingException { + super(URLEncodedUtils.format(parameters, HTTP.DEFAULT_CONTENT_CHARSET), + HTTP.DEFAULT_CONTENT_CHARSET); + setContentType(URLEncodedUtils.CONTENT_TYPE); } } diff --git a/module-client/src/main/java/org/apache/http/client/utils/URLEncodedUtils.java b/module-client/src/main/java/org/apache/http/client/utils/URLEncodedUtils.java new file mode 100644 index 000000000..55333ce97 --- /dev/null +++ b/module-client/src/main/java/org/apache/http/client/utils/URLEncodedUtils.java @@ -0,0 +1,138 @@ +/* + * $HeadURL$ + * $Revision$ + * $Date$ + * ==================================================================== + * 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.http.client.utils; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.net.URLDecoder; +import java.net.URLEncoder; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Scanner; +import org.apache.http.Header; +import org.apache.http.HttpEntity; +import org.apache.http.NameValuePair; +import org.apache.http.message.BasicNameValuePair; +import org.apache.http.protocol.HTTP; +import org.apache.http.util.EntityUtils; + +public class URLEncodedUtils { + + public static final String CONTENT_TYPE = "application/x-www-form-urlencoded"; + private static final String PARAMETER_SEPARATOR = "&"; + private static final String NAME_VALUE_SEPARATOR = "="; + + public static List parse (final URI uri, final String encoding) { + List result = Collections.emptyList(); + final String query = uri.getRawQuery(); + if (query != null && query.length() > 0) { + result = new ArrayList (); + parse(result, new Scanner(query), encoding); + } + return result; + } + + public static List parse ( + final HttpEntity entity) throws IOException { + List result = Collections.emptyList(); + if (isEncoded(entity)) { + final String content = EntityUtils.toString(entity); + final Header encoding = entity.getContentEncoding(); + if (content != null && content.length() > 0) { + result = new ArrayList (); + parse(result, new Scanner(content), + encoding != null ? encoding.getValue() : null); + } + } + return result; + } + + public static boolean isEncoded (final HttpEntity entity) { + final Header contentType = entity.getContentType(); + return (contentType != null && contentType.getValue().equalsIgnoreCase(CONTENT_TYPE)); + } + + public static void parse ( + final List parameters, + final Scanner scanner, + final String encoding) { + scanner.useDelimiter(PARAMETER_SEPARATOR); + while (scanner.hasNext()) { + final String[] nameValue = scanner.next().split(NAME_VALUE_SEPARATOR); + if (nameValue.length == 0 || nameValue.length > 2) + throw new IllegalArgumentException("bad parameter"); + + final String name = decode(nameValue[0], encoding); + String value = null; + if (nameValue.length == 2) + value = decode(nameValue[1], encoding); + parameters.add(new BasicNameValuePair(name, value)); + } + } + + public static String format ( + final List parameters, + final String encoding) { + final StringBuilder result = new StringBuilder(); + for (final NameValuePair parameter : parameters) { + final String encodedName = encode(parameter.getName(), encoding); + final String value = parameter.getValue(); + final String encodedValue = value != null ? encode(value, encoding) : ""; + if (result.length() > 0) + result.append(PARAMETER_SEPARATOR); + result.append(encodedName); + result.append(NAME_VALUE_SEPARATOR); + result.append(encodedValue); + } + return result.toString(); + } + + private static String decode (final String content, final String encoding) { + try { + return URLDecoder.decode(content, + encoding != null ? encoding : HTTP.DEFAULT_CONTENT_CHARSET); + } catch (UnsupportedEncodingException problem) { + throw new IllegalArgumentException(problem); + } + } + + private static String encode (final String content, final String encoding) { + try { + return URLEncoder.encode(content, + encoding != null ? encoding : HTTP.DEFAULT_CONTENT_CHARSET); + } catch (UnsupportedEncodingException problem) { + throw new IllegalArgumentException(problem); + } + } + +} diff --git a/module-client/src/main/java/org/apache/http/client/utils/URLUtils.java b/module-client/src/main/java/org/apache/http/client/utils/URLUtils.java index 73a101551..51f33beb5 100644 --- a/module-client/src/main/java/org/apache/http/client/utils/URLUtils.java +++ b/module-client/src/main/java/org/apache/http/client/utils/URLUtils.java @@ -29,170 +29,13 @@ */ package org.apache.http.client.utils; -import java.io.UnsupportedEncodingException; import java.net.URI; import java.net.URISyntaxException; -import java.net.URLDecoder; -import java.net.URLEncoder; -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Scanner; -import java.util.TreeMap; import org.apache.http.HttpHost; -import org.apache.http.NameValuePair; -import org.apache.http.protocol.HTTP; -/** - * The home for utility methods that handle various URL encoding tasks. - * - * @author Michael Becke - * @author Oleg Kalnichevski - * - * @since 4.0 - */ public class URLUtils { - /** Default content encoding chatset */ - private static final String DEFAULT_CHARSET = "ISO-8859-1"; - private static final String PARAMETER_SEPARATOR = "&"; - private static final String NAME_VALUE_SEPARATOR = "="; - - /** - * Form-urlencoding routine. - * - * The default encoding for all forms is `application/x-www-form-urlencoded'. - * A form data set is represented in this media type as follows: - * - * The form field names and values are escaped: space characters are replaced - * by `+', and then reserved characters are escaped as per [URL]; that is, - * non-alphanumeric characters are replaced by `%HH', a percent sign and two - * hexadecimal digits representing the ASCII code of the character. Line breaks, - * as in multi-line text field values, are represented as CR LF pairs, i.e. `%0D%0A'. - * - *

- * if the given charset is not supported, ISO-8859-1 is used instead. - *

- * - * @param pairs the values to be encoded - * @param charset the character set of pairs to be encoded - * - * @return the urlencoded pairs - */ - public static String simpleFormUrlEncode( - final NameValuePair[] pairs, - final String charset) { - try { - return formUrlEncode(pairs, charset); - } catch (UnsupportedEncodingException e) { - try { - return formUrlEncode(pairs, DEFAULT_CHARSET); - } catch (UnsupportedEncodingException fatal) { - // Should never happen. ISO-8859-1 must be supported on all JVMs - throw new Error("HttpClient requires " + DEFAULT_CHARSET + " support"); - } - } - } - - /** - * Form-urlencoding routine. - * - * The default encoding for all forms is `application/x-www-form-urlencoded'. - * A form data set is represented in this media type as follows: - * - * The form field names and values are escaped: space characters are replaced - * by `+', and then reserved characters are escaped as per [URL]; that is, - * non-alphanumeric characters are replaced by `%HH', a percent sign and two - * hexadecimal digits representing the ASCII code of the character. Line breaks, - * as in multi-line text field values, are represented as CR LF pairs, i.e. `%0D%0A'. - * - * @param pairs the values to be encoded - * @param charset the character set of pairs to be encoded - * - * @return the urlencoded pairs - * @throws UnsupportedEncodingException if charset is not supported - */ - public static String formUrlEncode( - final NameValuePair[] pairs, - final String charset) throws UnsupportedEncodingException { - StringBuilder buf = new StringBuilder(); - for (int i = 0; i < pairs.length; i++) { - NameValuePair pair = pairs[i]; - if (pair.getName() != null) { - if (i > 0) { - buf.append("&"); - } - buf.append(URLEncoder.encode(pair.getName(), charset)); - buf.append("="); - if (pair.getValue() != null) { - buf.append(URLEncoder.encode(pair.getValue(), charset)); - } - } - } - return buf.toString(); - } - - public static Map > parse ( - final URI uri, - String charset) throws UnsupportedEncodingException { - Map > result = Collections.emptyMap(); - final String query = uri.getRawQuery(); - if (query != null && query.length() > 0) { - result = new TreeMap >(); - parse(result, new Scanner(query), charset); - } - return result; - } - - public static void parse ( - final Map > result, - final Scanner scanner, String charset) throws UnsupportedEncodingException { - if (charset == null) { - charset = HTTP.DEFAULT_CONTENT_CHARSET; - } - scanner.useDelimiter(PARAMETER_SEPARATOR); - while (scanner.hasNext()) { - final String[] nameValue = scanner.next().split(NAME_VALUE_SEPARATOR); - if (nameValue.length == 0 || nameValue.length > 2) - throw new IllegalArgumentException("bad parameter"); - final String name = URLDecoder.decode(nameValue[0], charset); - if (nameValue.length == 2) { - if (!result.containsKey(name)) - result.put(name, new LinkedList ()); - String value = null; - final List values = result.get(name); - value = URLDecoder.decode(nameValue[1], charset); - values.add(value); - } - } - } - - public static String format ( - final Map > parameters, - String charset) throws UnsupportedEncodingException { - if (charset == null) { - charset = HTTP.DEFAULT_CONTENT_CHARSET; - } - final StringBuilder result = new StringBuilder(64); - for (final String name : parameters.keySet()) { - final List values = parameters.get(name); - if (values != null) { - final String encodedName = URLEncoder.encode(name, charset); - for (final String value : values) { - if (result.length() > 0) - result.append(PARAMETER_SEPARATOR); - final String encodedValue = URLEncoder.encode(value, charset); - result.append(encodedName); - result.append(NAME_VALUE_SEPARATOR); - result.append(encodedValue); - } - } - } - return result.toString(); - } - public static URI createURI( final String scheme, final String host, diff --git a/module-client/src/test/java/org/apache/http/client/utils/TestAllUtils.java b/module-client/src/test/java/org/apache/http/client/utils/TestAllUtils.java new file mode 100644 index 000000000..0730b8c17 --- /dev/null +++ b/module-client/src/test/java/org/apache/http/client/utils/TestAllUtils.java @@ -0,0 +1,54 @@ +/* + * $HeadURL$ + * $Revision$ + * $Date$ + * ==================================================================== + * 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.http.client.utils; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +public class TestAllUtils extends TestCase { + + public TestAllUtils(String testName) { + super(testName); + } + + public static Test suite() { + TestSuite suite = new TestSuite(); + suite.addTest(TestURLEncodedUtils.suite()); + return suite; + } + + public static void main(String args[]) { + String[] testCaseName = { TestAllUtils.class.getName() }; + junit.textui.TestRunner.main(testCaseName); + } + +} diff --git a/module-client/src/test/java/org/apache/http/client/utils/TestURLEncodedUtils.java b/module-client/src/test/java/org/apache/http/client/utils/TestURLEncodedUtils.java new file mode 100644 index 000000000..7ab20f3fd --- /dev/null +++ b/module-client/src/test/java/org/apache/http/client/utils/TestURLEncodedUtils.java @@ -0,0 +1,180 @@ +/* + * $HeadURL$ + * $Revision$ + * $Date$ + * ==================================================================== + * 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.http.client.utils; + +import java.io.IOException; +import java.net.URI; +import java.util.ArrayList; +import java.util.List; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +import org.apache.http.NameValuePair; +import org.apache.http.entity.StringEntity; +import org.apache.http.message.BasicNameValuePair; + +public class TestURLEncodedUtils extends TestCase { + + public TestURLEncodedUtils(final String testName) throws IOException { + super(testName); + } + + public static void main(String args[]) { + String[] testCaseName = { TestURLEncodedUtils.class.getName() }; + junit.textui.TestRunner.main(testCaseName); + } + + public static Test suite() { + return new TestSuite(TestURLEncodedUtils.class); + } + + public void testParseURI () throws Exception { + List result; + + result = parse("", null); + assertTrue(result.isEmpty()); + + result = parse("Name1=Value1", null); + assertEquals(1, result.size()); + assertNameValuePair(result.get(0), "Name1", "Value1"); + + result = parse("Name2=", null); + assertEquals(1, result.size()); + assertNameValuePair(result.get(0), "Name2", null); + + result = parse("Name3", null); + assertEquals(1, result.size()); + assertNameValuePair(result.get(0), "Name3", null); + + result = parse("Name4=Value+4%21", null); + assertEquals(1, result.size()); + assertNameValuePair(result.get(0), "Name4", "Value 4!"); + + result = parse("Name4=Value%2B4%21", null); + assertEquals(1, result.size()); + assertNameValuePair(result.get(0), "Name4", "Value+4!"); + + result = parse("Name4=Value+4%21+%214", null); + assertEquals(1, result.size()); + assertNameValuePair(result.get(0), "Name4", "Value 4! !4"); + + result = parse("Name5=aaa&Name6=bbb", null); + assertEquals(2, result.size()); + assertNameValuePair(result.get(0), "Name5", "aaa"); + assertNameValuePair(result.get(1), "Name6", "bbb"); + + result = parse("Name7=aaa&Name7=b%2Cb&Name7=ccc", null); + assertEquals(3, result.size()); + assertNameValuePair(result.get(0), "Name7", "aaa"); + assertNameValuePair(result.get(1), "Name7", "b,b"); + assertNameValuePair(result.get(2), "Name7", "ccc"); + + result = parse("Name8=xx%2C++yy++%2Czz", null); + assertEquals(1, result.size()); + assertNameValuePair(result.get(0), "Name8", "xx, yy ,zz"); + } + + public void testParseEntity () throws Exception { + final StringEntity entity = new StringEntity("Name1=Value1", null); + + entity.setContentType(URLEncodedUtils.CONTENT_TYPE); + final List result = URLEncodedUtils.parse(entity); + assertEquals(1, result.size()); + assertNameValuePair(result.get(0), "Name1", "Value1"); + + entity.setContentType("text/test"); + assertTrue(URLEncodedUtils.parse(entity).isEmpty()); + } + + public void testIsEncoded () throws Exception { + final StringEntity entity = new StringEntity("...", null); + + entity.setContentType(URLEncodedUtils.CONTENT_TYPE); + assertTrue(URLEncodedUtils.isEncoded(entity)); + + entity.setContentType("text/test"); + assertFalse(URLEncodedUtils.isEncoded(entity)); + } + + public void testFormat () throws Exception { + final List params = new ArrayList (); + assertEquals(0, URLEncodedUtils.format(params, null).length()); + + params.clear(); + params.add(new BasicNameValuePair("Name1", "Value1")); + assertEquals("Name1=Value1", URLEncodedUtils.format(params, null)); + + params.clear(); + params.add(new BasicNameValuePair("Name2", null)); + assertEquals("Name2=", URLEncodedUtils.format(params, null)); + + params.clear(); + params.add(new BasicNameValuePair("Name4", "Value 4!")); + assertEquals("Name4=Value+4%21", URLEncodedUtils.format(params, null)); + + params.clear(); + params.add(new BasicNameValuePair("Name4", "Value+4!")); + assertEquals("Name4=Value%2B4%21", URLEncodedUtils.format(params, null)); + + params.clear(); + params.add(new BasicNameValuePair("Name4", "Value 4! !4")); + assertEquals("Name4=Value+4%21+%214", URLEncodedUtils.format(params, null)); + + params.clear(); + params.add(new BasicNameValuePair("Name5", "aaa")); + params.add(new BasicNameValuePair("Name6", "bbb")); + assertEquals("Name5=aaa&Name6=bbb", URLEncodedUtils.format(params, null)); + + params.clear(); + params.add(new BasicNameValuePair("Name7", "aaa")); + params.add(new BasicNameValuePair("Name7", "b,b")); + params.add(new BasicNameValuePair("Name7", "ccc")); + assertEquals("Name7=aaa&Name7=b%2Cb&Name7=ccc", URLEncodedUtils.format(params, null)); + + params.clear(); + params.add(new BasicNameValuePair("Name8", "xx, yy ,zz")); + assertEquals("Name8=xx%2C++yy++%2Czz", URLEncodedUtils.format(params, null)); + } + + private List parse (final String params, final String encoding) { + return URLEncodedUtils.parse(URI.create("http://hc.apache.org/params?" + params), encoding); + } + + private static void assertNameValuePair ( + final NameValuePair parameter, + final String expectedName, + final String expectedValue) { + assertEquals(parameter.getName(), expectedName); + assertEquals(parameter.getValue(), expectedValue); + } +} \ No newline at end of file