简体   繁体   中英

Error 403 (Forbidden) on the DTD while opening a SVG with our application

In our C# application, sometimes the app needs to open a svg file. To do so, the following code is used:

XmlReaderSettings settings = new XmlReaderSettings();
settings.ProhibitDtd = false;
settings.ValidationType = ValidationType.None;
XmlReader xr = XmlReader.Create(serverMainPath + @"/path/to/svg/file.svg", settings);
XmlDocument xd = new XmlDocument();
_nmsm = new XmlNamespaceManager(xd.NameTable);
_nmsm.AddNamespace("svg", "http://www.w3.org/2000/svg");
_nmsm.AddNamespace("v", "http://schemas.microsoft.com/visio/2003/SVGExtensions/");
xd.Load(xr);

The standard svg we're using starts with (and as far as I know it's a valid svg):

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
    <!-- Généré par Microsoft Visio 11.0, SVG Export, v1.0 svgIncluded.svg Page-1 -->
    <svg xmlns="http://www.w3.org/2000/svg" xmlns:v="http://schemas.microsoft.com/visio/2003/SVGExtensions/" width="8.26772in" height="11.6929in" viewBox="0 0 595.276 841.889" xml:space="preserve" color-interpolation-filters="sRGB" class="st23" >

And it worked just fine during the last 6 months. But since one or two weeks, this code sometimes produced the following error:

Server Error in '/ourApp' Application.
--------------------------------------------------------------------------------

The remote server returned an error: (403) Forbidden. 
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. 

Exception Details: System.Net.WebException: The remote server returned an error: (403) Forbidden.

Source Error: 

Line 40:                 _nmsm.AddNamespace("svg", "http://www.w3.org/2000/svg");
Line 41:                 _nmsm.AddNamespace("v", "http://schemas.microsoft.com/visio/2003/SVGExtensions/");
Line 42:                 xd.Load(xr);


Source File: path/to/the/file/file.cs    Line: 42 

Stack Trace: 

[WebException: The remote server returned an error: (403) Forbidden.]
   System.Net.HttpWebRequest.GetResponse() +5400333
   System.Xml.XmlDownloadManager.GetNonFileStream(Uri uri, ICredentials credentials) +69
   System.Xml.XmlDownloadManager.GetStream(Uri uri, ICredentials credentials) +3929515
   System.Xml.XmlUrlResolver.GetEntity(Uri absoluteUri, String role, Type ofObjectToReturn) +54
   System.Xml.XmlTextReaderImpl.OpenStream(Uri uri) +34
   System.Xml.XmlTextReaderImpl.DtdParserProxy_PushExternalSubset(String systemId, String publicId) +380

[XmlException: An error has occurred while opening external DTD 'http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd': The remote server returned an error: (403) Forbidden.]
   System.Xml.XmlTextReaderImpl.Throw(Exception e) +76
   System.Xml.XmlTextReaderImpl.DtdParserProxy_PushExternalSubset(String systemId, String publicId) +513
   System.Xml.DtdParserProxy.System.Xml.IDtdParserAdapter.PushExternalSubset(String systemId, String publicId) +16
   System.Xml.DtdParser.ParseExternalSubset() +21
   System.Xml.DtdParser.ParseInDocumentDtd(Boolean saveInternalSubset) +4017069
   System.Xml.DtdParser.Parse(Boolean saveInternalSubset) +54
   System.Xml.DtdParserProxy.Parse(Boolean saveInternalSubset) +31
   System.Xml.XmlTextReaderImpl.ParseDoctypeDecl() +254
   System.Xml.XmlTextReaderImpl.ParseDocumentContent() +451
   System.Xml.XmlTextReaderImpl.Read() +151
   System.Xml.XmlLoader.LoadNode(Boolean skipOverWhitespace) +58
   System.Xml.XmlLoader.LoadDocSequence(XmlDocument parentDoc) +20
   System.Xml.XmlLoader.Load(XmlDocument doc, XmlReader reader, Boolean preserveWhitespace) +129
   System.Xml.XmlDocument.Load(XmlReader reader) +108
   OurMethod(params) in path/to/the/file/file.cs:42
   StackTrace in our App.

--------------------------------------------------------------------------------
Version Information: Microsoft .NET Framework Version:2.0.50727.3643; ASP.NET Version:2.0.50727.3634 

At first I thought it was due to a change in our internet proxy policy, but since it has been spotted on another deployment of the app which is behind a different proxy, I highly doubt that.

The error seems to be more or less random, sometimes it'll work, sometimes it won't. I'm just clueless at why it would act this way.

The question is: Do you have any idea why would this happen? If yes do you know how to fix it? If no, any idea of a workaround?

In the end, I used a homemade class to do the job. It's inspired from the MSDN implementation of the XmlUrlResolver extension . Thanks to @mzjn for pointing out a link that pointed out to the MSDN ressource.

using System;
using System.Net;
using System.Net.Cache;
using System.Xml;
using System.IO;

namespace My.Nasmespace.Class.IO
{
    class XmlExtendedResolver : XmlUrlResolver
    {
        bool enableHttpCaching;
        ICredentials credentials;
        private string localServerPath;
        //resolve ressource from localServerPath if it's possible
        //resolve resources from cache (if possible) when enableHttpCaching is set to true 
        //resolve resources from source when enableHttpcaching is set to false  
        public XmlExtendedResolver(bool enableHttpCaching, string serverPath)
        {
            this.enableHttpCaching = enableHttpCaching;
            localServerPath = serverPath;
        }

        public override ICredentials Credentials
        {
            set
            {
                credentials = value;
                base.Credentials = value;
            }
        }

        public override object GetEntity(Uri absoluteUri, string role, Type ofObjectToReturn)
        {
            if (absoluteUri == null)
            {
                throw new ArgumentNullException("absoluteUri");
            }
            //resolve resources from cache (if possible) 
            if (absoluteUri.Scheme == "http" && enableHttpCaching && (ofObjectToReturn == null || ofObjectToReturn == typeof(Stream)))
            {
                /*Try to resolve it from the local path if it exists*/
                if (!string.IsNullOrEmpty(localServerPath) && absoluteUri.AbsolutePath.EndsWith(".dtd") && !absoluteUri.AbsoluteUri.StartsWith(localServerPath))
                {
                    try { 
                        return GetEntity(new Uri(localServerPath + "/Xml/" + absoluteUri.Segments[absoluteUri.Segments.Length-1]), role, ofObjectToReturn);
                    } catch (FileNotFoundException){
                         //Fail silently to go to the web request.
                    }
                }
                WebRequest webReq = WebRequest.Create(absoluteUri);
                webReq.CachePolicy = new    HttpRequestCachePolicy(HttpRequestCacheLevel.Default);
                if (credentials != null)
                {
                    webReq.Credentials = credentials;
                }
                WebResponse resp = webReq.GetResponse();
                return resp.GetResponseStream();
            }
            //otherwise use the default behavior of the XmlUrlResolver class (resolve resources from source) 
        else
            {
                return base.GetEntity(absoluteUri, role, ofObjectToReturn);
            }
        }
    }
}

i think you have to try some logics around this , i just buffered from some where

request.UserAgent = "userAgents";
request.Accept = "*/*";

and

request.Credentials = new NetworkCredentials("username", "password");

or 

 request.Credentials = CredentialCache.DefaultCredentials;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM