|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.IO;
using System.Diagnostics;
// using System.Security.Permissions;
using Microsoft.Win32;
using System.Globalization;
using System.Security;
using Microsoft.Xml.Schema;
// using Microsoft.Xml.XmlConfiguration;
using System.Runtime.Versioning;
namespace Microsoft.Xml
{
using System;
// XmlReaderSettings class specifies basic features of an XmlReader.
// [PermissionSetAttribute(SecurityAction.InheritanceDemand, Name = "FullTrust")]
public sealed class XmlReaderSettings
{
//
// Fields
//
#if ASYNC || FEATURE_NETCORE
bool useAsync;
#endif
// Nametable
private XmlNameTable _nameTable;
// XmlResolver
private XmlResolver _xmlResolver;
// Text settings
private int _lineNumberOffset;
private int _linePositionOffset;
// Conformance settings
private ConformanceLevel _conformanceLevel;
private bool _checkCharacters;
private long _maxCharactersInDocument;
private long _maxCharactersFromEntities;
// Filtering settings
private bool _ignoreWhitespace;
private bool _ignorePIs;
private bool _ignoreComments;
// security settings
private DtdProcessing _dtdProcessing;
//Validation settings
private ValidationType _validationType;
private XmlSchemaValidationFlags _validationFlags;
private XmlSchemaSet _schemas;
private ValidationEventHandler _valEventHandler;
// other settings
private bool _closeInput;
// read-only flag
private bool _isReadOnly;
//
// Constructor
//
public XmlReaderSettings()
{
Initialize();
}
#if !FEATURE_LEGACYNETCF
// introduced for supporting design-time loading of phone assemblies
[Obsolete("This API supports the .NET Framework infrastructure and is not intended to be used directly from your code.", true)]
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
#endif
public XmlReaderSettings(XmlResolver resolver)
{
Initialize(resolver);
}
//
// Properties
//
#if ASYNC || FEATURE_NETCORE
public bool Async {
get {
return useAsync;
}
set {
CheckReadOnly("Async");
useAsync = value;
}
}
#endif
// Nametable
public XmlNameTable NameTable
{
get
{
return _nameTable;
}
set
{
CheckReadOnly("NameTable");
_nameTable = value;
}
}
// XmlResolver
internal bool IsXmlResolverSet
{
get;
set; // keep set internal as we need to call it from the schema validation code
}
public XmlResolver XmlResolver
{
set
{
CheckReadOnly("XmlResolver");
_xmlResolver = value;
IsXmlResolverSet = true;
}
}
internal XmlResolver GetXmlResolver()
{
return _xmlResolver;
}
//This is used by get XmlResolver in Xsd.
//Check if the config set to prohibit default resovler
//notice we must keep GetXmlResolver() to avoid dead lock when init System.Config.ConfigurationManager
internal XmlResolver GetXmlResolver_CheckConfig()
{
return _xmlResolver;
}
// Text settings
public int LineNumberOffset
{
get
{
return _lineNumberOffset;
}
set
{
CheckReadOnly("LineNumberOffset");
_lineNumberOffset = value;
}
}
public int LinePositionOffset
{
get
{
return _linePositionOffset;
}
set
{
CheckReadOnly("LinePositionOffset");
_linePositionOffset = value;
}
}
// Conformance settings
public ConformanceLevel ConformanceLevel
{
get
{
return _conformanceLevel;
}
set
{
CheckReadOnly("ConformanceLevel");
if ((uint)value > (uint)ConformanceLevel.Document)
{
throw new ArgumentOutOfRangeException("value");
}
_conformanceLevel = value;
}
}
public bool CheckCharacters
{
get
{
return _checkCharacters;
}
set
{
CheckReadOnly("CheckCharacters");
_checkCharacters = value;
}
}
public long MaxCharactersInDocument
{
get
{
return _maxCharactersInDocument;
}
set
{
CheckReadOnly("MaxCharactersInDocument");
if (value < 0)
{
throw new ArgumentOutOfRangeException("value");
}
_maxCharactersInDocument = value;
}
}
public long MaxCharactersFromEntities
{
get
{
return _maxCharactersFromEntities;
}
set
{
CheckReadOnly("MaxCharactersFromEntities");
if (value < 0)
{
throw new ArgumentOutOfRangeException("value");
}
_maxCharactersFromEntities = value;
}
}
// Filtering settings
public bool IgnoreWhitespace
{
get
{
return _ignoreWhitespace;
}
set
{
CheckReadOnly("IgnoreWhitespace");
_ignoreWhitespace = value;
}
}
public bool IgnoreProcessingInstructions
{
get
{
return _ignorePIs;
}
set
{
CheckReadOnly("IgnoreProcessingInstructions");
_ignorePIs = value;
}
}
public bool IgnoreComments
{
get
{
return _ignoreComments;
}
set
{
CheckReadOnly("IgnoreComments");
_ignoreComments = value;
}
}
[Obsolete("Use XmlReaderSettings.DtdProcessing property instead.")]
public bool ProhibitDtd
{
get
{
return _dtdProcessing == DtdProcessing.Prohibit;
}
set
{
CheckReadOnly("ProhibitDtd");
_dtdProcessing = value ? DtdProcessing.Prohibit : DtdProcessing.Parse;
}
}
public DtdProcessing DtdProcessing
{
get
{
return _dtdProcessing;
}
set
{
CheckReadOnly("DtdProcessing");
if ((uint)value > (uint)DtdProcessing.Parse)
{
throw new ArgumentOutOfRangeException("value");
}
_dtdProcessing = value;
}
}
public bool CloseInput
{
get
{
return _closeInput;
}
set
{
CheckReadOnly("CloseInput");
_closeInput = value;
}
}
public ValidationType ValidationType
{
get
{
return _validationType;
}
set
{
CheckReadOnly("ValidationType");
if ((uint)value > (uint)ValidationType.Schema)
{
throw new ArgumentOutOfRangeException("value");
}
_validationType = value;
}
}
public XmlSchemaValidationFlags ValidationFlags
{
get
{
return _validationFlags;
}
set
{
CheckReadOnly("ValidationFlags");
if ((uint)value > (uint)(XmlSchemaValidationFlags.ProcessInlineSchema | XmlSchemaValidationFlags.ProcessSchemaLocation |
XmlSchemaValidationFlags.ReportValidationWarnings | XmlSchemaValidationFlags.ProcessIdentityConstraints |
XmlSchemaValidationFlags.AllowXmlAttributes))
{
throw new ArgumentOutOfRangeException("value");
}
_validationFlags = value;
}
}
public XmlSchemaSet Schemas
{
get
{
if (_schemas == null)
{
_schemas = new XmlSchemaSet();
}
return _schemas;
}
set
{
CheckReadOnly("Schemas");
_schemas = value;
}
}
public event ValidationEventHandler ValidationEventHandler
{
add
{
CheckReadOnly("ValidationEventHandler");
_valEventHandler += value;
}
remove
{
CheckReadOnly("ValidationEventHandler");
_valEventHandler -= value;
}
}
//
// Public methods
//
public void Reset()
{
CheckReadOnly("Reset");
Initialize();
}
public XmlReaderSettings Clone()
{
XmlReaderSettings clonedSettings = this.MemberwiseClone() as XmlReaderSettings;
clonedSettings.ReadOnly = false;
return clonedSettings;
}
//
// Internal methods
//
internal ValidationEventHandler GetEventHandler()
{
return _valEventHandler;
}
// [ResourceConsumption(ResourceScope.Machine)]
// [ResourceExposure(ResourceScope.Machine)]
internal XmlReader CreateReader(String inputUri, XmlParserContext inputContext)
{
if (inputUri == null)
{
throw new ArgumentNullException("inputUri");
}
if (inputUri.Length == 0)
{
throw new ArgumentException(ResXml.XmlConvert_BadUri, "inputUri");
}
// resolve and open the url
XmlResolver tmpResolver = this.GetXmlResolver();
if (tmpResolver == null)
{
tmpResolver = CreateDefaultResolver();
}
// create text XML reader
XmlReader reader = new XmlTextReaderImpl(inputUri, this, inputContext, tmpResolver);
// wrap with validating reader
if (this.ValidationType != ValidationType.None)
{
reader = AddValidation(reader);
}
#if ASYNC
if (useAsync) {
reader = XmlAsyncCheckReader.CreateAsyncCheckWrapper(reader);
}
#endif
return reader;
}
internal XmlReader CreateReader(Stream input, Uri baseUri, string baseUriString, XmlParserContext inputContext)
{
if (input == null)
{
throw new ArgumentNullException("input");
}
if (baseUriString == null)
{
if (baseUri == null)
{
baseUriString = string.Empty;
}
else
{
baseUriString = baseUri.ToString();
}
}
// create text XML reader
XmlReader reader = new XmlTextReaderImpl(input, null, 0, this, baseUri, baseUriString, inputContext, _closeInput);
// wrap with validating reader
if (this.ValidationType != ValidationType.None)
{
reader = AddValidation(reader);
}
#if ASYNC
if (useAsync) {
reader = XmlAsyncCheckReader.CreateAsyncCheckWrapper(reader);
}
#endif
return reader;
}
internal XmlReader CreateReader(TextReader input, string baseUriString, XmlParserContext inputContext)
{
if (input == null)
{
throw new ArgumentNullException("input");
}
if (baseUriString == null)
{
baseUriString = string.Empty;
}
// create xml text reader
XmlReader reader = new XmlTextReaderImpl(input, this, baseUriString, inputContext);
// wrap with validating reader
if (this.ValidationType != ValidationType.None)
{
reader = AddValidation(reader);
}
#if ASYNC
if (useAsync) {
reader = XmlAsyncCheckReader.CreateAsyncCheckWrapper(reader);
}
#endif
return reader;
}
internal XmlReader CreateReader(XmlReader reader)
{
if (reader == null)
{
throw new ArgumentNullException("reader");
}
#if !ASYNC || SILVERLIGHT || FEATURE_NETCORE
// wrap with conformance layer (if needed)
return AddConformanceWrapper(reader);
#else
return AddValidationAndConformanceWrapper(reader);
#endif // !ASYNC || SILVERLIGHT || FEATURE_NETCORE
}
internal bool ReadOnly
{
get
{
return _isReadOnly;
}
set
{
_isReadOnly = value;
}
}
private void CheckReadOnly(string propertyName)
{
if (_isReadOnly)
{
throw new XmlException(ResXml.Xml_ReadOnlyProperty, this.GetType().Name + '.' + propertyName);
}
}
//
// Private methods
//
private void Initialize()
{
Initialize(null);
}
private void Initialize(XmlResolver resolver)
{
_nameTable = null;
if (!EnableLegacyXmlSettings())
{
_xmlResolver = resolver;
// limit the entity resolving to 10 million character. the caller can still
// override it to any other value or set it to zero for unlimiting it
_maxCharactersFromEntities = (long)1e7;
}
else
{
_xmlResolver = (resolver == null ? CreateDefaultResolver() : resolver);
_maxCharactersFromEntities = 0;
}
_lineNumberOffset = 0;
_linePositionOffset = 0;
_checkCharacters = true;
_conformanceLevel = ConformanceLevel.Document;
_ignoreWhitespace = false;
_ignorePIs = false;
_ignoreComments = false;
_dtdProcessing = DtdProcessing.Prohibit;
_closeInput = false;
_maxCharactersInDocument = 0;
_schemas = null;
_validationType = ValidationType.None;
_validationFlags = XmlSchemaValidationFlags.ProcessIdentityConstraints;
_validationFlags |= XmlSchemaValidationFlags.AllowXmlAttributes;
#if ASYNC || FEATURE_NETCORE
useAsync = false;
#endif
_isReadOnly = false;
IsXmlResolverSet = false;
}
private static XmlResolver CreateDefaultResolver()
{
return new XmlUrlResolver();
}
internal XmlReader AddValidation(XmlReader reader)
{
if (_validationType == ValidationType.Schema)
{
XmlResolver resolver = GetXmlResolver_CheckConfig();
if (resolver == null &&
!this.IsXmlResolverSet &&
!EnableLegacyXmlSettings())
{
resolver = new XmlUrlResolver();
}
reader = new XsdValidatingReader(reader, resolver, this);
}
else if (_validationType == ValidationType.DTD)
{
reader = CreateDtdValidatingReader(reader);
}
return reader;
}
private XmlReader AddValidationAndConformanceWrapper(XmlReader reader)
{
// wrap with DTD validating reader
if (_validationType == ValidationType.DTD)
{
reader = CreateDtdValidatingReader(reader);
}
// add conformance checking (must go after DTD validation because XmlValidatingReader works only on XmlTextReader),
// but before XSD validation because of typed value access
reader = AddConformanceWrapper(reader);
if (_validationType == ValidationType.Schema)
{
reader = new XsdValidatingReader(reader, GetXmlResolver_CheckConfig(), this);
}
return reader;
}
private XmlValidatingReaderImpl CreateDtdValidatingReader(XmlReader baseReader)
{
return new XmlValidatingReaderImpl(baseReader, this.GetEventHandler(), (this.ValidationFlags & XmlSchemaValidationFlags.ProcessIdentityConstraints) != 0);
}
internal XmlReader AddConformanceWrapper(XmlReader baseReader)
{
XmlReaderSettings baseReaderSettings = baseReader.Settings;
bool checkChars = false;
bool noWhitespace = false;
bool noComments = false;
bool noPIs = false;
DtdProcessing dtdProc = (DtdProcessing)(-1);
bool needWrap = false;
if (baseReaderSettings == null)
{
#pragma warning disable 618
if (_conformanceLevel != ConformanceLevel.Auto && _conformanceLevel != XmlReader.GetV1ConformanceLevel(baseReader))
{
throw new InvalidOperationException(string.Format(ResXml.Xml_IncompatibleConformanceLevel, _conformanceLevel.ToString()));
}
// get the V1 XmlTextReader ref
XmlTextReader v1XmlTextReader = baseReader as XmlTextReader;
if (v1XmlTextReader == null)
{
XmlValidatingReader vr = baseReader as XmlValidatingReader;
if (vr != null)
{
v1XmlTextReader = (XmlTextReader)vr.Reader;
}
}
// assume the V1 readers already do all conformance checking;
// wrap only if IgnoreWhitespace, IgnoreComments, IgnoreProcessingInstructions or ProhibitDtd is true;
if (_ignoreWhitespace)
{
WhitespaceHandling wh = WhitespaceHandling.All;
// special-case our V1 readers to see if whey already filter whitespaces
if (v1XmlTextReader != null)
{
wh = v1XmlTextReader.WhitespaceHandling;
}
if (wh == WhitespaceHandling.All)
{
noWhitespace = true;
needWrap = true;
}
}
if (_ignoreComments)
{
noComments = true;
needWrap = true;
}
if (_ignorePIs)
{
noPIs = true;
needWrap = true;
}
// DTD processing
DtdProcessing baseDtdProcessing = DtdProcessing.Parse;
if (v1XmlTextReader != null)
{
baseDtdProcessing = v1XmlTextReader.DtdProcessing;
}
if ((_dtdProcessing == DtdProcessing.Prohibit && baseDtdProcessing != DtdProcessing.Prohibit) ||
(_dtdProcessing == DtdProcessing.Ignore && baseDtdProcessing == DtdProcessing.Parse))
{
dtdProc = _dtdProcessing;
needWrap = true;
}
#pragma warning restore 618
}
else
{
if (_conformanceLevel != baseReaderSettings.ConformanceLevel && _conformanceLevel != ConformanceLevel.Auto)
{
throw new InvalidOperationException(string.Format(ResXml.Xml_IncompatibleConformanceLevel, _conformanceLevel.ToString()));
}
if (_checkCharacters && !baseReaderSettings.CheckCharacters)
{
checkChars = true;
needWrap = true;
}
if (_ignoreWhitespace && !baseReaderSettings.IgnoreWhitespace)
{
noWhitespace = true;
needWrap = true;
}
if (_ignoreComments && !baseReaderSettings.IgnoreComments)
{
noComments = true;
needWrap = true;
}
if (_ignorePIs && !baseReaderSettings.IgnoreProcessingInstructions)
{
noPIs = true;
needWrap = true;
}
if ((_dtdProcessing == DtdProcessing.Prohibit && baseReaderSettings.DtdProcessing != DtdProcessing.Prohibit) ||
(_dtdProcessing == DtdProcessing.Ignore && baseReaderSettings.DtdProcessing == DtdProcessing.Parse))
{
dtdProc = _dtdProcessing;
needWrap = true;
}
}
if (needWrap)
{
IXmlNamespaceResolver readerAsNSResolver = baseReader as IXmlNamespaceResolver;
if (readerAsNSResolver != null)
{
return new XmlCharCheckingReaderWithNS(baseReader, readerAsNSResolver, checkChars, noWhitespace, noComments, noPIs, dtdProc);
}
else
{
return new XmlCharCheckingReader(baseReader, checkChars, noWhitespace, noComments, noPIs, dtdProc);
}
}
else
{
return baseReader;
}
}
private static bool? s_enableLegacyXmlSettings = null;
static internal bool EnableLegacyXmlSettings()
{
return false;
}
}
}
|