AngleSharp by Florian Rappl

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

.NET API 1,175,040 bytes

 HtmlFormElement

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> NavigateTo(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; } } }