FormDataSet
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
{
protected string _name;
protected string _type;
public string Name {
get {
return _name;
}
set {
_name = value;
}
}
public string Type {
get {
return _type;
}
set {
_type = value;
}
}
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 string _value;
public string Value {
get {
return _value;
}
set {
_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 (_name != null && _value != null) {
stream.WriteLine("content-disposition: form-data; name=\"" + _name.HtmlEncode(stream.Encoding) + "\"");
stream.WriteLine();
stream.WriteLine(_value.HtmlEncode(stream.Encoding));
}
}
public override void AsPlaintext(StreamWriter stream)
{
if (_name != null && _value != null) {
stream.Write(_name);
stream.Write('=');
stream.Write(_value);
}
}
public override void AsUrlEncoded(StreamWriter stream)
{
if (_name != null && _value != null) {
stream.Write(_name.UrlEncode(stream.Encoding));
stream.Write('=');
stream.Write(_value.UrlEncode(stream.Encoding));
}
}
}
private sealed class FileDataSetEntry : FormDataSetEntry
{
private FileEntry _value;
public FileEntry Value {
get {
return _value;
}
set {
_value = value;
}
}
public override bool Contains(string boundary, Encoding encoding)
{
if (_value == null || _value.Body == null)
return false;
byte[] bytes = encoding.GetBytes(boundary);
byte[] body = _value.Body;
int num = body.Length;
int i = 0;
for (int num2 = num - bytes.Length; i < num2; i++) {
if (body[i] == bytes[0]) {
bool flag = true;
for (int j = 1; j < num; j++) {
if (body[i + j] != bytes[j]) {
flag = false;
break;
}
}
if (flag)
return true;
}
}
return false;
}
public override void AsMultipart(StreamWriter stream)
{
if (_name != null && _value != null && _value.Body != null && _value.Type != null && _value.Name != null) {
stream.WriteLine("content-disposition: form-data; name=\"{0}\"; filename=\"{1}\"", new object[2] {
_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();
stream.BaseStream.Write(_value.Body, 0, _value.Body.Length);
stream.WriteLine();
}
}
public override void AsPlaintext(StreamWriter stream)
{
if (_name != null && _value != null && _value.Name != null) {
stream.Write(_name);
stream.Write('=');
stream.Write(_value.Name);
}
}
public override void AsUrlEncoded(StreamWriter stream)
{
if (_name != null && _value != null && _value.Name != null) {
stream.Write(_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 ?? Encoding.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 ?? Encoding.UTF8);
string webName = encoding.WebName;
MemoryStream memoryStream = new MemoryStream();
CheckBoundaries(encoding);
ReplaceCharset(encoding);
StreamWriter streamWriter = new StreamWriter(memoryStream, encoding);
if (_entries.Count > 0) {
if (_entries[0].Name.Equals("isindex") && _entries[0].Type.Equals("text", StringComparison.OrdinalIgnoreCase))
streamWriter.Write(((TextDataSetEntry)_entries[0]).Value);
else
_entries[0].AsUrlEncoded(streamWriter);
for (int i = 1; i < _entries.Count; i++) {
streamWriter.Write('&');
_entries[i].AsUrlEncoded(streamWriter);
}
}
streamWriter.Flush();
memoryStream.Position = 0;
return memoryStream;
}
public Stream AsPlaintext(Encoding encoding = null)
{
encoding = (encoding ?? Encoding.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, "textarea", StringComparison.OrdinalIgnoreCase) == 0) {
name = Normalize(name);
value = Normalize(value);
}
_entries.Add(new TextDataSetEntry {
Name = name,
Value = value,
Type = type
});
}
public void Append(string name, FileEntry value, string type)
{
if (string.Compare(type, "file", StringComparison.OrdinalIgnoreCase) == 0)
name = Normalize(name);
_entries.Add(new FileDataSetEntry {
Name = name,
Value = value,
Type = 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("hidden", StringComparison.OrdinalIgnoreCase))
_entries[i] = new TextDataSetEntry {
Name = formDataSetEntry.Name,
Type = formDataSetEntry.Type,
Value = encoding.WebName
};
}
}
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();
}
}
}