1 2 using System; 3 using System.IO; 4 using System.Text; 5 using System.Xml.Schema; 6 using System.Collections; 7 using System.Diagnostics; 8 using System.Globalization; 9 using System.Security.Policy; 10 using System.Collections.Generic; 11 using System.Security.Permissions; 12 using System.Runtime.Versioning; 13 14 using System.Threading.Tasks; 15 16 namespace System.Xml 17 { 18 internal sealed partial class XmlValidatingReaderImpl : XmlReader, IXmlLineInfo, IXmlNamespaceResolver { 19 20 // Returns the text value of the current node. GetValueAsync()21 public override Task<string> GetValueAsync() { 22 return coreReader.GetValueAsync(); 23 } 24 25 // Reads and validated next node from the input data ReadAsync()26 public override async Task< bool > ReadAsync() { 27 switch ( parsingFunction ) { 28 case ParsingFunction.Read: 29 if ( await coreReader.ReadAsync().ConfigureAwait(false) ) { 30 ProcessCoreReaderEvent(); 31 return true; 32 } 33 else { 34 validator.CompleteValidation(); 35 return false; 36 } 37 case ParsingFunction.ParseDtdFromContext: 38 parsingFunction = ParsingFunction.Read; 39 await ParseDtdFromParserContextAsync().ConfigureAwait(false); 40 goto case ParsingFunction.Read; 41 case ParsingFunction.Error: 42 case ParsingFunction.ReaderClosed: 43 return false; 44 case ParsingFunction.Init: 45 parsingFunction = ParsingFunction.Read; // this changes the value returned by ReadState 46 if ( coreReader.ReadState == ReadState.Interactive ) { 47 ProcessCoreReaderEvent(); 48 return true; 49 } 50 else { 51 goto case ParsingFunction.Read; 52 } 53 case ParsingFunction.ResolveEntityInternally: 54 parsingFunction = ParsingFunction.Read; 55 await ResolveEntityInternallyAsync().ConfigureAwait(false); 56 goto case ParsingFunction.Read; 57 case ParsingFunction.InReadBinaryContent: 58 parsingFunction = ParsingFunction.Read; 59 await readBinaryHelper.FinishAsync().ConfigureAwait(false); 60 goto case ParsingFunction.Read; 61 default: 62 Debug.Assert( false ); 63 return false; 64 } 65 } 66 ReadContentAsBase64Async( byte[] buffer, int index, int count )67 public override async Task< int > ReadContentAsBase64Async( byte[] buffer, int index, int count ) { 68 if ( ReadState != ReadState.Interactive ) { 69 return 0; 70 } 71 72 // init ReadChunkHelper if called the first time 73 if ( parsingFunction != ParsingFunction.InReadBinaryContent ) { 74 readBinaryHelper = ReadContentAsBinaryHelper.CreateOrReset( readBinaryHelper, outerReader ); 75 } 76 77 // set parsingFunction to Read state in order to have a normal Read() behavior when called from readBinaryHelper 78 parsingFunction = ParsingFunction.Read; 79 80 // call to the helper 81 int readCount = await readBinaryHelper.ReadContentAsBase64Async( buffer, index, count ).ConfigureAwait(false); 82 83 // setup parsingFunction 84 parsingFunction = ParsingFunction.InReadBinaryContent; 85 return readCount; 86 } 87 ReadContentAsBinHexAsync( byte[] buffer, int index, int count )88 public override async Task< int > ReadContentAsBinHexAsync( byte[] buffer, int index, int count ) { 89 if ( ReadState != ReadState.Interactive ) { 90 return 0; 91 } 92 93 // init ReadChunkHelper when called first time 94 if ( parsingFunction != ParsingFunction.InReadBinaryContent ) { 95 readBinaryHelper = ReadContentAsBinaryHelper.CreateOrReset( readBinaryHelper, outerReader ); 96 } 97 98 // set parsingFunction to Read state in order to have a normal Read() behavior when called from readBinaryHelper 99 parsingFunction = ParsingFunction.Read; 100 101 // call to the helper 102 int readCount = await readBinaryHelper.ReadContentAsBinHexAsync( buffer, index, count ).ConfigureAwait(false); 103 104 // setup parsingFunction 105 parsingFunction = ParsingFunction.InReadBinaryContent; 106 return readCount; 107 } 108 ReadElementContentAsBase64Async( byte[] buffer, int index, int count )109 public override async Task< int > ReadElementContentAsBase64Async( byte[] buffer, int index, int count ) { 110 if ( ReadState != ReadState.Interactive ) { 111 return 0; 112 } 113 114 // init ReadChunkHelper if called the first time 115 if ( parsingFunction != ParsingFunction.InReadBinaryContent ) { 116 readBinaryHelper = ReadContentAsBinaryHelper.CreateOrReset( readBinaryHelper, outerReader ); 117 } 118 119 // set parsingFunction to Read state in order to have a normal Read() behavior when called from readBinaryHelper 120 parsingFunction = ParsingFunction.Read; 121 122 // call to the helper 123 int readCount = await readBinaryHelper.ReadElementContentAsBase64Async( buffer, index, count ).ConfigureAwait(false); 124 125 // setup parsingFunction 126 parsingFunction = ParsingFunction.InReadBinaryContent; 127 return readCount; 128 } 129 ReadElementContentAsBinHexAsync( byte[] buffer, int index, int count )130 public override async Task< int > ReadElementContentAsBinHexAsync( byte[] buffer, int index, int count ) { 131 if ( ReadState != ReadState.Interactive ) { 132 return 0; 133 } 134 135 // init ReadChunkHelper when called first time 136 if ( parsingFunction != ParsingFunction.InReadBinaryContent ) { 137 readBinaryHelper = ReadContentAsBinaryHelper.CreateOrReset( readBinaryHelper, outerReader ); 138 } 139 140 // set parsingFunction to Read state in order to have a normal Read() behavior when called from readBinaryHelper 141 parsingFunction = ParsingFunction.Read; 142 143 // call to the helper 144 int readCount = await readBinaryHelper.ReadElementContentAsBinHexAsync( buffer, index, count ).ConfigureAwait(false); 145 146 // setup parsingFunction 147 parsingFunction = ParsingFunction.InReadBinaryContent; 148 return readCount; 149 } 150 MoveOffEntityReferenceAsync()151 internal async Task MoveOffEntityReferenceAsync() { 152 if ( outerReader.NodeType == XmlNodeType.EntityReference && parsingFunction != ParsingFunction.ResolveEntityInternally ) { 153 if ( !await outerReader.ReadAsync().ConfigureAwait(false) ) { 154 throw new InvalidOperationException( Res.GetString(Res.Xml_InvalidOperation ) ); 155 } 156 } 157 } 158 159 // Returns typed value of the current node (based on the type specified by schema) ReadTypedValueAsync()160 public async Task< object > ReadTypedValueAsync() { 161 if ( validationType == ValidationType.None ) { 162 return null; 163 } 164 165 switch ( outerReader.NodeType ) { 166 case XmlNodeType.Attribute: 167 return coreReaderImpl.InternalTypedValue; 168 case XmlNodeType.Element: 169 if ( SchemaType == null ) { 170 return null; 171 } 172 XmlSchemaDatatype dtype = ( SchemaType is XmlSchemaDatatype ) ? (XmlSchemaDatatype)SchemaType : ((XmlSchemaType)SchemaType).Datatype; 173 if ( dtype != null ) { 174 if ( !outerReader.IsEmptyElement ) { 175 for (;;) { 176 if ( !await outerReader.ReadAsync().ConfigureAwait(false) ) { 177 throw new InvalidOperationException( Res.GetString( Res.Xml_InvalidOperation ) ); 178 } 179 XmlNodeType type = outerReader.NodeType; 180 if ( type != XmlNodeType.CDATA && type != XmlNodeType.Text && 181 type != XmlNodeType.Whitespace && type != XmlNodeType.SignificantWhitespace && 182 type != XmlNodeType.Comment && type != XmlNodeType.ProcessingInstruction ) { 183 break; 184 } 185 } 186 if ( outerReader.NodeType != XmlNodeType.EndElement ) { 187 throw new XmlException( Res.Xml_InvalidNodeType, outerReader.NodeType.ToString()); 188 } 189 } 190 return coreReaderImpl.InternalTypedValue; 191 } 192 return null; 193 194 case XmlNodeType.EndElement: 195 return null; 196 197 default: 198 if ( coreReaderImpl.V1Compat ) { //If v1 XmlValidatingReader return null 199 return null; 200 } 201 else { 202 return await GetValueAsync().ConfigureAwait(false); 203 } 204 } 205 } 206 207 // 208 // Private implementation methods 209 // 210 ParseDtdFromParserContextAsync()211 private async Task ParseDtdFromParserContextAsync() 212 { 213 Debug.Assert( parserContext != null ); 214 Debug.Assert( coreReaderImpl.DtdInfo == null ); 215 216 if ( parserContext.DocTypeName == null || parserContext.DocTypeName.Length == 0 ) { 217 return; 218 } 219 220 IDtdParser dtdParser = DtdParser.Create(); 221 XmlTextReaderImpl.DtdParserProxy proxy = new XmlTextReaderImpl.DtdParserProxy(coreReaderImpl); 222 IDtdInfo dtdInfo = await dtdParser.ParseFreeFloatingDtdAsync( parserContext.BaseURI, parserContext.DocTypeName, parserContext.PublicId, parserContext.SystemId, parserContext.InternalSubset, proxy ).ConfigureAwait(false); 223 coreReaderImpl.SetDtdInfo( dtdInfo); 224 225 ValidateDtd(); 226 } 227 ResolveEntityInternallyAsync()228 private async Task ResolveEntityInternallyAsync() { 229 Debug.Assert( coreReader.NodeType == XmlNodeType.EntityReference ); 230 int initialDepth = coreReader.Depth; 231 outerReader.ResolveEntity(); 232 while ( await outerReader.ReadAsync().ConfigureAwait(false) && coreReader.Depth > initialDepth ); 233 } 234 235 } 236 } 237 238