Example #1
0
        // userinfo    = *( unreserved / pct-encoded / sub-delims / ":" )
        private static bool ParseUser(ParserState state)
        {
            string        part = state.remaining;
            StringBuilder sb   = null;

            int index;

            for (index = 0; index < part.Length; index++)
            {
                char ch            = part[index];
                bool isEscapedChar = false;
                var  oldIndex      = index;

                if (ch == '%')
                {
                    if (!Uri.IsHexEncoding(part, index))
                    {
                        return(false);
                    }
                    ch = Uri.HexUnescape(part, ref index);
                    index--;
                    isEscapedChar = true;
                }

                if (!CharUtilities.IsLetterOrDigit(ch) && !IsUnreserved(ch) && !IsSubDelim(ch) && ch != ':')
                {
                    if (!isEscapedChar)
                    {
                        break;
                    }

                    ch    = '%';
                    index = oldIndex;
                }

                if (sb == null)
                {
                    sb = new StringBuilder();
                }
                sb.Append(ch);
            }

            if (index + 1 <= part.Length && part[index] == '@')
            {
                if (state.elements.scheme == Uri.UriSchemeFile)
                {
                    state.error = "Invalid URI: The hostname could not be parsed.";
                    return(false);
                }

                state.elements.user = sb == null ? "" : sb.ToString();
                state.remaining     = state.remaining.Substring(index + 1);
            }

            return(state.remaining.Length > 0);
        }
Example #2
0
        // port          = *DIGIT
        private static bool ParsePort(ParserState state)
        {
            string part = state.remaining;

            if (part.Length == 0 || part[0] != ':')
            {
                return(part.Length > 0);
            }

            StringBuilder sb = new StringBuilder();

            int index;

            for (index = 1; index < part.Length; index++)
            {
                char ch = part[index];

                if (!CharUtilities.IsDigit(ch))
                {
                    if (ch == '/' || ch == '#' || ch == '?')
                    {
                        break;
                    }

                    state.error = "Invalid URI: Invalid port specified.";
                    return(false);
                }

                sb.Append(ch);
            }

            if (index <= part.Length)
            {
                state.remaining = part.Substring(index);
            }

            if (sb.Length == 0)
            {
                return(state.remaining.Length > 0);
            }

            int port;

            try
            {
                port = Int32.Parse(sb.ToString());
            }
            catch (Exception)
            {
                state.error = "Invalid URI: Invalid port number";
                return(false);
            }
            if (port < 0 || port > UInt16.MaxValue)
            {
                state.error = "Invalid URI: Invalid port number";
                return(false);
            }

            state.elements.port = port;

            return(state.remaining.Length > 0);
        }
Example #3
0
        // 3.1) scheme      = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
        private static bool ParseScheme(ParserState state)
        {
            string part = state.remaining;

            StringBuilder sb = new StringBuilder();

            sb.Append(part[0]);

            int index;

            for (index = 1; index < part.Length; index++)
            {
                char ch = part[index];
                if (ch != '.' && ch != '-' && ch != '+' && !IsAlpha(ch) && !CharUtilities.IsDigit(ch))
                {
                    break;
                }

                sb.Append(ch);
            }

            if (index == 0 || index >= part.Length)
            {
                if (state.kind == UriKind.Absolute)
                {
                    state.error = "Invalid URI: The format of the URI could not be determined.";
                    return(false);
                }

                state.elements.isAbsoluteUri = false;
                return(state.remaining.Length > 0);
            }

            if (part[index] != ':')
            {
                if (state.kind == UriKind.Absolute)
                {
                    state.error = "Invalid URI: The URI scheme is not valid.";
                    return(false);
                }

                state.elements.isAbsoluteUri = false;
                return(state.remaining.Length > 0);
            }

            state.elements.scheme = sb.ToString().ToLower();
            state.remaining       = part.Substring(index);

            // Check scheme name characters as specified in RFC2396.
            // Note: different checks in 1.x and 2.0
            if (!Uri.CheckSchemeName(state.elements.scheme))
            {
                if (state.kind == UriKind.Absolute)
                {
                    state.error = "Invalid URI: The URI scheme is not valid.";
                    return(false);
                }

                state.elements.isAbsoluteUri = false;
                return(state.remaining.Length > 0);
            }

            return(ParseDelimiter(state));
        }
Example #4
0
        /// <summary>
        /// Loads the XML document from the specified string.
        /// </summary>
        /// <param name="xml">String containing the XML document to load.</param>
        /// <exception cref="T:System.Xml.XmlException">There is a load or parse error in the XML. In this case, the document remains empty. </exception>
        public override void LoadXml(string xml)
        {
            if (xml == null)
            {
                throw new ArgumentNullException("xml");
            }
            RemoveAll();
            int  l = xml.Length;
            char c;

            m_sb = new StringBuilder(100);
            m_exclamationInstruction = new StringBuilder(50);
            m_current             = this;
            m_state               = State.None;
            m_isAllWhitespace     = true;
            m_attribute           = null;
            m_attributeValueMatch = '\0';
            m_lastElement         = null;

            if (CreateDefaultDocumentElement)
            {
                m_current = AppendChild(GetDefaultDocumentNode());
            }

            for (int i = 0; i < l; i++)
            {
                c = xml[i];

                switch (m_state)
                {
                case State.EndElementImmediate:

                    if (IsXmlWhitespace(c) || c == '/')
                    {
                        // kill as much white space as we can
                        // while we're in the end of the element
                        continue;
                    }
                    else if (c == '>')
                    {
                        // We've already hit the end slash, and
                        // now we've hit the final >, so we just
                        // reset to a base state
                        m_state = State.None;
                    }
                    else if (c == '<')
                    {
                        ContextSwitch(State.Element);
                        continue;
                    }
                    else
                    {
                        m_state           = State.None;
                        m_isAllWhitespace = false;
                        m_sb.Append(c);
                    }

                    continue;

                case State.EndAttribute:
                    if (c == '/')
                    {
                        ContextSwitch(State.EndElementImmediate);
                        continue;
                    }
                    else if (c == '>')
                    {
                        ContextSwitch(State.EndElement);
                        continue;
                    }
                    else if (CharUtilities.IsQuoteCharacter(c))
                    {
                        m_attributeValueMatch = c;
                        ContextSwitch(State.StartAttributeValue);
                        continue;
                    }
                    else if (!IsXmlWhitespace(c))
                    {
                        m_attributeValueMatch = '\0';
                        ContextSwitch(State.StartAttributeValue);
                        m_sb.Append(c);
                        continue;
                    }

                    continue;

                case State.StartAttributeValue:
                    if (m_attributeValueMatch == '\0' && c == '/')
                    {
                        ContextSwitch(State.EndElementImmediate);
                        continue;
                    }
                    else if (c == '>')
                    {
                        ContextSwitch(State.EndElement);
                        continue;
                    }
                    else if (c == m_attributeValueMatch)
                    {
                        ContextSwitch(State.EndAttributeValue);
                        continue;
                    }
                    else if (m_attributeValueMatch == '\0' && IsXmlWhitespace(c))
                    {
                        ContextSwitch(State.EndAttributeValue);
                        continue;
                    }
                    else if (c == '&')
                    {
                        m_preEntityState = m_state;
                        ContextSwitch(State.StartEntity);
                        continue;
                    }

                    m_sb.Append(c);

                    continue;

                case State.StartAttribute:
                    if (c == '/')
                    {
                        ContextSwitch(State.EndElementImmediate);
                        continue;
                    }
                    else if (c == '>')
                    {
                        ContextSwitch(State.EndElement);
                        continue;
                    }
                    else if (IsValidNameCharacter(c))
                    {
                        m_sb.Append(c);
                    }
                    else if (IsXmlWhitespace(c) || c == '=')
                    {
                        ContextSwitch(State.EndAttribute);
                        continue;
                    }

                    continue;

                case State.InElement:
                case State.EndAttributeValue:
                    if (c == '/')
                    {
                        ContextSwitch(State.EndElementImmediate);
                        continue;
                    }
                    else if (c == '>')
                    {
                        ContextSwitch(State.EndElement);
                        continue;
                    }
                    else if (IsXmlWhitespace(c))
                    {
                        continue;
                    }
                    else if (IsValidFirstNameCharacter(c))
                    {
                        ContextSwitch(State.StartAttribute);
                        m_sb.Append(c);
                        continue;
                    }

                    continue;

                case State.CloseElement:
                    if (char.IsWhiteSpace(c))
                    {
                        continue;
                    }
                    else if (c == '>')
                    {
                        ContextSwitch(State.EndCloseElement);
                        m_state = State.None;
                        continue;
                    }

                    m_isAllWhitespace = false;
                    m_sb.Append(c);

                    continue;

                case State.InComment:

                    if (c == '-' && i + 2 < l && xml[i + 1] == '-' && xml[i + 2] == '>')
                    {
                        ContextSwitch(State.EndComment);
                        i += 2;
                        continue;
                    }

                    if (m_sb.Length == 0 && c == '-')
                    {
                        continue;
                    }

                    m_sb.Append(c);

                    continue;

                case State.InCDATA:

                    if (c == ']' && i + 2 < l && xml[i + 1] == ']' && xml[i + 2] == '>')
                    {
                        ContextSwitch(State.EndCDATA);
                        i += 2;
                        continue;
                    }

                    m_sb.Append(c);
                    continue;

                case State.StartDoctype:

                    if (c == '>')
                    {
                        ContextSwitch(State.None);
                        continue;
                    }
                    else if (c == '<')
                    {
                        ContextSwitch(State.None);
                        i--;
                        continue;
                    }

                    m_exclamationInstruction.Append(c);

                    continue;

                case State.StartExclamationPoint:

                    if (c == '-')
                    {
                        ContextSwitch(State.InComment);
                        continue;
                    }
                    else if (IsXmlWhitespace(c))
                    {
                        continue;
                    }

                    m_state = State.Element;
                    i--;

                    continue;

                case State.StartProcessingInstruction:
                    if (c == '>')
                    {
                        ContextSwitch(State.None);
                        continue;
                    }
                    else if (c == '<')
                    {
                        ContextSwitch(State.None);
                        i--;
                        continue;
                    }

                    //.Append(c);
                    continue;

                case State.Element:
                    if (c == '>')
                    {
                        ContextSwitch(State.EndElement);
                        continue;
                    }
                    else if (char.IsWhiteSpace(c))
                    {
                        if (m_sb.Length > 0)
                        {
                            ContextSwitch(State.InElement);
                        }
                        continue;
                    }
                    else if (c == '!')
                    {
                        if (i + 7 < l &&
                            xml[i + 1] == '[' &&
                            (xml[i + 2] == 'C' || xml[i + 2] == 'c') &&
                            (xml[i + 3] == 'D' || xml[i + 3] == 'd') &&
                            (xml[i + 4] == 'A' || xml[i + 4] == 'a') &&
                            (xml[i + 5] == 'T' || xml[i + 5] == 't') &&
                            (xml[i + 6] == 'A' || xml[i + 6] == 'a') &&
                            xml[i + 7] == '[')
                        {
                            ContextSwitch(State.InCDATA);
                            i += 7;
                            continue;
                        }
                        else if (i + 7 < l &&
                                 (xml[i + 1] == 'D' || xml[i + 1] == 'd') &&
                                 (xml[i + 2] == 'O' || xml[i + 2] == 'o') &&
                                 (xml[i + 3] == 'C' || xml[i + 3] == 'c') &&
                                 (xml[i + 4] == 'T' || xml[i + 4] == 't') &&
                                 (xml[i + 5] == 'Y' || xml[i + 5] == 'y') &&
                                 (xml[i + 6] == 'P' || xml[i + 6] == 'p') &&
                                 (xml[i + 7] == 'E' || xml[i + 7] == 'e'))
                        {
                            m_exclamationInstruction.Length = 0;
                            ContextSwitch(State.StartDoctype);
                            i += 7;
                            continue;
                        }
                        else
                        {
                            ContextSwitch(State.StartExclamationPoint);
                            continue;
                        }
                    }
                    else if (c == '?')
                    {
                        ContextSwitch(State.StartProcessingInstruction);
                        continue;
                    }
                    else if (c == '/')
                    {
                        if (m_sb.Length == 0)
                        {
                            ContextSwitch(State.CloseElement);
                        }
                        else
                        {
                            ContextSwitch(State.EndElementImmediate);
                        }
                        continue;
                    }

                    m_isAllWhitespace = false;
                    m_sb.Append(c);
                    continue;

                case State.StartEntity:

                    if (m_sb.Length == 0 && IsValidEntityFirstCharacter(c))
                    {
                        m_sb.Append(c);
                        continue;
                    }
                    else if (m_sb.Length > 0 && IsValidEntityCharacter(c))
                    {
                        m_sb.Append(c);
                        continue;
                    }
                    else if (c == ';' && m_sb.Length > 0)
                    {
                        ContextSwitch(m_preEntityState);
                        m_preEntityState = State.None;
                        continue;
                    }
                    else
                    {
                        m_sb.Insert(0, "&");
                        m_state           = State.None;
                        m_isAllWhitespace = false;
                        ContextSwitch(m_preEntityState);
                        m_preEntityState = State.None;

                        // redo this character
                        i--;
                        continue;
                    }

                default:

                    // Fall back in case we are not in a state
                    // in which we should special case

                    if (c == '<')
                    {
                        ContextSwitch(State.Element);
                        continue;
                    }
                    else if (c == '&')
                    {
                        m_preEntityState = m_state;
                        ContextSwitch(State.StartEntity);
                        continue;
                    }

                    if (m_isAllWhitespace && !IsXmlWhitespace(c))
                    {
                        m_isAllWhitespace = false;
                    }

                    m_sb.Append(c);
                    continue;
                }
            }

            ContextSwitch(State.Finished);
        }