1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BasicHeaderValueFormatter.java Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,429 @@ 1.4 +/* 1.5 + * ==================================================================== 1.6 + * Licensed to the Apache Software Foundation (ASF) under one 1.7 + * or more contributor license agreements. See the NOTICE file 1.8 + * distributed with this work for additional information 1.9 + * regarding copyright ownership. The ASF licenses this file 1.10 + * to you under the Apache License, Version 2.0 (the 1.11 + * "License"); you may not use this file except in compliance 1.12 + * with the License. You may obtain a copy of the License at 1.13 + * 1.14 + * http://www.apache.org/licenses/LICENSE-2.0 1.15 + * 1.16 + * Unless required by applicable law or agreed to in writing, 1.17 + * software distributed under the License is distributed on an 1.18 + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 1.19 + * KIND, either express or implied. See the License for the 1.20 + * specific language governing permissions and limitations 1.21 + * under the License. 1.22 + * ==================================================================== 1.23 + * 1.24 + * This software consists of voluntary contributions made by many 1.25 + * individuals on behalf of the Apache Software Foundation. For more 1.26 + * information on the Apache Software Foundation, please see 1.27 + * <http://www.apache.org/>. 1.28 + * 1.29 + */ 1.30 + 1.31 +package ch.boye.httpclientandroidlib.message; 1.32 + 1.33 +import ch.boye.httpclientandroidlib.HeaderElement; 1.34 +import ch.boye.httpclientandroidlib.NameValuePair; 1.35 +import ch.boye.httpclientandroidlib.util.CharArrayBuffer; 1.36 + 1.37 +/** 1.38 + * Basic implementation for formatting header value elements. 1.39 + * Instances of this class are stateless and thread-safe. 1.40 + * Derived classes are expected to maintain these properties. 1.41 + * 1.42 + * @since 4.0 1.43 + */ 1.44 +public class BasicHeaderValueFormatter implements HeaderValueFormatter { 1.45 + 1.46 + /** 1.47 + * A default instance of this class, for use as default or fallback. 1.48 + * Note that {@link BasicHeaderValueFormatter} is not a singleton, there 1.49 + * can be many instances of the class itself and of derived classes. 1.50 + * The instance here provides non-customized, default behavior. 1.51 + */ 1.52 + public final static 1.53 + BasicHeaderValueFormatter DEFAULT = new BasicHeaderValueFormatter(); 1.54 + 1.55 + 1.56 + /** 1.57 + * Special characters that can be used as separators in HTTP parameters. 1.58 + * These special characters MUST be in a quoted string to be used within 1.59 + * a parameter value . 1.60 + */ 1.61 + public final static String SEPARATORS = " ;,:@()<>\\\"/[]?={}\t"; 1.62 + 1.63 + 1.64 + /** 1.65 + * Unsafe special characters that must be escaped using the backslash 1.66 + * character 1.67 + */ 1.68 + public final static String UNSAFE_CHARS = "\"\\"; 1.69 + 1.70 + 1.71 + 1.72 + // public default constructor 1.73 + 1.74 + 1.75 + 1.76 + /** 1.77 + * Formats an array of header elements. 1.78 + * 1.79 + * @param elems the header elements to format 1.80 + * @param quote <code>true</code> to always format with quoted values, 1.81 + * <code>false</code> to use quotes only when necessary 1.82 + * @param formatter the formatter to use, or <code>null</code> 1.83 + * for the {@link #DEFAULT default} 1.84 + * 1.85 + * @return the formatted header elements 1.86 + */ 1.87 + public final static 1.88 + String formatElements(final HeaderElement[] elems, 1.89 + final boolean quote, 1.90 + HeaderValueFormatter formatter) { 1.91 + if (formatter == null) 1.92 + formatter = BasicHeaderValueFormatter.DEFAULT; 1.93 + return formatter.formatElements(null, elems, quote).toString(); 1.94 + } 1.95 + 1.96 + 1.97 + // non-javadoc, see interface HeaderValueFormatter 1.98 + public CharArrayBuffer formatElements(CharArrayBuffer buffer, 1.99 + final HeaderElement[] elems, 1.100 + final boolean quote) { 1.101 + if (elems == null) { 1.102 + throw new IllegalArgumentException 1.103 + ("Header element array must not be null."); 1.104 + } 1.105 + 1.106 + int len = estimateElementsLen(elems); 1.107 + if (buffer == null) { 1.108 + buffer = new CharArrayBuffer(len); 1.109 + } else { 1.110 + buffer.ensureCapacity(len); 1.111 + } 1.112 + 1.113 + for (int i=0; i<elems.length; i++) { 1.114 + if (i > 0) { 1.115 + buffer.append(", "); 1.116 + } 1.117 + formatHeaderElement(buffer, elems[i], quote); 1.118 + } 1.119 + 1.120 + return buffer; 1.121 + } 1.122 + 1.123 + 1.124 + /** 1.125 + * Estimates the length of formatted header elements. 1.126 + * 1.127 + * @param elems the header elements to format, or <code>null</code> 1.128 + * 1.129 + * @return a length estimate, in number of characters 1.130 + */ 1.131 + protected int estimateElementsLen(final HeaderElement[] elems) { 1.132 + if ((elems == null) || (elems.length < 1)) 1.133 + return 0; 1.134 + 1.135 + int result = (elems.length-1) * 2; // elements separated by ", " 1.136 + for (int i=0; i<elems.length; i++) { 1.137 + result += estimateHeaderElementLen(elems[i]); 1.138 + } 1.139 + 1.140 + return result; 1.141 + } 1.142 + 1.143 + 1.144 + 1.145 + /** 1.146 + * Formats a header element. 1.147 + * 1.148 + * @param elem the header element to format 1.149 + * @param quote <code>true</code> to always format with quoted values, 1.150 + * <code>false</code> to use quotes only when necessary 1.151 + * @param formatter the formatter to use, or <code>null</code> 1.152 + * for the {@link #DEFAULT default} 1.153 + * 1.154 + * @return the formatted header element 1.155 + */ 1.156 + public final static 1.157 + String formatHeaderElement(final HeaderElement elem, 1.158 + boolean quote, 1.159 + HeaderValueFormatter formatter) { 1.160 + if (formatter == null) 1.161 + formatter = BasicHeaderValueFormatter.DEFAULT; 1.162 + return formatter.formatHeaderElement(null, elem, quote).toString(); 1.163 + } 1.164 + 1.165 + 1.166 + // non-javadoc, see interface HeaderValueFormatter 1.167 + public CharArrayBuffer formatHeaderElement(CharArrayBuffer buffer, 1.168 + final HeaderElement elem, 1.169 + final boolean quote) { 1.170 + if (elem == null) { 1.171 + throw new IllegalArgumentException 1.172 + ("Header element must not be null."); 1.173 + } 1.174 + 1.175 + int len = estimateHeaderElementLen(elem); 1.176 + if (buffer == null) { 1.177 + buffer = new CharArrayBuffer(len); 1.178 + } else { 1.179 + buffer.ensureCapacity(len); 1.180 + } 1.181 + 1.182 + buffer.append(elem.getName()); 1.183 + final String value = elem.getValue(); 1.184 + if (value != null) { 1.185 + buffer.append('='); 1.186 + doFormatValue(buffer, value, quote); 1.187 + } 1.188 + 1.189 + final int parcnt = elem.getParameterCount(); 1.190 + if (parcnt > 0) { 1.191 + for (int i=0; i<parcnt; i++) { 1.192 + buffer.append("; "); 1.193 + formatNameValuePair(buffer, elem.getParameter(i), quote); 1.194 + } 1.195 + } 1.196 + 1.197 + return buffer; 1.198 + } 1.199 + 1.200 + 1.201 + /** 1.202 + * Estimates the length of a formatted header element. 1.203 + * 1.204 + * @param elem the header element to format, or <code>null</code> 1.205 + * 1.206 + * @return a length estimate, in number of characters 1.207 + */ 1.208 + protected int estimateHeaderElementLen(final HeaderElement elem) { 1.209 + if (elem == null) 1.210 + return 0; 1.211 + 1.212 + int result = elem.getName().length(); // name 1.213 + final String value = elem.getValue(); 1.214 + if (value != null) { 1.215 + // assume quotes, but no escaped characters 1.216 + result += 3 + value.length(); // ="value" 1.217 + } 1.218 + 1.219 + final int parcnt = elem.getParameterCount(); 1.220 + if (parcnt > 0) { 1.221 + for (int i=0; i<parcnt; i++) { 1.222 + result += 2 + // ; <param> 1.223 + estimateNameValuePairLen(elem.getParameter(i)); 1.224 + } 1.225 + } 1.226 + 1.227 + return result; 1.228 + } 1.229 + 1.230 + 1.231 + 1.232 + 1.233 + /** 1.234 + * Formats a set of parameters. 1.235 + * 1.236 + * @param nvps the parameters to format 1.237 + * @param quote <code>true</code> to always format with quoted values, 1.238 + * <code>false</code> to use quotes only when necessary 1.239 + * @param formatter the formatter to use, or <code>null</code> 1.240 + * for the {@link #DEFAULT default} 1.241 + * 1.242 + * @return the formatted parameters 1.243 + */ 1.244 + public final static 1.245 + String formatParameters(final NameValuePair[] nvps, 1.246 + final boolean quote, 1.247 + HeaderValueFormatter formatter) { 1.248 + if (formatter == null) 1.249 + formatter = BasicHeaderValueFormatter.DEFAULT; 1.250 + return formatter.formatParameters(null, nvps, quote).toString(); 1.251 + } 1.252 + 1.253 + 1.254 + // non-javadoc, see interface HeaderValueFormatter 1.255 + public CharArrayBuffer formatParameters(CharArrayBuffer buffer, 1.256 + NameValuePair[] nvps, 1.257 + boolean quote) { 1.258 + if (nvps == null) { 1.259 + throw new IllegalArgumentException 1.260 + ("Parameters must not be null."); 1.261 + } 1.262 + 1.263 + int len = estimateParametersLen(nvps); 1.264 + if (buffer == null) { 1.265 + buffer = new CharArrayBuffer(len); 1.266 + } else { 1.267 + buffer.ensureCapacity(len); 1.268 + } 1.269 + 1.270 + for (int i = 0; i < nvps.length; i++) { 1.271 + if (i > 0) { 1.272 + buffer.append("; "); 1.273 + } 1.274 + formatNameValuePair(buffer, nvps[i], quote); 1.275 + } 1.276 + 1.277 + return buffer; 1.278 + } 1.279 + 1.280 + 1.281 + /** 1.282 + * Estimates the length of formatted parameters. 1.283 + * 1.284 + * @param nvps the parameters to format, or <code>null</code> 1.285 + * 1.286 + * @return a length estimate, in number of characters 1.287 + */ 1.288 + protected int estimateParametersLen(final NameValuePair[] nvps) { 1.289 + if ((nvps == null) || (nvps.length < 1)) 1.290 + return 0; 1.291 + 1.292 + int result = (nvps.length-1) * 2; // "; " between the parameters 1.293 + for (int i=0; i<nvps.length; i++) { 1.294 + result += estimateNameValuePairLen(nvps[i]); 1.295 + } 1.296 + 1.297 + return result; 1.298 + } 1.299 + 1.300 + 1.301 + /** 1.302 + * Formats a name-value pair. 1.303 + * 1.304 + * @param nvp the name-value pair to format 1.305 + * @param quote <code>true</code> to always format with a quoted value, 1.306 + * <code>false</code> to use quotes only when necessary 1.307 + * @param formatter the formatter to use, or <code>null</code> 1.308 + * for the {@link #DEFAULT default} 1.309 + * 1.310 + * @return the formatted name-value pair 1.311 + */ 1.312 + public final static 1.313 + String formatNameValuePair(final NameValuePair nvp, 1.314 + final boolean quote, 1.315 + HeaderValueFormatter formatter) { 1.316 + if (formatter == null) 1.317 + formatter = BasicHeaderValueFormatter.DEFAULT; 1.318 + return formatter.formatNameValuePair(null, nvp, quote).toString(); 1.319 + } 1.320 + 1.321 + 1.322 + // non-javadoc, see interface HeaderValueFormatter 1.323 + public CharArrayBuffer formatNameValuePair(CharArrayBuffer buffer, 1.324 + final NameValuePair nvp, 1.325 + final boolean quote) { 1.326 + if (nvp == null) { 1.327 + throw new IllegalArgumentException 1.328 + ("NameValuePair must not be null."); 1.329 + } 1.330 + 1.331 + int len = estimateNameValuePairLen(nvp); 1.332 + if (buffer == null) { 1.333 + buffer = new CharArrayBuffer(len); 1.334 + } else { 1.335 + buffer.ensureCapacity(len); 1.336 + } 1.337 + 1.338 + buffer.append(nvp.getName()); 1.339 + final String value = nvp.getValue(); 1.340 + if (value != null) { 1.341 + buffer.append('='); 1.342 + doFormatValue(buffer, value, quote); 1.343 + } 1.344 + 1.345 + return buffer; 1.346 + } 1.347 + 1.348 + 1.349 + /** 1.350 + * Estimates the length of a formatted name-value pair. 1.351 + * 1.352 + * @param nvp the name-value pair to format, or <code>null</code> 1.353 + * 1.354 + * @return a length estimate, in number of characters 1.355 + */ 1.356 + protected int estimateNameValuePairLen(final NameValuePair nvp) { 1.357 + if (nvp == null) 1.358 + return 0; 1.359 + 1.360 + int result = nvp.getName().length(); // name 1.361 + final String value = nvp.getValue(); 1.362 + if (value != null) { 1.363 + // assume quotes, but no escaped characters 1.364 + result += 3 + value.length(); // ="value" 1.365 + } 1.366 + return result; 1.367 + } 1.368 + 1.369 + 1.370 + /** 1.371 + * Actually formats the value of a name-value pair. 1.372 + * This does not include a leading = character. 1.373 + * Called from {@link #formatNameValuePair formatNameValuePair}. 1.374 + * 1.375 + * @param buffer the buffer to append to, never <code>null</code> 1.376 + * @param value the value to append, never <code>null</code> 1.377 + * @param quote <code>true</code> to always format with quotes, 1.378 + * <code>false</code> to use quotes only when necessary 1.379 + */ 1.380 + protected void doFormatValue(final CharArrayBuffer buffer, 1.381 + final String value, 1.382 + boolean quote) { 1.383 + 1.384 + if (!quote) { 1.385 + for (int i = 0; (i < value.length()) && !quote; i++) { 1.386 + quote = isSeparator(value.charAt(i)); 1.387 + } 1.388 + } 1.389 + 1.390 + if (quote) { 1.391 + buffer.append('"'); 1.392 + } 1.393 + for (int i = 0; i < value.length(); i++) { 1.394 + char ch = value.charAt(i); 1.395 + if (isUnsafe(ch)) { 1.396 + buffer.append('\\'); 1.397 + } 1.398 + buffer.append(ch); 1.399 + } 1.400 + if (quote) { 1.401 + buffer.append('"'); 1.402 + } 1.403 + } 1.404 + 1.405 + 1.406 + /** 1.407 + * Checks whether a character is a {@link #SEPARATORS separator}. 1.408 + * 1.409 + * @param ch the character to check 1.410 + * 1.411 + * @return <code>true</code> if the character is a separator, 1.412 + * <code>false</code> otherwise 1.413 + */ 1.414 + protected boolean isSeparator(char ch) { 1.415 + return SEPARATORS.indexOf(ch) >= 0; 1.416 + } 1.417 + 1.418 + 1.419 + /** 1.420 + * Checks whether a character is {@link #UNSAFE_CHARS unsafe}. 1.421 + * 1.422 + * @param ch the character to check 1.423 + * 1.424 + * @return <code>true</code> if the character is unsafe, 1.425 + * <code>false</code> otherwise 1.426 + */ 1.427 + protected boolean isUnsafe(char ch) { 1.428 + return UNSAFE_CHARS.indexOf(ch) >= 0; 1.429 + } 1.430 + 1.431 + 1.432 +} // class BasicHeaderValueFormatter