1 2 using System; 3 using System.Xml; 4 using System.Diagnostics; 5 using System.Collections; 6 using System.Collections.Generic; 7 8 using System.Threading.Tasks; 9 10 namespace System.Xml { 11 12 // 13 // XmlCharCheckingReaderWithNS 14 // 15 internal partial class XmlCharCheckingReader : XmlWrappingReader { 16 ReadAsync()17 public override async Task< bool > ReadAsync() { 18 switch ( state ) { 19 case State.Initial: 20 state = State.Interactive; 21 if ( base.reader.ReadState == ReadState.Initial ) { 22 goto case State.Interactive; 23 } 24 break; 25 26 case State.Error: 27 return false; 28 29 case State.InReadBinary: 30 await FinishReadBinaryAsync().ConfigureAwait(false); 31 state = State.Interactive; 32 goto case State.Interactive; 33 34 case State.Interactive: 35 if ( !await base.reader.ReadAsync().ConfigureAwait(false) ) { 36 return false; 37 } 38 break; 39 40 default: 41 Debug.Assert( false ); 42 return false; 43 } 44 45 XmlNodeType nodeType = base.reader.NodeType; 46 47 if ( !checkCharacters ) { 48 switch ( nodeType ) { 49 case XmlNodeType.Comment: 50 if ( ignoreComments ) { 51 return await ReadAsync().ConfigureAwait(false); 52 } 53 break; 54 case XmlNodeType.Whitespace: 55 if ( ignoreWhitespace ) { 56 return await ReadAsync().ConfigureAwait(false); 57 } 58 break; 59 case XmlNodeType.ProcessingInstruction: 60 if ( ignorePis ) { 61 return await ReadAsync().ConfigureAwait(false); 62 } 63 break; 64 case XmlNodeType.DocumentType: 65 if ( dtdProcessing == DtdProcessing.Prohibit ) { 66 Throw( Res.Xml_DtdIsProhibitedEx, string.Empty ); 67 } 68 else if ( dtdProcessing == DtdProcessing.Ignore ) { 69 return await ReadAsync().ConfigureAwait(false); 70 } 71 break; 72 } 73 return true; 74 } 75 else { 76 switch ( nodeType ) { 77 case XmlNodeType.Element: 78 if ( checkCharacters ) { 79 // check element name 80 ValidateQName( base.reader.Prefix, base.reader.LocalName ); 81 82 // check values of attributes 83 if ( base.reader.MoveToFirstAttribute() ) { 84 do { 85 ValidateQName( base.reader.Prefix, base.reader.LocalName ); 86 CheckCharacters( base.reader.Value ); 87 } while ( base.reader.MoveToNextAttribute() ); 88 89 base.reader.MoveToElement(); 90 } 91 } 92 break; 93 94 case XmlNodeType.Text: 95 case XmlNodeType.CDATA: 96 if ( checkCharacters ) { 97 CheckCharacters( await base.reader.GetValueAsync().ConfigureAwait(false) ); 98 } 99 break; 100 101 case XmlNodeType.EntityReference: 102 if ( checkCharacters ) { 103 // check name 104 ValidateQName( base.reader.Name ); 105 } 106 break; 107 108 case XmlNodeType.ProcessingInstruction: 109 if ( ignorePis ) { 110 return await ReadAsync().ConfigureAwait(false); 111 } 112 if ( checkCharacters ) { 113 ValidateQName( base.reader.Name ); 114 CheckCharacters( base.reader.Value ); 115 } 116 break; 117 118 case XmlNodeType.Comment: 119 if ( ignoreComments ) { 120 return await ReadAsync().ConfigureAwait(false); 121 } 122 if ( checkCharacters ) { 123 CheckCharacters( base.reader.Value ); 124 } 125 break; 126 127 case XmlNodeType.DocumentType: 128 if ( dtdProcessing == DtdProcessing.Prohibit ) { 129 Throw( Res.Xml_DtdIsProhibitedEx, string.Empty ); 130 } 131 else if ( dtdProcessing == DtdProcessing.Ignore ) { 132 return await ReadAsync().ConfigureAwait(false); 133 } 134 if ( checkCharacters ) { 135 ValidateQName( base.reader.Name ); 136 CheckCharacters( base.reader.Value ); 137 138 string str; 139 str = base.reader.GetAttribute( "SYSTEM" ); 140 if ( str != null ) { 141 CheckCharacters( str ); 142 } 143 144 str = base.reader.GetAttribute( "PUBLIC" ); 145 if ( str != null ) { 146 int i; 147 if ( ( i = xmlCharType.IsPublicId( str ) ) >= 0 ) { 148 Throw( Res.Xml_InvalidCharacter, XmlException.BuildCharExceptionArgs( str, i ) ); 149 } 150 } 151 } 152 break; 153 154 case XmlNodeType.Whitespace: 155 if ( ignoreWhitespace ) { 156 return await ReadAsync().ConfigureAwait(false); 157 } 158 if ( checkCharacters ) { 159 CheckWhitespace( await base.reader.GetValueAsync().ConfigureAwait(false) ); 160 } 161 break; 162 163 case XmlNodeType.SignificantWhitespace: 164 if ( checkCharacters ) { 165 CheckWhitespace( await base.reader.GetValueAsync().ConfigureAwait(false) ); 166 } 167 break; 168 169 case XmlNodeType.EndElement: 170 if ( checkCharacters ) { 171 ValidateQName( base.reader.Prefix, base.reader.LocalName ); 172 } 173 break; 174 175 default: 176 break; 177 } 178 lastNodeType = nodeType; 179 return true; 180 } 181 } 182 ReadContentAsBase64Async( byte[] buffer, int index, int count )183 public override async Task< int > ReadContentAsBase64Async( byte[] buffer, int index, int count ) { 184 if (ReadState != ReadState.Interactive) { 185 return 0; 186 } 187 188 if ( state != State.InReadBinary ) { 189 // forward ReadBase64Chunk calls into the base (wrapped) reader if possible, i.e. if it can read binary and we 190 // should not check characters 191 if ( base.CanReadBinaryContent && ( !checkCharacters ) ) { 192 readBinaryHelper = null; 193 state = State.InReadBinary; 194 return await base.ReadContentAsBase64Async( buffer, index, count ).ConfigureAwait(false); 195 } 196 // the wrapped reader cannot read chunks or we are on an element where we should check characters or ignore white spaces 197 else { 198 readBinaryHelper = ReadContentAsBinaryHelper.CreateOrReset( readBinaryHelper, this ); 199 } 200 } 201 else { 202 // forward calls into wrapped reader 203 if ( readBinaryHelper == null ) { 204 return await base.ReadContentAsBase64Async( buffer, index, count ).ConfigureAwait(false); 205 } 206 } 207 208 // turn off InReadBinary state in order to have a normal Read() behavior when called from readBinaryHelper 209 state = State.Interactive; 210 211 // call to the helper 212 int readCount = await readBinaryHelper.ReadContentAsBase64Async(buffer, index, count).ConfigureAwait(false); 213 214 // turn on InReadBinary in again and return 215 state = State.InReadBinary; 216 return readCount; 217 } 218 ReadContentAsBinHexAsync( byte[] buffer, int index, int count )219 public override async Task< int > ReadContentAsBinHexAsync( byte[] buffer, int index, int count ) { 220 if (ReadState != ReadState.Interactive) { 221 return 0; 222 } 223 224 if ( state != State.InReadBinary ) { 225 // forward ReadBinHexChunk calls into the base (wrapped) reader if possible, i.e. if it can read chunks and we 226 // should not check characters 227 if ( base.CanReadBinaryContent && ( !checkCharacters ) ) { 228 readBinaryHelper = null; 229 state = State.InReadBinary; 230 return await base.ReadContentAsBinHexAsync( buffer, index, count ).ConfigureAwait(false); 231 } 232 // the wrapped reader cannot read chunks or we are on an element where we should check characters or ignore white spaces 233 else { 234 readBinaryHelper = ReadContentAsBinaryHelper.CreateOrReset( readBinaryHelper, this ); 235 } 236 } 237 else { 238 // forward calls into wrapped reader 239 if ( readBinaryHelper == null ) { 240 return await base.ReadContentAsBinHexAsync( buffer, index, count ).ConfigureAwait(false); 241 } 242 } 243 244 // turn off InReadBinary state in order to have a normal Read() behavior when called from readBinaryHelper 245 state = State.Interactive; 246 247 // call to the helper 248 int readCount = await readBinaryHelper.ReadContentAsBinHexAsync(buffer, index, count).ConfigureAwait(false); 249 250 // turn on InReadBinary in again and return 251 state = State.InReadBinary; 252 return readCount; 253 } 254 ReadElementContentAsBase64Async( byte[] buffer, int index, int count )255 public override async Task< int > ReadElementContentAsBase64Async( byte[] buffer, int index, int count ) { 256 // check arguments 257 if (buffer == null) { 258 throw new ArgumentNullException("buffer"); 259 } 260 if (count < 0) { 261 throw new ArgumentOutOfRangeException("count"); 262 } 263 if (index < 0) { 264 throw new ArgumentOutOfRangeException("index"); 265 } 266 if (buffer.Length - index < count) { 267 throw new ArgumentOutOfRangeException("count"); 268 } 269 270 if (ReadState != ReadState.Interactive) { 271 return 0; 272 } 273 274 if ( state != State.InReadBinary ) { 275 // forward ReadBase64Chunk calls into the base (wrapped) reader if possible, i.e. if it can read binary and we 276 // should not check characters 277 if ( base.CanReadBinaryContent && ( !checkCharacters ) ) { 278 readBinaryHelper = null; 279 state = State.InReadBinary; 280 return await base.ReadElementContentAsBase64Async( buffer, index, count ).ConfigureAwait(false); 281 } 282 // the wrapped reader cannot read chunks or we are on an element where we should check characters or ignore white spaces 283 else { 284 readBinaryHelper = ReadContentAsBinaryHelper.CreateOrReset( readBinaryHelper, this ); 285 } 286 } 287 else { 288 // forward calls into wrapped reader 289 if ( readBinaryHelper == null ) { 290 return await base.ReadElementContentAsBase64Async( buffer, index, count ).ConfigureAwait(false); 291 } 292 } 293 294 // turn off InReadBinary state in order to have a normal Read() behavior when called from readBinaryHelper 295 state = State.Interactive; 296 297 // call to the helper 298 int readCount = await readBinaryHelper.ReadElementContentAsBase64Async(buffer, index, count).ConfigureAwait(false); 299 300 // turn on InReadBinary in again and return 301 state = State.InReadBinary; 302 return readCount; 303 } 304 ReadElementContentAsBinHexAsync( byte[] buffer, int index, int count )305 public override async Task< int > ReadElementContentAsBinHexAsync( byte[] buffer, int index, int count ) { 306 // check arguments 307 if (buffer == null) { 308 throw new ArgumentNullException("buffer"); 309 } 310 if (count < 0) { 311 throw new ArgumentOutOfRangeException("count"); 312 } 313 if (index < 0) { 314 throw new ArgumentOutOfRangeException("index"); 315 } 316 if (buffer.Length - index < count) { 317 throw new ArgumentOutOfRangeException("count"); 318 } 319 if (ReadState != ReadState.Interactive) { 320 return 0; 321 } 322 323 if ( state != State.InReadBinary ) { 324 // forward ReadBinHexChunk calls into the base (wrapped) reader if possible, i.e. if it can read chunks and we 325 // should not check characters 326 if ( base.CanReadBinaryContent && ( !checkCharacters ) ) { 327 readBinaryHelper = null; 328 state = State.InReadBinary; 329 return await base.ReadElementContentAsBinHexAsync( buffer, index, count ).ConfigureAwait(false); 330 } 331 // the wrapped reader cannot read chunks or we are on an element where we should check characters or ignore white spaces 332 else { 333 readBinaryHelper = ReadContentAsBinaryHelper.CreateOrReset( readBinaryHelper, this ); 334 } 335 } 336 else { 337 // forward calls into wrapped reader 338 if ( readBinaryHelper == null ) { 339 return await base.ReadElementContentAsBinHexAsync( buffer, index, count ).ConfigureAwait(false); 340 } 341 } 342 343 // turn off InReadBinary state in order to have a normal Read() behavior when called from readBinaryHelper 344 state = State.Interactive; 345 346 // call to the helper 347 int readCount = await readBinaryHelper.ReadElementContentAsBinHexAsync(buffer, index, count).ConfigureAwait(false); 348 349 // turn on InReadBinary in again and return 350 state = State.InReadBinary; 351 return readCount; 352 } 353 FinishReadBinaryAsync()354 private async Task FinishReadBinaryAsync() { 355 state = State.Interactive; 356 if ( readBinaryHelper != null ) { 357 await readBinaryHelper.FinishAsync().ConfigureAwait(false); 358 } 359 } 360 361 } 362 } 363