using System;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
namespace Wayne.Lib
{
///
/// A util class to create and classes resistant to XXE attacks.>
///
///
/// https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet
///
public static class Xml
{
#region XmlDocument Constructors
///
/// Initializes a new instance of the class.
///
public static XmlDocument Document()
{
return FixDocument(new XmlDocument());
}
///
/// Initializes a new instance of the class with the specified .
///
public static XmlDocument Document(XmlNameTable nt)
{
return FixDocument(new XmlDocument(nt));
}
#endregion
#region XmlReader Constructors
///
/// Replace Create method. Creates a new instance using the specified with default settings.
///
public static XmlReader Reader(Stream input)
{
return XmlReader.Create(input, FixSettings());
}
///
/// Replace Create method. Creates a new instance using the specified and .
///
public static XmlReader Reader(Stream input, XmlReaderSettings settings)
{
return XmlReader.Create(input, FixSettings(settings));
}
///
/// Replace Create method. Creates a new instance by using the specified .
///
public static XmlReader Reader(TextReader input)
{
return XmlReader.Create(input, FixSettings());
}
///
/// Replace Create method. Creates a new instance by using the specified and .
///
public static XmlReader Reader(TextReader input, XmlReaderSettings settings)
{
return XmlReader.Create(input, FixSettings(settings));
}
#endregion
#region GetEncoding
///
/// Gets the encoded of the undeling xml data. Uses to read the data.
///
public static string GetEncodedString(byte[] data, int offset, int length)
{
string ret = null;
System.Text.Encoding encoding = GetEncoding(data, offset, length);
if (encoding != null && encoding.CodePage != 0)
{
ret = encoding.GetString(data, offset, length);
}
else
{
ret = System.Text.Encoding.UTF8.GetString(data, offset, length);
}
return ret;
}
#endregion
#region Serialization
///
/// Serializes a class instance to .
///
public static string Serialize(T instance) where T : class
{
var xmlWriterSettings = new XmlWriterSettings
{
Encoding = new UTF8Encoding(false)
};
using (var stream = new MemoryStream())
using (var writer = XmlWriter.Create(stream, xmlWriterSettings))
{
var serializer = new XmlSerializer(typeof(T));
serializer.Serialize(writer, instance);
return System.Text.Encoding.UTF8.GetString(stream.ToArray(), 0, (int)stream.Length);
}
}
///
/// Deserialize a xml .
///
public static T Deserialize(string xml) where T : class
{
using (var reader = new StringReader(xml))
{
var serializer = new XmlSerializer(typeof(T));
return serializer.Deserialize(reader) as T;
}
}
///
/// Deserializes XmlDocument object to Serializable object of type T.
///
/// Serializable object type as output type.
/// XmlDocument object to be deserialized.
/// Deserialized serializable object of type T.
public static T Deserialize(XmlDocument document) where T : class
{
using (var reader = new XmlNodeReader(document))
{
var serializer = new XmlSerializer(typeof(T));
return serializer.Deserialize(reader) as T;
}
}
#endregion
#region Implementation
private static System.Text.Encoding GetEncoding(byte[] data, int offset, int length)
{
System.Text.Encoding encoding = null;
using (var stream = new MemoryStream(data, offset, length))
{
using (var reader = FixTextReader(new XmlTextReader(stream)))
{
reader.Read();
encoding = reader.Encoding;
}
}
return encoding;
}
private static XmlDocument FixDocument(XmlDocument document)
{
document.XmlResolver = null; // Setting XmlResolver to NULL disables DTDs - Its NOT null by default.
return document;
}
private static XmlTextReader FixTextReader(XmlTextReader reader)
{
#if WindowsCE || OldFramework //Dtd processing is not supprted in .Net Compact Framework
#else
reader.DtdProcessing = DtdProcessing.Prohibit; // Needed because the default is Parse!!
#endif
return reader;
}
private static XmlReaderSettings FixSettings()
{
return FixSettings(null);
}
private static XmlReaderSettings FixSettings(XmlReaderSettings settings)
{
if (settings == null)
{
settings = new XmlReaderSettings();
}
#if WindowsCE || OldFramework //Dtd processing is not supprted in .Net Compact Framework
#else
settings.DtdProcessing = DtdProcessing.Prohibit; // Needed because the default is Parse!!
#endif
return settings;
}
#endregion
}
}