18b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira/* 28b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * Copyright (C) 2006 Google Inc. 38b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * 48b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * Licensed under the Apache License, Version 2.0 (the "License"); 58b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * you may not use this file except in compliance with the License. 68b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * You may obtain a copy of the License at 78b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * 88b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * http://www.apache.org/licenses/LICENSE-2.0 98b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * 108b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * Unless required by applicable law or agreed to in writing, software 118b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * distributed under the License is distributed on an "AS IS" BASIS, 128b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 138b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * See the License for the specific language governing permissions and 148b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * limitations under the License. 158b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira */ 1630e2c24b056542f3b1b438aeb798305d1226d0c8Andy Huangpackage com.android.mail.lib.base; 178b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 1830e2c24b056542f3b1b438aeb798305d1226d0c8Andy Huangimport static com.android.mail.lib.base.Preconditions.checkNotNull; 198b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 208b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereiraimport java.io.IOException; 218b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 228b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira/** 238b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * Utility functions for dealing with {@code CharEscaper}s, and some commonly 248b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * used {@code CharEscaper} instances. 258b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * 268b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * @author sven@google.com (Sven Mawson) 278b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * @author laurence@google.com (Laurence Gonsalves) 288b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira */ 298b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereirapublic final class CharEscapers { 308b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira private CharEscapers() {} 318b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 328b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira // TODO(matevossian): To implementors of escapers -- 338b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira // For each xxxEscaper method, please add links to external 348b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira // reference pages that we consider authoritative for what 358b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira // that escaper should exactly be doing. 368b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 378b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira /** 388b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * Performs no escaping. 398b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira */ 408b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira private static final CharEscaper NULL_ESCAPER = new CharEscaper() { 418b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira @Override 428b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira public String escape(String string) { 438b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira checkNotNull(string); 448b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira return string; 458b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira } 468b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 478b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira @Override 488b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira public Appendable escape(final Appendable out) { 498b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira checkNotNull(out); 508b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 518b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira // we can't simply return out because the CharEscaper contract says that 528b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira // the returned Appendable will throw a NullPointerException if asked to 538b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira // append null. 548b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira return new Appendable() { 558b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira @Override public Appendable append(CharSequence csq) throws IOException { 568b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira checkNotNull(csq); 578b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira out.append(csq); 588b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira return this; 598b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira } 608b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 618b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira @Override public Appendable append(CharSequence csq, int start, int end) 628b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira throws IOException { 638b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira checkNotNull(csq); 648b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira out.append(csq, start, end); 658b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira return this; 668b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira } 678b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 688b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira @Override public Appendable append(char c) throws IOException { 698b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira out.append(c); 708b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira return this; 718b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira } 728b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira }; 738b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira } 748b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 758b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira @Override 768b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira protected char[] escape(char c) { 778b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira return null; 788b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira } 798b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira }; 808b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 818b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira /** 828b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * Returns a {@link CharEscaper} that does no escaping. 838b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira */ 848b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira public static CharEscaper nullEscaper() { 858b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira return NULL_ESCAPER; 868b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira } 878b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 888b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira /** 898b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * Returns a {@link CharEscaper} instance that escapes special characters in a 908b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * string so it can safely be included in an XML document in either element 918b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * content or attribute values. 928b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * 938b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <p><b>Note</b></p>: silently removes null-characters and control 948b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * characters, as there is no way to represent them in XML. 958b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira */ 968b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira public static CharEscaper xmlEscaper() { 978b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira return XML_ESCAPER; 988b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira } 998b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 1008b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira /** 1018b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * Escapes special characters from a string so it can safely be included in an 1028b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * XML document in either element content or attribute values. Also removes 1038b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * null-characters and control characters, as there is no way to represent 1048b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * them in XML. 1058b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira */ 1068b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira private static final CharEscaper XML_ESCAPER = newBasicXmlEscapeBuilder() 1078b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('"', """) 1088b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\'', "'") 1098b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .toEscaper(); 1108b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 1118b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira /** 1128b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * Returns a {@link CharEscaper} instance that escapes special characters in a 1138b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * string so it can safely be included in an XML document in element content. 1148b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * 1158b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <p><b>Note</b></p>: double and single quotes are not escaped, so it is not 1168b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * safe to use this escaper to escape attribute values. Use the 1178b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * {@link #xmlEscaper()} escaper to escape attribute values or if you are 1188b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * unsure. Also silently removes non-whitespace control characters, as there 1198b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * is no way to represent them in XML. 1208b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira */ 1218b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira public static CharEscaper xmlContentEscaper() { 1228b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira return XML_CONTENT_ESCAPER; 1238b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira } 1248b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 1258b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira /** 1268b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * Escapes special characters from a string so it can safely be included in an 1278b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * XML document in element content. Note that quotes are <em>not</em> 1288b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * escaped, so <em>this is not safe for use in attribute values</em>. Use 1298b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * {@link #XML_ESCAPER} for attribute values, or if you are unsure. Also 1308b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * removes non-whitespace control characters, as there is no way to represent 1318b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * them in XML. 1328b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira */ 1338b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira private static final CharEscaper XML_CONTENT_ESCAPER = 1348b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira newBasicXmlEscapeBuilder().toEscaper(); 1358b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 1368b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira /** 1378b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * Returns a {@link CharEscaper} instance that escapes special characters in a 1388b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * string so it can safely be included in an HTML document in either element 1398b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * content or attribute values. 1408b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * 1418b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <p><b>Note</b></p>: alters non-ASCII and control characters. 1428b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * 1438b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * The entity list was taken from: 1448b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <a href="http://www.w3.org/TR/html4/sgml/entities.html">here</a> 1458b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira */ 1468b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira public static CharEscaper htmlEscaper() { 1478b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira return HtmlEscaperHolder.HTML_ESCAPER; 1488b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira } 1498b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 1508b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira /** 1518b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * A lazy initialization holder for HTML_ESCAPER. 1528b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira */ 1538b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira private static class HtmlEscaperHolder { 1548b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira private static final CharEscaper HTML_ESCAPER 1558b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira = new HtmlCharEscaper(new CharEscaperBuilder() 1568b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('"', """) 1578b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\'', "'") 1588b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('&', "&") 1598b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('<', "<") 1608b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('>', ">") 1618b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00A0', " ") 1628b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00A1', "¡") 1638b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00A2', "¢") 1648b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00A3', "£") 1658b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00A4', "¤") 1668b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00A5', "¥") 1678b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00A6', "¦") 1688b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00A7', "§") 1698b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00A8', "¨") 1708b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00A9', "©") 1718b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00AA', "ª") 1728b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00AB', "«") 1738b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00AC', "¬") 1748b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00AD', "­") 1758b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00AE', "®") 1768b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00AF', "¯") 1778b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00B0', "°") 1788b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00B1', "±") 1798b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00B2', "²") 1808b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00B3', "³") 1818b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00B4', "´") 1828b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00B5', "µ") 1838b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00B6', "¶") 1848b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00B7', "·") 1858b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00B8', "¸") 1868b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00B9', "¹") 1878b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00BA', "º") 1888b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00BB', "»") 1898b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00BC', "¼") 1908b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00BD', "½") 1918b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00BE', "¾") 1928b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00BF', "¿") 1938b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00C0', "À") 1948b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00C1', "Á") 1958b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00C2', "Â") 1968b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00C3', "Ã") 1978b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00C4', "Ä") 1988b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00C5', "Å") 1998b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00C6', "Æ") 2008b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00C7', "Ç") 2018b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00C8', "È") 2028b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00C9', "É") 2038b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00CA', "Ê") 2048b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00CB', "Ë") 2058b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00CC', "Ì") 2068b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00CD', "Í") 2078b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00CE', "Î") 2088b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00CF', "Ï") 2098b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00D0', "Ð") 2108b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00D1', "Ñ") 2118b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00D2', "Ò") 2128b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00D3', "Ó") 2138b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00D4', "Ô") 2148b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00D5', "Õ") 2158b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00D6', "Ö") 2168b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00D7', "×") 2178b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00D8', "Ø") 2188b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00D9', "Ù") 2198b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00DA', "Ú") 2208b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00DB', "Û") 2218b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00DC', "Ü") 2228b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00DD', "Ý") 2238b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00DE', "Þ") 2248b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00DF', "ß") 2258b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00E0', "à") 2268b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00E1', "á") 2278b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00E2', "â") 2288b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00E3', "ã") 2298b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00E4', "ä") 2308b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00E5', "å") 2318b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00E6', "æ") 2328b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00E7', "ç") 2338b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00E8', "è") 2348b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00E9', "é") 2358b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00EA', "ê") 2368b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00EB', "ë") 2378b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00EC', "ì") 2388b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00ED', "í") 2398b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00EE', "î") 2408b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00EF', "ï") 2418b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00F0', "ð") 2428b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00F1', "ñ") 2438b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00F2', "ò") 2448b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00F3', "ó") 2458b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00F4', "ô") 2468b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00F5', "õ") 2478b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00F6', "ö") 2488b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00F7', "÷") 2498b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00F8', "ø") 2508b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00F9', "ù") 2518b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00FA', "ú") 2528b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00FB', "û") 2538b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00FC', "ü") 2548b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00FD', "ý") 2558b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00FE', "þ") 2568b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u00FF', "ÿ") 2578b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u0152', "Œ") 2588b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u0153', "œ") 2598b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u0160', "Š") 2608b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u0161', "š") 2618b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u0178', "Ÿ") 2628b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u0192', "ƒ") 2638b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u02C6', "ˆ") 2648b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u02DC', "˜") 2658b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u0391', "Α") 2668b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u0392', "Β") 2678b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u0393', "Γ") 2688b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u0394', "Δ") 2698b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u0395', "Ε") 2708b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u0396', "Ζ") 2718b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u0397', "Η") 2728b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u0398', "Θ") 2738b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u0399', "Ι") 2748b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u039A', "Κ") 2758b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u039B', "Λ") 2768b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u039C', "Μ") 2778b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u039D', "Ν") 2788b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u039E', "Ξ") 2798b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u039F', "Ο") 2808b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u03A0', "Π") 2818b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u03A1', "Ρ") 2828b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u03A3', "Σ") 2838b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u03A4', "Τ") 2848b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u03A5', "Υ") 2858b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u03A6', "Φ") 2868b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u03A7', "Χ") 2878b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u03A8', "Ψ") 2888b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u03A9', "Ω") 2898b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u03B1', "α") 2908b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u03B2', "β") 2918b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u03B3', "γ") 2928b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u03B4', "δ") 2938b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u03B5', "ε") 2948b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u03B6', "ζ") 2958b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u03B7', "η") 2968b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u03B8', "θ") 2978b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u03B9', "ι") 2988b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u03BA', "κ") 2998b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u03BB', "λ") 3008b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u03BC', "μ") 3018b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u03BD', "ν") 3028b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u03BE', "ξ") 3038b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u03BF', "ο") 3048b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u03C0', "π") 3058b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u03C1', "ρ") 3068b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u03C2', "ς") 3078b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u03C3', "σ") 3088b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u03C4', "τ") 3098b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u03C5', "υ") 3108b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u03C6', "φ") 3118b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u03C7', "χ") 3128b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u03C8', "ψ") 3138b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u03C9', "ω") 3148b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u03D1', "ϑ") 3158b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u03D2', "ϒ") 3168b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u03D6', "ϖ") 3178b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u2002', " ") 3188b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u2003', " ") 3198b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u2009', " ") 3208b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u200C', "‌") 3218b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u200D', "‍") 3228b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u200E', "‎") 3238b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u200F', "‏") 3248b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u2013', "–") 3258b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u2014', "—") 3268b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u2018', "‘") 3278b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u2019', "’") 3288b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u201A', "‚") 3298b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u201C', "“") 3308b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u201D', "”") 3318b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u201E', "„") 3328b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u2020', "†") 3338b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u2021', "‡") 3348b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u2022', "•") 3358b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u2026', "…") 3368b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u2030', "‰") 3378b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u2032', "′") 3388b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u2033', "″") 3398b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u2039', "‹") 3408b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u203A', "›") 3418b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u203E', "‾") 3428b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u2044', "⁄") 3438b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u20AC', "€") 3448b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u2111', "ℑ") 3458b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u2118', "℘") 3468b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u211C', "ℜ") 3478b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u2122', "™") 3488b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u2135', "ℵ") 3498b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u2190', "←") 3508b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u2191', "↑") 3518b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u2192', "→") 3528b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u2193', "↓") 3538b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u2194', "↔") 3548b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u21B5', "↵") 3558b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u21D0', "⇐") 3568b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u21D1', "⇑") 3578b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u21D2', "⇒") 3588b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u21D3', "⇓") 3598b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u21D4', "⇔") 3608b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u2200', "∀") 3618b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u2202', "∂") 3628b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u2203', "∃") 3638b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u2205', "∅") 3648b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u2207', "∇") 3658b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u2208', "∈") 3668b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u2209', "∉") 3678b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u220B', "∋") 3688b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u220F', "∏") 3698b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u2211', "∑") 3708b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u2212', "−") 3718b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u2217', "∗") 3728b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u221A', "√") 3738b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u221D', "∝") 3748b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u221E', "∞") 3758b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u2220', "∠") 3768b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u2227', "∧") 3778b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u2228', "∨") 3788b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u2229', "∩") 3798b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u222A', "∪") 3808b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u222B', "∫") 3818b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u2234', "∴") 3828b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u223C', "∼") 3838b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u2245', "≅") 3848b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u2248', "≈") 3858b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u2260', "≠") 3868b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u2261', "≡") 3878b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u2264', "≤") 3888b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u2265', "≥") 3898b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u2282', "⊂") 3908b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u2283', "⊃") 3918b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u2284', "⊄") 3928b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u2286', "⊆") 3938b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u2287', "⊇") 3948b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u2295', "⊕") 3958b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u2297', "⊗") 3968b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u22A5', "⊥") 3978b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u22C5', "⋅") 3988b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u2308', "⌈") 3998b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u2309', "⌉") 4008b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u230A', "⌊") 4018b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u230B', "⌋") 4028b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u2329', "⟨") 4038b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u232A', "⟩") 4048b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u25CA', "◊") 4058b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u2660', "♠") 4068b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u2663', "♣") 4078b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u2665', "♥") 4088b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\u2666', "♦") 4098b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .toArray()); 4108b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira } 4118b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 4128b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira /** 4138b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * Returns a {@link CharEscaper} instance that escapes special characters in a 4148b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * string so it can safely be included in an HTML document in either element 4158b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * content or attribute values. 4168b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * 4178b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <p><b>Note</b></p>: does not alter non-ASCII and control characters. 4188b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira */ 4198b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira public static CharEscaper asciiHtmlEscaper() { 4208b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira return ASCII_HTML_ESCAPER; 4218b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira } 4228b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 4238b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira /** 4248b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * Escapes special characters from a string so it can safely be included in an 4258b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * HTML document in either element content or attribute values. Does 4268b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <em>not</em> alter non-ASCII characters or control characters. 4278b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira */ 4288b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira private static final CharEscaper ASCII_HTML_ESCAPER = new CharEscaperBuilder() 4298b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('"', """) 4308b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\'', "'") 4318b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('&', "&") 4328b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('<', "<") 4338b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('>', ">") 4348b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .toEscaper(); 4358b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 4368b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira /** 4378b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * Returns an {@link Escaper} instance that escapes Java chars so they can be 4388b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * safely included in URIs. For details on escaping URIs, see section 2.4 of 4398b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <a href="http://www.ietf.org/rfc/rfc2396.txt">RFC 2396</a>. 4408b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * 4418b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <p>When encoding a String, the following rules apply: 4428b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <ul> 4438b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <li>The alphanumeric characters "a" through "z", "A" through "Z" and "0" 4448b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * through "9" remain the same. 4458b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <li>The special characters ".", "-", "*", and "_" remain the same. 4468b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <li>The space character " " is converted into a plus sign "+". 4478b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <li>All other characters are converted into one or more bytes using UTF-8 4488b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * encoding and each byte is then represented by the 3-character string 4498b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * "%XY", where "XY" is the two-digit, uppercase, hexadecimal 4508b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * representation of the byte value. 4518b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <ul> 4528b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * 4538b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <p><b>Note</b>: Unlike other escapers, URI escapers produce uppercase 4548b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * hexadecimal sequences. From <a href="http://www.ietf.org/rfc/rfc3986.txt"> 4558b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * RFC 3986</a>:<br> 4568b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <i>"URI producers and normalizers should use uppercase hexadecimal digits 4578b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * for all percent-encodings."</i> 4588b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * 4598b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <p>This escaper has identical behavior to (but is potentially much faster 4608b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * than): 4618b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <ul> 4628b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <li>{@link com.google.httputil.FastURLEncoder#encode(String)} 4638b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <li>{@link com.google.httputil.FastURLEncoder#encode(String,String)} 4648b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * with the encoding name "UTF-8" 4658b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <li>{@link java.net.URLEncoder#encode(String, String)} 4668b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * with the encoding name "UTF-8" 4678b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * </ul> 4688b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * 4698b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <p>This method is equivalent to {@code uriEscaper(true)}. 4708b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira */ 4718b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira public static Escaper uriEscaper() { 4728b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira return uriEscaper(true); 4738b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira } 4748b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 4758b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira /** 4768b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * Returns an {@link Escaper} instance that escapes Java chars so they can be 4778b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * safely included in URI path segments. For details on escaping URIs, see 4788b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * section 2.4 of <a href="http://www.ietf.org/rfc/rfc3986.txt">RFC 3986</a>. 4798b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * 4808b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <p>When encoding a String, the following rules apply: 4818b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <ul> 4828b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <li>The alphanumeric characters "a" through "z", "A" through "Z" and "0" 4838b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * through "9" remain the same. 4848b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <li>The unreserved characters ".", "-", "~", and "_" remain the same. 4858b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <li>The general delimiters "@" and ":" remain the same. 4868b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <li>The subdelimiters "!", "$", "&", "'", "(", ")", "*", ",", ";", 4878b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * and "=" remain the same. 4888b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <li>The space character " " is converted into %20. 4898b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <li>All other characters are converted into one or more bytes using UTF-8 4908b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * encoding and each byte is then represented by the 3-character string 4918b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * "%XY", where "XY" is the two-digit, uppercase, hexadecimal 4928b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * representation of the byte value. 4938b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * </ul> 4948b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * 4958b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <p><b>Note</b>: Unlike other escapers, URI escapers produce uppercase 4968b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * hexadecimal sequences. From <a href="http://www.ietf.org/rfc/rfc3986.txt"> 4978b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * RFC 3986</a>:<br> 4988b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <i>"URI producers and normalizers should use uppercase hexadecimal digits 4998b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * for all percent-encodings."</i> 5008b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira */ 5018b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira public static Escaper uriPathEscaper() { 5028b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira return URI_PATH_ESCAPER; 5038b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira } 5048b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 5058b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira /** 5068b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * Returns an {@link Escaper} instance that escapes Java chars so they can be 5078b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * safely included in URI query string segments. When the query string 5088b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * consists of a sequence of name=value pairs separated by &, the names 5098b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * and values should be individually encoded. If you escape an entire query 5108b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * string in one pass with this escaper, then the "=" and "&" characters 5118b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * used as separators will also be escaped. 5128b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * 5138b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <p>This escaper is also suitable for escaping fragment identifiers. 5148b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * 5158b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <p>For details on escaping URIs, see 5168b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * section 2.4 of <a href="http://www.ietf.org/rfc/rfc3986.txt">RFC 3986</a>. 5178b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * 5188b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <p>When encoding a String, the following rules apply: 5198b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <ul> 5208b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <li>The alphanumeric characters "a" through "z", "A" through "Z" and "0" 5218b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * through "9" remain the same. 5228b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <li>The unreserved characters ".", "-", "~", and "_" remain the same. 5238b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <li>The general delimiters "@" and ":" remain the same. 5248b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <li>The path delimiters "/" and "?" remain the same. 5258b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <li>The subdelimiters "!", "$", "'", "(", ")", "*", ",", and ";", 5268b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * remain the same. 5278b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <li>The space character " " is converted into %20. 5288b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <li>The equals sign "=" is converted into %3D. 5298b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <li>The ampersand "&" is converted into %26. 5308b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <li>All other characters are converted into one or more bytes using UTF-8 5318b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * encoding and each byte is then represented by the 3-character string 5328b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * "%XY", where "XY" is the two-digit, uppercase, hexadecimal 5338b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * representation of the byte value. 5348b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * </ul> 5358b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * 5368b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <p><b>Note</b>: Unlike other escapers, URI escapers produce uppercase 5378b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * hexadecimal sequences. From <a href="http://www.ietf.org/rfc/rfc3986.txt"> 5388b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * RFC 3986</a>:<br> 5398b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <i>"URI producers and normalizers should use uppercase hexadecimal digits 5408b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * for all percent-encodings."</i> 5418b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * 5428b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <p>This method is equivalent to {@code uriQueryStringEscaper(false)}. 5438b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira */ 5448b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira public static Escaper uriQueryStringEscaper() { 5458b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira return uriQueryStringEscaper(false); 5468b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira } 5478b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 5488b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira /** 5498b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * Returns a {@link Escaper} instance that escapes Java characters so they can 5508b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * be safely included in URIs. For details on escaping URIs, see section 2.4 5518b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * of <a href="http://www.ietf.org/rfc/rfc2396.txt">RFC 2396</a>. 5528b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * 5538b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <p>When encoding a String, the following rules apply: 5548b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <ul> 5558b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <li>The alphanumeric characters "a" through "z", "A" through "Z" and "0" 5568b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * through "9" remain the same. 5578b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <li>The special characters ".", "-", "*", and "_" remain the same. 5588b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <li>If {@code plusForSpace} was specified, the space character " " is 5598b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * converted into a plus sign "+". Otherwise it is converted into "%20". 5608b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <li>All other characters are converted into one or more bytes using UTF-8 5618b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * encoding and each byte is then represented by the 3-character string 5628b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * "%XY", where "XY" is the two-digit, uppercase, hexadecimal 5638b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * representation of the byte value. 5648b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * </ul> 5658b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * 5668b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <p><b>Note</b>: Unlike other escapers, URI escapers produce uppercase 5678b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * hexadecimal sequences. From <a href="http://www.ietf.org/rfc/rfc3986.txt"> 5688b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * RFC 3986</a>:<br> 5698b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <i>"URI producers and normalizers should use uppercase hexadecimal digits 5708b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * for all percent-encodings."</i> 5718b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * 5728b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * @param plusForSpace if {@code true} space is escaped to {@code +} otherwise 5738b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * it is escaped to {@code %20}. Although common, the escaping of 5748b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * spaces as plus signs has a very ambiguous status in the relevant 5758b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * specifications. You should prefer {@code %20} unless you are doing 5768b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * exact character-by-character comparisons of URLs and backwards 5778b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * compatibility requires you to use plus signs. 5788b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * 5798b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * @see #uriEscaper() 5808b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira */ 5818b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira public static Escaper uriEscaper(boolean plusForSpace) { 5828b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira return plusForSpace ? URI_ESCAPER : URI_ESCAPER_NO_PLUS; 5838b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira } 5848b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 5858b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira /** 5868b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * Returns an {@link Escaper} instance that escapes Java chars so they can be 5878b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * safely included in URI query string segments. When the query string 5888b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * consists of a sequence of name=value pairs separated by &, the names 5898b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * and values should be individually encoded. If you escape an entire query 5908b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * string in one pass with this escaper, then the "=" and "&" characters 5918b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * used as separators will also be escaped. 5928b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * 5938b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <p>This escaper is also suitable for escaping fragment identifiers. 5948b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * 5958b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <p>For details on escaping URIs, see 5968b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * section 2.4 of <a href="http://www.ietf.org/rfc/rfc3986.txt">RFC 3986</a>. 5978b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * 5988b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <p>When encoding a String, the following rules apply: 5998b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <ul> 6008b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <li>The alphanumeric characters "a" through "z", "A" through "Z" and "0" 6018b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * through "9" remain the same. 6028b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <li>The unreserved characters ".", "-", "~", and "_" remain the same. 6038b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <li>The general delimiters "@" and ":" remain the same. 6048b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <li>The path delimiters "/" and "?" remain the same. 6058b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <li>The subdelimiters "!", "$", "'", "(", ")", "*", ",", and ";", 6068b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * remain the same. 6078b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <li>If {@code plusForSpace} was specified, the space character " " is 6088b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * converted into a plus sign "+". Otherwise it is converted into "%20". 6098b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <li>The equals sign "=" is converted into %3D. 6108b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <li>The ampersand "&" is converted into %26. 6118b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <li>All other characters are converted into one or more bytes using UTF-8 6128b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * encoding and each byte is then represented by the 3-character string 6138b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * "%XY", where "XY" is the two-digit, uppercase, hexadecimal 6148b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * representation of the byte value. 6158b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * </ul> 6168b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * 6178b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <p><b>Note</b>: Unlike other escapers, URI escapers produce uppercase 6188b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * hexadecimal sequences. From <a href="http://www.ietf.org/rfc/rfc3986.txt"> 6198b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * RFC 3986</a>:<br> 6208b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <i>"URI producers and normalizers should use uppercase hexadecimal digits 6218b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * for all percent-encodings."</i> 6228b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * 6238b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * @param plusForSpace if {@code true} space is escaped to {@code +} otherwise 6248b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * it is escaped to {@code %20}. Although common, the escaping of 6258b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * spaces as plus signs has a very ambiguous status in the relevant 6268b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * specifications. You should prefer {@code %20} unless you are doing 6278b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * exact character-by-character comparisons of URLs and backwards 6288b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * compatibility requires you to use plus signs. 6298b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * 6308b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * @see #uriQueryStringEscaper() 6318b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira */ 6328b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira public static Escaper uriQueryStringEscaper(boolean plusForSpace) { 6338b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira return plusForSpace ? 6348b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira URI_QUERY_STRING_ESCAPER_WITH_PLUS : URI_QUERY_STRING_ESCAPER; 6358b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira } 6368b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 6378b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira private static final Escaper URI_ESCAPER = 6388b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira new PercentEscaper(PercentEscaper.SAFECHARS_URLENCODER, true); 6398b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 6408b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira private static final Escaper URI_ESCAPER_NO_PLUS = 6418b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira new PercentEscaper(PercentEscaper.SAFECHARS_URLENCODER, false); 6428b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 6438b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira private static final Escaper URI_PATH_ESCAPER = 6448b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira new PercentEscaper(PercentEscaper.SAFEPATHCHARS_URLENCODER, false); 6458b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 6468b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira private static final Escaper URI_QUERY_STRING_ESCAPER = 6478b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira new PercentEscaper(PercentEscaper.SAFEQUERYSTRINGCHARS_URLENCODER, false); 6488b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 6498b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira private static final Escaper URI_QUERY_STRING_ESCAPER_WITH_PLUS = 6508b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira new PercentEscaper(PercentEscaper.SAFEQUERYSTRINGCHARS_URLENCODER, true); 6518b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 6528b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira /** 6538b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * Returns a {@link Escaper} instance that escapes Java characters in a manner 6548b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * compatible with the C++ webutil/url URL class (the {@code kGoogle1Escape} 6558b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * set). 6568b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * 6578b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <p>When encoding a String, the following rules apply: 6588b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <ul> 6598b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <li>The alphanumeric characters "a" through "z", "A" through "Z" and "0" 6608b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * through "9" remain the same. 6618b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <li>The special characters "!", "(", ")", "*", "-", ".", "_", "~", ",", "/" 6628b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * and ":" remain the same. 6638b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <li>The space character " " is converted into a plus sign "+". 6648b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <li>All other characters are converted into one or more bytes using UTF-8 6658b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * encoding and each byte is then represented by the 3-character string 6668b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * "%XY", where "XY" is the two-digit, uppercase, hexadecimal 6678b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * representation of the byte value. 6688b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * </ul> 6698b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * 6708b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <p><b>Note</b>: Unlike other escapers, URI escapers produce uppercase 6718b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * hexadecimal sequences. From <a href="http://www.ietf.org/rfc/rfc3986.txt"> 6728b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * RFC 3986</a>:<br> 6738b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <i>"URI producers and normalizers should use uppercase hexadecimal digits 6748b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * for all percent-encodings."</i> 6758b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * 6768b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <p><b>Note</b>: This escaper is a special case and is <em>not 6778b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * compliant</em> with <a href="http://www.ietf.org/rfc/rfc2396.txt"> 6788b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * RFC 2396</a>. Specifically it will not escape "/", ":" and ",". This is 6798b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * only provided for certain limited use cases and you should favor using 6808b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * {@link #uriEscaper()} whenever possible. 6818b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira */ 6828b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira public static Escaper cppUriEscaper() { 6838b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira return CPP_URI_ESCAPER; 6848b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira } 6858b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 6868b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira // Based on comments from FastURLEncoder: 6878b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira // These octets mimic the ones escaped by the C++ webutil/url URL class -- 6888b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira // the kGoogle1Escape set. 6898b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira // To produce the same escaping as C++, use this set with the plusForSpace 6908b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira // option. 6918b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira // WARNING: Contrary to RFC 2396 ",", "/" and ":" are listed as safe here. 6928b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira private static final Escaper CPP_URI_ESCAPER = 6938b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira new PercentEscaper("!()*-._~,/:", true); 6948b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 6958b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira /** 6968b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * Returns a {@link CharEscaper} instance that escapes special characters in a 6978b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * string so it can safely be included in a Java string literal. 6988b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * 6998b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <p><b>Note</b></p>: does not escape single quotes, so use the escaper 7008b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * returned by {@link #javaCharEscaper()} if you are generating char 7018b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * literals or if you are unsure. 7028b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira */ 7038b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira public static CharEscaper javaStringEscaper() { 7048b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira return JAVA_STRING_ESCAPER; 7058b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira } 7068b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 7078b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira /** 7088b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * Escapes special characters from a string so it can safely be included in a 7098b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * Java string literal. Does <em>not</em> escape single-quotes, so use 7108b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * JAVA_CHAR_ESCAPE if you are generating char literals, or if you are unsure. 7118b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * 7128b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <p>Note that non-ASCII characters will be octal or Unicode escaped. 7138b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira */ 7148b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira private static final CharEscaper JAVA_STRING_ESCAPER 7158b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira = new JavaCharEscaper(new CharEscaperBuilder() 7168b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\b', "\\b") 7178b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\f', "\\f") 7188b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\n', "\\n") 7198b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\r', "\\r") 7208b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\t', "\\t") 7218b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\"', "\\\"") 7228b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\\', "\\\\") 7238b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .toArray()); 7248b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 7258b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira /** 7268b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * Returns a {@link CharEscaper} instance that escapes special characters in a 7278b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * string so it can safely be included in a Java char or string literal. The 7288b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * behavior of this escaper is the same as that of the 7298b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * {@link #javaStringEscaper()}, except it also escapes single quotes. 7308b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira */ 7318b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira public static CharEscaper javaCharEscaper() { 7328b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira return JAVA_CHAR_ESCAPER; 7338b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira } 7348b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 7358b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira /** 7368b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * Escapes special characters from a string so it can safely be included in a 7378b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * Java char literal or string literal. 7388b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * 7398b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <p>Note that non-ASCII characters will be octal or Unicode escaped. 7408b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * 7418b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <p>This is the same as {@link #JAVA_STRING_ESCAPER}, except that it escapes 7428b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * single quotes. 7438b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira */ 7448b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira private static final CharEscaper JAVA_CHAR_ESCAPER 7458b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira = new JavaCharEscaper(new CharEscaperBuilder() 7468b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\b', "\\b") 7478b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\f', "\\f") 7488b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\n', "\\n") 7498b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\r', "\\r") 7508b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\t', "\\t") 7518b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\'', "\\'") 7528b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\"', "\\\"") 7538b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\\', "\\\\") 7548b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .toArray()); 7558b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 7568b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira /** 7578b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * Returns a {@link CharEscaper} instance that replaces non-ASCII characters 7588b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * in a string with their Unicode escape sequences ({@code \\uxxxx} where 7598b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * {@code xxxx} is a hex number). Existing escape sequences won't be affected. 7608b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira */ 7618b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira public static CharEscaper javaStringUnicodeEscaper() { 7628b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira return JAVA_STRING_UNICODE_ESCAPER; 7638b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira } 7648b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 7658b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira /** 7668b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * Escapes each non-ASCII character in with its Unicode escape sequence 7678b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * {@code \\uxxxx} where {@code xxxx} is a hex number. Existing escape 7688b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * sequences won't be affected. 7698b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira */ 7708b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira private static final CharEscaper JAVA_STRING_UNICODE_ESCAPER 7718b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira = new CharEscaper() { 7728b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira @Override protected char[] escape(char c) { 7738b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira if (c <= 127) { 7748b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira return null; 7758b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira } 7768b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 7778b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira char[] r = new char[6]; 7788b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira r[5] = HEX_DIGITS[c & 15]; 7798b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira c >>>= 4; 7808b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira r[4] = HEX_DIGITS[c & 15]; 7818b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira c >>>= 4; 7828b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira r[3] = HEX_DIGITS[c & 15]; 7838b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira c >>>= 4; 7848b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira r[2] = HEX_DIGITS[c & 15]; 7858b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira r[1] = 'u'; 7868b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira r[0] = '\\'; 7878b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira return r; 7888b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira } 7898b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira }; 7908b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 7918b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira /** 7928b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * Returns a {@link CharEscaper} instance that escapes special characters from 7938b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * a string so it can safely be included in a Python string literal. Does not 7948b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * have any special handling for non-ASCII characters. 7958b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira */ 7968b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira public static CharEscaper pythonEscaper() { 7978b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira return PYTHON_ESCAPER; 7988b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira } 7998b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 8008b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira /** 8018b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * Escapes special characters in a string so it can safely be included in a 8028b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * Python string literal. Does not have any special handling for non-ASCII 8038b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * characters. 8048b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira */ 8058b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira private static final CharEscaper PYTHON_ESCAPER = new CharEscaperBuilder() 8068b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira // TODO(laurence): perhaps this should escape non-ASCII characters? 8078b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\n', "\\n") 8088b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\r', "\\r") 8098b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\t', "\\t") 8108b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\\', "\\\\") 8118b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\"', "\\\"") 8128b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\'', "\\\'") 8138b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .toEscaper(); 8148b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 8158b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira /** 8168b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * Returns a {@link CharEscaper} instance that escapes non-ASCII characters in 8178b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * a string so it can safely be included in a Javascript string literal. 8188b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * Non-ASCII characters are replaced with their ASCII javascript escape 8198b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * sequences (e.g., \\uhhhh or \xhh). 8208b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira */ 8218b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira public static CharEscaper javascriptEscaper() { 8228b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira return JAVASCRIPT_ESCAPER; 8238b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira } 8248b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 8258b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira /** 8268b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * {@code CharEscaper} to escape javascript strings. Turns all non-ASCII 8278b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * characters into ASCII javascript escape sequences (e.g., \\uhhhh or \xhh). 8288b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira */ 8298b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira private static final CharEscaper JAVASCRIPT_ESCAPER 8308b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira = new JavascriptCharEscaper(new CharEscaperBuilder() 8318b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\'', "\\x27") 8328b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('"', "\\x22") 8338b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('<', "\\x3c") 8348b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('=', "\\x3d") 8358b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('>', "\\x3e") 8368b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('&', "\\x26") 8378b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\b', "\\b") 8388b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\t', "\\t") 8398b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\n', "\\n") 8408b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\f', "\\f") 8418b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\r', "\\r") 8428b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('\\', "\\\\") 8438b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .toArray()); 8448b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 8458b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira private static CharEscaperBuilder newBasicXmlEscapeBuilder() { 8468b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira return new CharEscaperBuilder() 8478b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('&', "&") 8488b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('<', "<") 8498b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscape('>', ">") 8508b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira .addEscapes(new char[] { 8518b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira '\000', '\001', '\002', '\003', '\004', 8528b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira '\005', '\006', '\007', '\010', '\013', 8538b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira '\014', '\016', '\017', '\020', '\021', 8548b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira '\022', '\023', '\024', '\025', '\026', 8558b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira '\027', '\030', '\031', '\032', '\033', 8568b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira '\034', '\035', '\036', '\037'}, ""); 8578b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira } 8588b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 8598b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira /** 8608b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * Returns a composite {@link CharEscaper} instance that tries to escape 8618b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * characters using a primary {@code CharEscaper} first and falls back to a 8628b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * secondary one if there is no escaping. 8638b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * 8648b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <p>The returned escaper will attempt to escape each character using the 8658b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * primary escaper, and if the primary escaper has no escaping for that 8668b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * character, it will use the secondary escaper. If the secondary escaper has 8678b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * no escaping for a character either, the original character will be used. 8688b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * If the primary escaper has an escape for a character, the secondary escaper 8698b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * will not be used at all for that character; the escaped output of the 8708b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * primary is not run through the secondary. For a case where you would like 8718b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * to first escape with one escaper, and then with another, it is recommended 8728b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * that you call each escaper in order. 8738b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * 8748b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * @param primary The primary {@code CharEscaper} to use 8758b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * @param secondary The secondary {@code CharEscaper} to use if the first one 8768b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * has no escaping rule for a character 8778b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * @throws NullPointerException if any of the arguments is null 8788b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira */ 8798b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira public static CharEscaper fallThrough(CharEscaper primary, 8808b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira CharEscaper secondary) { 8818b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira checkNotNull(primary); 8828b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira checkNotNull(secondary); 8838b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira return new FallThroughCharEscaper(primary, secondary); 8848b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira } 8858b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 8868b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira /** 8878b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * A fast {@link CharEscaper} that uses an array of replacement characters and 8888b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * a range of safe characters. It overrides {@link #escape(String)} to improve 8898b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * performance. Rough benchmarking shows that this almost doubles the speed 8908b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * when processing strings that do not require escaping (providing the escape 8918b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * test itself is efficient). 8928b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira */ 8938b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira private static abstract class FastCharEscaper extends CharEscaper { 8948b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 8958b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira protected final char[][] replacements; 8968b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira protected final int replacementLength; 8978b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira protected final char safeMin; 8988b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira protected final char safeMax; 8998b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 9008b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira public FastCharEscaper(char[][] replacements, char safeMin, char safeMax) { 9018b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira this.replacements = replacements; 9028b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira this.replacementLength = replacements.length; 9038b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira this.safeMin = safeMin; 9048b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira this.safeMax = safeMax; 9058b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira } 9068b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 9078b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira /** Overridden for performance (see {@link FastCharEscaper}). */ 9088b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira @Override public String escape(String s) { 9098b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira int slen = s.length(); 9108b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira for (int index = 0; index < slen; index++) { 9118b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira char c = s.charAt(index); 9128b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira if ((c < replacementLength && replacements[c] != null) 9138b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira || c < safeMin || c > safeMax) { 9148b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira return escapeSlow(s, index); 9158b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira } 9168b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira } 9178b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira return s; 9188b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira } 9198b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira } 9208b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 9218b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira /** 9228b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * Escaper for Java character escaping, contains both an array and a 9238b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * backup function. We're not overriding the array decorator because we 9248b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * want to keep this as fast as possible, so no calls to super.escape first. 9258b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira */ 9268b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira private static class JavaCharEscaper extends FastCharEscaper { 9278b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 9288b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira public JavaCharEscaper(char[][] replacements) { 9298b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira super(replacements, ' ', '~'); 9308b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira } 9318b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 9328b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira @Override protected char[] escape(char c) { 9338b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira // First check if our array has a valid escaping. 9348b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira if (c < replacementLength) { 9358b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira char[] r = replacements[c]; 9368b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira if (r != null) { 9378b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira return r; 9388b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira } 9398b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira } 9408b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 9418b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira // This range is un-escaped. 9428b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira if (safeMin <= c && c <= safeMax) { 9438b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira return null; 9448b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira } 9458b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 9468b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira if (c <= 0xFF) { 9478b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira // Convert c to an octal-escaped string. 9488b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira // Equivalent to String.format("\\%03o", (int)c); 9498b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira char[] r = new char[4]; 9508b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira r[0] = '\\'; 9518b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira r[3] = HEX_DIGITS[c & 7]; 9528b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira c >>>= 3; 9538b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira r[2] = HEX_DIGITS[c & 7]; 9548b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira c >>>= 3; 9558b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira r[1] = HEX_DIGITS[c & 7]; 9568b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira return r; 9578b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira } 9588b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 9598b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira // Convert c to a hex-escaped string. 9608b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira // Equivalent to String.format("\\u%04x", (int)c); 9618b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira char[] r = new char[6]; 9628b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira r[0] = '\\'; 9638b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira r[1] = 'u'; 9648b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira r[5] = HEX_DIGITS[c & 15]; 9658b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira c >>>= 4; 9668b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira r[4] = HEX_DIGITS[c & 15]; 9678b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira c >>>= 4; 9688b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira r[3] = HEX_DIGITS[c & 15]; 9698b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira c >>>= 4; 9708b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira r[2] = HEX_DIGITS[c & 15]; 9718b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira return r; 9728b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira } 9738b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira } 9748b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 9758b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira /** 9768b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * Escaper for javascript character escaping, contains both an array and a 9778b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * backup function. We're not overriding the array decorator because we 9788b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * want to keep this as fast as possible, so no calls to super.escape first. 9798b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira */ 9808b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira private static class JavascriptCharEscaper extends FastCharEscaper { 9818b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 9828b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira public JavascriptCharEscaper(char[][] replacements) { 9838b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira super(replacements, ' ', '~'); 9848b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira } 9858b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 9868b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira @Override protected char[] escape(char c) { 9878b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira // First check if our array has a valid escaping. 9888b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira if (c < replacementLength) { 9898b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira char[] r = replacements[c]; 9908b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira if (r != null) { 9918b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira return r; 9928b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira } 9938b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira } 9948b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 9958b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira // This range is unescaped. 9968b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira if (safeMin <= c && c <= safeMax) { 9978b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira return null; 9988b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira } 9998b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 10008b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira // we can do a 2 digit hex escape for chars less that 0x100 10018b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira if (c < 0x100) { 10028b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira char[] r = new char[4]; 10038b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira r[3] = HEX_DIGITS[c & 0xf]; 10048b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira c >>>= 4; 10058b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira r[2] = HEX_DIGITS[c & 0xf]; 10068b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira r[1] = 'x'; 10078b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira r[0] = '\\'; 10088b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira return r; 10098b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira } 10108b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 10118b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira // 4 digit hex escape everything else 10128b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira char[] r = new char[6]; 10138b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira r[5] = HEX_DIGITS[c & 0xf]; 10148b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira c >>>= 4; 10158b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira r[4] = HEX_DIGITS[c & 0xf]; 10168b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira c >>>= 4; 10178b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira r[3] = HEX_DIGITS[c & 0xf]; 10188b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira c >>>= 4; 10198b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira r[2] = HEX_DIGITS[c & 0xf]; 10208b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira r[1] = 'u'; 10218b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira r[0] = '\\'; 10228b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira return r; 10238b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira } 10248b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira } 10258b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 10268b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira /** 10278b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * Escaper for HTML character escaping, contains both an array and a 10288b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * backup function. We're not overriding the array decorator because we 10298b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * want to keep this as fast as possible, so no calls to super.escape first. 10308b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira */ 10318b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira private static class HtmlCharEscaper extends FastCharEscaper { 10328b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 10338b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira public HtmlCharEscaper(char[][] replacements) { 10348b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira super(replacements, Character.MIN_VALUE, '~'); 10358b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira } 10368b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 10378b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira @Override protected char[] escape(char c) { 10388b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira // First check if our array has a valid escaping. 10398b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira if (c < replacementLength) { 10408b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira char[] r = replacements[c]; 10418b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira if (r != null) { 10428b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira return r; 10438b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira } 10448b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira } 10458b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 10468b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira // ~ is ASCII 126, the highest value char that does not need 10478b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira // to be escaped 10488b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira if (c <= safeMax) { 10498b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira return null; 10508b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira } 10518b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 10528b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira int index; 10538b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira if (c < 1000) { 10548b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira index = 4; 10558b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira } else if (c < 10000) { 10568b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira index = 5; 10578b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira } else { 10588b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira index = 6; 10598b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira } 10608b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira char[] result = new char[index + 2]; 10618b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira result[0] = '&'; 10628b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira result[1] = '#'; 10638b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira result[index + 1] = ';'; 10648b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 10658b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira // TODO(sven): Convert this to a sequence of shifts/additions 10668b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira // to avoid the division and modulo operators. 10678b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira int intValue = c; 10688b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira for (; index > 1; index--) { 10698b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira result[index] = HEX_DIGITS[intValue % 10]; 10708b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira intValue /= 10; 10718b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira } 10728b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira return result; 10738b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira } 10748b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira } 10758b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 10768b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira /** 10778b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * A composite {@code CharEscaper} object that tries to escape characters 10788b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * using a primary {@code CharEscaper} first and falls back to a secondary 10798b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * one if there is no escaping. 10808b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira */ 10818b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira private static class FallThroughCharEscaper extends CharEscaper { 10828b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 10838b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira private final CharEscaper primary; 10848b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira private final CharEscaper secondary; 10858b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 10868b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira public FallThroughCharEscaper(CharEscaper primary, CharEscaper secondary) { 10878b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira this.primary = primary; 10888b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira this.secondary = secondary; 10898b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira } 10908b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 10918b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira @Override 10928b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira protected char[] escape(char c) { 10938b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira char result[] = primary.escape(c); 10948b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira if (result == null) { 10958b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira result = secondary.escape(c); 10968b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira } 10978b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira return result; 10988b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira } 10998b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira } 11008b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira 11018b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira private static final char[] HEX_DIGITS = "0123456789abcdef".toCharArray(); 11028b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira}