You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@struts.apache.org by "github-code-scanning[bot] (via GitHub)" <gi...@apache.org> on 2023/06/29 10:52:53 UTC

[GitHub] [struts] github-code-scanning[bot] commented on a diff in pull request #608: [WW-5233] Include Apache Tiles code base in the Tiles plugin

github-code-scanning[bot] commented on code in PR #608:
URL: https://github.com/apache/struts/pull/608#discussion_r1246462268


##########
plugins/tiles/src/main/java/org/apache/tiles/core/definition/digester/DigesterDefinitionsReader.java:
##########
@@ -0,0 +1,464 @@
+/*
+ * 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.tiles.core.definition.digester;
+
+import org.apache.commons.digester.Digester;
+import org.apache.commons.digester.Rule;
+import org.apache.tiles.api.Attribute;
+import org.apache.tiles.api.Definition;
+import org.apache.tiles.api.Expression;
+import org.apache.tiles.api.ListAttribute;
+import org.apache.tiles.core.definition.DefinitionsFactoryException;
+import org.apache.tiles.core.definition.DefinitionsReader;
+import org.xml.sax.Attributes;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * Reads {@link Definition} objects from
+ * an XML InputStream using Digester. <p/>
+ * <p>
+ * This <code>DefinitionsReader</code> implementation expects the source to be
+ * passed as an <code>InputStream</code>. It parses XML data from the source
+ * and builds a Map of Definition objects.
+ * </p>
+ * <p/>
+ * <p>
+ * The Digester object can be configured by passing in initialization
+ * parameters. Currently the only parameter that is supported is the
+ * <code>validating</code> parameter. This value is set to <code>false</code>
+ * by default. To enable DTD validation for XML Definition files, give the init
+ * method a parameter with a key of
+ * <code>org.apache.tiles.definition.digester.DigesterDefinitionsReader.PARSER_VALIDATE</code>
+ * and a value of <code>&quot;true&quot;</code>. <p/>
+ * <p>
+ * The Definition objects are stored internally in a Map. The Map is stored as
+ * an instance variable rather than a local variable in the <code>read</code>
+ * method. This means that instances of this class are <strong>not</strong>
+ * thread-safe and access by multiple threads must be synchronized.
+ * </p>
+ */
+public class DigesterDefinitionsReader implements DefinitionsReader {
+
+    /**
+     * Digester validation parameter name.
+     */
+    public static final String PARSER_VALIDATE_PARAMETER_NAME = "org.apache.tiles.definition.digester.DigesterDefinitionsReader.PARSER_VALIDATE";
+
+    // Digester rules constants for tag interception.
+
+    /**
+     * Intercepts a &lt;definition&gt; tag.
+     */
+    private static final String DEFINITION_TAG = "tiles-definitions/definition";
+
+    /**
+     * Intercepts a &lt;put-attribute&gt; tag.
+     */
+    private static final String PUT_TAG = "*/definition/put-attribute";
+
+    /**
+     * Intercepts a &lt;definition&gt; inside a  &lt;put-attribute&gt; tag.
+     */
+    private static final String PUT_DEFINITION_TAG = "*/put-attribute/definition";
+
+    /**
+     * Intercepts a &lt;definition&gt; inside an &lt;add-attribute&gt; tag.
+     */
+    private static final String ADD_DEFINITION_TAG = "*/add-attribute/definition";
+
+    /**
+     * Intercepts a &lt;put-list-attribute&gt; tag inside a %lt;definition&gt;
+     * tag.
+     */
+    private static final String DEF_LIST_TAG = "*/definition/put-list-attribute";
+
+    /**
+     * Intercepts a &lt;add-attribute&gt; tag.
+     */
+    private static final String ADD_LIST_ELE_TAG = "*/add-attribute";
+
+    /**
+     * Intercepts a &lt;add-list-attribute&gt; tag.
+     */
+    private static final String NESTED_LIST = "*/add-list-attribute";
+
+    // Handler class names.
+
+    /**
+     * The handler to create definitions.
+     *
+     * @since 2.1.0
+     */
+    protected static final String DEFINITION_HANDLER_CLASS =
+        Definition.class.getName();
+
+    /**
+     * The handler to create attributes.
+     *
+     * @since 2.1.0
+     */
+    protected static final String PUT_ATTRIBUTE_HANDLER_CLASS =
+        Attribute.class.getName();
+
+    /**
+     * The handler to create list attributes.
+     *
+     * @since 2.1.0
+     */
+    protected static final String LIST_HANDLER_CLASS =
+        ListAttribute.class.getName();
+
+    /**
+     * Digester rule to manage definition filling.
+     *
+     * @since 2.1.2
+     */
+    public static class FillDefinitionRule extends Rule {
+
+        /** {@inheritDoc} */
+        @Override
+        public void begin(String namespace, String name, Attributes attributes) {
+            Definition definition = (Definition) digester.peek();
+            definition.setName(attributes.getValue("name"));
+            definition.setPreparer(attributes.getValue("preparer"));
+            String extendsAttribute = attributes.getValue("extends");
+            definition.setExtends(extendsAttribute);
+
+            String template = attributes.getValue("template");
+            Attribute attribute = Attribute.createTemplateAttribute(template);
+            attribute.setExpressionObject(Expression
+                    .createExpressionFromDescribedExpression(attributes
+                            .getValue("templateExpression")));
+            attribute.setRole(attributes.getValue("role"));
+            String templateType = attributes.getValue("templateType");
+            if (templateType != null) {
+                attribute.setRenderer(templateType);
+            } else if (extendsAttribute != null) {
+                attribute.setRenderer(null);
+            }
+            definition.setTemplateAttribute(attribute);
+        }
+    }
+
+    /**
+     * Digester rule to manage attribute filling.
+     *
+     * @since 2.1.0
+     */
+    public static class FillAttributeRule extends Rule {
+
+        /** {@inheritDoc} */
+        @Override
+        public void begin(String namespace, String name, Attributes attributes) {
+            Attribute attribute = (Attribute) digester.peek();
+            attribute.setValue(attributes.getValue("value"));
+            String expression = attributes.getValue("expression");
+            attribute.setExpressionObject(Expression
+                    .createExpressionFromDescribedExpression(expression));
+            attribute.setRole(attributes.getValue("role"));
+            attribute.setRenderer(attributes.getValue("type"));
+        }
+    }
+
+    /**
+     * Digester rule to manage assignment of the attribute to the parent
+     * element.
+     *
+     * @since 2.1.0
+     */
+    public static class PutAttributeRule extends Rule {
+
+        /** {@inheritDoc} */
+        @Override
+        public void begin(String namespace, String name, Attributes attributes) {
+            Attribute attribute = (Attribute) digester.peek(0);
+            Definition definition = (Definition) digester.peek(1);
+            definition.putAttribute(attributes.getValue("name"), attribute,
+                    "true".equals(attributes.getValue("cascade")));
+        }
+    }
+
+    /**
+     * Digester rule to manage assignment of a nested definition in an attribute
+     * value.
+     *
+     * @since 2.1.0
+     */
+    public class AddNestedDefinitionRule extends Rule {
+
+        /** {@inheritDoc} */
+        @Override
+        public void begin(String namespace, String name, Attributes attributes) {
+            Definition definition = (Definition) digester.peek(0);
+            if (definition.getName() == null) {
+                definition.setName(getNextUniqueDefinitionName(definitions));
+            }
+            Attribute attribute = (Attribute) digester.peek(1);
+            attribute.setValue(definition.getName());
+            attribute.setRenderer("definition");
+        }
+    }
+
+    /**
+     * <code>Digester</code> object used to read Definition data
+     * from the source.
+     */
+    protected Digester digester;
+
+    /**
+     * The set of public identifiers, and corresponding resource names for
+     * the versions of the configuration file DTDs we know about.  There
+     * <strong>MUST</strong> be an even number of Strings in this list!
+     */
+    protected String[] registrations;
+
+    /**
+     * Stores Definition objects.
+     */
+    private Map<String, Definition> definitions;
+
+    /**
+     * Index to be used to create unique definition names for anonymous
+     * (nested) definitions.
+     */
+    private int anonymousDefinitionIndex = 1;
+
+    /**
+     * Creates a new instance of DigesterDefinitionsReader.
+     */
+    public DigesterDefinitionsReader() {
+        digester = new Digester();
+        digester.setNamespaceAware(true);
+        digester.setUseContextClassLoader(true);
+        digester.setErrorHandler(new ThrowingErrorHandler());
+
+        // Register our local copy of the DTDs that we can find
+        String[] registrations = getRegistrations();
+        for (int i = 0; i < registrations.length; i += 2) {
+            URL url = this.getClass().getResource(
+                registrations[i + 1]);
+            if (url != null) {
+                digester.register(registrations[i], url.toString());
+            }
+        }
+
+        initSyntax(digester);
+    }
+
+    /**
+     * Sets the validation of XML files.
+     *
+     * @param validating <code>true</code> means that XML validation is turned
+     * on. <code>false</code> otherwise.
+     * @since 3.3.0
+     */
+    public void setValidating(boolean validating) {
+        digester.setValidating(validating);
+    }
+
+    /**
+     * Reads <code>{@link Definition}</code> objects from a source.
+     * <p/>
+     * Implementations should publish what type of source object is expected.
+     *
+     * @param source The <code>InputStream</code> source from which definitions
+     *               will be read.
+     * @return a Map of <code>Definition</code> objects read from
+     *         the source.
+     * @throws DefinitionsFactoryException If the source is invalid or
+     *          an error occurs when reading definitions.
+     */
+    public Map<String, Definition> read(Object source) {
+        // This is an instance variable instead of a local variable because
+        // we want to be able to call the addDefinition method to populate it.
+        // But we reset the Map here, which, of course, has threading implications.
+        definitions = new LinkedHashMap<>();
+
+        if (source == null) {
+            // Perhaps we should throw an exception here.
+            return null;
+        }
+
+        InputStream input;
+        try {
+            input = (InputStream) source;
+        } catch (ClassCastException e) {
+            throw new DefinitionsFactoryException(
+                "Invalid source type.  Requires java.io.InputStream.", e);
+        }
+
+        try {
+            // set first object in stack
+            //digester.clear();
+            digester.push(this);
+            // parse
+            digester.parse(input);

Review Comment:
   ## Resolving XML external entity in user-controlled data
   
   XML parsing depends on a [user-provided value](1) without guarding against external entity expansion.
   XML parsing depends on a [user-provided value](2) without guarding against external entity expansion.
   
   [Show more details](https://github.com/apache/struts/security/code-scanning/235)



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@struts.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org