diff --git a/addOns/kotlin/CHANGELOG.md b/addOns/kotlin/CHANGELOG.md index 27e2f3386dc..71106474244 100644 --- a/addOns/kotlin/CHANGELOG.md +++ b/addOns/kotlin/CHANGELOG.md @@ -3,6 +3,6 @@ All notable changes to this add-on will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). -## Alpha +## Unreleased - Kotlin scripting for the JVM \ No newline at end of file diff --git a/addOns/kotlin/kotlin.gradle.kts b/addOns/kotlin/kotlin.gradle.kts index 0ec92e6a741..7174dc4dd89 100644 --- a/addOns/kotlin/kotlin.gradle.kts +++ b/addOns/kotlin/kotlin.gradle.kts @@ -4,11 +4,11 @@ plugins { kotlin("jvm") version "1.3.50" } -version = "1" -description = "Allows Kotlin to be used for ZAP scripting - templates included" +version = "1.0.0" +description = "Allows Kotlin to be used for ZAP scripting - (some) templates included" zapAddOn { - addOnName.set("Kotlin Scripting") + addOnName.set("Kotlin Support") addOnStatus.set(AddOnStatus.ALPHA) zapVersion.set("2.9.0") diff --git a/addOns/kotlin/src/main/java/org/zaproxy/zap/extension/kotlin/ExtensionKotlin.java b/addOns/kotlin/src/main/java/org/zaproxy/zap/extension/kotlin/ExtensionKotlin.java new file mode 100644 index 00000000000..e7167958511 --- /dev/null +++ b/addOns/kotlin/src/main/java/org/zaproxy/zap/extension/kotlin/ExtensionKotlin.java @@ -0,0 +1,86 @@ +/* + * Zed Attack Proxy (ZAP) and its related class files. + * + * ZAP is an HTTP/HTTPS proxy for assessing web application security. + * + * Copyright 2020 The ZAP Development Team + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.zaproxy.zap.extension.kotlin; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import javax.swing.*; +import org.apache.log4j.Logger; +import org.parosproxy.paros.control.Control; +import org.parosproxy.paros.extension.Extension; +import org.parosproxy.paros.extension.ExtensionAdaptor; +import org.parosproxy.paros.extension.ExtensionHook; +import org.parosproxy.paros.view.View; +import org.zaproxy.zap.ZAP; +import org.zaproxy.zap.control.AddOnLoader; +import org.zaproxy.zap.control.ExtensionFactory; +import org.zaproxy.zap.extension.script.ExtensionScript; + +public class ExtensionKotlin extends ExtensionAdaptor { + + public static final String NAME = "ExtensionKotlin"; + public static final int EXTENSION_ORDER = 9999; + public static final ImageIcon KOTLIN_ICON; + private static final List> EXTENSION_DEPENDENCIES; + private static final Logger LOGGER = Logger.getLogger(ExtensionKotlin.class); + + static { + List> dependencies = new ArrayList<>(1); + dependencies.add(ExtensionScript.class); + EXTENSION_DEPENDENCIES = Collections.unmodifiableList(dependencies); + + KOTLIN_ICON = + View.isInitialised() + ? new ImageIcon( + ExtensionKotlin.class.getResource( + "/org/zaproxy/zap/extension/kotlin/resources/kotlin.png")) + : null; + } + + public ExtensionKotlin() { + super(NAME); + setOrder(EXTENSION_ORDER); + } + + @Override + public void hook(ExtensionHook extensionHook) { + super.hook(extensionHook); + + LOGGER.debug("Hooking Kotlin Scripting Extension"); + String zapJar = ZAP.class.getProtectionDomain().getCodeSource().getLocation().getFile(); + + LOGGER.debug("Loading Kotlin engine..."); + AddOnLoader addonLoader = ExtensionFactory.getAddOnLoader(); + Arrays.stream(addonLoader.getURLs()).forEach(LOGGER::debug); + KotlinScriptEngineFactory factory = new KotlinScriptEngineFactory(addonLoader, zapJar); + getExtScript().registerScriptEngineWrapper(new KotlinEngineWrapper(factory)); + LOGGER.debug("Kotlin engine loaded."); + } + + public List> getDependencies() { + return EXTENSION_DEPENDENCIES; + } + + private ExtensionScript getExtScript() { + return Control.getSingleton().getExtensionLoader().getExtension(ExtensionScript.class); + } +} diff --git a/addOns/kotlin/src/main/java/org/zaproxy/zap/extension/kotlin/KotlinEngineWrapper.java b/addOns/kotlin/src/main/java/org/zaproxy/zap/extension/kotlin/KotlinEngineWrapper.java new file mode 100644 index 00000000000..8df0201ff26 --- /dev/null +++ b/addOns/kotlin/src/main/java/org/zaproxy/zap/extension/kotlin/KotlinEngineWrapper.java @@ -0,0 +1,54 @@ +/* + * Zed Attack Proxy (ZAP) and its related class files. + * + * ZAP is an HTTP/HTTPS proxy for assessing web application security. + * + * Copyright 2020 The ZAP Development Team + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.zaproxy.zap.extension.kotlin; + +import java.util.Collections; +import java.util.List; +import javax.script.ScriptEngineFactory; +import javax.swing.*; +import org.fife.ui.rsyntaxtextarea.SyntaxConstants; +import org.zaproxy.zap.extension.script.DefaultEngineWrapper; + +public class KotlinEngineWrapper extends DefaultEngineWrapper { + + @Override + public ImageIcon getIcon() { + return ExtensionKotlin.KOTLIN_ICON; + } + + @Override + public String getSyntaxStyle() { + return SyntaxConstants.SYNTAX_STYLE_NONE; + } + + @Override + public boolean isRawEngine() { + return false; + } + + @Override + public List getExtensions() { + return Collections.singletonList("kts"); + } + + public KotlinEngineWrapper(ScriptEngineFactory factory) { + super(factory); + } +} diff --git a/addOns/kotlin/src/main/java/org/zaproxy/zap/extension/kotlin/KotlinScriptEngineFactory.java b/addOns/kotlin/src/main/java/org/zaproxy/zap/extension/kotlin/KotlinScriptEngineFactory.java new file mode 100644 index 00000000000..1bab7f3f01c --- /dev/null +++ b/addOns/kotlin/src/main/java/org/zaproxy/zap/extension/kotlin/KotlinScriptEngineFactory.java @@ -0,0 +1,61 @@ +/* + * Zed Attack Proxy (ZAP) and its related class files. + * + * ZAP is an HTTP/HTTPS proxy for assessing web application security. + * + * Copyright 2020 The ZAP Development Team + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.zaproxy.zap.extension.kotlin; + +import java.io.File; +import java.util.List; +import javax.script.Bindings; +import javax.script.ScriptContext; +import javax.script.ScriptEngine; +import kotlin.jvm.JvmClassMappingKt; +import kotlin.reflect.KClass; +import kotlin.script.experimental.jvm.util.JvmClasspathUtilKt; +import org.jetbrains.kotlin.cli.common.repl.KotlinJsr223JvmScriptEngineFactoryBase; +import org.jetbrains.kotlin.cli.common.repl.ScriptArgsWithTypes; +import org.jetbrains.kotlin.script.jsr223.KotlinJsr223JvmLocalScriptEngine; +import org.jetbrains.kotlin.script.jsr223.KotlinStandardJsr223ScriptTemplate; + +public class KotlinScriptEngineFactory extends KotlinJsr223JvmScriptEngineFactoryBase { + + private final List jars; + + public KotlinScriptEngineFactory(ClassLoader classLoader, String zapJar) { + List clJars = + JvmClasspathUtilKt.scriptCompilationClasspathFromContextOrStdlib( + new String[] {"kotlin-stdlib"}, classLoader, true); + if (zapJar != null) { + clJars.add(new File(zapJar)); + } + jars = clJars; + } + + @Override + public ScriptEngine getScriptEngine() { + return new KotlinJsr223JvmLocalScriptEngine( + this, + jars, + KotlinStandardJsr223ScriptTemplate.class.getName(), + (ctx, types) -> + new ScriptArgsWithTypes( + new Bindings[] {ctx.getBindings(ScriptContext.ENGINE_SCOPE)}, + types), + new KClass[] {JvmClassMappingKt.getKotlinClass(Bindings.class)}); + } +} diff --git a/addOns/kotlin/src/main/kotlin/org/zaproxy/zap/extension/kotlin/ExtensionKotlin.kt b/addOns/kotlin/src/main/kotlin/org/zaproxy/zap/extension/kotlin/ExtensionKotlin.kt deleted file mode 100644 index 5b00f505614..00000000000 --- a/addOns/kotlin/src/main/kotlin/org/zaproxy/zap/extension/kotlin/ExtensionKotlin.kt +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Zed Attack Proxy (ZAP) and its related class files. - * - * ZAP is an HTTP/HTTPS proxy for assessing web application security. - * - * Copyright 2020 The ZAP Development Team - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.zaproxy.zap.extension.kotlin - -import org.apache.log4j.Logger -import org.parosproxy.paros.control.Control -import org.parosproxy.paros.extension.Extension -import org.parosproxy.paros.extension.ExtensionAdaptor -import org.parosproxy.paros.extension.ExtensionHook -import org.parosproxy.paros.view.View -import org.zaproxy.zap.ZAP -import org.zaproxy.zap.control.ExtensionFactory -import org.zaproxy.zap.extension.script.ExtensionScript -import javax.swing.ImageIcon - -class ExtensionKotlin : ExtensionAdaptor(NAME) { - - - companion object { - val NAME = "ExtensionKotlin" - val TEAM_NAME = "StackHawk Engineering" - val KOTLIN_ICON: ImageIcon? = if (View.isInitialised()) ImageIcon( - ExtensionKotlin::class.java.getResource( - "/org/zaproxy/zap/extension/kotlin/resources/kotlin.png")) else null - - val EXTENSION_DEPENDENCIES: List> = listOf(ExtensionScript::class.java) - private val LOGGER: Logger = Logger.getLogger(ExtensionKotlin::class.java) - } - - init { - order = 9999 - - } - - override fun hook(extensionHook: ExtensionHook?) { - super.hook(extensionHook) - - LOGGER.info("Hooking Kotlin Scripting Extension") - - val zapJar = ZAP::class.java.protectionDomain.codeSource.location.file - - LOGGER.info("Loading Kotlin engine...") - val cl = ExtensionFactory.getAddOnLoader() - cl.urLs.forEach { LOGGER.info(it) } - extScript - .registerScriptEngineWrapper( - KotlinEngineWrapper(KotlinScriptEngineFactory(cl, zapJar.toString()))) - LOGGER.info("Kotlin engine loaded.") - - } - - private val extScript: ExtensionScript by lazy { - Control.getSingleton() - .extensionLoader - .getExtension(ExtensionScript.NAME) as ExtensionScript - } - -} \ No newline at end of file diff --git a/addOns/kotlin/src/main/kotlin/org/zaproxy/zap/extension/kotlin/KotlinEngineWrapper.kt b/addOns/kotlin/src/main/kotlin/org/zaproxy/zap/extension/kotlin/KotlinEngineWrapper.kt deleted file mode 100644 index d1128e7eed9..00000000000 --- a/addOns/kotlin/src/main/kotlin/org/zaproxy/zap/extension/kotlin/KotlinEngineWrapper.kt +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Zed Attack Proxy (ZAP) and its related class files. - * - * ZAP is an HTTP/HTTPS proxy for assessing web application security. - * - * Copyright 2020 The ZAP Development Team - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.zaproxy.zap.extension.kotlin - -import org.fife.ui.rsyntaxtextarea.SyntaxConstants -import org.parosproxy.paros.Constant -import org.parosproxy.paros.extension.Extension -import org.zaproxy.zap.extension.script.DefaultEngineWrapper -import javax.script.ScriptEngine -import javax.script.ScriptEngineFactory -import javax.swing.ImageIcon - -class KotlinEngineWrapper(scriptEngineFactory: ScriptEngineFactory): DefaultEngineWrapper(scriptEngineFactory) { - - override fun getExtensions(): MutableList { - return mutableListOf("kts") - } - - override fun getIcon(): ImageIcon? { - return ExtensionKotlin.KOTLIN_ICON - } - - override fun getEngine(): ScriptEngine { - return super.getEngine() - } - - override fun getSyntaxStyle(): String { - return SyntaxConstants.SYNTAX_STYLE_NONE - } - - fun getAuthor(): String { - return ExtensionKotlin.TEAM_NAME - } - - fun getDescription(): String { - return Constant.messages.getString("kotlin.desc") - } - - fun getDependencies(): List> { - return ExtensionKotlin.EXTENSION_DEPENDENCIES - } - - override fun isRawEngine(): Boolean { - return false - } -} \ No newline at end of file diff --git a/addOns/kotlin/src/main/kotlin/org/zaproxy/zap/extension/kotlin/KotlinScriptEngineFactory.kt b/addOns/kotlin/src/main/kotlin/org/zaproxy/zap/extension/kotlin/KotlinScriptEngineFactory.kt deleted file mode 100644 index e5ee130d713..00000000000 --- a/addOns/kotlin/src/main/kotlin/org/zaproxy/zap/extension/kotlin/KotlinScriptEngineFactory.kt +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Zed Attack Proxy (ZAP) and its related class files. - * - * ZAP is an HTTP/HTTPS proxy for assessing web application security. - * - * Copyright 2020 The ZAP Development Team - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.zaproxy.zap.extension.kotlin - -import org.jetbrains.kotlin.cli.common.repl.KotlinJsr223JvmScriptEngineFactoryBase -import org.jetbrains.kotlin.cli.common.repl.ScriptArgsWithTypes -import org.jetbrains.kotlin.script.jsr223.KotlinJsr223JvmLocalScriptEngine -import org.jetbrains.kotlin.script.jsr223.KotlinStandardJsr223ScriptTemplate -import java.io.File -import javax.script.Bindings -import javax.script.ScriptContext -import javax.script.ScriptEngine -import kotlin.script.experimental.jvm.util.scriptCompilationClasspathFromContextOrStdlib - -class KotlinScriptEngineFactory(private val classLoader: ClassLoader, - private val zapJar: String? = null) : KotlinJsr223JvmScriptEngineFactoryBase() { - override fun getScriptEngine(): ScriptEngine { - val clJars = scriptCompilationClasspathFromContextOrStdlib("kotlin-stdlib", - wholeClasspath = true, - classLoader = classLoader) - val jars = if (zapJar != null) { - clJars + File(zapJar) - } else { - clJars - } - return KotlinJsr223JvmLocalScriptEngine( - this, - jars, - KotlinStandardJsr223ScriptTemplate::class.qualifiedName!!, - { ctx, types -> - ScriptArgsWithTypes(arrayOf(ctx.getBindings(ScriptContext.ENGINE_SCOPE)), types ?: emptyArray()) - }, - arrayOf(Bindings::class) - ) - } - -} \ No newline at end of file diff --git a/addOns/kotlin/src/main/resources/org/zaproxy/zap/extension/kotlin/resources/Messages.properties b/addOns/kotlin/src/main/resources/org/zaproxy/zap/extension/kotlin/resources/Messages.properties index bc4aa83d580..a8e29939945 100644 --- a/addOns/kotlin/src/main/resources/org/zaproxy/zap/extension/kotlin/resources/Messages.properties +++ b/addOns/kotlin/src/main/resources/org/zaproxy/zap/extension/kotlin/resources/Messages.properties @@ -1,3 +1,2 @@ - -kotlin.desc = Allows Kotlin to be used for ZAP scripting -kotlin.options.title = Kotlin +kotlin.desc=Allows Kotlin to be used for ZAP scripting +kotlin.options.title=Kotlin diff --git a/addOns/kotlin/src/main/zapHomeFiles/scripts/templates/authentication/Authentication default template.kts b/addOns/kotlin/src/main/zapHomeFiles/scripts/templates/authentication/Authentication default template.kts index 06683ab8fd0..c477d00d648 100644 --- a/addOns/kotlin/src/main/zapHomeFiles/scripts/templates/authentication/Authentication default template.kts +++ b/addOns/kotlin/src/main/zapHomeFiles/scripts/templates/authentication/Authentication default template.kts @@ -1,4 +1,3 @@ - import org.apache.commons.httpclient.URI import org.parosproxy.paros.network.HttpHeader import org.parosproxy.paros.network.HttpMessage diff --git a/addOns/kotlin/src/main/zapHomeFiles/scripts/templates/standalone/Standalone default template.kts b/addOns/kotlin/src/main/zapHomeFiles/scripts/templates/standalone/Standalone default template.kts index dc1f17b031b..2763b05d35b 100644 --- a/addOns/kotlin/src/main/zapHomeFiles/scripts/templates/standalone/Standalone default template.kts +++ b/addOns/kotlin/src/main/zapHomeFiles/scripts/templates/standalone/Standalone default template.kts @@ -1,2 +1,3 @@ - println("KaaKaawwtlin!!") + + diff --git a/addOns/kotlin/src/test/java/org/zaproxy/zap/extension/kotlin/VerifyScriptTemplates.java b/addOns/kotlin/src/test/java/org/zaproxy/zap/extension/kotlin/VerifyScriptTemplates.java new file mode 100644 index 00000000000..e4a2bc25fb5 --- /dev/null +++ b/addOns/kotlin/src/test/java/org/zaproxy/zap/extension/kotlin/VerifyScriptTemplates.java @@ -0,0 +1,57 @@ +/* + * Zed Attack Proxy (ZAP) and its related class files. + * + * ZAP is an HTTP/HTTPS proxy for assessing web application security. + * + * Copyright 2020 The ZAP Development Team + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.zaproxy.zap.extension.kotlin; + +import java.io.Reader; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import javax.script.Compilable; +import javax.script.CompiledScript; +import org.junit.jupiter.api.BeforeAll; +import org.zaproxy.zap.testutils.AbstractVerifyScriptTemplates; + +/** Verifies that the Jython script templates are parsed without errors. */ +public class VerifyScriptTemplates extends AbstractVerifyScriptTemplates { + + private static Compilable se; + + @BeforeAll + public static void setUp() { + se = + (Compilable) + new KotlinScriptEngineFactory( + Thread.currentThread().getContextClassLoader(), null) + .getScriptEngine(); + } + + @Override + protected String getScriptExtension() { + return ".kts"; + } + + @Override + protected void parseTemplate(Path template) throws Exception { + try (Reader reader = Files.newBufferedReader(template, StandardCharsets.UTF_8)) { + CompiledScript cs = se.compile(reader); + cs.eval(); + } + } +} diff --git a/addOns/kotlin/src/test/kotlin/org/zaproxy/zap/extension/kotlin/KotlinScriptTest.kt b/addOns/kotlin/src/test/kotlin/org/zaproxy/zap/extension/kotlin/KotlinScriptTest.kt deleted file mode 100644 index 0530affd2d4..00000000000 --- a/addOns/kotlin/src/test/kotlin/org/zaproxy/zap/extension/kotlin/KotlinScriptTest.kt +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Zed Attack Proxy (ZAP) and its related class files. - * - * ZAP is an HTTP/HTTPS proxy for assessing web application security. - * - * Copyright 2020 The ZAP Development Team - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.zaproxy.zap.extension.kotlin - -import org.junit.jupiter.api.BeforeAll -import org.zaproxy.zap.testutils.AbstractVerifyScriptTemplates -import java.nio.charset.StandardCharsets -import java.nio.file.Files -import java.nio.file.Path -import javax.script.Compilable - -class KotlinScriptTest : AbstractVerifyScriptTemplates() { - - companion object { - lateinit var se: Compilable - @BeforeAll - @JvmStatic - fun setUp() { - se = KotlinScriptEngineFactory(Thread.currentThread().contextClassLoader).scriptEngine as Compilable - } - } - - override fun getScriptExtension(): String? { - return ".kts" - } - - override fun parseTemplate(template: Path?) { - val reader = Files.newBufferedReader(template, StandardCharsets.UTF_8) - val s = se.compile(reader) - s.eval() - } -} \ No newline at end of file