1 //------------------------------------------------------------ 2 // Copyright (c) Microsoft Corporation. All rights reserved. 3 //------------------------------------------------------------ 4 namespace System.Xml 5 { 6 using System.Globalization; 7 using System.IO; 8 using System.Runtime; 9 using System.Runtime.Serialization; 10 using System.Text; 11 using System.Threading.Tasks; 12 13 abstract class XmlBaseWriter : XmlDictionaryWriter, IFragmentCapableXmlDictionaryWriter 14 { 15 XmlNodeWriter writer; 16 NamespaceManager nsMgr; 17 Element[] elements; 18 int depth; 19 string attributeLocalName; 20 string attributeValue; 21 bool isXmlAttribute; 22 bool isXmlnsAttribute; 23 WriteState writeState; 24 DocumentState documentState; 25 byte[] trailBytes; 26 int trailByteCount; 27 XmlStreamNodeWriter nodeWriter; 28 XmlSigningNodeWriter signingWriter; 29 XmlUTF8NodeWriter textFragmentWriter; 30 XmlNodeWriter oldWriter; 31 Stream oldStream; 32 int oldNamespaceBoundary; 33 bool inList; 34 const string xmlnsNamespace = "http://www.w3.org/2000/xmlns/"; 35 const string xmlNamespace = "http://www.w3.org/XML/1998/namespace"; 36 static BinHexEncoding binhexEncoding; 37 static string[] prefixes = { "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z" }; 38 XmlBaseWriterNodeWriterAsyncHelper nodeWriterAsyncHelper; 39 XmlBaseWriter()40 protected XmlBaseWriter() 41 { 42 this.nsMgr = new NamespaceManager(); 43 this.writeState = WriteState.Start; 44 this.documentState = DocumentState.None; 45 } 46 SetOutput(XmlStreamNodeWriter writer)47 protected void SetOutput(XmlStreamNodeWriter writer) 48 { 49 this.inList = false; 50 this.writer = writer; 51 this.nodeWriter = writer; 52 this.writeState = WriteState.Start; 53 this.documentState = DocumentState.None; 54 this.nsMgr.Clear(); 55 if (this.depth != 0) 56 { 57 this.elements = null; 58 this.depth = 0; 59 } 60 this.attributeLocalName = null; 61 this.attributeValue = null; 62 this.oldWriter = null; 63 this.oldStream = null; 64 } 65 Flush()66 public override void Flush() 67 { 68 if (IsClosed) 69 ThrowClosed(); 70 71 writer.Flush(); 72 } 73 Close()74 public override void Close() 75 { 76 if (IsClosed) 77 return; 78 79 try 80 { 81 FinishDocument(); 82 AutoComplete(WriteState.Closed); 83 writer.Flush(); 84 } 85 finally 86 { 87 nsMgr.Close(); 88 if (depth != 0) 89 { 90 elements = null; 91 depth = 0; 92 } 93 attributeValue = null; 94 attributeLocalName = null; 95 nodeWriter.Close(); 96 if (signingWriter != null) 97 { 98 signingWriter.Close(); 99 } 100 if (textFragmentWriter != null) 101 { 102 textFragmentWriter.Close(); 103 } 104 oldWriter = null; 105 oldStream = null; 106 } 107 } 108 109 protected bool IsClosed 110 { 111 get { return writeState == WriteState.Closed; } 112 } 113 ThrowClosed()114 protected void ThrowClosed() 115 { 116 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.XmlWriterClosed))); 117 } 118 119 static BinHexEncoding BinHexEncoding 120 { 121 get 122 { 123 if (binhexEncoding == null) 124 binhexEncoding = new BinHexEncoding(); 125 return binhexEncoding; 126 } 127 } 128 129 public override string XmlLang 130 { 131 get 132 { 133 return nsMgr.XmlLang; 134 } 135 } 136 137 public override XmlSpace XmlSpace 138 { 139 get 140 { 141 return nsMgr.XmlSpace; 142 } 143 } 144 145 public override WriteState WriteState 146 { 147 get 148 { 149 return writeState; 150 } 151 } 152 WriteXmlnsAttribute(string prefix, string ns)153 public override void WriteXmlnsAttribute(string prefix, string ns) 154 { 155 if (IsClosed) 156 ThrowClosed(); 157 158 if (ns == null) 159 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("ns"); 160 161 if (writeState != WriteState.Element) 162 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.XmlInvalidWriteState, "WriteXmlnsAttribute", WriteState.ToString()))); 163 164 if (prefix == null) 165 { 166 prefix = nsMgr.LookupPrefix(ns); 167 if (prefix == null) 168 { 169 GeneratePrefix(ns, null); 170 } 171 } 172 else 173 { 174 nsMgr.AddNamespaceIfNotDeclared(prefix, ns, null); 175 } 176 } 177 WriteXmlnsAttribute(string prefix, XmlDictionaryString ns)178 public override void WriteXmlnsAttribute(string prefix, XmlDictionaryString ns) 179 { 180 if (IsClosed) 181 ThrowClosed(); 182 183 if (ns == null) 184 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("ns"); 185 186 if (writeState != WriteState.Element) 187 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.XmlInvalidWriteState, "WriteXmlnsAttribute", WriteState.ToString()))); 188 189 if (prefix == null) 190 { 191 prefix = nsMgr.LookupPrefix(ns.Value); 192 if (prefix == null) 193 { 194 GeneratePrefix(ns.Value, ns); 195 } 196 } 197 else 198 { 199 nsMgr.AddNamespaceIfNotDeclared(prefix, ns.Value, ns); 200 } 201 } 202 StartAttribute(ref string prefix, string localName, string ns, XmlDictionaryString xNs)203 void StartAttribute(ref string prefix, string localName, string ns, XmlDictionaryString xNs) 204 { 205 if (IsClosed) 206 ThrowClosed(); 207 208 if (writeState == WriteState.Attribute) 209 WriteEndAttribute(); 210 211 if (localName == null || (localName.Length == 0 && prefix != "xmlns")) 212 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("localName")); 213 214 if (writeState != WriteState.Element) 215 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.XmlInvalidWriteState, "WriteStartAttribute", WriteState.ToString()))); 216 217 if (prefix == null) 218 { 219 if (ns == xmlnsNamespace && localName != "xmlns") 220 prefix = "xmlns"; 221 else if (ns == xmlNamespace) 222 prefix = "xml"; 223 else 224 prefix = string.Empty; 225 } 226 227 // Normalize a (prefix,localName) of (null, "xmlns") to ("xmlns", string.Empty). 228 if (prefix.Length == 0 && localName == "xmlns") 229 { 230 prefix = "xmlns"; 231 localName = string.Empty; 232 } 233 234 isXmlnsAttribute = false; 235 isXmlAttribute = false; 236 if (prefix == "xml") 237 { 238 if (ns != null && ns != xmlNamespace) 239 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.XmlPrefixBoundToNamespace, "xml", xmlNamespace, ns), "ns")); 240 isXmlAttribute = true; 241 attributeValue = string.Empty; 242 attributeLocalName = localName; 243 } 244 else if (prefix == "xmlns") 245 { 246 if (ns != null && ns != xmlnsNamespace) 247 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.XmlPrefixBoundToNamespace, "xmlns", xmlnsNamespace, ns), "ns")); 248 isXmlnsAttribute = true; 249 attributeValue = string.Empty; 250 attributeLocalName = localName; 251 } 252 else if (ns == null) 253 { 254 // A null namespace means the namespace of the given prefix. 255 if (prefix.Length == 0) 256 { 257 // An empty prefix on an attribute means no namespace (not the default namespace) 258 ns = string.Empty; 259 } 260 else 261 { 262 ns = nsMgr.LookupNamespace(prefix); 263 264 if (ns == null) 265 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.XmlUndefinedPrefix, prefix), "prefix")); 266 } 267 } 268 else if (ns.Length == 0) 269 { 270 // An empty namespace means no namespace; prefix must be empty 271 if (prefix.Length != 0) 272 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.XmlEmptyNamespaceRequiresNullPrefix), "prefix")); 273 } 274 else if (prefix.Length == 0) 275 { 276 // No prefix specified - try to find a prefix corresponding to the given namespace 277 prefix = nsMgr.LookupAttributePrefix(ns); 278 279 // If we didn't find anything with the right namespace, generate one. 280 if (prefix == null) 281 { 282 // Watch for special values 283 if (ns.Length == xmlnsNamespace.Length && ns == xmlnsNamespace) 284 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.XmlSpecificBindingNamespace, "xmlns", ns))); 285 if (ns.Length == xmlNamespace.Length && ns == xmlNamespace) 286 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.XmlSpecificBindingNamespace, "xml", ns))); 287 288 prefix = GeneratePrefix(ns, xNs); 289 } 290 } 291 else 292 { 293 nsMgr.AddNamespaceIfNotDeclared(prefix, ns, xNs); 294 } 295 writeState = WriteState.Attribute; 296 } 297 WriteStartAttribute(string prefix, string localName, string namespaceUri)298 public override void WriteStartAttribute(string prefix, string localName, string namespaceUri) 299 { 300 StartAttribute(ref prefix, localName, namespaceUri, null); 301 if (!isXmlnsAttribute) 302 { 303 writer.WriteStartAttribute(prefix, localName); 304 } 305 } 306 WriteStartAttribute(string prefix, XmlDictionaryString localName, XmlDictionaryString namespaceUri)307 public override void WriteStartAttribute(string prefix, XmlDictionaryString localName, XmlDictionaryString namespaceUri) 308 { 309 StartAttribute(ref prefix, (localName != null ? localName.Value : null), (namespaceUri != null ? namespaceUri.Value : null), namespaceUri); 310 if (!isXmlnsAttribute) 311 { 312 writer.WriteStartAttribute(prefix, localName); 313 } 314 } 315 WriteEndAttribute()316 public override void WriteEndAttribute() 317 { 318 if (IsClosed) 319 ThrowClosed(); 320 321 if (writeState != WriteState.Attribute) 322 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.XmlInvalidWriteState, "WriteEndAttribute", WriteState.ToString()))); 323 324 FlushBase64(); 325 try 326 { 327 if (isXmlAttribute) 328 { 329 if (attributeLocalName == "lang") 330 { 331 nsMgr.AddLangAttribute(attributeValue); 332 } 333 else if (attributeLocalName == "space") 334 { 335 if (attributeValue == "preserve") 336 { 337 nsMgr.AddSpaceAttribute(XmlSpace.Preserve); 338 } 339 else if (attributeValue == "default") 340 { 341 nsMgr.AddSpaceAttribute(XmlSpace.Default); 342 } 343 else 344 { 345 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.XmlInvalidXmlSpace, attributeValue))); 346 } 347 } 348 else 349 { 350 // XmlTextWriter specifically allows for other localNames 351 } 352 isXmlAttribute = false; 353 attributeLocalName = null; 354 attributeValue = null; 355 } 356 357 if (isXmlnsAttribute) 358 { 359 nsMgr.AddNamespaceIfNotDeclared(attributeLocalName, attributeValue, null); 360 isXmlnsAttribute = false; 361 attributeLocalName = null; 362 attributeValue = null; 363 } 364 else 365 { 366 writer.WriteEndAttribute(); 367 } 368 } 369 finally 370 { 371 writeState = WriteState.Element; 372 } 373 } 374 WriteComment(string text)375 public override void WriteComment(string text) 376 { 377 if (IsClosed) 378 ThrowClosed(); 379 380 if (writeState == WriteState.Attribute) 381 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.XmlInvalidWriteState, "WriteComment", WriteState.ToString()))); 382 383 if (text == null) 384 { 385 text = string.Empty; 386 } 387 else if (text.IndexOf("--", StringComparison.Ordinal) != -1 || (text.Length > 0 && text[text.Length - 1] == '-')) 388 { 389 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.XmlInvalidCommentChars), "text")); 390 } 391 392 StartComment(); 393 FlushBase64(); 394 writer.WriteComment(text); 395 EndComment(); 396 } 397 WriteFullEndElement()398 public override void WriteFullEndElement() 399 { 400 if (IsClosed) 401 ThrowClosed(); 402 403 if (writeState == WriteState.Attribute) 404 WriteEndAttribute(); 405 406 if (writeState != WriteState.Element && writeState != WriteState.Content) 407 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.XmlInvalidWriteState, "WriteFullEndElement", WriteState.ToString()))); 408 409 AutoComplete(WriteState.Content); 410 WriteEndElement(); 411 } 412 WriteCData(string text)413 public override void WriteCData(string text) 414 { 415 if (IsClosed) 416 ThrowClosed(); 417 418 if (writeState == WriteState.Attribute) 419 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.XmlInvalidWriteState, "WriteCData", WriteState.ToString()))); 420 421 if (text == null) 422 text = string.Empty; 423 424 if (text.Length > 0) 425 { 426 StartContent(); 427 FlushBase64(); 428 writer.WriteCData(text); 429 EndContent(); 430 } 431 } 432 WriteDocType(string name, string pubid, string sysid, string subset)433 public override void WriteDocType(string name, string pubid, string sysid, string subset) 434 { 435 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.XmlMethodNotSupported, "WriteDocType"))); 436 } 437 StartElement(ref string prefix, string localName, string ns, XmlDictionaryString xNs)438 void StartElement(ref string prefix, string localName, string ns, XmlDictionaryString xNs) 439 { 440 if (IsClosed) 441 ThrowClosed(); 442 443 if (this.documentState == DocumentState.Epilog) 444 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.XmlOnlyOneRoot))); 445 if (localName == null) 446 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("localName")); 447 if (localName.Length == 0) 448 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.InvalidLocalNameEmpty), "localName")); 449 if (writeState == WriteState.Attribute) 450 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.XmlInvalidWriteState, "WriteStartElement", WriteState.ToString()))); 451 452 FlushBase64(); 453 AutoComplete(WriteState.Element); 454 Element element = EnterScope(); 455 if (ns == null) 456 { 457 if (prefix == null) 458 prefix = string.Empty; 459 460 ns = nsMgr.LookupNamespace(prefix); 461 462 if (ns == null) 463 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.XmlUndefinedPrefix, prefix), "prefix")); 464 } 465 else if (prefix == null) 466 { 467 prefix = nsMgr.LookupPrefix(ns); 468 469 if (prefix == null) 470 { 471 prefix = string.Empty; 472 nsMgr.AddNamespace(string.Empty, ns, xNs); 473 } 474 } 475 else 476 { 477 nsMgr.AddNamespaceIfNotDeclared(prefix, ns, xNs); 478 } 479 element.Prefix = prefix; 480 element.LocalName = localName; 481 } 482 WriteStartElement(string prefix, string localName, string namespaceUri)483 public override void WriteStartElement(string prefix, string localName, string namespaceUri) 484 { 485 StartElement(ref prefix, localName, namespaceUri, null); 486 writer.WriteStartElement(prefix, localName); 487 } 488 WriteStartElement(string prefix, XmlDictionaryString localName, XmlDictionaryString namespaceUri)489 public override void WriteStartElement(string prefix, XmlDictionaryString localName, XmlDictionaryString namespaceUri) 490 { 491 StartElement(ref prefix, (localName != null ? localName.Value : null), (namespaceUri != null ? namespaceUri.Value : null), namespaceUri); 492 writer.WriteStartElement(prefix, localName); 493 } 494 WriteEndElement()495 public override void WriteEndElement() 496 { 497 if (IsClosed) 498 ThrowClosed(); 499 500 if (depth == 0) 501 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.XmlInvalidDepth, "WriteEndElement", depth.ToString(CultureInfo.InvariantCulture)))); 502 503 if (writeState == WriteState.Attribute) 504 WriteEndAttribute(); 505 506 FlushBase64(); 507 if (writeState == WriteState.Element) 508 { 509 nsMgr.DeclareNamespaces(writer); 510 writer.WriteEndStartElement(true); 511 } 512 else 513 { 514 Element element = elements[depth]; 515 writer.WriteEndElement(element.Prefix, element.LocalName); 516 } 517 518 ExitScope(); 519 writeState = WriteState.Content; 520 } 521 EnterScope()522 Element EnterScope() 523 { 524 nsMgr.EnterScope(); 525 depth++; 526 if (elements == null) 527 { 528 elements = new Element[4]; 529 } 530 else if (elements.Length == depth) 531 { 532 Element[] newElementNodes = new Element[depth * 2]; 533 Array.Copy(elements, newElementNodes, depth); 534 elements = newElementNodes; 535 } 536 Element element = elements[depth]; 537 if (element == null) 538 { 539 element = new Element(); 540 elements[depth] = element; 541 } 542 return element; 543 } 544 ExitScope()545 void ExitScope() 546 { 547 elements[depth].Clear(); 548 depth--; 549 if (depth == 0 && documentState == DocumentState.Document) 550 this.documentState = DocumentState.Epilog; 551 nsMgr.ExitScope(); 552 } 553 FlushElement()554 protected void FlushElement() 555 { 556 if (this.writeState == WriteState.Element) 557 { 558 AutoComplete(WriteState.Content); 559 } 560 } 561 StartComment()562 protected void StartComment() 563 { 564 FlushElement(); 565 } 566 EndComment()567 protected void EndComment() 568 { 569 } 570 StartContent()571 protected void StartContent() 572 { 573 FlushElement(); 574 if (depth == 0) 575 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.XmlIllegalOutsideRoot))); 576 } 577 StartContent(char ch)578 protected void StartContent(char ch) 579 { 580 FlushElement(); 581 if (depth == 0) 582 VerifyWhitespace(ch); 583 } 584 StartContent(string s)585 protected void StartContent(string s) 586 { 587 FlushElement(); 588 if (depth == 0) 589 VerifyWhitespace(s); 590 } 591 StartContent(char[] chars, int offset, int count)592 protected void StartContent(char[] chars, int offset, int count) 593 { 594 FlushElement(); 595 if (depth == 0) 596 VerifyWhitespace(chars, offset, count); 597 } 598 VerifyWhitespace(char ch)599 void VerifyWhitespace(char ch) 600 { 601 if (!IsWhitespace(ch)) 602 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.XmlIllegalOutsideRoot))); 603 } 604 VerifyWhitespace(string s)605 void VerifyWhitespace(string s) 606 { 607 for (int i = 0; i < s.Length; i++) 608 if (!IsWhitespace(s[i])) 609 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.XmlIllegalOutsideRoot))); 610 } 611 VerifyWhitespace(char[] chars, int offset, int count)612 void VerifyWhitespace(char[] chars, int offset, int count) 613 { 614 for (int i = 0; i < count; i++) 615 if (!IsWhitespace(chars[offset + i])) 616 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.XmlIllegalOutsideRoot))); 617 } 618 IsWhitespace(char ch)619 bool IsWhitespace(char ch) 620 { 621 return (ch == ' ' || ch == '\n' || ch == '\r' || ch == 't'); 622 } 623 EndContent()624 protected void EndContent() 625 { 626 } 627 AutoComplete(WriteState writeState)628 void AutoComplete(WriteState writeState) 629 { 630 if (this.writeState == WriteState.Element) 631 { 632 EndStartElement(); 633 } 634 this.writeState = writeState; 635 } 636 EndStartElement()637 void EndStartElement() 638 { 639 nsMgr.DeclareNamespaces(writer); 640 writer.WriteEndStartElement(false); 641 } 642 LookupPrefix(string ns)643 public override string LookupPrefix(string ns) 644 { 645 if (ns == null) 646 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("ns")); 647 648 if (IsClosed) 649 ThrowClosed(); 650 651 return nsMgr.LookupPrefix(ns); 652 } 653 LookupNamespace(string prefix)654 internal string LookupNamespace(string prefix) 655 { 656 if (prefix == null) 657 return null; 658 return nsMgr.LookupNamespace(prefix); 659 } 660 GetQualifiedNamePrefix(string namespaceUri, XmlDictionaryString xNs)661 string GetQualifiedNamePrefix(string namespaceUri, XmlDictionaryString xNs) 662 { 663 string prefix = nsMgr.LookupPrefix(namespaceUri); 664 if (prefix == null) 665 { 666 if (writeState != WriteState.Attribute) 667 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.XmlNamespaceNotFound, namespaceUri), "namespaceUri")); 668 669 prefix = GeneratePrefix(namespaceUri, xNs); 670 } 671 return prefix; 672 } 673 WriteQualifiedName(string localName, string namespaceUri)674 public override void WriteQualifiedName(string localName, string namespaceUri) 675 { 676 if (IsClosed) 677 ThrowClosed(); 678 if (localName == null) 679 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("localName")); 680 if (localName.Length == 0) 681 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.InvalidLocalNameEmpty), "localName")); 682 if (namespaceUri == null) 683 namespaceUri = string.Empty; 684 string prefix = GetQualifiedNamePrefix(namespaceUri, null); 685 if (prefix.Length != 0) 686 { 687 WriteString(prefix); 688 WriteString(":"); 689 } 690 WriteString(localName); 691 } 692 WriteQualifiedName(XmlDictionaryString localName, XmlDictionaryString namespaceUri)693 public override void WriteQualifiedName(XmlDictionaryString localName, XmlDictionaryString namespaceUri) 694 { 695 if (IsClosed) 696 ThrowClosed(); 697 if (localName == null) 698 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("localName")); 699 if (localName.Value.Length == 0) 700 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.InvalidLocalNameEmpty), "localName")); 701 if (namespaceUri == null) 702 namespaceUri = XmlDictionaryString.Empty; 703 string prefix = GetQualifiedNamePrefix(namespaceUri.Value, namespaceUri); 704 705 FlushBase64(); 706 if (attributeValue != null) 707 WriteAttributeText(string.Concat(prefix, ":", namespaceUri.Value)); 708 709 if (!isXmlnsAttribute) 710 { 711 StartContent(); 712 writer.WriteQualifiedName(prefix, localName); 713 EndContent(); 714 } 715 } 716 WriteStartDocument()717 public override void WriteStartDocument() 718 { 719 if (IsClosed) 720 ThrowClosed(); 721 722 if (writeState != WriteState.Start) 723 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.XmlInvalidWriteState, "WriteStartDocument", WriteState.ToString()))); 724 725 writeState = WriteState.Prolog; 726 documentState = DocumentState.Document; 727 writer.WriteDeclaration(); 728 } 729 WriteStartDocument(bool standalone)730 public override void WriteStartDocument(bool standalone) 731 { 732 if (IsClosed) 733 ThrowClosed(); 734 735 WriteStartDocument(); 736 } 737 738 WriteProcessingInstruction(string name, string text)739 public override void WriteProcessingInstruction(string name, string text) 740 { 741 if (IsClosed) 742 ThrowClosed(); 743 744 if (name != "xml") 745 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.XmlProcessingInstructionNotSupported), "name")); 746 747 if (writeState != WriteState.Start) 748 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.XmlInvalidDeclaration))); 749 750 // The only thing the text can legitimately contain is version, encoding, and standalone. 751 // We only support version 1.0, we can only write whatever encoding we were supplied, 752 // and we don't support DTDs, so whatever values are supplied in the text argument are irrelevant. 753 writer.WriteDeclaration(); 754 } 755 FinishDocument()756 void FinishDocument() 757 { 758 if (this.writeState == WriteState.Attribute) 759 { 760 WriteEndAttribute(); 761 } 762 763 while (this.depth > 0) 764 { 765 WriteEndElement(); 766 } 767 } 768 WriteEndDocument()769 public override void WriteEndDocument() 770 { 771 if (IsClosed) 772 ThrowClosed(); 773 774 if (writeState == WriteState.Start || writeState == WriteState.Prolog) 775 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.XmlNoRootElement))); 776 777 FinishDocument(); 778 writeState = WriteState.Start; 779 documentState = DocumentState.End; 780 } 781 782 protected int NamespaceBoundary 783 { 784 get 785 { 786 return nsMgr.NamespaceBoundary; 787 } 788 set 789 { 790 nsMgr.NamespaceBoundary = value; 791 } 792 } 793 WriteEntityRef(string name)794 public override void WriteEntityRef(string name) 795 { 796 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.XmlMethodNotSupported, "WriteEntityRef"))); 797 } 798 WriteName(string name)799 public override void WriteName(string name) 800 { 801 if (IsClosed) 802 ThrowClosed(); 803 804 WriteString(name); 805 } 806 WriteNmToken(string name)807 public override void WriteNmToken(string name) 808 { 809 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.XmlMethodNotSupported, "WriteNmToken"))); 810 } 811 WriteWhitespace(string whitespace)812 public override void WriteWhitespace(string whitespace) 813 { 814 if (IsClosed) 815 ThrowClosed(); 816 817 if (whitespace == null) 818 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("whitespace"); 819 820 for (int i = 0; i < whitespace.Length; ++i) 821 { 822 char c = whitespace[i]; 823 if (c != ' ' && 824 c != '\t' && 825 c != '\n' && 826 c != '\r') 827 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.XmlOnlyWhitespace), "whitespace")); 828 } 829 830 WriteString(whitespace); 831 } 832 WriteString(string value)833 public override void WriteString(string value) 834 { 835 if (IsClosed) 836 ThrowClosed(); 837 838 if (value == null) 839 value = string.Empty; 840 841 if (value.Length > 0 || this.inList) 842 { 843 FlushBase64(); 844 845 if (attributeValue != null) 846 WriteAttributeText(value); 847 848 if (!isXmlnsAttribute) 849 { 850 StartContent(value); 851 writer.WriteEscapedText(value); 852 EndContent(); 853 } 854 } 855 } 856 WriteString(XmlDictionaryString value)857 public override void WriteString(XmlDictionaryString value) 858 { 859 if (IsClosed) 860 ThrowClosed(); 861 862 if (value == null) 863 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("value"); 864 865 if (value.Value.Length > 0) 866 { 867 FlushBase64(); 868 869 if (attributeValue != null) 870 WriteAttributeText(value.Value); 871 872 if (!isXmlnsAttribute) 873 { 874 StartContent(value.Value); 875 writer.WriteEscapedText(value); 876 EndContent(); 877 } 878 } 879 } 880 WriteChars(char[] chars, int offset, int count)881 public override void WriteChars(char[] chars, int offset, int count) 882 { 883 if (IsClosed) 884 ThrowClosed(); 885 886 if (chars == null) 887 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("chars")); 888 889 // Not checking upper bound because it will be caught by "count". This is what XmlTextWriter does. 890 if (offset < 0) 891 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("offset", SR.GetString(SR.ValueMustBeNonNegative))); 892 893 if (count < 0) 894 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("count", SR.GetString(SR.ValueMustBeNonNegative))); 895 if (count > chars.Length - offset) 896 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("count", SR.GetString(SR.SizeExceedsRemainingBufferSpace, chars.Length - offset))); 897 898 if (count > 0) 899 { 900 FlushBase64(); 901 902 if (attributeValue != null) 903 WriteAttributeText(new string(chars, offset, count)); 904 905 if (!isXmlnsAttribute) 906 { 907 StartContent(chars, offset, count); 908 writer.WriteEscapedText(chars, offset, count); 909 EndContent(); 910 } 911 } 912 } 913 WriteRaw(string value)914 public override void WriteRaw(string value) 915 { 916 if (IsClosed) 917 ThrowClosed(); 918 919 if (value == null) 920 value = string.Empty; 921 922 if (value.Length > 0) 923 { 924 FlushBase64(); 925 926 if (attributeValue != null) 927 WriteAttributeText(value); 928 929 if (!isXmlnsAttribute) 930 { 931 StartContent(value); 932 writer.WriteText(value); 933 EndContent(); 934 } 935 } 936 } 937 WriteRaw(char[] chars, int offset, int count)938 public override void WriteRaw(char[] chars, int offset, int count) 939 { 940 if (IsClosed) 941 ThrowClosed(); 942 943 if (chars == null) 944 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("chars")); 945 946 // Not checking upper bound because it will be caught by "count". This is what XmlTextWriter does. 947 if (offset < 0) 948 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("offset", SR.GetString(SR.ValueMustBeNonNegative))); 949 950 if (count < 0) 951 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("count", SR.GetString(SR.ValueMustBeNonNegative))); 952 if (count > chars.Length - offset) 953 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("count", SR.GetString(SR.SizeExceedsRemainingBufferSpace, chars.Length - offset))); 954 955 if (count > 0) 956 { 957 FlushBase64(); 958 959 if (attributeValue != null) 960 WriteAttributeText(new string(chars, offset, count)); 961 962 if (!isXmlnsAttribute) 963 { 964 StartContent(chars, offset, count); 965 writer.WriteText(chars, offset, count); 966 EndContent(); 967 } 968 } 969 } 970 WriteCharEntity(char ch)971 public override void WriteCharEntity(char ch) 972 { 973 if (IsClosed) 974 ThrowClosed(); 975 976 if (ch >= 0xd800 && ch <= 0xdfff) 977 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.XmlMissingLowSurrogate), "ch")); 978 979 if (attributeValue != null) 980 WriteAttributeText(ch.ToString()); 981 982 if (!isXmlnsAttribute) 983 { 984 StartContent(ch); 985 FlushBase64(); 986 writer.WriteCharEntity(ch); 987 EndContent(); 988 } 989 } 990 WriteSurrogateCharEntity(char lowChar, char highChar)991 public override void WriteSurrogateCharEntity(char lowChar, char highChar) 992 { 993 if (IsClosed) 994 ThrowClosed(); 995 996 SurrogateChar ch = new SurrogateChar(lowChar, highChar); 997 998 if (attributeValue != null) 999 { 1000 char[] chars = new char[2] { highChar, lowChar }; 1001 WriteAttributeText(new string(chars)); 1002 } 1003 1004 if (!isXmlnsAttribute) 1005 { 1006 StartContent(); 1007 FlushBase64(); 1008 writer.WriteCharEntity(ch.Char); 1009 EndContent(); 1010 } 1011 } 1012 WriteValue(object value)1013 public override void WriteValue(object value) 1014 { 1015 if (IsClosed) 1016 ThrowClosed(); 1017 1018 if (value == null) 1019 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("value")); 1020 1021 else if (value is object[]) 1022 { 1023 WriteValue((object[])value); 1024 } 1025 else if (value is Array) 1026 { 1027 WriteValue((Array)value); 1028 } 1029 else if (value is IStreamProvider) 1030 { 1031 WriteValue((IStreamProvider)value); 1032 } 1033 else 1034 { 1035 WritePrimitiveValue(value); 1036 } 1037 } 1038 WritePrimitiveValue(object value)1039 protected void WritePrimitiveValue(object value) 1040 { 1041 if (IsClosed) 1042 ThrowClosed(); 1043 1044 if (value == null) 1045 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("value")); 1046 1047 if (value is ulong) 1048 { 1049 WriteValue((ulong)value); 1050 } 1051 else if (value is string) 1052 { 1053 WriteValue((string)value); 1054 } 1055 else if (value is int) 1056 { 1057 WriteValue((int)value); 1058 } 1059 else if (value is long) 1060 { 1061 WriteValue((long)value); 1062 } 1063 else if (value is bool) 1064 { 1065 WriteValue((bool)value); 1066 } 1067 else if (value is double) 1068 { 1069 WriteValue((double)value); 1070 } 1071 else if (value is DateTime) 1072 { 1073 WriteValue((DateTime)value); 1074 } 1075 else if (value is float) 1076 { 1077 WriteValue((float)value); 1078 } 1079 else if (value is decimal) 1080 { 1081 WriteValue((decimal)value); 1082 } 1083 else if (value is XmlDictionaryString) 1084 { 1085 WriteValue((XmlDictionaryString)value); 1086 } 1087 else if (value is UniqueId) 1088 { 1089 WriteValue((UniqueId)value); 1090 } 1091 else if (value is Guid) 1092 { 1093 WriteValue((Guid)value); 1094 } 1095 else if (value is TimeSpan) 1096 { 1097 WriteValue((TimeSpan)value); 1098 } 1099 else if (value.GetType().IsArray) 1100 { 1101 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.XmlNestedArraysNotSupported), "value")); 1102 } 1103 else 1104 { 1105 base.WriteValue(value); 1106 } 1107 } 1108 WriteValue(string value)1109 public override void WriteValue(string value) 1110 { 1111 if (IsClosed) 1112 ThrowClosed(); 1113 1114 WriteString(value); 1115 } 1116 WriteValue(int value)1117 public override void WriteValue(int value) 1118 { 1119 if (IsClosed) 1120 ThrowClosed(); 1121 1122 FlushBase64(); 1123 if (attributeValue != null) 1124 WriteAttributeText(XmlConverter.ToString(value)); 1125 1126 if (!isXmlnsAttribute) 1127 { 1128 StartContent(); 1129 writer.WriteInt32Text(value); 1130 EndContent(); 1131 } 1132 } 1133 WriteValue(long value)1134 public override void WriteValue(long value) 1135 { 1136 if (IsClosed) 1137 ThrowClosed(); 1138 1139 FlushBase64(); 1140 if (attributeValue != null) 1141 WriteAttributeText(XmlConverter.ToString(value)); 1142 1143 if (!isXmlnsAttribute) 1144 { 1145 StartContent(); 1146 writer.WriteInt64Text(value); 1147 EndContent(); 1148 } 1149 } 1150 WriteValue(ulong value)1151 void WriteValue(ulong value) 1152 { 1153 if (IsClosed) 1154 ThrowClosed(); 1155 1156 FlushBase64(); 1157 if (attributeValue != null) 1158 WriteAttributeText(XmlConverter.ToString(value)); 1159 1160 if (!isXmlnsAttribute) 1161 { 1162 StartContent(); 1163 writer.WriteUInt64Text(value); 1164 EndContent(); 1165 } 1166 } 1167 WriteValue(bool value)1168 public override void WriteValue(bool value) 1169 { 1170 if (IsClosed) 1171 ThrowClosed(); 1172 1173 FlushBase64(); 1174 if (attributeValue != null) 1175 WriteAttributeText(XmlConverter.ToString(value)); 1176 1177 if (!isXmlnsAttribute) 1178 { 1179 StartContent(); 1180 writer.WriteBoolText(value); 1181 EndContent(); 1182 } 1183 } 1184 WriteValue(decimal value)1185 public override void WriteValue(decimal value) 1186 { 1187 if (IsClosed) 1188 ThrowClosed(); 1189 1190 FlushBase64(); 1191 if (attributeValue != null) 1192 WriteAttributeText(XmlConverter.ToString(value)); 1193 1194 if (!isXmlnsAttribute) 1195 { 1196 StartContent(); 1197 writer.WriteDecimalText(value); 1198 EndContent(); 1199 } 1200 } 1201 WriteValue(float value)1202 public override void WriteValue(float value) 1203 { 1204 if (IsClosed) 1205 ThrowClosed(); 1206 1207 FlushBase64(); 1208 if (attributeValue != null) 1209 WriteAttributeText(XmlConverter.ToString(value)); 1210 1211 if (!isXmlnsAttribute) 1212 { 1213 StartContent(); 1214 writer.WriteFloatText(value); 1215 EndContent(); 1216 } 1217 } 1218 WriteValue(double value)1219 public override void WriteValue(double value) 1220 { 1221 if (IsClosed) 1222 ThrowClosed(); 1223 1224 FlushBase64(); 1225 if (attributeValue != null) 1226 WriteAttributeText(XmlConverter.ToString(value)); 1227 1228 if (!isXmlnsAttribute) 1229 { 1230 StartContent(); 1231 writer.WriteDoubleText(value); 1232 EndContent(); 1233 } 1234 } 1235 WriteValue(XmlDictionaryString value)1236 public override void WriteValue(XmlDictionaryString value) 1237 { 1238 WriteString(value); 1239 } 1240 WriteValue(DateTime value)1241 public override void WriteValue(DateTime value) 1242 { 1243 if (IsClosed) 1244 ThrowClosed(); 1245 1246 FlushBase64(); 1247 if (attributeValue != null) 1248 WriteAttributeText(XmlConverter.ToString(value)); 1249 1250 if (!isXmlnsAttribute) 1251 { 1252 StartContent(); 1253 writer.WriteDateTimeText(value); 1254 EndContent(); 1255 } 1256 } 1257 WriteValue(UniqueId value)1258 public override void WriteValue(UniqueId value) 1259 { 1260 if (IsClosed) 1261 ThrowClosed(); 1262 1263 if (value == null) 1264 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("value"); 1265 1266 FlushBase64(); 1267 if (attributeValue != null) 1268 WriteAttributeText(XmlConverter.ToString(value)); 1269 1270 if (!isXmlnsAttribute) 1271 { 1272 StartContent(); 1273 writer.WriteUniqueIdText(value); 1274 EndContent(); 1275 } 1276 } 1277 WriteValue(Guid value)1278 public override void WriteValue(Guid value) 1279 { 1280 if (IsClosed) 1281 ThrowClosed(); 1282 1283 FlushBase64(); 1284 if (attributeValue != null) 1285 WriteAttributeText(XmlConverter.ToString(value)); 1286 1287 if (!isXmlnsAttribute) 1288 { 1289 StartContent(); 1290 writer.WriteGuidText(value); 1291 EndContent(); 1292 } 1293 } 1294 WriteValue(TimeSpan value)1295 public override void WriteValue(TimeSpan value) 1296 { 1297 if (IsClosed) 1298 ThrowClosed(); 1299 1300 FlushBase64(); 1301 if (attributeValue != null) 1302 WriteAttributeText(XmlConverter.ToString(value)); 1303 1304 if (!isXmlnsAttribute) 1305 { 1306 StartContent(); 1307 writer.WriteTimeSpanText(value); 1308 EndContent(); 1309 } 1310 } 1311 WriteBase64(byte[] buffer, int offset, int count)1312 public override void WriteBase64(byte[] buffer, int offset, int count) 1313 { 1314 if (IsClosed) 1315 ThrowClosed(); 1316 1317 EnsureBufferBounds(buffer, offset, count); 1318 if (count > 0) 1319 { 1320 if (trailByteCount > 0) 1321 { 1322 while (trailByteCount < 3 && count > 0) 1323 { 1324 trailBytes[trailByteCount++] = buffer[offset++]; 1325 count--; 1326 } 1327 } 1328 1329 int totalByteCount = trailByteCount + count; 1330 int actualByteCount = totalByteCount - (totalByteCount % 3); 1331 1332 if (trailBytes == null) 1333 { 1334 trailBytes = new byte[3]; 1335 } 1336 1337 if (actualByteCount >= 3) 1338 { 1339 if (attributeValue != null) 1340 { 1341 WriteAttributeText(XmlConverter.Base64Encoding.GetString(trailBytes, 0, trailByteCount)); 1342 WriteAttributeText(XmlConverter.Base64Encoding.GetString(buffer, offset, actualByteCount - trailByteCount)); 1343 } 1344 1345 if (!isXmlnsAttribute) 1346 { 1347 StartContent(); 1348 writer.WriteBase64Text(trailBytes, trailByteCount, buffer, offset, actualByteCount - trailByteCount); 1349 EndContent(); 1350 } 1351 trailByteCount = (totalByteCount - actualByteCount); 1352 1353 if (trailByteCount > 0) 1354 { 1355 int trailOffset = offset + count - trailByteCount; 1356 for (int i = 0; i < trailByteCount; i++) 1357 trailBytes[i] = buffer[trailOffset++]; 1358 } 1359 } 1360 else 1361 { 1362 Buffer.BlockCopy(buffer, offset, trailBytes, trailByteCount, count); 1363 trailByteCount += count; 1364 } 1365 } 1366 } 1367 BeginWriteBase64(byte[] buffer, int offset, int count, AsyncCallback callback, object state)1368 internal override IAsyncResult BeginWriteBase64(byte[] buffer, int offset, int count, AsyncCallback callback, object state) 1369 { 1370 if (IsClosed) 1371 ThrowClosed(); 1372 1373 EnsureBufferBounds(buffer, offset, count); 1374 1375 return new WriteBase64AsyncResult(buffer, offset, count, this, callback, state); 1376 } 1377 EndWriteBase64(IAsyncResult result)1378 internal override void EndWriteBase64(IAsyncResult result) 1379 { 1380 WriteBase64AsyncResult.End(result); 1381 } 1382 WriteBase64Async(AsyncEventArgs<XmlWriteBase64AsyncArguments> state)1383 internal override AsyncCompletionResult WriteBase64Async(AsyncEventArgs<XmlWriteBase64AsyncArguments> state) 1384 { 1385 if (this.nodeWriterAsyncHelper == null) 1386 { 1387 this.nodeWriterAsyncHelper = new XmlBaseWriterNodeWriterAsyncHelper(this); 1388 } 1389 1390 this.nodeWriterAsyncHelper.SetArguments(state); 1391 1392 if (this.nodeWriterAsyncHelper.StartAsync() == AsyncCompletionResult.Completed) 1393 { 1394 return AsyncCompletionResult.Completed; 1395 } 1396 1397 return AsyncCompletionResult.Queued; 1398 } 1399 1400 class WriteBase64AsyncResult : AsyncResult 1401 { 1402 static AsyncCompletion onComplete = new AsyncCompletion(OnComplete); 1403 XmlBaseWriter writer; 1404 byte[] buffer; 1405 int offset; 1406 int count; 1407 int actualByteCount; 1408 int totalByteCount; 1409 WriteBase64AsyncResult(byte[] buffer, int offset, int count, XmlBaseWriter writer, AsyncCallback callback, object state)1410 public WriteBase64AsyncResult(byte[] buffer, int offset, int count, XmlBaseWriter writer, AsyncCallback callback, object state) 1411 : base(callback, state) 1412 { 1413 this.writer = writer; 1414 this.buffer = buffer; 1415 this.offset = offset; 1416 this.count = count; 1417 1418 bool completeSelf = true; 1419 1420 if (this.count > 0) 1421 { 1422 if (writer.trailByteCount > 0) 1423 { 1424 while (writer.trailByteCount < 3 && this.count > 0) 1425 { 1426 writer.trailBytes[writer.trailByteCount++] = buffer[this.offset++]; 1427 this.count--; 1428 } 1429 } 1430 1431 this.totalByteCount = writer.trailByteCount + this.count; 1432 this.actualByteCount = totalByteCount - (totalByteCount % 3); 1433 1434 if (writer.trailBytes == null) 1435 { 1436 writer.trailBytes = new byte[3]; 1437 } 1438 1439 if (actualByteCount >= 3) 1440 { 1441 if (writer.attributeValue != null) 1442 { 1443 writer.WriteAttributeText(XmlConverter.Base64Encoding.GetString(writer.trailBytes, 0, writer.trailByteCount)); 1444 writer.WriteAttributeText(XmlConverter.Base64Encoding.GetString(buffer, this.offset, actualByteCount - writer.trailByteCount)); 1445 } 1446 1447 // StartContent/WriteBase64Text/EndContent will be called from HandleWriteBase64 as appropriate 1448 completeSelf = HandleWriteBase64Text(null); 1449 } 1450 else 1451 { 1452 Buffer.BlockCopy(buffer, this.offset, writer.trailBytes, writer.trailByteCount, this.count); 1453 writer.trailByteCount += this.count; 1454 } 1455 } 1456 1457 if (completeSelf) 1458 { 1459 this.Complete(true); 1460 } 1461 } 1462 OnComplete(IAsyncResult result)1463 static bool OnComplete(IAsyncResult result) 1464 { 1465 WriteBase64AsyncResult thisPtr = (WriteBase64AsyncResult)result.AsyncState; 1466 return thisPtr.HandleWriteBase64Text(result); 1467 } 1468 HandleWriteBase64Text(IAsyncResult result)1469 bool HandleWriteBase64Text(IAsyncResult result) 1470 { 1471 // in this code block if count > 0 && actualByteCount >= 3 1472 if (!writer.isXmlnsAttribute) 1473 { 1474 if (result == null) 1475 { 1476 this.writer.StartContent(); 1477 result = this.writer.writer.BeginWriteBase64Text(this.writer.trailBytes, 1478 this.writer.trailByteCount, 1479 this.buffer, 1480 this.offset, 1481 this.actualByteCount - this.writer.trailByteCount, 1482 PrepareAsyncCompletion(onComplete), 1483 this); 1484 1485 if (!result.CompletedSynchronously) 1486 { 1487 return false; 1488 } 1489 } 1490 this.writer.writer.EndWriteBase64Text(result); 1491 this.writer.EndContent(); 1492 } 1493 1494 this.writer.trailByteCount = (totalByteCount - actualByteCount); 1495 if (this.writer.trailByteCount > 0) 1496 { 1497 int trailOffset = offset + count - this.writer.trailByteCount; 1498 for (int i = 0; i < this.writer.trailByteCount; i++) 1499 this.writer.trailBytes[i] = this.buffer[trailOffset++]; 1500 } 1501 1502 return true; 1503 } 1504 End(IAsyncResult result)1505 public static void End(IAsyncResult result) 1506 { 1507 AsyncResult.End<WriteBase64AsyncResult>(result); 1508 } 1509 } 1510 WriteBinHex(byte[] buffer, int offset, int count)1511 public override void WriteBinHex(byte[] buffer, int offset, int count) 1512 { 1513 if (IsClosed) 1514 ThrowClosed(); 1515 1516 EnsureBufferBounds(buffer, offset, count); 1517 1518 WriteRaw(BinHexEncoding.GetString(buffer, offset, count)); 1519 } 1520 1521 public override bool CanCanonicalize 1522 { 1523 get 1524 { 1525 return true; 1526 } 1527 } 1528 1529 protected bool Signing 1530 { 1531 get 1532 { 1533 return writer == signingWriter; 1534 } 1535 } 1536 StartCanonicalization(Stream stream, bool includeComments, string[] inclusivePrefixes)1537 public override void StartCanonicalization(Stream stream, bool includeComments, string[] inclusivePrefixes) 1538 { 1539 if (IsClosed) 1540 ThrowClosed(); 1541 if (Signing) 1542 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.XmlCanonicalizationStarted))); 1543 FlushElement(); 1544 if (signingWriter == null) 1545 signingWriter = CreateSigningNodeWriter(); 1546 signingWriter.SetOutput(writer, stream, includeComments, inclusivePrefixes); 1547 writer = signingWriter; 1548 SignScope(signingWriter.CanonicalWriter); 1549 } 1550 EndCanonicalization()1551 public override void EndCanonicalization() 1552 { 1553 if (IsClosed) 1554 ThrowClosed(); 1555 if (!Signing) 1556 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.XmlCanonicalizationNotStarted))); 1557 signingWriter.Flush(); 1558 writer = signingWriter.NodeWriter; 1559 } 1560 CreateSigningNodeWriter()1561 protected abstract XmlSigningNodeWriter CreateSigningNodeWriter(); 1562 1563 public virtual bool CanFragment 1564 { 1565 get 1566 { 1567 return true; 1568 } 1569 } 1570 StartFragment(Stream stream, bool generateSelfContainedTextFragment)1571 public void StartFragment(Stream stream, bool generateSelfContainedTextFragment) 1572 { 1573 if (!CanFragment) 1574 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException()); 1575 if (IsClosed) 1576 ThrowClosed(); 1577 if (stream == null) 1578 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("stream")); 1579 if (oldStream != null || oldWriter != null) 1580 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException()); 1581 if (WriteState == WriteState.Attribute) 1582 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.XmlInvalidWriteState, "StartFragment", WriteState.ToString()))); 1583 FlushElement(); 1584 writer.Flush(); 1585 1586 oldNamespaceBoundary = NamespaceBoundary; 1587 1588 XmlStreamNodeWriter fragmentWriter = null; 1589 if (generateSelfContainedTextFragment) 1590 { 1591 this.NamespaceBoundary = depth + 1; 1592 if (textFragmentWriter == null) 1593 textFragmentWriter = new XmlUTF8NodeWriter(); 1594 textFragmentWriter.SetOutput(stream, false, Encoding.UTF8); 1595 fragmentWriter = textFragmentWriter; 1596 } 1597 1598 if (Signing) 1599 { 1600 if (fragmentWriter != null) 1601 { 1602 oldWriter = signingWriter.NodeWriter; 1603 signingWriter.NodeWriter = fragmentWriter; 1604 } 1605 else 1606 { 1607 oldStream = ((XmlStreamNodeWriter)signingWriter.NodeWriter).Stream; 1608 ((XmlStreamNodeWriter)signingWriter.NodeWriter).Stream = stream; 1609 } 1610 } 1611 else 1612 { 1613 if (fragmentWriter != null) 1614 { 1615 oldWriter = writer; 1616 writer = fragmentWriter; 1617 } 1618 else 1619 { 1620 oldStream = nodeWriter.Stream; 1621 nodeWriter.Stream = stream; 1622 } 1623 } 1624 } 1625 EndFragment()1626 public void EndFragment() 1627 { 1628 if (IsClosed) 1629 ThrowClosed(); 1630 if (oldStream == null && oldWriter == null) 1631 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException()); 1632 if (WriteState == WriteState.Attribute) 1633 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.XmlInvalidWriteState, "EndFragment", WriteState.ToString()))); 1634 1635 FlushElement(); 1636 writer.Flush(); 1637 1638 if (Signing) 1639 { 1640 if (oldWriter != null) 1641 signingWriter.NodeWriter = oldWriter; 1642 else 1643 ((XmlStreamNodeWriter)signingWriter.NodeWriter).Stream = oldStream; 1644 } 1645 else 1646 { 1647 if (oldWriter != null) 1648 writer = oldWriter; 1649 else 1650 nodeWriter.Stream = oldStream; 1651 } 1652 NamespaceBoundary = oldNamespaceBoundary; 1653 oldWriter = null; 1654 oldStream = null; 1655 } 1656 WriteFragment(byte[] buffer, int offset, int count)1657 public void WriteFragment(byte[] buffer, int offset, int count) 1658 { 1659 if (!CanFragment) 1660 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException()); 1661 if (IsClosed) 1662 ThrowClosed(); 1663 if (buffer == null) 1664 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("buffer")); 1665 if (offset < 0) 1666 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("offset", SR.GetString(SR.ValueMustBeNonNegative))); 1667 if (count < 0) 1668 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("count", SR.GetString(SR.ValueMustBeNonNegative))); 1669 if (count > buffer.Length - offset) 1670 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("count", SR.GetString(SR.SizeExceedsRemainingBufferSpace, buffer.Length - offset))); 1671 if (WriteState == WriteState.Attribute) 1672 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.XmlInvalidWriteState, "WriteFragment", WriteState.ToString()))); 1673 if (writer != nodeWriter) 1674 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException()); 1675 FlushElement(); 1676 FlushBase64(); 1677 nodeWriter.Flush(); 1678 nodeWriter.Stream.Write(buffer, offset, count); 1679 } 1680 FlushBase64()1681 void FlushBase64() 1682 { 1683 if (trailByteCount > 0) 1684 { 1685 FlushTrailBytes(); 1686 } 1687 } 1688 FlushTrailBytes()1689 void FlushTrailBytes() 1690 { 1691 if (attributeValue != null) 1692 WriteAttributeText(XmlConverter.Base64Encoding.GetString(trailBytes, 0, trailByteCount)); 1693 1694 if (!isXmlnsAttribute) 1695 { 1696 StartContent(); 1697 writer.WriteBase64Text(trailBytes, trailByteCount, trailBytes, 0, 0); 1698 EndContent(); 1699 } 1700 trailByteCount = 0; 1701 } 1702 WriteValue(object[] array)1703 void WriteValue(object[] array) 1704 { 1705 FlushBase64(); 1706 StartContent(); 1707 writer.WriteStartListText(); 1708 this.inList = true; 1709 for (int i = 0; i < array.Length; i++) 1710 { 1711 if (i != 0) 1712 { 1713 writer.WriteListSeparator(); 1714 } 1715 WritePrimitiveValue(array[i]); 1716 } 1717 this.inList = false; 1718 writer.WriteEndListText(); 1719 EndContent(); 1720 } 1721 WriteValue(Array array)1722 void WriteValue(Array array) 1723 { 1724 FlushBase64(); 1725 StartContent(); 1726 writer.WriteStartListText(); 1727 this.inList = true; 1728 for (int i = 0; i < array.Length; i++) 1729 { 1730 if (i != 0) 1731 { 1732 writer.WriteListSeparator(); 1733 } 1734 WritePrimitiveValue(array.GetValue(i)); 1735 } 1736 this.inList = false; 1737 writer.WriteEndListText(); 1738 EndContent(); 1739 } 1740 StartArray(int count)1741 protected void StartArray(int count) 1742 { 1743 FlushBase64(); 1744 if (this.documentState == DocumentState.Epilog) 1745 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.XmlOnlyOneRoot))); 1746 if (this.documentState == DocumentState.Document && count > 1 && depth == 0) 1747 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.XmlOnlyOneRoot))); 1748 if (writeState == WriteState.Attribute) 1749 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.XmlInvalidWriteState, "WriteStartElement", WriteState.ToString()))); 1750 AutoComplete(WriteState.Content); 1751 } 1752 EndArray()1753 protected void EndArray() 1754 { 1755 } 1756 EnsureBufferBounds(byte[] buffer, int offset, int count)1757 void EnsureBufferBounds(byte[] buffer, int offset, int count) 1758 { 1759 if (buffer == null) 1760 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("buffer"); 1761 1762 // Not checking upper bound because it will be caught by "count". This is what XmlTextWriter does. 1763 if (offset < 0) 1764 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("offset", SR.GetString(SR.ValueMustBeNonNegative))); 1765 1766 if (count < 0) 1767 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("count", SR.GetString(SR.ValueMustBeNonNegative))); 1768 if (count > buffer.Length - offset) 1769 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("count", SR.GetString(SR.SizeExceedsRemainingBufferSpace, buffer.Length - offset))); 1770 } 1771 GeneratePrefix(string ns, XmlDictionaryString xNs)1772 string GeneratePrefix(string ns, XmlDictionaryString xNs) 1773 { 1774 if (writeState != WriteState.Element && writeState != WriteState.Attribute) 1775 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.XmlInvalidPrefixState, WriteState.ToString()))); 1776 1777 string prefix = nsMgr.AddNamespace(ns, xNs); 1778 1779 if (prefix != null) 1780 return prefix; 1781 1782 while (true) 1783 { 1784 int prefixId = elements[depth].PrefixId++; 1785 prefix = string.Concat("d", depth.ToString(CultureInfo.InvariantCulture), "p", prefixId.ToString(CultureInfo.InvariantCulture)); 1786 1787 if (nsMgr.LookupNamespace(prefix) == null) 1788 { 1789 nsMgr.AddNamespace(prefix, ns, xNs); 1790 return prefix; 1791 } 1792 } 1793 } 1794 SignScope(XmlCanonicalWriter signingWriter)1795 protected void SignScope(XmlCanonicalWriter signingWriter) 1796 { 1797 nsMgr.Sign(signingWriter); 1798 } 1799 WriteAttributeText(string value)1800 void WriteAttributeText(string value) 1801 { 1802 if (attributeValue.Length == 0) 1803 attributeValue = value; 1804 else 1805 attributeValue += value; 1806 } 1807 1808 class Element 1809 { 1810 string prefix; 1811 string localName; 1812 int prefixId; 1813 1814 public string Prefix 1815 { 1816 get 1817 { 1818 return prefix; 1819 } 1820 set 1821 { 1822 prefix = value; 1823 } 1824 } 1825 1826 public string LocalName 1827 { 1828 get 1829 { 1830 return localName; 1831 } 1832 set 1833 { 1834 localName = value; 1835 } 1836 } 1837 1838 public int PrefixId 1839 { 1840 get 1841 { 1842 return prefixId; 1843 } 1844 set 1845 { 1846 prefixId = value; 1847 } 1848 } 1849 Clear()1850 public void Clear() 1851 { 1852 this.prefix = null; 1853 this.localName = null; 1854 this.prefixId = 0; 1855 } 1856 } 1857 1858 enum DocumentState : byte 1859 { 1860 None, // Not inside StartDocument/EndDocument - Allows multiple root elemnts 1861 Document, // Inside StartDocument/EndDocument 1862 Epilog, // EndDocument must be called 1863 End // Nothing further to write 1864 } 1865 1866 class NamespaceManager 1867 { 1868 Namespace[] namespaces; 1869 Namespace lastNameSpace; 1870 int nsCount; 1871 int depth; 1872 XmlAttribute[] attributes; 1873 int attributeCount; 1874 XmlSpace space; 1875 string lang; 1876 int namespaceBoundary; 1877 int nsTop; 1878 Namespace defaultNamespace; 1879 NamespaceManager()1880 public NamespaceManager() 1881 { 1882 defaultNamespace = new Namespace(); 1883 defaultNamespace.Depth = 0; 1884 defaultNamespace.Prefix = string.Empty; 1885 defaultNamespace.Uri = string.Empty; 1886 defaultNamespace.UriDictionaryString = null; 1887 } 1888 1889 public string XmlLang 1890 { 1891 get 1892 { 1893 return lang; 1894 } 1895 } 1896 1897 public XmlSpace XmlSpace 1898 { 1899 get 1900 { 1901 return space; 1902 } 1903 } 1904 Clear()1905 public void Clear() 1906 { 1907 if (this.namespaces == null) 1908 { 1909 this.namespaces = new Namespace[4]; 1910 this.namespaces[0] = defaultNamespace; 1911 } 1912 this.nsCount = 1; 1913 this.nsTop = 0; 1914 this.depth = 0; 1915 this.attributeCount = 0; 1916 this.space = XmlSpace.None; 1917 this.lang = null; 1918 this.lastNameSpace = null; 1919 this.namespaceBoundary = 0; 1920 } 1921 1922 public int NamespaceBoundary 1923 { 1924 get 1925 { 1926 return namespaceBoundary; 1927 } 1928 set 1929 { 1930 int i; 1931 for (i = 0; i < nsCount; i++) 1932 if (namespaces[i].Depth >= value) 1933 break; 1934 1935 nsTop = i; 1936 namespaceBoundary = value; 1937 lastNameSpace = null; 1938 } 1939 } 1940 Close()1941 public void Close() 1942 { 1943 if (depth == 0) 1944 { 1945 if (namespaces != null && namespaces.Length > 32) 1946 namespaces = null; 1947 if (attributes != null && attributes.Length > 4) 1948 attributes = null; 1949 } 1950 else 1951 { 1952 namespaces = null; 1953 attributes = null; 1954 } 1955 lang = null; 1956 } 1957 DeclareNamespaces(XmlNodeWriter writer)1958 public void DeclareNamespaces(XmlNodeWriter writer) 1959 { 1960 int i = this.nsCount; 1961 while (i > 0) 1962 { 1963 Namespace nameSpace = namespaces[i - 1]; 1964 if (nameSpace.Depth != depth) 1965 break; 1966 i--; 1967 } 1968 while (i < this.nsCount) 1969 { 1970 Namespace nameSpace = namespaces[i]; 1971 if (nameSpace.UriDictionaryString != null) 1972 writer.WriteXmlnsAttribute(nameSpace.Prefix, nameSpace.UriDictionaryString); 1973 else 1974 writer.WriteXmlnsAttribute(nameSpace.Prefix, nameSpace.Uri); 1975 i++; 1976 } 1977 } 1978 EnterScope()1979 public void EnterScope() 1980 { 1981 depth++; 1982 } 1983 ExitScope()1984 public void ExitScope() 1985 { 1986 while (nsCount > 0) 1987 { 1988 Namespace nameSpace = namespaces[nsCount - 1]; 1989 if (nameSpace.Depth != depth) 1990 break; 1991 if (lastNameSpace == nameSpace) 1992 lastNameSpace = null; 1993 nameSpace.Clear(); 1994 nsCount--; 1995 } 1996 while (attributeCount > 0) 1997 { 1998 XmlAttribute attribute = attributes[attributeCount - 1]; 1999 if (attribute.Depth != depth) 2000 break; 2001 space = attribute.XmlSpace; 2002 lang = attribute.XmlLang; 2003 attribute.Clear(); 2004 attributeCount--; 2005 } 2006 depth--; 2007 } 2008 AddLangAttribute(string lang)2009 public void AddLangAttribute(string lang) 2010 { 2011 AddAttribute(); 2012 this.lang = lang; 2013 } 2014 AddSpaceAttribute(XmlSpace space)2015 public void AddSpaceAttribute(XmlSpace space) 2016 { 2017 AddAttribute(); 2018 this.space = space; 2019 } 2020 AddAttribute()2021 void AddAttribute() 2022 { 2023 if (attributes == null) 2024 { 2025 attributes = new XmlAttribute[1]; 2026 } 2027 else if (attributes.Length == attributeCount) 2028 { 2029 XmlAttribute[] newAttributes = new XmlAttribute[attributeCount * 2]; 2030 Array.Copy(attributes, newAttributes, attributeCount); 2031 attributes = newAttributes; 2032 } 2033 XmlAttribute attribute = attributes[attributeCount]; 2034 if (attribute == null) 2035 { 2036 attribute = new XmlAttribute(); 2037 attributes[attributeCount] = attribute; 2038 } 2039 attribute.XmlLang = this.lang; 2040 attribute.XmlSpace = this.space; 2041 attribute.Depth = depth; 2042 attributeCount++; 2043 } 2044 AddNamespace(string uri, XmlDictionaryString uriDictionaryString)2045 public string AddNamespace(string uri, XmlDictionaryString uriDictionaryString) 2046 { 2047 if (uri.Length == 0) 2048 { 2049 // Empty namespace can only be bound to the empty prefix 2050 AddNamespaceIfNotDeclared(string.Empty, uri, uriDictionaryString); 2051 return string.Empty; 2052 } 2053 else 2054 { 2055 for (int i = 0; i < prefixes.Length; i++) 2056 { 2057 string prefix = prefixes[i]; 2058 bool declared = false; 2059 for (int j = nsCount - 1; j >= nsTop; j--) 2060 { 2061 Namespace nameSpace = namespaces[j]; 2062 if (nameSpace.Prefix == prefix) 2063 { 2064 declared = true; 2065 break; 2066 } 2067 } 2068 if (!declared) 2069 { 2070 AddNamespace(prefix, uri, uriDictionaryString); 2071 return prefix; 2072 } 2073 } 2074 } 2075 return null; 2076 } 2077 AddNamespaceIfNotDeclared(string prefix, string uri, XmlDictionaryString uriDictionaryString)2078 public void AddNamespaceIfNotDeclared(string prefix, string uri, XmlDictionaryString uriDictionaryString) 2079 { 2080 if (LookupNamespace(prefix) != uri) 2081 { 2082 AddNamespace(prefix, uri, uriDictionaryString); 2083 } 2084 } 2085 AddNamespace(string prefix, string uri, XmlDictionaryString uriDictionaryString)2086 public void AddNamespace(string prefix, string uri, XmlDictionaryString uriDictionaryString) 2087 { 2088 if (prefix.Length >= 3) 2089 { 2090 // Upper and lower case letter differ by a bit. 2091 if ((prefix[0] & ~32) == 'X' && (prefix[1] & ~32) == 'M' && (prefix[2] & ~32) == 'L') 2092 { 2093 if (prefix == "xml" && uri == xmlNamespace) 2094 return; 2095 if (prefix == "xmlns" && uri == xmlnsNamespace) 2096 return; 2097 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.XmlReservedPrefix), "prefix")); 2098 } 2099 } 2100 Namespace nameSpace; 2101 for (int i = nsCount - 1; i >= 0; i--) 2102 { 2103 nameSpace = namespaces[i]; 2104 if (nameSpace.Depth != depth) 2105 break; 2106 if (nameSpace.Prefix == prefix) 2107 { 2108 if (nameSpace.Uri == uri) 2109 return; 2110 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.XmlPrefixBoundToNamespace, prefix, nameSpace.Uri, uri), "prefix")); 2111 } 2112 } 2113 if (prefix.Length != 0 && uri.Length == 0) 2114 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.XmlEmptyNamespaceRequiresNullPrefix), "prefix")); 2115 if (uri.Length == xmlnsNamespace.Length && uri == xmlnsNamespace) 2116 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.XmlSpecificBindingNamespace, "xmlns", uri))); 2117 // The addressing namespace and the xmlNamespace are the same length, so add a quick check to try to disambiguate 2118 if (uri.Length == xmlNamespace.Length && uri[18] == 'X' && uri == xmlNamespace) 2119 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.XmlSpecificBindingNamespace, "xml", uri))); 2120 2121 if (namespaces.Length == nsCount) 2122 { 2123 Namespace[] newNamespaces = new Namespace[nsCount * 2]; 2124 Array.Copy(namespaces, newNamespaces, nsCount); 2125 namespaces = newNamespaces; 2126 } 2127 nameSpace = namespaces[nsCount]; 2128 if (nameSpace == null) 2129 { 2130 nameSpace = new Namespace(); 2131 namespaces[nsCount] = nameSpace; 2132 } 2133 nameSpace.Depth = depth; 2134 nameSpace.Prefix = prefix; 2135 nameSpace.Uri = uri; 2136 nameSpace.UriDictionaryString = uriDictionaryString; 2137 nsCount++; 2138 lastNameSpace = null; 2139 } 2140 LookupPrefix(string ns)2141 public string LookupPrefix(string ns) 2142 { 2143 if (lastNameSpace != null && lastNameSpace.Uri == ns) 2144 return lastNameSpace.Prefix; 2145 int nsCount = this.nsCount; 2146 for (int i = nsCount - 1; i >= nsTop; i--) 2147 { 2148 Namespace nameSpace = namespaces[i]; 2149 if (object.ReferenceEquals(nameSpace.Uri, ns)) 2150 { 2151 string prefix = nameSpace.Prefix; 2152 // Make sure that the prefix refers to the namespace in scope 2153 bool declared = false; 2154 for (int j = i + 1; j < nsCount; j++) 2155 { 2156 if (namespaces[j].Prefix == prefix) 2157 { 2158 declared = true; 2159 break; 2160 } 2161 } 2162 if (!declared) 2163 { 2164 lastNameSpace = nameSpace; 2165 return prefix; 2166 } 2167 } 2168 } 2169 for (int i = nsCount - 1; i >= nsTop; i--) 2170 { 2171 Namespace nameSpace = namespaces[i]; 2172 if (nameSpace.Uri == ns) 2173 { 2174 string prefix = nameSpace.Prefix; 2175 // Make sure that the prefix refers to the namespace in scope 2176 bool declared = false; 2177 for (int j = i + 1; j < nsCount; j++) 2178 { 2179 if (namespaces[j].Prefix == prefix) 2180 { 2181 declared = true; 2182 break; 2183 } 2184 } 2185 if (!declared) 2186 { 2187 lastNameSpace = nameSpace; 2188 return prefix; 2189 } 2190 } 2191 } 2192 2193 if (ns.Length == 0) 2194 { 2195 // Make sure the default binding is still valid 2196 bool emptyPrefixUnassigned = true; 2197 for (int i = nsCount - 1; i >= nsTop; i--) 2198 { 2199 if (namespaces[i].Prefix.Length == 0) 2200 { 2201 emptyPrefixUnassigned = false; 2202 break; 2203 } 2204 } 2205 if (emptyPrefixUnassigned) 2206 return string.Empty; 2207 } 2208 2209 if (ns == xmlnsNamespace) 2210 return "xmlns"; 2211 if (ns == xmlNamespace) 2212 return "xml"; 2213 return null; 2214 } 2215 LookupAttributePrefix(string ns)2216 public string LookupAttributePrefix(string ns) 2217 { 2218 if (lastNameSpace != null && lastNameSpace.Uri == ns && lastNameSpace.Prefix.Length != 0) 2219 return lastNameSpace.Prefix; 2220 2221 int nsCount = this.nsCount; 2222 for (int i = nsCount - 1; i >= nsTop; i--) 2223 { 2224 Namespace nameSpace = namespaces[i]; 2225 2226 if (object.ReferenceEquals(nameSpace.Uri, ns)) 2227 { 2228 string prefix = nameSpace.Prefix; 2229 if (prefix.Length != 0) 2230 { 2231 // Make sure that the prefix refers to the namespace in scope 2232 bool declared = false; 2233 for (int j = i + 1; j < nsCount; j++) 2234 { 2235 if (namespaces[j].Prefix == prefix) 2236 { 2237 declared = true; 2238 break; 2239 } 2240 } 2241 if (!declared) 2242 { 2243 lastNameSpace = nameSpace; 2244 return prefix; 2245 } 2246 } 2247 } 2248 } 2249 for (int i = nsCount - 1; i >= nsTop; i--) 2250 { 2251 Namespace nameSpace = namespaces[i]; 2252 if (nameSpace.Uri == ns) 2253 { 2254 string prefix = nameSpace.Prefix; 2255 if (prefix.Length != 0) 2256 { 2257 // Make sure that the prefix refers to the namespace in scope 2258 bool declared = false; 2259 for (int j = i + 1; j < nsCount; j++) 2260 { 2261 if (namespaces[j].Prefix == prefix) 2262 { 2263 declared = true; 2264 break; 2265 } 2266 } 2267 if (!declared) 2268 { 2269 lastNameSpace = nameSpace; 2270 return prefix; 2271 } 2272 } 2273 } 2274 } 2275 if (ns.Length == 0) 2276 return string.Empty; 2277 return null; 2278 } 2279 LookupNamespace(string prefix)2280 public string LookupNamespace(string prefix) 2281 { 2282 int nsCount = this.nsCount; 2283 if (prefix.Length == 0) 2284 { 2285 for (int i = nsCount - 1; i >= nsTop; i--) 2286 { 2287 Namespace nameSpace = namespaces[i]; 2288 if (nameSpace.Prefix.Length == 0) 2289 return nameSpace.Uri; 2290 } 2291 return string.Empty; 2292 } 2293 if (prefix.Length == 1) 2294 { 2295 char prefixChar = prefix[0]; 2296 for (int i = nsCount - 1; i >= nsTop; i--) 2297 { 2298 Namespace nameSpace = namespaces[i]; 2299 if (nameSpace.PrefixChar == prefixChar) 2300 return nameSpace.Uri; 2301 } 2302 return null; 2303 } 2304 for (int i = nsCount - 1; i >= nsTop; i--) 2305 { 2306 Namespace nameSpace = namespaces[i]; 2307 if (nameSpace.Prefix == prefix) 2308 return nameSpace.Uri; 2309 } 2310 if (prefix == "xmlns") 2311 return xmlnsNamespace; 2312 if (prefix == "xml") 2313 return xmlNamespace; 2314 return null; 2315 } 2316 Sign(XmlCanonicalWriter signingWriter)2317 public void Sign(XmlCanonicalWriter signingWriter) 2318 { 2319 int nsCount = this.nsCount; 2320 Fx.Assert(nsCount >= 1 && namespaces[0].Prefix.Length == 0 && namespaces[0].Uri.Length == 0, ""); 2321 for (int i = 1; i < nsCount; i++) 2322 { 2323 Namespace nameSpace = namespaces[i]; 2324 2325 bool found = false; 2326 for (int j = i + 1; j < nsCount && !found; j++) 2327 { 2328 found = (nameSpace.Prefix == namespaces[j].Prefix); 2329 } 2330 2331 if (!found) 2332 { 2333 signingWriter.WriteXmlnsAttribute(nameSpace.Prefix, nameSpace.Uri); 2334 } 2335 } 2336 } 2337 2338 class XmlAttribute 2339 { 2340 XmlSpace space; 2341 string lang; 2342 int depth; 2343 XmlAttribute()2344 public XmlAttribute() 2345 { 2346 } 2347 2348 public int Depth 2349 { 2350 get 2351 { 2352 return depth; 2353 } 2354 set 2355 { 2356 depth = value; 2357 } 2358 } 2359 2360 public string XmlLang 2361 { 2362 get 2363 { 2364 return lang; 2365 } 2366 set 2367 { 2368 lang = value; 2369 } 2370 } 2371 2372 public XmlSpace XmlSpace 2373 { 2374 get 2375 { 2376 return space; 2377 } 2378 set 2379 { 2380 space = value; 2381 } 2382 } 2383 Clear()2384 public void Clear() 2385 { 2386 this.lang = null; 2387 } 2388 } 2389 2390 class Namespace 2391 { 2392 string prefix; 2393 string ns; 2394 XmlDictionaryString xNs; 2395 int depth; 2396 char prefixChar; 2397 Namespace()2398 public Namespace() 2399 { 2400 } 2401 Clear()2402 public void Clear() 2403 { 2404 this.prefix = null; 2405 this.prefixChar = (char)0; 2406 this.ns = null; 2407 this.xNs = null; 2408 this.depth = 0; 2409 } 2410 2411 public int Depth 2412 { 2413 get 2414 { 2415 return depth; 2416 } 2417 set 2418 { 2419 depth = value; 2420 } 2421 } 2422 2423 public char PrefixChar 2424 { 2425 get 2426 { 2427 return prefixChar; 2428 } 2429 } 2430 2431 public string Prefix 2432 { 2433 get 2434 { 2435 return prefix; 2436 } 2437 set 2438 { 2439 if (value.Length == 1) 2440 prefixChar = value[0]; 2441 else 2442 prefixChar = (char)0; 2443 prefix = value; 2444 } 2445 } 2446 2447 public string Uri 2448 { 2449 get 2450 { 2451 return ns; 2452 } 2453 set 2454 { 2455 ns = value; 2456 } 2457 } 2458 2459 public XmlDictionaryString UriDictionaryString 2460 { 2461 get 2462 { 2463 return xNs; 2464 } 2465 set 2466 { 2467 xNs = value; 2468 } 2469 } 2470 } 2471 } 2472 2473 class XmlBaseWriterNodeWriterAsyncHelper 2474 { 2475 static AsyncEventArgsCallback onWriteComplete; 2476 2477 XmlBaseWriter writer; 2478 byte[] buffer; 2479 int offset; 2480 int count; 2481 int actualByteCount; 2482 int totalByteCount; 2483 AsyncEventArgs<XmlNodeWriterWriteBase64TextArgs> nodeWriterAsyncState; 2484 XmlNodeWriterWriteBase64TextArgs nodeWriterArgs; 2485 AsyncEventArgs<XmlWriteBase64AsyncArguments> inputState; 2486 XmlBaseWriterNodeWriterAsyncHelper(XmlBaseWriter writer)2487 public XmlBaseWriterNodeWriterAsyncHelper(XmlBaseWriter writer) 2488 { 2489 this.writer = writer; 2490 } 2491 SetArguments(AsyncEventArgs<XmlWriteBase64AsyncArguments> inputState)2492 public void SetArguments(AsyncEventArgs<XmlWriteBase64AsyncArguments> inputState) 2493 { 2494 Fx.Assert(inputState != null, "InputState cannot be null."); 2495 this.inputState = inputState; 2496 this.buffer = inputState.Arguments.Buffer; 2497 this.offset = inputState.Arguments.Offset; 2498 this.count = inputState.Arguments.Count; 2499 } 2500 StartAsync()2501 public AsyncCompletionResult StartAsync() 2502 { 2503 bool completeSelf = true; 2504 2505 if (this.count > 0) 2506 { 2507 // Bytes that have been already been read. 2508 if (this.writer.trailByteCount > 0) 2509 { 2510 // Copy over up to 3 trailing bytes into the trailBytes buffer. 2511 while (this.writer.trailByteCount < 3 && this.count > 0) 2512 { 2513 this.writer.trailBytes[this.writer.trailByteCount++] = this.buffer[this.offset++]; 2514 this.count--; 2515 } 2516 } 2517 2518 this.totalByteCount = this.writer.trailByteCount + this.count; 2519 this.actualByteCount = this.totalByteCount - (this.totalByteCount % 3); 2520 2521 if (this.writer.trailBytes == null) 2522 { 2523 this.writer.trailBytes = new byte[3]; 2524 } 2525 2526 if (actualByteCount >= 3) 2527 { 2528 if (this.writer.attributeValue != null) 2529 { 2530 this.writer.WriteAttributeText(XmlConverter.Base64Encoding.GetString(this.writer.trailBytes, 0, this.writer.trailByteCount)); 2531 this.writer.WriteAttributeText(XmlConverter.Base64Encoding.GetString(this.buffer, this.offset, actualByteCount - this.writer.trailByteCount)); 2532 } 2533 2534 // StartContent/WriteBase64Text/EndContent will be called from HandleWriteBase64 as appropriate 2535 completeSelf = HandleWriteBase64Text(false); 2536 } 2537 else 2538 { 2539 Buffer.BlockCopy(this.buffer, this.offset, this.writer.trailBytes, this.writer.trailByteCount, this.count); 2540 this.writer.trailByteCount += this.count; 2541 } 2542 } 2543 2544 if (completeSelf) 2545 { 2546 this.Clear(); 2547 return AsyncCompletionResult.Completed; 2548 } 2549 2550 return AsyncCompletionResult.Queued; 2551 } 2552 OnWriteComplete(IAsyncEventArgs asyncEventArgs)2553 static void OnWriteComplete(IAsyncEventArgs asyncEventArgs) 2554 { 2555 bool completeSelf = false; 2556 Exception completionException = null; 2557 XmlBaseWriterNodeWriterAsyncHelper thisPtr = (XmlBaseWriterNodeWriterAsyncHelper)asyncEventArgs.AsyncState; 2558 AsyncEventArgs<XmlWriteBase64AsyncArguments> inputState = thisPtr.inputState; 2559 2560 try 2561 { 2562 if (asyncEventArgs.Exception != null) 2563 { 2564 completionException = asyncEventArgs.Exception; 2565 completeSelf = true; 2566 } 2567 else 2568 { 2569 completeSelf = thisPtr.HandleWriteBase64Text(true); 2570 } 2571 } 2572 catch (Exception exception) 2573 { 2574 if (Fx.IsFatal(exception)) 2575 { 2576 throw; 2577 } 2578 2579 completionException = exception; 2580 completeSelf = true; 2581 } 2582 2583 if (completeSelf) 2584 { 2585 thisPtr.Clear(); 2586 inputState.Complete(false, completionException); 2587 } 2588 } 2589 HandleWriteBase64Text(bool isAsyncCallback)2590 bool HandleWriteBase64Text(bool isAsyncCallback) 2591 { 2592 Fx.Assert(this.count > 0 && this.actualByteCount >= 3, "HandleWriteBase64Text cannot be invoked with less than 3 bytes."); 2593 if (!writer.isXmlnsAttribute) 2594 { 2595 if (!isAsyncCallback) 2596 { 2597 if (this.nodeWriterAsyncState == null) 2598 { 2599 this.nodeWriterAsyncState = new AsyncEventArgs<XmlNodeWriterWriteBase64TextArgs>(); 2600 this.nodeWriterArgs = new XmlNodeWriterWriteBase64TextArgs(); 2601 } 2602 if (onWriteComplete == null) 2603 { 2604 onWriteComplete = new AsyncEventArgsCallback(OnWriteComplete); 2605 } 2606 2607 this.writer.StartContent(); 2608 this.nodeWriterArgs.TrailBuffer = this.writer.trailBytes; 2609 this.nodeWriterArgs.TrailCount = this.writer.trailByteCount; 2610 this.nodeWriterArgs.Buffer = this.buffer; 2611 this.nodeWriterArgs.Offset = this.offset; 2612 this.nodeWriterArgs.Count = this.actualByteCount - this.writer.trailByteCount; 2613 2614 this.nodeWriterAsyncState.Set(onWriteComplete, this.nodeWriterArgs, this); 2615 if (this.writer.writer.WriteBase64TextAsync(this.nodeWriterAsyncState) != AsyncCompletionResult.Completed) 2616 { 2617 return false; 2618 } 2619 2620 this.nodeWriterAsyncState.Complete(true); 2621 } 2622 2623 this.writer.EndContent(); 2624 } 2625 2626 this.writer.trailByteCount = (this.totalByteCount - this.actualByteCount); 2627 if (this.writer.trailByteCount > 0) 2628 { 2629 int trailOffset = offset + count - this.writer.trailByteCount; 2630 for (int i = 0; i < this.writer.trailByteCount; i++) 2631 this.writer.trailBytes[i] = this.buffer[trailOffset++]; 2632 } 2633 2634 return true; 2635 } 2636 Clear()2637 void Clear() 2638 { 2639 this.inputState = null; 2640 this.buffer = null; 2641 this.offset = 0; 2642 this.count = 0; 2643 this.actualByteCount = 0; 2644 this.totalByteCount = 0; 2645 } 2646 } 2647 } 2648 } 2649