XmlUtil
using System.Configuration.Internal;
using System.Globalization;
using System.IO;
using System.Text;
using System.Xml;
namespace System.Configuration
{
internal sealed class XmlUtil : IDisposable, IConfigErrorInfo
{
private const int MaxLineWidth = 60;
private StringWriter _cachedStringWriter;
private int _lastLineNumber;
private int _lastLinePosition;
private Stream _stream;
private static ReadOnlySpan<int> PositionOffset {
get {
object obj = global::<PrivateImplementationDetails>.D523102CC9E2790FF1E8689A2541A70BB5FF2390AB957F902ACD5A04E22404C5_A6;
if (obj == null) {
obj = new int[18] {
0,
1,
-1,
0,
9,
1,
-1,
2,
4,
-1,
10,
-1,
-1,
0,
0,
2,
-1,
2
};
global::<PrivateImplementationDetails>.D523102CC9E2790FF1E8689A2541A70BB5FF2390AB957F902ACD5A04E22404C5_A6 = (int[])obj;
}
return new ReadOnlySpan<int>((int[])obj);
}
}
internal int TrueLinePosition => Reader.LinePosition - GetPositionOffset(Reader.NodeType);
internal XmlTextReader Reader { get; set; }
internal ConfigurationSchemaErrors SchemaErrors { get; }
public string Filename { get; }
public int LineNumber => Reader.LineNumber;
internal XmlUtil(Stream stream, string name, bool readToFirstElement)
: this(stream, name, readToFirstElement, new ConfigurationSchemaErrors())
{
}
internal XmlUtil(Stream stream, string name, bool readToFirstElement, ConfigurationSchemaErrors schemaErrors)
{
try {
Filename = name;
_stream = stream;
Reader = new XmlTextReader(_stream) {
XmlResolver = null
};
SchemaErrors = schemaErrors;
_lastLineNumber = 1;
_lastLinePosition = 1;
if (readToFirstElement) {
Reader.WhitespaceHandling = WhitespaceHandling.None;
bool flag = false;
while (!flag && Reader.Read()) {
switch (Reader.NodeType) {
case XmlNodeType.Element:
flag = true;
break;
default:
throw new ConfigurationErrorsException(System.SR.Config_base_unrecognized_element, this);
case XmlNodeType.Comment:
case XmlNodeType.DocumentType:
case XmlNodeType.XmlDeclaration:
break;
}
}
}
} catch {
ReleaseResources();
throw;
}
}
public void Dispose()
{
ReleaseResources();
}
private static int GetPositionOffset(XmlNodeType nodeType)
{
return PositionOffset[(int)nodeType];
}
private void ReleaseResources()
{
if (Reader != null) {
Reader.Close();
Reader = null;
} else
_stream?.Close();
_stream = null;
if (_cachedStringWriter != null) {
_cachedStringWriter.Close();
_cachedStringWriter = null;
}
}
internal void ReadToNextElement()
{
while (Reader.Read() && Reader.MoveToContent() != XmlNodeType.Element) {
}
}
internal void SkipToNextElement()
{
Reader.Skip();
Reader.MoveToContent();
while (!Reader.EOF && Reader.NodeType != XmlNodeType.Element) {
Reader.Read();
Reader.MoveToContent();
}
}
internal void StrictReadToNextElement(ExceptionAction action)
{
while (Reader.Read() && Reader.NodeType != XmlNodeType.Element) {
VerifyIgnorableNodeType(action);
}
}
internal void StrictSkipToNextElement(ExceptionAction action)
{
Reader.Skip();
while (!Reader.EOF && Reader.NodeType != XmlNodeType.Element) {
VerifyIgnorableNodeType(action);
Reader.Read();
}
}
internal void StrictSkipToOurParentsEndElement(ExceptionAction action)
{
int depth = Reader.Depth;
while (Reader.Depth >= depth) {
Reader.Skip();
}
while (!Reader.EOF && Reader.NodeType != XmlNodeType.EndElement) {
VerifyIgnorableNodeType(action);
Reader.Read();
}
}
internal void VerifyIgnorableNodeType(ExceptionAction action)
{
XmlNodeType nodeType = Reader.NodeType;
if (nodeType != XmlNodeType.Comment && nodeType != XmlNodeType.EndElement) {
ConfigurationException ce = new ConfigurationErrorsException(System.SR.Config_base_unrecognized_element, this);
SchemaErrors.AddError(ce, action);
}
}
internal void VerifyNoUnrecognizedAttributes(ExceptionAction action)
{
if (Reader.MoveToNextAttribute())
AddErrorUnrecognizedAttribute(action);
}
internal bool VerifyRequiredAttribute(object requiredAttribute, string attrName, ExceptionAction action)
{
if (requiredAttribute == null) {
AddErrorRequiredAttribute(attrName, action);
return false;
}
return true;
}
internal void AddErrorUnrecognizedAttribute(ExceptionAction action)
{
ConfigurationErrorsException ce = new ConfigurationErrorsException(System.SR.Format(System.SR.Config_base_unrecognized_attribute, Reader.Name), this);
SchemaErrors.AddError(ce, action);
}
internal void AddErrorRequiredAttribute(string attrib, ExceptionAction action)
{
ConfigurationErrorsException ce = new ConfigurationErrorsException(System.SR.Format(System.SR.Config_missing_required_attribute, attrib, Reader.Name), this);
SchemaErrors.AddError(ce, action);
}
internal void AddErrorReservedAttribute(ExceptionAction action)
{
ConfigurationErrorsException ce = new ConfigurationErrorsException(System.SR.Format(System.SR.Config_reserved_attribute, Reader.Name), this);
SchemaErrors.AddError(ce, action);
}
internal void AddErrorUnrecognizedElement(ExceptionAction action)
{
ConfigurationErrorsException ce = new ConfigurationErrorsException(System.SR.Config_base_unrecognized_element, this);
SchemaErrors.AddError(ce, action);
}
internal void VerifyAndGetNonEmptyStringAttribute(ExceptionAction action, out string newValue)
{
if (!string.IsNullOrEmpty(Reader.Value))
newValue = Reader.Value;
else {
newValue = null;
ConfigurationException ce = new ConfigurationErrorsException(System.SR.Format(System.SR.Empty_attribute, Reader.Name), this);
SchemaErrors.AddError(ce, action);
}
}
internal void VerifyAndGetBooleanAttribute(ExceptionAction action, bool defaultValue, out bool newValue)
{
string value = Reader.Value;
if (!(value == "true")) {
if (value == "false")
newValue = false;
else {
newValue = defaultValue;
SchemaErrors.AddError(new ConfigurationErrorsException(System.SR.Format(System.SR.Config_invalid_boolean_attribute, Reader.Name), this), action);
}
} else
newValue = true;
}
internal bool CopyOuterXmlToNextElement(XmlUtilWriter utilWriter, bool limitDepth)
{
CopyElement(utilWriter);
return CopyReaderToNextElement(utilWriter, limitDepth);
}
internal bool SkipChildElementsAndCopyOuterXmlToNextElement(XmlUtilWriter utilWriter)
{
bool isEmptyElement = Reader.IsEmptyElement;
int lineNumber = Reader.LineNumber;
CopyXmlNode(utilWriter);
if (!isEmptyElement) {
while (Reader.NodeType != XmlNodeType.EndElement) {
if (Reader.NodeType == XmlNodeType.Element) {
Reader.Skip();
if (Reader.NodeType == XmlNodeType.Whitespace)
Reader.Skip();
} else
CopyXmlNode(utilWriter);
}
if (Reader.LineNumber != lineNumber)
utilWriter.AppendSpacesToLinePosition(TrueLinePosition);
CopyXmlNode(utilWriter);
}
return CopyReaderToNextElement(utilWriter, true);
}
internal bool CopyReaderToNextElement(XmlUtilWriter utilWriter, bool limitDepth)
{
bool flag = true;
int num;
if (limitDepth) {
if (Reader.NodeType == XmlNodeType.EndElement)
return true;
num = Reader.Depth;
} else
num = 0;
while (Reader.NodeType != XmlNodeType.Element && Reader.Depth >= num) {
flag = CopyXmlNode(utilWriter);
if (!flag)
break;
}
return flag;
}
internal bool SkipAndCopyReaderToNextElement(XmlUtilWriter utilWriter, bool limitDepth)
{
if (!utilWriter.IsLastLineBlank) {
Reader.Skip();
return CopyReaderToNextElement(utilWriter, limitDepth);
}
int num = limitDepth ? Reader.Depth : 0;
Reader.Skip();
int lineNumber = Reader.LineNumber;
while (!Reader.EOF) {
if (Reader.NodeType != XmlNodeType.Whitespace) {
if (Reader.LineNumber > lineNumber) {
utilWriter.SeekToLineStart();
utilWriter.AppendWhiteSpace(lineNumber + 1, 1, LineNumber, TrueLinePosition);
}
break;
}
Reader.Read();
}
while (!Reader.EOF && Reader.NodeType != XmlNodeType.Element && Reader.Depth >= num) {
CopyXmlNode(utilWriter);
}
return !Reader.EOF;
}
private void CopyElement(XmlUtilWriter utilWriter)
{
int depth = Reader.Depth;
bool isEmptyElement = Reader.IsEmptyElement;
CopyXmlNode(utilWriter);
while (Reader.Depth > depth) {
CopyXmlNode(utilWriter);
}
if (!isEmptyElement)
CopyXmlNode(utilWriter);
}
internal bool CopyXmlNode(XmlUtilWriter utilWriter)
{
string text = null;
int fromLineNumber = -1;
int fromLinePosition = -1;
int num = 0;
int num2 = 0;
int num3 = 0;
int num4 = 0;
if (utilWriter.TrackPosition) {
num = Reader.LineNumber;
num2 = Reader.LinePosition;
num3 = utilWriter.LineNumber;
num4 = utilWriter.LinePosition;
}
switch (Reader.NodeType) {
case XmlNodeType.Whitespace:
utilWriter.Write(Reader.Value);
break;
case XmlNodeType.Element:
text = (Reader.IsEmptyElement ? "/>" : ">");
fromLineNumber = Reader.LineNumber;
fromLinePosition = Reader.LinePosition + Reader.Name.Length;
utilWriter.Write('<');
utilWriter.Write(Reader.Name);
while (Reader.MoveToNextAttribute()) {
int lineNumber2 = Reader.LineNumber;
int linePosition2 = Reader.LinePosition;
utilWriter.AppendRequiredWhiteSpace(fromLineNumber, fromLinePosition, lineNumber2, linePosition2);
int num7 = utilWriter.Write(Reader.Name);
num7 += utilWriter.Write('=');
num7 += utilWriter.AppendAttributeValue(Reader);
fromLineNumber = lineNumber2;
fromLinePosition = linePosition2 + num7;
}
break;
case XmlNodeType.EndElement:
text = ">";
fromLineNumber = Reader.LineNumber;
fromLinePosition = Reader.LinePosition + Reader.Name.Length;
utilWriter.Write("</");
utilWriter.Write(Reader.Name);
break;
case XmlNodeType.Comment:
utilWriter.AppendComment(Reader.Value);
break;
case XmlNodeType.Text:
utilWriter.AppendEscapeTextString(Reader.Value);
break;
case XmlNodeType.XmlDeclaration:
text = "?>";
fromLineNumber = Reader.LineNumber;
fromLinePosition = Reader.LinePosition + 3;
utilWriter.Write("<?xml");
while (Reader.MoveToNextAttribute()) {
int lineNumber = Reader.LineNumber;
int linePosition = Reader.LinePosition;
utilWriter.AppendRequiredWhiteSpace(fromLineNumber, fromLinePosition, lineNumber, linePosition);
int num6 = utilWriter.Write(Reader.Name);
num6 += utilWriter.Write('=');
num6 += utilWriter.AppendAttributeValue(Reader);
fromLineNumber = lineNumber;
fromLinePosition = linePosition + num6;
}
Reader.MoveToElement();
break;
case XmlNodeType.SignificantWhitespace:
utilWriter.Write(Reader.Value);
break;
case XmlNodeType.ProcessingInstruction:
utilWriter.AppendProcessingInstruction(Reader.Name, Reader.Value);
break;
case XmlNodeType.EntityReference:
utilWriter.AppendEntityRef(Reader.Name);
break;
case XmlNodeType.CDATA:
utilWriter.AppendCData(Reader.Value);
break;
case XmlNodeType.DocumentType: {
int num5 = utilWriter.Write("<!DOCTYPE");
utilWriter.AppendRequiredWhiteSpace(_lastLineNumber, _lastLinePosition + num5, Reader.LineNumber, Reader.LinePosition);
utilWriter.Write(Reader.Name);
string text2 = null;
if (Reader.HasValue)
text2 = Reader.Value;
fromLineNumber = Reader.LineNumber;
fromLinePosition = Reader.LinePosition + Reader.Name.Length;
if (Reader.MoveToFirstAttribute()) {
utilWriter.AppendRequiredWhiteSpace(fromLineNumber, fromLinePosition, Reader.LineNumber, Reader.LinePosition);
string name = Reader.Name;
utilWriter.Write(name);
utilWriter.AppendSpace();
utilWriter.AppendAttributeValue(Reader);
Reader.MoveToAttribute(0);
if (name == "PUBLIC") {
Reader.MoveToAttribute(1);
utilWriter.AppendSpace();
utilWriter.AppendAttributeValue(Reader);
Reader.MoveToAttribute(1);
}
}
if (!string.IsNullOrEmpty(text2)) {
utilWriter.Write(" [");
utilWriter.Write(text2);
utilWriter.Write(']');
}
utilWriter.Write('>');
break;
}
}
bool result = Reader.Read();
XmlNodeType nodeType = Reader.NodeType;
if (text != null) {
int positionOffset = GetPositionOffset(nodeType);
int lineNumber3 = Reader.LineNumber;
int toLinePosition = Reader.LinePosition - positionOffset - text.Length;
utilWriter.AppendWhiteSpace(fromLineNumber, fromLinePosition, lineNumber3, toLinePosition);
utilWriter.Write(text);
}
if (utilWriter.TrackPosition) {
_lastLineNumber = num - num3 + utilWriter.LineNumber;
if (num3 == utilWriter.LineNumber) {
_lastLinePosition = num2 - num4 + utilWriter.LinePosition;
return result;
}
_lastLinePosition = utilWriter.LinePosition;
}
return result;
}
private string RetrieveFullOpenElementTag()
{
StringBuilder stringBuilder = new StringBuilder(64);
stringBuilder.Append('<');
stringBuilder.Append(Reader.Name);
while (Reader.MoveToNextAttribute()) {
stringBuilder.Append(' ');
stringBuilder.Append(Reader.Name);
stringBuilder.Append('=');
stringBuilder.Append('"');
stringBuilder.Append(Reader.Value);
stringBuilder.Append('"');
}
stringBuilder.Append('>');
return stringBuilder.ToString();
}
internal string UpdateStartElement(XmlUtilWriter utilWriter, string updatedStartElement, bool needsChildren, int linePosition, int indent)
{
string result = null;
bool flag = false;
string name = Reader.Name;
if (Reader.IsEmptyElement) {
if ((updatedStartElement == null) & needsChildren)
updatedStartElement = RetrieveFullOpenElementTag();
flag = (updatedStartElement != null);
}
if (updatedStartElement == null)
CopyXmlNode(utilWriter);
else {
string str = "</" + name + ">";
string text = FormatXmlElement(updatedStartElement + str, linePosition, indent, true);
int num = text.LastIndexOf('\n') + 1;
string s;
if (flag) {
result = text.Substring(num);
s = text.Substring(0, num);
} else
s = text.Substring(0, num - 2);
utilWriter.Write(s);
Reader.Read();
}
return result;
}
private void ResetCachedStringWriter()
{
if (_cachedStringWriter == null)
_cachedStringWriter = new StringWriter(new StringBuilder(64), CultureInfo.InvariantCulture);
else
_cachedStringWriter.GetStringBuilder().Length = 0;
}
internal string CopySection()
{
ResetCachedStringWriter();
WhitespaceHandling whitespaceHandling = Reader.WhitespaceHandling;
Reader.WhitespaceHandling = WhitespaceHandling.All;
XmlUtilWriter xmlUtilWriter = new XmlUtilWriter(_cachedStringWriter, false);
CopyElement(xmlUtilWriter);
Reader.WhitespaceHandling = whitespaceHandling;
if (whitespaceHandling == WhitespaceHandling.None && Reader.NodeType == XmlNodeType.Whitespace)
Reader.Read();
xmlUtilWriter.Flush();
return ((StringWriter)xmlUtilWriter.Writer).ToString();
}
internal static string FormatXmlElement(string xmlElement, int linePosition, int indent, bool skipFirstIndent)
{
XmlParserContext context = new XmlParserContext(null, null, null, XmlSpace.Default, Encoding.Unicode);
XmlTextReader xmlTextReader = new XmlTextReader(xmlElement, XmlNodeType.Element, context);
XmlUtilWriter xmlUtilWriter = new XmlUtilWriter(new StringWriter(new StringBuilder(64), CultureInfo.InvariantCulture), false);
bool flag = false;
bool flag2 = false;
int num = 0;
while (xmlTextReader.Read()) {
XmlNodeType nodeType = xmlTextReader.NodeType;
int num2;
if (flag2) {
xmlUtilWriter.Flush();
num2 = num - ((StringWriter)xmlUtilWriter.Writer).GetStringBuilder().Length;
} else
num2 = 0;
switch (nodeType) {
case XmlNodeType.Element:
case XmlNodeType.CDATA:
case XmlNodeType.Comment:
case XmlNodeType.EndElement:
if (!skipFirstIndent && !flag2) {
xmlUtilWriter.AppendIndent(linePosition, indent, xmlTextReader.Depth, flag);
if (flag) {
xmlUtilWriter.Flush();
num = ((StringWriter)xmlUtilWriter.Writer).GetStringBuilder().Length;
}
}
break;
}
flag2 = false;
switch (nodeType) {
case XmlNodeType.SignificantWhitespace:
xmlUtilWriter.Write(xmlTextReader.Value);
break;
case XmlNodeType.CDATA:
xmlUtilWriter.AppendCData(xmlTextReader.Value);
break;
case XmlNodeType.ProcessingInstruction:
xmlUtilWriter.AppendProcessingInstruction(xmlTextReader.Name, xmlTextReader.Value);
break;
case XmlNodeType.Comment:
xmlUtilWriter.AppendComment(xmlTextReader.Value);
break;
case XmlNodeType.Text:
xmlUtilWriter.AppendEscapeTextString(xmlTextReader.Value);
flag2 = true;
break;
case XmlNodeType.Element: {
xmlUtilWriter.Write('<');
xmlUtilWriter.Write(xmlTextReader.Name);
num2 += xmlTextReader.Name.Length + 2;
int attributeCount = xmlTextReader.AttributeCount;
for (int i = 0; i < attributeCount; i++) {
bool flag3;
if (num2 > 60) {
xmlUtilWriter.AppendIndent(linePosition, indent, xmlTextReader.Depth - 1, true);
num2 = indent;
flag3 = false;
xmlUtilWriter.Flush();
num = ((StringWriter)xmlUtilWriter.Writer).GetStringBuilder().Length;
} else
flag3 = true;
xmlTextReader.MoveToNextAttribute();
xmlUtilWriter.Flush();
int length = ((StringWriter)xmlUtilWriter.Writer).GetStringBuilder().Length;
if (flag3)
xmlUtilWriter.AppendSpace();
xmlUtilWriter.Write(xmlTextReader.Name);
xmlUtilWriter.Write('=');
xmlUtilWriter.AppendAttributeValue(xmlTextReader);
xmlUtilWriter.Flush();
num2 += ((StringWriter)xmlUtilWriter.Writer).GetStringBuilder().Length - length;
}
xmlTextReader.MoveToElement();
if (xmlTextReader.IsEmptyElement)
xmlUtilWriter.Write(" />");
else
xmlUtilWriter.Write('>');
break;
}
case XmlNodeType.EndElement:
xmlUtilWriter.Write("</");
xmlUtilWriter.Write(xmlTextReader.Name);
xmlUtilWriter.Write('>');
break;
case XmlNodeType.EntityReference:
xmlUtilWriter.AppendEntityRef(xmlTextReader.Name);
break;
}
flag = true;
skipFirstIndent = false;
}
xmlUtilWriter.Flush();
return ((StringWriter)xmlUtilWriter.Writer).ToString();
}
}
}