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