// 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); }
// 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); }
// 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)); }
/// <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); }