Skip to content

Commit

Permalink
Add environment lookup and regex replacement for pattern layout
Browse files Browse the repository at this point in the history
  • Loading branch information
rgoers committed Oct 19, 2011
1 parent c0e509d commit a538903
Show file tree
Hide file tree
Showing 15 changed files with 408 additions and 46 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ private RolloverFrequency calculateFrequency(String pattern) {

private PatternParser createPatternParser() {

return new PatternParser(KEY, null);
return new PatternParser(null, KEY, null);
}

private boolean patternContains(String pattern, char[] chars) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
import org.apache.logging.log4j.core.filter.Filterable;
import org.apache.logging.log4j.core.filter.Filters;
import org.apache.logging.log4j.core.helpers.NameUtil;
import org.apache.logging.log4j.core.lookup.Interpolator;
import org.apache.logging.log4j.core.lookup.StrLookup;
import org.apache.logging.log4j.core.lookup.StrSubstitutor;
import org.apache.logging.log4j.status.StatusLogger;

Expand Down Expand Up @@ -74,6 +76,8 @@ public class BaseConfiguration extends Filterable implements Configuration {

private boolean started = false;

private ConcurrentMap<String, Object> componentMap = new ConcurrentHashMap<String, Object>();

/**
* Constructor.
*/
Expand Down Expand Up @@ -112,6 +116,14 @@ public void stop() {
protected void setup() {
}

public Object getComponent(String name) {
return componentMap.get(name);
}

public void addComponent(String name, Object obj) {
componentMap.putIfAbsent(name, obj);
}

protected void doConfigure() {
boolean setRoot = false;
boolean setLoggers = false;
Expand All @@ -121,8 +133,17 @@ protected void doConfigure() {
continue;
}
if (child.getName().equalsIgnoreCase("properties")) {
subst = (StrSubstitutor) child.getObject();
} else if (child.getName().equalsIgnoreCase("appenders")) {
if (subst.getVariableResolver() == null) {
subst.setVariableResolver((StrLookup) child.getObject());
} else {
logger.error("Properties declaration must be the first element in the configuration");
}
continue;
}
else if (subst.getVariableResolver() == null) {
subst.setVariableResolver(new Interpolator(null));
}
if (child.getName().equalsIgnoreCase("appenders")) {
appenders = (ConcurrentMap<String, Appender>) child.getObject();
} else if (child.getName().equalsIgnoreCase("filters")) {
setFilters((Filters) child.getObject());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,8 @@ public interface Configuration extends Filtering {
StrSubstitutor getSubst();

void createConfiguration(Node node, LogEvent event);

Object getComponent(String name);

void addComponent(String name, Object object);
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import org.apache.logging.log4j.core.config.Property;
import org.apache.logging.log4j.core.lookup.Interpolator;
import org.apache.logging.log4j.core.lookup.MapLookup;
import org.apache.logging.log4j.core.lookup.StrLookup;
import org.apache.logging.log4j.core.lookup.StrSubstitutor;

import java.util.HashMap;
Expand All @@ -31,16 +32,16 @@
public class PropertiesPlugin {

@PluginFactory
public static StrSubstitutor configureSubstitutor(@PluginElement("properties") Property[] properties) {
public static StrLookup configureSubstitutor(@PluginElement("properties") Property[] properties) {
if (properties == null) {
return new StrSubstitutor(new Interpolator(null));
return new Interpolator(null);
}
Map<String, String> map = new HashMap<String, String>();

for (Property prop : properties) {
map.put(prop.getName(), prop.getValue());
}

return new StrSubstitutor(new Interpolator(new MapLookup(map)));
return new Interpolator(new MapLookup(map));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,17 @@
package org.apache.logging.log4j.core.layout;

import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.config.plugins.Plugin;
import org.apache.logging.log4j.core.config.plugins.PluginAttr;
import org.apache.logging.log4j.core.config.plugins.PluginConfiguration;
import org.apache.logging.log4j.core.config.plugins.PluginElement;
import org.apache.logging.log4j.core.config.plugins.PluginFactory;
import org.apache.logging.log4j.core.helpers.OptionConverter;
import org.apache.logging.log4j.core.pattern.LogEventPatternConverter;
import org.apache.logging.log4j.core.pattern.PatternConverter;
import org.apache.logging.log4j.core.pattern.PatternParser;
import org.apache.logging.log4j.core.pattern.RegexReplacement;

import java.nio.charset.Charset;
import java.util.List;
Expand Down Expand Up @@ -415,7 +419,7 @@ public class PatternLayout extends AbstractStringLayout {
*/
private List<PatternConverter> converters;

private static final String KEY = "Converter";
public static final String KEY = "Converter";

/**
* Conversion pattern.
Expand All @@ -427,13 +431,20 @@ public class PatternLayout extends AbstractStringLayout {
*/
private boolean handlesExceptions;

/**
* The current Configuration.
*/
private final Configuration config;

private final RegexReplacement replace;

/**
* Constructs a EnhancedPatternLayout using the DEFAULT_LAYOUT_PATTERN.
* <p/>
* The default pattern just produces the application supplied message.
*/
public PatternLayout() {
this(DEFAULT_CONVERSION_PATTERN, Charset.defaultCharset());
this(null, null, DEFAULT_CONVERSION_PATTERN, Charset.defaultCharset());
}

/**
Expand All @@ -442,18 +453,30 @@ public PatternLayout() {
* The default pattern just produces the application supplied message.
*/
public PatternLayout(final String pattern) {
this(pattern, Charset.defaultCharset());
this(null, null, pattern, Charset.defaultCharset());
}

/**
* Constructs a EnhancedPatternLayout using the DEFAULT_LAYOUT_PATTERN.
* <p/>
* The default pattern just produces the application supplied message.
*/
public PatternLayout(Configuration config, final String pattern) {
this(config, null, pattern, Charset.defaultCharset());
}

/**
* Constructs a EnhancedPatternLayout using the supplied conversion pattern.
*
* @param pattern conversion pattern.
*/
public PatternLayout(final String pattern, final Charset charset) {
public PatternLayout(Configuration config, final RegexReplacement replace, final String pattern,
final Charset charset) {
super(charset);
this.replace = replace;
this.conversionPattern = pattern;
PatternParser parser = createPatternParser();
this.config = config;
PatternParser parser = createPatternParser(config);
converters = parser.parse((pattern == null) ? DEFAULT_CONVERSION_PATTERN : pattern);
handlesExceptions = parser.handlesExceptions();

Expand All @@ -471,7 +494,7 @@ public void setConversionPattern(final String conversionPattern) {
if (pattern == null) {
return;
}
PatternParser parser = createPatternParser();
PatternParser parser = createPatternParser(this.config);
converters = parser.parse(pattern);
handlesExceptions = parser.handlesExceptions();
}
Expand All @@ -486,12 +509,24 @@ public String formatAs(final LogEvent event) {
for (PatternConverter c : converters) {
c.format(event, buf);
}
return buf.toString();
String str = buf.toString();
if (replace != null) {
str = replace.format(str);
}
return config == null ? str : config.getSubst().replace(event, str);

This comment has been minimized.

Copy link
@mirabilos

mirabilos Dec 12, 2021

From what I can gather, this is where the root cause behind CVE-2021-44228 was introduced.

This comment has been minimized.

Copy link
@mirabilos

mirabilos Dec 13, 2021

2797204 #623 is going to remove this functionality of questionable worth entirely; thanks!

}

private PatternParser createPatternParser() {

return new PatternParser(KEY, LogEventPatternConverter.class);
private PatternParser createPatternParser(Configuration config) {
if (config == null) {
return new PatternParser(config, KEY, LogEventPatternConverter.class);
}
PatternParser parser = (PatternParser) config.getComponent(KEY);
if (parser == null) {
parser = new PatternParser(config, KEY, LogEventPatternConverter.class);
config.addComponent(KEY, parser);
parser = (PatternParser) config.getComponent(KEY);
}
return parser;
}

public String toString() {
Expand All @@ -500,6 +535,8 @@ public String toString() {

@PluginFactory
public static PatternLayout createLayout(@PluginAttr("pattern") String pattern,
@PluginConfiguration Configuration config,
@PluginElement("replace") RegexReplacement replace,
@PluginAttr("charset") String charset) {
Charset c = Charset.isSupported("UTF-8") ? Charset.forName("UTF-8") : Charset.defaultCharset();
if (charset != null) {
Expand All @@ -510,7 +547,7 @@ public static PatternLayout createLayout(@PluginAttr("pattern") String pattern,
}
}
if (pattern != null) {
return new PatternLayout(pattern, c);
return new PatternLayout(config, replace, pattern, c);
}
logger.error("No pattern specified for PatternLayout");
return null;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache license, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the license for the specific language governing permissions and
* limitations under the license.
*/
package org.apache.logging.log4j.core.lookup;

import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.config.plugins.Plugin;

/**
* Looks up keys from environment variables.
*/
@Plugin(name="env",type="Lookup")
public class EnvironmentLookup implements StrLookup {

/**
* Get the value of the environment variable.
* @param key the key to be looked up, may be null
* @return The value of the environment variable.
*/
public String lookup(String key) {
return System.getenv(key);
}

/**
* Get the value of the environment variable.
* @param event The current LogEvent (is ignored by this StrLookup).
* @param key the key to be looked up, may be null
* @return The value of the environment variable.
*/
public String lookup(LogEvent event, String key) {
return System.getenv(key);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public class Interpolator implements StrLookup {
private final StrLookup defaultLookup;

public Interpolator(StrLookup defaultLookup) {
this.defaultLookup = defaultLookup;
this.defaultLookup = defaultLookup == null ? new MapLookup(new HashMap<String, String>()) : defaultLookup;
PluginManager manager = new PluginManager("Lookup");
manager.collectPlugins();
Map<String, PluginType> plugins = manager.getPlugins();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
* Return the event's rendered message in a StringBuffer.
*/
@Plugin(name="MessagePatternConverter", type="Converter")
@ConverterKeys({"m", "message"})
@ConverterKeys({"m", "msg", "message"})
public final class MessagePatternConverter extends LogEventPatternConverter {

private final String format;
Expand Down
Loading

0 comments on commit a538903

Please sign in to comment.