HtmlFormElement
sealed class HtmlFormElement : HtmlElement, IHtmlFormElement, IHtmlElement, IElement, INode, IEventTarget, IMarkupFormattable, IParentNode, IChildNode, INonDocumentTypeChildNode, IElementCssInlineStyle, IDisposable
Represents the form element.
using AngleSharp.Dom.Collections;
using AngleSharp.Dom.Css;
using AngleSharp.Extensions;
using AngleSharp.Html;
using AngleSharp.Network;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace AngleSharp.Dom.Html
{
internal sealed class HtmlFormElement : HtmlElement, IHtmlFormElement, IHtmlElement, IElement, INode, IEventTarget, IMarkupFormattable, IParentNode, IChildNode, INonDocumentTypeChildNode, IElementCssInlineStyle, IDisposable
{
private static readonly string UsAscii = "us-ascii";
private HtmlFormControlsCollection _elements;
private Task<IDocument> ;
private CancellationTokenSource _cts;
public IElement this[int index] {
get {
return Elements[index];
}
}
public IElement this[string name] {
get {
return Elements[name];
}
}
public string Name {
get {
return GetOwnAttribute(AttributeNames.Name);
}
set {
SetOwnAttribute(AttributeNames.Name, value);
}
}
public int Length => Elements.Length;
public HtmlFormControlsCollection Elements => _elements ?? (_elements = new HtmlFormControlsCollection(this, null));
IHtmlFormControlsCollection IHtmlFormElement.Elements {
get {
return Elements;
}
}
public string AcceptCharset {
get {
return GetOwnAttribute(AttributeNames.AcceptCharset);
}
set {
SetOwnAttribute(AttributeNames.AcceptCharset, value);
}
}
public string Action {
get {
return GetOwnAttribute(AttributeNames.Action);
}
set {
SetOwnAttribute(AttributeNames.Action, value);
}
}
public string Autocomplete {
get {
return GetOwnAttribute(AttributeNames.AutoComplete);
}
set {
SetOwnAttribute(AttributeNames.AutoComplete, value);
}
}
public string Enctype {
get {
return CheckEncType(GetOwnAttribute(AttributeNames.Enctype));
}
set {
SetOwnAttribute(AttributeNames.Enctype, CheckEncType(value));
}
}
public string Encoding {
get {
return Enctype;
}
set {
Enctype = value;
}
}
public string Method {
get {
return GetOwnAttribute(AttributeNames.Method) ?? string.Empty;
}
set {
SetOwnAttribute(AttributeNames.Method, value);
}
}
public bool NoValidate {
get {
return GetOwnAttribute(AttributeNames.NoValidate) != null;
}
set {
SetOwnAttribute(AttributeNames.NoValidate, value ? string.Empty : null);
}
}
public string Target {
get {
return GetOwnAttribute(AttributeNames.Target);
}
set {
SetOwnAttribute(AttributeNames.Target, value);
}
}
public HtmlFormElement(Document owner, string prefix = null)
: base(owner, Tags.Form, prefix, NodeFlags.Special)
{
_cts = new CancellationTokenSource();
}
public void Dispose()
{
if (_cts != null)
_cts.Cancel();
_cts = null;
_navigationTask = null;
}
public Task<IDocument> Submit()
{
SubmitForm(this, true);
return _navigationTask;
}
public void Reset()
{
foreach (HtmlFormControlElement element in Elements) {
element.Reset();
}
}
public bool CheckValidity()
{
IEnumerable<HtmlFormControlElement> invalidControls = GetInvalidControls();
bool result = true;
foreach (HtmlFormControlElement item in invalidControls) {
if (!item.FireSimpleEvent(EventNames.Invalid, false, true))
result = false;
}
return result;
}
private IEnumerable<HtmlFormControlElement> GetInvalidControls()
{
foreach (HtmlFormControlElement element in Elements) {
if (element.WillValidate && !element.CheckValidity())
yield return element;
}
}
public bool ReportValidity()
{
IEnumerable<HtmlFormControlElement> invalidControls = GetInvalidControls();
bool result = true;
bool flag = false;
foreach (HtmlFormControlElement item in invalidControls) {
if (!item.FireSimpleEvent(EventNames.Invalid, false, true)) {
if (!flag) {
item.DoFocus();
flag = true;
}
result = false;
}
}
return result;
}
public void RequestAutocomplete()
{
}
private void SubmitForm(HtmlElement from, bool submittedFromSubmitMethod)
{
Document owner = base.Owner;
IBrowsingContext context = owner.Context;
if (!owner.ActiveSandboxing.HasFlag(Sandboxes.Forms)) {
if (!submittedFromSubmitMethod && !from.Attributes.Any((IAttr m) => m.Name == AttributeNames.FormNoValidate) && NoValidate && !CheckValidity())
this.FireSimpleEvent(EventNames.Invalid, false, false);
else {
Url url = string.IsNullOrEmpty(Action) ? new Url(owner.DocumentUri) : this.HyperReference(Action);
bool flag = false;
IBrowsingContext context2 = owner.Context;
string target = Target;
if (!string.IsNullOrEmpty(target) && (flag = (owner.GetTarget(target) == null)))
owner.CreateTarget(target);
int num;
bool flag2;
if (flag)
num = 1;
else
flag2 = (owner.ReadyState != DocumentReadyState.Complete);
string scheme = url.Scheme;
HttpMethod httpMethod = Method.ToEnum(HttpMethod.Get);
if (scheme == KnownProtocols.Http || scheme == KnownProtocols.Https) {
switch (httpMethod) {
case HttpMethod.Get:
MutateActionUrl(url);
break;
case HttpMethod.Post:
SubmitAsEntityBody(url);
break;
}
} else if (scheme == KnownProtocols.Data) {
switch (httpMethod) {
case HttpMethod.Get:
GetActionUrl(url);
break;
case HttpMethod.Post:
PostToData(url);
break;
}
} else if (scheme == KnownProtocols.Mailto) {
switch (httpMethod) {
case HttpMethod.Get:
MailWithHeaders(url);
break;
case HttpMethod.Post:
MailAsBody(url);
break;
}
} else if (scheme == KnownProtocols.Ftp || scheme == KnownProtocols.JavaScript) {
GetActionUrl(url);
} else {
MutateActionUrl(url);
}
}
}
}
private void PostToData(Url action)
{
string charset = string.IsNullOrEmpty(AcceptCharset) ? base.Owner.CharacterSet : AcceptCharset;
FormDataSet formDataSet = ConstructDataSet(null);
string enctype = Enctype;
string value = string.Empty;
if (enctype.Equals(MimeTypes.UrlencodedForm, StringComparison.OrdinalIgnoreCase)) {
using (StreamReader streamReader = new StreamReader(formDataSet.AsUrlEncoded(TextEncoding.Resolve(charset))))
value = streamReader.ReadToEnd();
} else if (enctype.Equals(MimeTypes.MultipartForm, StringComparison.OrdinalIgnoreCase)) {
using (StreamReader streamReader2 = new StreamReader(formDataSet.AsMultipart(TextEncoding.Resolve(charset))))
value = streamReader2.ReadToEnd();
} else if (enctype.Equals(MimeTypes.Plain, StringComparison.OrdinalIgnoreCase)) {
using (StreamReader streamReader3 = new StreamReader(formDataSet.AsPlaintext(TextEncoding.Resolve(charset))))
value = streamReader3.ReadToEnd();
}
if (action.Href.Contains("%%%%")) {
value = value.UrlEncode(TextEncoding.Resolve(UsAscii));
action.Href = action.Href.ReplaceFirst("%%%%", value);
} else if (action.Href.Contains("%%")) {
value = value.UrlEncode(TextEncoding.Utf8);
action.Href = action.Href.ReplaceFirst("%%", value);
}
_navigationTask = NavigateTo(new DocumentRequest(action) {
Referer = base.Owner.DocumentUri,
Source = this
});
}
private void MailWithHeaders(Url action)
{
Stream stream = ConstructDataSet(null).AsUrlEncoded(TextEncoding.Resolve(UsAscii));
string text = string.Empty;
using (StreamReader streamReader = new StreamReader(stream))
text = streamReader.ReadToEnd();
action.Query = text.Replace("+", "%20");
GetActionUrl(action);
}
private void MailAsBody(Url action)
{
FormDataSet formDataSet = ConstructDataSet(null);
string enctype = Enctype;
Encoding encoding = TextEncoding.Resolve(UsAscii);
string value = string.Empty;
if (enctype.Equals(MimeTypes.UrlencodedForm, StringComparison.OrdinalIgnoreCase)) {
using (StreamReader streamReader = new StreamReader(formDataSet.AsUrlEncoded(encoding)))
value = streamReader.ReadToEnd();
} else if (enctype.Equals(MimeTypes.MultipartForm, StringComparison.OrdinalIgnoreCase)) {
using (StreamReader streamReader2 = new StreamReader(formDataSet.AsMultipart(encoding)))
value = streamReader2.ReadToEnd();
} else if (enctype.Equals(MimeTypes.Plain, StringComparison.OrdinalIgnoreCase)) {
using (StreamReader streamReader3 = new StreamReader(formDataSet.AsPlaintext(encoding)))
value = streamReader3.ReadToEnd();
}
action.Query = "body=" + value.UrlEncode(encoding);
GetActionUrl(action);
}
private void GetActionUrl(Url action)
{
_navigationTask = NavigateTo(new DocumentRequest(action) {
Referer = base.Owner.DocumentUri,
Source = this
});
}
private void SubmitAsEntityBody(Url action)
{
string charset = string.IsNullOrEmpty(AcceptCharset) ? base.Owner.CharacterSet : AcceptCharset;
FormDataSet formDataSet = ConstructDataSet(null);
string enctype = Enctype;
string mimeType = null;
Stream body = Stream.Null;
if (enctype.Equals(MimeTypes.UrlencodedForm, StringComparison.OrdinalIgnoreCase)) {
body = formDataSet.AsUrlEncoded(TextEncoding.Resolve(charset));
mimeType = MimeTypes.UrlencodedForm;
} else if (enctype.Equals(MimeTypes.MultipartForm, StringComparison.OrdinalIgnoreCase)) {
body = formDataSet.AsMultipart(TextEncoding.Resolve(charset));
mimeType = MimeTypes.MultipartForm + "; boundary=" + formDataSet.Boundary;
} else if (enctype.Equals(MimeTypes.Plain, StringComparison.OrdinalIgnoreCase)) {
body = formDataSet.AsPlaintext(TextEncoding.Resolve(charset));
mimeType = MimeTypes.Plain;
}
_navigationTask = NavigateTo(new DocumentRequest(action) {
Method = HttpMethod.Post,
Source = this,
Body = body,
MimeType = mimeType,
Referer = base.Owner.DocumentUri
});
}
private Task<IDocument> (DocumentRequest request)
{
if (_navigationTask != null) {
_cts.Cancel();
_navigationTask = null;
_cts = new CancellationTokenSource();
}
return base.Owner.Context.OpenAsync(request, _cts.Token);
}
private void MutateActionUrl(Url action)
{
string charset = string.IsNullOrEmpty(AcceptCharset) ? base.Owner.CharacterSet : AcceptCharset;
using (StreamReader streamReader = new StreamReader(ConstructDataSet(null).AsUrlEncoded(TextEncoding.Resolve(charset))))
action.Query = streamReader.ReadToEnd();
GetActionUrl(action);
}
private FormDataSet ConstructDataSet(HtmlElement submitter = null)
{
FormDataSet formDataSet = new FormDataSet();
foreach (HtmlFormControlElement element in Elements) {
if (!(element.ParentElement is IHtmlDataListElement) && !element.IsDisabled)
element.ConstructDataSet(formDataSet, submitter);
}
return formDataSet;
}
private static string CheckEncType(string encType)
{
if (!string.IsNullOrEmpty(encType) && (encType.Equals(MimeTypes.Plain, StringComparison.OrdinalIgnoreCase) || encType.Equals(MimeTypes.MultipartForm, StringComparison.OrdinalIgnoreCase)))
return encType;
return MimeTypes.UrlencodedForm;
}
}
}