< Summary - CoreWCF Coverage — PR #1766

Information
Class: CoreWCF.IdentityModel.WrappedReader
Assembly: CoreWCF.Primitives
File(s): /home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.Primitives/src/CoreWCF/IdentityModel/WrappedReader.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 104
Coverable lines: 104
Total lines: 653
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 72
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
.ctor(...)0%440%
Close()100%110%
HasLineInfo()0%220%
MoveToAttribute(...)100%110%
MoveToAttribute(...)100%110%
MoveToAttribute(...)100%110%
MoveToElement()100%110%
MoveToFirstAttribute()100%110%
MoveToNextAttribute()100%110%
OnEndOfContent()0%440%
Read()0%440%
ReadBinaryContent(...)0%16160%
ReadContentAsBase64(...)100%110%
ReadContentAsBinHex(...)100%110%
ReadValueChunk(...)0%220%
Record()0%28280%
Dispose(...)0%880%

File(s)

/home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.Primitives/src/CoreWCF/IdentityModel/WrappedReader.cs

#LineLine coverage
 1// Licensed to the .NET Foundation under one or more agreements.
 2// The .NET Foundation licenses this file to you under the MIT license.
 3
 4using System;
 5using System.IO;
 6using System.Text;
 7using System.Xml;
 8using HexBinary = CoreWCF.Security.SoapHexBinary;
 9
 10namespace CoreWCF.IdentityModel
 11{
 12    internal sealed class WrappedReader : DelegatingXmlDictionaryReader, IXmlLineInfo
 13    {
 14        private MemoryStream _contentStream;
 15        private TextReader _contentReader;
 16        private bool _recordDone;
 17        private int _depth;
 18        private bool _disposed;
 19
 020        public WrappedReader(XmlDictionaryReader reader)
 21        {
 022            if (reader == null)
 23            {
 024                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(reader));
 25            }
 026            if (!reader.IsStartElement())
 27            {
 028                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.Format(SR.Inn
 29            }
 030            XmlTokens = new XmlTokenStream(32);
 031            base.InitializeInnerReader(reader);
 032            Record();
 033        }
 34
 35        public int LineNumber
 36        {
 37            get
 38            {
 039                IXmlLineInfo lineInfo = base.InnerReader as IXmlLineInfo;
 040                if (lineInfo == null)
 41                {
 042                    return 1;
 43                }
 044                return lineInfo.LineNumber;
 45            }
 46        }
 47
 48        public int LinePosition
 49        {
 50            get
 51            {
 052                IXmlLineInfo lineInfo = base.InnerReader as IXmlLineInfo;
 053                if (lineInfo == null)
 54                {
 055                    return 1;
 56                }
 057                return lineInfo.LinePosition;
 58            }
 59        }
 60
 061        public XmlTokenStream XmlTokens { get; }
 62
 63        public override void Close()
 64        {
 065            OnEndOfContent();
 066            base.InnerReader.Close();
 067        }
 68
 69        public bool HasLineInfo()
 70        {
 071            IXmlLineInfo lineInfo = base.InnerReader as IXmlLineInfo;
 072            return lineInfo != null && lineInfo.HasLineInfo();
 73        }
 74
 75        public override void MoveToAttribute(int index)
 76        {
 077            OnEndOfContent();
 078            base.InnerReader.MoveToAttribute(index);
 079        }
 80
 81        public override bool MoveToAttribute(string name)
 82        {
 083            OnEndOfContent();
 084            return base.InnerReader.MoveToAttribute(name);
 85        }
 86
 87        public override bool MoveToAttribute(string name, string ns)
 88        {
 089            OnEndOfContent();
 090            return base.InnerReader.MoveToAttribute(name, ns);
 91        }
 92
 93        public override bool MoveToElement()
 94        {
 095            OnEndOfContent();
 096            return base.MoveToElement();
 97        }
 98
 99        public override bool MoveToFirstAttribute()
 100        {
 0101            OnEndOfContent();
 0102            return base.MoveToFirstAttribute();
 103        }
 104
 105        public override bool MoveToNextAttribute()
 106        {
 0107            OnEndOfContent();
 0108            return base.MoveToNextAttribute();
 109        }
 110
 111        private void OnEndOfContent()
 112        {
 0113            if (_contentReader != null)
 114            {
 0115                _contentReader.Close();
 0116                _contentReader = null;
 117            }
 0118            if (_contentStream != null)
 119            {
 0120                _contentStream.Close();
 0121                _contentStream = null;
 122            }
 0123        }
 124
 125        public override bool Read()
 126        {
 0127            OnEndOfContent();
 0128            if (!base.Read())
 129            {
 0130                return false;
 131            }
 0132            if (!_recordDone)
 133            {
 0134                Record();
 135            }
 0136            return true;
 137        }
 138
 139        private int ReadBinaryContent(byte[] buffer, int offset, int count, bool isBase64)
 140        {
 0141            CryptoHelper.ValidateBufferBounds(buffer, offset, count);
 142
 143            //
 144            // Concatentate text nodes to get entire element value before attempting to convert
 145            // XmlDictionaryReader.CreateDictionaryReader( XmlReader ) creates a reader that returns base64 in a single 
 146            // XmlDictionaryReader.CreateTextReader( Stream ) creates a reader that produces multiple text and whitespac
 147            // Attribute nodes consist of only a single value
 148            //
 0149            if (_contentStream == null)
 150            {
 151                string encodedValue;
 0152                if (NodeType == XmlNodeType.Attribute)
 153                {
 0154                    encodedValue = Value;
 155                }
 156                else
 157                {
 0158                    StringBuilder fullText = new StringBuilder(1000);
 0159                    while (NodeType != XmlNodeType.Element && NodeType != XmlNodeType.EndElement)
 160                    {
 0161                        switch (NodeType)
 162                        {
 163                            // concatenate text nodes
 164                            case XmlNodeType.Text:
 0165                                fullText.Append(Value);
 166                                break;
 167
 168                            // skip whitespace
 169                            case XmlNodeType.Whitespace:
 170                                break;
 171                        }
 172
 0173                        Read();
 174                    }
 175
 0176                    encodedValue = fullText.ToString();
 177                }
 178
 0179                byte[] value = isBase64 ? Convert.FromBase64String(encodedValue) : HexBinary.Parse(encodedValue).Value;
 0180                _contentStream = new MemoryStream(value);
 181            }
 182
 0183            int read = _contentStream.Read(buffer, offset, count);
 0184            if (read == 0)
 185            {
 0186                _contentStream.Close();
 0187                _contentStream = null;
 188            }
 189
 0190            return read;
 191        }
 192
 193        public override int ReadContentAsBase64(byte[] buffer, int offset, int count)
 194        {
 0195            return ReadBinaryContent(buffer, offset, count, true);
 196        }
 197
 198        public override int ReadContentAsBinHex(byte[] buffer, int offset, int count)
 199        {
 0200            return ReadBinaryContent(buffer, offset, count, false);
 201        }
 202
 203        public override int ReadValueChunk(char[] chars, int offset, int count)
 204        {
 0205            if (_contentReader == null)
 206            {
 0207                _contentReader = new StringReader(Value);
 208            }
 0209            return _contentReader.Read(chars, offset, count);
 210        }
 211
 212        private void Record()
 213        {
 0214            switch (NodeType)
 215            {
 216                case XmlNodeType.Element:
 217                    {
 0218                        bool isEmpty = base.InnerReader.IsEmptyElement;
 0219                        XmlTokens.AddElement(base.InnerReader.Prefix, base.InnerReader.LocalName, base.InnerReader.Names
 0220                        if (base.InnerReader.MoveToFirstAttribute())
 221                        {
 222                            do
 223                            {
 0224                                XmlTokens.AddAttribute(base.InnerReader.Prefix, base.InnerReader.LocalName, base.InnerRe
 225                            }
 0226                            while (base.InnerReader.MoveToNextAttribute());
 0227                            base.InnerReader.MoveToElement();
 228                        }
 0229                        if (!isEmpty)
 230                        {
 0231                            _depth++;
 232                        }
 0233                        else if (_depth == 0)
 234                        {
 0235                            _recordDone = true;
 236                        }
 0237                        break;
 238                    }
 239                case XmlNodeType.CDATA:
 240                case XmlNodeType.Comment:
 241                case XmlNodeType.Text:
 242                case XmlNodeType.EntityReference:
 243                case XmlNodeType.EndEntity:
 244                case XmlNodeType.SignificantWhitespace:
 245                case XmlNodeType.Whitespace:
 246                    {
 0247                        XmlTokens.Add(NodeType, Value);
 0248                        break;
 249                    }
 250                case XmlNodeType.EndElement:
 251                    {
 0252                        XmlTokens.Add(NodeType, Value);
 0253                        if (--_depth == 0)
 254                        {
 0255                            _recordDone = true;
 256                        }
 0257                        break;
 258                    }
 259                case XmlNodeType.DocumentType:
 260                case XmlNodeType.XmlDeclaration:
 261                    {
 262                        break;
 263                    }
 264                default:
 265                    {
 266
 0267                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.Format(SR.UnsupportedN
 0268                     base.InnerReader.NodeType, base.InnerReader.Name)));
 269
 270                    }
 271
 272            }
 0273        }
 274
 275        protected override void Dispose(bool disposing)
 276        {
 0277            base.Dispose(disposing);
 278
 0279            if (_disposed)
 280            {
 0281                return;
 282            }
 283
 0284            if (disposing)
 285            {
 286                //
 287                // Free all of our managed resources
 288                //
 0289                if (_contentReader != null)
 290                {
 0291                    _contentReader.Dispose();
 0292                    _contentReader = null;
 293                }
 294
 0295                if (_contentStream != null)
 296                {
 0297                    _contentStream.Dispose();
 0298                    _contentStream = null;
 299                }
 300            }
 301
 302            // Free native resources, if any.
 303
 0304            _disposed = true;
 0305        }
 306    }
 307
 308    sealed internal class XmlTokenStream : ISecurityElement
 309    {
 310        private int count;
 311        private XmlTokenEntry[] _entries;
 312        private string _excludedElement;
 313        private int? _excludedElementDepth;
 314        private string _excludedElementNamespace;
 315
 316        public XmlTokenStream(int initialSize)
 317        {
 318            if (initialSize < 1)
 319            {
 320                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(initial
 321            }
 322            _entries = new XmlTokenEntry[initialSize];
 323        }
 324
 325        // This constructor is used by the Trim method to reduce the size of the XmlTokenEntry array to the minimum requ
 326        public XmlTokenStream(XmlTokenStream other)
 327        {
 328            count = other.count;
 329            _excludedElement = other._excludedElement;
 330            _excludedElementDepth = other._excludedElementDepth;
 331            _excludedElementNamespace = other._excludedElementNamespace;
 332            _entries = new XmlTokenEntry[count];
 333            Array.Copy(other._entries, _entries, count);
 334        }
 335
 336        public void Add(XmlNodeType type, string value)
 337        {
 338            EnsureCapacityToAdd();
 339            _entries[count++].Set(type, value);
 340        }
 341
 342        public void AddAttribute(string prefix, string localName, string namespaceUri, string value)
 343        {
 344            EnsureCapacityToAdd();
 345            _entries[count++].SetAttribute(prefix, localName, namespaceUri, value);
 346        }
 347
 348        public void AddElement(string prefix, string localName, string namespaceUri, bool isEmptyElement)
 349        {
 350            EnsureCapacityToAdd();
 351            _entries[count++].SetElement(prefix, localName, namespaceUri, isEmptyElement);
 352        }
 353
 354        private void EnsureCapacityToAdd()
 355        {
 356            if (count == _entries.Length)
 357            {
 358                XmlTokenEntry[] newBuffer = new XmlTokenEntry[_entries.Length * 2];
 359                Array.Copy(_entries, 0, newBuffer, 0, count);
 360                _entries = newBuffer;
 361            }
 362        }
 363
 364        public void SetElementExclusion(string excludedElement, string excludedElementNamespace)
 365        {
 366            SetElementExclusion(excludedElement, excludedElementNamespace, null);
 367        }
 368
 369        public void SetElementExclusion(string excludedElement, string excludedElementNamespace, int? excludedElementDep
 370        {
 371            _excludedElement = excludedElement;
 372            _excludedElementDepth = excludedElementDepth;
 373            _excludedElementNamespace = excludedElementNamespace;
 374        }
 375
 376        /// <summary>
 377        /// Free unneeded entries from array
 378        /// </summary>
 379        /// <returns></returns>
 380        public XmlTokenStream Trim()
 381        {
 382            return new XmlTokenStream(this);
 383        }
 384
 385        public XmlTokenStreamWriter GetWriter()
 386        {
 387            return new XmlTokenStreamWriter( _entries, count, _excludedElement, _excludedElementDepth, _excludedElementN
 388        }
 389
 390        public void WriteTo(XmlDictionaryWriter writer, DictionaryManager dictionaryManager)
 391        {
 392            GetWriter().WriteTo(writer, dictionaryManager);
 393        }
 394
 395        bool ISecurityElement.HasId
 396        {
 397            get { return false; }
 398        }
 399
 400        string ISecurityElement.Id
 401        {
 402            get { return null; }
 403        }
 404
 405        internal class XmlTokenStreamWriter : ISecurityElement
 406        {
 407            private XmlTokenEntry[] _entries;
 408            private int? _excludedElementDepth;
 409
 410            public XmlTokenStreamWriter(XmlTokenEntry[] entries,
 411                                         int count,
 412                                         string excludedElement,
 413                                         int? excludedElementDepth,
 414                                         string excludedElementNamespace)
 415            {
 416                if (entries == null)
 417                {
 418                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(entries));
 419                }
 420                _entries = entries;
 421                Count = count;
 422                ExcludedElement = excludedElement;
 423                _excludedElementDepth = excludedElementDepth;
 424                ExcludedElementNamespace = excludedElementNamespace;
 425            }
 426
 427            public int Count { get; }
 428
 429            public int Position { get; private set; }
 430
 431            public XmlNodeType NodeType
 432            {
 433                get { return _entries[Position].nodeType; }
 434            }
 435
 436            public bool IsEmptyElement
 437            {
 438                get { return _entries[Position].IsEmptyElement; }
 439            }
 440
 441            public string Prefix
 442            {
 443                get { return _entries[Position].prefix; }
 444            }
 445
 446            public string LocalName
 447            {
 448                get { return _entries[Position].localName; }
 449            }
 450
 451            public string NamespaceUri
 452            {
 453                get { return _entries[Position].namespaceUri; }
 454            }
 455
 456            public string Value
 457            {
 458                get { return _entries[Position].Value; }
 459            }
 460
 461            public string ExcludedElement { get; }
 462
 463            public string ExcludedElementNamespace { get; }
 464            bool ISecurityElement.HasId
 465            {
 466                get { return false; }
 467            }
 468
 469            string ISecurityElement.Id
 470            {
 471                get { return null; }
 472            }
 473
 474            public bool MoveToFirst()
 475            {
 476                Position = 0;
 477                return Count > 0;
 478            }
 479
 480            public bool MoveToFirstAttribute()
 481            {
 482                DiagnosticUtility.DebugAssert(NodeType == XmlNodeType.Element, "");
 483                if (Position < Count - 1 && _entries[Position + 1].nodeType == XmlNodeType.Attribute)
 484                {
 485                    Position++;
 486                    return true;
 487                }
 488                else
 489                {
 490                    return false;
 491                }
 492            }
 493
 494            public bool MoveToNext()
 495            {
 496                if (Position < Count - 1)
 497                {
 498                    Position++;
 499                    return true;
 500                }
 501                return false;
 502            }
 503
 504            public bool MoveToNextAttribute()
 505            {
 506                DiagnosticUtility.DebugAssert(NodeType == XmlNodeType.Attribute, "");
 507                if (Position < Count - 1 && _entries[Position + 1].nodeType == XmlNodeType.Attribute)
 508                {
 509                    Position++;
 510                    return true;
 511                }
 512                else
 513                {
 514                    return false;
 515                }
 516            }
 517
 518            public void WriteTo(XmlDictionaryWriter writer, DictionaryManager dictionaryManager)
 519            {
 520                if (writer == null)
 521                {
 522                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(writer)))
 523                }
 524                if (!MoveToFirst())
 525                {
 526                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.Format(SR
 527                }
 528                int depth = 0;
 529                int recordedDepth = -1;
 530                bool include = true;
 531                do
 532                {
 533                    switch (NodeType)
 534                    {
 535                        case XmlNodeType.Element:
 536                            bool isEmpty = IsEmptyElement;
 537                            depth++;
 538                            if (include
 539                                && (null == _excludedElementDepth || _excludedElementDepth == (depth - 1))
 540                                && LocalName == ExcludedElement
 541                                && NamespaceUri == ExcludedElementNamespace)
 542                            {
 543                                include = false;
 544                                recordedDepth = depth;
 545                            }
 546                            if (include)
 547                            {
 548                                writer.WriteStartElement(Prefix, LocalName, NamespaceUri);
 549                            }
 550                            if (MoveToFirstAttribute())
 551                            {
 552                                do
 553                                {
 554                                    if (include)
 555                                    {
 556                                        writer.WriteAttributeString(Prefix, LocalName, NamespaceUri, Value);
 557                                    }
 558                                }
 559                                while (MoveToNextAttribute());
 560                            }
 561                            if (isEmpty)
 562                            {
 563                                goto case XmlNodeType.EndElement;
 564                            }
 565                            break;
 566                        case XmlNodeType.EndElement:
 567                            if (include)
 568                            {
 569                                writer.WriteEndElement();
 570                            }
 571                            else if (recordedDepth == depth)
 572                            {
 573                                include = true;
 574                                recordedDepth = -1;
 575                            }
 576                            depth--;
 577                            break;
 578                        case XmlNodeType.CDATA:
 579                            if (include)
 580                            {
 581                                writer.WriteCData(Value);
 582                            }
 583                            break;
 584                        case XmlNodeType.Comment:
 585                            if (include)
 586                            {
 587                                writer.WriteComment(Value);
 588                            }
 589                            break;
 590                        case XmlNodeType.Text:
 591                            if (include)
 592                            {
 593                                writer.WriteString(Value);
 594                            }
 595                            break;
 596                        case XmlNodeType.SignificantWhitespace:
 597                        case XmlNodeType.Whitespace:
 598                            if (include)
 599                            {
 600                                writer.WriteWhitespace(Value);
 601                            }
 602                            break;
 603                        case XmlNodeType.DocumentType:
 604                        case XmlNodeType.XmlDeclaration:
 605                            break;
 606                    }
 607                }
 608                while (MoveToNext());
 609            }
 610
 611        }
 612
 613        internal struct XmlTokenEntry
 614        {
 615            internal XmlNodeType nodeType;
 616            internal string prefix;
 617            internal string localName;
 618            internal string namespaceUri;
 619
 620            public bool IsEmptyElement
 621            {
 622                get { return Value == null; }
 623                set { Value = value ? null : ""; }
 624            }
 625
 626            public string Value { get; private set; }
 627
 628            public void Set(XmlNodeType nodeType, string value)
 629            {
 630                this.nodeType = nodeType;
 631                Value = value;
 632            }
 633
 634            public void SetAttribute(string prefix, string localName, string namespaceUri, string value)
 635            {
 636                nodeType = XmlNodeType.Attribute;
 637                this.prefix = prefix;
 638                this.localName = localName;
 639                this.namespaceUri = namespaceUri;
 640                Value = value;
 641            }
 642
 643            public void SetElement(string prefix, string localName, string namespaceUri, bool isEmptyElement)
 644            {
 645                nodeType = XmlNodeType.Element;
 646                this.prefix = prefix;
 647                this.localName = localName;
 648                this.namespaceUri = namespaceUri;
 649                IsEmptyElement = isEmptyElement;
 650            }
 651        }
 652    }
 653}