feat: support suo5 v2 shell

This commit is contained in:
ReaJason
2025-12-10 02:09:13 +08:00
parent d7a67b3056
commit dd9333e473
31 changed files with 11821 additions and 34 deletions
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
@@ -55,7 +55,7 @@ public class MemShellGenerateRequest {
.encryptor(CommandConfig.Encryptor.fromString(shellToolConfig.getEncryptor())) .encryptor(CommandConfig.Encryptor.fromString(shellToolConfig.getEncryptor()))
.implementationClass(CommandConfig.ImplementationClass.fromString(shellToolConfig.getImplementationClass())) .implementationClass(CommandConfig.ImplementationClass.fromString(shellToolConfig.getImplementationClass()))
.build(); .build();
case Suo5 -> Suo5Config.builder() case Suo5, Suo5v2 -> Suo5Config.builder()
.shellClassName(shellToolConfig.getShellClassName()) .shellClassName(shellToolConfig.getShellClassName())
.headerName(shellToolConfig.getHeaderName()) .headerName(shellToolConfig.getHeaderName())
.headerValue(shellToolConfig.getHeaderValue()) .headerValue(shellToolConfig.getHeaderValue())
@@ -8,6 +8,7 @@ import com.reajason.javaweb.memshell.shelltool.command.*;
import com.reajason.javaweb.memshell.shelltool.godzilla.*; import com.reajason.javaweb.memshell.shelltool.godzilla.*;
import com.reajason.javaweb.memshell.shelltool.neoreg.*; import com.reajason.javaweb.memshell.shelltool.neoreg.*;
import com.reajason.javaweb.memshell.shelltool.suo5.*; import com.reajason.javaweb.memshell.shelltool.suo5.*;
import com.reajason.javaweb.memshell.shelltool.suo5v2.*;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@@ -184,6 +185,31 @@ public class ServerFactory {
.addShellClass(ACTION, Suo5Struct2Action.class) .addShellClass(ACTION, Suo5Struct2Action.class)
.build()); .build());
addToolMapping(ShellTool.Suo5v2, ToolMapping.builder()
.addShellClass(SERVLET, Suo5v2Servlet.class)
.addShellClass(JAKARTA_SERVLET, Suo5v2Servlet.class)
.addShellClass(FILTER, Suo5v2Filter.class)
.addShellClass(JAKARTA_FILTER, Suo5v2Filter.class)
.addShellClass(LISTENER, Suo5v2Listener.class)
.addShellClass(JAKARTA_LISTENER, Suo5v2Listener.class)
.addShellClass(VALVE, Suo5v2Valve.class)
.addShellClass(JAKARTA_VALVE, Suo5v2Valve.class)
.addShellClass(PROXY_VALVE, Suo5v2.class)
.addShellClass(JAKARTA_PROXY_VALVE, Suo5v2.class)
.addShellClass(SPRING_WEBMVC_INTERCEPTOR, Suo5v2Interceptor.class)
.addShellClass(SPRING_WEBMVC_JAKARTA_INTERCEPTOR, Suo5v2Interceptor.class)
.addShellClass(SPRING_WEBMVC_CONTROLLER_HANDLER, Suo5v2ControllerHandler.class)
.addShellClass(SPRING_WEBMVC_JAKARTA_CONTROLLER_HANDLER, Suo5v2ControllerHandler.class)
.addShellClass(SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET, Suo5v2.class)
.addShellClass(AGENT_FILTER_CHAIN, Suo5v2.class)
.addShellClass(CATALINA_AGENT_CONTEXT_VALVE, Suo5v2.class)
.addShellClass(JETTY_AGENT_HANDLER, Suo5v2JettyHandler.class)
.addShellClass(UNDERTOW_AGENT_SERVLET_HANDLER, Suo5v2UndertowServletHandler.class)
.addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT, Suo5v2.class)
.addShellClass(WAS_AGENT_FILTER_MANAGER, Suo5v2.class)
.addShellClass(ACTION, Suo5v2Struct2Action.class)
.build());
addToolMapping(ShellTool.NeoreGeorg, ToolMapping.builder() addToolMapping(ShellTool.NeoreGeorg, ToolMapping.builder()
.addShellClass(SERVLET, NeoreGeorgServlet.class) .addShellClass(SERVLET, NeoreGeorgServlet.class)
.addShellClass(JAKARTA_SERVLET, NeoreGeorgServlet.class) .addShellClass(JAKARTA_SERVLET, NeoreGeorgServlet.class)
@@ -9,6 +9,7 @@ public class ShellTool {
public static final String Behinder = "Behinder"; public static final String Behinder = "Behinder";
public static final String Command = "Command"; public static final String Command = "Command";
public static final String Suo5 = "Suo5"; public static final String Suo5 = "Suo5";
public static final String Suo5v2 = "Suo5v2";
public static final String AntSword = "AntSword"; public static final String AntSword = "AntSword";
public static final String NeoreGeorg = "NeoreGeorg"; public static final String NeoreGeorg = "NeoreGeorg";
public static final String Custom = "Custom"; public static final String Custom = "Custom";
@@ -23,6 +23,7 @@ public class ShellToolFactory {
register(ShellTool.Behinder, BehinderGenerator.class, BehinderConfig.class); register(ShellTool.Behinder, BehinderGenerator.class, BehinderConfig.class);
register(ShellTool.Command, CommandGenerator.class, CommandConfig.class); register(ShellTool.Command, CommandGenerator.class, CommandConfig.class);
register(ShellTool.Suo5, Suo5Generator.class, Suo5Config.class); register(ShellTool.Suo5, Suo5Generator.class, Suo5Config.class);
register(ShellTool.Suo5v2, Suo5Generator.class, Suo5Config.class);
register(ShellTool.AntSword, AntSwordGenerator.class, AntSwordConfig.class); register(ShellTool.AntSword, AntSwordGenerator.class, AntSwordConfig.class);
register(ShellTool.NeoreGeorg, NeoreGeorgGenerator.class, NeoreGeorgConfig.class); register(ShellTool.NeoreGeorg, NeoreGeorgGenerator.class, NeoreGeorgConfig.class);
register(ShellTool.Custom, CustomShellGenerator.class, CustomConfig.class); register(ShellTool.Custom, CustomShellGenerator.class, CustomConfig.class);
@@ -233,7 +233,8 @@ public class ShellAssertion {
behinderIsOk(shellUrl, ((BehinderConfig) generateResult.getShellToolConfig())); behinderIsOk(shellUrl, ((BehinderConfig) generateResult.getShellToolConfig()));
break; break;
case Suo5: case Suo5:
suo5IsOk(shellUrl, ((Suo5Config) generateResult.getShellToolConfig())); case Suo5v2:
suo5IsOk(shellTool, shellUrl, ((Suo5Config) generateResult.getShellToolConfig()));
break; break;
case AntSword: case AntSword:
antSwordIsOk(shellUrl, ((AntSwordConfig) generateResult.getShellToolConfig())); antSwordIsOk(shellUrl, ((AntSwordConfig) generateResult.getShellToolConfig()));
@@ -300,8 +301,8 @@ public class ShellAssertion {
assertTrue(behinderManager.test()); assertTrue(behinderManager.test());
} }
public static void suo5IsOk(String entrypoint, Suo5Config shellConfig) { public static void suo5IsOk(String shellTool, String entrypoint, Suo5Config shellConfig) {
assertTrue(Suo5Manager.test(entrypoint, shellConfig.getHeaderValue())); assertTrue(Suo5Manager.test(shellTool, entrypoint, shellConfig.getHeaderValue()));
} }
public static void antSwordIsOk(String entrypoint, AntSwordConfig shellConfig) { public static void antSwordIsOk(String entrypoint, AntSwordConfig shellConfig) {
@@ -342,6 +343,7 @@ public class ShellAssertion {
log.info("generated {} behinder with pass: {}, User-Agent: {}", shellType, behinderPass, uniqueName); log.info("generated {} behinder with pass: {}, User-Agent: {}", shellType, behinderPass, uniqueName);
break; break;
case Suo5: case Suo5:
case Suo5v2:
shellToolConfig = Suo5Config.builder() shellToolConfig = Suo5Config.builder()
.headerName("User-Agent") .headerName("User-Agent")
.headerValue(uniqueName) .headerValue(uniqueName)
@@ -3,10 +3,12 @@ package com.reajason.javaweb.integration.memshell.glassfish;
import com.reajason.javaweb.Server; import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.ShellAssertion; import com.reajason.javaweb.integration.ShellAssertion;
import com.reajason.javaweb.integration.TestCasesProvider; import com.reajason.javaweb.integration.TestCasesProvider;
import com.reajason.javaweb.memshell.ShellTool;
import com.reajason.javaweb.memshell.ShellType; import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.packer.Packers; import com.reajason.javaweb.packer.Packers;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.jar.asm.Opcodes; import net.bytebuddy.jar.asm.Opcodes;
import org.apache.commons.lang3.tuple.Triple;
import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.ParameterizedTest;
@@ -49,12 +51,12 @@ public class GlassFish3ContainerTest {
.withCopyToContainer(glassfishPid, "/fetch_pid.sh") .withCopyToContainer(glassfishPid, "/fetch_pid.sh")
.withNetwork(network) .withNetwork(network)
.withNetworkAliases("app") .withNetworkAliases("app")
.waitingFor(Wait.forHttp("/app")) .waitingFor(Wait.forLogMessage(".*(deployed|done).*", 1))
.withExposedPorts(8080); .withExposedPorts(8080);
@BeforeAll @BeforeAll
static void setup() { static void setup() {
container.waitingFor(Wait.forLogMessage(".*(deployed|done).*", 1)); container.waitingFor(Wait.forHttp("/app"));
} }
static Stream<Arguments> casesProvider() { static Stream<Arguments> casesProvider() {
@@ -67,7 +69,11 @@ public class GlassFish3ContainerTest {
ShellType.CATALINA_AGENT_CONTEXT_VALVE ShellType.CATALINA_AGENT_CONTEXT_VALVE
); );
List<Packers> testPackers = List.of(Packers.JSP); List<Packers> testPackers = List.of(Packers.JSP);
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers); List<Triple<String, String, Packers>> unSupportedCases = List.of(
Triple.of(ShellType.AGENT_FILTER_CHAIN, ShellTool.Suo5v2, Packers.AgentJar), // request.inputStream is empty
Triple.of(ShellType.CATALINA_AGENT_CONTEXT_VALVE, ShellTool.Suo5v2, Packers.AgentJar) // request.inputStream is empty
);
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers, unSupportedCases);
} }
@AfterAll @AfterAll
@@ -48,7 +48,7 @@ public class Payara5201ContainerTest {
.withCopyToContainer(glassfishPid, "/fetch_pid.sh") .withCopyToContainer(glassfishPid, "/fetch_pid.sh")
.withNetwork(network) .withNetwork(network)
.withNetworkAliases("app") .withNetworkAliases("app")
.waitingFor(Wait.forHttp("/app")) .waitingFor(Wait.forLogMessage(".*JMXService.*", 1))
.withExposedPorts(8080); .withExposedPorts(8080);
static Stream<Arguments> casesProvider() { static Stream<Arguments> casesProvider() {
@@ -66,7 +66,7 @@ public class Payara5201ContainerTest {
@BeforeAll @BeforeAll
static void setup() { static void setup() {
container.waitingFor(Wait.forLogMessage(".*JMXService.*", 1)); container.waitingFor(Wait.forHttp("/app"));
} }
@AfterAll @AfterAll
@@ -48,7 +48,7 @@ public class Payara520225ContainerTest {
.withCopyToContainer(glassfishPid, "/fetch_pid.sh") .withCopyToContainer(glassfishPid, "/fetch_pid.sh")
.withNetwork(network) .withNetwork(network)
.withNetworkAliases("app") .withNetworkAliases("app")
.waitingFor(Wait.forHttp("/app")) .waitingFor(Wait.forLogMessage(".*JMXService.*", 1))
.withExposedPorts(8080); .withExposedPorts(8080);
static Stream<Arguments> casesProvider() { static Stream<Arguments> casesProvider() {
@@ -66,7 +66,7 @@ public class Payara520225ContainerTest {
@BeforeAll @BeforeAll
static void setup() { static void setup() {
container.waitingFor(Wait.forLogMessage(".*JMXService.*", 1)); container.waitingFor(Wait.forHttp("/app"));
} }
@AfterAll @AfterAll
@@ -39,7 +39,7 @@ import static org.hamcrest.MatcherAssert.assertThat;
@Slf4j @Slf4j
@Testcontainers @Testcontainers
public class Wildfly9ContainerTest { public class Wildfly9ContainerTest {
public static final String imageName = "jboss/wildfly:10.0.0.Final"; public static final String imageName = "jboss/wildfly:9.0.1.Final";
static Network network = Network.newNetwork(); static Network network = Network.newNetwork();
@Container @Container
public final static GenericContainer<?> python = new GenericContainer<>(new ImageFromDockerfile() public final static GenericContainer<?> python = new GenericContainer<>(new ImageFromDockerfile()
@@ -30,7 +30,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
@Slf4j @Slf4j
@Testcontainers @Testcontainers
public class Wildfly9ContainerTest { public class Wildfly9ContainerTest {
public static final String imageName = "jboss/wildfly:10.0.0.Final"; public static final String imageName = "jboss/wildfly:9.0.1.Final";
@Container @Container
public static final GenericContainer<?> container = new GenericContainer<>(imageName) public static final GenericContainer<?> container = new GenericContainer<>(imageName)
.withCopyToContainer(warFile, "/opt/jboss/wildfly/standalone/deployments/app.war") .withCopyToContainer(warFile, "/opt/jboss/wildfly/standalone/deployments/app.war")
@@ -1,7 +1,5 @@
package com.reajason.javaweb.suo5; package com.reajason.javaweb.suo5;
import org.apache.commons.lang3.StringUtils;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.nio.file.Path; import java.nio.file.Path;
@@ -15,6 +13,7 @@ import java.util.concurrent.*;
public class Suo5Manager { public class Suo5Manager {
public static final String suo5Command; public static final String suo5Command;
public static final String suo5v2Command;
static { static {
String os = System.getProperty("os.name").toLowerCase(); String os = System.getProperty("os.name").toLowerCase();
@@ -29,17 +28,19 @@ public class Suo5Manager {
pwd = pwd.getParent(); pwd = pwd.getParent();
} }
suo5Command = pwd.resolve(Paths.get("asserts", "suo5", "suo5-" + osType + "-" + osArch)).toAbsolutePath().toString(); suo5Command = pwd.resolve(Paths.get("asserts", "suo5", "suo5-" + osType + "-" + osArch)).toAbsolutePath().toString();
suo5v2Command = pwd.resolve(Paths.get("asserts", "suo5", "suo5v2-" + osType + "-" + osArch)).toAbsolutePath().toString();
} }
public static void main(String[] args) { public static void main(String[] args) {
System.out.println(suo5Command); System.out.println(suo5Command);
boolean test = test("http://localhost:8082/app/test", "test"); boolean test = test("", "http://localhost:8082/app/test", "test");
System.out.println(test); System.out.println(test);
} }
public static boolean test(String targetUrl, String ua) { public static boolean test(String shellTool, String targetUrl, String ua) {
String command = shellTool.endsWith("v2") ? suo5v2Command : suo5Command;
ProcessBuilder processBuilder = new ProcessBuilder( ProcessBuilder processBuilder = new ProcessBuilder(
suo5Command, "-debug", "-t", targetUrl, "--timeout", "5", "-ua", ua, "-H", "Referer: " + targetUrl command, "-debug", "-t", targetUrl, "--timeout", "8", "-ua", ua, "-H", "Referer: " + targetUrl
); );
processBuilder.redirectErrorStream(true); processBuilder.redirectErrorStream(true);
ExecutorService executor = Executors.newSingleThreadExecutor(); ExecutorService executor = Executors.newSingleThreadExecutor();
@@ -53,6 +53,7 @@ const shellToolIcons: Record<ShellToolType, JSX.Element> = {
[ShellToolType.Command]: <CommandIcon className="h-4 w-4" />, [ShellToolType.Command]: <CommandIcon className="h-4 w-4" />,
[ShellToolType.AntSword]: <SwordIcon className="h-4 w-4" />, [ShellToolType.AntSword]: <SwordIcon className="h-4 w-4" />,
[ShellToolType.Suo5]: <WaypointsIcon className="h-4 w-4" />, [ShellToolType.Suo5]: <WaypointsIcon className="h-4 w-4" />,
[ShellToolType.Suo5v2]: <WaypointsIcon className="h-4 w-4" />,
[ShellToolType.NeoreGeorg]: <NetworkIcon className="h-4 w-4" />, [ShellToolType.NeoreGeorg]: <NetworkIcon className="h-4 w-4" />,
[ShellToolType.Custom]: <ZapIcon className="h-4 w-4" />, [ShellToolType.Custom]: <ZapIcon className="h-4 w-4" />,
}; };
@@ -467,7 +468,8 @@ export default function MainConfigCard({
<CommandTabContent form={form} shellTypes={shellTypes} /> <CommandTabContent form={form} shellTypes={shellTypes} />
<BehinderTabContent form={form} shellTypes={shellTypes} /> <BehinderTabContent form={form} shellTypes={shellTypes} />
<AntSwordTabContent form={form} shellTypes={shellTypes} /> <AntSwordTabContent form={form} shellTypes={shellTypes} />
<Suo5TabContent form={form} shellTypes={shellTypes} /> <Suo5TabContent tabValue="Suo5" form={form} shellTypes={shellTypes} />
<Suo5TabContent tabValue="Suo5v2" form={form} shellTypes={shellTypes} />
<NeoRegTabContent form={form} shellTypes={shellTypes} /> <NeoRegTabContent form={form} shellTypes={shellTypes} />
<CustomTabContent form={form} shellTypes={shellTypes} /> <CustomTabContent form={form} shellTypes={shellTypes} />
</Tabs> </Tabs>
@@ -133,7 +133,8 @@ export function BasicInfo({
} }
/> />
)} )}
{generateResult?.shellConfig.shellTool === ShellToolType.Suo5 && ( {(generateResult?.shellConfig.shellTool === ShellToolType.Suo5 ||
generateResult?.shellConfig.shellTool === ShellToolType.Suo5v2) && (
<CopyableField <CopyableField
label={t("shellToolConfig.suo5Header")} label={t("shellToolConfig.suo5Header")}
text={`${(generateResult?.shellToolConfig as Suo5ShellToolConfig).headerName}: ${(generateResult?.shellToolConfig as Suo5ShellToolConfig).headerValue}`} text={`${(generateResult?.shellToolConfig as Suo5ShellToolConfig).headerName}: ${(generateResult?.shellToolConfig as Suo5ShellToolConfig).headerValue}`}
@@ -12,14 +12,16 @@ import { UrlPatternFormField } from "./urlpattern-field";
export function Suo5TabContent({ export function Suo5TabContent({
form, form,
shellTypes, shellTypes,
tabValue,
}: Readonly<{ }: Readonly<{
form: UseFormReturn<MemShellFormSchema>; form: UseFormReturn<MemShellFormSchema>;
shellTypes: Array<string>; shellTypes: Array<string>;
tabValue: string;
}>) { }>) {
const { t } = useTranslation(["memshell", "common"]); const { t } = useTranslation(["memshell", "common"]);
return ( return (
<FormProvider {...form}> <FormProvider {...form}>
<TabsContent value="Suo5"> <TabsContent value={tabValue}>
<Card> <Card>
<CardContent className="space-y-2 mt-4"> <CardContent className="space-y-2 mt-4">
<div className="grid grid-cols-1 md:grid-cols-2 gap-2"> <div className="grid grid-cols-1 md:grid-cols-2 gap-2">
+1
View File
@@ -132,6 +132,7 @@ export enum ShellToolType {
Command = "Command", Command = "Command",
AntSword = "AntSword", AntSword = "AntSword",
Suo5 = "Suo5", Suo5 = "Suo5",
Suo5v2 = "Suo5v2",
NeoreGeorg = "NeoreGeorg", NeoreGeorg = "NeoreGeorg",
Custom = "Custom", Custom = "Custom",
} }
+5 -3
View File
@@ -489,7 +489,7 @@
"@types/ms": ["@types/[email protected]", "", {}, "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA=="], "@types/ms": ["@types/[email protected]", "", {}, "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA=="],
"@types/node": ["@types/[email protected].1", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ=="], "@types/node": ["@types/[email protected].2", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-WOhQTZ4G8xZ1tjJTvKOpyEVSGgOTvJAfDK3FNFgELyaTpzhdgHVHeqW8V+UJvzF5BT+/B54T/1S2K6gd9c7bbA=="],
"@types/parse-json": ["@types/[email protected]", "", {}, "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw=="], "@types/parse-json": ["@types/[email protected]", "", {}, "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw=="],
@@ -773,7 +773,7 @@
"human-signals": ["[email protected]", "", {}, "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw=="], "human-signals": ["[email protected]", "", {}, "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw=="],
"i18next": ["[email protected].1", "", { "dependencies": { "@babel/runtime": "^7.28.4" }, "peerDependencies": { "typescript": "^5" }, "optionalPeers": ["typescript"] }, "sha512-XbTnkh1yCZWSAZGnA9xcQfHcYNgZs2cNxm+c6v1Ma9UAUGCeJPplRe1ILia6xnDvXBjk0uXU+Z8FYWhA19SKFw=="], "i18next": ["[email protected].2", "", { "dependencies": { "@babel/runtime": "^7.28.4" }, "peerDependencies": { "typescript": "^5" }, "optionalPeers": ["typescript"] }, "sha512-58b4kmLpLv1buWUEwegMDUqZVR5J+rT+WTRFaBGL7lxDuJQQ0NrJFrq+eT2N94aYVR1k1Sr13QITNOL88tZCuw=="],
"image-size": ["[email protected]", "", { "bin": { "image-size": "bin/image-size.js" } }, "sha512-IRqXKlaXwgSMAMtpNzZa1ZAe8m+Sa1770Dhk8VkSsP9LS+iHD62Zd8FQKs8fbPiagBE7BzoFX23cxFnwshpV6w=="], "image-size": ["[email protected]", "", { "bin": { "image-size": "bin/image-size.js" } }, "sha512-IRqXKlaXwgSMAMtpNzZa1ZAe8m+Sa1770Dhk8VkSsP9LS+iHD62Zd8FQKs8fbPiagBE7BzoFX23cxFnwshpV6w=="],
@@ -1281,7 +1281,7 @@
"vfile-message": ["[email protected]", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-stringify-position": "^4.0.0" } }, "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw=="], "vfile-message": ["[email protected]", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-stringify-position": "^4.0.0" } }, "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw=="],
"vite": ["[email protected].6", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-tI2l/nFHC5rLh7+5+o7QjKjSR04ivXDF4jcgV0f/bTQ+OJiITy5S6gaynVsEM+7RqzufMnVbIon6Sr5x1SDYaQ=="], "vite": ["[email protected].7", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-ITcnkFeR3+fI8P1wMgItjGrR10170d8auB4EpMLPqmx6uxElH3a/hHGQabSHKdqd4FXWO1nFIp9rRn7JQ34ACQ=="],
"vite-node": ["[email protected]", "", { "dependencies": { "cac": "^6.7.14", "debug": "^4.4.1", "es-module-lexer": "^1.7.0", "pathe": "^2.0.3", "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" }, "bin": { "vite-node": "vite-node.mjs" } }, "sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg=="], "vite-node": ["[email protected]", "", { "dependencies": { "cac": "^6.7.14", "debug": "^4.4.1", "es-module-lexer": "^1.7.0", "pathe": "^2.0.3", "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" }, "bin": { "vite-node": "vite-node.mjs" } }, "sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg=="],
@@ -1381,6 +1381,8 @@
"vite-node/pathe": ["[email protected]", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], "vite-node/pathe": ["[email protected]", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="],
"vite-node/vite": ["[email protected]", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-tI2l/nFHC5rLh7+5+o7QjKjSR04ivXDF4jcgV0f/bTQ+OJiITy5S6gaynVsEM+7RqzufMnVbIon6Sr5x1SDYaQ=="],
"ansi-align/string-width/emoji-regex": ["[email protected]", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], "ansi-align/string-width/emoji-regex": ["[email protected]", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
"ansi-align/string-width/strip-ansi": ["[email protected]", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], "ansi-align/string-width/strip-ansi": ["[email protected]", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
+2 -2
View File
@@ -1,3 +1,3 @@
{ {
"title": "常见 Java 内存马" "title": "常见 Java 内存马"
} }
+3 -3
View File
@@ -24,7 +24,7 @@
"fumadocs-core": "16.2.3", "fumadocs-core": "16.2.3",
"fumadocs-mdx": "14.1.0", "fumadocs-mdx": "14.1.0",
"fumadocs-ui": "16.2.3", "fumadocs-ui": "16.2.3",
"i18next": "^25.7.1", "i18next": "^25.7.2",
"isbot": "^5.1.32", "isbot": "^5.1.32",
"lucide-react": "^0.556.0", "lucide-react": "^0.556.0",
"motion": "^12.23.25", "motion": "^12.23.25",
@@ -45,7 +45,7 @@
"@react-router/dev": "^7.10.1", "@react-router/dev": "^7.10.1",
"@tailwindcss/vite": "^4.1.17", "@tailwindcss/vite": "^4.1.17",
"@types/mdx": "^2.0.13", "@types/mdx": "^2.0.13",
"@types/node": "^24.10.1", "@types/node": "^24.10.2",
"@types/react": "^19.2.7", "@types/react": "^19.2.7",
"@types/react-copy-to-clipboard": "^5.0.7", "@types/react-copy-to-clipboard": "^5.0.7",
"@types/react-dom": "^19.2.3", "@types/react-dom": "^19.2.3",
@@ -55,7 +55,7 @@
"serve": "^14.2.5", "serve": "^14.2.5",
"tailwindcss": "^4.1.17", "tailwindcss": "^4.1.17",
"typescript": "^5.9.3", "typescript": "^5.9.3",
"vite": "^7.2.6", "vite": "^7.2.7",
"vite-plugin-devtools-json": "^1.0.0", "vite-plugin-devtools-json": "^1.0.0",
"vite-tsconfig-paths": "^5.1.4" "vite-tsconfig-paths": "^5.1.4"
} }
+5 -5
View File
@@ -8,7 +8,7 @@ import tsconfigPaths from "vite-tsconfig-paths";
import * as MdxConfig from "./source.config"; import * as MdxConfig from "./source.config";
export default defineConfig({ export default defineConfig({
base: env.NODE_ENV === "development" ? '/' : `${env.VITE_APP_API_URL}/`, base: env.NODE_ENV === "development" ? "/" : `${env.VITE_APP_API_URL}/`,
plugins: [ plugins: [
mdx(MdxConfig), mdx(MdxConfig),
tailwindcss(), tailwindcss(),
@@ -19,11 +19,11 @@ export default defineConfig({
}), }),
], ],
resolve: resolve:
process.env.NODE_ENV === 'development' process.env.NODE_ENV === "development"
? {} ? {}
: { : {
alias: { alias: {
'react-dom/server': 'react-dom/server.node', "react-dom/server": "react-dom/server.node",
},
}, },
},
}); });