VerifyIgnorableNodeType() private method

private VerifyIgnorableNodeType ( ExceptionAction action ) : void
action ExceptionAction
return void
        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);
                        }
                    }
                }
            }
        }