HtmlFormElement
sealed class HtmlFormElement : HtmlElement, IHtmlFormElement, IHtmlElement, IElement, INode, IEventTarget, IMarkupFormattable, IParentNode, IChildNode, INonDocumentTypeChildNode, IElementCssInlineStyle
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
{
private HtmlFormControlsCollection _elements;
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)
{
}
public Task<IDocument> Submit()
{
return SubmitForm(this, true);
}
internal Task<IDocument> SubmitForm(HtmlElement from, bool submittedFromSubmitMethod)
{
Document owner = base.Owner;
IBrowsingContext context2 = owner.Context;
if (owner.ActiveSandboxing.HasFlag(Sandboxes.Forms))
return null;
if (!submittedFromSubmitMethod && !from.Attributes.Any((IAttr m) => m.Name == AttributeNames.FormNoValidate) && NoValidate && !CheckValidity()) {
this.FireSimpleEvent(EventNames.Invalid, false, false);
return null;
}
Url url = string.IsNullOrEmpty(Action) ? new Url(owner.DocumentUri) : this.HyperReference(Action);
bool flag = false;
IBrowsingContext context = owner.Context;
string target = Target;
if (!string.IsNullOrEmpty(target)) {
context = owner.GetTarget(target);
if (flag = (context == null))
context = owner.CreateTarget(target);
}
if (!flag) {
DocumentReadyState readyState = owner.ReadyState;
}
string scheme = url.Scheme;
HttpMethod method = Method.ToEnum(HttpMethod.Get);
return SubmitForm(method, scheme, url);
}
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 Task<IDocument> SubmitForm(HttpMethod method, string scheme, Url action)
{
if (scheme == KnownProtocols.Http || scheme == KnownProtocols.Https) {
switch (method) {
case HttpMethod.Get:
return MutateActionUrl(action);
case HttpMethod.Post:
return SubmitAsEntityBody(action);
}
} else if (scheme == KnownProtocols.Data) {
switch (method) {
case HttpMethod.Get:
return GetActionUrl(action);
case HttpMethod.Post:
return PostToData(action);
}
} else if (scheme == KnownProtocols.Mailto) {
switch (method) {
case HttpMethod.Get:
return MailWithHeaders(action);
case HttpMethod.Post:
return MailAsBody(action);
}
} else if (scheme == KnownProtocols.Ftp || scheme == KnownProtocols.JavaScript) {
return GetActionUrl(action);
}
return MutateActionUrl(action);
}
private Task<IDocument> PostToData(Url action)
{
string charset = string.IsNullOrEmpty(AcceptCharset) ? base.Owner.CharacterSet : AcceptCharset;
FormDataSet formDataSet = ConstructDataSet(null);
string enctype = Enctype;
string value = string.Empty;
Stream stream = CreateBody(enctype, TextEncoding.Resolve(charset), formDataSet);
using (StreamReader streamReader = new StreamReader(stream))
value = streamReader.ReadToEnd();
if (action.Href.Contains("%%%%")) {
value = value.UrlEncode(TextEncoding.UsAscii);
action.Href = action.Href.ReplaceFirst("%%%%", value);
} else if (action.Href.Contains("%%")) {
value = value.UrlEncode(TextEncoding.Utf8);
action.Href = action.Href.ReplaceFirst("%%", value);
}
return GetActionUrl(action);
}
private Task<IDocument> MailWithHeaders(Url action)
{
FormDataSet formDataSet = ConstructDataSet(null);
Stream stream = formDataSet.AsUrlEncoded(TextEncoding.UsAscii);
string text = string.Empty;
using (StreamReader streamReader = new StreamReader(stream))
text = streamReader.ReadToEnd();
action.Query = text.Replace("+", "%20");
return GetActionUrl(action);
}
private Task<IDocument> MailAsBody(Url action)
{
FormDataSet formDataSet = ConstructDataSet(null);
string enctype = Enctype;
Encoding usAscii = TextEncoding.UsAscii;
Stream stream = CreateBody(enctype, usAscii, formDataSet);
string value = string.Empty;
using (StreamReader streamReader = new StreamReader(stream))
value = streamReader.ReadToEnd();
action.Query = "body=" + value.UrlEncode(usAscii);
return GetActionUrl(action);
}
private Task<IDocument> GetActionUrl(Url action)
{
return NavigateTo(DocumentRequest.Get(action, this, base.Owner.DocumentUri));
}
private Task<IDocument> SubmitAsEntityBody(Url target)
{
string charset = string.IsNullOrEmpty(AcceptCharset) ? base.Owner.CharacterSet : AcceptCharset;
FormDataSet formDataSet = ConstructDataSet(null);
string text = Enctype;
Stream body = CreateBody(text, TextEncoding.Resolve(charset), formDataSet);
if (text.Equals(MimeTypes.MultipartForm, StringComparison.OrdinalIgnoreCase))
text = MimeTypes.MultipartForm + "; boundary=" + formDataSet.Boundary;
DocumentRequest request = DocumentRequest.Post(target, body, text, this, base.Owner.DocumentUri);
return NavigateTo(request);
}
private Task<IDocument> (DocumentRequest request)
{
this.CancelTasks();
return this.CreateTask((CancellationToken cancel) => base.Owner.Context.OpenAsync(request, cancel));
}
private Task<IDocument> MutateActionUrl(Url action)
{
string charset = string.IsNullOrEmpty(AcceptCharset) ? base.Owner.CharacterSet : AcceptCharset;
FormDataSet formDataSet = ConstructDataSet(null);
Stream stream = formDataSet.AsUrlEncoded(TextEncoding.Resolve(charset));
using (StreamReader streamReader = new StreamReader(stream))
action.Query = streamReader.ReadToEnd();
return 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 Stream CreateBody(string enctype, Encoding encoding, FormDataSet formDataSet)
{
if (enctype.Equals(MimeTypes.UrlencodedForm, StringComparison.OrdinalIgnoreCase))
return formDataSet.AsUrlEncoded(encoding);
if (enctype.Equals(MimeTypes.MultipartForm, StringComparison.OrdinalIgnoreCase))
return formDataSet.AsMultipart(encoding);
if (enctype.Equals(MimeTypes.Plain, StringComparison.OrdinalIgnoreCase))
return formDataSet.AsPlaintext(encoding);
return Stream.Null;
}
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;
}
}
}