From 94c4997e0178b274ee643fd68262fe373af4b2bd Mon Sep 17 00:00:00 2001 From: hns Date: Mon, 30 Jul 2001 00:04:07 +0000 Subject: [PATCH] implemented sandbox for script-generated user level skins --- src/helma/framework/core/Application.java | 6 ++-- src/helma/framework/core/HopExtension.java | 34 +++++++--------------- src/helma/framework/core/Skin.java | 23 ++++++++++++++- 3 files changed, 36 insertions(+), 27 deletions(-) diff --git a/src/helma/framework/core/Application.java b/src/helma/framework/core/Application.java index efb47327..519f3053 100644 --- a/src/helma/framework/core/Application.java +++ b/src/helma/framework/core/Application.java @@ -75,7 +75,7 @@ public class Application extends UnicastRemoteObject implements IRemoteApp, IRep private DbMapping rootMapping, userRootMapping, userMapping; - protected CacheMap skincache = new CacheMap (100); + boolean checkSubnodes; String charset; @@ -131,6 +131,8 @@ public class Application extends UnicastRemoteObject implements IRemoteApp, IRep charset = props.getProperty ("charset", "ISO-8859-1"); debug = "true".equalsIgnoreCase (props.getProperty ("debug")); + checkSubnodes = !"false".equalsIgnoreCase (props.getProperty ("subnodeChecking")); + try { requestTimeout = Long.parseLong (props.getProperty ("requestTimeout", "60"))*1000l; } catch (Exception ignore) { } @@ -710,7 +712,7 @@ public class Application extends UnicastRemoteObject implements IRemoteApp, IRep * It is recommended to leave it on except you suffer severe performance problems and know what you do. */ public boolean doesSubnodeChecking () { - return !"false".equalsIgnoreCase (props.getProperty ("subnodeChecking")); + return checkSubnodes; } } diff --git a/src/helma/framework/core/HopExtension.java b/src/helma/framework/core/HopExtension.java index 77246736..24a1ba02 100644 --- a/src/helma/framework/core/HopExtension.java +++ b/src/helma/framework/core/HopExtension.java @@ -106,7 +106,7 @@ public class HopExtension { go.putHiddenProperty("getXmlDocument", new GlobalGetXmlDocument ("getXmlDocument", evaluator, fp)); go.putHiddenProperty("getHtmlDocument", new GlobalGetHtmlDocument ("getHtmlDocument", evaluator, fp)); go.putHiddenProperty("jdomize", new GlobalJDOM ("jdomize", evaluator, fp)); - go.putHiddenProperty("getSkin", new GlobalGetSkin ("getSkin", evaluator, fp)); + go.putHiddenProperty("getSkin", new GlobalCreateSkin ("getSkin", evaluator, fp)); go.putHiddenProperty("createSkin", new GlobalCreateSkin ("createSkin", evaluator, fp)); go.putHiddenProperty("renderSkin", new RenderSkin ("renderSkin", evaluator, fp, true, false)); go.putHiddenProperty("renderSkinAsString", new RenderSkin ("renderSkinAsString", evaluator, fp, true, true)); @@ -569,26 +569,6 @@ public class HopExtension { } } - /** - * Get a parsed Skin from the central skin cache if possible, otherwise create it - */ - class GlobalGetSkin extends BuiltinFunctionObject { - GlobalGetSkin (String name, Evaluator evaluator, FunctionPrototype fp) { - super (fp, evaluator, name, 1); - } - public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException { - if (arguments.length != 1 || ESNull.theNull.equals (arguments[0])) - throw new EcmaScriptException ("getSkin must be called with one String argument!"); - String str = arguments[0].toString (); - Skin skin = (Skin) app.skincache.get (str); - if (skin == null) { - skin = new Skin (str, app); - app.skincache.put (str, skin); - } - return new ESWrapper (skin, evaluator); - } - } - /** * Get a parsed Skin from an app-managed skin text */ @@ -597,9 +577,15 @@ public class HopExtension { super (fp, evaluator, name, 1); } public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException { - if (arguments.length != 1 || ESNull.theNull.equals (arguments[0])) - throw new EcmaScriptException ("createSkin must be called with one String argument!"); - return new ESWrapper (new Skin (arguments[0].toString(), app), evaluator); + if (arguments.length < 1 || arguments.length > 2 || ESNull.theNull.equals (arguments[0])) + throw new EcmaScriptException ("createSkin must be called with one String argument and an optional sandbox parameter!"); + String str = arguments[0].toString (); + Skin skin = null; + if (arguments.length == 2 && arguments[1] instanceof ESObject) + skin = new Skin (str, app, (ESObject) arguments[1]); + else + skin = new Skin (str, app); + return new ESWrapper (skin, evaluator); } } diff --git a/src/helma/framework/core/Skin.java b/src/helma/framework/core/Skin.java index dac725a7..abdc84f5 100644 --- a/src/helma/framework/core/Skin.java +++ b/src/helma/framework/core/Skin.java @@ -25,9 +25,15 @@ public class Skin { Object[] parts; Application app; String source; + ESObject sandbox; public Skin (String content, Application app) { + this (content, app, null); + } + + public Skin (String content, Application app, ESObject sandbox) { this.app = app; + this.sandbox = sandbox; parse (content); } @@ -87,6 +93,7 @@ public class Skin { String handler; String name; Hashtable parameters; + boolean notallowed = false; public Macro (String str) { @@ -173,12 +180,26 @@ public class Skin { else if (state <= MACRO) name = b.toString().trim(); } + if (sandbox != null && name != null) try { + ESValue allow = handler == null ? + sandbox.getProperty ("global", "global".hashCode ()) : + sandbox.getProperty (handler, handler.hashCode ()); + allow = ((ESObject) allow).getProperty (name, name.hashCode ()); + if (allow == null || allow == ESUndefined.theUndefined) + notallowed = true; + } catch (Exception x) { + notallowed = true; + } } public void render (RequestEvaluator reval, ESNode thisNode, ESObject paramObject) throws RedirectException { - if ("response".equalsIgnoreCase (handler)) { + if (notallowed) { + String h = handler == null ? "global" : handler; + reval.res.write ("[Macro "+h+"."+name+" not allowed in sandbox]"); + return; + } else if ("response".equalsIgnoreCase (handler)) { renderFromResponse (reval); return; } else if ("request".equalsIgnoreCase (handler)) {