View Javadoc

    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements. See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache license, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License. You may obtain a copy of the License at
    8    *
    9    *      http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the license for the specific language governing permissions and
    15   * limitations under the license.
    16   */
    17  package org.apache.logging.log4j.core.util;
    18
    19  import org.apache.logging.log4j.util.Strings;
    20
    21
    22  /**
    23   * Utility class for transforming strings.
    24   */
    25  public final class Transform {
    26
    27      private static final String CDATA_START = "<![CDATA[";
    28      private static final String CDATA_END = "]]>";
    29      private static final String CDATA_PSEUDO_END = "]]&gt;";
    30      private static final String CDATA_EMBEDED_END = CDATA_END + CDATA_PSEUDO_END + CDATA_START;
    31      private static final int CDATA_END_LEN = CDATA_END.length();
    32
    33      private Transform() {
    34      }
    35
    36      /**
    37       * This method takes a string which may contain HTML tags (ie,
    38       * &lt;b&gt;, &lt;table&gt;, etc) and replaces any
    39       * '&lt;',  '&gt;' , '&amp;' or '&quot;'
    40       * characters with respective predefined entity references.
    41       *
    42       * @param input The text to be converted.
    43       * @return The input string with the special characters replaced.
    44       */
    45      public static String escapeHtmlTags(final String input) {
    46          //Check if the string is null, zero length or devoid of special characters
    47          // if so, return what was sent in.
    48
    49          if (Strings.isEmpty(input)
    50              || (input.indexOf('"') == -1 &&
    51              input.indexOf('&') == -1 &&
    52              input.indexOf('<') == -1 &&
    53              input.indexOf('>') == -1)) {
    54              return input;
    55          }
    56
    57          //Use a StringBuilder in lieu of String concatenation -- it is
    58          //much more efficient this way.
    59
    60          final StringBuilder buf = new StringBuilder(input.length() + 6);
    61          char ch = ' ';
    62
    63          final int len = input.length();
    64          for (int i = 0; i < len; i++) {
    65              ch = input.charAt(i);
    66              if (ch > '>') {
    67                  buf.append(ch);
    68              } else if (ch == '<') {
    69                  buf.append("&lt;");
    70              } else if (ch == '>') {
    71                  buf.append("&gt;");
    72              } else if (ch == '&') {
    73                  buf.append("&amp;");
    74              } else if (ch == '"') {
    75                  buf.append("&quot;");
    76              } else {
    77                  buf.append(ch);
    78              }
    79          }
    80          return buf.toString();
    81      }
    82
    83      /**
    84       * Ensures that embedded CDEnd strings (]]&gt;) are handled properly
    85       * within message, NDC and throwable tag text.
    86       *
    87       * @param buf StringBuilder holding the XML data to this point.  The
    88       *            initial CDStart (&lt;![CDATA[) and final CDEnd (]]&gt;) of the CDATA
    89       *            section are the responsibility of the calling method.
    90       * @param str The String that is inserted into an existing CDATA Section within buf.
    91       */
    92      public static void appendEscapingCData(final StringBuilder buf, final String str) {
    93          if (str != null) {
    94              int end = str.indexOf(CDATA_END);
    95              if (end < 0) {
    96                  buf.append(str);
    97              } else {
    98                  int start = 0;
    99                  while (end > -1) {
    100                     buf.append(str.substring(start, end));
    101                     buf.append(CDATA_EMBEDED_END);
    102                     start = end + CDATA_END_LEN;
    103                     if (start < str.length()) {
    104                         end = str.indexOf(CDATA_END, start);
    105                     } else {
    106                         return;
    107                     }
    108                 }
    109                 buf.append(str.substring(start));
    110             }
    111         }
    112     }
    113
    114     /**
    115      * This method takes a string which may contain JSON reserved chars and
    116      * escapes them.
    117      *
    118      * @param input The text to be converted.
    119      * @return The input string with the special characters replaced.
    120      */
    121     public static String escapeJsonControlCharacters(final String input) {
    122         // Check if the string is null, zero length or devoid of special characters
    123         // if so, return what was sent in.
    124
    125         // TODO: escaped Unicode chars.
    126
    127         if (Strings.isEmpty(input)
    128             || (input.indexOf('"') == -1 &&
    129             input.indexOf('\\') == -1 &&
    130             input.indexOf('/') == -1 &&
    131             input.indexOf('\b') == -1 &&
    132             input.indexOf('\f') == -1 &&
    133             input.indexOf('\n') == -1 &&
    134             input.indexOf('\r') == -1 &&
    135             input.indexOf('\t') == -1)) {
    136             return input;
    137         }
    138
    139         final StringBuilder buf = new StringBuilder(input.length() + 6);
    140
    141         final int len = input.length();
    142         for (int i = 0; i < len; i++) {
    143             final char ch = input.charAt(i);
    144             final String escBs = "\\";
    145             switch (ch) {
    146             case '"':
    147                 buf.append(escBs);
    148                 buf.append(ch);
    149                 break;
    150             case '\\':
    151                 buf.append(escBs);
    152                 buf.append(ch);
    153                 break;
    154             case '/':
    155                 buf.append(escBs);
    156                 buf.append(ch);
    157                 break;
    158             case '\b':
    159                 buf.append(escBs);
    160                 buf.append('b');
    161                 break;
    162             case '\f':
    163                 buf.append(escBs);
    164                 buf.append('f');
    165                 break;
    166             case '\n':
    167                 buf.append(escBs);
    168                 buf.append('n');
    169                 break;
    170             case '\r':
    171                 buf.append(escBs);
    172                 buf.append('r');
    173                 break;
    174             case '\t':
    175                 buf.append(escBs);
    176                 buf.append('t');
    177                 break;
    178             default:
    179                 buf.append(ch);
    180             }
    181         }
    182         return buf.toString();
    183     }
    184 }