/**
* Copyright (c) 2000-present Liferay, Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*/
package com.liferay.portal.kernel.log;
import com.liferay.portal.kernel.util.CharPool;
import com.liferay.portal.kernel.util.GetterUtil;
import com.liferay.portal.kernel.util.PropsKeys;
import com.liferay.portal.kernel.util.StringUtil;
import com.liferay.portal.kernel.util.SystemProperties;
import java.util.ArrayList;
import java.util.List;
/**
* @author Tomas Polesovsky
* @author Raymond Augé
*/
public class SanitizerLogWrapper extends LogWrapper {
public static Log allowCRLF(Log log) {
if (!(log instanceof SanitizerLogWrapper)) {
return log;
}
SanitizerLogWrapper sanitizerLogWrapper = (SanitizerLogWrapper)log;
sanitizerLogWrapper = new SanitizerLogWrapper(
sanitizerLogWrapper.getWrappedLog());
sanitizerLogWrapper._allowCRLF = true;
return sanitizerLogWrapper;
}
public static void init() {
if (!_LOG_SANITIZER_ENABLED) {
return;
}
_logSanitizerEscapeHTMLEnabled = GetterUtil.getBoolean(
SystemProperties.get(PropsKeys.LOG_SANITIZER_ESCAPE_HTML_ENABLED));
_logSanitizerReplacementCharacter = (char)GetterUtil.getInteger(
SystemProperties.get(
PropsKeys.LOG_SANITIZER_REPLACEMENT_CHARACTER));
for (int i = 0; i < _whitelistCharacters.length; i++) {
_whitelistCharacters[i] = 1;
}
int[] whitelistCharacters = GetterUtil.getIntegerValues(
StringUtil.split(
SystemProperties.get(
PropsKeys.LOG_SANITIZER_WHITELIST_CHARACTERS)));
for (int whitelistCharacter : whitelistCharacters) {
if ((whitelistCharacter >= 0) &&
(whitelistCharacter < _whitelistCharacters.length)) {
_whitelistCharacters[whitelistCharacter] = 0;
}
else {
System.err.println(
"Unable to register log whitelist character " +
whitelistCharacter);
}
}
}
public static boolean isEnabled() {
return _LOG_SANITIZER_ENABLED;
}
public SanitizerLogWrapper(Log log) {
super(log);
setLogWrapperClassName(SanitizerLogWrapper.class.getName());
}
@Override
public void debug(Object msg) {
super.debug(sanitize(msg));
}
@Override
public void debug(Object msg, Throwable t) {
super.debug(sanitize(msg), sanitize(t));
}
@Override
public void debug(Throwable t) {
super.debug(sanitize(t));
}
@Override
public void error(Object msg) {
super.error(sanitize(msg));
}
@Override
public void error(Object msg, Throwable t) {
super.error(sanitize(msg), sanitize(t));
}
@Override
public void error(Throwable t) {
super.error(sanitize(t));
}
@Override
public void fatal(Object msg) {
super.fatal(sanitize(msg));
}
@Override
public void fatal(Object msg, Throwable t) {
super.fatal(sanitize(msg), sanitize(t));
}
@Override
public void fatal(Throwable t) {
super.fatal(sanitize(t));
}
@Override
public void info(Object msg) {
super.info(sanitize(msg));
}
@Override
public void info(Object msg, Throwable t) {
super.info(sanitize(msg), sanitize(t));
}
@Override
public void info(Throwable t) {
super.info(sanitize(t));
}
@Override
public void trace(Object msg) {
super.trace(sanitize(msg));
}
@Override
public void trace(Object msg, Throwable t) {
super.trace(sanitize(msg), sanitize(t));
}
@Override
public void trace(Throwable t) {
super.trace(sanitize(t));
}
@Override
public void warn(Object msg) {
super.warn(sanitize(msg));
}
@Override
public void warn(Object msg, Throwable t) {
super.warn(sanitize(msg), sanitize(t));
}
@Override
public void warn(Throwable t) {
super.warn(sanitize(t));
}
protected String sanitize(Object obj) {
if (obj == null) {
return null;
}
String message = obj.toString();
return sanitize(message, message);
}
protected String sanitize(String message, String defaultResult) {
if (message == null) {
return null;
}
char[] chars = message.toCharArray();
boolean hasCRLF = false;
boolean hasLessThanCharacter = false;
boolean sanitized = false;
for (int i = 0; i < chars.length; i++) {
int c = chars[i];
if (_allowCRLF &&
((c == CharPool.NEW_LINE) || (c == CharPool.RETURN))) {
hasCRLF = true;
continue;
}
if ((c >= 0) && (c < _whitelistCharacters.length) &&
(_whitelistCharacters[c] != 0)) {
chars[i] = _logSanitizerReplacementCharacter;
sanitized = true;
}
if (c == CharPool.LESS_THAN) {
hasLessThanCharacter = true;
}
}
boolean escapeHTML = false;
if (_logSanitizerEscapeHTMLEnabled && hasLessThanCharacter) {
escapeHTML = true;
}
if (sanitized || escapeHTML || hasCRLF) {
String sanitizedMessage = new String(chars);
if (escapeHTML) {
sanitizedMessage = StringUtil.replace(
sanitizedMessage, CharPool.LESS_THAN, _LESS_THAN_ESCAPED);
}
if (sanitized) {
sanitizedMessage = sanitizedMessage.concat(_SANITIZED);
}
if (hasCRLF) {
sanitizedMessage = CRLF_WARNING.concat(sanitizedMessage);
}
return sanitizedMessage;
}
return defaultResult;
}
protected Throwable sanitize(Throwable throwable) {
List<Throwable> throwables = new ArrayList<>();
Throwable tempThrowable = throwable;
while (tempThrowable != null) {
throwables.add(tempThrowable);
tempThrowable = tempThrowable.getCause();
}
Throwable resultThrowable = null;
boolean sanitized = false;
for (int i = throwables.size() - 1; i > -1; i--) {
Throwable curThrowable = throwables.get(i);
String message = curThrowable.toString();
String sanitizedMessage = sanitize(message, null);
if (!sanitized && (sanitizedMessage == null)) {
resultThrowable = curThrowable;
continue;
}
if (sanitizedMessage == null) {
sanitizedMessage = message;
}
sanitized = true;
resultThrowable = new LogSanitizerException(
sanitizedMessage, curThrowable.getStackTrace(),
resultThrowable);
}
return resultThrowable;
}
protected static final String CRLF_WARNING =
"SanitizerLogWrapper warning: Following message contains CRLF " +
"characters\n";
private static final String _LESS_THAN_ESCAPED = "<";
private static final boolean _LOG_SANITIZER_ENABLED = GetterUtil.getBoolean(
SystemProperties.get(PropsKeys.LOG_SANITIZER_ENABLED));
private static final String _SANITIZED = " [Sanitized]";
private static boolean _logSanitizerEscapeHTMLEnabled;
private static char _logSanitizerReplacementCharacter = CharPool.UNDERLINE;
private static final int[] _whitelistCharacters = new int[128];
private boolean _allowCRLF;
}