diff --git a/src/helma/framework/core/Application.java b/src/helma/framework/core/Application.java index 7f0d496e..d205bb73 100644 --- a/src/helma/framework/core/Application.java +++ b/src/helma/framework/core/Application.java @@ -173,6 +173,8 @@ public final class Application implements Runnable { // Field to cache unmapped java classes private final static String CLASS_NOT_MAPPED = "(unmapped)"; + protected boolean allowDeepMacros = false; + /** * Simple constructor for dead application instances. */ @@ -1871,6 +1873,8 @@ public final class Application implements Runnable { ((Logger) eventLog).setLogLevel(debug ? Logger.DEBUG : Logger.INFO); } + allowDeepMacros = "true".equalsIgnoreCase(props.getProperty("allowDeepMacros")); + // set prop read timestamp lastPropertyRead = props.lastModified(); } diff --git a/src/helma/framework/core/Skin.java b/src/helma/framework/core/Skin.java index d11aa60e..83ba221b 100644 --- a/src/helma/framework/core/Skin.java +++ b/src/helma/framework/core/Skin.java @@ -35,6 +35,7 @@ import java.io.IOException; public final class Skin { static private final int PARSE_MACRONAME = 0; static private final int PARSE_PARAM = 1; + static private final int PARSE_DONE = 2; static private final int ENCODE_NONE = 0; static private final int ENCODE_HTML = 1; @@ -314,6 +315,7 @@ public final class Skin { case '%': if ((state != PARSE_PARAM || quotechar == '\u0000') && source[i + 1] == '>') { + state = PARSE_DONE; break loop; } b.append(source[i]); @@ -332,10 +334,9 @@ public final class Skin { (source[i] != '%' || source[i + 1] != '>')) { i++; } - + state = PARSE_DONE; break loop; } - break; case '|': @@ -345,6 +346,7 @@ public final class Skin { i = filterChain.end - 2; lastParamName = null; b.setLength(0); + state = PARSE_DONE; break loop; } b.append(source[i]); @@ -432,14 +434,17 @@ public final class Skin { this.end = Math.min(sourceLength, i + 2); if (b.length() > 0) { - if (lastParamName != null) { - // add parameter - addParameter(lastParamName, b.toString()); - } else if (state == PARSE_MACRONAME) { + if (name == null) { name = b.toString().trim(); + } else { + addParameter(lastParamName, b.toString()); } } + if (state != PARSE_DONE) { + app.logError("Unterminated Macro Tag: " +this); + } + path = StringUtils.split(name, "."); if (path.length <= 1) { handler = HANDLER_GLOBAL; @@ -765,6 +770,10 @@ public final class Skin { } private Object resolvePath(Object handler, RequestEvaluator reval) { + if (!app.allowDeepMacros && path.length > 2) { + throw new RuntimeException("allowDeepMacros property must be true " + + "in order to enable deep macro paths."); + } for (int i = 1; i < path.length - 1; i++) { handler = getProperty(handler, path[i], reval); if (handler == null) {