XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFESystem

【Rust】XFE系统,基于Rust和汇编

公开
关注 0 Fork 0 Star 0
UTF-8
using AngleSharp.Dom;
using AngleSharp.Html.Dom;

namespace XFESystem.Browser;

public sealed partial class BrowserService
{
    private string? pendingNavigation;
    private bool SubmitForm(IElement form, IElement? submitter = null, bool fireEvent = true)
    {
        if (fireEvent && dom?.DispatchEvent(form, "submit") == false) return false;
        string method = submitter?.GetAttribute("formmethod") ?? form.GetAttribute("method") ?? "get";
        if (!method.Equals("get", StringComparison.OrdinalIgnoreCase))
        { Diagnostic("Form navigation failed: only GET form submission is supported."); return false; }
        if (scriptPolicy?.BlocksAllScripts == true)
        { Diagnostic("Form navigation blocked: the declared policy cannot be enforced."); return false; }
        string action = submitter?.GetAttribute("formaction") ?? form.GetAttribute("action") ?? "";
        Uri target = action.Length == 0 ? currentAddress! : ResourceAddress(action);
        if (currentAddress!.Scheme == "https" && target.Scheme != "https")
        { Diagnostic("Form navigation blocked: HTTPS cannot downgrade to HTTP."); return false; }
        var fields = new List<string>();
        string Encode(string value) => Uri.EscapeDataString(value.Replace("\r\n", "\n").Replace("\r", "\n").Replace("\n", "\r\n")).Replace("%20", "+");
        foreach (var control in document!.QuerySelectorAll("input,textarea,select,button"))
        {
            string? owner = control.GetAttribute("form");
            if (owner is not null ? owner != form.Id : !ReferenceEquals(control.Closest("form"), form)) continue;
            string name = control.GetAttribute("name") ?? "";
            if (name.Length == 0 || control.HasAttribute("disabled")) continue;
            string type = (control.GetAttribute("type") ?? (control.LocalName == "button" ? "submit" : "text")).ToLowerInvariant();
            if (type is "reset" or "button" or "file" || type is "submit" or "image" && !ReferenceEquals(control, submitter)) continue;
            if (control is IHtmlInputElement check && type is "checkbox" or "radio" && !check.IsChecked) continue;
            string value = (control switch { IHtmlInputElement input => input.Value, IHtmlTextAreaElement area => area.Value,
                IHtmlSelectElement select => select.Value, _ => control.GetAttribute("value") }) ?? "";
            fields.Add(Encode(name) + "=" + Encode(value));
        }
        var destination = new UriBuilder(target) { Query = string.Join('&', fields), Fragment = "" };
        pendingNavigation = destination.Uri.AbsoluteUri;
        return true;
    }
    private void FollowPendingNavigation()
    {
        if (pendingNavigation is not { } next) return;
        pendingNavigation = null;
        Navigate(next);
    }
    private void DefaultClick(IElement? element)
    {
        var control = element?.Closest("button,input[type=submit],input[type=image]");
        if (control is not null && !control.HasAttribute("disabled") &&
            (control.GetAttribute("type") ?? "submit").Equals("submit", StringComparison.OrdinalIgnoreCase) && control.Closest("form") is { } form)
            SubmitForm(form, control);
        else if (element?.Closest("a[href]") is { } anchor && anchor.GetAttribute("href") is { } href && !href.StartsWith("javascript:", StringComparison.OrdinalIgnoreCase))
            pendingNavigation = ResourceAddress(href).AbsoluteUri;
    }
}