import React, {useEffect, useRef, useState} from "react"
import {
    Button,
    Card,
    Col,
    Divider,
    Form,
    Input,
    Modal,
    notification,
    Result,
    Row,
    Space,
    Spin,
    Tag,
    Typography,
    Dropdown,
    Menu,
    Popover, Checkbox, Tooltip
} from "antd"
import {HTTPPacketEditor, IMonacoEditor} from "../../utils/editors"
import {showDrawer, showModal} from "../../utils/showModal"
import {monacoEditorWrite} from "./fuzzerTemplates"
import {StringFuzzer} from "./StringFuzzer"
import {InputFloat, InputInteger, InputItem, ManyMultiSelectForString, OneLine, SwitchItem} from "../../utils/inputUtil"
import {fixEncoding} from "../../utils/convertor"
import {FuzzerResponseToHTTPFlowDetail} from "../../components/HTTPFlowDetail"
import {randomString} from "../../utils/randomUtil"
import {
    ColumnWidthOutlined,
    DeleteOutlined,
    ProfileOutlined,
    LeftOutlined,
    RightOutlined,
    DownOutlined,
    HistoryOutlined,
    DownloadOutlined, QuestionCircleOutlined
} from "@ant-design/icons"
import {HTTPFuzzerResultsCard} from "./HTTPFuzzerResultsCard"
import {failed, success} from "../../utils/notification"
import {AutoSpin} from "../../components/AutoSpin"
import {ResizeBox} from "../../components/ResizeBox"
import {useGetState, useMemoizedFn} from "ahooks";
import {getValue, saveValue} from "../../utils/kv";
import {HTTPFuzzerHistorySelector} from "./HTTPFuzzerHistory";
import {PayloadManagerPage} from "../payloadManager/PayloadManager";
import {HackerPlugin} from "../hacker/HackerPlugin"
import {fuzzerInfoProp} from "../MainOperator"
import {ItemSelects} from "../../components/baseTemplate/FormItemUtil"
import {HTTPFuzzerHotPatch} from "./HTTPFuzzerHotPatch";
import {AutoCard} from "../../components/AutoCard";
import {callCopyToClipboard} from "../../utils/basic";

const {ipcRenderer} = window.require("electron")

export const analyzeFuzzerResponse =
    (
        i: FuzzerResponse,
        setRequest: (isHttps: boolean, request: string) => any,
        index?: number,
        data?: FuzzerResponse[]
    ) => {
        let m = showDrawer({
            width: "90%",
            content: (
                <>
                    <FuzzerResponseToHTTPFlowDetail
                        response={i}
                        onClosed={() => {
                            m.destroy()
                        }}
                        index={index}
                        data={data}
                    />
                </>
            )
        })
    }

export interface HTTPFuzzerPageProp {
    isHttps?: boolean
    request?: string
    system?: string
    order?: string
    fuzzerParams?: fuzzerInfoProp
}

const {Text} = Typography

export interface FuzzerResponse {
    Method: string
    StatusCode: number
    Host: string
    ContentType: string
    Headers: { Header: string; Value: string }[]
    ResponseRaw: Uint8Array
    RequestRaw: Uint8Array
    BodyLength: number
    UUID: string
    Timestamp: number
    DurationMs: number

    Ok: boolean
    Reason: string
    Payloads?: string[]

    IsHTTPS?: boolean
    Count?: number

    HeaderSimilarity?: number
    BodySimilarity?: number
    MatchedByFilter?: boolean
}

const defaultPostTemplate = `POST / HTTP/1.1
Content-Type: application/json
Host: www.example.com

{"key": "value"}`

const WEB_FUZZ_PROXY = "WEB_FUZZ_PROXY"
const WEB_FUZZ_HOTPATCH_CODE = "WEB_FUZZ_HOTPATCH_CODE"

interface HistoryHTTPFuzzerTask {
    Request: string
    Proxy: string
    IsHTTPS: boolean
}

export const showDictsAndSelect = (res: (i: string) => any) => {
    const m = showModal({
        title: "选择想要插入的字典",
        width: 1200,
        content: <div style={{width: 1100, height: 500, overflow: "hidden"}}>
            <PayloadManagerPage readOnly={true} selectorHandle={e => {
                res(e)
                m.destroy()
            }}/>
        </div>
    })
}

interface FuzzResponseFilter {
    MinBodySize: number
    MaxBodySize: number
    Regexps: string[]
    Keywords: string[]
    StatusCode: string[]
}

function removeEmptyFiledFromFuzzResponseFilter(i: FuzzResponseFilter): FuzzResponseFilter {
    i.Keywords = (i.Keywords || []).filter(i => !!i)
    i.StatusCode = (i.StatusCode || []).filter(i => !!i)
    i.Regexps = (i.Regexps || []).filter(i => !!i)
    return {...i}
}

function filterIsEmpty(f: FuzzResponseFilter): boolean {
    return f.MinBodySize === 0 && f.MaxBodySize === 0 &&
        f.Regexps.length === 0 && f.Keywords.length === 0 &&
        f.StatusCode.length === 0
}

function copyAsUrl(f: { Request: string, IsHTTPS: boolean }) {
    ipcRenderer.invoke("ExtractUrl", f).then((data: { Url: string }) => {
        callCopyToClipboard(data.Url)
    }).catch(e => {
        failed("复制 URL 失败:包含 Fuzz 标签可能会导致 URL 不完整")
    })
}

export const HTTPFuzzerPage: React.FC<HTTPFuzzerPageProp> = (props) => {
    // params
    const [isHttps, setIsHttps, getIsHttps] = useGetState<boolean>(props.fuzzerParams?.isHttps || props.isHttps || false)
    const [noFixContentLength, setNoFixContentLength] = useState(false)
    const [request, setRequest, getRequest] = useGetState(props.fuzzerParams?.request || props.request || defaultPostTemplate)
    const [concurrent, setConcurrent] = useState(props.fuzzerParams?.concurrent || 20)
    const [forceFuzz, setForceFuzz] = useState<boolean>(props.fuzzerParams?.forceFuzz || true)
    const [timeout, setParamTimeout] = useState(props.fuzzerParams?.timeout || 10.0)
    const [proxy, setProxy] = useState(props.fuzzerParams?.proxy || "")
    const [actualHost, setActualHost] = useState(props.fuzzerParams?.actualHost || "")
    const [advancedConfig, setAdvancedConfig] = useState(false)
    const [redirectedResponse, setRedirectedResponse] = useState<FuzzerResponse>()
    const [historyTask, setHistoryTask] = useState<HistoryHTTPFuzzerTask>();
    const [hotPatchCode, setHotPatchCode] = useState<string>("");

    // filter
    const [_, setFilter, getFilter] = useGetState<FuzzResponseFilter>({
        Keywords: [],
        MaxBodySize: 0,
        MinBodySize: 0,
        Regexps: [],
        StatusCode: []
    });
    const [droppedCount, setDroppedCount] = useState(0);

    // state
    const [loading, setLoading] = useState(false)
    const [content, setContent] = useState<FuzzerResponse[]>([])
    const [reqEditor, setReqEditor] = useState<IMonacoEditor>()
    const [fuzzToken, setFuzzToken] = useState("")
    const [search, setSearch] = useState("")
    const [targetUrl, setTargetUrl] = useState("")

    const [refreshTrigger, setRefreshTrigger] = useState(false)
    const refreshRequest = () => {
        setRefreshTrigger(!refreshTrigger)
    }

    // history
    const [history, setHistory] = useState<string[]>([])
    const [currentHistoryIndex, setCurrentHistoryIndex] = useState<number>()

    const [urlPacketShow, setUrlPacketShow] = useState<boolean>(false)

    // filter
    const [keyword, setKeyword] = useState<string>("")
    const [filterContent, setFilterContent] = useState<FuzzerResponse[]>([])
    const [timer, setTimer] = useState<any>()

    useEffect(() => {
        getValue(WEB_FUZZ_HOTPATCH_CODE).then((data: any) => {
            if (!data) {
                return
            }
            setHotPatchCode(`${data}`)
        })
    }, [])

    // 定时器
    const sendTimer = useRef<any>(null)

    const withdrawRequest = useMemoizedFn(() => {
        const targetIndex = history.indexOf(request) - 1
        if (targetIndex >= 0) {
            setRequest(history[targetIndex])
            setCurrentHistoryIndex(targetIndex)
        }
    })
    const forwardRequest = useMemoizedFn(() => {
        const targetIndex = history.indexOf(request) + 1
        if (targetIndex < history.length) {
            setCurrentHistoryIndex(targetIndex)
            setRequest(history[targetIndex])
        }
    })

    const sendToFuzzer = useMemoizedFn((isHttps: boolean, request: string) => {
        ipcRenderer.invoke("send-to-tab", {
            type: "fuzzer",
            data: {isHttps: isHttps, request: request}
        })
    })
    const sendToPlugin = useMemoizedFn((request: Uint8Array, isHTTPS: boolean, response?: Uint8Array) => {
        let m = showDrawer({
            width: "80%",
            content: <HackerPlugin request={request} isHTTPS={isHTTPS} response={response}></HackerPlugin>
        })
    })

    // 从历史记录中恢复
    useEffect(() => {
        if (!historyTask) {
            return
        }

        setRequest(historyTask.Request)
        setIsHttps(historyTask.IsHTTPS)
        setProxy(historyTask.Proxy)
        refreshRequest()
    }, [historyTask])

    useEffect(() => {
        // 缓存全局参数
        getValue(WEB_FUZZ_PROXY).then(e => {
            if (!e) {
                return
            }
            setProxy(`${e}`)
        })

    }, [])

    useEffect(() => {
        if (currentHistoryIndex === undefined) {
            return
        }
        refreshRequest()
    }, [currentHistoryIndex])

    useEffect(() => {
        setIsHttps(!!props.isHttps)
        if (props.request) {
            setRequest(props.request)
            setContent([])
        }
    }, [props.isHttps, props.request])

    const loadHistory = useMemoizedFn((id: number) => {
        setLoading(true)
        setHistory([])
        ipcRenderer.invoke(
            "HTTPFuzzer",
            {HistoryWebFuzzerId: id}, fuzzToken
        ).then(() => {
            ipcRenderer.invoke("GetHistoryHTTPFuzzerTask", {Id: id}).then((data: { OriginRequest: HistoryHTTPFuzzerTask }) => {
                setHistoryTask(data.OriginRequest)
            })
        })
    })

    const submitToHTTPFuzzer = useMemoizedFn(() => {
        // 清楚历史任务的标记
        setHistoryTask(undefined);

        saveValue(WEB_FUZZ_PROXY, proxy)
        setLoading(true)
        if (history.includes(request)) {
            history.splice(history.indexOf(request), 1)
        }
        history.push(request)
        setHistory([...history])

        setDroppedCount(0)
        ipcRenderer.invoke(
            "HTTPFuzzer",
            {
                Request: request,
                ForceFuzz: forceFuzz,
                IsHTTPS: isHttps,
                Concurrent: concurrent,
                PerRequestTimeoutSeconds: timeout,
                NoFixContentLength: noFixContentLength,
                Proxy: proxy,
                ActualAddr: actualHost,
                HotPatchCode: hotPatchCode,
                Filter: getFilter(),
            },
            fuzzToken
        )
    })

    const cancelCurrentHTTPFuzzer = useMemoizedFn(() => {
        ipcRenderer.invoke("cancel-HTTPFuzzer", fuzzToken)
    })

    useEffect(() => {
        const token = randomString(60)
        setFuzzToken(token)

        const dataToken = `${token}-data`
        const errToken = `${token}-error`
        const endToken = `${token}-end`

        ipcRenderer.on(errToken, (e, details) => {
            notification["error"]({
                message: `提交模糊测试请求失败 ${details}`,
                placement: "bottomRight"
            })
        })
        let buffer: FuzzerResponse[] = []
        let droppedCount = 0;
        let count: number = 0
        const updateData = () => {
            if (buffer.length <= 0) {
                return
            }
            if (JSON.stringify(buffer) !== JSON.stringify(content)) setContent([...buffer])
        }

        ipcRenderer.on(dataToken, (e: any, data: any) => {
            if (data["MatchedByFilter"] !== true && !filterIsEmpty(getFilter())) {
                // 不匹配的
                droppedCount++
                setDroppedCount(droppedCount)
                return
            }
            // const response = new Buffer(data.ResponseRaw).toString(fixEncoding(data.GuessResponseEncoding))
            buffer.push({
                StatusCode: data.StatusCode,
                Ok: data.Ok,
                Reason: data.Reason,
                Method: data.Method,
                Host: data.Host,
                ContentType: data.ContentType,
                Headers: (data.Headers || []).map((i: any) => {
                    return {Header: i.Header, Value: i.Value}
                }),
                DurationMs: data.DurationMs,
                BodyLength: data.BodyLength,
                UUID: data.UUID,
                Timestamp: data.Timestamp,
                ResponseRaw: data.ResponseRaw,
                RequestRaw: data.RequestRaw,
                Payloads: data.Payloads,
                IsHTTPS: data.IsHTTPS,
                Count: count,
                BodySimilarity: data.BodySimilarity,
                HeaderSimilarity: data.HeaderSimilarity,
            } as FuzzerResponse)
            count++
            // setContent([...buffer])
        })
        ipcRenderer.on(endToken, () => {
            updateData()
            buffer = []
            count = 0
            droppedCount = 0
            setLoading(false)
        })

        const updateDataId = setInterval(() => {
            updateData()
        }, 200)

        return () => {
            ipcRenderer.invoke("cancel-HTTPFuzzer", token)

            clearInterval(updateDataId)
            ipcRenderer.removeAllListeners(errToken)
            ipcRenderer.removeAllListeners(dataToken)
            ipcRenderer.removeAllListeners(endToken)
        }
    }, [])

    const searchContent = (keyword: string) => {
        if (timer) {
            clearTimeout(timer)
            setTimer(null)
        }
        setTimer(
            setTimeout(() => {
                try {
                    const filters = content.filter((item) => {
                        return Buffer.from(item.ResponseRaw).toString("utf8").match(new RegExp(keyword, "g"))
                    })
                    setFilterContent(filters)
                } catch (error) {
                }
            }, 500)
        )
    }

    const downloadContent = useMemoizedFn(() => {
        if (!keyword) {
            failed('请先输入需要搜索的关键词')
            return
        }

        const strs = []
        try {
            const reg = new RegExp(keyword)
            for (let info of filterContent) {
                let str = Buffer.from(info.ResponseRaw).toString('utf8')
                let temp: any
                while ((temp = reg.exec(str)) !== null) {
                    // @ts-ignore
                    if (temp[1]) {
                        // @ts-ignore
                        strs.push(temp[1])
                        str = str.substring(temp['index'] + 1)
                        reg.lastIndex = 0
                    } else {
                        break
                    }
                }
            }
        } catch (error) {
            failed("正则有问题,请检查后重新输入")
            return
        }

        if (strs.length === 0) {
            failed('未捕获到关键词信息')
            return
        }

        ipcRenderer.invoke("show-save-dialog", 'fuzzer列表命中内容.txt').then((res) => {
            if (res.canceled) return

            ipcRenderer
                .invoke("write-file", {
                    route: res.filePath,
                    data: strs.join('\n\r')
                })
                .then(() => {
                    success('下载完成')
                    ipcRenderer.invoke("open-specified-file", res.filePath)
                })
        })
    })

    useEffect(() => {
        if (!!keyword) {
            searchContent(keyword)
        } else {
            setFilterContent([])
        }
    }, [keyword])

    useEffect(() => {
        if (keyword && content.length !== 0) {
            const filters = content.filter(item => {
                return Buffer.from(item.ResponseRaw).toString("utf8").match(new RegExp(keyword, 'g'))
            })
            setFilterContent(filters)
        }
    }, [content])

    const onlyOneResponse = !loading && (content || []).length === 1

    const filtredResponses =
        search === ""
            ? content || []
            : (content || []).filter((i) => {
                return Buffer.from(i.ResponseRaw).toString().includes(search)
            })
    const successResults = filtredResponses.filter((i) => i.Ok)
    const failedResults = filtredResponses.filter((i) => !i.Ok)

    const sendFuzzerSettingInfo = useMemoizedFn(() => {
        const info: fuzzerInfoProp = {
            time: new Date().getTime().toString(),
            isHttps: isHttps,
            forceFuzz: forceFuzz,
            concurrent: concurrent,
            proxy: proxy,
            actualHost: actualHost,
            timeout: timeout,
            request: request
        }
        if (sendTimer.current) {
            clearTimeout(sendTimer.current)
            sendTimer.current = null
        }
        sendTimer.current = setTimeout(() => {
            ipcRenderer.invoke('send-fuzzer-setting-data', {key: props.order || "", param: JSON.stringify(info)})
        }, 1000);
    })
    useEffect(() => {
        sendFuzzerSettingInfo()
    }, [isHttps, forceFuzz, concurrent, proxy, actualHost, timeout, request])

    const responseViewer = useMemoizedFn((rsp: FuzzerResponse) => {
        return (
            <HTTPPacketEditor
                system={props.system}
                originValue={rsp.ResponseRaw}
                bordered={true}
                hideSearch={true}
                emptyOr={
                    !rsp?.Ok && (
                        <Result
                            status={"error"}
                            title={"请求失败"}
                            // no such host
                            subTitle={(() => {
                                const reason = content[0]!.Reason
                                if (reason.includes("tcp: i/o timeout")) {
                                    return "网络超时"
                                }
                                if (reason.includes("no such host")) {
                                    return "DNS 错误或主机错误"
                                }
                                return undefined
                            })()}
                        >
                            <>详细原因:{rsp.Reason}</>
                        </Result>
                    )
                }
                readOnly={true}
                extra={
                    (
                        <Space>
                            {loading && <Spin size={"small"} spinning={loading}/>}
                            {onlyOneResponse ? (
                                <Space>
                                    {content[0].IsHTTPS && <Tag>{content[0].IsHTTPS ? "https" : ""}</Tag>}
                                    <Tag>{content[0].DurationMs}ms</Tag>
                                    <Space key='single'>
                                        <Button
                                            size={"small"}
                                            onClick={() => {
                                                analyzeFuzzerResponse(
                                                    rsp,
                                                    (bool, r) => {
                                                        // setRequest(r)
                                                        // refreshRequest()
                                                    }
                                                )
                                            }}
                                            type={"primary"}
                                            icon={<ProfileOutlined/>}
                                        >
                                            详情
                                        </Button>
                                        <Button
                                            type={"primary"}
                                            size={"small"}
                                            onClick={() => {
                                                setContent([])
                                            }}
                                            danger={true}
                                            icon={<DeleteOutlined/>}
                                        />
                                    </Space>
                                </Space>
                            ) : (
                                <Space key='list'>
                                    <Tag color={"green"}>成功:{successResults.length}</Tag>
                                    <Input
                                        size={"small"}
                                        value={search}
                                        onChange={(e) => {
                                            setSearch(e.target.value)
                                        }}
                                    />
                                    {/*<Tag>当前请求结果数[{(content || []).length}]</Tag>*/}
                                    <Button
                                        size={"small"}
                                        onClick={() => {
                                            setContent([])
                                        }}
                                    >
                                        清除数据
                                    </Button>
                                </Space>
                            )}

                        </Space>
                    )
                }
            />
        )
    })

    const hotPatchTrigger = useMemoizedFn(() => {
        let m = showModal({
            title: "调试 / 插入热加载代码",
            width: "60%",
            content: (
                <div>
                    <HTTPFuzzerHotPatch initialHotPatchCode={hotPatchCode || ""} onInsert={tag => {
                        if (reqEditor) monacoEditorWrite(reqEditor, tag);
                        m.destroy()
                    }} onSaveCode={code => {
                        setHotPatchCode(code)
                        saveValue(WEB_FUZZ_HOTPATCH_CODE, code)
                    }}/>
                </div>
            )
        })
    })

    return (
        <div style={{height: "100%", width: "100%", display: "flex", flexDirection: "column", overflow: "hidden"}}>
            <Row gutter={8} style={{marginBottom: 8}}>
                <Col span={24} style={{textAlign: "left", marginTop: 4}}>
                    <Space>
                        {loading ? (
                            <Button
                                style={{width: 150}}
                                onClick={() => {
                                    cancelCurrentHTTPFuzzer()
                                }}
                                // size={"small"}
                                danger={true}
                                type={"primary"}
                            >
                                强制停止
                            </Button>
                        ) : (
                            <Button
                                style={{width: 150}}
                                onClick={() => {
                                    setContent([])
                                    setRedirectedResponse(undefined)
                                    sendFuzzerSettingInfo()
                                    submitToHTTPFuzzer()
                                }}
                                // size={"small"}
                                type={"primary"}
                            >
                                发送数据包
                            </Button>
                        )}
                        <Space>
                            <Button
                                onClick={() => {
                                    withdrawRequest()
                                }}
                                type={"link"}
                                icon={<LeftOutlined/>}
                            />
                            <Button
                                onClick={() => {
                                    forwardRequest()
                                }}
                                type={"link"}
                                icon={<RightOutlined/>}
                            />
                            {history.length > 1 && (
                                <Dropdown
                                    trigger={["click"]}
                                    overlay={() => {
                                        return (
                                            <Menu>
                                                {history.map((i, index) => {
                                                    return (
                                                        <Menu.Item
                                                            style={{width: 120}}
                                                            onClick={() => {
                                                                setRequest(i)
                                                                setCurrentHistoryIndex(index)
                                                            }}
                                                        >{`${index}`}</Menu.Item>
                                                    )
                                                })}
                                            </Menu>
                                        )
                                    }}
                                >
                                    <Button size={"small"} type={"link"} onClick={(e) => e.preventDefault()}>
                                        History <DownOutlined/>
                                    </Button>
                                </Dropdown>
                            )}
                        </Space>
                        <Checkbox defaultChecked={isHttps} value={isHttps} onChange={() => setIsHttps(!isHttps)}>强制
                            HTTPS</Checkbox>
                        <SwitchItem
                            label={"高级配置"}
                            formItemStyle={{marginBottom: 0}}
                            value={advancedConfig}
                            setValue={setAdvancedConfig}
                            size={"small"}
                        />
                        {droppedCount > 0 && <Tag color={"red"}>已丢弃[{droppedCount}]个响应</Tag>}
                        {onlyOneResponse && content[0].Ok && (
                            <Form.Item style={{marginBottom: 0}}>
                                <Button
                                    onClick={() => {
                                        setLoading(true)
                                        ipcRenderer
                                            .invoke("RedirectRequest", {
                                                Request: request,
                                                Response: new Buffer(content[0].ResponseRaw).toString("utf8"),
                                                IsHttps: isHttps,
                                                PerRequestTimeoutSeconds: timeout,
                                                NoFixContentLength: noFixContentLength,
                                                Proxy: proxy
                                            })
                                            .then((rsp: FuzzerResponse) => {
                                                setRedirectedResponse(rsp)
                                            })
                                            .catch((e) => {
                                                failed(`"ERROR in: ${e}"`)
                                            })
                                            .finally(() => {
                                                setTimeout(() => setLoading(false), 300)
                                            })
                                    }}
                                >
                                    跟随重定向
                                </Button>
                            </Form.Item>
                        )}
                        {loading && (
                            <Space>
                                <Spin size={"small"}/>
                                <div style={{color: "#3a8be3"}}>sending packets</div>
                            </Space>
                        )}
                        {proxy && <Tag>代理:{proxy}</Tag>}
                        {/*<Popover*/}
                        {/*    trigger={"click"}*/}
                        {/*    content={*/}
                        {/*    }*/}
                        {/*>*/}
                        {/*    <Button type={"link"} size={"small"}>*/}
                        {/*        配置请求包*/}
                        {/*    </Button>*/}
                        {/*</Popover>*/}
                        {actualHost !== "" && <Tag color={"red"}>请求 Host:{actualHost}</Tag>}
                    </Space>
                </Col>
                {/*<Col span={12} style={{textAlign: "left"}}>*/}
                {/*</Col>*/}
            </Row>

            {advancedConfig && (
                <Row style={{marginBottom: 8}} gutter={8}>
                    <Col span={16}>
                        {/*高级配置*/}
                        <Card bordered={true} size={"small"} bodyStyle={{height: 106}}>
                            <Spin style={{width: "100%"}} spinning={!reqEditor}>
                                <Form
                                    onSubmitCapture={(e) => e.preventDefault()}
                                    // layout={"horizontal"}
                                    size={"small"}
                                    // labelCol={{span: 8}}
                                    // wrapperCol={{span: 16}}
                                >
                                    <Row gutter={8}>
                                        <Col span={12} xl={8}>
                                            <Form.Item
                                                label={<OneLine width={68}>Intruder</OneLine>}
                                                style={{marginBottom: 4}}
                                            >
                                                <Button
                                                    style={{backgroundColor: "#08a701"}}
                                                    size={"small"}
                                                    type={"primary"}
                                                    onClick={() => {
                                                        const m = showModal({
                                                            width: "70%",
                                                            content: (
                                                                <>
                                                                    <StringFuzzer
                                                                        advanced={true}
                                                                        disableBasicMode={true}
                                                                        insertCallback={(template: string) => {
                                                                            if (!template) {
                                                                                Modal.warn({
                                                                                    title: "Payload 为空 / Fuzz 模版为空"
                                                                                })
                                                                            } else {
                                                                                if (reqEditor && template) {
                                                                                    reqEditor.trigger(
                                                                                        "keyboard",
                                                                                        "type",
                                                                                        {
                                                                                            text: template
                                                                                        }
                                                                                    )
                                                                                } else {
                                                                                    Modal.error({
                                                                                        title: "BUG: 编辑器失效"
                                                                                    })
                                                                                }
                                                                                m.destroy()
                                                                            }
                                                                        }}
                                                                    />
                                                                </>
                                                            )
                                                        })
                                                    }}
                                                >
                                                    插入 yak.fuzz 语法
                                                </Button>
                                            </Form.Item>
                                        </Col>
                                        <Col span={12} xl={8}>
                                            <SwitchItem
                                                label={<OneLine width={68}>渲染 fuzz</OneLine>}
                                                setValue={(e) => {
                                                    if (!e) {
                                                        Modal.confirm({
                                                            title: "确认关闭 Fuzz 功能吗?关闭之后,所有的 Fuzz 标签将会失效",
                                                            onOk: () => {
                                                                setForceFuzz(e)
                                                            }
                                                        })
                                                        return
                                                    }
                                                    setForceFuzz(e)
                                                }}
                                                size={"small"}
                                                value={forceFuzz}
                                                formItemStyle={{marginBottom: 4}}
                                            />
                                        </Col>
                                        <Col span={12} xl={8}>
                                            <InputInteger
                                                label={<OneLine width={68}>并发线程</OneLine>}
                                                size={"small"}
                                                setValue={(e) => {
                                                    setConcurrent(e)
                                                }}
                                                formItemStyle={{marginBottom: 4}} // width={40}
                                                width={50}
                                                value={concurrent}
                                            />
                                        </Col>
                                        <Col span={12} xl={8}>
                                            <SwitchItem
                                                label={<OneLine width={68}>HTTPS</OneLine>}
                                                setValue={(e) => {
                                                    setIsHttps(e)
                                                }}
                                                size={"small"}
                                                value={isHttps}
                                                formItemStyle={{marginBottom: 4}}
                                            />
                                        </Col>
                                        <Col span={12} xl={8}>
                                            <SwitchItem
                                                label={<OneLine width={70}>
                                                    <Tooltip title={"不修复 Content-Length: 常用发送多个数据包"}>
                                                        不修复长度
                                                    </Tooltip>
                                                </OneLine>}
                                                setValue={(e) => {
                                                    setNoFixContentLength(e)
                                                }}
                                                size={"small"}
                                                value={noFixContentLength}
                                                formItemStyle={{marginBottom: 4}}
                                            />
                                        </Col>
                                        <Col span={12} xl={8}>
                                            <ItemSelects
                                                item={{
                                                    style: {marginBottom: 4},
                                                    label: <OneLine width={68}>设置代理</OneLine>,
                                                }}
                                                select={{
                                                    style: {width: "100%"},
                                                    allowClear: true,
                                                    autoClearSearchValue: true,
                                                    maxTagTextLength: 8,
                                                    mode: "tags",
                                                    data: [
                                                        {text: "http://127.0.0.1:7890", value: "http://127.0.0.1:7890"},
                                                        {text: "http://127.0.0.1:8080", value: "http://127.0.0.1:8080"},
                                                        {text: "http://127.0.0.1:8082", value: "http://127.0.0.1:8082"}
                                                    ],
                                                    value: proxy ? proxy.split(",") : [],
                                                    setValue: (value) => setProxy(value.join(",")),
                                                    maxTagCount: "responsive",
                                                }}
                                            ></ItemSelects>
                                            {/* <ManyMultiSelectForString
                                                formItemStyle={{marginBottom: 4}}
                                                label={<OneLine width={68}>设置代理</OneLine>}
                                                data={[
                                                    "http://127.0.0.1:7890",
                                                    "http://127.0.0.1:8080",
                                                    "http://127.0.0.1:8082"
                                                ].map((i) => {
                                                    return {label: i, value: i}
                                                })}
                                                mode={"tags"}
                                                defaultSep={","}
                                                value={proxy}
                                                setValue={(r) => {
                                                    setProxy(r.split(",").join(","))
                                                }}
                                            /> */}
                                        </Col>
                                        <Col span={12} xl={8}>
                                            <InputItem
                                                extraFormItemProps={{
                                                    style: {marginBottom: 0}
                                                }}
                                                label={<OneLine width={68}>请求 Host</OneLine>}
                                                setValue={setActualHost}
                                                value={actualHost}
                                            />
                                        </Col>
                                        <Col span={12} xl={8}>
                                            <InputFloat
                                                formItemStyle={{marginBottom: 4}}
                                                size={"small"}
                                                label={<OneLine width={68}>超时时间</OneLine>}
                                                setValue={setParamTimeout}
                                                value={timeout}
                                            />
                                        </Col>
                                    </Row>
                                </Form>
                            </Spin>
                        </Card>
                    </Col>
                    <Col span={8}>
                        <AutoCard title={<Tooltip title={"通过过滤匹配,丢弃无用数据包,保证界面性能!"}>
                            设置过滤器
                        </Tooltip>}
                                  bordered={false} size={"small"} bodyStyle={{paddingTop: 4}}
                                  style={{marginTop: 0, paddingTop: 0}}
                        >
                            <Form size={"small"} onSubmitCapture={e => e.preventDefault()}>
                                <Row gutter={20}>
                                    <Col span={12}>
                                        <InputItem
                                            label={"状态码"} placeholder={"200,300-399"}
                                            disable={loading}
                                            value={getFilter().StatusCode.join(",")}
                                            setValue={e => {
                                                setFilter({...getFilter(), StatusCode: e.split(",").filter(i => !!i)})
                                            }}
                                            extraFormItemProps={{style: {marginBottom: 0}}}
                                        />
                                    </Col>
                                    <Col span={12}>
                                        <InputItem
                                            label={"关键字"} placeholder={"Login,登录成功"}
                                            value={getFilter().Keywords.join(",")}
                                            disable={loading}
                                            setValue={e => {
                                                setFilter({...getFilter(), Keywords: e.split(",").filter(i => !!i)})
                                            }}
                                            extraFormItemProps={{style: {marginBottom: 0}}}
                                        />
                                    </Col>
                                    <Col span={12}>
                                        <InputItem
                                            label={"正则"} placeholder={`Welcome\\s+\\w+!`}
                                            value={getFilter().Regexps.join(",")}
                                            disable={loading}
                                            setValue={e => {
                                                setFilter({...getFilter(), Regexps: e.split(",").filter(i => !!i)})
                                            }}
                                            extraFormItemProps={{style: {marginBottom: 0, marginTop: 2}}}
                                        />
                                    </Col>
                                </Row>
                            </Form>
                        </AutoCard>
                    </Col>
                </Row>
            )}
            {/*<Divider style={{marginTop: 6, marginBottom: 8, paddingTop: 0}}/>*/}
            <ResizeBox
                firstMinSize={350} secondMinSize={360}
                style={{overflow: "hidden"}}
                firstNode={<HTTPPacketEditor
                    system={props.system}
                    refreshTrigger={refreshTrigger}
                    hideSearch={true}
                    bordered={true}
                    originValue={new Buffer(request)}
                    actions={[
                        {
                            id: "packet-from-url",
                            label: "URL转数据包",
                            contextMenuGroupId: "1_urlPacket",
                            run: () => {
                                setUrlPacketShow(true)
                            }
                        },
                        {
                            id: "copy-as-url",
                            label: "复制为 URL",
                            contextMenuGroupId: "1_urlPacket",
                            run: () => {
                                copyAsUrl({Request: getRequest(), IsHTTPS: getIsHttps()})
                            }
                        },
                        {
                            id: "insert-intruder-tag",
                            label: "插入模糊测试字典标签",
                            contextMenuGroupId: "1_urlPacket",
                            run: (editor) => {
                                showDictsAndSelect(i => {
                                    monacoEditorWrite(editor, i, editor.getSelection())
                                })
                            }
                        },
                        {
                            id: "insert-hotpatch-tag",
                            label: "插入热加载标签",
                            contextMenuGroupId: "1_urlPacket",
                            run: (editor) => {
                                hotPatchTrigger()
                            }
                        },
                    ]}
                    onEditor={setReqEditor}
                    onChange={(i) => setRequest(new Buffer(i).toString("utf8"))}
                    extra={
                        <Space size={2}>
                            <Button
                                style={{marginRight: 1}}
                                size={"small"} type={"primary"}
                                onClick={() => {
                                    hotPatchTrigger()
                                }}
                            >热加载标签</Button>
                            <Popover
                                trigger={"click"}
                                title={"从 URL 加载数据包"}
                                content={
                                    <div style={{width: 400}}>
                                        <Form
                                            layout={"vertical"}
                                            onSubmitCapture={(e) => {
                                                e.preventDefault()

                                                ipcRenderer
                                                    .invoke("Codec", {
                                                        Type: "packet-from-url",
                                                        Text: targetUrl
                                                    })
                                                    .then((e) => {
                                                        if (e?.Result) {
                                                            setRequest(e.Result)
                                                            refreshRequest()
                                                        }
                                                    })
                                                    .finally(() => {
                                                    })
                                            }}
                                            size={"small"}
                                        >
                                            <InputItem
                                                label={"从 URL 构造请求"}
                                                value={targetUrl}
                                                setValue={setTargetUrl}
                                                extraFormItemProps={{style: {marginBottom: 8}}}
                                            ></InputItem>
                                            <Form.Item style={{marginBottom: 8}}>
                                                <Button type={"primary"} htmlType={"submit"}>
                                                    构造请求
                                                </Button>
                                            </Form.Item>

                                        </Form>
                                    </div>
                                }
                            >
                                <Button size={"small"} type={"primary"}>
                                    URL
                                </Button>
                            </Popover>
                            <Popover
                                trigger={"click"}
                                placement={"bottom"}
                                destroyTooltipOnHide={true}
                                content={
                                    <div style={{width: 400}}>
                                        <HTTPFuzzerHistorySelector onSelect={e => {
                                            loadHistory(e)
                                        }}/>
                                    </div>
                                }
                            >
                                <Button size={"small"} type={"primary"} icon={<HistoryOutlined/>}>
                                    历史
                                </Button>
                            </Popover>
                        </Space>
                    }
                />}
                secondNode={<AutoSpin spinning={false}>
                    {onlyOneResponse ? (
                        <>{redirectedResponse ? responseViewer(redirectedResponse) : responseViewer(content[0])}</>
                    ) : (
                        <>
                            {(content || []).length > 0 ? (
                                <HTTPFuzzerResultsCard
                                    onSendToWebFuzzer={sendToFuzzer}
                                    sendToPlugin={sendToPlugin}
                                    setRequest={(r) => {
                                        setRequest(r)
                                        refreshRequest()
                                    }}
                                    extra={
                                        <div>
                                            <Input
                                                value={keyword}
                                                style={{maxWidth: 200}}
                                                allowClear
                                                placeholder="输入字符串或正则表达式"
                                                onChange={e => setKeyword(e.target.value)}
                                                addonAfter={
                                                    <DownloadOutlined style={{cursor: "pointer"}}
                                                                      onClick={downloadContent}/>
                                                }></Input>
                                        </div>
                                    }
                                    failedResponses={failedResults}
                                    successResponses={filterContent.length !== 0 ? filterContent : keyword ? [] : successResults}
                                />
                            ) : (
                                <Result
                                    status={"info"}
                                    title={"请在左边编辑并发送一个 HTTP 请求/模糊测试"}
                                    subTitle={
                                        "本栏结果针对模糊测试的多个 HTTP 请求结果展示做了优化,可以自动识别单个/多个请求的展示"
                                    }
                                />
                            )}
                        </>
                    )}
                </AutoSpin>}/>
            <Modal
                visible={urlPacketShow}
                title='从 URL 加载数据包'
                onCancel={() => setUrlPacketShow(false)}
                footer={null}
            >
                <Form
                    layout={"vertical"}
                    onSubmitCapture={(e) => {
                        e.preventDefault()

                        ipcRenderer
                            .invoke("Codec", {
                                Type: "packet-from-url",
                                Text: targetUrl
                            })
                            .then((e) => {
                                if (e?.Result) {
                                    setRequest(e.Result)
                                    refreshRequest()
                                    setUrlPacketShow(false)
                                }
                            })
                            .finally(() => {
                            })
                    }}
                    size={"small"}
                >
                    <InputItem
                        label={"从 URL 构造请求"}
                        value={targetUrl}
                        setValue={setTargetUrl}
                        extraFormItemProps={{style: {marginBottom: 8}}}
                    ></InputItem>
                    <Form.Item style={{marginBottom: 8}}>
                        <Button type={"primary"} htmlType={"submit"}>
                            构造请求
                        </Button>
                    </Form.Item>
                </Form>
            </Modal>
        </div>
    )
}