You are viewing a plain text version of this content. The canonical link for it is here.
Posted to batik-dev@xmlgraphics.apache.org by vh...@apache.org on 2002/04/30 17:05:19 UTC

cvs commit: xml-batik/sources/org/apache/batik/script/rhino BatikSecuritySupport.java RhinoClassLoader.java RhinoInterpreter.java RhinoInterpreterFactory.java

vhardy      02/04/30 08:05:19

  Modified:    lib      js.jar
               resources/org/apache/batik/apps/svgbrowser/resources
                        svgbrowser.bin.policy svgbrowser.policy
               sources/org/apache/batik/script Interpreter.java
               sources/org/apache/batik/script/rhino RhinoInterpreter.java
                        RhinoInterpreterFactory.java
  Added:       sources/org/apache/batik/script/rhino
                        BatikSecuritySupport.java RhinoClassLoader.java
  Log:
  Modified ECMAScript security so that it uses the Rhino SecuritySupport interface. Now, ECMAScripts can connect back to the server that served the document referencing the script
  
  Revision  Changes    Path
  1.7       +784 -772  xml-batik/lib/js.jar
  
  	<<Binary file>>
  
  
  1.2       +1 -0      xml-batik/resources/org/apache/batik/apps/svgbrowser/resources/svgbrowser.bin.policy
  
  Index: svgbrowser.bin.policy
  ===================================================================
  RCS file: /home/cvs/xml-batik/resources/org/apache/batik/apps/svgbrowser/resources/svgbrowser.bin.policy,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- svgbrowser.bin.policy	30 Apr 2002 08:45:14 -0000	1.1
  +++ svgbrowser.bin.policy	30 Apr 2002 15:05:18 -0000	1.2
  @@ -68,5 +68,6 @@
   
   grant codeBase "${squiggle.jar.base}/lib/js.jar" {
     permission java.lang.RuntimePermission "createClassLoader";
  +  permission java.net.SocketPermission "*", "listen, connect, resolve, accept";
   };
   
  
  
  
  1.2       +1 -0      xml-batik/resources/org/apache/batik/apps/svgbrowser/resources/svgbrowser.policy
  
  Index: svgbrowser.policy
  ===================================================================
  RCS file: /home/cvs/xml-batik/resources/org/apache/batik/apps/svgbrowser/resources/svgbrowser.policy,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- svgbrowser.policy	30 Apr 2002 08:45:14 -0000	1.1
  +++ svgbrowser.policy	30 Apr 2002 15:05:18 -0000	1.2
  @@ -11,6 +11,7 @@
   
   grant codeBase "${squiggle.dev.base}/lib/js.jar" {
     permission java.lang.RuntimePermission "createClassLoader";
  +  permission java.net.SocketPermission "*", "listen, connect, resolve, accept";
   };
   
   
  
  
  
  1.5       +12 -1     xml-batik/sources/org/apache/batik/script/Interpreter.java
  
  Index: Interpreter.java
  ===================================================================
  RCS file: /home/cvs/xml-batik/sources/org/apache/batik/script/Interpreter.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- Interpreter.java	8 Oct 2001 15:04:39 -0000	1.4
  +++ Interpreter.java	30 Apr 2002 15:05:18 -0000	1.5
  @@ -12,44 +12,55 @@
   import java.io.Writer;
   import java.io.IOException;
   
  +import org.w3c.dom.Document;
  +
   /**
    * An hight level interface that represents an interpreter engine of
    * a particular scripting language.
  + *
    * @author <a href="mailto:cjolif@ilog.fr">Christophe Jolif</a>
  - * @version $Id: Interpreter.java,v 1.4 2001/10/08 15:04:39 cjolif Exp $
  + * @version $Id: Interpreter.java,v 1.5 2002/04/30 15:05:18 vhardy Exp $
    */
   public interface Interpreter extends org.apache.batik.i18n.Localizable {
       /**
        * This method should evaluate a piece of script.
  +     *
        * @param scriptreader a <code>java.io.Reader</code> on the piece of script
        * @return if no exception is thrown during the call, should return the
        * value of the last expression evaluated in the script
        */
       public Object evaluate(Reader scriptreader)
           throws InterpreterException, IOException;
  +
       /**
        * This method should evaluate a piece of script using a <code>String</code>
        * instead of a <code>Reader</code>. This usually allows do easily do some
        * caching.
  +     *
        * @param script the piece of script
        * @return if no exception is thrown during the call, should return the
        * value of the last expression evaluated in the script
        */
       public Object evaluate(String script)
           throws InterpreterException;
  +
       /**
        * This method should register a particular Java <code>Object</code> in
        * the environment of the interpreter.
  +     *
        * @param name the name of the script object to create
        * @param object the Java object
        */
       public void bindObject(String name, Object object);
  +
       /**
        * This method should change the output <code>Writer</code> that will be
        * used when output function of the scripting langage is used.
  +     *
        * @param output the new out <code>Writer</code>.
        */
       public void setOut(Writer output);
  +
       /**
        * This method can dispose resources used by the interpreter when it is
        * no longer used. Be careful, you SHOULD NOT use this interpreter instance
  
  
  
  1.15      +74 -13    xml-batik/sources/org/apache/batik/script/rhino/RhinoInterpreter.java
  
  Index: RhinoInterpreter.java
  ===================================================================
  RCS file: /home/cvs/xml-batik/sources/org/apache/batik/script/rhino/RhinoInterpreter.java,v
  retrieving revision 1.14
  retrieving revision 1.15
  diff -u -r1.14 -r1.15
  --- RhinoInterpreter.java	10 Apr 2002 16:19:03 -0000	1.14
  +++ RhinoInterpreter.java	30 Apr 2002 15:05:18 -0000	1.15
  @@ -12,9 +12,13 @@
   import java.io.Reader;
   import java.io.Writer;
   import java.io.StringReader;
  +
  +import java.net.URL;
  +
   import java.util.Iterator;
   import java.util.LinkedList;
   import java.util.Locale;
  +import java.util.Vector;
   
   import org.w3c.dom.events.EventTarget;
   
  @@ -27,6 +31,7 @@
   import org.mozilla.javascript.ImporterTopLevel;
   import org.mozilla.javascript.JavaScriptException;
   import org.mozilla.javascript.NativeJavaPackage;
  +import org.mozilla.javascript.SecuritySupport;
   import org.mozilla.javascript.Script;
   import org.mozilla.javascript.Scriptable;
   import org.mozilla.javascript.ScriptableObject;
  @@ -37,7 +42,7 @@
    * A simple implementation of <code>Interpreter</code> interface to use
    * Rhino ECMAScript interpreter.
    * @author <a href="mailto:cjolif@ilog.fr">Christophe Jolif</a>
  - * @version $Id: RhinoInterpreter.java,v 1.14 2002/04/10 16:19:03 hillion Exp $
  + * @version $Id: RhinoInterpreter.java,v 1.15 2002/04/30 15:05:18 vhardy Exp $
    */
   public class RhinoInterpreter implements Interpreter {
       private static String[] TO_BE_IMPORTED = {
  @@ -69,17 +74,50 @@
           new EventTargetWrapHandler(this);
   
       /**
  +     * The SecuritySupport implementation for Batik,
  +     * which ensures scripts have access to the 
  +     * server they were downloaded from
  +     */
  +    private SecuritySupport securitySupport 
  +        = new BatikSecuritySupport();
  +
  +    /**
  +     * The Rhino 'security domain'. We use the RhinoClassLoader
  +     * which will grant permissions to connect to the document
  +     * URL.
  +     */
  +    protected RhinoClassLoader rhinoClassLoader;
  +
  +    /**
  +     * Default Context for scripts
  +     */
  +    protected Context defaultContext;
  +
  +    /**
  +     * Context vector, to make sure we are not 
  +     * setting the security context too many times
  +     */
  +    protected Vector contexts;
  +
  +    /**
        * Build a <code>Interpreter</code> for ECMAScript using Rhino.
  +     * 
  +     * @param documentURL the URL for the document which references
  +     *        
        * @see org.apache.batik.script.Interpreter
        * @see org.apache.batik.script.InterpreterPool
        */
  -    public RhinoInterpreter() {
  +    public RhinoInterpreter(URL documentURL) {
  +        rhinoClassLoader = new RhinoClassLoader(documentURL);
  +
           Context.setCachingEnabled(false); // reset the cache
           Context.setCachingEnabled(true);  // enable caching again
  -
           // entering a context
  -        Context ctx = Context.enter();
  +        defaultContext = new Context(securitySupport);
  +        Context ctx = enterContext();
  +            
           try {
  +
               // init std object with an importer
               // building the importer automatically initialize the
               // context with it since Rhino1.5R3
  @@ -98,6 +136,23 @@
       }
   
       /**
  +     * Implementation helper. Makes sure the proper security is set 
  +     * on the context.
  +     */
  +    public Context enterContext(){
  +        Context ctx = Context.enter(defaultContext);
  +        if (ctx != defaultContext){
  +            // Set the SecuritySupport the Context should
  +            // use.
  +            if (!contexts.contains(ctx)) {
  +                ctx.setSecuritySupport(securitySupport);
  +                contexts.add(ctx);
  +            }
  +        }
  +        return ctx;
  +    }
  +
  +    /**
        * This method returns the ECMAScript global object used by this interpreter.
        */
       protected ScriptableObject getGlobalObject() {
  @@ -115,13 +170,14 @@
       public Object evaluate(Reader scriptreader)
           throws InterpreterException, IOException {
           Object rv = null;
  -        Context ctx = Context.enter();
  +        Context ctx = enterContext();
  +
           ctx.setWrapHandler(wrapHandler);
           try {
               rv = ctx.evaluateReader(globalObject,
                                       scriptreader,
                                       "<SVG>",
  -                                    1, null);
  +                                    1, rhinoClassLoader);
           } catch (JavaScriptException e) {
               // exception from JavaScript (possibly wrapping a Java Ex)
               if (e.getValue() instanceof Exception) {
  @@ -156,7 +212,8 @@
       public Object evaluate(String scriptstr)
           throws InterpreterException {
    
  -        Context ctx = Context.enter();
  +        Context ctx = enterContext();
  +
           ctx.setWrapHandler(wrapHandler);
           Script script = null;
           Entry et = null;
  @@ -182,7 +239,7 @@
                   script = ctx.compileReader(globalObject,
                                              new StringReader(scriptstr),
                                              "<SVG>",
  -                                           1, null);
  +                                           1, rhinoClassLoader);
               } catch (IOException io) {
                   // can't happen because we use a String...
               }
  @@ -236,7 +293,8 @@
        * @param object the Java object
        */
       public void bindObject(String name, Object object) {
  -        Context ctx = Context.enter();
  +        Context ctx = enterContext();
  +
           ctx.setWrapHandler(wrapHandler);
           try {
               Scriptable jsObject =  Context.toObject(object, globalObject);
  @@ -269,7 +327,8 @@
       void callHandler(Function handler,
                        Object arg)
           throws JavaScriptException {
  -        Context ctx = Context.enter();
  +        Context ctx = enterContext();
  +
           ctx.setWrapHandler(wrapHandler);
           try {
               arg = Context.toObject(arg, globalObject);
  @@ -286,7 +345,8 @@
       void callHandler(Function handler,
                        Object[] args)
           throws JavaScriptException {
  -        Context ctx = Context.enter();
  +        Context ctx = enterContext();
  +
           ctx.setWrapHandler(wrapHandler);
           try {
               handler.call(ctx, globalObject, globalObject, args);
  @@ -301,7 +361,8 @@
       void callHandler(Function handler,
                        ArgumentsBuilder ab)
           throws JavaScriptException {
  -        Context ctx = Context.enter();
  +        Context ctx = enterContext();
  +
           ctx.setWrapHandler(wrapHandler);
           try {
               handler.call(ctx, globalObject, globalObject, ab.buildArguments());
  @@ -355,7 +416,7 @@
       }
   
       /**
  -     * Creates and returns a localized message, given the key of the message
  +     * Creates and returns a localized message, given the key of the message, 0, data.length
        * in the resource bundle and the message parameters.
        * The messages in the resource bundle must have the syntax described in
        * the java.text.MessageFormat class documentation.
  
  
  
  1.5       +2 -52     xml-batik/sources/org/apache/batik/script/rhino/RhinoInterpreterFactory.java
  
  Index: RhinoInterpreterFactory.java
  ===================================================================
  RCS file: /home/cvs/xml-batik/sources/org/apache/batik/script/rhino/RhinoInterpreterFactory.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- RhinoInterpreterFactory.java	30 Apr 2002 08:45:15 -0000	1.4
  +++ RhinoInterpreterFactory.java	30 Apr 2002 15:05:19 -0000	1.5
  @@ -19,31 +19,10 @@
    * 
    * @author <a href="mailto:cjolif@ilog.fr">Christophe Jolif</a>
    * @author <a href="mailto:vhardy@apache.org">Vincent Hardy</a>
  - * @version $Id: RhinoInterpreterFactory.java,v 1.4 2002/04/30 08:45:15 vhardy Exp $
  + * @version $Id: RhinoInterpreterFactory.java,v 1.5 2002/04/30 15:05:19 vhardy Exp $
    */
   public class RhinoInterpreterFactory implements InterpreterFactory {
       /**
  -     * Class for the Rhino interpreter
  -     */
  -    public static final String RHINO_INTERPRETER
  -        = "org.apache.batik.script.rhino.RhinoInterpreter";
  -
  -    /**
  -     * Message when an error happens loading the rhino interpreter.
  -     * This should *never* happen.
  -     */
  -    public static final String EXCEPTION_COULD_NOT_FIND_RHINO_INTERPRETER_CLASS
  -        = Messages.getString("RhinoInterpreterFactory.exception.could.not.find.rhino.interpreter.class");
  -
  -    /**
  -     * Message when an error happens while instantiating the
  -     * Rhino interpreter. This should *never* happen except under
  -     * extraordinary conditions.
  -     */
  -    public static final String EXCEPTION_WHILE_INSTANTIATING_RHINO_INTERPRETER
  -        = Messages.getString("RhinoInterpreterFactory.exception.while.instantiating.rhino.interpreter");
  -
  -    /**
        * Builds a <code>RhinoInterpreterFactory</code>.
        */
       public RhinoInterpreterFactory() {
  @@ -55,35 +34,6 @@
        * @param documentURL the url for the document which will be scripted
        */
       public Interpreter createInterpreter(URL documentURL) {
  -        if (documentURL != null) {
  -            // Use a URLClassLoader to let the document scripts 
  -            // access the URL from where the document was loaded
  -            URLClassLoader cl = new URLClassLoader(new URL[]{documentURL});
  -
  -            Class rhinoInterpreterClass = null;
  -            try {
  -                rhinoInterpreterClass = cl.loadClass(RHINO_INTERPRETER);
  -            } catch (ClassNotFoundException e){
  -                // Installation is flawed: should not continue
  -                throw new Error(EXCEPTION_COULD_NOT_FIND_RHINO_INTERPRETER_CLASS);
  -            }
  -            
  -            try {
  -                return (Interpreter)rhinoInterpreterClass.newInstance();
  -            } catch (InstantiationException ie){
  -                throw new Error(EXCEPTION_WHILE_INSTANTIATING_RHINO_INTERPRETER);
  -            } catch (IllegalAccessException iae){
  -                throw new Error(EXCEPTION_WHILE_INSTANTIATING_RHINO_INTERPRETER);
  -            } catch (ExceptionInInitializerError eii){
  -                throw new Error(EXCEPTION_WHILE_INSTANTIATING_RHINO_INTERPRETER);
  -            } catch (SecurityException se){
  -                throw new Error(EXCEPTION_WHILE_INSTANTIATING_RHINO_INTERPRETER);
  -            }
  -        } else {
  -            // Return a new RhinoInterpreter which will be 
  -            // limited to the local sandbox with no possible 
  -            // connection to the network.
  -            return new RhinoInterpreter();
  -        }
  +        return new RhinoInterpreter(documentURL);
       }
   }
  
  
  
  1.1                  xml-batik/sources/org/apache/batik/script/rhino/BatikSecuritySupport.java
  
  Index: BatikSecuritySupport.java
  ===================================================================
  /*****************************************************************************
   * Copyright (C) The Apache Software Foundation. All rights reserved.        *
   *---------------------------------------------------------------------------*
   * This software is published under the terms of the Apache Software License *
   * version 1.1, a copy of which has been included with this distribution in  *
   * the LICENSE file.                                                         *
   *****************************************************************************/
  
  package org.apache.batik.script.rhino;
  
  import java.net.URL;
  import java.net.URLClassLoader;
  
  import org.mozilla.javascript.SecuritySupport;
  
  /**
   * This implementation of the Rhino <tt>SecuritySupport</tt> interface is
   * meant for use within the context of Batik only. It is a partial 
   * implementation of the interface that does what is needed by Batik and 
   * no more.
   *
   * @author <a href="mailto:vincent.hardy@sun.com">Vincent Hardy</a>
   * @version $Id: BatikSecuritySupport.java,v 1.1 2002/04/30 15:05:18 vhardy Exp $
   */
  public class BatikSecuritySupport implements SecuritySupport {
      /**
       * Default constructor
       */
      public BatikSecuritySupport(){
      }
  
      /**
       * Define and load a Java class
       */
      public Class defineClass(String name,
                               byte[] data,
                               Object securityDomain){
          RhinoClassLoader rcl = (RhinoClassLoader)securityDomain;
          return rcl.defineClass(name, data);
      }
  
      /**
       * Get the current class Context.
       * This implementation always returns null.
       */
      public Class[] getClassContext(){
          return null;
      }
  
      /**
       * Return teh security context associated with the 
       * given class.
       * In this implementation, we return the <tt>ClassLoader</tt>
       * which created the input class.
       */
      public Object getSecurityDomain(Class cl){
          return cl.getClassLoader();
      }
  
      /**
       * Return true if the Java class with the given name should 
       * be exposed to scripts.
       * 
       * In this implementation, this always return true, as 
       * security is enforced by the SecurityManager's policy
       * and the Permissions granted by the URLClassLoader 
       * used to load classes.
       */
      public boolean visibleToScripts(String fullClassName){
          return true;
      }
  }
  
  
  
  1.1                  xml-batik/sources/org/apache/batik/script/rhino/RhinoClassLoader.java
  
  Index: RhinoClassLoader.java
  ===================================================================
  /*****************************************************************************
   * Copyright (C) The Apache Software Foundation. All rights reserved.        *
   *---------------------------------------------------------------------------*
   * This software is published under the terms of the Apache Software License *
   * version 1.1, a copy of which has been included with this distribution in  *
   * the LICENSE file.                                                         *
   *****************************************************************************/
  
  package org.apache.batik.script.rhino;
  
  import java.net.URL;
  import java.net.URLClassLoader;
  
  import java.security.SecureClassLoader;
  import java.security.CodeSource;
  import java.security.PermissionCollection;
  
  /**
   * This class loader implementation will work whether or not the
   * documentURL is null.
   *
   * @author <a href="mailto:vincent.hardy@sun.com">Vincent Hardy</a>
   * @version $Id: RhinoClassLoader.java,v 1.1 2002/04/30 15:05:18 vhardy Exp $
   */
  public class RhinoClassLoader extends URLClassLoader {
      /**
       * URL for the document referencing the script.
       */
      protected URL documentURL;
  
      /**
       * CodeSource for classes defined by this loader
       */
      protected CodeSource codeSource;
      
      /**
       * Constructor.
       * @param documentURL the URL from which to load classes and resources 
       */
      public RhinoClassLoader(URL documentURL){
          super(documentURL != null ? new URL[]{documentURL} : new URL[]{});
          // super(new URL[]{});
          this.documentURL = documentURL;
          if (documentURL != null){
              codeSource = new CodeSource(documentURL, null);
          }
      }
      
      /**
       * Define and load a Java class
       */
      public Class defineClass(String name, 
                               byte[] data){
          return super.defineClass(name, data, 0, data.length, codeSource);
      }
  
      /**
       * Returns the permissions for the given CodeSource object. 
       */
      protected PermissionCollection getPermissions(CodeSource codesource) {
          return super.getPermissions(codesource);
      }
  }
  
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: batik-dev-unsubscribe@xml.apache.org
For additional commands, e-mail: batik-dev-help@xml.apache.org