1 /******************************************************************************* 2 * Copyright 2012 Internet2 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 ******************************************************************************/ 16 /* 17 * $HeadURL: https://svn.apache.org/repos/asf/jakarta/httpcomponents/oac.hc3x/tags/HTTPCLIENT_3_1/src/java/org/apache/commons/httpclient/util/ParameterFormatter.java $ 18 * $Revision: 1.1 $ 19 * $Date: 2008-11-30 10:57:27 $ 20 * 21 * ==================================================================== 22 * 23 * Licensed to the Apache Software Foundation (ASF) under one or more 24 * contributor license agreements. See the NOTICE file distributed with 25 * this work for additional information regarding copyright ownership. 26 * The ASF licenses this file to You under the Apache License, Version 2.0 27 * (the "License"); you may not use this file except in compliance with 28 * the License. You may obtain a copy of the License at 29 * 30 * http://www.apache.org/licenses/LICENSE-2.0 31 * 32 * Unless required by applicable law or agreed to in writing, software 33 * distributed under the License is distributed on an "AS IS" BASIS, 34 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 35 * See the License for the specific language governing permissions and 36 * limitations under the License. 37 * ==================================================================== 38 * 39 * This software consists of voluntary contributions made by many 40 * individuals on behalf of the Apache Software Foundation. For more 41 * information on the Apache Software Foundation, please see 42 * <http://www.apache.org/>. 43 * 44 */ 45 46 package edu.internet2.middleware.grouperInstallerExt.org.apache.commons.httpclient.util; 47 48 import edu.internet2.middleware.grouperInstallerExt.org.apache.commons.httpclient.NameValuePair; 49 50 /** 51 * <p> 52 * This formatter produces a textual representation of attribute/value pairs. It 53 * comforms to the generic grammar and formatting rules outlined in the 54 * <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec2.html#sec2.1">Section 2.1</a> 55 * and 56 * <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.6">Section 3.6</a> 57 * of <a href="http://www.w3.org/Protocols/rfc2616/rfc2616.txt">RFC 2616</a> 58 * </p> 59 * <h>2.1 Augmented BNF</h> 60 * <p> 61 * Many HTTP/1.1 header field values consist of words separated by LWS or special 62 * characters. These special characters MUST be in a quoted string to be used within 63 * a parameter value (as defined in section 3.6). 64 * <p> 65 * <pre> 66 * token = 1*<any CHAR except CTLs or separators> 67 * separators = "(" | ")" | "<" | ">" | "@" 68 * | "," | ";" | ":" | "\" | <"> 69 * | "/" | "[" | "]" | "?" | "=" 70 * | "{" | "}" | SP | HT 71 * </pre> 72 * <p> 73 * A string of text is parsed as a single word if it is quoted using double-quote marks. 74 * </p> 75 * <pre> 76 * quoted-string = ( <"> *(qdtext | quoted-pair ) <"> ) 77 * qdtext = <any TEXT except <">> 78 * </pre> 79 * <p> 80 * The backslash character ("\") MAY be used as a single-character quoting mechanism only 81 * within quoted-string and comment constructs. 82 * </p> 83 * <pre> 84 * quoted-pair = "\" CHAR 85 * </pre> 86 * <h>3.6 Transfer Codings</h> 87 * <p> 88 * Parameters are in the form of attribute/value pairs. 89 * </p> 90 * <pre> 91 * parameter = attribute "=" value 92 * attribute = token 93 * value = token | quoted-string 94 * </pre> 95 * 96 * @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a> 97 * 98 * @since 3.0 99 */ 100 public class ParameterFormatter { 101 102 /** 103 * Special characters that can be used as separators in HTTP parameters. 104 * These special characters MUST be in a quoted string to be used within 105 * a parameter value 106 */ 107 private static final char[] SEPARATORS = { 108 '(', ')', '<', '>', '@', 109 ',', ';', ':', '\\', '"', 110 '/', '[', ']', '?', '=', 111 '{', '}', ' ', '\t' 112 }; 113 114 /** 115 * Unsafe special characters that must be escaped using the backslash 116 * character 117 */ 118 private static final char[] UNSAFE_CHARS = { 119 '"', '\\' 120 }; 121 122 /** 123 * This flag determines whether all parameter values must be enclosed in 124 * quotation marks, even if they do not contain any special characters 125 */ 126 private boolean alwaysUseQuotes = true; 127 128 /** Default ParameterFormatter constructor */ 129 public ParameterFormatter() { 130 super(); 131 } 132 133 private static boolean isOneOf(char[] chars, char ch) { 134 for (int i = 0; i < chars.length; i++) { 135 if (ch == chars[i]) { 136 return true; 137 } 138 } 139 return false; 140 } 141 142 private static boolean isUnsafeChar(char ch) { 143 return isOneOf(UNSAFE_CHARS, ch); 144 } 145 146 private static boolean isSeparator(char ch) { 147 return isOneOf(SEPARATORS, ch); 148 } 149 150 /** 151 * Determines whether all parameter values must be enclosed in quotation 152 * marks, even if they do not contain any special characters 153 * 154 * @return <tt>true</tt> if all parameter values must be enclosed in 155 * quotation marks, <tt>false</tt> otherwise 156 */ 157 public boolean isAlwaysUseQuotes() { 158 return alwaysUseQuotes; 159 } 160 161 /** 162 * Defines whether all parameter values must be enclosed in quotation 163 * marks, even if they do not contain any special characters 164 * 165 * @param alwaysUseQuotes 166 */ 167 public void setAlwaysUseQuotes(boolean alwaysUseQuotes) { 168 this.alwaysUseQuotes = alwaysUseQuotes; 169 } 170 171 /** 172 * Formats the given parameter value using formatting rules defined 173 * in RFC 2616 174 * 175 * @param buffer output buffer 176 * @param value the parameter value to be formatted 177 * @param alwaysUseQuotes <tt>true</tt> if the parameter value must 178 * be enclosed in quotation marks, even if it does not contain any special 179 * characters<tt>, false</tt> only if the parameter value contains 180 * potentially unsafe special characters 181 */ 182 public static void formatValue( 183 final StringBuffer buffer, final String value, boolean alwaysUseQuotes) { 184 if (buffer == null) { 185 throw new IllegalArgumentException("String buffer may not be null"); 186 } 187 if (value == null) { 188 throw new IllegalArgumentException("Value buffer may not be null"); 189 } 190 if (alwaysUseQuotes) { 191 buffer.append('"'); 192 for (int i = 0; i < value.length(); i++) { 193 char ch = value.charAt(i); 194 if (isUnsafeChar(ch)) { 195 buffer.append('\\'); 196 } 197 buffer.append(ch); 198 } 199 buffer.append('"'); 200 } else { 201 int offset = buffer.length(); 202 boolean unsafe = false; 203 for (int i = 0; i < value.length(); i++) { 204 char ch = value.charAt(i); 205 if (isSeparator(ch)) { 206 unsafe = true; 207 } 208 if (isUnsafeChar(ch)) { 209 buffer.append('\\'); 210 } 211 buffer.append(ch); 212 } 213 if (unsafe) { 214 buffer.insert(offset, '"'); 215 buffer.append('"'); 216 } 217 } 218 } 219 220 /** 221 * Produces textual representaion of the attribute/value pair using 222 * formatting rules defined in RFC 2616 223 * 224 * @param buffer output buffer 225 * @param param the parameter to be formatted 226 */ 227 public void format(final StringBuffer buffer, final NameValuePair param) { 228 if (buffer == null) { 229 throw new IllegalArgumentException("String buffer may not be null"); 230 } 231 if (param == null) { 232 throw new IllegalArgumentException("Parameter may not be null"); 233 } 234 buffer.append(param.getName()); 235 String value = param.getValue(); 236 if (value != null) { 237 buffer.append("="); 238 formatValue(buffer, value, this.alwaysUseQuotes); 239 } 240 } 241 242 /** 243 * Produces textual representaion of the attribute/value pair using 244 * formatting rules defined in RFC 2616 245 * 246 * @param param the parameter to be formatted 247 * 248 * @return RFC 2616 conformant textual representaion of the 249 * attribute/value pair 250 */ 251 public String format(final NameValuePair param) { 252 StringBuffer buffer = new StringBuffer(); 253 format(buffer, param); 254 return buffer.toString(); 255 } 256 257 }