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