Ejemplo n.º 1
0
        /// <summary>
        /// Treats all include tags, if there are bad reference on document, catches exception and tries to find fallback, which is treated as document.
        /// </summary>
        /// <param name="includeNodes">Nodes, which will be replace</param>
        /// <param name="document">Document, which contains includeNodes</param>
        /// <param name="absoluteUri">Uri of document</param>
        /// <param name="nsPrefix">Prefix of include namespace</param>
        /// <param name="nsm">Namespace Manager of document</param>
        /// <returns></returns>
        bool TreatIncludes(XmlElement[] includeNodes, XmlDocument document, string absoluteUri, string nsPrefix, XmlNamespaceManager nsm)
        {
            foreach (var includeElement in includeNodes)
            {
                var valueOfXPoiner = includeElement.GetAttribute(atXPointer);
                var valueOfHref    = includeElement.GetAttribute(atHref);

                if (string.IsNullOrEmpty(valueOfHref)) // There must be xpointer Attribute, if not, fatal error..
                {
                    if (string.IsNullOrEmpty(valueOfXPoiner))
                    {
                        PhpLibXml.IssueXmlError(_ctx, PhpLibXml.LIBXML_ERR_WARNING, 0, 0, 0, $"DOMDocument::xinclude(): detected a local recursion with no xpointer in {absoluteUri} in {_ctx.MainScriptFile.Path}", absoluteUri);
                        return(true);
                    }
                    _documents.Push(document);
                    var includeUri = includeElement.BaseURI + valueOfXPoiner;
                    if (_references.ContainsKey(includeUri)) // fatal error, cycle recursion
                    {
                        PhpLibXml.IssueXmlError(_ctx, PhpLibXml.LIBXML_ERR_WARNING, 0, 0, 0, $"DOMDocument::xinclude(): detected a recursion in {absoluteUri} in {_ctx.MainScriptFile.Path}", absoluteUri);
                        return(true);
                    }
                    _references[absoluteUri] = includeUri;

                    IncludeXml(includeElement.BaseURI, includeElement, null, valueOfXPoiner);
                    return(false);
                }

                // Resolving absolute and relative uri...
                string uri = UriResolver(valueOfHref, Path.GetDirectoryName(absoluteUri));

                // Resolving type of parsing.
                string typeOfParse = includeElement.GetAttribute(atParse);
                try
                {
                    if (string.Equals(typeOfParse, "text", StringComparison.OrdinalIgnoreCase))
                    {
                        _documents.Push(document);
                        IncludeText(uri, includeElement);
                    }
                    else
                    {
                        if (_references.ContainsKey(uri + valueOfXPoiner)) // fatal error, cycle recursion
                        {
                            PhpLibXml.IssueXmlError(_ctx, PhpLibXml.LIBXML_ERR_WARNING, 0, 0, 0, $"DOMDocument::xinclude(): detected a recursion in {absoluteUri} in {_ctx.MainScriptFile.Path}", absoluteUri);
                            //return true;
                        }
                        else
                        {
                            _documents.Push(document);
                            _references[absoluteUri] = uri + valueOfXPoiner;
                            IncludeXml(uri, includeElement, null, string.IsNullOrEmpty(valueOfXPoiner) ? null : valueOfXPoiner);
                        }
                    }
                }
                catch (System.IO.FileNotFoundException)
                {
                    PhpLibXml.IssueXmlError(_ctx, PhpLibXml.LIBXML_ERR_WARNING, 0, 0, 0, $"DOMDocument::xinclude(): I/O warning : failed to load external entity &quot;{absoluteUri}&quot; in {_ctx.MainScriptFile.Path}", absoluteUri);
                    _documents.Pop();
                    XmlElement[] fallbacks = includeElement.GetElementsByTagName(nsPrefix + ":" + etFallback).OfType <XmlElement>().ToArray <XmlElement>();

                    if (fallbacks.Length > 1) // fatal error
                    {
                        PhpLibXml.IssueXmlError(_ctx, PhpLibXml.LIBXML_ERR_WARNING, 0, 0, 0, $"DOMDocument::xinclude(): include has multiple fallback children in {_ctx.MainScriptFile.Path}", _ctx.MainScriptFile.Path);
                        return(true);
                    }

                    if (fallbacks.Length == 1)
                    {
                        XmlElement[] includes = fallbacks[0].SelectNodes($".//{nsPrefix}:{etInclude}[ not( descendant::{nsPrefix}:{etFallback} ) ]", nsm).OfType <XmlElement>().ToArray();

                        while (fallbacks[0].ChildNodes.Count != 0)
                        {
                            includeElement.ParentNode.InsertAfter(fallbacks[0].LastChild, includeElement);
                        }

                        TreatIncludes(includes, document, absoluteUri, nsPrefix, nsm);

                        includeElement.ParentNode.RemoveChild(includeElement);
                    }
                    else // error missing fallback
                    {
                        PhpLibXml.IssueXmlError(_ctx, PhpLibXml.LIBXML_ERR_WARNING, 0, 0, 0, $"DOMDocument::xinclude(): could not load {absoluteUri}, and no fallback was found in {_ctx.MainScriptFile.Path}", absoluteUri);
                        return(true);
                    }
                }
                _references = new Dictionary <string, string>();
            }
            return(false);
        }