Project

Profile

Help

How to implement an InputXmlResolver for Xslt30Transformer on .NET so that local files can't be accessed?

Added by Martin Honnen over 6 years ago

https://www.saxonica.com/html/documentation/dotnetdoc/Saxon/Api/Xslt30Transformer.html#InputXmlResolver allows me to assign an @XmlResolver@ "to be used at run-time to resolve and dereference URIs supplied to the doc() and document() functions".

How would I have to implement such an @XmlResolver@ so that @file:@ URIs don't work?

I have tried to subclass the @XmlUrlResolver@ as follows:


    class CustomResolver : XmlUrlResolver
    {
        public override object GetEntity(Uri absoluteUri, string role, Type ofObjectToReturn)
        {
            if (absoluteUri.IsFile)
            {
                return null;
            }
            return base.GetEntity(absoluteUri, role, ofObjectToReturn);
        }

        public override Task GetEntityAsync(Uri absoluteUri, string role, Type ofObjectToReturn)
        {
            if (absoluteUri.IsFile)
            {
                return null;
            }
            return base.GetEntityAsync(absoluteUri, role, ofObjectToReturn);
        }

        public override Uri ResolveUri(Uri baseUri, string relativeUri)
        {
            return base.ResolveUri(baseUri, relativeUri);
        }
    }

that is, for the @GetEntity@ method the custom resolver returns @null@ instead of a @Stream@. However, that doesn't seem to change Saxon's (tested with NuGet package of Saxon 9.8.0.6 HE) behaviour at all, neither @document@ nor @doc-available@ nor @doc@ calls show any difference to a normal XmlUrlResolver. On the other hand, if I pass such a CustomResolver to Microsoft's @XslCompiledTransform@, it throws an error when encountering a @document@ call with a @file:@ URI.

Test code I used:


       static void TestSaxon(string inputUri, string sheetUri, XmlResolver resolver)
        {
            Processor processor = new Processor();

            using (XmlReader sheetReader = XmlReader.Create(sheetUri))
            {
                Xslt30Transformer transformer = processor.NewXsltCompiler().Compile(XmlReader.Create(sheetUri)).Load30();
                transformer.InputXmlResolver = resolver;
                Console.WriteLine("resolver: {0}", resolver.GetType().Name);
                using (XmlReader inputReader = XmlReader.Create(inputUri))
                {
                    DocumentBuilder docBuilder = processor.NewDocumentBuilder();
                    XdmNode inputNode = docBuilder.Build(inputReader);
                    transformer.ApplyTemplates(inputNode, processor.NewSerializer(Console.Out));
                }
            }
        }

Run with


           TestSaxon("../../available-tests/dummy-input1.xml", "../../available-tests/available-test1.xsl", new XmlUrlResolver());
            Console.WriteLine();
            TestSaxon("../../available-tests/dummy-input1.xml", "../../available-tests/available-test1.xsl", new CustomResolver());
            Console.WriteLine();

where @dummy-input1.xml@ can be any XML input and the stylesheet is




    
    
    
    
    
    
    
        
            
                
                    
                        
                    
                
            
            
                
                    
                        
                    
                
            
        
    
    

If @test-doc1.xml@ and @test-text1.txt@ exist and the files @test-doc2.xml@ and @test-text2.txt@ don't exist then the result for Saxon is the same for both method calls:

resolver: XmlUrlResolver


   
      example content 1
   
   
   Test text doc 1. Example text 1.
   


resolver: CustomResolver


   
      example content 1
   
   
   Test text doc 1. Example text 1.
   

So that approach doesn't in any restrict the use of @file:@ URLs? How would I have to implement the @InputXmlResolver@ to prevent file URL access? Or do I have to use some other setting or property?


Please register to reply