diff --git a/web/bun.lockb b/web/bun.lockb index 7cc671c7..fc1d67d7 100755 Binary files a/web/bun.lockb and b/web/bun.lockb differ diff --git a/web/package.json b/web/package.json index 653534fd..811a7389 100644 --- a/web/package.json +++ b/web/package.json @@ -15,7 +15,7 @@ }, "devDependencies": { "@biomejs/biome": "1.9.4", - "@tanstack/router-plugin": "^1.111.7", + "@tanstack/router-plugin": "^1.112.0", "@types/node": "^22.13.5", "@types/react": "^19.0.10", "@types/react-copy-to-clipboard": "^5.0.7", @@ -23,7 +23,7 @@ "@types/react-syntax-highlighter": "^15.5.13", "@vitejs/plugin-react": "^4.3.4", "rimraf": "^6.0.1", - "tailwindcss": "^4.0.8", + "tailwindcss": "^4.0.9", "typescript": "^5.7.3", "vite": "^6.2.0", "vite-bundle-visualizer": "^1.2.1" @@ -41,14 +41,14 @@ "@radix-ui/react-switch": "^1.1.3", "@radix-ui/react-tabs": "^1.1.3", "@radix-ui/react-tooltip": "^1.1.8", - "@tailwindcss/vite": "^4.0.8", - "@tanstack/react-query": "^5.66.9", - "@tanstack/react-router": "^1.111.7", - "@tanstack/router-devtools": "^1.111.7", + "@tailwindcss/vite": "^4.0.9", + "@tanstack/react-query": "^5.66.11", + "@tanstack/react-router": "^1.112.0", + "@tanstack/router-devtools": "^1.112.0", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "i18next": "^24.2.2", - "lucide-react": "^0.475.0", + "lucide-react": "^0.476.0", "react": "^19.0.0", "react-copy-to-clipboard": "^5.1.0", "react-dom": "^19.0.0", diff --git a/web/src/components/main-config-card.tsx b/web/src/components/main-config-card.tsx index 8bd0f5d1..be0559d8 100644 --- a/web/src/components/main-config-card.tsx +++ b/web/src/components/main-config-card.tsx @@ -1,12 +1,10 @@ -import { UrlPatternTip } from "@/components/tips/url-pattern-tip.tsx"; import { FormControl, FormDescription, FormField, FormItem, FormLabel } from "@/components/ui/form.tsx"; -import { Input } from "@/components/ui/input.tsx"; import { Label } from "@/components/ui/label.tsx"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select.tsx"; import { Switch } from "@/components/ui/switch.tsx"; -import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; +import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { FormSchema } from "@/types/schema.ts"; -import { MainConfig } from "@/types/shell.ts"; +import { JDKVersion, MainConfig, ShellToolType } from "@/types/shell.ts"; import { JreTip } from "@/components/tips/jre-tip.tsx"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card.tsx"; @@ -23,25 +21,20 @@ import { import { JSX, useState } from "react"; import { FormProvider, UseFormReturn } from "react-hook-form"; import { useTranslation } from "react-i18next"; - -const JDKVersion = [ - { name: "Java6", value: "50" }, - { name: "Java8", value: "52" }, - { name: "Java9", value: "53" }, - { name: "Java11", value: "55" }, - { name: "Java17", value: "61" }, - { name: "Java21", value: "65" }, -]; - -type ShellToolType = "Behinder" | "Godzilla" | "Command" | "AntSword" | "Suo5" | "Neo-reGeorg"; +import { AntSwordTabContent } from "./tools/antsword-tab"; +import { BehinderTabContent } from "./tools/behinder-tab"; +import { CommandTabContent } from "./tools/command-tab"; +import { GodzillaTabContent } from "./tools/godzilla-tab"; +import { NeoRegTabContent } from "./tools/neoreg-tab"; +import { Suo5TabContent } from "./tools/suo5-tab"; const shellToolIcons: Record = { - Behinder: , - Godzilla: , - Command: , - AntSword: , - Suo5: , - "Neo-reGeorg": , + [ShellToolType.Behinder]: , + [ShellToolType.Godzilla]: , + [ShellToolType.Command]: , + [ShellToolType.AntSword]: , + [ShellToolType.Suo5]: , + [ShellToolType.NeoreGeorg]: , }; export function MainConfigCard({ @@ -56,13 +49,13 @@ export function MainConfigCard({ const [shellToolMap, setShellToolMap] = useState<{ [toolName: string]: string[]; }>(); - const [shellTools, setShellTools] = useState([ - "Behinder", - "Godzilla", - "Command", - "AntSword", - "Suo5", - "Neo-reGeorg", + const [shellTools, setShellTools] = useState([ + ShellToolType.Godzilla, + ShellToolType.Behinder, + ShellToolType.AntSword, + ShellToolType.Command, + ShellToolType.Suo5, + ShellToolType.NeoreGeorg, ]); const [shellTypes, setShellTypes] = useState([]); const shellTool = form.watch("shellTool"); @@ -73,7 +66,7 @@ export function MainConfigCard({ const newShellToolMap = mainConfig[value]; setShellToolMap(newShellToolMap); const newShellTools = Object.keys(newShellToolMap); - setShellTools(newShellTools); + setShellTools(newShellTools.map((tool) => tool as ShellToolType)); if (newShellTools.length > 0) { const firstTool = newShellTools[0]; setShellTypes(newShellToolMap[firstTool]); @@ -126,22 +119,29 @@ export function MainConfigCard({ form.resetField("headerValue"); }; + const resetNeoreGeorg = () => { + form.setValue("headerName", "Referer"); + form.resetField("headerValue"); + }; + if (shellToolMap) { setShellTypes(shellToolMap[value]); form.resetField("urlPattern"); form.resetField("shellType"); form.resetField("shellClassName"); form.resetField("injectorClassName"); - if (value === "Godzilla") { + if (value === ShellToolType.Godzilla) { resetGodzilla(); - } else if (value === "Behinder") { + } else if (value === ShellToolType.Behinder) { resetBehinder(); - } else if (value === "Command") { + } else if (value === ShellToolType.Command) { resetCommand(); - } else if (value === "Suo5") { + } else if (value === ShellToolType.Suo5) { resetSuo5(); - } else if (value === "AntSword") { + } else if (value === ShellToolType.AntSword) { resetAntSword(); + } else if (value === ShellToolType.NeoreGeorg) { + resetNeoreGeorg(); } } form.setValue("shellTool", value); @@ -282,7 +282,7 @@ export function MainConfigCard({ }} className="w-full" > -
+
{shellTools.map((shellTool) => (
- + - + ); } - -function ShellTypeFormField({ form, shellTypes }: { form: UseFormReturn; shellTypes: Array }) { - const { t } = useTranslation(); - return ( - - ( - - {t("mainConfig.shellMountType")} - - - )} - /> - - ); -} - -function UrlPatternFormField({ form }: { form: UseFormReturn }) { - const { t } = useTranslation(); - return ( - - ( - - - {t("mainConfig.urlPattern")} - - - - )} - /> - - ); -} - -function OptionalClassFormField({ form }: { form: UseFormReturn }) { - const { t } = useTranslation(); - return ( - - ( - - - {t("mainConfig.shellClassName")} {t("optional")} - - - - )} - /> - ( - - - {t("mainConfig.injectorClassName")} {t("optional")} - - - - )} - /> - - ); -} - -function BehinderTabContent({ form, shellTypes }: { form: UseFormReturn; shellTypes: Array }) { - const { t } = useTranslation(); - return ( - - - - -
- - -
- ( - - {t("shellToolConfig.behinderPass")} - - - )} - /> -
- ( - - {t("shellToolConfig.headerName")} - - - )} - /> - ( - - {t("shellToolConfig.headerValue")} - - - )} - /> -
- -
-
-
-
- ); -} - -function GodzillaTabContent({ form, shellTypes }: { form: UseFormReturn; shellTypes: Array }) { - const { t } = useTranslation(); - return ( - - - - -
- - -
-
- ( - - {t("shellToolConfig.pass")} - - - )} - /> - ( - - {t("shellToolConfig.key")} - - - )} - /> - ( - - {t("shellToolConfig.headerName")} - - - )} - /> - ( - - {t("shellToolConfig.headerValue")} - - - )} - /> -
- -
-
-
-
- ); -} - -function CommandTabContent({ form, shellTypes }: { form: UseFormReturn; shellTypes: Array }) { - const { t } = useTranslation(); - return ( - - - - -
- - -
- ( - - {t("shellToolConfig.paramName")} - - - - - )} - /> - -
-
-
-
- ); -} - -function AntSwordTabContent({ form, shellTypes }: { form: UseFormReturn; shellTypes: Array }) { - const { t } = useTranslation(); - return ( - - - - -
- - -
- ( - - {t("shellToolConfig.antSwordPass")} - - - )} - /> -
- ( - - {t("shellToolConfig.headerName")} - - - )} - /> - ( - - {t("shellToolConfig.headerValue")} - - - )} - /> -
- -
-
-
-
- ); -} - -function Suo5TabContent({ form, shellTypes }: { form: UseFormReturn; shellTypes: Array }) { - const { t } = useTranslation(); - return ( - - - - -
- - -
-
- ( - - {t("shellToolConfig.headerName")} - - - )} - /> - ( - - {t("shellToolConfig.headerValue")} - - - )} - /> -
- -
-
-
-
- ); -} - -function NeoreGeorgTabContent() { - return ( - - - -
- WIP -
-
-
-
- ); -} diff --git a/web/src/components/results/agent.tsx b/web/src/components/results/agent.tsx new file mode 100644 index 00000000..9cce853a --- /dev/null +++ b/web/src/components/results/agent.tsx @@ -0,0 +1,60 @@ +import { downloadBytes } from "@/lib/utils"; +import { GenerateResult } from "@/types/shell"; +import { Separator } from "@radix-ui/react-dropdown-menu"; +import { ScrollTextIcon } from "lucide-react"; +import { useTranslation } from "react-i18next"; +import { Button } from "../ui/button"; +import { Card, CardContent, CardHeader, CardTitle } from "../ui/card"; + +export function AgentResult({ packResult, generateResult }: { packResult: string; generateResult?: GenerateResult }) { + const { t } = useTranslation(); + return ( + + + + + {t("generateResult.usage")} + + + +
    +
  1. + {t("download")} MemShellAgent.jar + +
  2. +
  3. + {t("tips.download-jattach")} + +
  4. + +
  5. {t("tips.move-to-container")}
  6. +
  7. {t("tips.get-pid")}
  8. +
  9. {t("tips.execute-command")}
  10. +
  11. {t("tips.try-to-use-shell")}
  12. +
+
+
+ ); +} diff --git a/web/src/components/results/basic-info.tsx b/web/src/components/results/basic-info.tsx new file mode 100644 index 00000000..e3ea4e02 --- /dev/null +++ b/web/src/components/results/basic-info.tsx @@ -0,0 +1,140 @@ +import { + AntSwordShellToolConfig, + BehinderShellToolConfig, + CommandShellToolConfig, + GenerateResult, + GodzillaShellToolConfig, + Suo5ShellToolConfig, +} from "@/types/shell"; +import { Separator } from "@radix-ui/react-dropdown-menu"; +import { FileTextIcon } from "lucide-react"; +import { useTranslation } from "react-i18next"; +import { Fragment } from "react/jsx-runtime"; +import { CopyableField } from "../copyable-field"; +import { Card, CardContent, CardHeader, CardTitle } from "../ui/card"; +import { FeedbackAlert } from "./feedback-alert"; + +export function BasicInfo({ generateResult }: { generateResult?: GenerateResult }) { + const { t } = useTranslation(); + return ( + + + +
+ + {t("generateResult.basicInfo")} +
+ +
+
+ +
+ + + + +
+ + + {(generateResult?.shellConfig.shellTool === "Behinder" || + generateResult?.shellConfig.shellTool === "Godzilla" || + generateResult?.shellConfig.shellTool === "Command" || + generateResult?.shellConfig.shellTool === "AntSword" || + generateResult?.shellConfig.shellTool === "Suo5") && ( +
+ {/* Tool-specific fields */} + {generateResult?.shellConfig.shellTool === "Behinder" && ( + <> + + + + + + )} + {generateResult?.shellConfig.shellTool === "Godzilla" && ( + + + + + + + + )} + {generateResult?.shellConfig.shellTool === "Command" && ( + + + + )} + {generateResult?.shellConfig.shellTool === "Suo5" && ( + + + + )} + {generateResult?.shellConfig.shellTool === "AntSword" && ( + + + + + )} +
+ )} + +
+ + +
+
+
+ ); +} diff --git a/web/src/components/results/feedback-alert.tsx b/web/src/components/results/feedback-alert.tsx new file mode 100644 index 00000000..e9d2900a --- /dev/null +++ b/web/src/components/results/feedback-alert.tsx @@ -0,0 +1,49 @@ +import { + AlertDialog, + AlertDialogAction, + AlertDialogCancel, + AlertDialogContent, + AlertDialogDescription, + AlertDialogTitle, + AlertDialogTrigger, +} from "@radix-ui/react-alert-dialog"; +import { CircleHelpIcon } from "lucide-react"; +import { useTranslation } from "react-i18next"; +import { AlertDialogFooter, AlertDialogHeader } from "../ui/alert-dialog"; +import { Button } from "../ui/button"; + +export function FeedbackAlert() { + const { t } = useTranslation(); + return ( + + + + + + + {t("shellNotWork.title")} + +
    +
  1. {t("shellNotWork.step1")}
  2. +
  3. {t("shellNotWork.step2")}
  4. +
+
+
+ + {t("cancel")} + + window.open( + "https://github.com/ReaJason/MemShellParty/issues/new?template=%E5%86%85%E5%AD%98%E9%A9%AC%E7%94%9F%E6%88%90-bug-%E4%B8%8A%E6%8A%A5.md", + ) + } + > + {t("feedback")} + + +
+
+ ); +} diff --git a/web/src/components/results/jar-result.tsx b/web/src/components/results/jar-result.tsx new file mode 100644 index 00000000..3951e36a --- /dev/null +++ b/web/src/components/results/jar-result.tsx @@ -0,0 +1,24 @@ +import { downloadBytes } from "@/lib/utils"; +import { GenerateResult } from "@/types/shell"; +import { useTranslation } from "react-i18next"; +import { Button } from "../ui/button"; + +export function JarResult({ packResult, generateResult }: { packResult: string; generateResult?: GenerateResult }) { + const { t } = useTranslation(); + return ( +
+ +
+ ); +} diff --git a/web/src/components/results/multi-packer.tsx b/web/src/components/results/multi-packer.tsx new file mode 100644 index 00000000..7d14642e --- /dev/null +++ b/web/src/components/results/multi-packer.tsx @@ -0,0 +1,63 @@ +import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@radix-ui/react-select"; +import { TFunction } from "i18next"; +import { useEffect, useState } from "react"; +import { Fragment } from "react/jsx-runtime"; +import { CodeViewer } from "../code-viewer"; + +export function MultiPackResult({ + allPackResults, + packMethod, + t, +}: { + allPackResults: object | undefined; + packMethod: string; + t: TFunction; +}) { + const showCode = packMethod === "JSP"; + const packMethods = Object.keys(allPackResults ?? {}); + const [selectedMethod, setSelectedMethod] = useState(packMethods[0]); + const [packResult, setPackResult] = useState(allPackResults?.[selectedMethod as keyof typeof allPackResults] ?? ""); + + useEffect(() => { + const methods = Object.keys(allPackResults ?? {}); + const firstMethod = methods[0]; + setSelectedMethod(firstMethod); + setPackResult(allPackResults?.[firstMethod as keyof typeof allPackResults] ?? ""); + }, [allPackResults]); + + return ( + + + + ({packResult?.length}) +
+ } + wrapLongLines={!showCode} + showLineNumbers={showCode} + language={showCode ? "java" : "text"} + height={350} + /> + + ); +} diff --git a/web/src/components/results/result-component.tsx b/web/src/components/results/result-component.tsx new file mode 100644 index 00000000..383b7daf --- /dev/null +++ b/web/src/components/results/result-component.tsx @@ -0,0 +1,57 @@ +import { GenerateResult } from "@/types/shell"; +import { TFunction } from "i18next"; +import { Fragment } from "react/jsx-runtime"; +import { CodeViewer } from "../code-viewer"; +import { AgentResult } from "./agent"; +import { JarResult } from "./jar-result"; +import { MultiPackResult } from "./multi-packer"; + +export function ResultComponent({ + packResult, + allPackResults, + packMethod, + t, + generateResult, +}: { + packResult: string | undefined; + allPackResults: Map | undefined; + packMethod: string; + t: TFunction; + generateResult?: GenerateResult; +}) { + const showCode = packMethod === "JSP"; + const isAgent = packMethod.startsWith("Agent"); + const isJar = packMethod === "Jar"; + if (allPackResults) { + return ; + } + + if (isAgent) { + return ; + } + if (isJar) { + return ; + } + if (!isAgent && !isJar) { + return ( + + + + {t("packageConfig.title")}:{packMethod} + + ({packResult?.length}) + + } + wrapLongLines={!showCode} + showLineNumbers={showCode} + language={showCode ? "java" : "text"} + height={350} + /> + + ); + } + return null; +} diff --git a/web/src/components/shell-result.tsx b/web/src/components/shell-result.tsx index e29adddd..41881e71 100644 --- a/web/src/components/shell-result.tsx +++ b/web/src/components/shell-result.tsx @@ -1,373 +1,15 @@ import { CodeViewer } from "@/components/code-viewer.tsx"; -import { CopyableField } from "@/components/copyable-field.tsx"; import { QuickUsage } from "@/components/quick-usage.tsx"; -import { - AlertDialog, - AlertDialogAction, - AlertDialogCancel, - AlertDialogContent, - AlertDialogDescription, - AlertDialogFooter, - AlertDialogHeader, - AlertDialogTitle, - AlertDialogTrigger, -} from "@/components/ui/alert-dialog"; import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert.tsx"; import { Button } from "@/components/ui/button.tsx"; -import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card.tsx"; -import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; -import { Separator } from "@/components/ui/separator.tsx"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs.tsx"; import { downloadBytes } from "@/lib/utils.ts"; -import { - AntSwordShellToolConfig, - BehinderShellToolConfig, - CommandShellToolConfig, - GenerateResult, - GodzillaShellToolConfig, - Suo5ShellToolConfig, -} from "@/types/shell.ts"; -import { TFunction } from "i18next"; -import { CircleHelpIcon, FileTextIcon, ScrollTextIcon, TriangleAlertIcon } from "lucide-react"; -import { Fragment, useEffect, useState } from "react"; +import { GenerateResult } from "@/types/shell.ts"; +import { TriangleAlertIcon } from "lucide-react"; import { useTranslation } from "react-i18next"; import { toast } from "sonner"; - -function AgentResult({ packResult, generateResult }: { packResult: string; generateResult?: GenerateResult }) { - const { t } = useTranslation(); - return ( - - - - - {t("generateResult.usage")} - - - -
    -
  1. - {t("download")} MemShellAgent.jar - -
  2. -
  3. - {t("tips.download-jattach")} - -
  4. - -
  5. {t("tips.move-to-container")}
  6. -
  7. {t("tips.get-pid")}
  8. -
  9. {t("tips.execute-command")}
  10. -
  11. {t("tips.try-to-use-shell")}
  12. -
-
-
- ); -} - -function JarResult({ packResult, generateResult }: { packResult: string; generateResult?: GenerateResult }) { - const { t } = useTranslation(); - return ( -
- -
- ); -} - -function FeedbackAlert() { - const { t } = useTranslation(); - return ( - - - - - - - {t("shellNotWork.title")} - -
    -
  1. {t("shellNotWork.step1")}
  2. -
  3. {t("shellNotWork.step2")}
  4. -
-
-
- - {t("cancel")} - - window.open( - "https://github.com/ReaJason/MemShellParty/issues/new?template=%E5%86%85%E5%AD%98%E9%A9%AC%E7%94%9F%E6%88%90-bug-%E4%B8%8A%E6%8A%A5.md", - ) - } - > - {t("feedback")} - - -
-
- ); -} - -function BasicInfo({ generateResult }: { generateResult?: GenerateResult }) { - const { t } = useTranslation(); - return ( - - - -
- - {t("generateResult.basicInfo")} -
- -
-
- -
- - - - -
- - - {(generateResult?.shellConfig.shellTool === "Behinder" || - generateResult?.shellConfig.shellTool === "Godzilla" || - generateResult?.shellConfig.shellTool === "Command" || - generateResult?.shellConfig.shellTool === "AntSword" || - generateResult?.shellConfig.shellTool === "Suo5") && ( -
- {/* Tool-specific fields */} - {generateResult?.shellConfig.shellTool === "Behinder" && ( - <> - - - - - - )} - {generateResult?.shellConfig.shellTool === "Godzilla" && ( - - - - - - - - )} - {generateResult?.shellConfig.shellTool === "Command" && ( - - - - )} - {generateResult?.shellConfig.shellTool === "Suo5" && ( - - - - )} - {generateResult?.shellConfig.shellTool === "AntSword" && ( - - - - - )} -
- )} - -
- - -
-
-
- ); -} - -function MultiPackResult({ - allPackResults, - packMethod, - t, -}: { - allPackResults: object | undefined; - packMethod: string; - t: TFunction; -}) { - const showCode = packMethod === "JSP"; - const packMethods = Object.keys(allPackResults ?? {}); - const [selectedMethod, setSelectedMethod] = useState(packMethods[0]); - const [packResult, setPackResult] = useState(allPackResults?.[selectedMethod as keyof typeof allPackResults] ?? ""); - - useEffect(() => { - const methods = Object.keys(allPackResults ?? {}); - const firstMethod = methods[0]; - setSelectedMethod(firstMethod); - setPackResult(allPackResults?.[firstMethod as keyof typeof allPackResults] ?? ""); - }, [allPackResults]); - - return ( - - - - ({packResult?.length}) - - } - wrapLongLines={!showCode} - showLineNumbers={showCode} - language={showCode ? "java" : "text"} - height={350} - /> - - ); -} - -function renderResultComponent( - packResult: string | undefined, - allPackResults: Map | undefined, - packMethod: string, - t: TFunction, - generateResult?: GenerateResult, -) { - const showCode = packMethod === "JSP"; - const isAgent = packMethod.startsWith("Agent"); - const isJar = packMethod === "Jar"; - if (allPackResults) { - return ; - } - - if (isAgent) { - return ; - } - if (isJar) { - return ; - } - if (!isAgent && !isJar) { - return ( - - - - {t("packageConfig.title")}:{packMethod} - - ({packResult?.length}) - - } - wrapLongLines={!showCode} - showLineNumbers={showCode} - language={showCode ? "java" : "text"} - height={350} - /> - - ); - } - return null; -} +import { BasicInfo } from "./results/basic-info"; +import { ResultComponent } from "./results/result-component"; export function ShellResult({ packResult, @@ -391,11 +33,15 @@ export function ShellResult({ {t("generateResult.title2")} {t("generateResult.title3")} - -
- -
- {renderResultComponent(packResult, allPackResults, packMethod, t, generateResult)} + + + diff --git a/web/src/components/tools/antsword-tab.tsx b/web/src/components/tools/antsword-tab.tsx new file mode 100644 index 00000000..03ea2d61 --- /dev/null +++ b/web/src/components/tools/antsword-tab.tsx @@ -0,0 +1,64 @@ +import { FormSchema } from "@/types/schema"; +import { TabsContent } from "@radix-ui/react-tabs"; +import { FormProvider, UseFormReturn } from "react-hook-form"; +import { useTranslation } from "react-i18next"; +import { Card, CardContent } from "../ui/card"; +import { FormField, FormItem, FormLabel } from "../ui/form"; +import { Input } from "../ui/input"; +import { OptionalClassFormField } from "./classname-field"; +import { ShellTypeFormField } from "./shelltype-field"; +import { UrlPatternFormField } from "./urlpattern-field"; + +export function AntSwordTabContent({ + form, + shellTypes, +}: { form: UseFormReturn; shellTypes: Array }) { + const { t } = useTranslation(); + return ( + + + + +
+ + +
+ ( + + {t("shellToolConfig.antSwordPass")} + + + )} + /> +
+ ( + + {t("shellToolConfig.headerName")} + + + )} + /> + ( + + {t("shellToolConfig.headerValue")} + + + )} + /> +
+ +
+
+
+
+ ); +} diff --git a/web/src/components/tools/behinder-tab.tsx b/web/src/components/tools/behinder-tab.tsx new file mode 100644 index 00000000..0c207d6d --- /dev/null +++ b/web/src/components/tools/behinder-tab.tsx @@ -0,0 +1,64 @@ +import { FormSchema } from "@/types/schema"; +import { TabsContent } from "@radix-ui/react-tabs"; +import { FormProvider, UseFormReturn } from "react-hook-form"; +import { useTranslation } from "react-i18next"; +import { Card, CardContent } from "../ui/card"; +import { FormField, FormItem, FormLabel } from "../ui/form"; +import { Input } from "../ui/input"; +import { OptionalClassFormField } from "./classname-field"; +import { ShellTypeFormField } from "./shelltype-field"; +import { UrlPatternFormField } from "./urlpattern-field"; + +export function BehinderTabContent({ + form, + shellTypes, +}: { form: UseFormReturn; shellTypes: Array }) { + const { t } = useTranslation(); + return ( + + + + +
+ + +
+ ( + + {t("shellToolConfig.behinderPass")} + + + )} + /> +
+ ( + + {t("shellToolConfig.headerName")} + + + )} + /> + ( + + {t("shellToolConfig.headerValue")} + + + )} + /> +
+ +
+
+
+
+ ); +} diff --git a/web/src/components/tools/classname-field.tsx b/web/src/components/tools/classname-field.tsx new file mode 100644 index 00000000..443d9eba --- /dev/null +++ b/web/src/components/tools/classname-field.tsx @@ -0,0 +1,37 @@ +import { FormField, FormItem, FormLabel } from "@/components/ui/form.tsx"; +import { Input } from "@/components/ui/input.tsx"; +import { FormSchema } from "@/types/schema.ts"; +import { FormProvider, UseFormReturn } from "react-hook-form"; +import { useTranslation } from "react-i18next"; + +export function OptionalClassFormField({ form }: { form: UseFormReturn }) { + const { t } = useTranslation(); + return ( + + ( + + + {t("mainConfig.shellClassName")} {t("optional")} + + + + )} + /> + ( + + + {t("mainConfig.injectorClassName")} {t("optional")} + + + + )} + /> + + ); +} diff --git a/web/src/components/tools/command-tab.tsx b/web/src/components/tools/command-tab.tsx new file mode 100644 index 00000000..c03cb9e5 --- /dev/null +++ b/web/src/components/tools/command-tab.tsx @@ -0,0 +1,44 @@ +import { FormSchema } from "@/types/schema"; +import { TabsContent } from "@radix-ui/react-tabs"; +import { FormProvider, UseFormReturn } from "react-hook-form"; +import { useTranslation } from "react-i18next"; +import { Card, CardContent } from "../ui/card"; +import { FormControl, FormField, FormItem, FormLabel } from "../ui/form"; +import { Input } from "../ui/input"; +import { OptionalClassFormField } from "./classname-field"; +import { ShellTypeFormField } from "./shelltype-field"; +import { UrlPatternFormField } from "./urlpattern-field"; + +export function CommandTabContent({ + form, + shellTypes, +}: { form: UseFormReturn; shellTypes: Array }) { + const { t } = useTranslation(); + return ( + + + + +
+ + +
+ ( + + {t("shellToolConfig.paramName")} + + + + + )} + /> + +
+
+
+
+ ); +} diff --git a/web/src/components/tools/godzilla-tab.tsx b/web/src/components/tools/godzilla-tab.tsx new file mode 100644 index 00000000..a9ecad5b --- /dev/null +++ b/web/src/components/tools/godzilla-tab.tsx @@ -0,0 +1,74 @@ +import { FormSchema } from "@/types/schema"; +import { TabsContent } from "@radix-ui/react-tabs"; +import { FormProvider, UseFormReturn } from "react-hook-form"; +import { useTranslation } from "react-i18next"; +import { Card, CardContent } from "../ui/card"; +import { FormField, FormItem, FormLabel } from "../ui/form"; +import { Input } from "../ui/input"; +import { OptionalClassFormField } from "./classname-field"; +import { ShellTypeFormField } from "./shelltype-field"; +import { UrlPatternFormField } from "./urlpattern-field"; + +export function GodzillaTabContent({ + form, + shellTypes, +}: { form: UseFormReturn; shellTypes: Array }) { + const { t } = useTranslation(); + return ( + + + + +
+ + +
+
+ ( + + {t("shellToolConfig.pass")} + + + )} + /> + ( + + {t("shellToolConfig.key")} + + + )} + /> + ( + + {t("shellToolConfig.headerName")} + + + )} + /> + ( + + {t("shellToolConfig.headerValue")} + + + )} + /> +
+ +
+
+
+
+ ); +} diff --git a/web/src/components/tools/neoreg-tab.tsx b/web/src/components/tools/neoreg-tab.tsx new file mode 100644 index 00000000..99308f04 --- /dev/null +++ b/web/src/components/tools/neoreg-tab.tsx @@ -0,0 +1,51 @@ +import { FormSchema } from "@/types/schema"; +import { TabsContent } from "@radix-ui/react-tabs"; +import { FormProvider, UseFormReturn } from "react-hook-form"; +import { useTranslation } from "react-i18next"; +import { Card, CardContent } from "../ui/card"; +import { FormField, FormItem, FormLabel } from "../ui/form"; +import { Input } from "../ui/input"; +import { OptionalClassFormField } from "./classname-field"; +import { ShellTypeFormField } from "./shelltype-field"; +import { UrlPatternFormField } from "./urlpattern-field"; + +export function NeoRegTabContent({ form, shellTypes }: { form: UseFormReturn; shellTypes: Array }) { + const { t } = useTranslation(); + return ( + + + + +
+ + +
+
+ ( + + {t("shellToolConfig.headerName")} + + + )} + /> + ( + + {t("shellToolConfig.headerValue")} + + + )} + /> +
+ +
+
+
+
+ ); +} diff --git a/web/src/components/tools/shelltype-field.tsx b/web/src/components/tools/shelltype-field.tsx new file mode 100644 index 00000000..1eedbde6 --- /dev/null +++ b/web/src/components/tools/shelltype-field.tsx @@ -0,0 +1,44 @@ +import { FormControl, FormField, FormItem, FormLabel } from "@/components/ui/form.tsx"; +import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select.tsx"; +import { FormSchema } from "@/types/schema.ts"; + +import { FormProvider, UseFormReturn } from "react-hook-form"; +import { useTranslation } from "react-i18next"; + +export function ShellTypeFormField({ + form, + shellTypes, +}: { form: UseFormReturn; shellTypes: Array }) { + const { t } = useTranslation(); + return ( + + ( + + {t("mainConfig.shellMountType")} + + + )} + /> + + ); +} diff --git a/web/src/components/tools/suo5-tab.tsx b/web/src/components/tools/suo5-tab.tsx new file mode 100644 index 00000000..ba07f27c --- /dev/null +++ b/web/src/components/tools/suo5-tab.tsx @@ -0,0 +1,51 @@ +import { FormSchema } from "@/types/schema"; +import { TabsContent } from "@radix-ui/react-tabs"; +import { FormProvider, UseFormReturn } from "react-hook-form"; +import { useTranslation } from "react-i18next"; +import { Card, CardContent } from "../ui/card"; +import { FormField, FormItem, FormLabel } from "../ui/form"; +import { Input } from "../ui/input"; +import { OptionalClassFormField } from "./classname-field"; +import { ShellTypeFormField } from "./shelltype-field"; +import { UrlPatternFormField } from "./urlpattern-field"; + +export function Suo5TabContent({ form, shellTypes }: { form: UseFormReturn; shellTypes: Array }) { + const { t } = useTranslation(); + return ( + + + + +
+ + +
+
+ ( + + {t("shellToolConfig.headerName")} + + + )} + /> + ( + + {t("shellToolConfig.headerValue")} + + + )} + /> +
+ +
+
+
+
+ ); +} diff --git a/web/src/components/tools/urlpattern-field.tsx b/web/src/components/tools/urlpattern-field.tsx new file mode 100644 index 00000000..0fbfc08f --- /dev/null +++ b/web/src/components/tools/urlpattern-field.tsx @@ -0,0 +1,26 @@ +import { UrlPatternTip } from "@/components/tips/url-pattern-tip.tsx"; +import { FormField, FormItem, FormLabel } from "@/components/ui/form.tsx"; +import { Input } from "@/components/ui/input.tsx"; +import { FormSchema } from "@/types/schema.ts"; +import { FormProvider, UseFormReturn } from "react-hook-form"; +import { useTranslation } from "react-i18next"; + +export function UrlPatternFormField({ form }: { form: UseFormReturn }) { + const { t } = useTranslation(); + return ( + + ( + + + {t("mainConfig.urlPattern")} + + + + )} + /> + + ); +} diff --git a/web/src/routes/index.tsx b/web/src/routes/index.tsx index e557a31d..962cbfaf 100644 --- a/web/src/routes/index.tsx +++ b/web/src/routes/index.tsx @@ -37,7 +37,7 @@ function IndexComponent() { debug: false, bypassJavaModule: false, shellClassName: "", - shellTool: "Behinder", + shellTool: "Godzilla", shellType: "", urlPattern: "/*", godzillaPass: "pass", diff --git a/web/src/types/shell.ts b/web/src/types/shell.ts index 5c2e6c08..eb489563 100644 --- a/web/src/types/shell.ts +++ b/web/src/types/shell.ts @@ -94,3 +94,21 @@ export interface GenerateResult { shellToolConfig: CommandShellToolConfig | GodzillaShellToolConfig | BehinderShellToolConfig | AntSwordShellToolConfig; injectorConfig: InjectorConfig; } + +export const JDKVersion = [ + { name: "Java6", value: "50" }, + { name: "Java8", value: "52" }, + { name: "Java9", value: "53" }, + { name: "Java11", value: "55" }, + { name: "Java17", value: "61" }, + { name: "Java21", value: "65" }, +]; + +export enum ShellToolType { + Behinder = "Behinder", + Godzilla = "Godzilla", + Command = "Command", + AntSword = "AntSword", + Suo5 = "Suo5", + NeoreGeorg = "NeoreGeorg", +} diff --git a/web/vite.config.ts b/web/vite.config.ts index e912c489..e96f8f42 100644 --- a/web/vite.config.ts +++ b/web/vite.config.ts @@ -6,7 +6,7 @@ import { defineConfig } from "vite"; // https://vitejs.dev/config/ export default defineConfig({ - plugins: [TanStackRouterVite(), react(), tailwindcss()], + plugins: [TanStackRouterVite({ autoCodeSplitting: true }), react(), tailwindcss()], resolve: { alias: { "@": path.resolve(__dirname, "./src"),