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.helpers;
18  
19  
20  /**
21   * Utility class for transforming strings.
22   */
23  public final class Transform {
24  
25      private static final String CDATA_START = "<![CDATA[";
26      private static final String CDATA_END = "]]>";
27      private static final String CDATA_PSEUDO_END = "]]&gt;";
28      private static final String CDATA_EMBEDED_END = CDATA_END + CDATA_PSEUDO_END + CDATA_START;
29      private static final int CDATA_END_LEN = CDATA_END.length();
30  
31      private Transform() {
32      }
33  
34      /**
35       * This method takes a string which may contain HTML tags (ie,
36       * &lt;b&gt;, &lt;table&gt;, etc) and replaces any
37       * '<',  '>' , '&' or '"'
38       * characters with respective predefined entity references.
39       *
40       * @param input The text to be converted.
41       * @return The input string with the special characters replaced.
42       */
43      public static String escapeTags(final String input) {
44          //Check if the string is null, zero length or devoid of special characters
45          // if so, return what was sent in.
46  
47          if (input == null
48              || input.length() == 0
49              || (input.indexOf('"') == -1 &&
50              input.indexOf('&') == -1 &&
51              input.indexOf('<') == -1 &&
52              input.indexOf('>') == -1)) {
53              return input;
54          }
55  
56          //Use a StringBuffer in lieu of String concatenation -- it is
57          //much more efficient this way.
58  
59          StringBuilder buf = new StringBuilder(input.length() + 6);
60          char ch = ' ';
61  
62          int len = input.length();
63          for (int i = 0; i < len; i++) {
64              ch = input.charAt(i);
65              if (ch > '>') {
66                  buf.append(ch);
67              } else if (ch == '<') {
68                  buf.append("&lt;");
69              } else if (ch == '>') {
70                  buf.append("&gt;");
71              } else if (ch == '&') {
72                  buf.append("&amp;");
73              } else if (ch == '"') {
74                  buf.append("&quot;");
75              } else {
76                  buf.append(ch);
77              }
78          }
79          return buf.toString();
80      }
81  
82      /**
83       * Ensures that embeded CDEnd strings (]]>) are handled properly
84       * within message, NDC and throwable tag text.
85       *
86       * @param buf StringBuffer holding the XML data to this point.  The
87       *            initial CDStart (<![CDATA[) and final CDEnd (]]>) of the CDATA
88       *            section are the responsibility of the calling method.
89       * @param str The String that is inserted into an existing CDATA Section within buf.
90       */
91      public static void appendEscapingCDATA(final StringBuilder buf, final String str) {
92          if (str != null) {
93              int end = str.indexOf(CDATA_END);
94              if (end < 0) {
95                  buf.append(str);
96              } else {
97                  int start = 0;
98                  while (end > -1) {
99                      buf.append(str.substring(start, end));
100                     buf.append(CDATA_EMBEDED_END);
101                     start = end + CDATA_END_LEN;
102                     if (start < str.length()) {
103                         end = str.indexOf(CDATA_END, start);
104                     } else {
105                         return;
106                     }
107                 }
108                 buf.append(str.substring(start));
109             }
110         }
111     }
112 }