Author: olegk Date: Thu May 26 11:21:14 2005 New Revision: 178662 URL: http://svn.apache.org/viewcvs?rev=178662&view=rev Log: PR #34961 (HttpClient does not correctly handle escaped characters in HTTP header elements)
Contributed by Oleg Kalnichevski Reviewed by Ortwin Glück Added: jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/util/ParameterFormatter.java (with props) jakarta/commons/proper/httpclient/trunk/src/test/org/apache/commons/httpclient/TestParameterFormatter.java (with props) Modified: jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/auth/DigestScheme.java jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/cookie/RFC2109Spec.java jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/util/ParameterParser.java jakarta/commons/proper/httpclient/trunk/src/test/org/apache/commons/httpclient/TestNoHost.java jakarta/commons/proper/httpclient/trunk/src/test/org/apache/commons/httpclient/TestParameterParser.java Modified: jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/auth/DigestScheme.java URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/auth/DigestScheme.java?rev=178662&r1=178661&r2=178662&view=diff ============================================================================== --- jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/auth/DigestScheme.java (original) +++ jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/auth/DigestScheme.java Thu May 26 11:21:14 2005 @@ -31,13 +31,17 @@ import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; +import java.util.ArrayList; +import java.util.List; import java.util.StringTokenizer; import org.apache.commons.httpclient.Credentials; import org.apache.commons.httpclient.HttpClientError; import org.apache.commons.httpclient.HttpMethod; +import org.apache.commons.httpclient.NameValuePair; import org.apache.commons.httpclient.UsernamePasswordCredentials; import org.apache.commons.httpclient.util.EncodingUtil; +import org.apache.commons.httpclient.util.ParameterFormatter; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -97,6 +101,7 @@ private int qopVariant = QOP_MISSING; private String cnonce; + private final ParameterFormatter formatter; /** * Default constructor for the digest authetication scheme. * @@ -105,6 +110,8 @@ public DigestScheme() { super(); this.complete = false; + this.formatter = new ParameterFormatter(); + this.formatter.setAlwaysUseQuotes(true); } /** @@ -138,8 +145,8 @@ */ public DigestScheme(final String challenge) throws MalformedChallengeException { - super(challenge); - this.complete = true; + this(); + processChallenge(challenge); } /** @@ -431,7 +438,7 @@ return serverDigest; } - + /** * Creates digest-response header as defined in RFC2617. * @@ -440,12 +447,12 @@ * * @return The digest-response as String. */ - private String createDigestHeader(String uname, String digest) throws AuthenticationException { + private String createDigestHeader(final String uname, final String digest) + throws AuthenticationException { LOG.trace("enter DigestScheme.createDigestHeader(String, Map, " + "String)"); - StringBuffer sb = new StringBuffer(); String uri = getParameter("uri"); String realm = getParameter("realm"); String nonce = getParameter("nonce"); @@ -455,22 +462,34 @@ String qop = getParameter("qop"); String algorithm = getParameter("algorithm"); - sb.append("username=\"" + uname + "\"") - .append(", realm=\"" + realm + "\"") - .append(", nonce=\"" + nonce + "\"").append(", uri=\"" + uri + "\"") - .append(", response=\"" + response + "\""); + List params = new ArrayList(20); + params.add(new NameValuePair("username", uname)); + params.add(new NameValuePair("realm", realm)); + params.add(new NameValuePair("nonce", nonce)); + params.add(new NameValuePair("uri", uri)); + params.add(new NameValuePair("response", response)); + if (qopVariant != QOP_MISSING) { - sb.append(", qop=\"" + getQopVariantString() + "\"") - .append(", nc="+ NC) - .append(", cnonce=\"" + cnonce + "\""); + params.add(new NameValuePair("qop", getQopVariantString())); + params.add(new NameValuePair("nc", NC)); + params.add(new NameValuePair("cnonce", this.cnonce)); } if (algorithm != null) { - sb.append(", algorithm=\"" + algorithm + "\""); + params.add(new NameValuePair("algorithm", algorithm)); } if (opaque != null) { - sb.append(", opaque=\"" + opaque + "\""); + params.add(new NameValuePair("opaque", opaque)); + } + + StringBuffer buffer = new StringBuffer(); + for (int i = 0; i < params.size(); i++) { + NameValuePair param = (NameValuePair) params.get(i); + if (i > 0) { + buffer.append(", "); + } + this.formatter.format(buffer, param); } - return sb.toString(); + return buffer.toString(); } private String getQopVariantString() { Modified: jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/cookie/RFC2109Spec.java URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/cookie/RFC2109Spec.java?rev=178662&r1=178661&r2=178662&view=diff ============================================================================== --- jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/cookie/RFC2109Spec.java (original) +++ jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/cookie/RFC2109Spec.java Thu May 26 11:21:14 2005 @@ -31,6 +31,7 @@ import org.apache.commons.httpclient.NameValuePair; import org.apache.commons.httpclient.Cookie; +import org.apache.commons.httpclient.util.ParameterFormatter; /** * <p>RFC 2109 specific cookie management functions @@ -51,12 +52,15 @@ public class RFC2109Spec extends CookieSpecBase { + private final ParameterFormatter formatter; + /** Default constructor */ public RFC2109Spec() { super(); + this.formatter = new ParameterFormatter(); + this.formatter.setAlwaysUseQuotes(true); } - /** * Parse RFC 2109 specific cookie attribute and update the corresponsing * [EMAIL PROTECTED] Cookie} properties. @@ -189,60 +193,46 @@ * Return a name/value string suitable for sending in a <tt>"Cookie"</tt> * header as defined in RFC 2109 for backward compatibility with cookie * version 0 - * @param name The name. - * @param value The value + * @param buffer The string buffer to use for output + * @param param The parameter. * @param version The cookie version - * @return a string suitable for sending in a <tt>"Cookie"</tt> header. */ - - private String formatNameValuePair( - final String name, final String value, int version) { - - final StringBuffer buffer = new StringBuffer(); + private void formatParam(final StringBuffer buffer, final NameValuePair param, int version) { if (version < 1) { - buffer.append(name); + buffer.append(param.getName()); buffer.append("="); - if (value != null) { - buffer.append(value); + if (param.getValue() != null) { + buffer.append(param.getValue()); } } else { - buffer.append(name); - buffer.append("=\""); - if (value != null) { - buffer.append(value); - } - buffer.append("\""); + this.formatter.format(buffer, param); } - return buffer.toString(); } /** * Return a string suitable for sending in a <tt>"Cookie"</tt> header * as defined in RFC 2109 for backward compatibility with cookie version 0 - * @param cookie a [EMAIL PROTECTED] Cookie} to be formatted as string + * @param buffer The string buffer to use for output + * @param cookie The [EMAIL PROTECTED] Cookie} to be formatted as string * @param version The version to use. - * @return a string suitable for sending in a <tt>"Cookie"</tt> header. */ - private String formatCookieAsVer(Cookie cookie, int version) { - LOG.trace("enter RFC2109Spec.formatCookieAsVer(Cookie)"); - StringBuffer buf = new StringBuffer(); - buf.append(formatNameValuePair(cookie.getName(), - cookie.getValue(), version)); + private void formatCookieAsVer(final StringBuffer buffer, final Cookie cookie, int version) { + String value = cookie.getValue(); + if (value == null) { + value = ""; + } + formatParam(buffer, new NameValuePair(cookie.getName(), value), version); if (cookie.getDomain() != null && cookie.isDomainAttributeSpecified()) { - - buf.append("; "); - buf.append(formatNameValuePair("$Domain", - cookie.getDomain(), version)); + buffer.append("; "); + formatParam(buffer, new NameValuePair("$Domain", cookie.getDomain()), version); } if (cookie.getPath() != null && cookie.isPathAttributeSpecified()) { - buf.append("; "); - buf.append(formatNameValuePair("$Path", cookie.getPath(), version)); + buffer.append("; "); + formatParam(buffer, new NameValuePair("$Path", cookie.getPath()), version); } - return buf.toString(); } - /** * Return a string suitable for sending in a <tt>"Cookie"</tt> header as * defined in RFC 2109 @@ -254,12 +244,13 @@ if (cookie == null) { throw new IllegalArgumentException("Cookie may not be null"); } - int ver = cookie.getVersion(); + int version = cookie.getVersion(); StringBuffer buffer = new StringBuffer(); - buffer.append(formatNameValuePair("$Version", - Integer.toString(ver), ver)); + formatParam(buffer, + new NameValuePair("$Version", Integer.toString(version)), + version); buffer.append("; "); - buffer.append(formatCookieAsVer(cookie, ver)); + formatCookieAsVer(buffer, cookie, version); return buffer.toString(); } @@ -281,11 +272,12 @@ } } final StringBuffer buffer = new StringBuffer(); - buffer.append(formatNameValuePair("$Version", - Integer.toString(version), version)); + formatParam(buffer, + new NameValuePair("$Version", Integer.toString(version)), + version); for (int i = 0; i < cookies.length; i++) { buffer.append("; "); - buffer.append(formatCookieAsVer(cookies[i], version)); + formatCookieAsVer(buffer, cookies[i], version); } return buffer.toString(); } Added: jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/util/ParameterFormatter.java URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/util/ParameterFormatter.java?rev=178662&view=auto ============================================================================== --- jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/util/ParameterFormatter.java (added) +++ jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/util/ParameterFormatter.java Thu May 26 11:21:14 2005 @@ -0,0 +1,241 @@ +/* + * $HeadURL$ + * $Revision$ + * $Date$ + * + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * <http://www.apache.org/>. + * + */ + +package org.apache.commons.httpclient.util; + +import org.apache.commons.httpclient.NameValuePair; + +/** + * <p> + * This formatter produces a textual representation of attribute/value pairs. It + * comforms to the generic grammar and formatting rules outlined in the + * <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec2.html#sec2.1">Section 2.1</a> + * and + * <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.6">Section 3.6</a> + * of <a href="http://www.w3.org/Protocols/rfc2616/rfc2616.txt">RFC 2616</a> + * </p> + * <h>2.1 Augmented BNF</h> + * <p> + * Many HTTP/1.1 header field values consist of words separated by LWS or special + * characters. These special characters MUST be in a quoted string to be used within + * a parameter value (as defined in section 3.6). + * <p> + * <pre> + * token = 1*<any CHAR except CTLs or separators> + * separators = "(" | ")" | "<" | ">" | "@" + * | "," | ";" | ":" | "\" | <"> + * | "/" | "[" | "]" | "?" | "=" + * | "{" | "}" | SP | HT + * </pre> + * <p> + * A string of text is parsed as a single word if it is quoted using double-quote marks. + * </p> + * <pre> + * quoted-string = ( <"> *(qdtext | quoted-pair ) <"> ) + * qdtext = <any TEXT except <">> + * </pre> + * <p> + * The backslash character ("\") MAY be used as a single-character quoting mechanism only + * within quoted-string and comment constructs. + * </p> + * <pre> + * quoted-pair = "\" CHAR + * </pre> + * <h>3.6 Transfer Codings</h> + * <p> + * Parameters are in the form of attribute/value pairs. + * </p> + * <pre> + * parameter = attribute "=" value + * attribute = token + * value = token | quoted-string + * </pre> + * + * @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a> + * + * @since 3.0 + */ +public class ParameterFormatter { + + /** + * Special characters that can be used as separators in HTTP parameters. + * These special characters MUST be in a quoted string to be used within + * a parameter value + */ + private static final char[] SEPARATORS = { + '(', ')', '<', '>', '@', + ',', ';', ':', '\\', '"', + '/', '[', ']', '?', '=', + '{', '}', ' ', '\t' + }; + + /** + * Unsafe special characters that must be escaped using the backslash + * character + */ + private static final char[] UNSAFE_CHARS = { + '"', '\\' + }; + + /** + * This flag determines whether all parameter values must be enclosed in + * quotation marks, even if they do not contain any special characters + */ + private boolean alwaysUseQuotes = true; + + /** Default ParameterFormatter constructor */ + public ParameterFormatter() { + super(); + } + + private static boolean isOneOf(char[] chars, char ch) { + for (int i = 0; i < chars.length; i++) { + if (ch == chars[i]) { + return true; + } + } + return false; + } + + private static boolean isUnsafeChar(char ch) { + return isOneOf(UNSAFE_CHARS, ch); + } + + private static boolean isSeparator(char ch) { + return isOneOf(SEPARATORS, ch); + } + + /** + * Determines whether all parameter values must be enclosed in quotation + * marks, even if they do not contain any special characters + * + * @return <tt>true</tt> if all parameter values must be enclosed in + * quotation marks, <tt>false</tt> otherwise + */ + public boolean isAlwaysUseQuotes() { + return alwaysUseQuotes; + } + + /** + * Defines whether all parameter values must be enclosed in quotation + * marks, even if they do not contain any special characters + * + * @param alwaysUseQuotes + */ + public void setAlwaysUseQuotes(boolean alwaysUseQuotes) { + this.alwaysUseQuotes = alwaysUseQuotes; + } + + /** + * Formats the given parameter value using formatting rules defined + * in RFC 2616 + * + * @param buffer output buffer + * @param value the parameter value to be formatted + * @param alwaysUseQuotes <tt>true</tt> if the parameter value must + * be enclosed in quotation marks, even if it does not contain any special + * characters<tt>, false</tt> only if the parameter value contains + * potentially unsafe special characters + */ + public static void formatValue( + final StringBuffer buffer, final String value, boolean alwaysUseQuotes) { + if (buffer == null) { + throw new IllegalArgumentException("String buffer may not be null"); + } + if (value == null) { + throw new IllegalArgumentException("Value buffer may not be null"); + } + if (alwaysUseQuotes) { + buffer.append('"'); + for (int i = 0; i < value.length(); i++) { + char ch = value.charAt(i); + if (isUnsafeChar(ch)) { + buffer.append('\\'); + } + buffer.append(ch); + } + buffer.append('"'); + } else { + int offset = buffer.length(); + boolean unsafe = false; + for (int i = 0; i < value.length(); i++) { + char ch = value.charAt(i); + if (isSeparator(ch)) { + unsafe = true; + } + if (isUnsafeChar(ch)) { + buffer.append('\\'); + } + buffer.append(ch); + } + if (unsafe) { + buffer.insert(offset, '"'); + buffer.append('"'); + } + } + } + + /** + * Produces textual representaion of the attribute/value pair using + * formatting rules defined in RFC 2616 + * + * @param buffer output buffer + * @param param the parameter to be formatted + */ + public void format(final StringBuffer buffer, final NameValuePair param) { + if (buffer == null) { + throw new IllegalArgumentException("String buffer may not be null"); + } + if (param == null) { + throw new IllegalArgumentException("Parameter may not be null"); + } + buffer.append(param.getName()); + String value = param.getValue(); + if (value != null) { + buffer.append("="); + formatValue(buffer, value, this.alwaysUseQuotes); + } + } + + /** + * Produces textual representaion of the attribute/value pair using + * formatting rules defined in RFC 2616 + * + * @param param the parameter to be formatted + * + * @return RFC 2616 conformant textual representaion of the + * attribute/value pair + */ + public String format(final NameValuePair param) { + StringBuffer buffer = new StringBuffer(); + format(buffer, param); + return buffer.toString(); + } + +} Propchange: jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/util/ParameterFormatter.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/util/ParameterFormatter.java ------------------------------------------------------------------------------ svn:keywords = Date Author Id Revision HeadURL Propchange: jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/util/ParameterFormatter.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Modified: jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/util/ParameterParser.java URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/util/ParameterParser.java?rev=178662&r1=178661&r2=178662&view=diff ============================================================================== --- jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/util/ParameterParser.java (original) +++ jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/util/ParameterParser.java Thu May 26 11:21:14 2005 @@ -142,16 +142,19 @@ i1 = pos; i2 = pos; boolean quoted = false; + boolean charEscaped = false; while (hasChar()) { ch = chars[pos]; if (!quoted && isOneOf(ch, terminators)) { break; } - if (ch == '"') { + if (!charEscaped && ch == '"') { quoted = !quoted; } + charEscaped = (!charEscaped && ch == '\\'); i2++; pos++; + } return getToken(true); } Modified: jakarta/commons/proper/httpclient/trunk/src/test/org/apache/commons/httpclient/TestNoHost.java URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/httpclient/trunk/src/test/org/apache/commons/httpclient/TestNoHost.java?rev=178662&r1=178661&r2=178662&view=diff ============================================================================== --- jakarta/commons/proper/httpclient/trunk/src/test/org/apache/commons/httpclient/TestNoHost.java (original) +++ jakarta/commons/proper/httpclient/trunk/src/test/org/apache/commons/httpclient/TestNoHost.java Thu May 26 11:21:14 2005 @@ -64,6 +64,7 @@ suite.addTest(TestRequestHeaders.suite()); suite.addTest(TestStreams.suite()); suite.addTest(TestParameterParser.suite()); + suite.addTest(TestParameterFormatter.suite()); suite.addTest(TestNVP.suite()); suite.addTest(TestMethodCharEncoding.suite()); suite.addTest(TestHttpVersion.suite()); Added: jakarta/commons/proper/httpclient/trunk/src/test/org/apache/commons/httpclient/TestParameterFormatter.java URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/httpclient/trunk/src/test/org/apache/commons/httpclient/TestParameterFormatter.java?rev=178662&view=auto ============================================================================== --- jakarta/commons/proper/httpclient/trunk/src/test/org/apache/commons/httpclient/TestParameterFormatter.java (added) +++ jakarta/commons/proper/httpclient/trunk/src/test/org/apache/commons/httpclient/TestParameterFormatter.java Thu May 26 11:21:14 2005 @@ -0,0 +1,88 @@ +/* + * $HeadURL$ + * $Revision$ + * $Date$ + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * <http://www.apache.org/>. + * + */ + +package org.apache.commons.httpclient; + +import org.apache.commons.httpclient.util.ParameterFormatter; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +/** + * Unit tests for [EMAIL PROTECTED] ParameterFormatter}. + * + * @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a> + */ +public class TestParameterFormatter extends TestCase { + + // ------------------------------------------------------------ Constructor + public TestParameterFormatter(String testName) { + super(testName); + } + + // ------------------------------------------------------------------- Main + public static void main(String args[]) { + String[] testCaseName = { TestParameterFormatter.class.getName() }; + junit.textui.TestRunner.main(testCaseName); + } + + // ------------------------------------------------------- TestCase Methods + + public static Test suite() { + return new TestSuite(TestParameterFormatter.class); + } + + public void testBasicValueFormatting() throws Exception { + ParameterFormatter formatter = new ParameterFormatter(); + + NameValuePair param1 = new NameValuePair("param", "regular_stuff"); + NameValuePair param2 = new NameValuePair("param", "this\\that"); + NameValuePair param3 = new NameValuePair("param", "this,that"); + NameValuePair param4 = new NameValuePair("param", "quote marks (\") must be escaped"); + NameValuePair param5 = new NameValuePair("param", "back slash (\\) must be escaped too"); + NameValuePair param6 = new NameValuePair("param", "values with\tblanks must always be quoted"); + + formatter.setAlwaysUseQuotes(false); + assertEquals("param=regular_stuff", formatter.format(param1)); + assertEquals("param=\"this\\\\that\"", formatter.format(param2)); + assertEquals("param=\"this,that\"", formatter.format(param3)); + assertEquals("param=\"quote marks (\\\") must be escaped\"", formatter.format(param4)); + assertEquals("param=\"back slash (\\\\) must be escaped too\"", formatter.format(param5)); + assertEquals("param=\"values with\tblanks must always be quoted\"", formatter.format(param6)); + + formatter.setAlwaysUseQuotes(true); + assertEquals("param=\"regular_stuff\"", formatter.format(param1)); + assertEquals("param=\"this\\\\that\"", formatter.format(param2)); + assertEquals("param=\"this,that\"", formatter.format(param3)); + assertEquals("param=\"quote marks (\\\") must be escaped\"", formatter.format(param4)); + assertEquals("param=\"back slash (\\\\) must be escaped too\"", formatter.format(param5)); + assertEquals("param=\"values with\tblanks must always be quoted\"", formatter.format(param6)); + } + +} Propchange: jakarta/commons/proper/httpclient/trunk/src/test/org/apache/commons/httpclient/TestParameterFormatter.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: jakarta/commons/proper/httpclient/trunk/src/test/org/apache/commons/httpclient/TestParameterFormatter.java ------------------------------------------------------------------------------ svn:keywords = Date Author Id Revision HeadURL Propchange: jakarta/commons/proper/httpclient/trunk/src/test/org/apache/commons/httpclient/TestParameterFormatter.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Modified: jakarta/commons/proper/httpclient/trunk/src/test/org/apache/commons/httpclient/TestParameterParser.java URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/httpclient/trunk/src/test/org/apache/commons/httpclient/TestParameterParser.java?rev=178662&r1=178661&r2=178662&view=diff ============================================================================== --- jakarta/commons/proper/httpclient/trunk/src/test/org/apache/commons/httpclient/TestParameterParser.java (original) +++ jakarta/commons/proper/httpclient/trunk/src/test/org/apache/commons/httpclient/TestParameterParser.java Thu May 26 11:21:14 2005 @@ -1,4 +1,7 @@ /* + * $HeadURL$ + * $Revision$ + * $Date$ * ==================================================================== * * Copyright 1999-2004 The Apache Software Foundation @@ -21,8 +24,6 @@ * information on the Apache Software Foundation, please see * <http://www.apache.org/>. * - * [Additional notices, if required by prior licensing conditions] - * */ package org.apache.commons.httpclient; @@ -38,7 +39,7 @@ /** * Unit tests for [EMAIL PROTECTED] ParameterParser}. * - * @author <a href="mailto:[EMAIL PROTECTED]">Oleg Kalnichevski</a> + * @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a> */ public class TestParameterParser extends TestCase { @@ -98,4 +99,27 @@ params = parser.parse(s, ';'); assertEquals(0, params.size()); } + + public void testParsingEscapedChars() { + String s = "param = \"stuff\\\"; more stuff\""; + ParameterParser parser = new ParameterParser(); + List params = parser.parse(s, ';'); + assertEquals(1, params.size()); + assertEquals("param", + ((NameValuePair)params.get(0)).getName()); + assertEquals("stuff\\\"; more stuff", + ((NameValuePair)params.get(0)).getValue()); + + s = "param = \"stuff\\\\\"; anotherparam"; + params = parser.parse(s, ';'); + assertEquals(2, params.size()); + assertEquals("param", + ((NameValuePair)params.get(0)).getName()); + assertEquals("stuff\\\\", + ((NameValuePair)params.get(0)).getValue()); + assertEquals("anotherparam", + ((NameValuePair)params.get(1)).getName()); + assertNull( + ((NameValuePair)params.get(1)).getValue()); + } } --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]