1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.logging.log4j.core.pattern;
18
19 import java.util.List;
20
21 import org.apache.logging.log4j.core.LogEvent;
22 import org.apache.logging.log4j.core.config.Configuration;
23 import org.apache.logging.log4j.core.config.plugins.Plugin;
24 import org.apache.logging.log4j.core.layout.PatternLayout;
25 import org.apache.logging.log4j.util.Chars;
26 import org.apache.logging.log4j.util.EnglishEnums;
27 import org.apache.logging.log4j.util.PerformanceSensitive;
28 import org.apache.logging.log4j.util.StringBuilders;
29
30
31
32
33
34 @Plugin(name = "encode", category = PatternConverter.CATEGORY)
35 @ConverterKeys({"enc", "encode"})
36 @PerformanceSensitive("allocation")
37 public final class EncodingPatternConverter extends LogEventPatternConverter {
38
39 private final List<PatternFormatter> formatters;
40 private final EscapeFormat escapeFormat;
41
42
43
44
45
46
47
48 private EncodingPatternConverter(final List<PatternFormatter> formatters,
49 final EscapeFormat escapeFormat) {
50 super("encode", "encode");
51 this.formatters = formatters;
52 this.escapeFormat = escapeFormat;
53 }
54
55
56
57
58
59
60
61
62 public static EncodingPatternConverter newInstance(final Configuration config, final String[] options) {
63 if (options.length > 2 || options.length == 0) {
64 LOGGER.error("Incorrect number of options on escape. Expected 1 or 2, but received {}",
65 options.length);
66 return null;
67 }
68 if (options[0] == null) {
69 LOGGER.error("No pattern supplied on escape");
70 return null;
71 }
72 final EscapeFormat escapeFormat = options.length < 2 ? EscapeFormat.HTML
73 : EnglishEnums.valueOf(EscapeFormat.class, options[1], EscapeFormat.HTML);
74 final PatternParser parser = PatternLayout.createPatternParser(config);
75 final List<PatternFormatter> formatters = parser.parse(options[0]);
76 return new EncodingPatternConverter(formatters, escapeFormat);
77 }
78
79
80
81
82 @Override
83 public void format(final LogEvent event, final StringBuilder toAppendTo) {
84 final int start = toAppendTo.length();
85 for (int i = 0; i < formatters.size(); i++) {
86 formatters.get(i).format(event, toAppendTo);
87 }
88 escapeFormat.escape(toAppendTo, start);
89 }
90
91 private enum EscapeFormat {
92 HTML {
93 @Override
94 void escape(final StringBuilder toAppendTo, final int start) {
95 for (int i = toAppendTo.length() - 1; i >= start; i--) {
96 final char c = toAppendTo.charAt(i);
97 switch (c) {
98 case '\r':
99 toAppendTo.setCharAt(i, '\\');
100 toAppendTo.insert(i + 1, 'r');
101 break;
102 case '\n':
103 toAppendTo.setCharAt(i, '\\');
104 toAppendTo.insert(i + 1, 'n');
105 break;
106 case '&':
107 toAppendTo.setCharAt(i, '&');
108 toAppendTo.insert(i + 1, "amp;");
109 break;
110 case '<':
111 toAppendTo.setCharAt(i, '&');
112 toAppendTo.insert(i + 1, "lt;");
113 break;
114 case '>':
115 toAppendTo.setCharAt(i, '&');
116 toAppendTo.insert(i + 1, "gt;");
117 break;
118 case '"':
119 toAppendTo.setCharAt(i, '&');
120 toAppendTo.insert(i + 1, "quot;");
121 break;
122 case '\'':
123 toAppendTo.setCharAt(i, '&');
124 toAppendTo.insert(i + 1, "apos;");
125 break;
126 case '/':
127 toAppendTo.setCharAt(i, '&');
128 toAppendTo.insert(i + 1, "#x2F;");
129 break;
130 }
131 }
132 }
133 },
134
135
136
137
138
139
140 JSON {
141 @Override
142 void escape(final StringBuilder toAppendTo, final int start) {
143 StringBuilders.escapeJson(toAppendTo, start);
144 }
145 },
146
147 CRLF {
148 @Override
149 void escape(final StringBuilder toAppendTo, final int start) {
150 for (int i = toAppendTo.length() - 1; i >= start; i--) {
151 final char c = toAppendTo.charAt(i);
152 switch (c) {
153 case '\r':
154 toAppendTo.setCharAt(i, '\\');
155 toAppendTo.insert(i + 1, 'r');
156 break;
157 case '\n':
158 toAppendTo.setCharAt(i, '\\');
159 toAppendTo.insert(i + 1, 'n');
160 break;
161 }
162 }
163 }
164 },
165
166
167
168
169
170
171 XML {
172 @Override
173 void escape(final StringBuilder toAppendTo, final int start) {
174 StringBuilders.escapeXml(toAppendTo, start);
175 }
176 };
177
178
179
180
181
182
183
184 abstract void escape(final StringBuilder toAppendTo, final int start);
185 }
186 }