1 //------------------------------------------------------------------------------
2 // <copyright file="XmlReaderSettings.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
5 // <owner current="true" primary="true">[....]</owner>
6 //------------------------------------------------------------------------------
9 using System.Diagnostics;
10 using System.Security.Permissions;
12 using Microsoft.Win32;
13 using System.Globalization;
14 using System.Security;
15 using System.Xml.Schema;
16 using System.Xml.XmlConfiguration;
18 using System.Runtime.Versioning;
20 namespace System.Xml {
22 // XmlReaderSettings class specifies basic features of an XmlReader.
23 #if !SILVERLIGHT && !MOBILE
24 [PermissionSetAttribute(SecurityAction.InheritanceDemand, Name = "FullTrust")]
26 public sealed class XmlReaderSettings {
32 #if ASYNC || FEATURE_NETCORE
38 XmlNameTable nameTable;
41 XmlResolver xmlResolver;
45 int linePositionOffset;
47 // Conformance settings
48 ConformanceLevel conformanceLevel;
51 long maxCharactersInDocument;
52 long maxCharactersFromEntities;
55 bool ignoreWhitespace;
60 DtdProcessing dtdProcessing;
64 ValidationType validationType;
65 XmlSchemaValidationFlags validationFlags;
67 ValidationEventHandler valEventHandler;
79 public XmlReaderSettings() {
83 #if !FEATURE_LEGACYNETCF
84 // introduced for supporting design-time loading of phone assemblies
85 [Obsolete("This API supports the .NET Framework infrastructure and is not intended to be used directly from your code.", true)]
86 [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
88 public XmlReaderSettings(XmlResolver resolver) {
96 #if ASYNC || FEATURE_NETCORE
102 CheckReadOnly("Async");
109 public XmlNameTable NameTable {
114 CheckReadOnly("NameTable");
121 internal bool IsXmlResolverSet {
123 set; // keep set internal as we need to call it from the schema validation code
127 public XmlResolver XmlResolver {
129 CheckReadOnly("XmlResolver");
132 IsXmlResolverSet = true;
137 internal XmlResolver GetXmlResolver() {
141 #if !SILVERLIGHT && !MOBILE
142 //This is used by get XmlResolver in Xsd.
143 //Check if the config set to prohibit default resovler
144 //notice we must keep GetXmlResolver() to avoid dead lock when init System.Config.ConfigurationManager
145 internal XmlResolver GetXmlResolver_CheckConfig() {
146 if (System.Xml.XmlConfiguration.XmlReaderSection.ProhibitDefaultUrlResolver && !IsXmlResolverSet)
154 public int LineNumberOffset {
156 return lineNumberOffset;
159 CheckReadOnly("LineNumberOffset");
160 lineNumberOffset = value;
164 public int LinePositionOffset {
166 return linePositionOffset;
169 CheckReadOnly("LinePositionOffset");
170 linePositionOffset = value;
174 // Conformance settings
175 public ConformanceLevel ConformanceLevel {
177 return conformanceLevel;
180 CheckReadOnly("ConformanceLevel");
182 if ((uint)value > (uint)ConformanceLevel.Document) {
183 throw new ArgumentOutOfRangeException("value");
185 conformanceLevel = value;
189 public bool CheckCharacters {
191 return checkCharacters;
194 CheckReadOnly("CheckCharacters");
195 checkCharacters = value;
199 public long MaxCharactersInDocument {
201 return maxCharactersInDocument;
204 CheckReadOnly("MaxCharactersInDocument");
206 throw new ArgumentOutOfRangeException("value");
208 maxCharactersInDocument = value;
212 public long MaxCharactersFromEntities {
214 return maxCharactersFromEntities;
217 CheckReadOnly("MaxCharactersFromEntities");
219 throw new ArgumentOutOfRangeException("value");
221 maxCharactersFromEntities = value;
225 // Filtering settings
226 public bool IgnoreWhitespace {
228 return ignoreWhitespace;
231 CheckReadOnly("IgnoreWhitespace");
232 ignoreWhitespace = value;
236 public bool IgnoreProcessingInstructions {
241 CheckReadOnly("IgnoreProcessingInstructions");
246 public bool IgnoreComments {
248 return ignoreComments;
251 CheckReadOnly("IgnoreComments");
252 ignoreComments = value;
257 [Obsolete("Use XmlReaderSettings.DtdProcessing property instead.")]
258 public bool ProhibitDtd {
260 return dtdProcessing == DtdProcessing.Prohibit;
263 CheckReadOnly("ProhibitDtd");
264 dtdProcessing = value ? DtdProcessing.Prohibit : DtdProcessing.Parse;
269 public DtdProcessing DtdProcessing {
271 return dtdProcessing;
274 CheckReadOnly("DtdProcessing");
276 if ((uint)value > (uint)DtdProcessing.Parse) {
277 throw new ArgumentOutOfRangeException("value");
279 dtdProcessing = value;
283 public bool CloseInput {
288 CheckReadOnly("CloseInput");
294 public ValidationType ValidationType {
296 return validationType;
299 CheckReadOnly("ValidationType");
301 if ((uint)value > (uint)ValidationType.Schema) {
302 throw new ArgumentOutOfRangeException("value");
304 validationType = value;
308 public XmlSchemaValidationFlags ValidationFlags {
310 return validationFlags;
313 CheckReadOnly("ValidationFlags");
315 if ((uint)value > (uint)(XmlSchemaValidationFlags.ProcessInlineSchema | XmlSchemaValidationFlags.ProcessSchemaLocation |
316 XmlSchemaValidationFlags.ReportValidationWarnings | XmlSchemaValidationFlags.ProcessIdentityConstraints |
317 XmlSchemaValidationFlags.AllowXmlAttributes)) {
318 throw new ArgumentOutOfRangeException("value");
320 validationFlags = value;
324 public XmlSchemaSet Schemas {
326 if (schemas == null) {
327 schemas = new XmlSchemaSet();
332 CheckReadOnly("Schemas");
337 public event ValidationEventHandler ValidationEventHandler {
339 CheckReadOnly("ValidationEventHandler");
340 valEventHandler += value;
343 CheckReadOnly("ValidationEventHandler");
344 valEventHandler -= value;
352 public void Reset() {
353 CheckReadOnly("Reset");
357 public XmlReaderSettings Clone() {
358 XmlReaderSettings clonedSettings = this.MemberwiseClone() as XmlReaderSettings;
359 clonedSettings.ReadOnly = false;
360 return clonedSettings;
367 internal ValidationEventHandler GetEventHandler() {
368 return valEventHandler;
374 [ResourceConsumption(ResourceScope.Machine)]
375 [ResourceExposure(ResourceScope.Machine)]
377 internal XmlReader CreateReader(String inputUri, XmlParserContext inputContext) {
378 if (inputUri == null) {
379 throw new ArgumentNullException("inputUri");
381 if (inputUri.Length == 0) {
382 throw new ArgumentException(Res.GetString(Res.XmlConvert_BadUri), "inputUri");
385 // resolve and open the url
386 XmlResolver tmpResolver = this.GetXmlResolver();
387 if (tmpResolver == null) {
388 tmpResolver = CreateDefaultResolver();
391 // create text XML reader
392 XmlReader reader = new XmlTextReaderImpl(inputUri, this, inputContext, tmpResolver);
395 // wrap with validating reader
396 if (this.ValidationType != ValidationType.None) {
397 reader = AddValidation(reader);
403 reader = XmlAsyncCheckReader.CreateAsyncCheckWrapper(reader);
409 internal XmlReader CreateReader(Stream input, Uri baseUri, string baseUriString, XmlParserContext inputContext) {
411 throw new ArgumentNullException("input");
413 if (baseUriString == null) {
414 if (baseUri == null) {
415 baseUriString = string.Empty;
418 baseUriString = baseUri.ToString();
422 // create text XML reader
423 XmlReader reader = new XmlTextReaderImpl(input, null, 0, this, baseUri, baseUriString, inputContext, closeInput);
426 // wrap with validating reader
427 if (this.ValidationType != ValidationType.None) {
428 reader = AddValidation(reader);
434 reader = XmlAsyncCheckReader.CreateAsyncCheckWrapper(reader);
441 internal XmlReader CreateReader(TextReader input, string baseUriString, XmlParserContext inputContext) {
443 throw new ArgumentNullException("input");
445 if (baseUriString == null) {
446 baseUriString = string.Empty;
449 // create xml text reader
450 XmlReader reader = new XmlTextReaderImpl(input, this, baseUriString, inputContext);
453 // wrap with validating reader
454 if (this.ValidationType != ValidationType.None) {
455 reader = AddValidation(reader);
461 reader = XmlAsyncCheckReader.CreateAsyncCheckWrapper(reader);
468 internal XmlReader CreateReader(XmlReader reader) {
469 if (reader == null) {
470 throw new ArgumentNullException("reader");
472 #if !ASYNC || SILVERLIGHT || FEATURE_NETCORE
473 // wrap with conformance layer (if needed)
474 return AddConformanceWrapper(reader);
476 return AddValidationAndConformanceWrapper(reader);
477 #endif // !ASYNC || SILVERLIGHT || FEATURE_NETCORE
480 internal bool ReadOnly {
489 void CheckReadOnly(string propertyName) {
491 throw new XmlException(Res.Xml_ReadOnlyProperty, this.GetType().Name + '.' + propertyName);
502 void Initialize(XmlResolver resolver) {
504 #if !SILVERLIGHT && !MOBILE
505 if (!EnableLegacyXmlSettings())
507 xmlResolver = resolver;
508 // limit the entity resolving to 10 million character. the caller can still
509 // override it to any other value or set it to zero for unlimiting it
510 maxCharactersFromEntities = (long) 1e7;
515 xmlResolver = (resolver == null ? CreateDefaultResolver() : resolver);
516 maxCharactersFromEntities = 0;
518 lineNumberOffset = 0;
519 linePositionOffset = 0;
520 checkCharacters = true;
521 conformanceLevel = ConformanceLevel.Document;
523 ignoreWhitespace = false;
525 ignoreComments = false;
526 dtdProcessing = DtdProcessing.Prohibit;
529 maxCharactersInDocument = 0;
533 validationType = ValidationType.None;
534 validationFlags = XmlSchemaValidationFlags.ProcessIdentityConstraints;
535 validationFlags |= XmlSchemaValidationFlags.AllowXmlAttributes;
538 #if ASYNC || FEATURE_NETCORE
544 IsXmlResolverSet = false;
548 static XmlResolver CreateDefaultResolver() {
550 return new XmlXapResolver();
552 return new XmlUrlResolver();
557 internal XmlReader AddValidation(XmlReader reader) {
558 if (this.validationType == ValidationType.Schema) {
559 XmlResolver resolver = GetXmlResolver_CheckConfig();
561 if (resolver == null &&
562 !this.IsXmlResolverSet &&
563 !EnableLegacyXmlSettings())
565 resolver = new XmlUrlResolver();
567 reader = new XsdValidatingReader(reader, resolver, this);
569 else if (this.validationType == ValidationType.DTD) {
570 reader = CreateDtdValidatingReader(reader);
575 private XmlReader AddValidationAndConformanceWrapper(XmlReader reader) {
576 // wrap with DTD validating reader
577 if (this.validationType == ValidationType.DTD) {
578 reader = CreateDtdValidatingReader(reader);
580 // add conformance checking (must go after DTD validation because XmlValidatingReader works only on XmlTextReader),
581 // but before XSD validation because of typed value access
582 reader = AddConformanceWrapper(reader);
584 if (this.validationType == ValidationType.Schema) {
585 reader = new XsdValidatingReader(reader, GetXmlResolver_CheckConfig(), this);
590 private XmlValidatingReaderImpl CreateDtdValidatingReader(XmlReader baseReader) {
591 return new XmlValidatingReaderImpl(baseReader, this.GetEventHandler(), (this.ValidationFlags & XmlSchemaValidationFlags.ProcessIdentityConstraints) != 0);
593 #endif // !SILVERLIGHT
595 internal XmlReader AddConformanceWrapper(XmlReader baseReader) {
596 XmlReaderSettings baseReaderSettings = baseReader.Settings;
597 bool checkChars = false;
598 bool noWhitespace = false;
599 bool noComments = false;
601 DtdProcessing dtdProc = (DtdProcessing)(-1);
602 bool needWrap = false;
604 if (baseReaderSettings == null) {
606 #pragma warning disable 618
609 if (this.conformanceLevel != ConformanceLevel.Auto) {
610 throw new InvalidOperationException(Res.GetString(Res.Xml_IncompatibleConformanceLevel, this.conformanceLevel.ToString()));
613 if (this.conformanceLevel != ConformanceLevel.Auto && this.conformanceLevel != XmlReader.GetV1ConformanceLevel(baseReader)) {
614 throw new InvalidOperationException(Res.GetString(Res.Xml_IncompatibleConformanceLevel, this.conformanceLevel.ToString()));
619 // get the V1 XmlTextReader ref
620 XmlTextReader v1XmlTextReader = baseReader as XmlTextReader;
621 if (v1XmlTextReader == null) {
622 XmlValidatingReader vr = baseReader as XmlValidatingReader;
624 v1XmlTextReader = (XmlTextReader)vr.Reader;
629 // assume the V1 readers already do all conformance checking;
630 // wrap only if IgnoreWhitespace, IgnoreComments, IgnoreProcessingInstructions or ProhibitDtd is true;
631 if (this.ignoreWhitespace) {
632 WhitespaceHandling wh = WhitespaceHandling.All;
634 // special-case our V1 readers to see if whey already filter whitespaces
635 if (v1XmlTextReader != null) {
636 wh = v1XmlTextReader.WhitespaceHandling;
639 if (wh == WhitespaceHandling.All) {
644 if (this.ignoreComments) {
648 if (this.ignorePIs) {
653 DtdProcessing baseDtdProcessing = DtdProcessing.Parse;
655 if (v1XmlTextReader != null) {
656 baseDtdProcessing = v1XmlTextReader.DtdProcessing;
659 if ((this.dtdProcessing == DtdProcessing.Prohibit && baseDtdProcessing != DtdProcessing.Prohibit) ||
660 (this.dtdProcessing == DtdProcessing.Ignore && baseDtdProcessing == DtdProcessing.Parse)) {
661 dtdProc = this.dtdProcessing;
664 #pragma warning restore 618
667 if (this.conformanceLevel != baseReaderSettings.ConformanceLevel && this.conformanceLevel != ConformanceLevel.Auto) {
668 throw new InvalidOperationException(Res.GetString(Res.Xml_IncompatibleConformanceLevel, this.conformanceLevel.ToString()));
670 if (this.checkCharacters && !baseReaderSettings.CheckCharacters) {
674 if (this.ignoreWhitespace && !baseReaderSettings.IgnoreWhitespace) {
678 if (this.ignoreComments && !baseReaderSettings.IgnoreComments) {
682 if (this.ignorePIs && !baseReaderSettings.IgnoreProcessingInstructions) {
687 if ((this.dtdProcessing == DtdProcessing.Prohibit && baseReaderSettings.DtdProcessing != DtdProcessing.Prohibit) ||
688 (this.dtdProcessing == DtdProcessing.Ignore && baseReaderSettings.DtdProcessing == DtdProcessing.Parse)) {
689 dtdProc = this.dtdProcessing;
695 IXmlNamespaceResolver readerAsNSResolver = baseReader as IXmlNamespaceResolver;
696 if (readerAsNSResolver != null) {
697 return new XmlCharCheckingReaderWithNS(baseReader, readerAsNSResolver, checkChars, noWhitespace, noComments, noPIs, dtdProc);
700 return new XmlCharCheckingReader(baseReader, checkChars, noWhitespace, noComments, noPIs, dtdProc);
708 #if !SILVERLIGHT && !MOBILE
709 private static bool? s_enableLegacyXmlSettings = null;
711 static internal bool EnableLegacyXmlSettings()
713 if (s_enableLegacyXmlSettings.HasValue)
715 return s_enableLegacyXmlSettings.Value;
718 if (!System.Xml.BinaryCompatibility.TargetsAtLeast_Desktop_V4_5_2)
720 s_enableLegacyXmlSettings = true;
721 return s_enableLegacyXmlSettings.Value;
724 bool enableSettings = false; // default value
725 if (!ReadSettingsFromRegistry(Registry.LocalMachine, ref enableSettings))
727 // still ok if this call return false too as we'll use the default value which is false
728 ReadSettingsFromRegistry(Registry.CurrentUser, ref enableSettings);
731 s_enableLegacyXmlSettings = enableSettings;
732 return s_enableLegacyXmlSettings.Value;
735 [RegistryPermission(SecurityAction.Assert, Unrestricted = true)]
736 [SecuritySafeCritical]
737 private static bool ReadSettingsFromRegistry(RegistryKey hive, ref bool value)
739 const string regValueName = "EnableLegacyXmlSettings";
740 const string regValuePath = @"SOFTWARE\Microsoft\.NETFramework\XML";
744 using (RegistryKey xmlRegKey = hive.OpenSubKey(regValuePath, false))
746 if (xmlRegKey != null)
748 if (xmlRegKey.GetValueKind(regValueName) == RegistryValueKind.DWord)
750 value = ((int)xmlRegKey.GetValue(regValueName)) == 1;
756 catch { /* use the default if we couldn't read the key */ }
761 #endif // SILVERLIGHT