// Copy configuration sections from the original configuration file.
        private bool CopyConfigDefinitionsRecursive(
                ConfigDefinitionUpdates configDefinitionUpdates, XmlUtil xmlUtil, XmlUtilWriter utilWriter,
                bool locationPathApplies, LocationUpdates locationUpdates, SectionUpdates sectionUpdates,
                bool addNewSections, string group, int parentLinePosition, int parentIndent) {

            bool wroteASection = false;
            XmlTextReader reader = xmlUtil.Reader;
            int linePosition;
            int indent;
            int startingLinePosition;

            indent = UpdateIndent(parentIndent, xmlUtil, utilWriter, parentLinePosition);

            if (reader.NodeType == XmlNodeType.Element) {
                linePosition = xmlUtil.TrueLinePosition;
                startingLinePosition = linePosition;
            }
            else if (reader.NodeType == XmlNodeType.EndElement) {
                linePosition = parentLinePosition + indent;
                if (utilWriter.IsLastLineBlank) {
                    startingLinePosition = xmlUtil.TrueLinePosition;
                }
                else {
                    startingLinePosition = parentLinePosition;
                }
            }
            else {
                linePosition = parentLinePosition + indent;
                startingLinePosition = 0;
            }

            //
            // Write any new sections that apply to this group
            //
            if (sectionUpdates != null && addNewSections) {
                // Remove newness, so we won't write again
                sectionUpdates.IsNew = false;

                Debug.Assert(locationPathApplies, "locationPathApplies");
                string[] movedSectionNames = sectionUpdates.GetMovedSectionNames();
                if (movedSectionNames != null) {
                    if (!utilWriter.IsLastLineBlank) {
                        utilWriter.AppendNewLine();
                    }

                    utilWriter.AppendSpacesToLinePosition(linePosition);
                    bool skipFirstIndent = true;

                    foreach (string configKey in movedSectionNames) {
                        DefinitionUpdate update = sectionUpdates.GetDefinitionUpdate(configKey);

                        WriteSectionUpdate(utilWriter, update, linePosition, indent, skipFirstIndent);
                        skipFirstIndent = false;
                        utilWriter.AppendNewLine();
                        wroteASection = true;
                    }

                    // Restore the whitespace we used for the first element, which is either a start or an end element.
                    utilWriter.AppendSpacesToLinePosition(startingLinePosition);
                }
            }

            if (reader.NodeType == XmlNodeType.Element) {
                //
                // For each element at this depth, either:
                // - Write the element verbatim and recurse due to a location section or group hierarchy element.
                // - Write the element verbatim because it is unchanged, or because the current location does
                //   not apply.
                // - Write the updated XML for the section.
                // - Skip it because the section has been removed.
                //
                int depth = reader.Depth;
                while (reader.Depth == depth) {
                    bool                recurse = false;
                    DefinitionUpdate    update = null;
                    bool                elementLocationPathApplies = locationPathApplies;
                    LocationUpdates     recurseLocationUpdates = locationUpdates;
                    SectionUpdates      recurseSectionUpdates = sectionUpdates;
                    bool                recurseAddNewSections = addNewSections;
                    string              recurseGroup = group;
                    bool                removedSectionOrGroup = false;

                    // update the lineposition and indent for each element
                    indent = UpdateIndent(indent, xmlUtil, utilWriter, parentLinePosition);
                    linePosition = xmlUtil.TrueLinePosition;

                    string elementName = reader.Name;
                    if (elementName == KEYWORD_LOCATION) {
                        string locationSubPathAttribute = reader.GetAttribute(KEYWORD_LOCATION_PATH);
                        locationSubPathAttribute = NormalizeLocationSubPath(locationSubPathAttribute, xmlUtil);
                        elementLocationPathApplies = false;
                        OverrideModeSetting overrideMode = OverrideModeSetting.LocationDefault;
                        bool inheritInChildApps = true;

                        if (IsLocationConfig) {
                            // For location config we will compare config paths instead of location strings
                            // so that we dont end up comparing "1" with "Default Web Site" and ending up with the wrong result
                            if (locationSubPathAttribute == null) {
                                elementLocationPathApplies = false;
                            }
                            else {
                                elementLocationPathApplies = StringUtil.EqualsIgnoreCase(ConfigPath, Host.GetConfigPathFromLocationSubPath(Parent.ConfigPath, locationSubPathAttribute));
                            }
                        }
                        else {
                            Debug.Assert(LocationSubPath == null);

                            // This is the same as doing StringUtil.EqualsIgnoreCase(_locationSubPath, locationSubPathAttribute)
                            // but remember the first one is null. Also remember locationSubPathAttribute is already normalized
                            elementLocationPathApplies = (locationSubPathAttribute == null);
                        }

                        if (elementLocationPathApplies) {
                            // Retrieve overrideMode and InheritInChildApps

                            string allowOverrideAttribute = reader.GetAttribute(KEYWORD_LOCATION_ALLOWOVERRIDE);
                            if (allowOverrideAttribute != null) {
                                overrideMode = OverrideModeSetting.CreateFromXmlReadValue(Boolean.Parse(allowOverrideAttribute));
                            }

                            string overrideModeAttribute = reader.GetAttribute(KEYWORD_LOCATION_OVERRIDEMODE);
                            if (overrideModeAttribute != null) {
                                overrideMode = OverrideModeSetting.CreateFromXmlReadValue(OverrideModeSetting.ParseOverrideModeXmlValue(overrideModeAttribute, null));

                                Debug.Assert(allowOverrideAttribute == null, "allowOverride and overrideMode both detected in a <location> tag");
                            }

                            string inheritInChildAppsAttribute = reader.GetAttribute(KEYWORD_LOCATION_INHERITINCHILDAPPLICATIONS);
                            if (inheritInChildAppsAttribute != null) {
                                inheritInChildApps = Boolean.Parse(inheritInChildAppsAttribute);
                            }

                            // Flag that we already have one of these locations
                            configDefinitionUpdates.FlagLocationWritten();
                        }

                        if (reader.IsEmptyElement) {
                            if (elementLocationPathApplies &&
                                 (configDefinitionUpdates.FindLocationUpdates(overrideMode,
                                                                              inheritInChildApps) != null)) {
                                // If we are going to make updates here, then
                                // delete the one that is here (so we can update later)
                                elementLocationPathApplies = true;
                            }
                            else {
                                // If not lets leave it
                                elementLocationPathApplies = false;
                            }
                        }
                        else {
                            // recurse if this location applies to us
                            if (elementLocationPathApplies) {
                                if (configDefinitionUpdates != null) {
                                    recurseLocationUpdates = configDefinitionUpdates.FindLocationUpdates(overrideMode, inheritInChildApps);
                                    if (recurseLocationUpdates != null) {
                                        recurse = true;
                                        recurseSectionUpdates = recurseLocationUpdates.SectionUpdates;

                                        // If this is <location path=".">, we don't want to add moved sections
                                        // to it.
                                        if (_locationSubPath == null && recurseLocationUpdates.IsDefault) {
                                            recurseAddNewSections = false;
                                        }
                                    }
                                }
                            }
                            else {
                                // recurse if necessary to remove items in _removedSections and _removedGroups
                                if (HasRemovedSectionsOrGroups && !IsLocationConfig && Host.SupportsLocation) {
                                    recurse = true;
                                    recurseLocationUpdates = null;
                                    recurseSectionUpdates = null;
                                    recurseAddNewSections = false;
                                }
                            }
                        }
                    }
                    else {
                        string configKey = CombineConfigKey(group, elementName);
                        FactoryRecord factoryRecord = FindFactoryRecord(configKey, false);
                        if (factoryRecord == null) {
                            // The factory was deleted, so regardless of whether this is a
                            // section or sectionGroup, it can be skipped.
                            if (!elementLocationPathApplies && !IsLocationConfig) {
                                removedSectionOrGroup = true;
                            }
                        }
                        else if (factoryRecord.IsGroup) {
                            if (reader.IsEmptyElement) {
                                if (!elementLocationPathApplies && !IsLocationConfig) {
                                    removedSectionOrGroup = true;
                                }
                            }
                            else {
                                // if the location path applies, recurse if there are updates
                                if (sectionUpdates != null) {
                                    SectionUpdates sectionUpdatesChild = sectionUpdates.GetSectionUpdatesForGroup(elementName);
                                    if (sectionUpdatesChild != null) {
                                        recurse = true;
                                        recurseGroup = configKey;
                                        recurseSectionUpdates = sectionUpdatesChild;
                                    }
                                }
                                else if (!elementLocationPathApplies && !IsLocationConfig) {
                                    if (_removedSectionGroups != null && _removedSectionGroups.Contains(configKey)) {
                                        removedSectionOrGroup = true;
                                    }
                                    else {
                                        recurse = true;
                                        recurseGroup = configKey;
                                        recurseLocationUpdates = null;
                                        recurseSectionUpdates = null;
                                        recurseAddNewSections = false;
                                    }
                                }
                            }
                        }
                        else {
                            // it is a section - get the update
                            if (sectionUpdates != null) {
                                update = sectionUpdates.GetDefinitionUpdate(configKey);
                            }
                            else if (!elementLocationPathApplies && !IsLocationConfig) {
                                if (_removedSections != null && _removedSections.Contains(configKey)) {
                                    removedSectionOrGroup = true;
                                }
                            }
                        }
                    }

                    if (recurse) {
#if DBG
                        string startElementName = reader.Name;
#endif

                        // flush, and get length of underlying stream
                        object checkpoint = utilWriter.CreateStreamCheckpoint();

                        // Copy this element node and up to the first subelement
                        xmlUtil.CopyXmlNode(utilWriter);
                        xmlUtil.CopyReaderToNextElement(utilWriter, true);

                        // Recurse
                        bool recurseWroteASection = CopyConfigDefinitionsRecursive(
                                configDefinitionUpdates, xmlUtil, utilWriter, elementLocationPathApplies, recurseLocationUpdates, recurseSectionUpdates,
                                recurseAddNewSections, recurseGroup, linePosition, indent);

                        // Copy the end element
                        xmlUtil.CopyXmlNode(utilWriter);

                        if (recurseWroteASection) {
                            wroteASection = true;
                        }
                        else {
                            // back out the change
                            utilWriter.RestoreStreamCheckpoint(checkpoint);
                        }

                        // Copy up to the next element, or exit this level.
                        xmlUtil.CopyReaderToNextElement(utilWriter, true);
                    }
                    else {
                        bool skip;
                        if (update == null) {
                            // remove the section from the file if we're in the correct location,
                            // or if the section or group should be removed from all locations
                            skip = elementLocationPathApplies || removedSectionOrGroup;
                        }
                        else {
                            // replace the section if the xml for it has been updated
                            // if it is a configSource, don't write it unless the configSource parameters have changed
                            skip = false;
                            if (update.UpdatedXml != null) {
                                ConfigurationSection configSection = (ConfigurationSection) update.SectionRecord.Result;
                                if (    String.IsNullOrEmpty(configSection.SectionInformation.ConfigSource) ||
                                        configSection.SectionInformation.ConfigSourceModified) {
                                    skip = true;
                                    WriteSectionUpdate(utilWriter, update, linePosition, indent, true);
                                    wroteASection = true;
                                }
                            }
                        }

                        if (skip) {
                            //
                            // Skip over the existing element, then
                            // copy up to the next element, or exit this level.
                            //
                            xmlUtil.SkipAndCopyReaderToNextElement(utilWriter, true);
                        }
                        else {
                            // Copy this entire contents of this element and then to the next element, or exit this level.
                            xmlUtil.CopyOuterXmlToNextElement(utilWriter, true);
                            wroteASection = true;
                        }
                    }
                }
            }

            //
            // Write new section groups
            //
            if (sectionUpdates != null && addNewSections && sectionUpdates.HasNewSectionGroups()) {
                // Add whitespace to align us with the other elements in this group
                linePosition = parentLinePosition + indent;
                if (reader.NodeType == XmlNodeType.EndElement) {
                    if (utilWriter.IsLastLineBlank) {
                        startingLinePosition = xmlUtil.TrueLinePosition;
                    }
                    else {
                        startingLinePosition = parentLinePosition;
                    }
                }
                else {
                    startingLinePosition = 0;
                }

                utilWriter.AppendSpacesToLinePosition(linePosition);

                bool wroteNewSection = WriteNewConfigDefinitionsRecursive(utilWriter, sectionUpdates, linePosition, indent, true);
                if (wroteNewSection) {
                    wroteASection = true;
                }

                // Restore the whitespace of the end element
                utilWriter.AppendSpacesToLinePosition(startingLinePosition);
            }

            return wroteASection;
        }
        private void WriteNewConfigDefinitions(ConfigDefinitionUpdates configDefinitionUpdates, XmlUtilWriter utilWriter, int linePosition, int indent) {
            if (configDefinitionUpdates == null)
                return;

            foreach (LocationUpdates locationUpdates in configDefinitionUpdates.LocationUpdatesList) {
                SectionUpdates sectionUpdates = locationUpdates.SectionUpdates;
                if (sectionUpdates.IsEmpty || !sectionUpdates.IsNew)
                    continue;

                configDefinitionUpdates.FlagLocationWritten();
                bool writeLocationTag = _locationSubPath != null || !locationUpdates.IsDefault;
                int recurseLinePosition = linePosition;

                utilWriter.AppendSpacesToLinePosition(linePosition);

                if (writeLocationTag) {
                    // write the <location> start tag
                    if (_locationSubPath == null) {
                        utilWriter.Write(String.Format(CultureInfo.InvariantCulture, FORMAT_LOCATION_NOPATH, locationUpdates.OverrideMode.LocationTagXmlString, BoolToString(locationUpdates.InheritInChildApps)));
                    }
                    else {
                        utilWriter.Write(String.Format(CultureInfo.InvariantCulture, FORMAT_LOCATION_PATH, locationUpdates.OverrideMode.LocationTagXmlString, BoolToString(locationUpdates.InheritInChildApps), _locationSubPath));
                    }

                    recurseLinePosition += indent;
                    utilWriter.AppendSpacesToLinePosition(recurseLinePosition);
                }

                // Invoke the recursive write.
                WriteNewConfigDefinitionsRecursive(utilWriter, locationUpdates.SectionUpdates, recurseLinePosition, indent, true);

                if (writeLocationTag) {
                    // Write the location end tag
                    utilWriter.AppendSpacesToLinePosition(linePosition);
                    utilWriter.Write(FORMAT_LOCATION_ENDELEMENT);
                    utilWriter.AppendNewLine();
                }
            }

            if (configDefinitionUpdates.RequireLocation) {
                Debug.Assert(IsLocationConfig, "IsLocationConfig");

                // If we still require this to be written, then we must write it out now
                configDefinitionUpdates.FlagLocationWritten();

                utilWriter.AppendSpacesToLinePosition(linePosition);

                utilWriter.Write(String.Format(CultureInfo.InvariantCulture, FORMAT_LOCATION_PATH, OverrideModeSetting.LocationDefault.LocationTagXmlString, KEYWORD_TRUE, _locationSubPath));
                utilWriter.AppendSpacesToLinePosition(linePosition);
                utilWriter.Write(FORMAT_LOCATION_ENDELEMENT);
                utilWriter.AppendNewLine();
            }
        }
        // Copy a config file, replacing sections with updates.
        private void CopyConfig(SectionUpdates declarationUpdates, ConfigDefinitionUpdates definitionUpdates,
                byte[] buffer, string filename, NamespaceChange namespaceChange, XmlUtilWriter utilWriter) {

            CheckPreamble(ConfigStreamInfo.StreamEncoding.GetPreamble(), utilWriter, buffer);

            using (Stream stream = new MemoryStream(buffer)) {
                using (XmlUtil xmlUtil = new XmlUtil(stream, filename, false)) {
                    // copy up to the <configuration> node
                    XmlTextReader reader = xmlUtil.Reader;
                    reader.WhitespaceHandling = WhitespaceHandling.All;
                    reader.Read();
                    xmlUtil.CopyReaderToNextElement(utilWriter, false);

                    Debug.Assert(reader.NodeType == XmlNodeType.Element && reader.Name == KEYWORD_CONFIGURATION,
                                 "reader.NodeType == XmlNodeType.Element && reader.Name == KEYWORD_CONFIGURATION");

                    int indent = DEFAULT_INDENT;
                    int configurationElementLinePosition = xmlUtil.TrueLinePosition;
                    bool isEmptyConfigurationElement = reader.IsEmptyElement;

                    // copy <configuration> node
                    // if the node is an empty element, we may need to open it.
                    string configurationStartElement;
                    if (namespaceChange == NamespaceChange.Add) {
                        configurationStartElement = string.Format(
                            CultureInfo.InvariantCulture, FORMAT_CONFIGURATION_NAMESPACE, KEYWORD_CONFIGURATION_NAMESPACE);
                    }
                    else if (namespaceChange == NamespaceChange.Remove) {
                        configurationStartElement = FORMAT_CONFIGURATION;
                    }
                    else {
                        configurationStartElement = null;
                    }

                    bool needsChildren = (declarationUpdates != null || definitionUpdates  != null);
                    string configurationEndElement = xmlUtil.UpdateStartElement(utilWriter, configurationStartElement, needsChildren, configurationElementLinePosition, indent);

                    bool foundConfigSectionsElement = false;
                    if (!isEmptyConfigurationElement) {
                        // copy up to the first element under <configuration>
                        xmlUtil.CopyReaderToNextElement(utilWriter, true);

                        // updateIndent
                        indent = UpdateIndent(indent, xmlUtil, utilWriter, configurationElementLinePosition);

                        if (reader.NodeType == XmlNodeType.Element && reader.Name == KEYWORD_CONFIGSECTIONS) {
                            foundConfigSectionsElement = true;

                            int configSectionsElementLinePosition = xmlUtil.TrueLinePosition;
                            bool isEmptyConfigSectionsElement = reader.IsEmptyElement;

                            // if no updates, copy the entire <configSections> element
                            if (declarationUpdates == null) {
                                xmlUtil.CopyOuterXmlToNextElement(utilWriter, true);
                            }
                            else {
                                // copy <configSections>, and open it if it is an empty element
                                string configSectionsEndElement = xmlUtil.UpdateStartElement(
                                    utilWriter, null, true, configSectionsElementLinePosition, indent);

                                if (!isEmptyConfigSectionsElement) {
                                    // copy to next element under <configSections>, or up to closing </configSections>
                                    xmlUtil.CopyReaderToNextElement(utilWriter, true);

                                    // copy config declarations
                                    CopyConfigDeclarationsRecursive(declarationUpdates, xmlUtil, utilWriter, string.Empty,
                                            configSectionsElementLinePosition, indent);

                                    Debug.Assert(reader.NodeType == XmlNodeType.EndElement && reader.Name == KEYWORD_CONFIGSECTIONS,
                                                 "reader.NodeType == XmlNodeType.EndElement && reader.Name == \"KEYWORD_CONFIGSECTIONS\"");
                                }

                                // write declarations not written by above copy
                                if (declarationUpdates.HasUnretrievedSections()) {

                                    // determine the line position of the end element
                                    int endElementLinePosition = 0;
                                    if (configSectionsEndElement == null) {
                                        endElementLinePosition = xmlUtil.TrueLinePosition;
                                    }

                                    // indent a new line
                                    if (!utilWriter.IsLastLineBlank) {
                                        utilWriter.AppendNewLine();
                                    }

                                    WriteUnwrittenConfigDeclarations(declarationUpdates, utilWriter, configSectionsElementLinePosition + indent, indent, false);

                                    // restore spaces to end element
                                    if (configSectionsEndElement == null) {
                                        utilWriter.AppendSpacesToLinePosition(endElementLinePosition);
                                    }
                                }

                                // Copy the </configSections> element
                                if (configSectionsEndElement == null) {
                                    xmlUtil.CopyXmlNode(utilWriter);
                                }
                                else {
                                    // note that configSectionsEndElement already contains the proper indenting
                                    utilWriter.Write(configSectionsEndElement);
                                }

                                // copy up to the next element under <configuration>, or up to closing </configSections>
                                xmlUtil.CopyReaderToNextElement(utilWriter, true);
                            }
                        }
                    }

                    // Write new declarations
                    if (!foundConfigSectionsElement && declarationUpdates != null) {
                        bool skipFirstIndent = reader.Depth > 0 && reader.NodeType == XmlNodeType.Element;
                        int newConfigSectionsLinePosition;
                        if (skipFirstIndent) {
                            newConfigSectionsLinePosition = xmlUtil.TrueLinePosition;
                        }
                        else {
                            newConfigSectionsLinePosition = configurationElementLinePosition + indent;
                        }

                        WriteNewConfigDeclarations(declarationUpdates, utilWriter, newConfigSectionsLinePosition, indent, skipFirstIndent);
                    }

                    if (definitionUpdates != null) {
                        //
                        // Copy sections recursively. In the file we copy we start out at
                        //     location path="." allowOverride="true" inheritInChildApps="true"
                        //
                        bool locationPathApplies = false;
                        LocationUpdates locationUpdates = null;
                        SectionUpdates sectionUpdates = null;
                        if (!IsLocationConfig) {
                            locationPathApplies = true;
                            locationUpdates = definitionUpdates.FindLocationUpdates(OverrideModeSetting.LocationDefault, true);
                            if (locationUpdates != null) {
                                sectionUpdates = locationUpdates.SectionUpdates;
                            }
                        }

                        CopyConfigDefinitionsRecursive(definitionUpdates, xmlUtil, utilWriter, locationPathApplies,
                            locationUpdates, sectionUpdates, true, string.Empty, configurationElementLinePosition, indent);

                        // Write new config sections from new groups.
                        WriteNewConfigDefinitions(definitionUpdates, utilWriter, configurationElementLinePosition + indent, indent);

#if DBG
                        Debug.Assert(configurationEndElement != null || (reader.NodeType == XmlNodeType.EndElement && reader.Name == KEYWORD_CONFIGURATION),
                                     "configurationEndElement != null || (reader.NodeType == XmlNodeType.EndElement && reader.Name == KEYWORD_CONFIGURATION)");
#endif



#if DBG
                        {
                            foreach (LocationUpdates l in definitionUpdates.LocationUpdatesList) {
                                Debug.Assert(!l.SectionUpdates.HasUnretrievedSections(), "!l.SectionUpdates.HasUnretrievedSections()");
                            }
                        }
#endif
                    }


                    if (configurationEndElement != null) {
                        // If we have to add closing config tag, then do it now
                        // before copying extra whitespace/comments
                        if (!utilWriter.IsLastLineBlank) {
                            utilWriter.AppendNewLine();
                        }

                        utilWriter.Write(configurationEndElement);
                    }

                    //
                    // Copy the remainder of the file, the closing </configuration> node plus any whitespace
                    // and comments
                    //
                    while (xmlUtil.CopyXmlNode(utilWriter)) {
                    }
                }
            }
        }
        // Gather all the updates to the configuration section definitions.
        private void GetConfigDefinitionUpdates(
                bool requireUpdates, ConfigurationSaveMode saveMode, bool forceSaveAll,
                out ConfigDefinitionUpdates definitionUpdates, out ArrayList configSourceUpdates) {

            definitionUpdates = new ConfigDefinitionUpdates();
            configSourceUpdates = null;
            bool hasChanged = HasRemovedSections;

            // Loop through all the section records.
            if (_sectionRecords != null) {
                InitProtectedConfigurationSection(); // Make sure we have the initialized the protected config section, otherwise the foreach loop may ---- up
                foreach (DictionaryEntry de in _sectionRecords) {
                    string configKey = (string)de.Key;
                    SectionRecord sectionRecord = (SectionRecord) de.Value;
                    sectionRecord.AddUpdate = false;
                    bool addUpdate = sectionRecord.HasFileInput;    // If true, add this section to definitionUpdates, and optinally to configSourceUpdates
                    OverrideModeSetting overrideMode = OverrideModeSetting.LocationDefault;
                    bool inheritInChildApplications = true;
                    bool moved = false;
                    string updatedXml = null;
                    bool addToConfigSourceUpdates = false;      // If true, we have to update the external config file for this section

                    if (!sectionRecord.HasResult) {
                        if (sectionRecord.HasFileInput) {
                            SectionXmlInfo sectionXmlInfo = sectionRecord.FileInput.SectionXmlInfo;
                            overrideMode = sectionXmlInfo.OverrideModeSetting;
                            inheritInChildApplications = !sectionXmlInfo.SkipInChildApps;
                            addToConfigSourceUpdates = requireUpdates && !String.IsNullOrEmpty(sectionXmlInfo.ConfigSource);
                        }
                    }
                    else {
                        ConfigurationSection configSection = (ConfigurationSection) sectionRecord.Result;

                        if (TargetFramework != null && !configSection.ShouldSerializeSectionInTargetVersion(TargetFramework))
                            continue;

                        overrideMode = configSection.SectionInformation.OverrideModeSetting;
                        inheritInChildApplications = configSection.SectionInformation.InheritInChildApplications;

                        // it is an error to require a location section when the type doesn't allow locations.
                        if (!configSection.SectionInformation.AllowLocation && (!overrideMode.IsDefaultForLocationTag || !inheritInChildApplications)) {
                            throw new ConfigurationErrorsException(SR.GetString(SR.Config_inconsistent_location_attributes, configKey));
                        }

                        addToConfigSourceUpdates = requireUpdates && !String.IsNullOrEmpty(configSection.SectionInformation.ConfigSource);
                        try {
                            bool isModified = configSection.SectionInformation.ForceSave ||
                                    configSection.IsModified() ||
                                    (forceSaveAll && !configSection.SectionInformation.IsLocked);

                            bool sectionAttributesModified = AreSectionAttributesModified(sectionRecord, configSection);
                            bool sectionContentModified = (isModified || configSection.SectionInformation.RawXml != null);

                            // Get the updated XML if the section has been modified.
                            if (sectionContentModified || sectionAttributesModified) {
                                configSection.SectionInformation.VerifyIsEditable();
                                configSection.SectionInformation.Removed = false;
                                addUpdate = true;
                                moved = IsConfigSectionMoved(sectionRecord, configSection);

                                if (!addToConfigSourceUpdates) {
                                    addToConfigSourceUpdates =
                                               !String.IsNullOrEmpty(configSection.SectionInformation.ConfigSource)
                                            && (sectionContentModified || configSection.SectionInformation.ConfigSourceModified);
                                }

                                if (    isModified ||
                                        configSection.SectionInformation.RawXml == null ||
                                        saveMode == ConfigurationSaveMode.Full) {
                                    // Note: we won't use RawXml if saveMode == Full because Full means we want to
                                    // write all properties, and RawXml may not have all properties.
                                    ConfigurationSection parentConfigSection = FindImmediateParentSection(configSection);
                                    updatedXml = configSection.SerializeSection(parentConfigSection, configSection.SectionInformation.Name, saveMode);
                                    ValidateSectionXml(updatedXml, configKey);
                                }
                                else {
                                    updatedXml = configSection.SectionInformation.RawXml;
                                }

                                if (string.IsNullOrEmpty(updatedXml)) {
                                    //
                                    // We always need to emit a section, even if empty, when:
                                    // * The section has configSoure
                                    // * The section is in a location section that has non-default attributes
                                    // * The section is encrypted.
                                    //
                                    if (    !String.IsNullOrEmpty(configSection.SectionInformation.ConfigSource) ||
                                            !configSection.SectionInformation.LocationAttributesAreDefault ||
                                            (configSection.SectionInformation.ProtectionProvider != null)) {

                                        updatedXml = WriteEmptyElement(configSection.SectionInformation.Name);
                                    }
                                }

                                if (string.IsNullOrEmpty(updatedXml)) {
                                    configSection.SectionInformation.Removed = true;
                                    // configSection.ElementPresent = false;
                                    updatedXml = null;
                                    addUpdate = false;
                                    if (sectionRecord.HasFileInput) {
                                        hasChanged = true;
                                        // VSWhidbey 580658: When a section is to be removed, its corresponding file
                                        // input should be cleared as well so this section will be indicated as "moved"
                                        // next time something is added back to the section.  Without marking it as "moved",
                                        // adding new content to a removed section fails as the bug describes.
                                        sectionRecord.RemoveFileInput();
                                    }
                                }
                                else {
                                    // configSection.ElementPresent = true;
                                    if (sectionAttributesModified || moved || String.IsNullOrEmpty(configSection.SectionInformation.ConfigSource)) {
                                        hasChanged = true;
                                    }

                                    // Encrypt if required.
                                    if (configSection.SectionInformation.ProtectionProvider != null) {
                                        ProtectedConfigurationSection protectedConfig = GetSection(BaseConfigurationRecord.RESERVED_SECTION_PROTECTED_CONFIGURATION) as ProtectedConfigurationSection;
                                        try {
                                            string encryptedSection = Host.EncryptSection(updatedXml, configSection.SectionInformation.ProtectionProvider, protectedConfig);

                                            // VsWhidbey 495120: The config host is responsible for encrypting a section, but it is the job of
                                            // System.Configuration to format an encrypted section during write (and to detect an encrypted section during read.)
                                            updatedXml = ProtectedConfigurationSection.FormatEncryptedSection(encryptedSection, configSection.SectionInformation.Name, configSection.SectionInformation.ProtectionProvider.Name);
                                        }
                                        catch (Exception e) {
                                            throw new ConfigurationErrorsException(
                                                    SR.GetString(SR.Encryption_failed, configSection.SectionInformation.SectionName, configSection.SectionInformation.ProtectionProvider.Name, e.Message),
                                                    e);
                                        }
                                    }
                                }
                            }
                            else if (configSection.SectionInformation.Removed) {
                                addUpdate = false;
                                if (sectionRecord.HasFileInput) {
                                    hasChanged = true;
                                }
                            }
                        }
                        catch (Exception e) {
                            throw new ConfigurationErrorsException(SR.GetString(SR.Config_exception_in_config_section_handler, configSection.SectionInformation.SectionName), e);
                        }
                    }

                    if (addUpdate) {
                        // Make sure we are not addingh a definition of a locked section
                        if (GetSectionLockedMode(sectionRecord.ConfigKey) == OverrideMode.Deny) {
                            throw new ConfigurationErrorsException(SR.GetString(SR.Config_section_locked), (IConfigErrorInfo)(null));
                        }

                        sectionRecord.AddUpdate = true;
                        DefinitionUpdate definitionUpdate = definitionUpdates.AddUpdate(overrideMode, inheritInChildApplications, moved, updatedXml, sectionRecord);
                        if (addToConfigSourceUpdates) {
                            if (configSourceUpdates == null) {
                                configSourceUpdates = new ArrayList();
                            }

                            configSourceUpdates.Add(definitionUpdate);
                        }
                    }
                }
            }

            if (_flags[ ForceLocationWritten ]) {
                // We must write the location tag
                hasChanged = true;
                definitionUpdates.RequireLocation = true;
            }

            if (_flags[ SuggestLocationRemoval ]) {
                // We should try to remove location
                hasChanged = true;
            }

            if (hasChanged) {
                definitionUpdates.CompleteUpdates();
            }
            else {
                definitionUpdates = null;
            }
        }
        // Create a new config file.
        private void CreateNewConfig(
                SectionUpdates          declarationUpdates,
                ConfigDefinitionUpdates definitionUpdates,
                NamespaceChange         namespaceChange,
                XmlUtilWriter           utilWriter) {
            int linePosition = DEFAULT_INDENT + 1;
            int indent = DEFAULT_INDENT;

            // Write Header
            utilWriter.Write(string.Format(CultureInfo.InvariantCulture,
                    FORMAT_NEWCONFIGFILE,
                    ConfigStreamInfo.StreamEncoding.WebName));

            // Write <configuration> tag
            if (namespaceChange == NamespaceChange.Add) {
                utilWriter.Write(string.Format(CultureInfo.InvariantCulture,
                        FORMAT_CONFIGURATION_NAMESPACE,
                        KEYWORD_CONFIGURATION_NAMESPACE));
            }
            else {
                utilWriter.Write(FORMAT_CONFIGURATION);
            }


            if (declarationUpdates != null) {
                WriteNewConfigDeclarations(declarationUpdates, utilWriter, linePosition, indent, false);
            }

            WriteNewConfigDefinitions(definitionUpdates, utilWriter, linePosition, indent);

            utilWriter.Write(FORMAT_CONFIGURATION_ENDELEMENT);
        }
 private void CreateNewConfig(SectionUpdates declarationUpdates, ConfigDefinitionUpdates definitionUpdates, NamespaceChange namespaceChange, XmlUtilWriter utilWriter)
 {
     int linePosition = 5;
     int indent = 4;
     utilWriter.Write(string.Format(CultureInfo.InvariantCulture, "<?xml version=\"1.0\" encoding=\"{0}\"?>\r\n", new object[] { base.ConfigStreamInfo.StreamEncoding.WebName }));
     if (namespaceChange == NamespaceChange.Add)
     {
         utilWriter.Write(string.Format(CultureInfo.InvariantCulture, "<configuration xmlns=\"{0}\">\r\n", new object[] { "http://schemas.microsoft.com/.NetConfiguration/v2.0" }));
     }
     else
     {
         utilWriter.Write("<configuration>\r\n");
     }
     if (declarationUpdates != null)
     {
         this.WriteNewConfigDeclarations(declarationUpdates, utilWriter, linePosition, indent, false);
     }
     this.WriteNewConfigDefinitions(definitionUpdates, utilWriter, linePosition, indent);
     utilWriter.Write("</configuration>");
 }
Пример #7
0
        // Create a new config file.
        private void CreateNewConfig(
            SectionUpdates declarationUpdates,
            ConfigDefinitionUpdates definitionUpdates,
            NamespaceChange namespaceChange,
            XmlUtilWriter utilWriter)
        {
            // Write Header
            utilWriter.Write(string.Format(CultureInfo.InvariantCulture,
                FormatNewconfigfile,
                ConfigStreamInfo.StreamEncoding.WebName));

            // Write <configuration> tag
            if (namespaceChange == NamespaceChange.Add)
            {
                utilWriter.Write(string.Format(CultureInfo.InvariantCulture,
                    FormatConfigurationNamespace,
                    KeywordConfigurationNamespace));
            }
            else utilWriter.Write(FormatConfiguration);

            const int LineIndent = DefaultIndent + 1;

            if (declarationUpdates != null)
                WriteNewConfigDeclarations(declarationUpdates, utilWriter, LineIndent, DefaultIndent, false);

            WriteNewConfigDefinitions(definitionUpdates, utilWriter, LineIndent, DefaultIndent);

            utilWriter.Write(FormatConfigurationEndelement);
        }
 private bool CopyConfigDefinitionsRecursive(ConfigDefinitionUpdates configDefinitionUpdates, XmlUtil xmlUtil, XmlUtilWriter utilWriter, bool locationPathApplies, LocationUpdates locationUpdates, SectionUpdates sectionUpdates, bool addNewSections, string group, int parentLinePosition, int parentIndent)
 {
     int trueLinePosition;
     int num3;
     bool flag = false;
     XmlTextReader reader = xmlUtil.Reader;
     int indent = this.UpdateIndent(parentIndent, xmlUtil, utilWriter, parentLinePosition);
     if (reader.NodeType == XmlNodeType.Element)
     {
         trueLinePosition = xmlUtil.TrueLinePosition;
         num3 = trueLinePosition;
     }
     else if (reader.NodeType == XmlNodeType.EndElement)
     {
         trueLinePosition = parentLinePosition + indent;
         if (utilWriter.IsLastLineBlank)
         {
             num3 = xmlUtil.TrueLinePosition;
         }
         else
         {
             num3 = parentLinePosition;
         }
     }
     else
     {
         trueLinePosition = parentLinePosition + indent;
         num3 = 0;
     }
     if ((sectionUpdates != null) && addNewSections)
     {
         sectionUpdates.IsNew = false;
         string[] movedSectionNames = sectionUpdates.GetMovedSectionNames();
         if (movedSectionNames != null)
         {
             if (!utilWriter.IsLastLineBlank)
             {
                 utilWriter.AppendNewLine();
             }
             utilWriter.AppendSpacesToLinePosition(trueLinePosition);
             bool skipFirstIndent = true;
             foreach (string str in movedSectionNames)
             {
                 DefinitionUpdate definitionUpdate = sectionUpdates.GetDefinitionUpdate(str);
                 this.WriteSectionUpdate(utilWriter, definitionUpdate, trueLinePosition, indent, skipFirstIndent);
                 skipFirstIndent = false;
                 utilWriter.AppendNewLine();
                 flag = true;
             }
             utilWriter.AppendSpacesToLinePosition(num3);
         }
     }
     if (reader.NodeType == XmlNodeType.Element)
     {
         int depth = reader.Depth;
         while (reader.Depth == depth)
         {
             bool flag3 = false;
             DefinitionUpdate update = null;
             bool flag4 = locationPathApplies;
             LocationUpdates updates = locationUpdates;
             SectionUpdates updates2 = sectionUpdates;
             bool flag5 = addNewSections;
             string str2 = group;
             bool flag6 = false;
             indent = this.UpdateIndent(indent, xmlUtil, utilWriter, parentLinePosition);
             trueLinePosition = xmlUtil.TrueLinePosition;
             string name = reader.Name;
             if (name == "location")
             {
                 string locationSubPath = BaseConfigurationRecord.NormalizeLocationSubPath(reader.GetAttribute("path"), xmlUtil);
                 flag4 = false;
                 OverrideModeSetting locationDefault = OverrideModeSetting.LocationDefault;
                 bool inheritInChildApps = true;
                 if (base.IsLocationConfig)
                 {
                     if (locationSubPath == null)
                     {
                         flag4 = false;
                     }
                     else
                     {
                         flag4 = StringUtil.EqualsIgnoreCase(base.ConfigPath, base.Host.GetConfigPathFromLocationSubPath(base.Parent.ConfigPath, locationSubPath));
                     }
                 }
                 else
                 {
                     flag4 = locationSubPath == null;
                 }
                 if (flag4)
                 {
                     string attribute = reader.GetAttribute("allowOverride");
                     if (attribute != null)
                     {
                         locationDefault = OverrideModeSetting.CreateFromXmlReadValue(bool.Parse(attribute));
                     }
                     string str6 = reader.GetAttribute("overrideMode");
                     if (str6 != null)
                     {
                         locationDefault = OverrideModeSetting.CreateFromXmlReadValue(OverrideModeSetting.ParseOverrideModeXmlValue(str6, null));
                     }
                     string str7 = reader.GetAttribute("inheritInChildApplications");
                     if (str7 != null)
                     {
                         inheritInChildApps = bool.Parse(str7);
                     }
                     configDefinitionUpdates.FlagLocationWritten();
                 }
                 if (reader.IsEmptyElement)
                 {
                     if (flag4 && (configDefinitionUpdates.FindLocationUpdates(locationDefault, inheritInChildApps) != null))
                     {
                         flag4 = true;
                     }
                     else
                     {
                         flag4 = false;
                     }
                 }
                 else if (flag4)
                 {
                     if (configDefinitionUpdates != null)
                     {
                         updates = configDefinitionUpdates.FindLocationUpdates(locationDefault, inheritInChildApps);
                         if (updates != null)
                         {
                             flag3 = true;
                             updates2 = updates.SectionUpdates;
                             if ((base._locationSubPath == null) && updates.IsDefault)
                             {
                                 flag5 = false;
                             }
                         }
                     }
                 }
                 else if ((this.HasRemovedSectionsOrGroups && !base.IsLocationConfig) && base.Host.SupportsLocation)
                 {
                     flag3 = true;
                     updates = null;
                     updates2 = null;
                     flag5 = false;
                 }
             }
             else
             {
                 string configKey = BaseConfigurationRecord.CombineConfigKey(group, name);
                 FactoryRecord record = base.FindFactoryRecord(configKey, false);
                 if (record == null)
                 {
                     if (!flag4 && !base.IsLocationConfig)
                     {
                         flag6 = true;
                     }
                 }
                 else if (record.IsGroup)
                 {
                     if (reader.IsEmptyElement)
                     {
                         if (!flag4 && !base.IsLocationConfig)
                         {
                             flag6 = true;
                         }
                     }
                     else if (sectionUpdates != null)
                     {
                         SectionUpdates sectionUpdatesForGroup = sectionUpdates.GetSectionUpdatesForGroup(name);
                         if (sectionUpdatesForGroup != null)
                         {
                             flag3 = true;
                             str2 = configKey;
                             updates2 = sectionUpdatesForGroup;
                         }
                     }
                     else if (!flag4 && !base.IsLocationConfig)
                     {
                         if ((this._removedSectionGroups != null) && this._removedSectionGroups.Contains(configKey))
                         {
                             flag6 = true;
                         }
                         else
                         {
                             flag3 = true;
                             str2 = configKey;
                             updates = null;
                             updates2 = null;
                             flag5 = false;
                         }
                     }
                 }
                 else if (sectionUpdates != null)
                 {
                     update = sectionUpdates.GetDefinitionUpdate(configKey);
                 }
                 else if ((!flag4 && !base.IsLocationConfig) && ((this._removedSections != null) && this._removedSections.Contains(configKey)))
                 {
                     flag6 = true;
                 }
             }
             if (flag3)
             {
                 object o = utilWriter.CreateStreamCheckpoint();
                 xmlUtil.CopyXmlNode(utilWriter);
                 xmlUtil.CopyReaderToNextElement(utilWriter, true);
                 bool flag8 = this.CopyConfigDefinitionsRecursive(configDefinitionUpdates, xmlUtil, utilWriter, flag4, updates, updates2, flag5, str2, trueLinePosition, indent);
                 xmlUtil.CopyXmlNode(utilWriter);
                 if (flag8)
                 {
                     flag = true;
                 }
                 else
                 {
                     utilWriter.RestoreStreamCheckpoint(o);
                 }
                 xmlUtil.CopyReaderToNextElement(utilWriter, true);
             }
             else
             {
                 bool flag9;
                 if (update == null)
                 {
                     flag9 = flag4 || flag6;
                 }
                 else
                 {
                     flag9 = false;
                     if (update.UpdatedXml != null)
                     {
                         ConfigurationSection result = (ConfigurationSection) update.SectionRecord.Result;
                         if (string.IsNullOrEmpty(result.SectionInformation.ConfigSource) || result.SectionInformation.ConfigSourceModified)
                         {
                             flag9 = true;
                             this.WriteSectionUpdate(utilWriter, update, trueLinePosition, indent, true);
                             flag = true;
                         }
                     }
                 }
                 if (flag9)
                 {
                     xmlUtil.SkipAndCopyReaderToNextElement(utilWriter, true);
                 }
                 else
                 {
                     xmlUtil.CopyOuterXmlToNextElement(utilWriter, true);
                     flag = true;
                 }
             }
         }
     }
     if (((sectionUpdates != null) && addNewSections) && sectionUpdates.HasNewSectionGroups())
     {
         trueLinePosition = parentLinePosition + indent;
         if (reader.NodeType == XmlNodeType.EndElement)
         {
             if (utilWriter.IsLastLineBlank)
             {
                 num3 = xmlUtil.TrueLinePosition;
             }
             else
             {
                 num3 = parentLinePosition;
             }
         }
         else
         {
             num3 = 0;
         }
         utilWriter.AppendSpacesToLinePosition(trueLinePosition);
         if (this.WriteNewConfigDefinitionsRecursive(utilWriter, sectionUpdates, trueLinePosition, indent, true))
         {
             flag = true;
         }
         utilWriter.AppendSpacesToLinePosition(num3);
     }
     return flag;
 }
 private void CopyConfig(SectionUpdates declarationUpdates, ConfigDefinitionUpdates definitionUpdates, byte[] buffer, string filename, NamespaceChange namespaceChange, XmlUtilWriter utilWriter)
 {
     this.CheckPreamble(base.ConfigStreamInfo.StreamEncoding.GetPreamble(), utilWriter, buffer);
     using (Stream stream = new MemoryStream(buffer))
     {
         using (XmlUtil util = new XmlUtil(stream, filename, false))
         {
             string str;
             XmlTextReader reader = util.Reader;
             reader.WhitespaceHandling = WhitespaceHandling.All;
             reader.Read();
             util.CopyReaderToNextElement(utilWriter, false);
             int indent = 4;
             int trueLinePosition = util.TrueLinePosition;
             bool isEmptyElement = reader.IsEmptyElement;
             if (namespaceChange == NamespaceChange.Add)
             {
                 str = string.Format(CultureInfo.InvariantCulture, "<configuration xmlns=\"{0}\">\r\n", new object[] { "http://schemas.microsoft.com/.NetConfiguration/v2.0" });
             }
             else if (namespaceChange == NamespaceChange.Remove)
             {
                 str = "<configuration>\r\n";
             }
             else
             {
                 str = null;
             }
             bool needsChildren = (declarationUpdates != null) || (definitionUpdates != null);
             string s = util.UpdateStartElement(utilWriter, str, needsChildren, trueLinePosition, indent);
             bool flag3 = false;
             if (!isEmptyElement)
             {
                 util.CopyReaderToNextElement(utilWriter, true);
                 indent = this.UpdateIndent(indent, util, utilWriter, trueLinePosition);
                 if ((reader.NodeType == XmlNodeType.Element) && (reader.Name == "configSections"))
                 {
                     flag3 = true;
                     int linePosition = util.TrueLinePosition;
                     bool flag4 = reader.IsEmptyElement;
                     if (declarationUpdates == null)
                     {
                         util.CopyOuterXmlToNextElement(utilWriter, true);
                     }
                     else
                     {
                         string str3 = util.UpdateStartElement(utilWriter, null, true, linePosition, indent);
                         if (!flag4)
                         {
                             util.CopyReaderToNextElement(utilWriter, true);
                             this.CopyConfigDeclarationsRecursive(declarationUpdates, util, utilWriter, string.Empty, linePosition, indent);
                         }
                         if (declarationUpdates.HasUnretrievedSections())
                         {
                             int num4 = 0;
                             if (str3 == null)
                             {
                                 num4 = util.TrueLinePosition;
                             }
                             if (!utilWriter.IsLastLineBlank)
                             {
                                 utilWriter.AppendNewLine();
                             }
                             this.WriteUnwrittenConfigDeclarations(declarationUpdates, utilWriter, linePosition + indent, indent, false);
                             if (str3 == null)
                             {
                                 utilWriter.AppendSpacesToLinePosition(num4);
                             }
                         }
                         if (str3 == null)
                         {
                             util.CopyXmlNode(utilWriter);
                         }
                         else
                         {
                             utilWriter.Write(str3);
                         }
                         util.CopyReaderToNextElement(utilWriter, true);
                     }
                 }
             }
             if (!flag3 && (declarationUpdates != null))
             {
                 int num5;
                 bool skipFirstIndent = (reader.Depth > 0) && (reader.NodeType == XmlNodeType.Element);
                 if (skipFirstIndent)
                 {
                     num5 = util.TrueLinePosition;
                 }
                 else
                 {
                     num5 = trueLinePosition + indent;
                 }
                 this.WriteNewConfigDeclarations(declarationUpdates, utilWriter, num5, indent, skipFirstIndent);
             }
             if (definitionUpdates != null)
             {
                 bool locationPathApplies = false;
                 LocationUpdates locationUpdates = null;
                 SectionUpdates sectionUpdates = null;
                 if (!base.IsLocationConfig)
                 {
                     locationPathApplies = true;
                     locationUpdates = definitionUpdates.FindLocationUpdates(OverrideModeSetting.LocationDefault, true);
                     if (locationUpdates != null)
                     {
                         sectionUpdates = locationUpdates.SectionUpdates;
                     }
                 }
                 this.CopyConfigDefinitionsRecursive(definitionUpdates, util, utilWriter, locationPathApplies, locationUpdates, sectionUpdates, true, string.Empty, trueLinePosition, indent);
                 this.WriteNewConfigDefinitions(definitionUpdates, utilWriter, trueLinePosition + indent, indent);
             }
             if (s != null)
             {
                 if (!utilWriter.IsLastLineBlank)
                 {
                     utilWriter.AppendNewLine();
                 }
                 utilWriter.Write(s);
             }
             while (util.CopyXmlNode(utilWriter))
             {
             }
         }
     }
 }
 private void WriteNewConfigDefinitions(ConfigDefinitionUpdates configDefinitionUpdates, XmlUtilWriter utilWriter, int linePosition, int indent)
 {
     if (configDefinitionUpdates != null)
     {
         foreach (LocationUpdates updates in configDefinitionUpdates.LocationUpdatesList)
         {
             SectionUpdates sectionUpdates = updates.SectionUpdates;
             if (!sectionUpdates.IsEmpty && sectionUpdates.IsNew)
             {
                 configDefinitionUpdates.FlagLocationWritten();
                 bool flag = (base._locationSubPath != null) || !updates.IsDefault;
                 int num = linePosition;
                 utilWriter.AppendSpacesToLinePosition(linePosition);
                 if (flag)
                 {
                     if (base._locationSubPath == null)
                     {
                         utilWriter.Write(string.Format(CultureInfo.InvariantCulture, "<location {0} inheritInChildApplications=\"{1}\">\r\n", new object[] { updates.OverrideMode.LocationTagXmlString, BoolToString(updates.InheritInChildApps) }));
                     }
                     else
                     {
                         utilWriter.Write(string.Format(CultureInfo.InvariantCulture, "<location path=\"{2}\" {0} inheritInChildApplications=\"{1}\">\r\n", new object[] { updates.OverrideMode.LocationTagXmlString, BoolToString(updates.InheritInChildApps), base._locationSubPath }));
                     }
                     num += indent;
                     utilWriter.AppendSpacesToLinePosition(num);
                 }
                 this.WriteNewConfigDefinitionsRecursive(utilWriter, updates.SectionUpdates, num, indent, true);
                 if (flag)
                 {
                     utilWriter.AppendSpacesToLinePosition(linePosition);
                     utilWriter.Write("</location>");
                     utilWriter.AppendNewLine();
                 }
             }
         }
         if (configDefinitionUpdates.RequireLocation)
         {
             configDefinitionUpdates.FlagLocationWritten();
             utilWriter.AppendSpacesToLinePosition(linePosition);
             utilWriter.Write(string.Format(CultureInfo.InvariantCulture, "<location path=\"{2}\" {0} inheritInChildApplications=\"{1}\">\r\n", new object[] { OverrideModeSetting.LocationDefault.LocationTagXmlString, "true", base._locationSubPath }));
             utilWriter.AppendSpacesToLinePosition(linePosition);
             utilWriter.Write("</location>");
             utilWriter.AppendNewLine();
         }
     }
 }
 private void GetConfigDefinitionUpdates(bool requireUpdates, ConfigurationSaveMode saveMode, bool forceSaveAll, out ConfigDefinitionUpdates definitionUpdates, out ArrayList configSourceUpdates)
 {
     definitionUpdates = new ConfigDefinitionUpdates();
     configSourceUpdates = null;
     bool hasRemovedSections = this.HasRemovedSections;
     if (base._sectionRecords != null)
     {
         base.InitProtectedConfigurationSection();
         foreach (DictionaryEntry entry in base._sectionRecords)
         {
             string key = (string) entry.Key;
             SectionRecord sectionRecord = (SectionRecord) entry.Value;
             sectionRecord.AddUpdate = false;
             bool hasFileInput = sectionRecord.HasFileInput;
             OverrideModeSetting locationDefault = OverrideModeSetting.LocationDefault;
             bool inheritInChildApps = true;
             bool moved = false;
             string xmlElement = null;
             bool flag5 = false;
             if (!sectionRecord.HasResult)
             {
                 if (sectionRecord.HasFileInput)
                 {
                     SectionXmlInfo sectionXmlInfo = sectionRecord.FileInput.SectionXmlInfo;
                     locationDefault = sectionXmlInfo.OverrideModeSetting;
                     inheritInChildApps = !sectionXmlInfo.SkipInChildApps;
                     flag5 = requireUpdates && !string.IsNullOrEmpty(sectionXmlInfo.ConfigSource);
                 }
             }
             else
             {
                 ConfigurationSection result = (ConfigurationSection) sectionRecord.Result;
                 if ((base.TargetFramework != null) && !result.ShouldSerializeSectionInTargetVersion(base.TargetFramework))
                 {
                     continue;
                 }
                 locationDefault = result.SectionInformation.OverrideModeSetting;
                 inheritInChildApps = result.SectionInformation.InheritInChildApplications;
                 if (!result.SectionInformation.AllowLocation && (!locationDefault.IsDefaultForLocationTag || !inheritInChildApps))
                 {
                     throw new ConfigurationErrorsException(System.Configuration.SR.GetString("Config_inconsistent_location_attributes", new object[] { key }));
                 }
                 flag5 = requireUpdates && !string.IsNullOrEmpty(result.SectionInformation.ConfigSource);
                 try
                 {
                     bool flag6 = (result.SectionInformation.ForceSave || result.IsModified()) || (forceSaveAll && !result.SectionInformation.IsLocked);
                     bool flag7 = this.AreSectionAttributesModified(sectionRecord, result);
                     bool flag8 = flag6 || (result.SectionInformation.RawXml != null);
                     if (flag8 || flag7)
                     {
                         result.SectionInformation.VerifyIsEditable();
                         result.SectionInformation.Removed = false;
                         hasFileInput = true;
                         moved = this.IsConfigSectionMoved(sectionRecord, result);
                         if (!flag5)
                         {
                             flag5 = !string.IsNullOrEmpty(result.SectionInformation.ConfigSource) && (flag8 || result.SectionInformation.ConfigSourceModified);
                         }
                         if ((flag6 || (result.SectionInformation.RawXml == null)) || (saveMode == ConfigurationSaveMode.Full))
                         {
                             ConfigurationSection parentElement = this.FindImmediateParentSection(result);
                             xmlElement = result.SerializeSection(parentElement, result.SectionInformation.Name, saveMode);
                             this.ValidateSectionXml(xmlElement, key);
                         }
                         else
                         {
                             xmlElement = result.SectionInformation.RawXml;
                         }
                         if (string.IsNullOrEmpty(xmlElement) && ((!string.IsNullOrEmpty(result.SectionInformation.ConfigSource) || !result.SectionInformation.LocationAttributesAreDefault) || (result.SectionInformation.ProtectionProvider != null)))
                         {
                             xmlElement = this.WriteEmptyElement(result.SectionInformation.Name);
                         }
                         if (string.IsNullOrEmpty(xmlElement))
                         {
                             result.SectionInformation.Removed = true;
                             xmlElement = null;
                             hasFileInput = false;
                             if (sectionRecord.HasFileInput)
                             {
                                 hasRemovedSections = true;
                                 sectionRecord.RemoveFileInput();
                             }
                             goto Label_0416;
                         }
                         if ((flag7 || moved) || string.IsNullOrEmpty(result.SectionInformation.ConfigSource))
                         {
                             hasRemovedSections = true;
                         }
                         if (result.SectionInformation.ProtectionProvider == null)
                         {
                             goto Label_0416;
                         }
                         ProtectedConfigurationSection section = base.GetSection("configProtectedData") as ProtectedConfigurationSection;
                         try
                         {
                             xmlElement = ProtectedConfigurationSection.FormatEncryptedSection(base.Host.EncryptSection(xmlElement, result.SectionInformation.ProtectionProvider, section), result.SectionInformation.Name, result.SectionInformation.ProtectionProvider.Name);
                             goto Label_0416;
                         }
                         catch (Exception exception)
                         {
                             throw new ConfigurationErrorsException(System.Configuration.SR.GetString("Encryption_failed", new object[] { result.SectionInformation.SectionName, result.SectionInformation.ProtectionProvider.Name, exception.Message }), exception);
                         }
                     }
                     if (result.SectionInformation.Removed)
                     {
                         hasFileInput = false;
                         if (sectionRecord.HasFileInput)
                         {
                             hasRemovedSections = true;
                         }
                     }
                 }
                 catch (Exception exception2)
                 {
                     throw new ConfigurationErrorsException(System.Configuration.SR.GetString("Config_exception_in_config_section_handler", new object[] { result.SectionInformation.SectionName }), exception2);
                 }
             }
         Label_0416:
             if (hasFileInput)
             {
                 if (base.GetSectionLockedMode(sectionRecord.ConfigKey) == OverrideMode.Deny)
                 {
                     throw new ConfigurationErrorsException(System.Configuration.SR.GetString("Config_section_locked"), null);
                 }
                 sectionRecord.AddUpdate = true;
                 DefinitionUpdate update = definitionUpdates.AddUpdate(locationDefault, inheritInChildApps, moved, xmlElement, sectionRecord);
                 if (flag5)
                 {
                     if (configSourceUpdates == null)
                     {
                         configSourceUpdates = new ArrayList();
                     }
                     configSourceUpdates.Add(update);
                 }
             }
         }
     }
     if (this._flags[0x1000000])
     {
         hasRemovedSections = true;
         definitionUpdates.RequireLocation = true;
     }
     if (this._flags[0x2000000])
     {
         hasRemovedSections = true;
     }
     if (hasRemovedSections)
     {
         definitionUpdates.CompleteUpdates();
     }
     else
     {
         definitionUpdates = null;
     }
 }
        // Gather all the updates to the configuration section definitions.
        private void GetConfigDefinitionUpdates(
                bool requireUpdates, ConfigurationSaveMode saveMode, bool forceSaveAll, 
                out ConfigDefinitionUpdates definitionUpdates, out ArrayList configSourceUpdates) {

            definitionUpdates = new ConfigDefinitionUpdates();
            configSourceUpdates = null;
            bool hasChanged = HasRemovedSections;

            // Loop through all the section records.
            if (_sectionRecords != null) {
                InitProtectedConfigurationSection(); // Make sure we have the initialized the protected config section, otherwise the foreach loop may blow up
                foreach (DictionaryEntry de in _sectionRecords) {
                    string configKey = (string)de.Key;
                    SectionRecord sectionRecord = (SectionRecord) de.Value;
                    sectionRecord.AddUpdate = false;
                    bool addUpdate = sectionRecord.HasFileInput;    // If true, add this section to definitionUpdates, and optinally to configSourceUpdates
                    bool allowOverride = true;
                    bool inheritInChildApplications = true;
                    bool moved = false;
                    string updatedXml = null;
                    bool addToConfigSourceUpdates = false;      // If true, we have to update the external config file for this section

                    if (!sectionRecord.HasResult) {
                        if (sectionRecord.HasFileInput) {
                            SectionXmlInfo sectionXmlInfo = sectionRecord.FileInput.SectionXmlInfo;
                            allowOverride = !sectionXmlInfo.LockChildren;
                            inheritInChildApplications = !sectionXmlInfo.SkipInChildApps;
                            addToConfigSourceUpdates = requireUpdates && !String.IsNullOrEmpty(sectionXmlInfo.ConfigSource);
                        }
                    }
                    else {
                        ConfigurationSection configSection = (ConfigurationSection) sectionRecord.Result;

                        allowOverride = configSection.SectionInformation.AllowOverride;
                        inheritInChildApplications = configSection.SectionInformation.InheritInChildApplications;

                        // it is an error to require a location section when the type doesn't allow locations.
                        if (!configSection.SectionInformation.AllowLocation && (!allowOverride || !inheritInChildApplications)) {
                            throw new ConfigurationErrorsException(SR.GetString(SR.Config_inconsistent_location_attributes, configKey));
                        }

                        addToConfigSourceUpdates = requireUpdates && !String.IsNullOrEmpty(configSection.SectionInformation.ConfigSource);
                        try {
                            bool isModified = configSection.SectionInformation.ForceSave ||
                                    configSection.IsModified() ||
                                    (forceSaveAll && !configSection.SectionInformation.IsLocked);

                            bool sectionAttributesModified = AreSectionAttributesModified(sectionRecord, configSection);
                            bool sectionContentModified = (isModified || configSection.SectionInformation.RawXml != null);

                            // Get the updated XML if the section has been modified.
                            if (sectionContentModified || sectionAttributesModified) {
                                configSection.SectionInformation.VerifyIsEditable(); 
                                configSection.SectionInformation.Removed = false;
                                addUpdate = true;
                                moved = IsConfigSectionMoved(sectionRecord, configSection);

                                if (!addToConfigSourceUpdates) {
                                    addToConfigSourceUpdates = 
                                               !String.IsNullOrEmpty(configSection.SectionInformation.ConfigSource) 
                                            && (sectionContentModified || configSection.SectionInformation.ConfigSourceModified);
                                }

                                if (    isModified || 
                                        configSection.SectionInformation.RawXml == null || 
                                        saveMode == ConfigurationSaveMode.Full) {
                                    // Note: we won't use RawXml if saveMode == Full because Full means we want to
                                    // write all properties, and RawXml may not have all properties.
                                    ConfigurationSection parentConfigSection = FindImmediateParentSection(configSection);
                                    updatedXml = configSection.SerializeSection(parentConfigSection, configSection.SectionInformation.Name, saveMode);
                                    ValidateSectionXml(updatedXml, configKey);
                                }
                                else {
                                    updatedXml = configSection.SectionInformation.RawXml;
                                }

                                if (string.IsNullOrEmpty(updatedXml)) {
                                    //
                                    // We always need to emit a section, even if empty, when:
                                    // * The section has configSoure
                                    // * The section is in a location section that has non-default attributes
                                    // * The section is encrypted.
                                    // 
                                    if (    !String.IsNullOrEmpty(configSection.SectionInformation.ConfigSource) ||
                                            !configSection.SectionInformation.LocationAttributesAreDefault ||
                                            (configSection.SectionInformation.ProtectionProvider != null)) {

                                        updatedXml = WriteEmptyElement(configSection.SectionInformation.Name);
                                    }
                                }

                                if (string.IsNullOrEmpty(updatedXml)) {
                                    configSection.SectionInformation.Removed = true;
                                    // configSection.ElementPresent = false;
                                    updatedXml = null;
                                    addUpdate = false;
                                    if (sectionRecord.HasFileInput) {
                                        hasChanged = true;
                                    }
                                }
                                else {
                                    // configSection.ElementPresent = true;
                                    if (sectionAttributesModified || moved || String.IsNullOrEmpty(configSection.SectionInformation.ConfigSource)) {
                                        hasChanged = true;
                                    }

                                    // Encrypt if required.
                                    if (configSection.SectionInformation.ProtectionProvider != null) {
                                        ProtectedConfigurationSection protectedConfig = GetSection(BaseConfigurationRecord.RESERVED_SECTION_PROTECTED_CONFIGURATION) as ProtectedConfigurationSection;
                                        try {
                                            string encryptedSection = Host.EncryptSection(updatedXml, configSection.SectionInformation.ProtectionProvider, protectedConfig);

                                            updatedXml = ProtectedConfigurationSection.FormatEncryptedSection(encryptedSection, configSection.SectionInformation.Name, configSection.SectionInformation.ProtectionProvider.Name);
                                        }
                                        catch (Exception e) {
                                            throw new ConfigurationErrorsException(
                                                    SR.GetString(SR.Encryption_failed, configSection.SectionInformation.SectionName, configSection.SectionInformation.ProtectionProvider.Name, e.Message), 
                                                    e);
                                        }
                                        catch {
                                            throw new ConfigurationErrorsException(
                                                    SR.GetString(SR.Encryption_failed, configSection.SectionInformation.SectionName, configSection.SectionInformation.ProtectionProvider.Name, ExceptionUtil.NoExceptionInformation));
                                        }
                                    }
                                }
                            }
                            else if (configSection.SectionInformation.Removed) {
                                addUpdate = false;
                                if (sectionRecord.HasFileInput) {
                                    hasChanged = true;
                                }
                            }
                        }
                        catch (Exception e) {
                            throw new ConfigurationErrorsException(SR.GetString(SR.Config_exception_in_config_section_handler, configSection.SectionInformation.SectionName), e);
                        }
                        catch {
                            throw new ConfigurationErrorsException(SR.GetString(SR.Config_exception_in_config_section_handler, configSection.SectionInformation.SectionName));
                        }
                    }

                    if (addUpdate) {
                        VerifySectionUnlocked(sectionRecord.ConfigKey, null);
                        sectionRecord.AddUpdate = true;
                        DefinitionUpdate definitionUpdate = definitionUpdates.AddUpdate(allowOverride, inheritInChildApplications, moved, updatedXml, sectionRecord);
                        if (addToConfigSourceUpdates) {
                            if (configSourceUpdates == null) {
                                configSourceUpdates = new ArrayList();
                            }

                            configSourceUpdates.Add(definitionUpdate);
                        }
                    }
                }
            }

            if (_flags[ ForceLocationWritten ]) {
                // We must write the location tag
                hasChanged = true;
                definitionUpdates.RequireLocation = true;
            }

            if (_flags[ SuggestLocationRemoval ]) {
                // We should try to remove location
                hasChanged = true;
            }

            if (hasChanged) {
                definitionUpdates.CompleteUpdates();
            }
            else {
                definitionUpdates = null;
            }
        }