src/com/sun/org/apache/xerces/internal/impl/XMLEntityManager.java

Print this page

        

@@ -1,7 +1,7 @@
 /*
- * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2006, 2013 Oracle and/or its affiliates. All rights reserved.
  */
 
 /*
  * Copyright 2005 The Apache Software Foundation.
  *

@@ -18,57 +18,43 @@
  * limitations under the License.
  */
 
 package com.sun.org.apache.xerces.internal.impl ;
 
+import com.sun.org.apache.xerces.internal.impl.Constants;
+import com.sun.org.apache.xerces.internal.impl.io.ASCIIReader;
+import com.sun.org.apache.xerces.internal.impl.io.UCSReader;
+import com.sun.org.apache.xerces.internal.impl.io.UTF8Reader;
+import com.sun.org.apache.xerces.internal.impl.msg.XMLMessageFormatter;
+import com.sun.org.apache.xerces.internal.impl.XMLEntityHandler;
+import com.sun.org.apache.xerces.internal.impl.validation.ValidationManager;
+import com.sun.org.apache.xerces.internal.util.*;
+import com.sun.org.apache.xerces.internal.util.SecurityManager;
+import com.sun.org.apache.xerces.internal.util.URI;
+import com.sun.org.apache.xerces.internal.utils.SecuritySupport;
+import com.sun.org.apache.xerces.internal.xni.Augmentations;
+import com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier;
+import com.sun.org.apache.xerces.internal.xni.XNIException;
+import com.sun.org.apache.xerces.internal.xni.parser.*;
+import com.sun.xml.internal.stream.Entity;
 import com.sun.xml.internal.stream.StaxEntityResolverWrapper;
 import com.sun.xml.internal.stream.StaxXMLInputSource;
 import com.sun.xml.internal.stream.XMLEntityStorage;
 import java.io.*;
-import java.io.BufferedReader;
-import java.util.*;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.io.StringReader;
 import java.lang.reflect.Method;
 import java.net.HttpURLConnection;
+import java.net.URISyntaxException;
 import java.net.URL;
 import java.net.URLConnection;
-import java.net.URISyntaxException;
 import java.util.Hashtable;
 import java.util.Iterator;
 import java.util.Locale;
 import java.util.Map;
 import java.util.Stack;
+import javax.xml.XMLConstants;
 
 
-import com.sun.org.apache.xerces.internal.impl.io.*;
-import com.sun.org.apache.xerces.internal.impl.msg.XMLMessageFormatter;
-import com.sun.org.apache.xerces.internal.util.*;
-import com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier;
-import com.sun.org.apache.xerces.internal.xni.XNIException;
-import com.sun.org.apache.xerces.internal.xni.parser.*;
-import com.sun.org.apache.xerces.internal.impl.Constants;
-import com.sun.org.apache.xerces.internal.utils.SecuritySupport;
-import com.sun.xml.internal.stream.Entity;
-import com.sun.org.apache.xerces.internal.xni.Augmentations;
-
-import com.sun.org.apache.xerces.internal.impl.io.UTF8Reader;
-import com.sun.org.apache.xerces.internal.impl.io.ASCIIReader;
-import com.sun.org.apache.xerces.internal.impl.io.UCSReader;
-import com.sun.org.apache.xerces.internal.impl.XMLEntityHandler;
-import com.sun.org.apache.xerces.internal.util.HTTPInputSource;
-import com.sun.org.apache.xerces.internal.xinclude.XIncludeHandler;
-
-import com.sun.org.apache.xerces.internal.impl.validation.ValidationManager;
-import com.sun.org.apache.xerces.internal.util.SecurityManager;
-import com.sun.org.apache.xerces.internal.util.URI;
-
-
 /**
  * Will keep track of current entity.
  *
  * The entity manager handles the registration of general and parameter
  * entities; resolves entities; and starts entities. The entity manager

@@ -138,10 +124,14 @@
 
     /** Feature identifier: warn on duplicate EntityDef */
     protected static final String WARN_ON_DUPLICATE_ENTITYDEF =
             Constants.XERCES_FEATURE_PREFIX +Constants.WARN_ON_DUPLICATE_ENTITYDEF_FEATURE;
 
+    /** Feature identifier: load external DTD. */
+    protected static final String LOAD_EXTERNAL_DTD =
+            Constants.XERCES_FEATURE_PREFIX + Constants.LOAD_EXTERNAL_DTD_FEATURE;
+
     // property identifiers
 
     /** Property identifier: symbol table. */
     protected static final String SYMBOL_TABLE =
             Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY;

@@ -171,12 +161,20 @@
 
     /** property identifier: security manager. */
     protected static final String SECURITY_MANAGER =
         Constants.XERCES_PROPERTY_PREFIX + Constants.SECURITY_MANAGER_PROPERTY;
 
-protected static final String PARSER_SETTINGS =
+    protected static final String PARSER_SETTINGS =
         Constants.XERCES_FEATURE_PREFIX + Constants.PARSER_SETTINGS;
+
+    /** property identifier: access external dtd. */
+    protected static final String ACCESS_EXTERNAL_DTD = XMLConstants.ACCESS_EXTERNAL_DTD;
+
+    /** access external dtd: file protocol */
+    static final String EXTERNAL_ACCESS_DEFAULT = Constants.EXTERNAL_ACCESS_DEFAULT; 
+
+
     // recognized features and properties
 
     /** Recognized features. */
     private static final String[] RECOGNIZED_FEATURES = {
                 VALIDATION,

@@ -203,21 +201,22 @@
                 ERROR_REPORTER,
                 ENTITY_RESOLVER,
                 VALIDATION_MANAGER,
                 BUFFER_SIZE,
                 SECURITY_MANAGER,
-
+                ACCESS_EXTERNAL_DTD
     };
 
     /** Property defaults. */
     private static final Object[] PROPERTY_DEFAULTS = {
                 null,
                 null,
                 null,
                 null,
                 new Integer(DEFAULT_BUFFER_SIZE),
-                null
+                null,
+                EXTERNAL_ACCESS_DEFAULT 
     };
 
     private static final String XMLEntity = "[xml]".intern();
     private static final String DTDEntity = "[dtd]".intern();
 

@@ -272,10 +271,12 @@
      * Allow Java encoding names. This feature identifier is:
      * http://apache.org/xml/features/allow-java-encodings
      */
     protected boolean fAllowJavaEncodings = true ;
 
+    /** Load external DTD. */
+    protected boolean fLoadExternalDTD = true;
 
     // properties
 
     /**
      * Symbol table. This property identifier is:

@@ -300,11 +301,12 @@
     protected StaxEntityResolverWrapper fStaxEntityResolver;
 
     /** Property Manager. This is used from Stax */
     protected PropertyManager fPropertyManager ;
 
-
+    /** used to restrict external access */
+    protected String fAccessExternalDTD = EXTERNAL_ACCESS_DEFAULT;
     // settings
 
     /**
      * Validation manager. This property identifier is:
      * http://apache.org/xml/properties/internal/validation-manager

@@ -364,10 +366,13 @@
     protected Stack fEntityStack = new Stack();
 
     /** Current entity. */
     protected Entity.ScannedEntity fCurrentEntity = null;
 
+    /** identify if the InputSource is created by a resolver */
+    boolean fISCreatedByResolver = false;
+
     // shared context
 
     protected XMLEntityStorage fEntityStorage ;
 
     protected final Object [] defaultEncoding = new Object[]{"UTF-8", null};

@@ -963,22 +968,29 @@
         ri.setValues(publicId, literalSystemId, baseSystemId, expandedSystemId);
         if(DEBUG_RESOLVER){
             System.out.println("BEFORE Calling resolveEntity") ;
         }
 
+        fISCreatedByResolver = false;
         //either of Stax or Xerces would be null
         if(fStaxEntityResolver != null){
             staxInputSource = fStaxEntityResolver.resolveEntity(ri);
+            if(staxInputSource != null) {
+                fISCreatedByResolver = true;
         }
+        }
 
         if(fEntityResolver != null){
             xmlInputSource = fEntityResolver.resolveEntity(ri);
+            if(xmlInputSource != null) {
+                fISCreatedByResolver = true;
         }
+        }
 
         if(xmlInputSource != null){
             //wrap this XMLInputSource to StaxInputSource
-            staxInputSource = new StaxXMLInputSource(xmlInputSource);
+            staxInputSource = new StaxXMLInputSource(xmlInputSource, fISCreatedByResolver);
         }
 
         // do default resolution
         //this works for both stax & Xerces, if staxInputSource is null, it means parser need to revert to default resolution
         if (staxInputSource == null) {

@@ -1106,27 +1118,26 @@
             return;
         }
 
         // should we skip external entities?
         boolean external = entity.isExternal();
+        Entity.ExternalEntity externalEntity = null;
+        String extLitSysId = null, extBaseSysId = null, expandedSystemId = null;
         if (external) {
+            externalEntity = (Entity.ExternalEntity)entity;
+            extLitSysId = (externalEntity.entityLocation != null ? externalEntity.entityLocation.getLiteralSystemId() : null);
+            extBaseSysId = (externalEntity.entityLocation != null ? externalEntity.entityLocation.getBaseSystemId() : null);
+            expandedSystemId = expandSystemId(extLitSysId, extBaseSysId);
             boolean unparsed = entity.isUnparsed();
             boolean parameter = entityName.startsWith("%");
             boolean general = !parameter;
             if (unparsed || (general && !fExternalGeneralEntities) ||
                     (parameter && !fExternalParameterEntities)) {
 
                 if (fEntityHandler != null) {
                     fResourceIdentifier.clear();
                     final String encoding = null;
-                    Entity.ExternalEntity externalEntity = (Entity.ExternalEntity)entity;
-                    //REVISIT:  since we're storing expandedSystemId in the
-                    // externalEntity, how could this have got here if it wasn't already
-                    // expanded??? - neilg
-                    String extLitSysId = (externalEntity.entityLocation != null ? externalEntity.entityLocation.getLiteralSystemId() : null);
-                    String extBaseSysId = (externalEntity.entityLocation != null ? externalEntity.entityLocation.getBaseSystemId() : null);
-                    String expandedSystemId = expandSystemId(extLitSysId, extBaseSysId);
                     fResourceIdentifier.setValues(
                             (externalEntity.entityLocation != null ? externalEntity.entityLocation.getPublicId() : null),
                             extLitSysId, extBaseSysId, expandedSystemId);
                     fEntityAugs.removeAllItems();
                     fEntityAugs.putItem(Constants.ENTITY_SKIPPED, Boolean.TRUE);

@@ -1160,15 +1171,10 @@
 
                         if (fEntityHandler != null) {
                             fResourceIdentifier.clear();
                             final String encoding = null;
                             if (external) {
-                                Entity.ExternalEntity externalEntity = (Entity.ExternalEntity)entity;
-                                // REVISIT:  for the same reason above...
-                                String extLitSysId = (externalEntity.entityLocation != null ? externalEntity.entityLocation.getLiteralSystemId() : null);
-                                String extBaseSysId = (externalEntity.entityLocation != null ? externalEntity.entityLocation.getBaseSystemId() : null);
-                                String expandedSystemId = expandSystemId(extLitSysId, extBaseSysId);
                                 fResourceIdentifier.setValues(
                                         (externalEntity.entityLocation != null ? externalEntity.entityLocation.getPublicId() : null),
                                         extLitSysId, extBaseSysId, expandedSystemId);
                             }
                             fEntityAugs.removeAllItems();

@@ -1186,19 +1192,30 @@
         // resolve external entity
         StaxXMLInputSource staxInputSource = null;
         XMLInputSource xmlInputSource = null ;
 
         if (external) {
-            Entity.ExternalEntity externalEntity = (Entity.ExternalEntity)entity;
             staxInputSource = resolveEntityAsPerStax(externalEntity.entityLocation);
             /** xxx:  Waiting from the EG
              * //simply return if there was entity resolver registered and application
              * //returns either XMLStreamReader or XMLEventReader.
              * if(staxInputSource.hasXMLStreamOrXMLEventReader()) return ;
              */
             xmlInputSource = staxInputSource.getXMLInputSource() ;
+            if (!fISCreatedByResolver) {
+                //let the not-LoadExternalDTD or not-SupportDTD process to handle the situation
+                if (fLoadExternalDTD) {
+                    String accessError = SecuritySupport.checkAccess(expandedSystemId, fAccessExternalDTD, Constants.ACCESS_EXTERNAL_ALL);
+                    if (accessError != null) {
+                        fErrorReporter.reportError(this.getEntityScanner(),XMLMessageFormatter.XML_DOMAIN,
+                                "AccessExternalEntity",
+                                new Object[] { SecuritySupport.sanitizePath(expandedSystemId), accessError },
+                                XMLErrorReporter.SEVERITY_FATAL_ERROR);
         }
+                }
+            }
+        }
         // wrap internal entity
         else {
             Entity.InternalEntity internalEntity = (Entity.InternalEntity)entity;
             Reader reader = new StringReader(internalEntity.text);
             xmlInputSource = new XMLInputSource(null, null, null, reader, null);

@@ -1398,21 +1415,25 @@
             fStaxEntityResolver = (StaxEntityResolverWrapper)propertyManager.getProperty(STAX_ENTITY_RESOLVER);
         } catch (XMLConfigurationException e) {
             fStaxEntityResolver = null;
         }
 
+        // Zephyr feature ignore-external-dtd is the opposite of Xerces' load-external-dtd
+        fLoadExternalDTD = !((Boolean)propertyManager.getProperty(Constants.ZEPHYR_PROPERTY_PREFIX + Constants.IGNORE_EXTERNAL_DTD)).booleanValue();
+
+        // JAXP 1.5 feature 
+        fAccessExternalDTD = (String) propertyManager.getProperty(ACCESS_EXTERNAL_DTD);
+
         // initialize state
         //fStandalone = false;
         fEntities.clear();
         fEntityStack.removeAllElements();
         fCurrentEntity = null;
         fValidation = false;
         fExternalGeneralEntities = true;
         fExternalParameterEntities = true;
         fAllowJavaEncodings = true ;
-
-        //test();
     }
 
     /**
      * Resets the component. The component can query the component manager
      * about any features and properties that affect the operation of the

@@ -1451,19 +1472,23 @@
 
         // xerces features
         fAllowJavaEncodings = componentManager.getFeature(ALLOW_JAVA_ENCODINGS, false);
         fWarnDuplicateEntityDef = componentManager.getFeature(WARN_ON_DUPLICATE_ENTITYDEF, false);
         fStrictURI = componentManager.getFeature(STANDARD_URI_CONFORMANT, false);
+        fLoadExternalDTD = componentManager.getFeature(LOAD_EXTERNAL_DTD, true);
 
         // xerces properties
         fSymbolTable = (SymbolTable)componentManager.getProperty(SYMBOL_TABLE);
         fErrorReporter = (XMLErrorReporter)componentManager.getProperty(ERROR_REPORTER);
         fEntityResolver = (XMLEntityResolver)componentManager.getProperty(ENTITY_RESOLVER, null);
         fStaxEntityResolver = (StaxEntityResolverWrapper)componentManager.getProperty(STAX_ENTITY_RESOLVER, null);
         fValidationManager = (ValidationManager)componentManager.getProperty(VALIDATION_MANAGER, null);
         fSecurityManager = (SecurityManager)componentManager.getProperty(SECURITY_MANAGER, null);
 
+        // JAXP 1.5 feature 
+        fAccessExternalDTD = (String) componentManager.getProperty(ACCESS_EXTERNAL_DTD, EXTERNAL_ACCESS_DEFAULT);
+
         //reset general state
         reset();
 
         fEntityScanner.reset(componentManager);
         fEntityStorage.reset(componentManager);

@@ -1552,11 +1577,16 @@
             final int suffixLength = featureId.length() - Constants.XERCES_FEATURE_PREFIX.length();
             if (suffixLength == Constants.ALLOW_JAVA_ENCODINGS_FEATURE.length() &&
                 featureId.endsWith(Constants.ALLOW_JAVA_ENCODINGS_FEATURE)) {
                 fAllowJavaEncodings = state;
             }
+            if (suffixLength == Constants.LOAD_EXTERNAL_DTD_FEATURE.length() &&
+                featureId.endsWith(Constants.LOAD_EXTERNAL_DTD_FEATURE)) {
+                fLoadExternalDTD = state;
+                return;
         }
+        }
 
     } // setFeature(String,boolean)
 
     /**
      * Sets the value of a property. This method is called by the component

@@ -1608,11 +1638,19 @@
                 fSecurityManager = (SecurityManager)value;
                 fEntityExpansionLimit = (fSecurityManager != null)?fSecurityManager.getEntityExpansionLimit():0;
             }
         }
 
+        //JAXP 1.5 properties
+        if (propertyId.startsWith(Constants.JAXPAPI_PROPERTY_PREFIX)) {
+            if (propertyId.equals(ACCESS_EXTERNAL_DTD))
+            {
+                fAccessExternalDTD = (String)value;
     }
+        }
+    }
+
     /**
      * Returns a list of property identifiers that are recognized by
      * this component. This method may return null if no properties
      * are recognized by this component.
      */