diff --git a/src/main/java/com/pycript/ui/ConfigTab.java b/src/main/java/com/pycript/ui/ConfigTab.java
index 6260eed..f42ff65 100644
--- a/src/main/java/com/pycript/ui/ConfigTab.java
+++ b/src/main/java/com/pycript/ui/ConfigTab.java
@@ -778,6 +778,26 @@ private JLayeredPane createAdditionalSettingsPane()
JButton selectLanguageButton = new JButton("Select Language Binary Path");
JButton clearLanguageButton = new JButton("Clear Language Selected");
+ selectLanguageButton.addActionListener(e -> {
+ JFileChooser fileChooser = new JFileChooser();
+ fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
+ fileChooser.setDialogTitle("Select Language Binary");
+ int userSelection = fileChooser.showDialog(null, "Select");
+ if (userSelection == JFileChooser.APPROVE_OPTION) {
+ File selectedFile = fileChooser.getSelectedFile();
+ if (selectedFile != null) {
+ String filePath = selectedFile.getAbsolutePath();
+ languageTextField.setText(filePath);
+ api.persistence().preferences().setString("pycript.language.path", filePath);
+ }
+ }
+ });
+
+ clearLanguageButton.addActionListener(e -> {
+ languageTextField.setText("");
+ api.persistence().preferences().setString("pycript.language.path", "");
+ });
+
JLabel methodLabel = new JLabel("Encryption Decryption Method");
methodLabel.setFont(new java.awt.Font("Segoe UI", java.awt.Font.BOLD, 12));
methodLabel.setForeground(new Color(0xFF, 0x66, 0x33));
diff --git a/src/main/java/com/pycript/ui/ResourceTab.java b/src/main/java/com/pycript/ui/ResourceTab.java
index a2d797b..90ffa3a 100644
--- a/src/main/java/com/pycript/ui/ResourceTab.java
+++ b/src/main/java/com/pycript/ui/ResourceTab.java
@@ -52,6 +52,35 @@ private String getHTMLContent()
Documentation for PyCript
+ Getting Started
+ Select Encryption and Decryption Files
+
+ - PyCript expects you to provide encryption and decryption files as per your application requirements
+ - You can write encryption/decryption code in any language: Bash, PowerShell, C, Python, JavaScript, etc.
+ - PyCript expects the code in a specific format. Get example scripts from PyCript Template Repository
+ - For custom code documentation, visit Writing Custom Scripts
+
+
+ Configure Language Binary
+
+ - For interpreted languages (Python, Node.js, Ruby, etc.), provide the interpreter path (e.g., C:\\python\\python.exe, /usr/bin/node)
+ - For compiled binaries (EXE, C, C#, Go, etc.), keep the language path empty
+ - For shell scripts (Bash, PowerShell), provide the shell path or keep empty if executable directly
+
+
+ Select Request/Response Type
+
+ - Complete Body: Use when your encryption/decryption script handles the full raw request body and headers. PyCript will not parse any parameters. Useful when the whole body is encrypted
+ - Parameter Value: Extension will handle parsing of parameters from the request body or URL and send only values to your script. Useful when only parameter values are encrypted (e.g., JSON body)
+ - Parameter Key and Value: Extension will handle parsing of parameters and send both keys and values to your script when both are encrypted in the request
+
+
+ Debug and Monitor
+
+ - Use the Log tab to see how the extension runs your encryption/decryption script
+ - View the command executed, script output, and any errors from your script
+
+
Articles
- Manipulating Encrypted Traffic using PyCript
diff --git a/src/main/java/com/pycript/websocket/WebSocketMessageEditor.java b/src/main/java/com/pycript/websocket/WebSocketMessageEditor.java
index b6fd6bf..990d16b 100644
--- a/src/main/java/com/pycript/websocket/WebSocketMessageEditor.java
+++ b/src/main/java/com/pycript/websocket/WebSocketMessageEditor.java
@@ -19,12 +19,14 @@ public class WebSocketMessageEditor implements ExtensionProvidedWebSocketMessage
{
private final RawEditor editor;
private final MontoyaApi api;
+ private final boolean isReadOnly;
public WebSocketMessageEditor(MontoyaApi api, EditorCreationContext creationContext)
{
this.api = api;
+ this.isReadOnly = creationContext.editorMode() == EditorMode.READ_ONLY;
- if (creationContext.editorMode() == EditorMode.READ_ONLY)
+ if (isReadOnly)
{
editor = api.userInterface().createRawEditor(EditorOptions.READ_ONLY);
}
@@ -58,14 +60,15 @@ public ByteArray getMessage() {
@Override
public void setMessage(WebSocketMessage message) {
- // Check if the WebSocket upgrade request is in scope
if (message.upgradeRequest() == null || !api.scope().isInScope(message.upgradeRequest().url())) {
editor.setEditable(false);
editor.setContents(ByteArray.byteArray(api.utilities().byteUtils().convertFromString("WebSocket is out of scope")));
return;
}
- editor.setEditable(true);
+ if (!isReadOnly) {
+ editor.setEditable(true);
+ }
if (!ConfigTab.webSocketEnabled || ConfigTab.webSocketDecryptionFile == null || ConfigTab.webSocketDecryptionFile.isBlank()) {
editor.setContents(message.payload());