User Guide

Scripter

Scripter is an extension that introduces scripting support to PETEP.

Scripting is based on GraalVM Polyglot. One of the greatest advantages is that you can use Java libraries in the code, so you can also use PETEP utils etc.

Since GraalVM 22.2, JavaScript is no longer installed by default, so you have to install it using the following command:

gu install js

For more information, see GraalVM 22.2 Release Notes

If you edit a File script, you have to reload the script in the PETEP UI.

All scripts are persisted in Groups. You have to define these groups and bind them with specific Scripter interceptors to make them work.

Be aware that scripts are potentially dangerous and can break PETEP (like extensions). Scripts should never register any listeners, receivers etc. in PETEP, because scripts can be reloaded and this would break it.

Scripter interfaces

Scripter currently has the following interface accessible through "scripter" variable:

void registerInterceptor(ScriptInterceptor interceptor)
Registers interceptor that allows you to work with PDUs.
void require(String path)
Loads script from specified path.
ScriptLogger getLogger()
Returns simplified logger.
ExtensionHelper getExtensionHelper()
Returns extension helper (see DEV guide).

Script interceptor

boolean intercept(PDU pdu, PetepHelper helper)
This method is called automatically for each PDU that goes through the interceptor.

Script logger

void info(String message)
Extension should be initalized inside this method - registration of modules etc.
void warning(String message)
Extension GUI should be initialized inside this method - creation of tabs etc.
void error(String message)
Extension GUI should be initialized inside this method - creation of tabs etc.

Pro Tip

Use PETEP's Java utils to work with the PDUs. This can be achieved using the Java.type function:

const PduUtils = Java.type('com.warxim.petep.util.PduUtils');
const BytesUtils = Java.type('com.warxim.petep.util.BytesUtils');

Take full advantage of Java interoperability, see GraalVM Java Interoperability

Special tags

In order to specify, which PDUs should be processed using scripts, you can tag them using the following tags (all PDUs are processed by default):

  • no_scripter - tagged PDU won't be processed
  • scripter - tagged PDU will be processed even if it already has no_scripter tag.

Example scripts

The following examples are part of Example preset. There are three scripts - simple replacer, logging interceptor and colorizing interceptor.

Simple console replacer - custom

This simple script uses JavaScript to process custom replacement. (Replaces bytes at specific index with given data.)

replacer.js
// Imports
const BytesUtils = Java.type('com.warxim.petep.util.BytesUtils');

// Config
const NEW_DATA = BytesUtils.hexStringToBytes('3A 29');
const TARGET_INDEX = 2;
const TARGET_LENGTH = NEW_DATA.length;
const TARGET_TAG = 'tag-1';

// Replacer
scripter.registerInterceptor({
    intercept: function(pdu, helper) {
        const buffer = pdu.getBuffer();

        if (!pdu.hasTag(TARGET_TAG)) {
            return true;
        }

        for (let i = 0; i < TARGET_LENGTH; ++i) {
            buffer[TARGET_INDEX + i] = NEW_DATA[i];
        }

        return true;
    }
});

Simple console logger

This simple script uses logger and PduUtils to print information about PDUs to console.

log-config.js
var config = {};

config.messages = {
	init: 'Script initialized!'
};

config.log = {
	type: true,
	size: true,
	proxy: true,
	connection: true,
	interceptor: false,
	destination: true,
	tags: true,
	buffer: false
};
logger.js
// Import config script
scripter.require('log-config.js');

// Load PETEP utils
const PduUtils = Java.type('com.warxim.petep.util.PduUtils');

// Load Java utils
const StringJoiner = Java.type('java.util.StringJoiner');
const ArrayList = Java.type('java.util.ArrayList');

// Obtain logger
const log = scripter.getLogger();
log.info(config.messages.init);

// Register info interceptor
scripter.registerInterceptor({
    intercept: function(pdu, helper) {
		var information = '';
		
		if (config.log.type) {
			information += '
- type: ' + pdu.getClass().getSimpleName();
		}
		
		if (config.log.destination) {
			information += '
- destination: ' + pdu.getDestination();
		}
		
		if (config.log.proxy) {
			let proxy = pdu.getProxy();
			information += '
- proxy: ' + proxy.getName() + ' (' + proxy.getCode() + ')';
		}
		
		if (config.log.connection) {
			let connection = pdu.getConnection();
			information += '
- connection: ' + connection.getCode();
		}
		
		if (config.log.interceptor) {
			let interceptor = pdu.getLastInterceptor();
			information += '
- last interceptor: ' + interceptor.getName() + ' (' + interceptor.getCode() + ')';
		}
		
		if (config.log.size) {
			information += '
- size: ' + pdu.getSize();
		}
		
		if (config.log.tags) {
			let tagJoiner = new StringJoiner(', ');
			pdu.getTags().forEach(tagJoiner.add);
			information += '
- tags: ' + tagJoiner.toString();
		}
		
		if (config.log.buffer) {
			information += '
- buffer: ' + PduUtils.bufferToHexString(pdu);
		}
		
		if (information.length > 0) {
			log.info('PDU information: ' + information);
		}
		
        return true;
    }
});

Simple replacer - using internal utils

This simple script uses PduUtils and BytesUtils to replace colors in the PDU data.

color-config.js
var config = {};

config.colors = {
	'#383b53': '#533838',
	'#b4b9e6': '#e6b4b4',
	'#8e96d9': '#d98e8e',
	'#33364b': '#4b3333',
	'#1f2639': '#391f1f',
	'#403e66': '#663e3e',
	'#daddf3': '#f3dada',
	'#edeff9': '#f9eded',
	'#f9f9fd': '#fdf9f9',
	'#f7f8fc': '#fcf7f7',
	'rgba(142,150,217,0.25)': 'rgba(217,142,142,0.25)'
}
colorizer.js
// Import config script
scripter.require('color-config.js');

// Load PETEP utils
const PduUtils = Java.type('com.warxim.petep.util.PduUtils');
const BytesUtils = Java.type('com.warxim.petep.util.BytesUtils');

// Register colorize interceptor
scripter.registerInterceptor({
    intercept: function(pdu, helper) {
		if (pdu.getProxy().getCode() !== 'petep') {
			return;
		}
		
		for (let currentColor in config.colors) {
			let newColor = config.colors[currentColor];
			PduUtils.replace(
				pdu,
				BytesUtils.getBytes(currentColor),
				BytesUtils.getBytes(newColor)
			);
		}
		return true;
    }
});