2003-08-10 Atsushi Enomoto <ginga@kit.hi-ho.ne.jp>
authorAtsushi Eno <atsushieno@gmail.com>
Sun, 10 Aug 2003 07:20:07 +0000 (07:20 -0000)
committerAtsushi Eno <atsushieno@gmail.com>
Sun, 10 Aug 2003 07:20:07 +0000 (07:20 -0000)
* DTDObjectModel.cs : added XmlResolver related members. Added
  invalid entity recursion logic. Added encodingdecl check on textdecl.
* DTDValidatingReader.cs : It now implements IHasXmlParserContext.
* XmlChar.cs : IsPubidChar() should not allow TAB(&#9;).
* XmlDocumentType.cs : 1) internal CreateDocumentType() was now changed
  to receive DTDObjectModel to support other than XmlTextReader.
  2) Most of its public member is now based on DTDObjectModel.
* XmlDocument.cs : 1) Synchronous change with XmlDocumentType.
  2) ReadNode() now considers XmlParserContext's DTDObjectModel for
  other than XmlTextReader (such as XmlValidatingReader).
* XmlNode.cs : code cleanup only.
* XmlParserInput.cs : added HasPEBuffer, used to check illegal nesting.
* XmlTextReader.cs : 1) Illegal entity reference check logic was moved
  from ReadContent() to SetEntityReferenceProperties(). 2) Indentation
  change on ReadEntityReference(). 3) ReadAttribute() now checks
  reference to external entity reference. 4) Added textdecl encoding
  check. 5) DTDObjectModel fields are now set correctly. 6) added
  PERef markup nest check. 7) If PEDecl was not found, it might be WFC
  violation, not only be VC violation. 8) ReadEntityDecl() now receives
  its declared entity itself, and this method checks IsInternalSubset.
* XmlValidatingReader.cs : 1) Added GetInternalPerserContext().
  2) ValidationType.None should be the same as Auto, not DTD (in the
  future it should keep xml schema's default values).

Pending Stuff in XmlTextReader which breaks some NUnit tests;
  1) SetEntityReferenceProperies() has check for illegal references.
  2) ReadAttribute(bool) has similar check for illegal references.

svn path=/trunk/mcs/; revision=17218

mcs/class/System.XML/System.Xml/ChangeLog
mcs/class/System.XML/System.Xml/DTDObjectModel.cs
mcs/class/System.XML/System.Xml/DTDValidatingReader.cs
mcs/class/System.XML/System.Xml/XmlChar.cs
mcs/class/System.XML/System.Xml/XmlDocument.cs
mcs/class/System.XML/System.Xml/XmlDocumentType.cs
mcs/class/System.XML/System.Xml/XmlNode.cs
mcs/class/System.XML/System.Xml/XmlParserInput.cs
mcs/class/System.XML/System.Xml/XmlTextReader.cs
mcs/class/System.XML/System.Xml/XmlValidatingReader.cs

index 1df2ce94be05c91629f18d64d2df26bb5120a445..20dfffef47e5b90a18c1d559048bfc5d73b18547 100644 (file)
@@ -1,3 +1,33 @@
+2003-08-10  Atsushi Enomoto <ginga@kit.hi-ho.ne.jp>
+
+       * DTDObjectModel.cs : added XmlResolver related members. Added
+         invalid entity recursion logic. Added encodingdecl check on textdecl.
+       * DTDValidatingReader.cs : It now implements IHasXmlParserContext.
+       * XmlChar.cs : IsPubidChar() should not allow TAB(&#9;).
+       * XmlDocumentType.cs : 1) internal CreateDocumentType() was now changed
+         to receive DTDObjectModel to support other than XmlTextReader. 
+         2) Most of its public member is now based on DTDObjectModel.
+       * XmlDocument.cs : 1) Synchronous change with XmlDocumentType.
+         2) ReadNode() now considers XmlParserContext's DTDObjectModel for
+         other than XmlTextReader (such as XmlValidatingReader).
+       * XmlNode.cs : code cleanup only.
+       * XmlParserInput.cs : added HasPEBuffer, used to check illegal nesting.
+       * XmlTextReader.cs : 1) Illegal entity reference check logic was moved 
+         from ReadContent() to SetEntityReferenceProperties(). 2) Indentation
+         change on ReadEntityReference(). 3) ReadAttribute() now checks
+         reference to external entity reference. 4) Added textdecl encoding
+         check. 5) DTDObjectModel fields are now set correctly. 6) added
+         PERef markup nest check. 7) If PEDecl was not found, it might be WFC
+         violation, not only be VC violation. 8) ReadEntityDecl() now receives
+         its declared entity itself, and this method checks IsInternalSubset.
+       * XmlValidatingReader.cs : 1) Added GetInternalPerserContext().
+         2) ValidationType.None should be the same as Auto, not DTD (in the
+         future it should keep xml schema's default values).
+
+       Pending Stuff in XmlTextReader which breaks some NUnit tests;
+         1) SetEntityReferenceProperies() has check for illegal references.
+         2) ReadAttribute(bool) has similar check for illegal references.
+
 2003-08-09  Atsushi Enomoto <ginga@kit.hi-ho.ne.jp>
 
        * DTDAutomata.cs : Fixed (modified or added) TryEndElement() of choice,
index 0752f3d4fd8f1c0cfd0da38566c64be5bc36390a..1d0419cad4cc917cef14243c5e3763d300cba312 100644 (file)
@@ -8,6 +8,7 @@
 //
 using System;
 using System.Collections;
+using System.Collections.Specialized;
 using System.Globalization;
 using System.IO;
 using System.Text;
@@ -25,6 +26,7 @@ namespace Mono.Xml
                DTDEntityDeclarationCollection entityDecls;
                DTDNotationDeclarationCollection notationDecls;
                ArrayList validationErrors;
+               XmlResolver resolver;
 
                public DTDObjectModel ()
                {
@@ -55,6 +57,14 @@ namespace Mono.Xml
                        return decl.EntityValue;
                }
 
+               internal XmlResolver Resolver {
+                       get { return resolver; }
+               }
+
+               public XmlResolver XmlResolver {
+                       set { resolver = value; }
+               }
+
                private DTDAutomataFactory factory;
                public DTDAutomataFactory Factory {
                        get { return factory; }
@@ -396,6 +406,8 @@ namespace Mono.Xml
        {
                private DTDObjectModel root;
                public string BaseURI;
+               public int LineNumber;
+               public int LinePosition;
 
                internal void SetRoot (DTDObjectModel root)
                {
@@ -605,21 +617,75 @@ namespace Mono.Xml
                public string NotationName;
                public string LiteralEntityValue;
                public bool IsInternalSubset;
+               public StringCollection ReferencingEntities = new StringCollection ();
+               bool scanned;
+               bool recursed;
 
                public string EntityValue {
                        get {
                                if (entityValue == null) {
-                                       if (SystemId == null)
+                                       if (NotationName != null)
+                                               entityValue = "";
+                                       else if (SystemId == null)
                                                entityValue = LiteralEntityValue;
                                        else {
                                                // FIXME: should use specified XmlUrlResolver.
-                                               entityValue = ResolveExternalEntity (new XmlUrlResolver ());
+                                               entityValue = ResolveExternalEntity (Root.Resolver);
                                        }
+                                       // Check illegal recursion.
+                                       ScanEntityValue (new StringCollection ());
                                }
                                return entityValue;
                        }
                }
 
+               public void ScanEntityValue (StringCollection refs)
+               {
+                       // To modify this code, beware nesting between this and EntityValue.
+                       string value = EntityValue;
+
+                       if (recursed)
+                               throw new XmlException ("Entity recursion was found.");
+                       recursed = true;
+
+                       if (scanned) {
+                               foreach (string referenced in refs)
+                                       if (this.ReferencingEntities.Contains (referenced))
+                                               throw new XmlException (String.Format (
+                                                       "Nested entity was found between {0} and {1}",
+                                                       referenced, Name));
+                               recursed = false;
+                               return;
+                       }
+
+                       int len = value.Length;
+                       int start = 0;
+                       for (int i=0; i<len; i++) {
+                               switch (value [i]) {
+                               case '&':
+                                       start = i+1;
+                                       break;
+                               case ';':
+                                       if (start == 0)
+                                               break;
+                                       string name = value.Substring (start, i - start);
+                                       this.ReferencingEntities.Add (name);
+                                       DTDEntityDeclaration decl = Root.EntityDecls [name];
+                                       if (decl != null) {
+                                               refs.Add (Name);
+                                               decl.ScanEntityValue (refs);
+                                               foreach (string str in decl.ReferencingEntities)
+                                                       ReferencingEntities.Add (str);
+                                               refs.Remove (Name);
+                                       }
+                                       start = 0;
+                                       break;
+                               }
+                       }
+                       scanned = true;
+                       recursed = false;
+               }
+
                private string ResolveExternalEntity (XmlResolver resolver)
                {
                        if (resolver == null)
@@ -637,14 +703,16 @@ namespace Mono.Xml
 
                        bool checkTextDecl = true;
                        while (reader.Peek () != -1) {
-                               sb.Append (reader.Read ());
+                               sb.Append ((char) reader.Read ());
                                if (checkTextDecl && sb.Length == 6) {
                                        if (sb.ToString () == "<?xml ") {
                                                // Skip Text declaration.
                                                sb.Length = 0;
                                                StringBuilder textdecl = new StringBuilder ();
-                                               while (reader.Peek () == '>' || reader.Peek () == -1)
-                                                       textdecl.Append (reader.Read ());
+                                               while (reader.Peek () != '>' && reader.Peek () != -1)
+                                                       textdecl.Append ((char) reader.Read ());
+                                               if (textdecl.ToString ().IndexOf ("encoding") < 0)
+                                                       throw new XmlException ("Text declaration must have encoding specification: " + BaseURI);
                                                if (textdecl.ToString ().IndexOf ("standalone") >= 0)
                                                        throw new XmlException ("Text declaration cannot have standalone declaration: " + BaseURI);
                                        }
@@ -711,11 +779,17 @@ namespace Mono.Xml
                        string absPath = absUri.ToString ();
 
                        try {
-                               TextReader tw = new XmlStreamReader (absUri.ToString (), false, resolver, BaseURI);
+                               XmlStreamReader tw = new XmlStreamReader (absUri.ToString (), false, resolver, BaseURI);
                                string s = tw.ReadToEnd ();
                                if (s.StartsWith ("<?xml")) {
-                                       int end = s.IndexOf (">" + 1);
-                                       if (s.IndexOf ("standal0ne", end) >= 0)
+                                       int end = s.IndexOf (">") + 1;
+                                       if (end < 0)
+                                               throw new XmlException (this as IXmlLineInfo,
+                                                       "Inconsistent text declaration markup.");
+                                       if (s.IndexOf ("encoding", 0, end) < 0)
+                                               throw new XmlException (this as IXmlLineInfo,
+                                                       "Text declaration must not omit encoding specification.");
+                                       if (s.IndexOf ("standalone", 0, end) >= 0)
                                                throw new XmlException (this as IXmlLineInfo,
                                                        "Text declaration cannot have standalone declaration.");
                                        resolvedValue = s.Substring (end);
index 357f22766eeef9e1c9be59db73b4af2903d6a3cc..c4d5520637d90b7cef50220f5331a306d9921570 100644 (file)
@@ -8,7 +8,7 @@ using System.Xml.Schema;
 
 namespace Mono.Xml
 {
-       public class DTDValidatingReader : XmlReader, IXmlLineInfo
+       public class DTDValidatingReader : XmlReader, IXmlLineInfo, IHasXmlParserContext
        {
                public DTDValidatingReader (XmlReader reader)
                        : this (reader, null)
@@ -764,18 +764,6 @@ namespace Mono.Xml
                                throw new InvalidOperationException ("The current node is not an Entity Reference");
                        DTDEntityDeclaration entity = DTD != null ? DTD.EntityDecls [reader.Name] as DTDEntityDeclaration : null;
 
-                       XmlParserContext ctx = null;
-                       if (sourceTextReader != null)
-                               ctx = sourceTextReader.GetInternalParserContext ();
-                       else if (reader is XmlNodeReader)
-                               ctx = ((XmlNodeReader) reader).GetInternalParserContext ();
-                       else if (reader is IHasXmlParserContext)
-                               ctx = ((IHasXmlParserContext) reader).ParserContext;
-
-                       if (ctx == null)
-                               throw new NotSupportedException (
-                                       "Entity resolution from non-XmlTextReader XmlReader could not be supported.");
-
                        XmlNodeType xmlReaderNodeType =
                                (currentAttribute != null) ? XmlNodeType.Attribute : XmlNodeType.Element;
 
@@ -783,11 +771,11 @@ namespace Mono.Xml
                        if (entity != null && entity.SystemId != null) {
                                Uri baseUri = entity.BaseURI == null ? null : new Uri (entity.BaseURI);
                                Stream stream = resolver.GetEntity (resolver.ResolveUri (baseUri, entity.SystemId), null, typeof (Stream)) as Stream;
-                               nextEntityReader = new XmlTextReader (stream, xmlReaderNodeType, ctx);
+                               nextEntityReader = new XmlTextReader (stream, xmlReaderNodeType, ParserContext);
                        } else {
                                string replacementText =
                                        (entity != null) ? entity.EntityValue : String.Empty;
-                               nextEntityReader = new XmlTextReader (replacementText, xmlReaderNodeType, ctx);
+                               nextEntityReader = new XmlTextReader (replacementText, xmlReaderNodeType, ParserContext);
                        }
                        nextEntityReader.XmlResolver = resolver;
                        nextEntityReader.MaybeTextDecl = true;
@@ -936,6 +924,24 @@ namespace Mono.Xml
                        }
                }
 
+               public XmlParserContext ParserContext {
+                       get {
+                               XmlParserContext ctx = null;
+                               if (sourceTextReader != null)
+                                       ctx = sourceTextReader.GetInternalParserContext ();
+                               else if (reader is XmlNodeReader)
+                                       ctx = ((XmlNodeReader) reader).GetInternalParserContext ();
+                               else if (reader is IHasXmlParserContext)
+                                       ctx = ((IHasXmlParserContext) reader).ParserContext;
+
+                               if (ctx == null)
+                                       throw new NotSupportedException (
+                                               "Cannot get parser context from specified XmlReader. To support this XmlReader, implement IHasXmlParserContext interface on the reader.");
+
+                               return ctx;
+                       }
+               }
+
                public override string Prefix {
                        get {
                                if (currentTextValue != null)
index e6b4177776484c74bb7e9b5917c5dac72841b5a8..52bb5537fbdc26db06950d1768f87baaa93021b2 100644 (file)
@@ -97,7 +97,7 @@ namespace System.Xml
 \r
                internal static bool IsPubidChar(int ch)\r
                {\r
-                       return IsWhitespace(ch) | ('a' <= ch && ch <= 'z') | ('A' <= ch && ch <= 'Z') | ('0' <= ch && ch <= '9') | "-'()+,./:=?;!*#@$_%".IndexOf((char)ch) >= 0;\r
+                       return (IsWhitespace(ch) && ch != '\t') | ('a' <= ch && ch <= 'z') | ('A' <= ch && ch <= 'Z') | ('0' <= ch && ch <= '9') | "-'()+,./:=?;!*#@$_%".IndexOf((char)ch) >= 0;\r
                }\r
 \r
                internal static bool IsPubid (string str)\r
index 203f9417bb32b157693657501e6d83f0beae389a..383cc3fd580e2f845e16d2457b379d6182e0b7bc 100644 (file)
@@ -268,9 +268,9 @@ namespace System.Xml
                        return new XmlDocumentType (name, publicId, systemId, internalSubset, this);
                }
 
-               private XmlDocumentType CreateDocumentType (XmlTextReader reader)
+               private XmlDocumentType CreateDocumentType (DTDObjectModel dtd)
                {
-                       return new XmlDocumentType (reader, this);
+                       return new XmlDocumentType (dtd, this);
                }
 
                public XmlElement CreateElement (string name)
@@ -800,15 +800,28 @@ namespace System.Xml
                                        break;
 
                                case XmlNodeType.DocumentType:
-                                       // hack ;-)
+                                       if(currentNode != null)
+                                               throw new XmlException (reader as IXmlLineInfo, "XmlDocumentType at invalid position.");
+
+                                       DTDObjectModel dtd = null;
                                        XmlTextReader xtReader = reader as XmlTextReader;
-                                       if(xtReader == null)
-                                               newNode = CreateDocumentType (reader.Name, reader ["PUBLIC"], reader ["SYSTEM"], reader.Value);
+                                       if (xtReader != null)
+                                               dtd = xtReader.DTD;
+                                       XmlNodeReader xnReader = reader as XmlNodeReader;
+                                       if (xnReader != null)
+                                               dtd = xnReader.GetInternalParserContext ().Dtd;
+                                       XmlValidatingReader xvReader = reader as XmlValidatingReader;
+                                       if (xvReader != null)
+                                               dtd = xvReader.GetInternalParserContext ().Dtd;
+                                       IHasXmlParserContext ctxReader = reader as IHasXmlParserContext;
+                                       if (ctxReader != null)
+                                               dtd = ctxReader.ParserContext.Dtd;
+
+                                       if (dtd != null)
+                                               newNode = CreateDocumentType (dtd);
                                        else
-                                               newNode = CreateDocumentType (xtReader);
+                                               newNode = CreateDocumentType (reader.Name, reader ["PUBLIC"], reader ["SYSTEM"], reader.Value);
 
-                                       if(currentNode != null)
-                                               throw new XmlException (reader as IXmlLineInfo, "XmlDocumentType at invalid position.");
                                        break;
 
                                case XmlNodeType.EntityReference:
index 1d5e51466da0e6f4d0ad1aac2ccaba23f80f2ace..4fd7e87b292933c25e35fedc55b45ff757ce2f0b 100644 (file)
@@ -16,10 +16,10 @@ namespace System.Xml
        public class XmlDocumentType  : XmlLinkedNode\r
        {\r
                // Fields\r
-               string name;            // name of the document type\r
-               string publicId;        // public identifier on the DOCTYPE\r
-               string systemId;        // system identifier on the DOCTYPE\r
-               string internalSubset;  // value of the DTD internal subset\r
+//             string name;            // name of the document type\r
+//             string publicId;        // public identifier on the DOCTYPE\r
+//             string systemId;        // system identifier on the DOCTYPE\r
+//             string internalSubset;  // value of the DTD internal subset\r
                internal XmlNamedNodeMap entities;\r
                internal XmlNamedNodeMap notations;\r
                DTDObjectModel dtd;\r
@@ -30,11 +30,6 @@ namespace System.Xml
                                                    XmlDocument doc)\r
                        : base (doc)\r
                {\r
-                       this.name = name;\r
-                       this.publicId = publicId;\r
-                       this.systemId = systemId;\r
-                       this.internalSubset = internalSubset;\r
-\r
                        XmlTextReader xtr = new XmlTextReader (BaseURI, new StringReader (""), doc.NameTable);\r
                        xtr.XmlResolver = doc.Resolver;\r
                        xtr.GenerateDTDObjectModel (name, publicId, systemId, internalSubset);\r
@@ -43,15 +38,10 @@ namespace System.Xml
                        ImportFromDTD ();\r
                }\r
 \r
-               internal XmlDocumentType (XmlTextReader reader, XmlDocument doc)\r
+               internal XmlDocumentType (DTDObjectModel dtd, XmlDocument doc)\r
                        : base (doc)\r
                {\r
-                       this.name = reader.Name;\r
-                       this.publicId = reader ["PUBLIC"];\r
-                       this.systemId = reader ["SYSTEM"];\r
-                       this.internalSubset = reader.Value;\r
-                       this.dtd = reader.DTD;\r
-\r
+                       this.dtd = dtd;\r
                        ImportFromDTD ();\r
                }\r
 \r
@@ -86,7 +76,7 @@ namespace System.Xml
                        \r
                public string InternalSubset\r
                {\r
-                       get { return internalSubset; }\r
+                       get { return dtd.InternalSubset; }\r
                }\r
 \r
                public override bool IsReadOnly\r
@@ -96,12 +86,12 @@ namespace System.Xml
 \r
                public override string LocalName\r
                {\r
-                       get { return name; }\r
+                       get { return dtd.Name; }\r
                }\r
 \r
                public override string Name\r
                {\r
-                       get { return name; }\r
+                       get { return dtd.Name; }\r
                }\r
 \r
                public override XmlNodeType NodeType\r
@@ -116,20 +106,21 @@ namespace System.Xml
 \r
                public string PublicId\r
                {\r
-                       get { return publicId; }\r
+                       get { return dtd.PublicId; }\r
                }\r
 \r
                public string SystemId\r
                {\r
-                       get { return systemId; }\r
+                       get { return dtd.SystemId; }\r
                }\r
 \r
                // Methods\r
                public override XmlNode CloneNode (bool deep)\r
                {\r
                        // deep is ignored\r
-                       return new XmlDocumentType (name, publicId, systemId,\r
-                                                   internalSubset, OwnerDocument);\r
+//                     return new XmlDocumentType (Name, PublicId, SystemId,\r
+//                                                 InternalSubset, OwnerDocument);\r
+                       return new XmlDocumentType (dtd, OwnerDocument);\r
                }\r
                \r
                public override void WriteContentTo (XmlWriter w)\r
@@ -139,7 +130,7 @@ namespace System.Xml
 \r
                public override void WriteTo (XmlWriter w)\r
                {\r
-                       w.WriteDocType (name, publicId, systemId, internalSubset);\r
+                       w.WriteDocType (Name, PublicId, SystemId, InternalSubset);\r
                }\r
        }\r
 }\r
index f29b08d425df5f78b16cc6daff2922287bbcc4bc..7899d2a13e728cba675baad6a73f01b6ef339a26 100644 (file)
@@ -254,7 +254,6 @@ namespace System.Xml
 
                public abstract XmlNode CloneNode (bool deep);
 
-               [MonoTODO]
                public XPathNavigator CreateNavigator ()
                {
                        XmlDocument document = this.NodeType == XmlNodeType.Document ?
@@ -347,7 +346,6 @@ namespace System.Xml
                        return InsertBefore (newChild, argNode);
                }
 
-               [MonoTODO("If inserted node is entity reference, then check conforming entity. Wait for DTD implementation.")]
                public virtual XmlNode InsertBefore (XmlNode newChild, XmlNode refChild)
                {
                        XmlDocument ownerDoc = (NodeType == XmlNodeType.Document) ? (XmlDocument)this : OwnerDocument;
@@ -552,7 +550,7 @@ namespace System.Xml
                        return SelectNodes (xpath, null);
                }
 
-               [MonoTODO]
+               [MonoTODO ("return nodes in document order")]
                public XmlNodeList SelectNodes (string xpath, XmlNamespaceManager nsmgr)
                {
                        XPathNavigator nav = CreateNavigator ();
@@ -586,11 +584,6 @@ namespace System.Xml
                        return ((XmlDocumentNavigator) iter.Current).Node;
                }
 
-//             internal void SetParentNode (XmlNode parent)
-//             {
-//                     parentNode = parent;
-//             }
-
                [MonoTODO]
                public virtual bool Supports (string feature, string version)
                {
index 0df31bde86a17d9e00ac2454cd6d0424c095a966..b5b5da741bd974af4c4687360216cb206d5c1939 100644 (file)
@@ -125,6 +125,18 @@ namespace Mono.Xml.Native
                        get { return this.currentMarkup; }
                }
 
+               private char [] wsChars = new char [] {' ', '\r', '\n', '\t'};
+               public bool HasPEBuffer {
+                       get {
+                               if (peBuffer.Length == 0)
+                                       return false;
+                               else if (peBuffer.ToString ().Trim (wsChars).Length == 0)
+                                       return false;
+                               else
+                                       return true;
+                       }
+               }
+
                public int LineNumber {
                        get { return line; }
                }
index 21eec470ab60d98532524c2a2b66abbeb1189b48..8c16f275b2e783db83a327e543c284bba38088b6 100644 (file)
@@ -19,6 +19,7 @@
 
 using System;
 using System.Collections;
+using System.Collections.Specialized;
 using System.IO;
 using System.Text;
 using System.Xml.Schema;
@@ -1010,16 +1011,9 @@ namespace System.Xml
                                popScope = false;
                        }
 
-                       if (returnEntityReference) {
+                       if (returnEntityReference)
                                SetEntityReferenceProperties ();
-                               if (DTD == null)
-                                       throw new XmlException (this as IXmlLineInfo,
-                                               "Entity reference is not allowed without document type declaration.");
-                               else if((!DTD.InternalSubsetHasPEReference || 
-                                       isStandalone || resolver == null) && DTD.EntityDecls [name] == null)
-                                       throw new XmlException (this as IXmlLineInfo,
-                                               "Required entity declaration for '" + name + "' was not found.");
-                       } else {
+                       else {
                                switch (PeekChar ()) {
                                case '<':
                                        ReadChar ();
@@ -1061,6 +1055,18 @@ namespace System.Xml
 
                private void SetEntityReferenceProperties ()
                {
+/*
+                       if (resolver != null) {
+                               if (DTD == null)
+                                       throw new XmlException (this as IXmlLineInfo,
+                                               "Entity reference is not allowed without document type declaration.");
+                               else if((!DTD.InternalSubsetHasPEReference || isStandalone) &&
+                                       DTD.EntityDecls [entityReferenceName] == null)
+                                       throw new XmlException (this as IXmlLineInfo,
+                                               "Required entity declaration for '" + entityReferenceName + "' was not found.");
+                               string dummy = DTD.EntityDecls [entityReferenceName].EntityValue;
+                       }
+*/
                        SetProperties (
                                XmlNodeType.EntityReference, // nodeType
                                entityReferenceName, // name
@@ -1358,23 +1364,23 @@ namespace System.Xml
                                throw new XmlException (this as IXmlLineInfo,
                                        "Invalid entity reference name was found.");
 
-                               char predefined = XmlChar.GetPredefinedEntity (name);
-                               if (predefined != 0)
-                                       AppendValueChar (predefined);
-                               else {
-                                       if (ignoreEntityReferences) {
-                                               AppendValueChar ('&');
-
-                                               foreach (char ch2 in name) {
-                                                       AppendValueChar (ch2);
-                                               }
+                       char predefined = XmlChar.GetPredefinedEntity (name);
+                       if (predefined != 0)
+                               AppendValueChar (predefined);
+                       else {
+                               if (ignoreEntityReferences) {
+                                       AppendValueChar ('&');
 
-                                               AppendValueChar (';');
-                                       } else {
-                                               returnEntityReference = true;
-                                               entityReferenceName = name;
+                                       foreach (char ch2 in name) {
+                                               AppendValueChar (ch2);
                                        }
+
+                                       AppendValueChar (';');
+                               } else {
+                                       returnEntityReference = true;
+                                       entityReferenceName = name;
                                }
+                       }
                }
 
                // The reader is positioned on the first character of
@@ -1444,9 +1450,7 @@ namespace System.Xml
                                        if (XmlChar.GetPredefinedEntity (entName) == 0) {
                                                DTDEntityDeclaration entDecl = 
                                                        DTD == null ? null : DTD.EntityDecls [entName];
-                                               // In this point, XML 1.0 spec is tricky. Its WFC constraints 
-                                               // allow non-declared entity, while prohibiting external entity reference.
-                                               if (entDecl == null || !entDecl.IsInternalSubset)
+                                               if (entDecl == null || entDecl.SystemId != null)
                                                        throw new XmlException (this as IXmlLineInfo,
                                                                "Reference to external entities is not allowed in attribute value.");
                                        }
@@ -1553,8 +1557,8 @@ namespace System.Xml
                                                message = "Version 1.0 declaration is required in Text Declaration.";
                                        currentCheck = 1;
                                }
-                               if (orderedAttributes.Count > currentCheck && orderedAttributes [currentCheck] as string != "encoding")
-                                       message = "Invalid Text Declaration markup was found.";
+                               if (orderedAttributes.Count <= currentCheck || orderedAttributes [currentCheck] as string != "encoding")
+                                       message = "Invalid Text Declaration markup was found. encoding specification is required.";
                        }
                        if (message != null)
                                throw new XmlException (this as IXmlLineInfo, message);
@@ -1699,8 +1703,8 @@ namespace System.Xml
                        currentState = XmlNodeType.DocumentType;
 
                        string doctypeName = null;
-                       string publicId = String.Empty;
-                       string systemId = String.Empty;
+                       string publicId = null;
+                       string systemId = null;
                        int intSubsetStartLine = 0;
                        int intSubsetStartColumn = 0;
 
@@ -1765,6 +1769,10 @@ namespace System.Xml
                        parserContext.Dtd = new DTDObjectModel ();      // merges both internal and external subsets in the meantime,
                        DTD.BaseURI = BaseURI;
                        DTD.Name = name;
+                       DTD.PublicId = publicId;
+                       DTD.SystemId = systemId;
+                       DTD.InternalSubset = internalSubset;
+                       DTD.XmlResolver = resolver;
                        int originalParserDepth = parserInputStack.Count;
                        if (internalSubset != null && internalSubset.Length > 0) {
                                XmlParserInput original = currentInput;
@@ -1787,7 +1795,6 @@ namespace System.Xml
                                } while (nodeType != XmlNodeType.None || parserInputStack.Count > originalParserDepth + 1);
                                PopParserInput ();
                        }
-                       // TODO: Check entity nesting
 
                        return DTD;
                }
@@ -2002,7 +2009,18 @@ namespace System.Xml
                                // It affects on entity references' well-formedness
                                if (this.parserInputStack.Count == 0)
                                        DTD.InternalSubsetHasPEReference = true;
-                               TryExpandPERef ();
+                               ReadChar ();
+                               string peName = ReadName ();
+                               Expect (';');
+                               currentInput.InsertParameterEntityBuffer (GetPEValue (peName));
+                               int currentLine = currentInput.LineNumber;
+                               int currentColumn = currentInput.LinePosition;
+                               while (currentInput.HasPEBuffer)
+                                       CompileDTDSubset ();
+                               if (currentInput.LineNumber != currentLine ||
+                                       currentInput.LinePosition != currentColumn)
+                                       throw new XmlException (this as IXmlLineInfo,
+                                               "Incorrectly nested parameter entity.");
                                break;
                        case '<':
                                ReadChar ();
@@ -2060,7 +2078,7 @@ namespace System.Xml
                                                        TryExpandPERef ();
                                                        SkipWhitespace ();
                                                        if (XmlChar.IsNameChar (PeekChar ()))
-                                                       ReadParameterEntityDecl ();
+                                                               ReadParameterEntityDecl ();
                                                        else
                                                                throw new XmlException (this as IXmlLineInfo,"expected name character");
                                                }
@@ -2420,8 +2438,12 @@ namespace System.Xml
                                this.parameterEntities [peName] as DTDParameterEntityDeclaration;
                        if (peDecl != null)
                                return peDecl.Value;
-                               DTD.AddError (new XmlSchemaException (
-                                       "Parameter entity " + peName + " not found.", null));
+                       // See XML 1.0 section 4.1 for both WFC and VC.
+                       if ((DTD.SystemId == null && !DTD.InternalSubsetHasPEReference) || this.isStandalone)
+                               throw new XmlException (this as IXmlLineInfo,
+                                       "Parameter entity " + peName + " not found.");
+                       DTD.AddError (new XmlSchemaException (
+                               "Parameter entity " + peName + " not found.", null));
                        return "";
                }
 
@@ -2484,7 +2506,7 @@ namespace System.Xml
                        }
                        else {
                                // literal entity
-                               decl.LiteralEntityValue = ReadEntityValueDecl ();
+                               ReadEntityValueDecl (decl);
                        }
                        SkipWhitespace ();
                        // This expanding is only allowed as a non-validating parser.
@@ -2494,7 +2516,7 @@ namespace System.Xml
                        return decl;
                }
 
-               private string ReadEntityValueDecl ()
+               private void ReadEntityValueDecl (DTDEntityDeclaration decl)
                {
                        SkipWhitespace ();
                        // quotation char will be finally removed on unescaping
@@ -2511,8 +2533,10 @@ namespace System.Xml
                                        ReadChar ();
                                        string name = ReadName ();
                                        Expect (';');
+                                       if (decl.IsInternalSubset)
+                                               throw new XmlException (this as IXmlLineInfo,
+                                                       "Parameter entity is not allowed in internal subset entity '" + name + "'");
                                        valueBuffer.Append (GetPEValue (name));
-                                       continue;
                                        break;
                                case -1:
                                        throw new XmlException ("unexpected end of stream.");
@@ -2526,7 +2550,7 @@ namespace System.Xml
                        ClearValueBuffer ();
 
                        Expect (quoteChar);
-                       return value;
+                       decl.LiteralEntityValue = value;
                }
 
                private DTDAttListDeclaration ReadAttListDecl ()
@@ -2627,7 +2651,9 @@ namespace System.Xml
                                case 'O':
                                        Expect ("OTATION");
                                        def.Datatype = XmlSchemaDatatype.FromName ("NOTATION");
-                                       SkipWhitespace ();
+                                       if (!SkipWhitespace ())
+                                               throw new XmlException (this as IXmlLineInfo,
+                                                       "Whitespace is required between name and content in DTD attribute definition.");
                                        Expect ('(');
                                        SkipWhitespace ();
                                        def.EnumeratedNotations.Add (ReadName ());              // notation name
index ec9ac29de15a61b15dc512f5205ef529371ac88c..d800d0e1be686ca1fcec92d2028720c9679a26dd 100644 (file)
@@ -25,6 +25,7 @@ namespace System.Xml {
                XmlResolver resolver;
                ValidationType validationType;
                XmlSchemaCollection schemas;
+               DTDValidatingReader dtdReader;
 
                #endregion // Fields
 
@@ -283,6 +284,12 @@ namespace System.Xml {
                        return validatingReader.GetAttribute (localName, namespaceName);
                }
 
+               internal XmlParserContext GetInternalParserContext ()
+               {
+                       return dtdReader != null ?
+                               dtdReader.ParserContext : null;
+               }
+
                bool IXmlLineInfo.HasLineInfo ()
                {
                        IXmlLineInfo info = validatingReader as IXmlLineInfo;
@@ -337,19 +344,17 @@ namespace System.Xml {
                        if (ReadState == ReadState.Initial) {
                                switch (ValidationType) {
                                case ValidationType.Auto:
+                               case ValidationType.None:
                                        if (schemas.Count > 0)
                                                goto case ValidationType.Schema;
                                        else
                                                goto case ValidationType.DTD;
-                               case ValidationType.None:
-                                       validatingReader = // new XmlSchemaValidatingReader (
-                                               new DTDValidatingReader (sourceReader, this);
-                                       break;
                                case ValidationType.DTD:
-                                       validatingReader = new DTDValidatingReader (sourceReader, this);
+                                       validatingReader = dtdReader = new DTDValidatingReader (sourceReader, this);
                                        break;
                                case ValidationType.Schema:
-//                                     validatingReader = new XmlSchemaValidatingReader (sourceReader, this);
+//                                     dtdReader = new DTDValidatingReader (sourceReader, this);
+//                                     validatingReader = new XmlSchemaValidatingReader (dtdReader, this);
 //                                     break;
                                case ValidationType.XDR:
                                        throw new NotImplementedException ();