private VerifyRequiredAttribute ( object o, string attrName, ExceptionAction action ) : bool | ||
o | object | |
attrName | string | |
action | ExceptionAction | |
return | bool |
// Scans the <configSections> section of a configuration file. The function is recursive // to traverse arbitrarily nested config groups. // // <sectionGroup name="foo"> // <sectionGroup name="bar"> // <section name="fooBarSection" type="..." /> // ... // // Note: This function valiates that the factory record has not been // declared before in a parent record. (it does not check // current record, which allows you to update list) // private void ScanFactoriesRecursive(XmlUtil xmlUtil, string parentConfigKey, Hashtable factoryList) { // discard any accumulated local errors xmlUtil.SchemaErrors.ResetLocalErrors(); int depth = xmlUtil.Reader.Depth; xmlUtil.StrictReadToNextElement(ExceptionAction.NonSpecific); while (xmlUtil.Reader.Depth == depth + 1) { bool positionedAtNextElement = false; switch (xmlUtil.Reader.Name) { // // Handle <sectionGroup name="groupName" [type="typename"] /> // case KEYWORD_SECTIONGROUP: { string tagName = null; string typeName = null; int lineNumber = xmlUtil.Reader.LineNumber; while (xmlUtil.Reader.MoveToNextAttribute()) { switch (xmlUtil.Reader.Name) { case KEYWORD_SECTIONGROUP_NAME: tagName = xmlUtil.Reader.Value; VerifySectionName(tagName, xmlUtil, ExceptionAction.Local, false); break; case KEYWORD_SECTIONGROUP_TYPE: xmlUtil.VerifyAndGetNonEmptyStringAttribute(ExceptionAction.Local, out typeName); break; default: xmlUtil.AddErrorUnrecognizedAttribute(ExceptionAction.Local); break; } } xmlUtil.Reader.MoveToElement(); // if on an attribute move back to the element if (!xmlUtil.VerifyRequiredAttribute( tagName, KEYWORD_SECTIONGROUP_NAME, ExceptionAction.NonSpecific)) { // // Without a name, we cannot continue parsing the sections and groups within. // Skip the entire section. // xmlUtil.SchemaErrors.RetrieveAndResetLocalErrors(true); xmlUtil.StrictSkipToNextElement(ExceptionAction.NonSpecific); } else { string configKey = CombineConfigKey(parentConfigKey, tagName); FactoryRecord factoryRecord = (FactoryRecord) factoryList[configKey]; if (factoryRecord != null) { // Error: duplicate sectionGroup declaration xmlUtil.SchemaErrors.AddError( new ConfigurationErrorsException(SR.GetString(SR.Config_tag_name_already_defined_at_this_level, tagName), xmlUtil), ExceptionAction.Local); } else { FactoryRecord parentFactoryRecord = _parent.FindFactoryRecord(configKey, true); if (parentFactoryRecord != null) { configKey = parentFactoryRecord.ConfigKey; // make sure that an ancestor has not defined a section with the same name as the group if ( !parentFactoryRecord.IsGroup || !parentFactoryRecord.IsEquivalentSectionGroupFactory(Host, typeName)) { xmlUtil.SchemaErrors.AddError( new ConfigurationErrorsException(SR.GetString(SR.Config_tag_name_already_defined, tagName), xmlUtil), ExceptionAction.Local); parentFactoryRecord = null; } } if (parentFactoryRecord != null) { factoryRecord = parentFactoryRecord.CloneSectionGroup(typeName, xmlUtil.Filename, lineNumber); } else { factoryRecord = new FactoryRecord(configKey, parentConfigKey, tagName, typeName, xmlUtil.Filename, lineNumber); } factoryList[configKey] = factoryRecord; } // Add any errors we may have encountered factoryRecord.AddErrors(xmlUtil.SchemaErrors.RetrieveAndResetLocalErrors(true)); // continue recursive scan ScanFactoriesRecursive(xmlUtil, configKey, factoryList); } continue; } case KEYWORD_SECTION: { string tagName = null; string typeName = null; ConfigurationAllowDefinition allowDefinition = ConfigurationAllowDefinition.Everywhere; ConfigurationAllowExeDefinition allowExeDefinition = ConfigurationAllowExeDefinition.MachineToApplication; bool allowLocation = true; bool restartOnExternalChanges = true; bool requirePermission = true; bool gotType = false; // parse section attributes int lineNumber = xmlUtil.Reader.LineNumber; while (xmlUtil.Reader.MoveToNextAttribute()) { switch (xmlUtil.Reader.Name) { case KEYWORD_SECTION_NAME: tagName = xmlUtil.Reader.Value; VerifySectionName(tagName, xmlUtil, ExceptionAction.Local, false); break; case KEYWORD_SECTION_TYPE: xmlUtil.VerifyAndGetNonEmptyStringAttribute(ExceptionAction.Local, out typeName); gotType = true; break; case KEYWORD_SECTION_ALLOWLOCATION: xmlUtil.VerifyAndGetBooleanAttribute( ExceptionAction.Local, true, out allowLocation); break; case KEYWORD_SECTION_ALLOWEXEDEFINITION: try { allowExeDefinition = AllowExeDefinitionToEnum(xmlUtil.Reader.Value, xmlUtil); } catch (ConfigurationException ce) { xmlUtil.SchemaErrors.AddError(ce, ExceptionAction.Local); } break; case KEYWORD_SECTION_ALLOWDEFINITION: try { allowDefinition = AllowDefinitionToEnum(xmlUtil.Reader.Value, xmlUtil); } catch (ConfigurationException ce) { xmlUtil.SchemaErrors.AddError(ce, ExceptionAction.Local); } break; case KEYWORD_SECTION_RESTARTONEXTERNALCHANGES: xmlUtil.VerifyAndGetBooleanAttribute( ExceptionAction.Local, true, out restartOnExternalChanges); break; case KEYWORD_SECTION_REQUIREPERMISSION: xmlUtil.VerifyAndGetBooleanAttribute( ExceptionAction.Local, true, out requirePermission); break; default: xmlUtil.AddErrorUnrecognizedAttribute(ExceptionAction.Local); break; } } xmlUtil.Reader.MoveToElement(); // if on an attribute move back to the element if (!xmlUtil.VerifyRequiredAttribute( tagName, KEYWORD_SECTION_NAME, ExceptionAction.NonSpecific)) { // // Without a name, we cannot continue to create a factoryRecord. // xmlUtil.SchemaErrors.RetrieveAndResetLocalErrors(true); } else { // Verify that the Type attribute was present. // Note that 'typeName' will be null if the attribute was present // but specified as an empty string. if (!gotType) { xmlUtil.AddErrorRequiredAttribute(KEYWORD_SECTION_TYPE, ExceptionAction.Local); } string configKey = CombineConfigKey(parentConfigKey, tagName); FactoryRecord factoryRecord = (FactoryRecord) factoryList[configKey]; if (factoryRecord != null) { // Error: duplicate section declaration xmlUtil.SchemaErrors.AddError( new ConfigurationErrorsException(SR.GetString(SR.Config_tag_name_already_defined_at_this_level, tagName), xmlUtil), ExceptionAction.Local); } else { FactoryRecord parentFactoryRecord = _parent.FindFactoryRecord(configKey, true); if (parentFactoryRecord != null) { configKey = parentFactoryRecord.ConfigKey; // make sure that an ancestor has not defined a section with the same name as the group if (parentFactoryRecord.IsGroup) { xmlUtil.SchemaErrors.AddError( new ConfigurationErrorsException(SR.GetString(SR.Config_tag_name_already_defined, tagName), xmlUtil), ExceptionAction.Local); parentFactoryRecord = null; } else if (!parentFactoryRecord.IsEquivalentSectionFactory(Host, typeName, allowLocation, allowDefinition, allowExeDefinition, restartOnExternalChanges, requirePermission)) { xmlUtil.SchemaErrors.AddError( new ConfigurationErrorsException(SR.GetString(SR.Config_tag_name_already_defined, tagName), xmlUtil), ExceptionAction.Local); parentFactoryRecord = null; } } if (parentFactoryRecord != null) { // Note - Clone will propagate the IsFromTrustedConfigRecord bit, // which is what we want - if this record is a duplicate of an ancestor, // the ancestor may be from a trusted config record. factoryRecord = parentFactoryRecord.CloneSection(xmlUtil.Filename, lineNumber); } else { factoryRecord = new FactoryRecord( configKey, parentConfigKey, tagName, typeName, allowLocation, allowDefinition, allowExeDefinition, restartOnExternalChanges, requirePermission, _flags[IsTrusted], false, // isUndeclared xmlUtil.Filename, lineNumber); } factoryList[configKey] = factoryRecord; } // Add any errors we may have encountered factoryRecord.AddErrors(xmlUtil.SchemaErrors.RetrieveAndResetLocalErrors(true)); } } break; case KEYWORD_REMOVE: { string name = null; int lineNumber = -1; // parse attributes while (xmlUtil.Reader.MoveToNextAttribute()) { if (xmlUtil.Reader.Name != KEYWORD_SECTION_NAME) { xmlUtil.AddErrorUnrecognizedAttribute(ExceptionAction.NonSpecific); } name = xmlUtil.Reader.Value; lineNumber = xmlUtil.Reader.LineNumber; } xmlUtil.Reader.MoveToElement(); if (xmlUtil.VerifyRequiredAttribute( name, KEYWORD_SECTION_NAME, ExceptionAction.NonSpecific)) { VerifySectionName(name, xmlUtil, ExceptionAction.NonSpecific, false); } } break; case KEYWORD_CLEAR: { xmlUtil.VerifyNoUnrecognizedAttributes(ExceptionAction.NonSpecific); } break; default: xmlUtil.AddErrorUnrecognizedElement(ExceptionAction.NonSpecific); xmlUtil.StrictSkipToNextElement(ExceptionAction.NonSpecific); positionedAtNextElement = true; break; } if (!positionedAtNextElement) { // Need to read to next element, and check if an unrecognized child // element is found. xmlUtil.StrictReadToNextElement(ExceptionAction.NonSpecific); // unrecognized children are not allowed in <configSections> if (xmlUtil.Reader.Depth > depth + 1) { xmlUtil.AddErrorUnrecognizedElement(ExceptionAction.NonSpecific); // Lets try to backup to where we are suppose to be while (xmlUtil.Reader.Depth > (depth + 1)) { xmlUtil.ReadToNextElement(); } } } } }