CopySection() private method

private CopySection ( ) : string
return string
Ejemplo n.º 1
0
        protected internal override void DeserializeElement(XmlReader reader, bool serializeCollectionKey)
        {
            string name = reader.Name;

            base.DeserializeElement(reader, serializeCollectionKey);
            if ((this.File != null) && (this.File.Length > 0))
            {
                string file;
                string source = base.ElementInformation.Source;
                if (string.IsNullOrEmpty(source))
                {
                    file = this.File;
                }
                else
                {
                    file = Path.Combine(Path.GetDirectoryName(source), this.File);
                }
                if (System.IO.File.Exists(file))
                {
                    int    lineOffset = 0;
                    string rawXml     = null;
                    using (Stream stream = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read))
                    {
                        using (XmlUtil util = new XmlUtil(stream, file, true))
                        {
                            if (util.Reader.Name != name)
                            {
                                throw new ConfigurationErrorsException(System.Configuration.SR.GetString("Config_name_value_file_section_file_invalid_root", new object[] { name }), util);
                            }
                            lineOffset = util.Reader.LineNumber;
                            rawXml     = util.CopySection();
                            while (!util.Reader.EOF)
                            {
                                if (util.Reader.NodeType != XmlNodeType.Comment)
                                {
                                    throw new ConfigurationErrorsException(System.Configuration.SR.GetString("Config_source_file_format"), util);
                                }
                                util.Reader.Read();
                            }
                        }
                    }
                    ConfigXmlReader reader2 = new ConfigXmlReader(rawXml, file, lineOffset);
                    reader2.Read();
                    if (reader2.MoveToNextAttribute())
                    {
                        throw new ConfigurationErrorsException(System.Configuration.SR.GetString("Config_base_unrecognized_attribute", new object[] { reader2.Name }), reader2);
                    }
                    reader2.MoveToElement();
                    base.DeserializeElement(reader2, serializeCollectionKey);
                }
            }
        }
 protected internal override void DeserializeElement(XmlReader reader, bool serializeCollectionKey)
 {
     string name = reader.Name;
     base.DeserializeElement(reader, serializeCollectionKey);
     if ((this.File != null) && (this.File.Length > 0))
     {
         string file;
         string source = base.ElementInformation.Source;
         if (string.IsNullOrEmpty(source))
         {
             file = this.File;
         }
         else
         {
             file = Path.Combine(Path.GetDirectoryName(source), this.File);
         }
         if (System.IO.File.Exists(file))
         {
             int lineOffset = 0;
             string rawXml = null;
             using (Stream stream = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read))
             {
                 using (XmlUtil util = new XmlUtil(stream, file, true))
                 {
                     if (util.Reader.Name != name)
                     {
                         throw new ConfigurationErrorsException(System.Configuration.SR.GetString("Config_name_value_file_section_file_invalid_root", new object[] { name }), util);
                     }
                     lineOffset = util.Reader.LineNumber;
                     rawXml = util.CopySection();
                     while (!util.Reader.EOF)
                     {
                         if (util.Reader.NodeType != XmlNodeType.Comment)
                         {
                             throw new ConfigurationErrorsException(System.Configuration.SR.GetString("Config_source_file_format"), util);
                         }
                         util.Reader.Read();
                     }
                 }
             }
             ConfigXmlReader reader2 = new ConfigXmlReader(rawXml, file, lineOffset);
             reader2.Read();
             if (reader2.MoveToNextAttribute())
             {
                 throw new ConfigurationErrorsException(System.Configuration.SR.GetString("Config_base_unrecognized_attribute", new object[] { reader2.Name }), reader2);
             }
             reader2.MoveToElement();
             base.DeserializeElement(reader2, serializeCollectionKey);
         }
     }
 }
Ejemplo n.º 3
0
        protected internal override void DeserializeElement(XmlReader reader, bool serializeCollectionKey)
        {
            string elementName = reader.Name;

            base.DeserializeElement(reader, serializeCollectionKey);
            if (!(File?.Length > 0))
            {
                return;
            }

            string sourceFileFullPath;

            // Determine file location
            string configFile = ElementInformation.Source;

            sourceFileFullPath = string.IsNullOrEmpty(configFile)
                ? File
                : Path.Combine(Path.GetDirectoryName(configFile), File);

            if (!IO.File.Exists(sourceFileFullPath))
            {
                return;
            }
            int    lineOffset;
            string rawXml;

            using (Stream sourceFileStream = new FileStream(sourceFileFullPath, FileMode.Open, FileAccess.Read, FileShare.Read))
                using (XmlUtil xmlUtil = new XmlUtil(sourceFileStream, sourceFileFullPath, true))
                {
                    if (xmlUtil.Reader.Name != elementName)
                    {
                        throw new ConfigurationErrorsException(
                                  SR.Format(SR.Config_name_value_file_section_file_invalid_root, elementName),
                                  xmlUtil);
                    }

                    lineOffset = xmlUtil.Reader.LineNumber;
                    rawXml     = xmlUtil.CopySection();

                    // Detect if there is any XML left over after the section
                    while (!xmlUtil.Reader.EOF)
                    {
                        XmlNodeType t = xmlUtil.Reader.NodeType;
                        if (t != XmlNodeType.Comment)
                        {
                            throw new ConfigurationErrorsException(SR.Config_source_file_format, xmlUtil);
                        }

                        xmlUtil.Reader.Read();
                    }
                }

            ConfigXmlReader internalReader = new ConfigXmlReader(rawXml, sourceFileFullPath, lineOffset);

            internalReader.Read();

            if (internalReader.MoveToNextAttribute())
            {
                throw new ConfigurationErrorsException(
                          SR.Format(SR.Config_base_unrecognized_attribute, internalReader.Name),
                          (XmlReader)internalReader);
            }

            internalReader.MoveToElement();

            base.DeserializeElement(internalReader, serializeCollectionKey);
        }
Ejemplo n.º 4
0
        protected internal override void DeserializeElement(XmlReader reader, bool serializeCollectionKey)
        {
            string elementName = reader.Name;

            base.DeserializeElement(reader, serializeCollectionKey);
            if (!(File?.Length > 0)) return;

            string sourceFileFullPath;

            // Determine file location
            string configFile = ElementInformation.Source;

            if (string.IsNullOrEmpty(configFile))
                sourceFileFullPath = File;
            else
            {
                string configFileDirectory = Path.GetDirectoryName(configFile);
                sourceFileFullPath = Path.Combine(configFileDirectory, File);
            }

            if (!IO.File.Exists(sourceFileFullPath)) return;
            int lineOffset;
            string rawXml;

            using (
                Stream sourceFileStream = new FileStream(sourceFileFullPath, FileMode.Open, FileAccess.Read,
                    FileShare.Read))
            {
                using (XmlUtil xmlUtil = new XmlUtil(sourceFileStream, sourceFileFullPath, true))
                {
                    if (xmlUtil.Reader.Name != elementName)
                    {
                        throw new ConfigurationErrorsException(
                            string.Format(SR.Config_name_value_file_section_file_invalid_root, elementName),
                            xmlUtil);
                    }

                    lineOffset = xmlUtil.Reader.LineNumber;
                    rawXml = xmlUtil.CopySection();

                    // Detect if there is any XML left over after the section
                    while (!xmlUtil.Reader.EOF)
                    {
                        XmlNodeType t = xmlUtil.Reader.NodeType;
                        if (t != XmlNodeType.Comment)
                        {
                            throw new ConfigurationErrorsException(SR.Config_source_file_format,
                                xmlUtil);
                        }

                        xmlUtil.Reader.Read();
                    }
                }
            }

            ConfigXmlReader internalReader = new ConfigXmlReader(rawXml, sourceFileFullPath, lineOffset);
            internalReader.Read();
            if (internalReader.MoveToNextAttribute())
            {
                throw new ConfigurationErrorsException(
                    string.Format(SR.Config_base_unrecognized_attribute, internalReader.Name),
                    (XmlReader)internalReader);
            }

            internalReader.MoveToElement();

            base.DeserializeElement(internalReader, serializeCollectionKey);
        }
        private void ScanSectionsRecursive(
                XmlUtil xmlUtil, string parentConfigKey, bool inLocation, string locationSubPath, 
                bool lockChildren, bool skipInChildApps) {

            // discard any accumulated local errors
            xmlUtil.SchemaErrors.ResetLocalErrors();

            int depth;

            // only move to child nodes when not on first level (we've already passed the first <configsections>)
            if (parentConfigKey.Length == 0 && !inLocation) {
                depth = 0;
            }
            else {
                depth = xmlUtil.Reader.Depth;
                xmlUtil.StrictReadToNextElement(ExceptionAction.NonSpecific);
            }

            while (xmlUtil.Reader.Depth == depth + 1) {

                string tagName = xmlUtil.Reader.Name;

                //
                // Check for reserved elements before looking up the factory,
                // which may have the same name if it is in error.
                //
                if (tagName == KEYWORD_CONFIGSECTIONS) {
                    // Error: duplicate <configSections> tag, or <configSections> not the first tag under <configuration>
                    xmlUtil.SchemaErrors.AddError(
                            new ConfigurationErrorsException(SR.GetString(SR.Config_client_config_too_many_configsections_elements, tagName), xmlUtil),
                            ExceptionAction.NonSpecific);

                    xmlUtil.StrictSkipToNextElement(ExceptionAction.NonSpecific);
                    continue;
                }

                if (tagName == KEYWORD_LOCATION) {
                    if (parentConfigKey.Length > 0 || inLocation) {
                        // Error: <location> section not at top level
                        xmlUtil.SchemaErrors.AddError(
                                new ConfigurationErrorsException(SR.GetString(SR.Config_location_location_not_allowed), xmlUtil),
                                ExceptionAction.Global);

                        xmlUtil.StrictSkipToNextElement(ExceptionAction.NonSpecific);
                    }
                    else {
                        // Recurse into the location section
                        ScanLocationSection(xmlUtil);
                    }

                    continue;
                }

                string configKey = CombineConfigKey(parentConfigKey, tagName);
                FactoryRecord factoryRecord = FindFactoryRecord(configKey, true);


                if (factoryRecord == null) {
                    // 
                    //
                    if (!ClassFlags[ClassIgnoreLocalErrors]) {
                        xmlUtil.SchemaErrors.AddError(
                                new ConfigurationErrorsException(SR.GetString(SR.Config_unrecognized_configuration_section, configKey), xmlUtil),
                                ExceptionAction.Local);
                    }

                    VerifySectionName(tagName, xmlUtil, ExceptionAction.Local, false);

                    factoryRecord = new FactoryRecord(
                            configKey, 
                            parentConfigKey,
                            tagName,
                            typeof(DefaultSection).AssemblyQualifiedName,
                            true,   // allowLocation
                            ConfigurationAllowDefinition.Everywhere,
                            ConfigurationAllowExeDefinition.MachineToRoamingUser,
                            true,   // restartOnExternalChanges
                            true,   // requirePermission
                            _flags[IsTrusted],
                            true,   // isUndeclared
                            null,
                            -1);

                    // Add any errors we may have encountered to the factory record,
                    // so that child config that also refer to this unrecognized section
                    // get the error.
                    factoryRecord.AddErrors(xmlUtil.SchemaErrors.RetrieveAndResetLocalErrors(true));

                    // Add the factory to the list of factories
                    EnsureFactories()[configKey] = factoryRecord;
                }

                if (factoryRecord.IsGroup) {
                    //
                    // Section Group
                    //
                    if (factoryRecord.HasErrors) {
                        xmlUtil.StrictSkipToNextElement(ExceptionAction.NonSpecific);
                    }
                    else {
                        if (xmlUtil.Reader.AttributeCount > 0) {
                            while (xmlUtil.Reader.MoveToNextAttribute()) {
                                if (IsReservedAttributeName(xmlUtil.Reader.Name)) {
                                    xmlUtil.AddErrorReservedAttribute(ExceptionAction.NonSpecific);
                                }
                            }

                            xmlUtil.Reader.MoveToElement(); // if on an attribute move back to the element
                        }

                        // Recurse into group definition
                        ScanSectionsRecursive(xmlUtil, configKey, inLocation, locationSubPath, lockChildren, skipInChildApps);
                    }
                }
                else {
                    //
                    // Section
                    //
                    configKey = factoryRecord.ConfigKey;
                    string fileName = xmlUtil.Filename;
                    int lineNumber = xmlUtil.LineNumber;
                    string rawXml = null;
                    string configSource = null;
                    string configSourceStreamName = null;
                    object configSourceStreamVersion = null;
                    string protectionProviderName = null;
                    bool isSectionLocked = false;
                    bool positionedAtNextElement = false;
                    bool isFileInput = (locationSubPath == null);

                    if (!factoryRecord.HasErrors) {
                        // We have a valid factoryRecord for a section
                        if (inLocation && factoryRecord.AllowLocation == false) {
                            xmlUtil.SchemaErrors.AddError(
                                    new ConfigurationErrorsException(SR.GetString(SR.Config_section_cannot_be_used_in_location), xmlUtil), 
                                    ExceptionAction.Local);
                        }
    
                        // Verify correctness for file inputs.
                        if (isFileInput) {
                            // Verify that the section is unique
                            SectionRecord sectionRecord = GetSectionRecord(configKey, true);
                            if (sectionRecord != null && sectionRecord.HasFileInput) {
                                xmlUtil.SchemaErrors.AddError(
                                    new ConfigurationErrorsException(SR.GetString(SR.Config_sections_must_be_unique), xmlUtil),
                                    ExceptionAction.Local);
                            }

                            // Verify that the definition is allowed.
                            try {
                                VerifyDefinitionAllowed(factoryRecord, _configPath, xmlUtil);
                            }
                            catch (ConfigurationException ce) {
                                xmlUtil.SchemaErrors.AddError(ce, ExceptionAction.Local);
                            }
                        }

                        // Verify that section is unlocked, both for file and location inputs.
                        try {
                            VerifySectionUnlocked(configKey, xmlUtil);
                        }
                        catch (ConfigurationException ce) {
                            isSectionLocked = true;
                            xmlUtil.SchemaErrors.AddError(ce, ExceptionAction.Local);
                        }

                        // check for configSource or protectionProvider
                        if (xmlUtil.Reader.AttributeCount >= 1) {
                            // First do all the attributes reading without advancing the reader.
                            
                            string configSourceAttribute = xmlUtil.Reader.GetAttribute(KEYWORD_CONFIGSOURCE);
                            if (configSourceAttribute != null) {
                                try {
                                    configSource = NormalizeConfigSource(configSourceAttribute, xmlUtil);
                                }
                                catch (ConfigurationException ce) {
                                    xmlUtil.SchemaErrors.AddError(ce, ExceptionAction.Local);
                                }

                                if (xmlUtil.Reader.AttributeCount != 1) {
                                    // Error: elements with configSource should not have other attributes
                                    xmlUtil.SchemaErrors.AddError(
                                            new ConfigurationErrorsException(SR.GetString(SR.Config_source_syntax_error), xmlUtil), 
                                            ExceptionAction.Local);
                                }
                            }

                            string protectionProviderAttribute = xmlUtil.Reader.GetAttribute(KEYWORD_PROTECTION_PROVIDER);
                            if (protectionProviderAttribute != null) {
                                try {
                                    protectionProviderName = ValidateProtectionProviderAttribute(protectionProviderAttribute, xmlUtil);
                                }
                                catch (ConfigurationException ce) {
                                    xmlUtil.SchemaErrors.AddError(ce, ExceptionAction.Local);
                                }
                                
                                if (xmlUtil.Reader.AttributeCount != 1) {
                                    // Error: elements with protectionProvider should not have other attributes
                                    xmlUtil.SchemaErrors.AddError(
                                            new ConfigurationErrorsException(SR.GetString(SR.Protection_provider_syntax_error), xmlUtil), 
                                            ExceptionAction.Local);
                                }
                            }

                            // The 2nd part of the configSource check requires advancing the reader.
                            // Please note that this part should be done only AFTER all other attributes
                            // checking are done.
                            if (configSourceAttribute != null) {
                                if (!xmlUtil.Reader.IsEmptyElement) {
                                    while (xmlUtil.Reader.Read()) {
                                        XmlNodeType t = xmlUtil.Reader.NodeType;
                                        if (t == XmlNodeType.EndElement)
                                            break;

                                        if (t != XmlNodeType.Comment) {
                                            // Error: elements with configSource should not subelements other than comments
                                            xmlUtil.SchemaErrors.AddError(
                                                    new ConfigurationErrorsException(SR.GetString(SR.Config_source_syntax_error), xmlUtil),
                                                    ExceptionAction.Local);

                                            if (t == XmlNodeType.Element) {
                                                xmlUtil.StrictSkipToOurParentsEndElement(ExceptionAction.NonSpecific);
                                            }
                                            else {
                                                xmlUtil.StrictSkipToNextElement(ExceptionAction.NonSpecific);
                                            }

                                            positionedAtNextElement = true;
                                            break;
                                        }
                                    }
                                }
                            }
                        }

                        if (configSource != null) {
                            try {
                                try {
                                    configSourceStreamName = Host.GetStreamNameForConfigSource(ConfigStreamInfo.StreamName, configSource);
                                }
                                catch (Exception e) {
                                    throw ExceptionUtil.WrapAsConfigException(SR.GetString(SR.Config_source_invalid), e, xmlUtil);
                                }
                                ValidateUniqueConfigSource(configKey, configSourceStreamName, configSource, xmlUtil);
                                configSourceStreamVersion = MonitorStream(configKey, configSource, configSourceStreamName);
                            }
                            catch (ConfigurationException ex) {
                                xmlUtil.SchemaErrors.AddError(ex, ExceptionAction.Local);
                            }
                        }

                        //
                        // prefetch the raw xml
                        //
                        if (!xmlUtil.SchemaErrors.HasLocalErrors) {
                            if (configSource == null && ShouldPrefetchRawXml(factoryRecord)) {
                                Debug.Assert(!positionedAtNextElement, "!positionedAtNextElement");

                                rawXml = xmlUtil.CopySection();
                                if (xmlUtil.Reader.NodeType != XmlNodeType.Element) {
                                    xmlUtil.VerifyIgnorableNodeType(ExceptionAction.NonSpecific);
                                    xmlUtil.StrictReadToNextElement(ExceptionAction.NonSpecific);
                                }

                                positionedAtNextElement = true;
                            }
                        }
                    }

                    // Get the list of errors before advancing the reader
                    List<ConfigurationException> localErrors = xmlUtil.SchemaErrors.RetrieveAndResetLocalErrors(isFileInput);

                    // advance the reader to the next element
                    if (!positionedAtNextElement) {
                        xmlUtil.StrictSkipToNextElement(ExceptionAction.NonSpecific);                            
                    }

                    // Add the input either to:
                    // 1. The file input at the current config level, or
                    // 2. LocationSections, where it will be used in sub paths
                    bool addInput = true;

                    if (isFileInput) {
                        // If isFileInput==true, Input added will be used against this config level.
                        // Need to check if we need to skip it due to inheritInChildApplications.
                        
                        if (ShouldSkipDueToInheritInChildApplications(skipInChildApps)) {
                            addInput = false;
                        }
                    }
                    else {
                        if (!_flags[SupportsLocation]) {
                            // Skip if we have a location input but we don't support location tag.
                            addInput = false;
                        }
                    }
                    
                    if (addInput) {

                        string targetConfigPath = (locationSubPath == null) ? _configPath : null;

                        SectionXmlInfo sectionXmlInfo = new SectionXmlInfo(
                                configKey, _configPath, targetConfigPath, locationSubPath,
                                fileName, lineNumber, ConfigStreamInfo.StreamVersion, rawXml, 
                                configSource, configSourceStreamName, configSourceStreamVersion,
                                protectionProviderName, lockChildren, skipInChildApps);

                        if (locationSubPath == null) {
                            //
                            // Add this file input to the section record
                            //

                            // We've already checked for locked above, so use skip the second check
                            // and set the locked bit.
                            SectionRecord sectionRecord = EnsureSectionRecordUnsafe(configKey, true);

                            Debug.Assert(!sectionRecord.Locked || isSectionLocked,
                                        "!sectionRecord.Locked || isSectionLocked");

                            if (isSectionLocked) {
                                sectionRecord.Locked = true;
                            }
                            
                            SectionInput fileInput = new SectionInput(sectionXmlInfo, localErrors);
                            sectionRecord.AddFileInput(fileInput);
                        }
                        else {
                            //
                            // Add this location input to this list of location sections
                            //
                            LocationSectionRecord locationSectionRecord = new LocationSectionRecord(sectionXmlInfo, localErrors);
                            EnsureLocationSections().Add(locationSectionRecord);
                        }
                    }
                }
            }
        }
        private ConfigXmlReader LoadConfigSource(string name, SectionXmlInfo sectionXmlInfo) {
            string configSourceStreamName = sectionXmlInfo.ConfigSourceStreamName;
            
            try {
                using (Impersonate()) {
                    using (Stream stream = Host.OpenStreamForRead(configSourceStreamName)) {
                        if (stream == null) {
                            throw new ConfigurationErrorsException(
                                    SR.GetString(SR.Config_cannot_open_config_source, sectionXmlInfo.ConfigSource),
                                    sectionXmlInfo);
                        }

                        using (XmlUtil xmlUtil = new XmlUtil(stream, configSourceStreamName, true)) {
                            if (xmlUtil.Reader.Name != name) {
                                throw new ConfigurationErrorsException(SR.GetString(SR.Config_source_file_format), xmlUtil);
                            }

                            // Check for protectionProvider
                            string protectionProviderAttribute = xmlUtil.Reader.GetAttribute(KEYWORD_PROTECTION_PROVIDER);
                            if (protectionProviderAttribute != null) {
                                if (xmlUtil.Reader.AttributeCount != 1) {
                                    // Error: elements with protectionProvider should not have other attributes
                                    throw new ConfigurationErrorsException(SR.GetString(SR.Protection_provider_syntax_error), xmlUtil);
                                }
        
                                sectionXmlInfo.ProtectionProviderName = ValidateProtectionProviderAttribute(protectionProviderAttribute, xmlUtil);
                            }
                            
                            int lineOffset = xmlUtil.Reader.LineNumber;
                            string rawXml = xmlUtil.CopySection();

                            // Detect if there is any XML left over after the section
                            while (!xmlUtil.Reader.EOF) {
                                XmlNodeType t = xmlUtil.Reader.NodeType;
                                if (t != XmlNodeType.Comment) {
                                    throw new ConfigurationErrorsException(SR.GetString(SR.Config_source_file_format), xmlUtil);
                                }

                                xmlUtil.Reader.Read();
                            }

                            ConfigXmlReader section = new ConfigXmlReader(rawXml, configSourceStreamName, lineOffset);
                            return section;
                        }
                    }
                }
            }
            catch {
                // Don't allow frames up the stack to run exception filters while impersonated.
                throw;
            }
        }
        private ConfigXmlReader FindSectionRecursive(string [] keys, int iKey, XmlUtil xmlUtil, ref int lineNumber) {
            string name = keys[iKey];
            ConfigXmlReader section = null;

            int depth = xmlUtil.Reader.Depth;
            xmlUtil.ReadToNextElement();

            while (xmlUtil.Reader.Depth > depth) {
                if (xmlUtil.Reader.Name == name) {
                    if (iKey < keys.Length - 1) {
                        //
                        // We haven't reached the section yet, so keep evaluating
                        //
                        section = FindSectionRecursive(keys, iKey + 1, xmlUtil, ref lineNumber);
                        if (section != null) {
                            break;
                        }

                        continue; // don't call "Skip" -- FindSectionRecursive forwards the reader
                    }
                    else {
                        //
                        // We've reached the section. Load the section into a string.
                        //
                        string filename = ((IConfigErrorInfo)xmlUtil).Filename;
                        int lineOffset = xmlUtil.Reader.LineNumber;
                        string rawXml = xmlUtil.CopySection();
                        section = new ConfigXmlReader(rawXml, filename, lineOffset);
                        break;
                    }
                }
                else if (iKey == 0 && xmlUtil.Reader.Name == KEYWORD_LOCATION) {
                    string locationSubPath = xmlUtil.Reader.GetAttribute(KEYWORD_LOCATION_PATH);
                    bool isValid = false;
                    try {
                        locationSubPath = NormalizeLocationSubPath(locationSubPath, xmlUtil);
                        isValid = true;
                    }
                    catch (ConfigurationException ce) {
                        xmlUtil.SchemaErrors.AddError(ce, ExceptionAction.NonSpecific);
                    }

                    if (isValid && locationSubPath == null) {
                        //
                        // Location sections that don't have a subpath are treated
                        // as ordinary sections.
                        //
                        section = FindSectionRecursive(keys, iKey, xmlUtil, ref lineNumber);
                        if (section != null) {
                            break;
                        }

                        continue; // don't call "Skip" -- FindSectionRecursive forwards the reader
                    }
                }

                xmlUtil.SkipToNextElement();
            }

            return section;
        }