From 33a54101ec3fd37dabf2ae499753a8a3c164aed3 Mon Sep 17 00:00:00 2001
From: Nathan Ferreira <14365254+nathan130200@users.noreply.github.com>
Date: Tue, 7 May 2024 09:12:33 -0300
Subject: [PATCH] Update project.
XMPP# - Core
- Minor improvements.
- Fixed wrong indent chars & side for default formatting options.
- Fixed `Element.Value` returning entire inner text from all descendant nodes.
XMPP# - Expat
- Minor improvements.
- Better namespace handler (using namespace stack to track different XML scopes).
- All tests passing.
---
XmppSharp.Expat/CHANGELOG.md | 20 +-
XmppSharp.Expat/ExpatXmppParser.cs | 127 ++++++++--
XmppSharp.Expat/XmppSharp.Expat.csproj | 4 +-
XmppSharp.Test/ExpatParserTests.cs | 334 ++++++++++++++++++++++++-
XmppSharp.Test/XmppSharp.Test.csproj | 3 -
XmppSharp/AsyncDelegates.cs | 4 +
XmppSharp/CHANGELOG.md | 45 +++-
XmppSharp/Dom/Element.cs | 10 +-
XmppSharp/Parsers/BaseXmppParser.cs | 4 +-
XmppSharp/Parsers/DefaultXmppParser.cs | 2 +-
XmppSharp/Xml.cs | 4 +-
XmppSharp/XmlFormatting.cs | 7 +-
XmppSharp/XmppSharp.csproj | 2 +-
13 files changed, 520 insertions(+), 46 deletions(-)
diff --git a/XmppSharp.Expat/CHANGELOG.md b/XmppSharp.Expat/CHANGELOG.md
index bc6feca..b62fc13 100644
--- a/XmppSharp.Expat/CHANGELOG.md
+++ b/XmppSharp.Expat/CHANGELOG.md
@@ -1,5 +1,21 @@
# XMPP# Expat
This package implements the Expat parser in Xmpp Sharp library.
-# Common Types
-- `ExpatXmppParser`
\ No newline at end of file
+[![github](https://img.shields.io/badge/XMPP%23_%20Expat-ffe000?style=flat-square&logo=github&label=Github)](https://github.com/nathan130200/XmppSharp)
+
+### Common Types
+- `ExpatXmppParser`
+
+### Version History
+
+*1.0.0*
+
+- Initial Release
+
+___
+
+*1.0.1*
+
+- Minor improvements.
+- Better namespace handler (using namespace stack to track different XML scopes).
+- All tests passing.
\ No newline at end of file
diff --git a/XmppSharp.Expat/ExpatXmppParser.cs b/XmppSharp.Expat/ExpatXmppParser.cs
index 863c94a..764fad1 100644
--- a/XmppSharp.Expat/ExpatXmppParser.cs
+++ b/XmppSharp.Expat/ExpatXmppParser.cs
@@ -1,4 +1,7 @@
-using Expat;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Xml;
+using Expat;
using XmppSharp.Dom;
using XmppSharp.Exceptions;
using XmppSharp.Factory;
@@ -9,31 +12,57 @@ namespace XmppSharp.Parsers;
///
/// An enhanced XMPP parser built using Expat library.
///
-public class ExpatXmppParser : BaseXmppParser
+public partial class ExpatXmppParser : BaseXmppParser
{
private Parser _parser;
private Element _currentElem;
+ private XmlNamespaceManager _nsStack;
+ private NameTable _xmlNames;
+
+ void AddNamespacesToScope(IReadOnlyDictionary attrs)
+ {
+ foreach (var (key, value) in attrs)
+ {
+ if (key == "xmlns")
+ this._nsStack.AddNamespace(string.Empty, value);
+ else if (key.StartsWith("xmlns:"))
+ {
+ var prefix = key[(key.IndexOf(':') + 1)..];
+ this._nsStack.AddNamespace(prefix, value);
+ }
+ }
+ }
public ExpatXmppParser(ExpatEncodingType encoding = ExpatEncodingType.Utf8)
{
+ this._nsStack = new(this._xmlNames = new NameTable());
+
this._parser = new Parser(encoding);
this._parser.OnElementStart += e =>
{
- var entity = Xml.ExtractQualifiedName(e.Name);
+ this._nsStack.PushScope();
- string ns;
+ AddNamespacesToScope(e.Attributes);
- if (entity.HasPrefix)
- e.Attributes.TryGetValue($"xmlns:{entity.Prefix}", out ns);
- else
- e.Attributes.TryGetValue("xmlns", out ns);
+ var qname = Xml.ExtractQualifiedName(e.Name);
+
+ var ns = this._nsStack.LookupNamespace(qname.HasPrefix ? qname.Prefix : string.Empty);
if (e.Name is "iq" or "message" or "presence") // work-around
ns ??= Namespace.Client;
var element = ElementFactory.Create(e.Name, ns);
+ //foreach (var (key, value) in _nsStack.GetNamespacesInScope(XmlNamespaceScope.Local))
+ //{
+ // var att = string.IsNullOrWhiteSpace(key) ? "xmlns" : $"xmlns:{key}";
+ // element.SetAttribute(att, value);
+ //}
+
+ foreach (var (key, value) in e.Attributes)
+ element.SetAttribute(key, value);
+
if (e.Name == "stream:stream")
AsyncHelper.RunSync(() => FireStreamStart(element as StreamStream));
else
@@ -45,6 +74,8 @@ public ExpatXmppParser(ExpatEncodingType encoding = ExpatEncodingType.Utf8)
this._parser.OnElementEnd += e =>
{
+ this._nsStack.PopScope();
+
if (e.Value == "stream:stream")
AsyncHelper.RunSync(() => FireStreamEnd());
else
@@ -72,10 +103,21 @@ public ExpatXmppParser(ExpatEncodingType encoding = ExpatEncodingType.Utf8)
{
if (_currentElem != null)
{
+ var trimWS = _currentElem.GetAttribute("xml:space") != "preserve";
+
+ // skip whitespace if not explicit declared.
+ if (string.IsNullOrWhiteSpace(e.Value) && trimWS)
+ return;
+
+ var val = e.Value;
+
+ if (trimWS) // same for trailing whitespace
+ val = TrimWhitespace(val);
+
if (_currentElem.LastNode is Text text)
- text.Value += e.Value;
+ text.Value += val;
else
- _currentElem.AddChild(new Text(e.Value));
+ _currentElem.AddChild(new Text(val));
}
};
@@ -90,23 +132,78 @@ public ExpatXmppParser(ExpatEncodingType encoding = ExpatEncodingType.Utf8)
};
}
+ [GeneratedRegex("\n")]
+ protected static partial Regex NewLineRegex();
+
+ [GeneratedRegex(@"\s+")]
+ protected static partial Regex ContiguousSpaceRegex();
+
+ static string TrimWhitespace(string str)
+ {
+ if (string.IsNullOrEmpty(str))
+ return string.Empty;
+
+ str = NewLineRegex().Replace(str, string.Empty);
+ str = str.Replace("\t", " ");
+ str = str.Trim();
+ str = ContiguousSpaceRegex().Replace(str, " ");
+
+ return str;
+ }
+
public void Reset()
{
this.EnsureNotDisposed();
+
+ while (this._nsStack.PopScope())
+ ;
+
+ // reset namespace stack.
+ this._nsStack = new(this._xmlNames);
+
+ // reset the parser
this._parser.Reset();
}
- public void Write(byte[] buffer, int offset = 0, int length = -1, bool isFinalBlock = false)
+ public void Write(byte[] buffer, int offset, int length, bool isFinalBlock = false)
+ {
+ this.EnsureNotDisposed();
+
+ byte[] temp;
+
+ try
+ {
+ temp = GC.AllocateUninitializedArray(length, true);
+ Buffer.BlockCopy(buffer, offset, temp, 0, length);
+ this._parser.Feed(temp, length, isFinalBlock);
+ }
+ finally
+ {
+ temp = null;
+ }
+ }
+
+ public void Write(byte[] buffer, int length, bool isFinalBlock = false)
{
- length = length < 0 ? buffer.Length : length;
- Write(buffer[offset..length], isFinalBlock);
+ this.EnsureNotDisposed();
+ this._parser.Feed(buffer, length, isFinalBlock);
}
public void Write(byte[] buffer, bool isFinalBlock = false)
- => this._parser.Feed(buffer, buffer.Length, isFinalBlock);
+ {
+ this.EnsureNotDisposed();
+ this._parser.Feed(buffer, buffer.Length, isFinalBlock);
+ }
- protected override void OnDispose()
+ protected override void Disposing()
{
+ this._xmlNames = null;
+
+ while (this._nsStack.PopScope())
+ ;
+
+ this._nsStack = null;
+
this._parser?.Dispose();
this._parser = null;
}
diff --git a/XmppSharp.Expat/XmppSharp.Expat.csproj b/XmppSharp.Expat/XmppSharp.Expat.csproj
index 5171629..89562d4 100644
--- a/XmppSharp.Expat/XmppSharp.Expat.csproj
+++ b/XmppSharp.Expat/XmppSharp.Expat.csproj
@@ -1,7 +1,7 @@
- net8.0
+ net8.0;net7.0
enable
annotations
@@ -26,7 +26,7 @@
- 1.0.0
+ 1.0.1
true
nathan130200
git
diff --git a/XmppSharp.Test/ExpatParserTests.cs b/XmppSharp.Test/ExpatParserTests.cs
index 20f085a..39cee07 100644
--- a/XmppSharp.Test/ExpatParserTests.cs
+++ b/XmppSharp.Test/ExpatParserTests.cs
@@ -1,6 +1,8 @@
-using Expat;
+using System.IO.Compression;
+using Expat;
using XmppSharp.Dom;
using XmppSharp.Parsers;
+using XmppSharp.Protocol.Base;
namespace XmppSharp.Test;
@@ -26,6 +28,334 @@ public async Task ParseFromBuffer()
var result = await tcs.Task;
- Console.WriteLine("XML:\n" + result);
+ Console.WriteLine("XML:\n" + result.ToString(XmlFormatting.None));
+ }
+
+ [TestMethod]
+ public async Task ParseStreamError()
+ {
+ // Not declared: xmlns:stream="http://etherx.jabber.org/streams"
+ // but expat can parse even with missing namespace declaration 😛
+ // test output will be:
+
+ /*
+
+ Element: stream:error
+ Element: bad-namespace-prefix
+ Attribute: xmlns=urn:ietf:params:xml:ns:xmpp-streams
+
+ */
+
+ var xml = @"
+
+";
+
+ using var parser = new ExpatXmppParser();
+
+ var tcs = new TaskCompletionSource();
+
+ parser.OnStreamElement += e =>
+ {
+ tcs.TrySetResult(e);
+ return Task.CompletedTask;
+ };
+
+ using var stream = new MemoryStream(xml.GetBytes());
+
+ stream.Position = 0;
+
+ _ = Task.Run(async () =>
+ {
+ // simulate IO
+
+ try
+ {
+ var buf = new byte[16];
+ int cnt;
+
+ while (true)
+ {
+ cnt = await stream.ReadAsync(buf);
+ parser.Write(buf, cnt, cnt == 0);
+
+ if (cnt == 0)
+ break;
+ }
+ }
+ catch (Exception e)
+ {
+ tcs.TrySetException(e);
+ }
+ });
+
+ _ = Task.Delay(3000).ContinueWith(_ => tcs.TrySetCanceled());
+
+ var element = await tcs.Task;
+
+ Assert.IsNotNull(element);
+ Assert.AreEqual("stream:error", element.TagName);
+
+ Dump(element);
+ }
+
+ [TestMethod]
+ public async Task ParseStreamStart()
+ {
+ var xml = new StreamStream
+ {
+ From = "localhost",
+ To = "user1",
+ Id = Guid.NewGuid().ToString(),
+ Version = "1.0",
+ Language = "en"
+ }.StartTag();
+
+ using var parser = new ExpatXmppParser();
+
+ var tcs = new TaskCompletionSource();
+
+ parser.OnStreamStart += e =>
+ {
+ tcs.TrySetResult(e);
+ return Task.CompletedTask;
+ };
+
+ using var stream = new MemoryStream(xml.GetBytes());
+ stream.Position = 0;
+
+ _ = Task.Run(async () =>
+ {
+ // simulate IO
+
+ try
+ {
+ var buf = new byte[16];
+ int cnt;
+
+ while (true)
+ {
+ cnt = await stream.ReadAsync(buf);
+ parser.Write(buf, cnt, cnt == 0);
+
+ if (cnt == 0)
+ break;
+ }
+ }
+ catch (Exception e)
+ {
+ tcs.TrySetException(e);
+ }
+ });
+
+ _ = Task.Delay(3000).ContinueWith(_ => tcs.TrySetCanceled());
+
+ var element = await tcs.Task;
+
+ Console.WriteLine("XML:\n" + element.ToString(XmlFormatting.Indented));
+ }
+
+ [TestMethod]
+ public async Task ParseFromString()
+ {
+ // .NET XmlReader consider those whitespaces after XML Decl invalid and cannot parse, while expat just skip since it's still a well-formed XML.
+
+ var xml = @"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+";
+
+ using var parser = new ExpatXmppParser();
+
+ var tcs = new TaskCompletionSource();
+
+ parser.OnStreamElement += e =>
+ {
+ tcs.TrySetResult(e);
+ return Task.CompletedTask;
+ };
+
+ using var stream = new MemoryStream(xml.GetBytes());
+ stream.Position = 0;
+
+ _ = Task.Run(async () =>
+ {
+ // simulate IO
+
+ try
+ {
+ var buf = new byte[16];
+ int cnt;
+
+ while (true)
+ {
+ cnt = await stream.ReadAsync(buf);
+ parser.Write(buf, cnt, cnt == 0);
+
+ if (cnt == 0)
+ break;
+ }
+ }
+ catch (Exception e)
+ {
+ tcs.TrySetException(e);
+ }
+ });
+
+ _ = Task.Delay(3000).ContinueWith(_ => tcs.TrySetCanceled());
+
+ var element = await tcs.Task;
+
+ Console.WriteLine("XML:\n" + element.ToString(XmlFormatting.Indented));
+ }
+
+ [TestMethod]
+ public async Task ParseFromZipFile()
+ {
+ using var fs = File.OpenRead(Path.Combine(Directory.GetCurrentDirectory(), "zipfile.zip"));
+ using var archive = new ZipArchive(fs, ZipArchiveMode.Read);
+
+ var entry = archive.GetEntry("snippet.xml");
+ Assert.IsNotNull(entry);
+
+ using var parser = new ExpatXmppParser();
+
+ var tcs = new TaskCompletionSource();
+
+ parser.OnStreamElement += e =>
+ {
+ tcs.TrySetResult(e);
+ return Task.CompletedTask;
+ };
+
+ using var stream = entry.Open();
+
+ _ = Task.Run(async () =>
+ {
+ // simulate IO
+
+ var buf = new byte[entry.Length / 8];
+ int cnt;
+
+ while (true)
+ {
+ cnt = await stream.ReadAsync(buf);
+ parser.Write(buf, cnt, cnt == 0);
+
+ if (cnt == 0)
+ break;
+ }
+ });
+
+ _ = Task.Delay(3000).ContinueWith(_ => tcs.TrySetCanceled());
+
+ var element = await tcs.Task;
+
+ Assert.AreEqual("CodeSnippets", element.TagName);
+ Assert.AreEqual("http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet", element.DefaultNamespace);
+ Assert.AreEqual("CodeSnippet", element.FirstChild.TagName);
+
+ Console.WriteLine("XML:\n" + element.ToString(XmlFormatting.None) + "\n");
+
+ Dump(element);
+ }
+
+ [TestMethod]
+ public async Task ParseRealSample()
+ {
+ var xml = @"
+
+
+
+";
+
+ using var parser = new ExpatXmppParser();
+
+ var tcs = new TaskCompletionSource();
+
+ parser.OnStreamElement += e =>
+ {
+ tcs.TrySetResult(e);
+ return Task.CompletedTask;
+ };
+
+ using var stream = new MemoryStream(xml.GetBytes());
+ stream.Position = 0;
+
+ _ = Task.Run(async () =>
+ {
+ // simulate IO
+
+ try
+ {
+ var buf = new byte[16];
+ int cnt;
+
+ while (true)
+ {
+ cnt = await stream.ReadAsync(buf);
+ parser.Write(buf, cnt, cnt == 0);
+
+ if (cnt == 0)
+ break;
+ }
+ }
+ catch (Exception e)
+ {
+ tcs.TrySetException(e);
+ }
+ });
+
+ _ = Task.Delay(3000).ContinueWith(_ => tcs.TrySetCanceled());
+
+ var element = await tcs.Task;
+
+ Console.WriteLine("XML:\n" + element.ToString(XmlFormatting.Indented));
+ }
+
+ static void Dump(Element e, int depth = 0)
+ {
+ var tab = new string(' ', depth);
+
+ Console.Write(tab + "Element: " + e.TagName);
+
+ tab = new string(' ', depth + 1);
+
+ if (string.IsNullOrWhiteSpace(e.Value))
+ Console.WriteLine();
+ else
+ Console.WriteLine(" (value: {0})", e.Value);
+
+ foreach (var (key, value) in e.Attributes())
+ {
+ if (key == "xmlns " && value == e.Parent?.GetAttribute(key))
+ continue;
+
+ Console.WriteLine(tab + "Attribute: {0}={1}", key, value);
+ }
+
+ foreach (var child in e.Children())
+ Dump(child, depth + 3);
}
}
diff --git a/XmppSharp.Test/XmppSharp.Test.csproj b/XmppSharp.Test/XmppSharp.Test.csproj
index e8517a2..bf8bda9 100644
--- a/XmppSharp.Test/XmppSharp.Test.csproj
+++ b/XmppSharp.Test/XmppSharp.Test.csproj
@@ -29,9 +29,6 @@
PreserveNewest
-
- PreserveNewest
-
PreserveNewest
diff --git a/XmppSharp/AsyncDelegates.cs b/XmppSharp/AsyncDelegates.cs
index e098c7e..804f8a4 100644
--- a/XmppSharp/AsyncDelegates.cs
+++ b/XmppSharp/AsyncDelegates.cs
@@ -39,6 +39,7 @@ public static class AsyncUtilities
///
/// Delegate of the event that will be invoked.
/// Returns a task that invokes the event asynchronously.
+ [StackTraceHidden]
public static async Task InvokeAsync(this AsyncAction func)
{
try
@@ -59,6 +60,7 @@ public static async Task InvokeAsync(this AsyncAction func)
/// Delegate of the event that will be invoked.
/// Parameter value.
/// Returns a task that invokes the event asynchronously.
+ [StackTraceHidden]
public static async Task InvokeAsync(this AsyncAction func, TParam param)
{
try
@@ -77,6 +79,7 @@ public static async Task InvokeAsync(this AsyncAction func, TPar
///
/// Type of result that will be returned.
/// When awaited, returns the event value or the default value of if an error occurs.
+ [StackTraceHidden]
public static async Task InvokeAsync(this AsyncFunc func)
{
try
@@ -102,6 +105,7 @@ public static async Task InvokeAsync(this AsyncFunc f
/// When awaited, returns the event value or the default value of if an error occurs.
/// The error will be displayed in the debug window using .
///
+ [StackTraceHidden]
public static async Task InvokeAsync(this AsyncFunc func, TParam param)
{
try
diff --git a/XmppSharp/CHANGELOG.md b/XmppSharp/CHANGELOG.md
index 729c58e..b8e9610 100644
--- a/XmppSharp/CHANGELOG.md
+++ b/XmppSharp/CHANGELOG.md
@@ -1,49 +1,70 @@
# XMPP#
-[![github](https://img.shields.io/badge/XmppSharp-1?style=plastic&logo=github&label=Github)](https://github.com/nathan130200/XmppSharp)
+[![github](https://img.shields.io/badge/XMPP%23_%20Core-ffe000?style=flat-square&logo=github&label=Github)](https://github.com/nathan130200/XmppSharp)
A manipulation library and utility with the main objective to reduce the level of unnecessary verbosity for constructing XML tags for XMPP protocol, supporting `net6.0`, `net7.0` and `net8.0`.
-# Lastest Updates
+### Version History
+
+*3.0.0*
-**3.0.0**
-____
- Most big change! Bring back own XML implementation supporting nodes:
- `Element`
- `Text`
- `Comment`
- `Cdata`
-**3.1.0**
+____
+
+*3.1.0*
- Add enhanced utilities & helper methods to interact with element and nodes.
-**3.1.1**
____
+
+*3.1.1*
+
- Minor fixes.
- Fixed wrong sub classing around some elements.
- Added full control about XML formatting.
- In .Net6 use `TryParseHelper` helper methods to parse attribute values. While in .Net7 or higher use `IParsable` abstract static interfaces feature, for parsing attribute values.
-**3.1.2**
____
+
+*3.1.2*
+
- Added missing `StartTag` and `EndTag` in elements. Both strings will contains well-formed XML string.
- Ability to make a shallow copy of element instead a full copy with `Element.Clone(deep)` overload.
- More formatting options in `XmlFormatting` structure.
-**3.1.3**
____
+
+*3.1.3*
+
- Enhance XMPP parser with different ctors provide an Stream or an factory function to create an stream. `XmppParser::Reset()` no longer needs an stream as argument.
- Renamed `XmppParser::Advance` to `XmppParser::AdvanceAsync` for async version and leave `XmppParser::Advance` for sync method version.
- Added `GetAwaiter` in XMPP parser for simple calling `await myParser;` have same behaviour and return same result as calling `await myParser.AdvanceAsync()`
-**3.1.4**
____
+
+
+*3.1.4*
+
- Minor fixes around `XmppParser` and added helper method to advance and get next element.
-**3.1.5**
-___
+____
+
+*3.1.5*
+
- Rename `XmppParser` to `DefaultXmppParser` to indicade this uses regular .NET `XmlReader` to parse xmpp packets.
- Add basic abstraction layer to implement your own xmpp parser. Also i'm releasing a separated package `XmppSharp.Expat` to provide expat XMPP parser implementation. (Note: You must install native libraries to use expat.
- Added `AsyncHelper` (from `AspNetCore` repo) to calling async functions in sync methods.
-> In **XMPP#** repository i did an github actions to automatically build expat using vcpkg with most common systems: ubuntu, macos, windows but only x64 is working at this moment). Consider using [XmppShap.Expat](https://www.nuget.org/packages/XmppSharp.Expat/) package too if you need a fast and stable parser.
\ No newline at end of file
+> In **XMPP#** repository i did an github actions to automatically build expat using vcpkg with most common systems: ubuntu, macos, windows but only x64 is working at this moment). Consider using [XmppShap.Expat](https://www.nuget.org/packages/XmppSharp.Expat/) package too if you need a fast and stable parser.
+
+____
+
+*3.1.6*
+
+- Minor improvements.
+- Fixed wrong indent chars & side for default formatting options.
+- Fixed `Element.Value` returning entire inner text from all descendant nodes.
\ No newline at end of file
diff --git a/XmppSharp/Dom/Element.cs b/XmppSharp/Dom/Element.cs
index 1438e83..245089e 100644
--- a/XmppSharp/Dom/Element.cs
+++ b/XmppSharp/Dom/Element.cs
@@ -96,7 +96,7 @@ public IEnumerable DescendantsAndSelf()
public override string Value
{
- get => string.Concat(this.DescendantNodes().OfType().Select(x => x.Value));
+ get => string.Concat(this.Nodes().OfType().Select(x => x.Value));
set
{
this.Nodes().Remove();
@@ -113,6 +113,14 @@ public override string Value
public override string ToString()
=> this.ToString(XmlFormatting.None);
+ ///
+ /// Gets the XML string representation of the current element and its child nodes.
+ ///
+ /// Determines if result xml will be indented.
+ /// Well-formed XML serialized with the entire XML tree.
+ public string ToString(bool indented)
+ => this.ToString(indented ? XmlFormatting.Indented : XmlFormatting.None);
+
///
/// Gets the XML string representation of the current element and its child nodes.
///
diff --git a/XmppSharp/Parsers/BaseXmppParser.cs b/XmppSharp/Parsers/BaseXmppParser.cs
index fcd50b6..403ba5a 100644
--- a/XmppSharp/Parsers/BaseXmppParser.cs
+++ b/XmppSharp/Parsers/BaseXmppParser.cs
@@ -36,7 +36,7 @@ protected void EnsureNotDisposed()
throw new ObjectDisposedException(GetType().FullName);
}
- protected virtual void OnDispose()
+ protected virtual void Disposing()
{
}
@@ -47,7 +47,7 @@ public void Dispose()
return;
_disposed = true;
- OnDispose();
+ Disposing();
}
protected async Task FireStreamStart(StreamStream e)
diff --git a/XmppSharp/Parsers/DefaultXmppParser.cs b/XmppSharp/Parsers/DefaultXmppParser.cs
index 290e788..a6f77a0 100644
--- a/XmppSharp/Parsers/DefaultXmppParser.cs
+++ b/XmppSharp/Parsers/DefaultXmppParser.cs
@@ -69,7 +69,7 @@ public DefaultXmppParser(Func streamFactory, Encoding? encoding = defaul
Reset();
}
- protected override void OnDispose()
+ protected override void Disposing()
{
if (this._disposed)
return;
diff --git a/XmppSharp/Xml.cs b/XmppSharp/Xml.cs
index 6528e21..79e7d13 100644
--- a/XmppSharp/Xml.cs
+++ b/XmppSharp/Xml.cs
@@ -36,13 +36,13 @@ public static XmlQualifiedName ExtractQualifiedName(string source)
};
}
- internal static XmlWriter CreateWriter(StringBuilder output, in XmlFormatting formatting)
+ internal static XmlWriter CreateWriter(StringBuilder output, XmlFormatting formatting)
{
Require.NotNull(output);
var settings = new XmlWriterSettings
{
- Indent = formatting.IndentSize > 0,
+ Indent = formatting.IndentSize != 0,
IndentChars = formatting.IndentChars,
DoNotEscapeUriAttributes = formatting.DoNotEscapeUriAttributes,
WriteEndDocumentOnClose = formatting.WriteEndDocumentOnClose,
diff --git a/XmppSharp/XmlFormatting.cs b/XmppSharp/XmlFormatting.cs
index 27ca47f..b2814c0 100644
--- a/XmppSharp/XmlFormatting.cs
+++ b/XmppSharp/XmlFormatting.cs
@@ -1,4 +1,5 @@
-using System.Xml;
+using System.Diagnostics;
+using System.Xml;
namespace XmppSharp;
@@ -79,7 +80,7 @@ public XmlFormatting()
DoNotEscapeUriAttributes = false;
IndentSize = 0;
- IndentChars = "\t";
+ IndentChars = " ";
NewLineHandling = NewLineHandling.Replace;
NewLineOnAttributes = false;
@@ -96,6 +97,6 @@ public XmlFormatting()
///
public static XmlFormatting Indented { get; } = None with
{
- IndentSize = 2,
+ IndentSize = 4,
};
}
diff --git a/XmppSharp/XmppSharp.csproj b/XmppSharp/XmppSharp.csproj
index d6081c1..16fe6df 100644
--- a/XmppSharp/XmppSharp.csproj
+++ b/XmppSharp/XmppSharp.csproj
@@ -26,7 +26,7 @@
- 3.1.5
+ 3.1.6
true
nathan130200
git