AngleSharp by Florian Rappl

<PackageReference Include="AngleSharp" Version="0.8.7" />

 FormDataSet

sealed class FormDataSet : IEnumerable<string>, IEnumerable
Bundles information stored in HTML forms.
using AngleSharp.Dom.Io; using AngleSharp.Extensions; using System; using System.Collections; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; namespace AngleSharp.Html { internal sealed class FormDataSet : IEnumerable<string>, IEnumerable { private abstract class FormDataSetEntry { private readonly string _name; private readonly string _type; public bool HasName => _name != null; public string Name => _name ?? string.Empty; public string Type => _type ?? InputTypeNames.Text; public FormDataSetEntry(string name, string type) { _name = name; _type = type; } public abstract void AsMultipart(StreamWriter stream); public abstract void AsPlaintext(StreamWriter stream); public abstract void AsUrlEncoded(StreamWriter stream); public abstract bool Contains(string boundary, Encoding encoding); } private sealed class TextDataSetEntry : FormDataSetEntry { private readonly string _value; public bool HasValue => _value != null; public string Value => _value; public TextDataSetEntry(string name, string value, string type) : base(name, type) { _value = value; } public override bool Contains(string boundary, Encoding encoding) { if (_value == null) return false; return _value.Contains(boundary); } public override void AsMultipart(StreamWriter stream) { if (base.HasName && HasValue) { stream.WriteLine("content-disposition: form-data; name=\"" + base.Name.HtmlEncode(stream.Encoding) + "\""); stream.WriteLine(); stream.WriteLine(_value.HtmlEncode(stream.Encoding)); } } public override void AsPlaintext(StreamWriter stream) { if (base.HasName && HasValue) { stream.Write(base.Name); stream.Write('='); stream.Write(_value); } } public override void AsUrlEncoded(StreamWriter stream) { if (base.HasName && HasValue) { stream.Write(base.Name.UrlEncode(stream.Encoding)); stream.Write('='); stream.Write(_value.UrlEncode(stream.Encoding)); } } } private sealed class FileDataSetEntry : FormDataSetEntry { private readonly IFile _value; public bool HasValue { get { if (_value != null) return _value.Name != null; return false; } } public bool HasValueBody { get { if (_value != null && _value.Body != null) return _value.Type != null; return false; } } public IFile Value => _value; public FileDataSetEntry(string name, IFile value, string type) : base(name, type) { _value = value; } public override bool Contains(string boundary, Encoding encoding) { if (_value == null || _value.Body == null) return false; return false; } public override void AsMultipart(StreamWriter stream) { if (base.HasName && HasValue && HasValueBody) { stream.WriteLine("content-disposition: form-data; name=\"{0}\"; filename=\"{1}\"", new object[2] { base.Name.HtmlEncode(stream.Encoding), _value.Name.HtmlEncode(stream.Encoding) }); stream.WriteLine("content-type: " + _value.Type); stream.WriteLine("content-transfer-encoding: binary"); stream.WriteLine(); stream.Flush(); _value.Body.CopyTo(stream.BaseStream); stream.WriteLine(); } } public override void AsPlaintext(StreamWriter stream) { if (base.HasName && HasValue) { stream.Write(base.Name); stream.Write('='); stream.Write(_value.Name); } } public override void AsUrlEncoded(StreamWriter stream) { if (base.HasName && HasValue) { stream.Write(base.Name.UrlEncode(stream.Encoding)); stream.Write('='); stream.Write(_value.Name.UrlEncode(stream.Encoding)); } } } private readonly List<FormDataSetEntry> _entries; private string _boundary; public string Boundary => _boundary; public FormDataSet() { _boundary = Guid.NewGuid().ToString(); _entries = new List<FormDataSetEntry>(); } public Stream AsMultipart(Encoding encoding = null) { encoding = (encoding ?? TextEncoding.Utf8); MemoryStream memoryStream = new MemoryStream(); CheckBoundaries(encoding); ReplaceCharset(encoding); StreamWriter streamWriter = new StreamWriter(memoryStream, encoding); streamWriter.WriteLine(); foreach (FormDataSetEntry entry in _entries) { streamWriter.Write("--"); streamWriter.WriteLine(_boundary); entry.AsMultipart(streamWriter); } streamWriter.Write("--"); streamWriter.Write(_boundary); streamWriter.Write("--"); streamWriter.Flush(); memoryStream.Position = 0; return memoryStream; } public Stream AsUrlEncoded(Encoding encoding = null) { encoding = (encoding ?? TextEncoding.Utf8); string webName = encoding.WebName; MemoryStream memoryStream = new MemoryStream(); CheckBoundaries(encoding); ReplaceCharset(encoding); StreamWriter streamWriter = new StreamWriter(memoryStream, encoding); int i = 0; bool flag = false; if (i < _entries.Count && _entries[i].HasName && _entries[i].Name.Equals(Tags.IsIndex) && _entries[i].Type.Equals(InputTypeNames.Text, StringComparison.OrdinalIgnoreCase)) { streamWriter.Write(((TextDataSetEntry)_entries[i]).Value); i++; } for (; i < _entries.Count; i++) { if (_entries[i].HasName) { if (flag) streamWriter.Write('&'); _entries[i].AsUrlEncoded(streamWriter); flag = true; } } streamWriter.Flush(); memoryStream.Position = 0; return memoryStream; } public Stream AsPlaintext(Encoding encoding = null) { encoding = (encoding ?? TextEncoding.Utf8); string webName = encoding.WebName; MemoryStream memoryStream = new MemoryStream(); CheckBoundaries(encoding); ReplaceCharset(encoding); StreamWriter streamWriter = new StreamWriter(memoryStream, encoding); streamWriter.WriteLine(); foreach (FormDataSetEntry entry in _entries) { entry.AsPlaintext(streamWriter); streamWriter.Write("\r\n"); } streamWriter.Flush(); memoryStream.Position = 0; return memoryStream; } public void Append(string name, string value, string type) { if (string.Compare(type, Tags.Textarea, StringComparison.OrdinalIgnoreCase) == 0) { name = Normalize(name); value = Normalize(value); } _entries.Add(new TextDataSetEntry(name, value, type)); } public void Append(string name, IFile value, string type) { if (string.Compare(type, InputTypeNames.File, StringComparison.OrdinalIgnoreCase) == 0) name = Normalize(name); _entries.Add(new FileDataSetEntry(name, value, type)); } private void ReplaceCharset(Encoding encoding) { for (int i = 0; i < _entries.Count; i++) { FormDataSetEntry formDataSetEntry = _entries[i]; if (!string.IsNullOrEmpty(formDataSetEntry.Name) && formDataSetEntry.Name.Equals("_charset_") && formDataSetEntry.Type.Equals(InputTypeNames.Hidden, StringComparison.OrdinalIgnoreCase)) _entries[i] = new TextDataSetEntry(formDataSetEntry.Name, encoding.WebName, formDataSetEntry.Type); } } private void CheckBoundaries(Encoding encoding) { bool flag = false; do { for (int i = 0; i < _entries.Count; i++) { if (flag = _entries[i].Contains(_boundary, encoding)) { _boundary = Guid.NewGuid().ToString(); break; } } } while (flag); } private static string Normalize(string value) { string[] value2 = value.Split(new string[3] { "\r\n", "\r", "\n" }, StringSplitOptions.None); return string.Join("\r\n", value2); } public IEnumerator<string> GetEnumerator() { return (from m in _entries select m.Name).GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } }