[Xml] Fix GetAttribute to handle null namespaces properly, add unit test.
[mono.git] / mcs / class / System.XML / System.Xml / XmlDeclaration.cs
index 5b10f8cfbd958287bfd2a02cc08922cfcb6d20dc..821d82e2eb6cdf1585a782478d3115f7928c0e4b 100644 (file)
@@ -7,6 +7,27 @@
 //
 // (C) Ximian, Inc.
 
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
 using System;
 using System.Globalization;
 using System.Text;
@@ -106,27 +127,94 @@ namespace System.Xml
                        w.WriteRaw (String.Format ("<?xml {0}?>", Value));
                }
 
+               private int SkipWhitespace (string input, int index)
+               {
+                       while (index < input.Length) {
+                               if (XmlChar.IsWhitespace (input [index]))
+                                       index++;
+                               else
+                                       break;
+                       }
+                       return index;
+               }
+
                void ParseInput (string input)
                {
-                       char [] sep = new char [] {'\'', '"'};
-                       if (!input.Trim (XmlChar.WhitespaceChars).StartsWith ("version"))
-                               throw new XmlException("missing \"version\".");
-                       int start = input.IndexOf ("encoding");
-                       int sstart = -1;
-                       if (start > 0) {
-                               int valStart = input.IndexOfAny (sep, start) + 1;
-                               int valEnd = input.IndexOfAny (sep, valStart);
-                               Encoding = input.Substring (valStart, valEnd - valStart);
-                               sstart = input.IndexOf ("standalone");
+                       int index = SkipWhitespace (input, 0);
+                       if (index + 7 > input.Length || input.IndexOf ("version", index, 7) != index)
+                               throw new XmlException ("Missing 'version' specification.");
+                       index = SkipWhitespace (input, index + 7);
+
+                       char c = input [index];
+                       if (c != '=')
+                               throw new XmlException ("Invalid 'version' specification.");
+                       index++;
+                       index = SkipWhitespace (input, index);
+                       c = input [index];
+                       if (c != '"' && c != '\'')
+                               throw new XmlException ("Invalid 'version' specification.");
+                       index++;
+                       int end = input.IndexOf (c, index);
+                       if (end < 0 || input.IndexOf ("1.0", index, 3) != index)
+                               throw new XmlException ("Invalid 'version' specification.");
+                       index += 4;
+                       if (index == input.Length)
+                               return;
+                       if (!XmlChar.IsWhitespace (input [index]))
+                               throw new XmlException ("Invalid XML declaration.");
+                       index = SkipWhitespace (input, index + 1);
+                       if (index == input.Length)
+                               return;
+
+                       if (input.Length > index + 8 && input.IndexOf ("encoding", index, 8) > 0) {
+                               index = SkipWhitespace (input, index + 8);
+                               c = input [index];
+                               if (c != '=')
+                                       throw new XmlException ("Invalid 'version' specification.");
+                               index++;
+                               index = SkipWhitespace (input, index);
+                               c = input [index];
+                               if (c != '"' && c != '\'')
+                                       throw new XmlException ("Invalid 'encoding' specification.");
+                               end = input.IndexOf (c, index + 1);
+                               if (end < 0)
+                                       throw new XmlException ("Invalid 'encoding' specification.");
+                               Encoding = input.Substring (index + 1, end - index - 1);
+                               index = end + 1;
+                               if (index == input.Length)
+                                       return;
+                               if (!XmlChar.IsWhitespace (input [index]))
+                                       throw new XmlException ("Invalid XML declaration.");
+                               index = SkipWhitespace (input, index + 1);
+                       }
+
+                       if (input.Length > index + 10 && input.IndexOf ("standalone", index, 10) > 0) {
+                               index = SkipWhitespace (input, index + 10);
+                               c = input [index];
+                               if (c != '=')
+                                       throw new XmlException ("Invalid 'version' specification.");
+                               index++;
+                               index = SkipWhitespace (input, index);
+                               c = input [index];
+                               if (c != '"' && c != '\'')
+                                       throw new XmlException ("Invalid 'standalone' specification.");
+                               end = input.IndexOf (c, index + 1);
+                               if (end < 0)
+                                       throw new XmlException ("Invalid 'standalone' specification.");
+                               string tmp = input.Substring (index + 1, end - index - 1);
+                               switch (tmp) {
+                               case "yes":
+                               case "no":
+                                       break;
+                               default:
+                                       throw new XmlException ("Invalid standalone specification.");
+                               }
+                               Standalone = tmp;
+                               index = end + 1;
+                               index = SkipWhitespace (input, index);
                        }
-                       else
-                               sstart = input.IndexOf ("standalone");
-
-                       if (sstart > 0) {
-                               int svalStart = input.IndexOfAny (sep, sstart) + 1;
-                               int svalEnd = input.IndexOfAny (sep, svalStart);
-                               Standalone = input.Substring (svalStart, svalEnd - svalStart);
-                       }       // TODO: some error check
+                       if (index != input.Length)
+                               throw new XmlException ("Invalid XML declaration.");
                }
        }
 }