public void TestHtmlDecode() { Assert.Equal(null, HEntity.HtmlDecode(null)); Assert.Equal("", HEntity.HtmlDecode("")); Assert.Equal(" \t ", HEntity.HtmlDecode(" \t ")); Assert.Equal("test", HEntity.HtmlDecode("test")); // named entities Assert.Equal("&", HEntity.HtmlDecode("&")); Assert.Equal("&test", HEntity.HtmlDecode("&test")); Assert.Equal("test&", HEntity.HtmlDecode("test&")); Assert.Equal("te&st", HEntity.HtmlDecode("te&st")); // Unknown entity Assert.Equal("&test;", HEntity.HtmlDecode("&test;")); Assert.Equal("", HEntity.HtmlDecode("&test;", true)); Assert.Equal("&test;", HEntity.HtmlDecode("&test;", false)); // Numeric entities Assert.Equal("&", HEntity.HtmlDecode("&")); Assert.Equal("&test", HEntity.HtmlDecode("&test")); Assert.Equal("test&", HEntity.HtmlDecode("test&")); Assert.Equal("te&st", HEntity.HtmlDecode("te&st")); // Invalid numeric Assert.Equal("Z6;", HEntity.HtmlDecode("Z6;")); Assert.Equal("", HEntity.HtmlDecode("Z6;", true)); Assert.Equal("d8;test", HEntity.HtmlDecode("d8;test")); Assert.Equal("test", HEntity.HtmlDecode("d8;test", true)); // Non closed entities Assert.Equal("test& test&test", HEntity.HtmlDecode("test& test&test")); }
public static HMessage TurnEntityToPet(HEntity entity, int petid, int pettypeid, string petcolor, ushort header) { var ret = new HMessage(header); ret.WriteInteger(1); ret.WriteInteger(entity.Id); ret.WriteString(entity.Name); ret.WriteString(entity.Motto); ret.WriteString(string.Concat(new object[] { petid, " ", pettypeid, " ", petcolor })); ret.WriteInteger(entity.Index); ret.WriteInteger(entity.Tile.X); ret.WriteInteger(entity.Tile.Y); ret.WriteString("0.0"); ret.WriteInteger(0); ret.WriteInteger(2); ret.WriteInteger(0); ret.WriteInteger(entity.Id); ret.WriteString(entity.Name); ret.WriteBoolean(false); ret.WriteInteger(0); ret.WriteInteger(0); ret.WriteBoolean(false); ret.WriteInteger(0); ret.WriteString("std"); return(ret); }
/// <summary> /// Serialize an escapable text content /// </summary> protected virtual void SerializeEscapableRawText(IEnumerable <HNode> content, TextWriter writer) { foreach (var node in content.OfType <HText>()) { writer.Write(HEntity.HtmlEncode(node.Value)); } }
/// <summary> /// Serialize an attribute /// </summary> protected virtual void SerializeAttribute(String name, String value, TextWriter writer) { if (!String.IsNullOrWhiteSpace(name)) { writer.Write(" {0}=\"{1}\"", name.Trim(), HEntity.HtmlEncode(value)); } }
private void OnRoomUsersPacket(DataInterceptedEventArgs e) { Task.Run(async() => { var entities = HEntity.Parse(e.Packet); foreach (var hEntity in entities) { var flag = true; // Updates user ids that should be visible if they have re-entered the room if (_users.ContainsKey(hEntity.Id) && _keepVisibleUsers.ContainsKey(_users[hEntity.Id])) { _keepVisibleUsers.Remove(_users[hEntity.Id]); // remove old index _keepVisibleUsers.Add(hEntity.Index, hEntity.Id); // add new index flag = false; } _users[hEntity.Id] = hEntity.Index; if (_muteIsActivated && flag) { await Task.Delay(150); await Connection.SendToClientAsync(In.RoomUserRemove, hEntity.Index.ToString()); } } }); }
private static void GetPlainText(StringBuilder builder, IEnumerable <HNode> nodes) { foreach (HNode node in nodes) { HElement element = node as HElement; if (element != null) { if (element.Name != "script" && element.Name != "style") { GetPlainText(builder, element.Nodes()); } } else { HText text = node as HText; if (text != null) { builder.Append(text + "\r\n"); } else { HEntity entity = node as HEntity; if (entity != null) { builder.Append(entity.Value + "\r\n"); } } } } }
public static int WhisperFixerInt(HEntity ent) { if (GlobalLists.whisperfix.Find(f => f.entity == ent) != null) { return(GlobalLists.whisperfix.Find(f => f.entity == ent).bubbleid); } else { return(18); } }
public static string FindUsernameByEntity(HEntity entity) { if (entity != null) { return(entity.Name); } else { return(null); } }
public void OnUsers(DataInterceptedEventArgs obj) { foreach (var entity in HEntity.Parse(obj.Packet)) { UsersData.Add(new LocalHEntity { Id = entity.Id, Index = entity.Index, Name = entity.Name }); } }
public void GetRoomUsers(DataInterceptedEventArgs e) { foreach (HEntity hentity1 in HEntity.Parse(e.Packet)) { HEntity hentity = hentity1; if (Users.ContainsKey(hentity.Name)) { Users.Remove(hentity.Name); } Users.Add(hentity.Name, hentity); } }
/// <summary> /// Parse a comment /// </summary> protected ParsedToken ParseComment() { // We are in comment _State = ParseState.Comment; // Read loop CharInfo c; int s = 0; // s : state // 0 : in comment // 1 : first end tag '-' // 2 : second end tag '-' while ((c = ReadChar()) != CharInfo.EOF) { if (c == '-') { if (s == 0) { s = 1; } else { s = 2; } } else if (c == '>' && s == 2) { break; // End tag stop the loop } else { s = 0; // Reset state } } if (c == CharInfo.EOF) { throw new ParseError("End of file unexpected, comment not closed.", ReadPosition); } // Back to content state _State = ParseState.Content; ResetTagBuffer(); // Returns comment String comment = GetCurrentRead(true); comment = comment.Substring(4, comment.Length - 7).Trim(); return(new ParsedComment() { Position = _CurrentPosition, Text = HEntity.HtmlDecode(comment, RemoveUnknownOrInvalidEntities) }); }
public void InUserEnterRoom(DataInterceptedEventArgs obj) { HEntity[] array = HEntity.Parse(obj.Packet); if (array.Length != 0) { foreach (HEntity hentity in array) { hentity.Motto = String.Empty; if (!users.ContainsKey(hentity.Id)) { users.Add(hentity.Id, hentity); } } } WriteRegistrationUsers(users.Count); }
public void TestFindByName() { var entity = HEntity.FindEntityByName("amp"); Assert.Equal("amp", entity.Name); entity = HEntity.FindEntityByName("acE"); Assert.Equal("acE", entity.Name); Assert.Null(HEntity.FindEntityByName("unknown")); Assert.Null(HEntity.FindEntityByName(" ")); Assert.Null(HEntity.FindEntityByName("")); Assert.Null(HEntity.FindEntityByName(null)); foreach (var ent in HEntity.GetEntities()) { entity = HEntity.FindEntityByName(ent.Name); Assert.Same(ent, entity); } }
/// <summary> /// Parse a text content /// </summary> protected ParsedContent ParseText() { // Loop read CharInfo c; while ((c = ReadChar(false)) != CharInfo.EOF && c != '<') { AddToCurrentRead(c); } if (c != CharInfo.EOF) { SaveChar(c); } // Returns parse result return(new ParsedText() { Position = _CurrentPosition, Text = HEntity.HtmlDecode(GetCurrentRead(true), RemoveUnknownOrInvalidEntities) }); }
private void HandleGameObjects(HPacket packet, bool isOutgoing) { packet.Position = 0; if (!isOutgoing) { if (packet.Id == In.Users) { HEntity[] entities = HEntity.Parse(packet); foreach (HEntity entity in entities) { _entities[entity.Index] = entity; } _container.OnEntitiesLoaded(entities.Length); } else if (packet.Id == In.Items) { HWallItem[] wallItems = HWallItem.Parse(packet); foreach (HWallItem wallItem in wallItems) { _wallItems[wallItem.Id] = wallItem; } _container.OnWallItemsLoaded(wallItems.Length); } else if (packet.Id == In.Objects) { HFloorItem[] floorItems = HFloorItem.Parse(packet); foreach (HFloorItem floorItem in floorItems) { _floorItems[floorItem.Id] = floorItem; } _container.OnFloorItemsLoaded(floorItems.Length); } else if (packet.Id == In.FloorHeightMap) { _entities.Clear(); _wallItems.Clear(); _floorItems.Clear(); } } packet.Position = 0; }
public void TestFindByChars_String() { var entity = HEntity.FindEntityByChars("&"); Assert.Equal("amp", entity.Name); entity = HEntity.FindEntityByChars("\u223E\u0333"); Assert.Equal("acE", entity.Name); Assert.Null(HEntity.FindEntityByChars("unknown")); Assert.Null(HEntity.FindEntityByChars(" ")); Assert.Null(HEntity.FindEntityByChars("")); Assert.Null(HEntity.FindEntityByChars((String)null)); foreach (var ent in HEntity.GetEntities()) { entity = HEntity.FindEntityByChars(ent.ToString()); //Assert.Equal(ent.Name, entity.Name); Assert.Equal(ent.Characters, entity.Characters); } }
public void TestHtmlEncode() { Assert.Equal(null, HEntity.HtmlEncode(null)); Assert.Equal("", HEntity.HtmlEncode("")); Assert.Equal(" \t ", HEntity.HtmlEncode(" \t ")); Assert.Equal("test", HEntity.HtmlEncode("test")); // named entities Assert.Equal("&", HEntity.HtmlEncode("&")); Assert.Equal("&test", HEntity.HtmlEncode("&test")); Assert.Equal("test&", HEntity.HtmlEncode("test\u0026")); Assert.Equal("te&st", HEntity.HtmlEncode("te&st")); // Numeric entities Assert.Equal("ɠ", HEntity.HtmlEncode("\u0260")); // Multiple chars Assert.Equal("∾Test", HEntity.HtmlEncode("\u223ETest")); Assert.Equal("∾̳Test", HEntity.HtmlEncode("\u223E\u0333Test")); Assert.Equal("∾&Test", HEntity.HtmlEncode("\u223E\u0026Test")); }
public void TestFindByChars_Chars() { var entity = HEntity.FindEntityByChars('&'); Assert.Equal("amp", entity.Name); entity = HEntity.FindEntityByChars('\u223E', '\u0333'); Assert.Equal("acE", entity.Name); Assert.Null(HEntity.FindEntityByChars('a')); Assert.Null(HEntity.FindEntityByChars('&', '&')); Assert.Null(HEntity.FindEntityByChars('a', '&')); Assert.Null(HEntity.FindEntityByChars('\u223E', 'a')); Assert.Null(HEntity.FindEntityByChars('\u223E', '\u0333', 'a')); Assert.Null(HEntity.FindEntityByChars((char[])null)); foreach (var ent in HEntity.GetEntities()) { entity = HEntity.FindEntityByChars(ent.ToString()); //Assert.Equal(ent.Name, entity.Name); Assert.Equal(ent.Characters, entity.Characters); } }
public void TestBugHtmlEncodeElementAtTheEnd() { Assert.Equal("Test <html>", HEntity.HtmlEncode("Test <html>")); // The bug was fired because '>' is a start char for a multiple chars. }
private void IncomingUser(DataInterceptedEventArgs e) { int entityCount = e.Packet.ReadInteger(); var entityList = new List <HEntity>(entityCount); for (int i = 0; i < entityList.Capacity; i++) { int id = e.Packet.ReadInteger(); string name = e.Packet.ReadString(); string motto = e.Packet.ReadString(); string figureId = e.Packet.ReadString(); int index = e.Packet.ReadInteger(); int x = e.Packet.ReadInteger(); int y = e.Packet.ReadInteger(); var z = double.Parse( e.Packet.ReadString(), CultureInfo.InvariantCulture); e.Packet.ReadInteger(); int type = e.Packet.ReadInteger(); HGender gender = HGender.Unisex; string favoriteGroup = string.Empty; #region Switch: type switch (type) { case 1: { gender = SKore.ToGender(e.Packet.ReadString()); e.Packet.ReadInteger(); e.Packet.ReadInteger(); favoriteGroup = e.Packet.ReadString(); e.Packet.ReadString(); e.Packet.ReadInteger(); e.Packet.ReadBoolean(); break; } case 2: { e.Packet.ReadInteger(); e.Packet.ReadInteger(); e.Packet.ReadString(); e.Packet.ReadInteger(); e.Packet.ReadBoolean(); e.Packet.ReadBoolean(); e.Packet.ReadBoolean(); e.Packet.ReadBoolean(); e.Packet.ReadBoolean(); e.Packet.ReadBoolean(); e.Packet.ReadInteger(); e.Packet.ReadString(); break; } case 4: { e.Packet.ReadString(); e.Packet.ReadInteger(); e.Packet.ReadString(); for (int j = e.Packet.ReadInteger(); j > 0; j--) { e.Packet.ReadShort(); } break; } } #endregion var entity = new HEntity(id, index, name, new HPoint(x, y, z), motto, gender, figureId, favoriteGroup); entityList.Add(entity); } foreach (HEntity Player in entityList) { playerList.Items.Add(Player.Index + "`" + Player.Name + "`" + Player.FigureId + "`" + Player.Gender + "`" + Player.Motto); } }
/// <summary> /// Deserialize as a list of nodes /// </summary> public IEnumerable <HNode> Deserialize(TextReader reader, Func <Exception, bool> errorHandler = null) { if (reader == null) { throw new ArgumentNullException("reader"); } // Create the parser var parser = new HParser(reader); parser.RemoveUnknownOrInvalidEntities = this.RemoveUnknownOrInvalidEntities; var token = ParseNext(parser, errorHandler); Stack <HElement> opened = new Stack <HElement>(); HXmlDeclaration currentXDecl = null; String tag; HNode tokenToReturns = null; while (token != null) { switch (token.TokenType) { case ParsedTokenType.Text: var htxt = new HText(HEntity.HtmlDecode(((ParsedText)token).Text, RemoveUnknownOrInvalidEntities)); if (opened.Count > 0) { ProtectAddOnPeek(opened, htxt, errorHandler); } else { tokenToReturns = htxt; } break; case ParsedTokenType.CData: var hcd = new HCData(((ParsedCData)token).Text); if (opened.Count > 0) { ProtectAddOnPeek(opened, hcd, errorHandler); } else { tokenToReturns = hcd; } break; case ParsedTokenType.Comment: var hcom = new HComment(HEntity.HtmlDecode(((ParsedComment)token).Text, RemoveUnknownOrInvalidEntities)); if (opened.Count > 0) { ProtectAddOnPeek(opened, hcom, errorHandler); } else { tokenToReturns = hcom; } break; case ParsedTokenType.OpenTag: opened.Push(new HElement(((ParsedTag)token).TagName)); break; case ParsedTokenType.AutoClosedTag: System.Diagnostics.Debug.Assert(opened.Count > 0, "Opened tags are empty when receiving AutoClosedTag."); System.Diagnostics.Debug.Assert(opened.Peek().Name == ((ParsedTag)token).TagName, "AutoClosedTag and opened element are not same tag name."); var actag = opened.Pop(); if (opened.Count > 0) { ProtectAddOnPeek(opened, actag, errorHandler); } else { tokenToReturns = actag; } break; case ParsedTokenType.CloseTag: System.Diagnostics.Debug.Assert(opened.Count > 0, "Opened tags are empty when receiving CloseTag."); System.Diagnostics.Debug.Assert(opened.Peek().Name == ((ParsedTag)token).TagName, "CloseTag and opened element are not same tag name."); // Tag with text content String tagName = opened.Peek().Name; if (IsRawElement(tagName) || IsEscapableRawElement(tagName)) { token = ParseContentTextNext(tagName, parser, errorHandler); continue; } break; case ParsedTokenType.EndTag: tag = ((ParsedTag)token).TagName; HElement helm; // Close all elements that not matching the tag while (opened.Count > 0 && !String.Equals(opened.Peek().Name, tag, StringComparison.OrdinalIgnoreCase)) { helm = opened.Pop(); if (opened.Count > 0) { ProtectAddOnPeek(opened, helm, errorHandler); } else { yield return(helm); } } // If we are opened tag, then close it because we find our element if (opened.Count > 0) { helm = opened.Pop(); if (opened.Count > 0) { ProtectAddOnPeek(opened, helm, errorHandler); } else { yield return(helm); } } break; case ParsedTokenType.OpenProcessInstruction: if (currentXDecl != null) { while ((token = ParseNext(parser, errorHandler)) != null && token.TokenType != ParsedTokenType.CloseProcessInstruction) { ; } ProcessError(new ParseError("XML declaration already opened."), errorHandler); } tag = ((ParsedTag)token).TagName; if (!String.Equals("xml", tag, StringComparison.OrdinalIgnoreCase)) { while ((token = ParseNext(parser, errorHandler)) != null && token.TokenType != ParsedTokenType.CloseProcessInstruction) { ; } ProcessError(new ParseError(String.Format("Unexpected '{0}' process instruction.", tag)), errorHandler); } currentXDecl = new HXmlDeclaration(null, null, null); break; case ParsedTokenType.CloseProcessInstruction: if (currentXDecl == null) { ProcessError(new ParseError("No XML declaration opened."), errorHandler); } else { if (opened.Count > 0) { ProtectAddOnPeek(opened, currentXDecl, errorHandler); } else { tokenToReturns = currentXDecl; } } currentXDecl = null; break; case ParsedTokenType.Doctype: var vs = ((ParsedDoctype)token).Values ?? new String[0]; var hdt = new HDocumentType( vs.Length > 0 ? vs[0] : null, vs.Length > 1 ? vs[1] : null, vs.Length > 2 ? vs[2] : null, vs.Length > 3 ? vs[3] : null ); if (opened.Count > 0) { ProtectAddOnPeek(opened, hdt, errorHandler); } else { tokenToReturns = hdt; } break; case ParsedTokenType.Attribute: var attr = (ParsedAttribute)token; // Xml declaration ? if (currentXDecl != null) { if (String.Equals("version", attr.Name, StringComparison.OrdinalIgnoreCase)) { currentXDecl.Version = attr.Value; } else if (String.Equals("encoding", attr.Name, StringComparison.OrdinalIgnoreCase)) { currentXDecl.Encoding = attr.Value; } else if (String.Equals("standalone", attr.Name, StringComparison.OrdinalIgnoreCase)) { currentXDecl.Standalone = attr.Value; } else { ProcessError(new ParseError(String.Format("Invalid XML declaration attribute : ''", attr.Name)), errorHandler); } } System.Diagnostics.Debug.Assert(opened.Count > 0, "No element opened for the attribtue."); ProtectAddOnPeek(opened, new HAttribute(attr.Name, attr.Value), errorHandler); break; //default: // break; } // Returns a token if we have one if (tokenToReturns != null) { yield return(tokenToReturns); tokenToReturns = null; } // Next token token = ParseNext(parser, errorHandler); } // Close all opened elements while (opened.Count > 0) { yield return(opened.Pop()); } }
/// <summary> /// Parse a content as raw text. /// </summary> /// <remarks> /// This method is used for parsing the content of the script, style tag content. /// The parsing is continue until matching the end of the <paramref name="tag"/>. /// If <paramref name="tag"/> is null or empty then we accept all endtag. /// </remarks> /// <exception cref="InvalidOperationException"> /// Raised when the parser is not in a normal state : all tag need to be closed. /// </exception> /// <param name="tag">Tag name for the end tag expected.</param> /// <returns>Content</returns> public ParsedText ParseContentText(String tag) { // Verify if (this._State != ParseState.Content) { throw new InvalidOperationException("Can't read a content in a opened tag."); } // Read loop var start = SourceReader.Position; CharInfo c; while ((c = ReadChar(false)) != CharInfo.EOF) { // End detected ? if (c == '<') { var endTagPos = c.Position; StringBuilder saveTag = new StringBuilder(15); saveTag.Append(c); while ((c = ReadChar(false)) != CharInfo.EOF && Char.IsWhiteSpace(c.AsChar)) { saveTag.Append(c.AsChar); } if (c == '/') { // Pass '/' saveTag.Append(c); while ((c = ReadChar(false)) != CharInfo.EOF && Char.IsWhiteSpace(c.AsChar)) { saveTag.Append(c.AsChar); } if (c != CharInfo.EOF) { // Pass tag name StringBuilder tagName = new StringBuilder(10); saveTag.Append(c.AsChar); tagName.Append(c.AsChar); while ((c = ReadChar(false)) != CharInfo.EOF && IsAttributeNameChar(c.AsChar)) { saveTag.Append(c.AsChar); tagName.Append(c.AsChar); } // We find the good end tag ? if (c != CharInfo.EOF) { if (String.IsNullOrEmpty(tag) || String.Equals(tagName.ToString(), tag, StringComparison.OrdinalIgnoreCase)) { SaveChar(c); // Search the good end while ((c = ReadChar(false)) != CharInfo.EOF && Char.IsWhiteSpace(c.AsChar)) { saveTag.Append(c.AsChar); } if (c == '>') { // Save the end tag for the next parse _CurrentToken = ParsedTag.EndTag(tagName.ToString()); _CurrentToken.Position = endTagPos; c = CharInfo.EOF; // Don't save the char // Exit the loop break; } } } } } // If here then we don't find a good end tag we convert to 'text' var etp = endTagPos; foreach (var st in saveTag.ToString()) { AddToCurrentRead(new CharInfo(st, etp++)); } } // AddToCurrentRead(c); } if (c != CharInfo.EOF) { SaveChar(c); } // Returns parse result LastParsed = new ParsedText() { Position = start, Text = HEntity.HtmlDecode(GetCurrentRead(true), RemoveUnknownOrInvalidEntities) }; return((ParsedText)LastParsed); }
/// <summary> /// Serialize a text /// </summary> protected virtual void SerializeText(HText text, TextWriter writer) { writer.Write(HEntity.HtmlEncode(text.Value)); }
/// <summary> /// Serialize a comment /// </summary> protected virtual void SerializeComment(HComment comment, TextWriter writer) { writer.Write("<!-- "); writer.Write(HEntity.HtmlEncode(comment.Value)); writer.Write(" -->"); }
public EntityWhisper(HEntity ent, int bubble) { entity = ent; bubbleid = bubble; }
private object[] CreateValues(DataInterceptedEventArgs args) { ParameterInfo[] parameters = Method.GetParameters(); var values = new object[parameters.Length]; int position = 0; for (int i = 0; i < values.Length; i++) { ParameterInfo parameter = parameters[i]; switch (Type.GetTypeCode(parameter.ParameterType)) { case TypeCode.UInt16: { if (parameter.Name.Equals("id", StringComparison.OrdinalIgnoreCase)) { values[i] = args.Packet.Id; } else { values[i] = args.Packet.ReadUInt16(ref position); } break; } case TypeCode.Int32: values[i] = args.Packet.ReadInt32(ref position); break; case TypeCode.Boolean: values[i] = args.Packet.ReadBoolean(ref position); break; case TypeCode.Byte: values[i] = args.Packet.ReadByte(ref position); break; case TypeCode.String: values[i] = args.Packet.ReadUTF8(ref position); break; case TypeCode.Double: values[i] = args.Packet.ReadDouble(ref position); break; case TypeCode.Object: { if (parameter.ParameterType == typeof(DataInterceptedEventArgs)) { values[i] = args; } else if (parameter.ParameterType == typeof(HPacket)) { values[i] = args.Packet; } else if (parameter.ParameterType == typeof(HPoint)) { values[i] = new HPoint(args.Packet.ReadInt32(ref position), args.Packet.ReadInt32(ref position)); } else if (parameter.ParameterType == typeof(byte[])) { int length = args.Packet.ReadInt32(ref position); values[i] = args.Packet.ReadBytes(length, ref position); } else if (typeof(IList <HEntity>).IsAssignableFrom(parameter.ParameterType)) { args.Packet.Position = 0; values[i] = HEntity.Parse(args.Packet); } else if (typeof(IList <HFloorItem>).IsAssignableFrom(parameter.ParameterType)) { args.Packet.Position = 0; values[i] = HFloorItem.Parse(args.Packet); } else if (typeof(IList <HWallItem>).IsAssignableFrom(parameter.ParameterType)) { args.Packet.Position = 0; values[i] = HWallItem.Parse(args.Packet); } break; } } } return(values); }
/// <summary> /// Parse in tag /// </summary> protected ParsedToken ParseInTag() { _CurrentRead = null; // Whitespaces CharInfo c; while ((c = ReadChar(false)) != CharInfo.EOF && Char.IsWhiteSpace(c.AsChar)) { ; } var cpos = c.Position; // EOF ? if (c == CharInfo.EOF) { _CurrentToken = null; _State = ParseState.Content; ResetTagBuffer(); throw new ParseError("Unexpected end of file. Tag not closed.", ReadPosition); } // End of auto closed tag ? else if (c == '/' && _State == ParseState.Tag) { CharInfo saveSlash = c; bool spaces = false; while ((c = ReadChar(false)) != CharInfo.EOF && Char.IsWhiteSpace(c.AsChar)) { spaces = true; } if (c != '>') { // Prepare a correct next tag SaveChar(new CharInfo('>', (c == CharInfo.EOF) ? saveSlash.Position : c.Position)); SaveChar(saveSlash); throw new ParseError("Invalid char after '/'. End of auto closed tag expected.", cpos); } if (spaces) { // Prepare a correct next tag SaveChar(c); SaveChar(saveSlash); // Raise the error throw new ParseError("Invalid auto closed tag, '/' need to be follow by '>'.", cpos); } // Returns autoclosed var result = ParsedTag.AutoClosedTag(((ParsedTag)_CurrentToken).TagName); result.Position = cpos; _CurrentToken = null; _CurrentRead = null; _State = ParseState.Content; ResetTagBuffer(); return(result); } // End of process instruction else if (c == '?' && _State == ParseState.ProcessInstruction) { c = ReadChar(false); if (c != '>') { throw new ParseError("Invalid char after '?'. End of process instruction expected.", cpos); } // Returns processinstruction var result = ParsedTag.CloseProcessInstruction(((ParsedTag)_CurrentToken).TagName); result.Position = cpos; _CurrentToken = null; _CurrentRead = null; _State = ParseState.Content; ResetTagBuffer(); return(result); } else if (c == '>') { // Check tag if (_State == ParseState.ProcessInstruction) { throw new ParseError("A process instruction need to be closed with '?>'.", cpos); } // Returns close var result = ParsedTag.CloseTag(((ParsedTag)_CurrentToken).TagName); result.Position = cpos; _CurrentToken = null; _CurrentRead = null; _State = ParseState.Content; ResetTagBuffer(); return(result); } // Get the attribute name if (!IsAttributeNameChar(c.AsChar)) { throw new ParseError("Unexpected character.", cpos); } AddToCurrentRead(c); while ((c = ReadChar(false)) != CharInfo.EOF && IsAttributeNameChar(c.AsChar)) { AddToCurrentRead(c); } if (c != CharInfo.EOF) { SaveChar(c); } String attrName = GetCurrentRead(true); ParsePosition attrPos = cpos; // Whitespaces while ((c = ReadChar(false)) != CharInfo.EOF && Char.IsWhiteSpace(c.AsChar)) { ; } // Attribute whithout value if (c != '=') { SaveChar(c); // Attribute whithout content return(new ParsedAttribute() { Position = attrPos, Name = attrName, Value = null, Quote = '\0' }); } // Whitespaces while ((c = ReadChar(false)) != CharInfo.EOF && Char.IsWhiteSpace(c.AsChar)) { ; } // Search the value if (c == 0 || c == '/' || c == '?' || c == '>') { _CurrentAttr = new ParsedAttribute() { Position = attrPos, Name = attrName, Value = null, Quote = '\0' }; if (c != CharInfo.EOF) { SaveChar(c); } throw new ParseError("Attribute value expected.", ReadPosition); } // Quoted value ? _CurrentRead = null; char quote = '\0'; if (c == '"' || c == '\'') { quote = c.AsChar; while ((c = ReadChar(false)) != CharInfo.EOF && c != quote) { AddToCurrentRead(c); } _CurrentAttr = new ParsedAttribute() { Position = attrPos, Name = attrName, Value = HEntity.HtmlDecode(GetCurrentRead(true), RemoveUnknownOrInvalidEntities), Quote = quote }; if (c == CharInfo.EOF) { throw new ParseError("Unexpected end of file. Attribute is not closed.", ReadPosition); } var result = _CurrentAttr; _CurrentAttr = null; return(result); } // Unquoted value AddToCurrentRead(c); while ((c = ReadChar(false)) != CharInfo.EOF && !Char.IsWhiteSpace(c.AsChar) && c != '"' && c != '\'' && c != '=' && c != '<' && c != '>' && c != '`') { AddToCurrentRead(c); } SaveChar(c); return(new ParsedAttribute() { Position = attrPos, Name = attrName, Value = HEntity.HtmlDecode(GetCurrentRead(true), RemoveUnknownOrInvalidEntities), Quote = quote }); }
/// <summary> /// Parse the next element /// </summary> public ParsedToken Parse() { CharInfo c; // If end of stream when stop here if (EOF) { return(null); } // Current token defined if (_CurrentToken != null) { // End tag out Doctype : error while end tag or doctype parsing, reset parser if (_CurrentToken.TokenType == ParsedTokenType.EndTag || _CurrentToken.TokenType == ParsedTokenType.Doctype) { _CurrentRead = null; _State = ParseState.Content; ResetTagBuffer(); LastParsed = _CurrentToken; _CurrentToken = null; return(LastParsed); } } // Current Attribute defined if (_CurrentAttr != null) { LastParsed = _CurrentAttr; _CurrentAttr = null; return(LastParsed); } // Current Read not empty ? if (_CurrentRead != null) { bool returnLast = true; switch (_State) { // Returns a non closed comment case ParseState.Comment: String comment = GetCurrentRead(true); comment = comment.Substring(4).TrimStart(); LastParsed = new ParsedComment() { Position = _CurrentPosition, Text = HEntity.HtmlDecode(comment, RemoveUnknownOrInvalidEntities) }; break; // Returns a text case ParseState.Content: LastParsed = new ParsedText() { Position = _CurrentPosition, Text = HEntity.HtmlDecode(GetCurrentRead(true), RemoveUnknownOrInvalidEntities) }; break; // Returns a text case ParseState.Doctype: case ParseState.ProcessInstruction: case ParseState.EndTag: case ParseState.Tag: //LastParsed = new ParsedText() { // Position = _CurrentPosition, // Text = GetCurrentRead(true) //}; _State = ParseState.Content; LastParsed = ParseText(); break; // We forget the result //default: // returnLast = false; // break; } _State = ParseState.Content; ResetTagBuffer(); if (returnLast) { return(LastParsed); } } // Read loop while (true) { // Read next char c = ReadChar(); // EOF ? if (c == CharInfo.EOF) { // Check unexpected EOF if (_State != ParseState.Content) { _State = ParseState.Content; ResetTagBuffer(); throw new ParseError("End of file unexpected.", ReadPosition); } // Stop the parsing LastParsed = null; EOF = true; return(null); } // Other case switch (_State) { // In text case ParseState.Content: if (c == '<') { LastParsed = ParseStartTag(); } else { LastParsed = ParseText(); } return(LastParsed); // In tag or process instruction case ParseState.Tag: case ParseState.Doctype: case ParseState.ProcessInstruction: SaveChar(c); LastParsed = ParseInTag(); return(LastParsed); default: break; } } }