XMLPrime XLST.Compile throwing a null exception - c#

public static SqlXml XMLPrimeTransform(SqlXml inputDataXML, SqlXml inputTrasnformXML)
{
MemoryStream ms = new MemoryStream();
XmlReader inxml = inputDataXML.CreateReader();
XmlReader intrans = inputTrasnformXML.CreateReader();
XmlReaderSettings xmlreadersettings = new XmlReaderSettings { NameTable = intrans.NameTable };
XdmDocument document= new XdmDocument(inxml);
XmlPrime.XsltSettings xsltSettings = new XmlPrime.XsltSettings(intrans.NameTable) { ContextItemType = XdmType.Node };
var xslt = Xslt.Compile(intrans, xsltSettings);
//var xslt = Xslt.Compile(inputTrasnformXML.CreateReader());
var contextItem = document.CreateNavigator();
var settings = new DynamicContextSettings { ContextItem = contextItem };
xslt.ApplyTemplates(settings, ms);
return new SqlXml(ms);
}
I wrote the above code function to apply a xlst 2.0 stylesheet to xml and return the XML.
I tried to modify the XMLPrime example, but for some reason the line:
var xslt = Xslt.Compile(intrans, xsltSettings);
is throwing a NullReferenceException. Both intrans and xsltSettings are not null. Anyone have any luck trying to accomplish this with XMLPrime or any other library?

It may be a bug specific to the stylesheet you are loading. Try using a minimal stylesheet to see if that is the case. If you think it is a bug in XmlPrime, contact the developers and supply a Visual Studio solution which reproduces the problem.

Related

XXE: Improper Restriction of XML External Entity Reference With XDocument

So I am running into an issue when I run a security scan on my application. It turns out that I am failing to protect against XXE.
Here is a short snippet showing the offending code:
static void Main()
{
string inp = Console.ReadLine();
string xmlStr = ""; //This has a value that is much too long to put into a single post
if (!string.IsNullOrEmpty(inp))
{
xmlStr = inp;
}
XmlDocument xmlDocObj = new XmlDocument {XmlResolver = null};
xmlDocObj.LoadXml(xmlStr);
XmlNodeList measureXmlNodeListObj = xmlDocObj.SelectNodes("REQ/MS/M");
foreach (XmlNode measureXmlNodeObj in measureXmlNodeListObj)
{
XmlNode detailXmlNodeListObj = xmlDocObj.SelectSingleNode("REQ/DTD");
string measureKey = measureXmlNodeObj.Attributes["KY"].Value;
if (detailXmlNodeListObj.Attributes["MKY"].Value ==
measureKey) //Checking if selected MeasureKey is same
{
XmlNode filerNode = measureXmlNodeObj.SelectSingleNode("FS");
if (filerNode != null)
{
XDocument fixedFilterXmlObj = XDocument.Load(new StringReader(filerNode.OuterXml));
var measureFixedFilters = (from m in fixedFilterXmlObj.Element("FS").Elements("F")
select m).ToList();
foreach (var fixedFilter in measureFixedFilters)
{
var fixedFilterValues = (from m in fixedFilter.Elements("VS").Elements("V")
select m.Attribute("DESC").Value).ToList();
foreach (var value in fixedFilterValues)
{
Console.WriteLine(value.Trim());
}
}
}
}
}
Console.ReadLine();
}
According to Veracode, the line that unsafe is XDocument fixedFilterXmlObj = XDocument.Load(new StringReader(filerNode.OuterXml));
But it seems like according to Owsap, it should be safe:
Both the XElement and XDocument objects in the System.Xml.Linq library
are safe from XXE injection by default. XElement parses only the
elements within the XML file, so DTDs are ignored altogether.
XDocument has DTDs disabled by default, and is only unsafe if
constructed with a different unsafe XML parser.
So it seems like I am making the mistake of using an usafe XML Parser, opening XDocument to XXE.
I found a unit test that replicates the issue and also has a safe usage of XDocument but I can't seem to find what exactly my code is unsafe, because I do not use:
XmlReaderSettings settings = new XmlReaderSettings();
settings.DtdProcessing = DtdProcessing.Parse; // unsafe!
You can run my code to replicate the issue, but you should replace the line with the empty xmlStr with this value: here (too large for a single post)
I'm not sure how or why this works, but it does:
XDocument fixedFilterXmlObj;
using (XmlNodeReader nodeReader = new XmlNodeReader(filerNode))
{
nodeReader.MoveToContent();
fixedFilterXmlObj = XDocument.Load(nodeReader);
}

Cannot fix Improper Restriction of XML External Entity Reference error

I have changed the code when trying to fix Veracode error for Improper Restriction of XML External Entity Reference, but it did not fix it.
Here is the code I have now:
XmlDocument xmlDoc=new XmlDocument();
using (System.IO.MemoryStream xmlstream = new System.IO.MemoryStream
(Encoding.Default.GetBytes(dsEQ.GetXml().ToString())))
{
XmlReaderSettings settings = new XmlReaderSettings();
settings.DtdProcessing = DtdProcessing.Prohibit;
using (XmlReader xmlreader = XmlReader.Create(xmlstream, settings))
{
try
{
xmlDoc.Load(xmlreader);
}
catch(XmlException e)
{
Connection.LogError(e.ToString(), e.Message);
}
}
}
However, Veracode still point out on this section of code with the same error message.
Is there anything else that I should do to fix it? We do not have any external references, everything is through intranet.
Set XmlResolver to null:
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.XmlResolver = null;
Set XmlResolver = null will fix the issue.
static void LoadXML()
{
string xml = "<?xml version=\"1.0\" ?><!DOCTYPE doc
[<!ENTITY win SYSTEM \"file:///C:/Users/user/Documents/testdata2.txt\">]
><doc>&win;</doc>";
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.XmlResolver = null; // Setting this to NULL disables DTDs - Its NOT null by default.
xmlDoc.LoadXml(xml);
Console.WriteLine(xmlDoc.InnerText);
Console.ReadLine();
}
Please go through below link for more information.
XML External Entity (XXE) Prevention Cheat Sheet
The original answer works for xmlDoc.Load(xmlreader).
The second question is a different context and requires different technology.
using (System.IO.StringReader rxml = new System.IO.StringReader(myxmltext))
{
XmlSerializer serializer = new XmlSerializer(typeof(MenuConfigBase));
using (XmlTextReader xr = new XmlTextReader(rxml))
{
xr.XmlResolver = null;
var cfgBase = (MenuConfigBase)serializer.Deserialize(xr);
}
}

Can't set settings on XmlTextReader?

I need to set the MaxCharactersFromEntities on the XmlTextReader, this is my code so far :
xmlDocument = new XmlDocument();
xmlTextReader = new XmlTextReader(fileInfo.FullName);
xmlTextReader.Settings = new XmlReaderSettings();
xmlTextReader.Settings.MaxCharactersFromEntities = 0;
var vr = new XmlValidatingReader(xmlTextReader);
vr.ValidationType = ValidationType.None;
vr.EntityHandling = EntityHandling.ExpandEntities;
xmlDocument.Load(vr);
The Settings property is read-only so it canĀ“t be set and its null? How is this supposed to work?
You're supposed to pass XmlReaderSettings instance upon construction of the XmlReader instance in the first place, rather than updating the reader's Settings property later -which is impossible as the property doesn't have setter- :
var xmlDocument = new XmlDocument();
//create XmlReaderSettings first
var settings = new XmlReaderSettings();
settings.MaxCharactersFromEntities = 80; //0 doesn't make sense here, as it's the default value
//create XmlReader later, passing the pre-defined settings
var xmlReader = XmlReader.Create(fileInfo.FullName, settings);
//the rest of the codes remain untouched
var vr = new XmlValidatingReader(xmlReader);
vr.ValidationType = ValidationType.None;
vr.EntityHandling = EntityHandling.ExpandEntities;
xmlDocument.Load(vr);
You should use XmlReader.Create(string, XmlReaderSettings) instead to create your reader instance.
From the MSDN reference:
Starting with the .NET Framework 2.0, we recommend that you use the
System.Xml.XmlReader class instead.
The idea is to use the Create(...) factory method of the base class XmlReader instead of instantiating the derived class directly. Also see the factory method pattern for additional info.
The rest of your code remains unaffected since XmlValidatingReader takes an XmlReader in the constructor.
So you should end up with somehting like:
xmlDocument = new XmlDocument();
XmlReaderSettings settings = new XmlReaderSettings();
settings.MaxCharactersFromEntities = 0;
XmlReader reader = XmlReader.Create(fileInfo.FullName, settings);
var vr = new XmlValidatingReader(reader);
vr.ValidationType = ValidationType.None;
vr.EntityHandling = EntityHandling.ExpandEntities;
xmlDocument.Load(vr);

Problems to modify XElement after using Converter

I am creating a XElement via htmlconverter Class from OpenXML Powertools.
XElement html = HtmlConverter.ConvertToHtml(doc, settings)
Now I'm trying to add some new nodes like
html.Element("head").Add(new XElement("link",
new XAttribute("href", "stylesheet.css"),
new XAttribute("rel", "stylesheet"),
new XAttribute("type", "text/css")));
But html.Element("head") is always returning null and i get a NullReferenceException Error from Visual Studio while running in Debug Mode and i still have no idea why.
This is the code based on this article, which i am currently using in my project. I think it has to do something with the htmlconverter because it works if i create a handmade XElement.
// This example shows the simplest conversion. No images are converted.
// A cascading style sheet is not used.
byte[] byteArray = File.ReadAllBytes("Test.docx");
using (MemoryStream memoryStream = new MemoryStream())
{
memoryStream.Write(byteArray, 0, byteArray.Length);
using (WordprocessingDocument doc =
WordprocessingDocument.Open(memoryStream, true))
{
HtmlConverterSettings settings = new HtmlConverterSettings()
{
PageTitle = "My Page Title"
};
XElement html = HtmlConverter.ConvertToHtml(doc, settings);
// Note: the XHTML returned by ConvertToHtmlTransform contains objects of type
// XEntity. PtOpenXmlUtil.cs defines the XEntity class. See
// http://blogs.msdn.com/ericwhite/archive/2010/01/21/writing-entity-references-using-linq-to-xml.aspx
// for detailed explanation.
//
// If you further transform the XML tree returned by ConvertToHtmlTransform, you
// must do it correctly, or entities do not serialize properly.
File.WriteAllText("Test.html", html.ToStringNewLineOnAttributes());
}
}
You missed the namespace, try this instead:
XNamespace w = "http://www.w3.org/1999/xhtml";
var head = html.Element(w + "head");

Transforming large Xml files

I was using this extension method to transform very large xml files with an xslt.
Unfortunately, I get an OutOfMemoryException on the source.ToString() line.
I realize there must be a better way, I'm just not sure what that would be?
public static XElement Transform(this XElement source, string xslPath, XsltArgumentList arguments)
{
var doc = new XmlDocument();
doc.LoadXml(source.ToString());
var xsl = new XslCompiledTransform();
xsl.Load(xslPath);
using (var swDocument = new StringWriter(System.Globalization.CultureInfo.InvariantCulture))
{
using (var xtw = new XmlTextWriter(swDocument))
{
xsl.Transform((doc.CreateNavigator()), arguments, xtw);
xtw.Flush();
return XElement.Parse(swDocument.ToString());
}
}
}
Thoughts? Solutions? Etc.
UPDATE:
Now that this is solved, I have issues with validating the schema!
Validating large Xml files
Try this:
using System.Xml.Linq;
using System.Xml.XPath;
using System.Xml.Xsl;
static class Extensions
{
public static XElement Transform(
this XElement source, string xslPath, XsltArgumentList arguments)
{
var xsl = new XslCompiledTransform();
xsl.Load(xslPath);
var result = new XDocument();
using (var writer = result.CreateWriter())
{
xsl.Transform(source.CreateNavigator(), arguments, writer);
}
return result.Root;
}
}
BTW, new XmlTextWriter() is deprecated as of .NET 2.0. Use XmlWriter.Create() instead. Same with new XmlTextReader() and XmlReader.Create().
For large XML files you can try to use XPathDocument as suggested in Microsoft Knowledge Base article.
XPathDocument srcDoc = new XPathDocument(srcFile);
XslCompiledTransform myXslTransform = new XslCompiledTransform();
myXslTransform.Load(xslFile);
using (XmlWriter destDoc = XmlWriter.Create(destFile))
{
myXslTransform.Transform(srcDoc, destDoc);
}

Categories

Resources