001
014
015 package com.liferay.portal.kernel.log;
016
017 import com.liferay.portal.kernel.util.CharPool;
018 import com.liferay.portal.kernel.util.GetterUtil;
019 import com.liferay.portal.kernel.util.PropsKeys;
020 import com.liferay.portal.kernel.util.StringPool;
021 import com.liferay.portal.kernel.util.SystemProperties;
022
023 import java.util.ArrayList;
024 import java.util.List;
025
026
030 public class SanitizerLogWrapper extends LogWrapper {
031
032 public static Log allowCRLF(Log log) {
033 if (!(log instanceof SanitizerLogWrapper)) {
034 return log;
035 }
036
037 SanitizerLogWrapper sanitizerLogWrapper = (SanitizerLogWrapper)log;
038
039 sanitizerLogWrapper = new SanitizerLogWrapper(
040 sanitizerLogWrapper.getWrappedLog());
041
042 sanitizerLogWrapper._allowCRLF = true;
043
044 return sanitizerLogWrapper;
045 }
046
047 public static void init() {
048 if (!_LOG_SANITIZER_ENABLED) {
049 return;
050 }
051
052 _LOG_SANITIZER_ESCAPE_HTML_ENABLED = GetterUtil.getBoolean(
053 SystemProperties.get(PropsKeys.LOG_SANITIZER_ESCAPE_HTML_ENABLED));
054
055 _LOG_SANITIZER_REPLACEMENT_CHARACTER = (char)GetterUtil.getInteger(
056 SystemProperties.get(
057 PropsKeys.LOG_SANITIZER_REPLACEMENT_CHARACTER));
058
059 for (int i = 0; i < _whitelistCharacters.length; i++) {
060 _whitelistCharacters[i] = 1;
061 }
062
063 int[] whitelistCharacters = GetterUtil.getIntegerValues(
064 SystemProperties.getArray(
065 PropsKeys.LOG_SANITIZER_WHITELIST_CHARACTERS));
066
067 for (int whitelistCharacter : whitelistCharacters) {
068 if ((whitelistCharacter >= 0) &&
069 (whitelistCharacter < _whitelistCharacters.length)) {
070
071 _whitelistCharacters[whitelistCharacter] = 0;
072 }
073 else {
074 System.err.println(
075 "Unable to register log whitelist character " +
076 whitelistCharacter);
077 }
078 }
079 }
080
081 public static boolean isEnabled() {
082 return _LOG_SANITIZER_ENABLED;
083 }
084
085 public SanitizerLogWrapper(Log log) {
086 super(log);
087
088 setLogWrapperClassName(SanitizerLogWrapper.class.getName());
089 }
090
091 @Override
092 public void debug(Object msg) {
093 super.debug(sanitize(msg));
094 }
095
096 @Override
097 public void debug(Object msg, Throwable t) {
098 super.debug(sanitize(msg), sanitize(t));
099 }
100
101 @Override
102 public void debug(Throwable t) {
103 super.debug(sanitize(t));
104 }
105
106 @Override
107 public void error(Object msg) {
108 super.error(sanitize(msg));
109 }
110
111 @Override
112 public void error(Object msg, Throwable t) {
113 super.error(sanitize(msg), sanitize(t));
114 }
115
116 @Override
117 public void error(Throwable t) {
118 super.error(sanitize(t));
119 }
120
121 @Override
122 public void fatal(Object msg) {
123 super.fatal(sanitize(msg));
124 }
125
126 @Override
127 public void fatal(Object msg, Throwable t) {
128 super.fatal(sanitize(msg), sanitize(t));
129 }
130
131 @Override
132 public void fatal(Throwable t) {
133 super.fatal(sanitize(t));
134 }
135
136 @Override
137 public void info(Object msg) {
138 super.info(sanitize(msg));
139 }
140
141 @Override
142 public void info(Object msg, Throwable t) {
143 super.info(sanitize(msg), sanitize(t));
144 }
145
146 @Override
147 public void info(Throwable t) {
148 super.info(sanitize(t));
149 }
150
151 @Override
152 public void trace(Object msg) {
153 super.trace(sanitize(msg));
154 }
155
156 @Override
157 public void trace(Object msg, Throwable t) {
158 super.trace(sanitize(msg), sanitize(t));
159 }
160
161 @Override
162 public void trace(Throwable t) {
163 super.trace(sanitize(t));
164 }
165
166 @Override
167 public void warn(Object msg) {
168 super.warn(sanitize(msg));
169 }
170
171 @Override
172 public void warn(Object msg, Throwable t) {
173 super.warn(sanitize(msg), sanitize(t));
174 }
175
176 @Override
177 public void warn(Throwable t) {
178 super.warn(sanitize(t));
179 }
180
181 protected String sanitize(Object obj) {
182 if (obj == null) {
183 return null;
184 }
185
186 String message = obj.toString();
187
188 return sanitize(message, message);
189 }
190
191 protected String sanitize(String message, String defaultResult) {
192 if (message == null) {
193 return null;
194 }
195
196 char[] chars = message.toCharArray();
197 boolean hasCRLF = false;
198 boolean hasLessThanCharacter = false;
199 boolean sanitized = false;
200
201 for (int i = 0; i < chars.length; i++) {
202 int c = chars[i];
203
204 if (_allowCRLF &&
205 ((c == CharPool.NEW_LINE) || (c == CharPool.RETURN))) {
206
207 hasCRLF = true;
208
209 continue;
210 }
211
212 if ((c >= 0) && (c < _whitelistCharacters.length) &&
213 (_whitelistCharacters[c] != 0)) {
214
215 chars[i] = _LOG_SANITIZER_REPLACEMENT_CHARACTER;
216 sanitized = true;
217 }
218
219 if (c == CharPool.LESS_THAN) {
220 hasLessThanCharacter = true;
221 }
222 }
223
224 boolean escapeHTML = false;
225
226 if (_LOG_SANITIZER_ESCAPE_HTML_ENABLED && hasLessThanCharacter) {
227 escapeHTML = true;
228 }
229
230 if (sanitized || escapeHTML || hasCRLF) {
231 String sanitizedMessage = new String(chars);
232
233 if (escapeHTML) {
234 sanitizedMessage = sanitizedMessage.replaceAll(
235 StringPool.LESS_THAN, _LESS_THAN_ESCAPED);
236 }
237
238 if (sanitized) {
239 sanitizedMessage = sanitizedMessage.concat(_SANITIZED);
240 }
241
242 if (hasCRLF) {
243 sanitizedMessage = CRLF_WARNING.concat(sanitizedMessage);
244 }
245
246 return sanitizedMessage;
247 }
248
249 return defaultResult;
250 }
251
252 protected Throwable sanitize(Throwable throwable) {
253 List<Throwable> throwables = new ArrayList<Throwable>();
254
255 Throwable tempThrowable = throwable;
256
257 while (tempThrowable != null) {
258 throwables.add(tempThrowable);
259
260 tempThrowable = tempThrowable.getCause();
261 }
262
263 Throwable resultThrowable = null;
264
265 boolean sanitized = false;
266
267 for (int i = throwables.size() - 1; i > - 1; i--) {
268 Throwable curThrowable = throwables.get(i);
269
270 String message = curThrowable.toString();
271
272 String sanitizedMessage = sanitize(message, null);
273
274 if (!sanitized && (sanitizedMessage == null)) {
275 resultThrowable = curThrowable;
276
277 continue;
278 }
279
280 if (sanitizedMessage == null) {
281 sanitizedMessage = message;
282 }
283
284 sanitized = true;
285
286 resultThrowable = new LogSanitizerException(
287 sanitizedMessage, curThrowable.getStackTrace(),
288 resultThrowable);
289 }
290
291 return resultThrowable;
292 }
293
294 protected static final String CRLF_WARNING =
295 "SanitizerLogWrapper warning: Following message contains CRLF " +
296 "characters\n";
297
298 private static final String _LESS_THAN_ESCAPED = "<";
299
300 private static final String _SANITIZED = " [Sanitized]";
301
302 private static boolean _LOG_SANITIZER_ENABLED = GetterUtil.getBoolean(
303 SystemProperties.get(PropsKeys.LOG_SANITIZER_ENABLED));
304
305 private static boolean _LOG_SANITIZER_ESCAPE_HTML_ENABLED = false;
306
307 private static char _LOG_SANITIZER_REPLACEMENT_CHARACTER =
308 CharPool.UNDERLINE;
309
310 private static int[] _whitelistCharacters = new int[128];
311
312 private boolean _allowCRLF;
313
314 }