modules)
+ throws ConfigurationException {
+ // Use gson with pretty printing.
+ Gson gson = new GsonBuilder().setPrettyPrinting().create();
+ JsonArray list = new JsonArray(modules.size());
+
+ for (M module : modules) {
+ JsonObject object = new JsonObject();
+
+ // Add properties to the json object.
+ object.addProperty(Constant.CONFIG_ITEM_CODE, module.getCode());
+ object.addProperty(Constant.CONFIG_ITEM_NAME, module.getName());
+ object.addProperty(Constant.CONFIG_ITEM_DESCRIPTION, module.getDescription());
+ object.addProperty(Constant.CONFIG_ITEM_FACTORY, module.getFactory().getCode());
+ object.addProperty(Constant.CONFIG_ITEM_ENABLED, module.isEnabled());
+
+ // Add store to the json object.
+ Type storeType = ExtensionUtils.getStoreType(module);
+ if (storeType != null) {
+ object.add(Constant.CONFIG_ITEM_STORE,
+ gson.toJsonTree(((Storable>) module).saveStore(), storeType));
+ }
+
+ // Add config to the json object.
+ Type configType = ExtensionUtils.getConfigType(module);
+ if (configType != null) {
+ object.add(Constant.CONFIG_ITEM_CONFIG,
+ gson.toJsonTree(((Configurable>) module).saveConfig(), configType));
+ }
+
+ list.add(object);
+ }
+
+ // Write json to specified path.
+ try (JsonWriter writer = gson.newJsonWriter(new FileWriter(path))) {
+ gson.toJson(list, writer);
+ } catch (NoSuchFileException e) {
+ throw new ConfigurationException("Could not found configuration! (" + path + ")", e);
+ } catch (IOException e) {
+ throw new ConfigurationException("Could not save configuration! (" + path + ")", e);
+ }
+ }
+}
diff --git a/src/main/java/com/warxim/petep/configuration/ProjectLoader.java b/src/main/java/com/warxim/petep/configuration/ProjectLoader.java
new file mode 100644
index 0000000..85113f7
--- /dev/null
+++ b/src/main/java/com/warxim/petep/configuration/ProjectLoader.java
@@ -0,0 +1,45 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.configuration;
+
+import java.io.FileReader;
+import java.io.IOException;
+import java.nio.file.NoSuchFileException;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonParseException;
+import com.google.gson.JsonParser;
+import com.google.gson.stream.JsonReader;
+import com.warxim.petep.exception.ConfigurationException;
+import com.warxim.petep.project.Project;
+
+/** Static class for project loading. */
+public final class ProjectLoader {
+ private ProjectLoader() {}
+
+ /** Loads project from specified path. */
+ public static Project load(String path) throws ConfigurationException {
+ try (JsonReader reader = new JsonReader(new FileReader(path))) {
+ return new GsonBuilder().create().fromJson(JsonParser.parseReader(reader), Project.class);
+ } catch (JsonParseException e) {
+ throw new ConfigurationException("Could not parse project configuration!", e);
+ } catch (NoSuchFileException e) {
+ throw new ConfigurationException("Could not find project configuration!", e);
+ } catch (IOException e) {
+ throw new ConfigurationException("Could not load project configuration!", e);
+ }
+ }
+}
diff --git a/src/main/java/com/warxim/petep/configuration/ProjectSaver.java b/src/main/java/com/warxim/petep/configuration/ProjectSaver.java
new file mode 100644
index 0000000..71649dc
--- /dev/null
+++ b/src/main/java/com/warxim/petep/configuration/ProjectSaver.java
@@ -0,0 +1,44 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.configuration;
+
+import java.io.FileWriter;
+import java.io.IOException;
+import java.nio.file.NoSuchFileException;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.stream.JsonWriter;
+import com.warxim.petep.exception.ConfigurationException;
+import com.warxim.petep.project.Project;
+
+/** Static class for project saving. */
+public final class ProjectSaver {
+ private ProjectSaver() {}
+
+ /** Saves project to specified path. */
+ public static void save(String path, Project project) throws ConfigurationException {
+ Gson gson = new GsonBuilder().setPrettyPrinting().create();
+
+ try (JsonWriter writer = gson.newJsonWriter(new FileWriter(path))) {
+ gson.toJson(gson.toJsonTree(project), writer);
+ } catch (NoSuchFileException e) {
+ throw new ConfigurationException("Could not found project configuration!", e);
+ } catch (IOException e) {
+ throw new ConfigurationException("Could not save project configuration!", e);
+ }
+ }
+}
diff --git a/src/main/java/com/warxim/petep/core/PETEP.java b/src/main/java/com/warxim/petep/core/PETEP.java
new file mode 100644
index 0000000..7c54514
--- /dev/null
+++ b/src/main/java/com/warxim/petep/core/PETEP.java
@@ -0,0 +1,230 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.core;
+
+import java.util.logging.Logger;
+import com.warxim.petep.core.listener.PetepListener;
+import com.warxim.petep.core.pdu.PDU;
+import com.warxim.petep.helper.DefaultPetepHelper;
+import com.warxim.petep.helper.PetepHelper;
+import com.warxim.petep.interceptor.module.InterceptorModuleContainer;
+import com.warxim.petep.interceptor.worker.InterceptorExecutor;
+import com.warxim.petep.interceptor.worker.InterceptorManager;
+import com.warxim.petep.proxy.module.ProxyModuleContainer;
+import com.warxim.petep.proxy.worker.ProxyExecutor;
+import com.warxim.petep.proxy.worker.ProxyManager;
+
+/** PETEP core class. */
+public final class PETEP {
+ private final PetepListener listener;
+ private final PetepHelper helper;
+ private final Thread thread;
+
+ private PetepState state;
+
+ // Managers
+ private final ProxyManager proxyManager;
+ private final InterceptorManager interceptorManagerC2S;
+ private final InterceptorManager interceptorManagerS2C;
+
+ // Executors
+ private final ProxyExecutor proxyExecutor;
+ private final InterceptorExecutor interceptorExecutorC2S;
+ private final InterceptorExecutor interceptorExecutorS2C;
+
+ /** PETEP constructor. */
+ public PETEP(
+ ProxyModuleContainer proxyModuleContainer,
+ InterceptorModuleContainer interceptorModuleContainerC2S,
+ InterceptorModuleContainer interceptorModuleContainerS2C,
+ PetepListener listener) {
+ this.listener = listener;
+
+ // Create helper.
+ helper = new DefaultPetepHelper(this);
+
+ // Create managers.
+ proxyManager = new ProxyManager(helper, proxyModuleContainer);
+ interceptorManagerC2S = new InterceptorManager(helper, interceptorModuleContainerC2S);
+ interceptorManagerS2C = new InterceptorManager(helper, interceptorModuleContainerS2C);
+
+ // Create executors.
+ proxyExecutor = new ProxyExecutor(proxyManager);
+
+ interceptorExecutorC2S = new InterceptorExecutor(interceptorManagerC2S, this::sendC2S);
+ interceptorExecutorS2C = new InterceptorExecutor(interceptorManagerS2C, this::sendS2C);
+
+ state = PetepState.STOPPED;
+
+ this.thread = new Thread(this::run);
+ }
+
+ /** Starts PETEP. */
+ public void start() {
+ if (state != PetepState.STOPPED) {
+ return;
+ }
+
+ thread.start();
+ }
+
+ /** Stops PETEP. */
+ public void stop() {
+ if (state != PetepState.STARTED) {
+ return;
+ }
+
+ thread.interrupt();
+ }
+
+ /** Runs PETEP. */
+ private void run() {
+ listener.beforePrepare(helper);
+ if (!runPrepare()) {
+ Logger.getGlobal().severe("PETEP failed to prepare!");
+ } else {
+ listener.afterPrepare(helper);
+
+ listener.beforeStart(helper);
+ if (!runStart()) {
+ Logger.getGlobal().severe("PETEP failed to start!");
+ } else {
+ listener.afterStart(helper);
+
+ try {
+ thread.join();
+ } catch (InterruptedException e) {
+ Logger.getGlobal().info("PETEP interrupted...");
+ Thread.currentThread().interrupt();
+ }
+ }
+ }
+
+ listener.beforeStop(helper);
+ runStop();
+ listener.afterStop(helper);
+ }
+
+ /** Runs prepare. */
+ private boolean runPrepare() {
+ Logger.getGlobal().info("PETEP preparing...");
+ state = PetepState.PREPARING;
+
+ if (!proxyExecutor.prepare() || !interceptorExecutorC2S.prepare()
+ || !interceptorExecutorS2C.prepare()) {
+ return false;
+ }
+
+ state = PetepState.PREPARED;
+ Logger.getGlobal().info("PETEP prepared...");
+
+ return true;
+ }
+
+ /** Runs start. */
+ private boolean runStart() {
+ Logger.getGlobal().info("PETEP starting...");
+ state = PetepState.STARTING;
+
+ if (!proxyExecutor.start()) {
+ return false;
+ }
+
+ interceptorExecutorC2S.start();
+ interceptorExecutorS2C.start();
+
+ state = PetepState.STARTED;
+ Logger.getGlobal().info("PETEP started...");
+
+ return true;
+ }
+
+ /** Runs stop. */
+ private void runStop() {
+ Logger.getGlobal().info("PETEP stopping...");
+ state = PetepState.STOPPING;
+
+ proxyExecutor.stop();
+ interceptorExecutorC2S.stop();
+ interceptorExecutorS2C.stop();
+
+ state = PetepState.STOPPED;
+ Logger.getGlobal().info("PETEP stopped...");
+ }
+
+ /** Sends PDU in direction C2S out of PETEP. (Client -> Server) */
+ public void sendC2S(PDU pdu) {
+ pdu.getConnection().sendC2S(pdu);
+ }
+
+ /** Sends PDU in direction S2C out of PETEP. (Client <- Server) */
+ public void sendS2C(PDU pdu) {
+ pdu.getConnection().sendS2C(pdu);
+ }
+
+ /** Processes PDU internally in direction C2S. (Client -> Server) */
+ public void processC2S(PDU pdu) {
+ if (pdu.getLastInterceptor() == null) {
+ interceptorExecutorC2S.intercept(pdu);
+ } else {
+ interceptorExecutorC2S.intercept(pdu, pdu.getLastInterceptor().getId() + 1);
+ }
+ }
+
+ /** Processes PDU internally in direction S2C. (Client <- Server) */
+ public void processS2C(PDU pdu) {
+ if (pdu.getLastInterceptor() == null) {
+ interceptorExecutorS2C.intercept(pdu);
+ } else {
+ interceptorExecutorS2C.intercept(pdu, pdu.getLastInterceptor().getId() + 1);
+ }
+ }
+
+ /**
+ * Processes PDU internally in direction C2S and start in specified interceptor. (Client ->
+ * Server)
+ */
+ public void processC2S(PDU pdu, int interceptorId) {
+ interceptorExecutorC2S.intercept(pdu, interceptorId);
+ }
+
+ /**
+ * Processes PDU internally in direction S2C and start in specified interceptor. (Client <-
+ * Server)
+ */
+ public void processS2C(PDU pdu, int interceptorId) {
+ interceptorExecutorS2C.intercept(pdu, interceptorId);
+ }
+
+ public PetepState getState() {
+ return state;
+ }
+
+ public ProxyManager getProxyManager() {
+ return proxyManager;
+ }
+
+ /** Returns interceptor manager in direction C2S. (Client -> Server) */
+ public InterceptorManager getInterceptorManagerC2S() {
+ return interceptorManagerC2S;
+ }
+
+ /** Returns interceptor manager in direction S2C. (Client <- Server) */
+ public InterceptorManager getInterceptorManagerS2C() {
+ return interceptorManagerS2C;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/core/PetepManager.java b/src/main/java/com/warxim/petep/core/PetepManager.java
new file mode 100644
index 0000000..fa646a2
--- /dev/null
+++ b/src/main/java/com/warxim/petep/core/PetepManager.java
@@ -0,0 +1,139 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.core;
+
+import com.warxim.petep.core.listener.PetepListener;
+import com.warxim.petep.core.listener.PetepListenerManager;
+import com.warxim.petep.helper.PetepHelper;
+import com.warxim.petep.interceptor.module.InterceptorModuleContainer;
+import com.warxim.petep.proxy.module.ProxyModuleContainer;
+
+/**
+ * PETEP manager allows application to start & stop PETEP and hands over the resources to the PETEP
+ * core.
+ */
+public final class PetepManager implements PetepListener {
+ private final ProxyModuleContainer proxyModuleContainer;
+ private final InterceptorModuleContainer interceptorModuleContainerC2S;
+ private final InterceptorModuleContainer interceptorModuleContainerS2C;
+
+ private final PetepListenerManager petepListenerManager;
+
+ private PETEP petep;
+
+ public PetepManager(
+ ProxyModuleContainer proxyModuleManager,
+ InterceptorModuleContainer interceptorModuleContainerC2S,
+ InterceptorModuleContainer interceptorModuleContainerS2C,
+ PetepListenerManager petepListenerManager) {
+ this.proxyModuleContainer = proxyModuleManager;
+ this.interceptorModuleContainerC2S = interceptorModuleContainerC2S;
+ this.interceptorModuleContainerS2C = interceptorModuleContainerS2C;
+ this.petepListenerManager = petepListenerManager;
+
+ petep = null;
+
+ petepListenerManager.registerListener(this);
+ }
+
+ /*
+ * CONTROL
+ */
+ /** Creates and starts PETEP. */
+ public synchronized void start() {
+ if (petep != null) {
+ return;
+ }
+
+ petep = new PETEP(proxyModuleContainer, interceptorModuleContainerC2S,
+ interceptorModuleContainerS2C, petepListenerManager);
+
+ petep.start();
+ }
+
+ /** Stops PETEP. */
+ public synchronized void stop() {
+ if (petep == null) {
+ return;
+ }
+
+ petep.stop();
+ }
+
+ /*
+ * GETTERS
+ */
+ /** Returns PETEP state. */
+ public synchronized PetepState getState() {
+ if (petep == null) {
+ return PetepState.STOPPED;
+ }
+
+ return petep.getState();
+ }
+
+ public ProxyModuleContainer getProxyModuleContainer() {
+ return proxyModuleContainer;
+ }
+
+ /** Returns interceptor module container for direction C2S. (Client -> Server) */
+ public InterceptorModuleContainer getInterceptorModuleContainerC2S() {
+ return interceptorModuleContainerC2S;
+ }
+
+ /** Returns interceptor module container for direction S2C. (Client <- Server) */
+ public InterceptorModuleContainer getInterceptorModuleContainerS2C() {
+ return interceptorModuleContainerS2C;
+ }
+
+ public PetepListenerManager getPetepListenerManager() {
+ return petepListenerManager;
+ }
+
+ /*
+ * LISTENER
+ */
+ @Override
+ public void beforePrepare(PetepHelper helper) {
+ // No action needed.
+ }
+
+ @Override
+ public void afterPrepare(PetepHelper helper) {
+ // No action needed.
+ }
+
+ @Override
+ public void afterStart(PetepHelper helper) {
+ // No action needed.
+ }
+
+ @Override
+ public void beforeStart(PetepHelper helper) {
+ // No action needed.
+ }
+
+ @Override
+ public void beforeStop(PetepHelper helper) {
+ // No action needed.
+ }
+
+ @Override
+ public synchronized void afterStop(PetepHelper helper) {
+ petep = null;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/core/PetepState.java b/src/main/java/com/warxim/petep/core/PetepState.java
new file mode 100644
index 0000000..7cccf93
--- /dev/null
+++ b/src/main/java/com/warxim/petep/core/PetepState.java
@@ -0,0 +1,25 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.core;
+
+import com.warxim.petep.extension.PetepAPI;
+
+/** State of PETEP. */
+@PetepAPI
+public enum PetepState {
+ PREPARING, PREPARED, STARTING, STARTED, STOPPING, STOPPED
+}
diff --git a/src/main/java/com/warxim/petep/core/connection/Connection.java b/src/main/java/com/warxim/petep/core/connection/Connection.java
new file mode 100644
index 0000000..29fafd9
--- /dev/null
+++ b/src/main/java/com/warxim/petep/core/connection/Connection.java
@@ -0,0 +1,100 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.core.connection;
+
+import com.warxim.petep.core.pdu.PDU;
+import com.warxim.petep.core.pdu.PduDestination;
+import com.warxim.petep.core.pdu.PduQueue;
+import com.warxim.petep.extension.PetepAPI;
+import com.warxim.petep.proxy.worker.Proxy;
+
+/**
+ * Connection in PETEP proxy has to handle both connection between client and proxy and between
+ * proxy and server. Contains two outgoing queues that contain PDUs that should be sent in a given
+ * direction (C2S / S2C).
+ */
+@PetepAPI
+public abstract class Connection {
+ /** Unique nummeric identifier of the connection. */
+ protected final int id;
+
+ /** Parent proxy. */
+ protected final Proxy proxy;
+
+ /** Outgoing queue in direction C2S (client -> server). */
+ protected final PduQueue queueC2S;
+
+ /** Outgoing queue in direction S2C (client <- server). */
+ protected final PduQueue queueS2C;
+
+ /** Connection constructor. */
+ public Connection(int id, Proxy proxy) {
+ this.id = id;
+ this.proxy = proxy;
+ this.queueC2S = new PduQueue();
+ this.queueS2C = new PduQueue();
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ /** Sends PDU outside the PETEP. */
+ public final void send(PDU pdu) {
+ if (pdu.getDestination() == PduDestination.SERVER) {
+ queueC2S.add(pdu);
+ } else {
+ queueS2C.add(pdu);
+ }
+ }
+
+ /** Sends PDU outside the PETEP in direction C2S (client -> server). */
+ public final void sendC2S(PDU pdu) {
+ queueC2S.add(pdu);
+ }
+
+ /** Sends PDU outside the PETEP in direction S2C (client <- server). */
+ public final void sendS2C(PDU pdu) {
+ queueS2C.add(pdu);
+ }
+
+ /** Processes PDU in PETEP core. */
+ protected final void process(PDU pdu) {
+ proxy.getHelper().processPdu(pdu);
+ }
+
+ /** About connection. */
+ @Override
+ public String toString() {
+ return "Connection " + id;
+ }
+
+ /**
+ * Starts connection.
+ *
+ *
+ * @return Returns true if the start was successful.
+ *
+ *
+ * Attention: this method should return ASAP - it should be used to create threads and then
+ * return immediately.
+ */
+ public abstract boolean start();
+
+ /** Stops connection. */
+ public abstract void stop();
+}
diff --git a/src/main/java/com/warxim/petep/core/connection/ConnectionManager.java b/src/main/java/com/warxim/petep/core/connection/ConnectionManager.java
new file mode 100644
index 0000000..1fe8a84
--- /dev/null
+++ b/src/main/java/com/warxim/petep/core/connection/ConnectionManager.java
@@ -0,0 +1,45 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.core.connection;
+
+import java.util.List;
+import com.warxim.petep.extension.PetepAPI;
+
+/**
+ * Abstract class of connection manager that could be used by internal or external modules to work
+ * with connections of a given proxy.
+ */
+@PetepAPI
+public abstract class ConnectionManager {
+ /** Returns connection by ID. */
+ public abstract Connection get(int id);
+
+ /** Adds connection to the connection manager. */
+ public abstract boolean add(Connection connection);
+
+ /** Removes connection from the connection manager. */
+ public abstract boolean remove(Connection connection);
+
+ /** Removes connection from the connection manager. */
+ public abstract Connection remove(int id);
+
+ /** Returns list of connections. */
+ public abstract List getList();
+
+ /** Stops all connections. */
+ public abstract void stop();
+}
diff --git a/src/main/java/com/warxim/petep/core/connection/DefaultConnectionManager.java b/src/main/java/com/warxim/petep/core/connection/DefaultConnectionManager.java
new file mode 100644
index 0000000..4d3df0e
--- /dev/null
+++ b/src/main/java/com/warxim/petep/core/connection/DefaultConnectionManager.java
@@ -0,0 +1,72 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.core.connection;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
+import com.warxim.petep.extension.PetepAPI;
+
+/** Default connection manager that uses ConcurrentHashMap for connection storage. */
+@PetepAPI
+public class DefaultConnectionManager extends ConnectionManager {
+ /** Map of connections. */
+ protected final ConcurrentHashMap connections;
+
+ /** ID of last connection. */
+ private int lastId;
+
+ public DefaultConnectionManager() {
+ connections = new ConcurrentHashMap<>();
+ lastId = 0;
+ }
+
+ @Override
+ public Connection get(int id) {
+ return connections.get(id);
+ }
+
+ @Override
+ public boolean add(Connection connection) {
+ return connections.putIfAbsent(connection.getId(), connection) == null;
+ }
+
+ @Override
+ public boolean remove(Connection connection) {
+ return connections.remove(connection.getId(), connection);
+ }
+
+ @Override
+ public Connection remove(int id) {
+ return connections.remove(id);
+ }
+
+ @Override
+ public List getList() {
+ return new ArrayList<>(connections.values());
+ }
+
+ @Override
+ public void stop() {
+ connections.values().parallelStream().forEach(Connection::stop);
+ }
+
+ /** Generates new id for connection. */
+ public synchronized int nextId() {
+ return lastId++;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/core/listener/PetepListener.java b/src/main/java/com/warxim/petep/core/listener/PetepListener.java
new file mode 100644
index 0000000..d849e34
--- /dev/null
+++ b/src/main/java/com/warxim/petep/core/listener/PetepListener.java
@@ -0,0 +1,50 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.core.listener;
+
+import com.warxim.petep.extension.PetepAPI;
+import com.warxim.petep.helper.PetepHelper;
+
+/**
+ * PETEP listener interface. Allows extensions to listen for PETEP events and also allows them to
+ * obtain PetepHelper.
+ *
+ *
+ * ATTENTION: Extensions should remove PetepHelper from their memory after PETEP stops, so
+ * that GC can collect resources. (This, of course, applies to all other resources that are
+ * connected to PETEP instance.)
+ */
+@PetepAPI
+public interface PetepListener {
+ /** Event before prepare step is processed. */
+ default void beforePrepare(PetepHelper helper) {}
+
+ /** Event after prepare step is processed. */
+ default void afterPrepare(PetepHelper helper) {}
+
+ /** Event before start step is processed. */
+ default void beforeStart(PetepHelper helper) {}
+
+ /** Event after start step is processed. */
+ default void afterStart(PetepHelper helper) {}
+
+ /** Event before stop step is processed. */
+ default void beforeStop(PetepHelper helper) {}
+
+ /** Event after stop step is processed. */
+ default void afterStop(PetepHelper helper) {}
+}
diff --git a/src/main/java/com/warxim/petep/core/listener/PetepListenerManager.java b/src/main/java/com/warxim/petep/core/listener/PetepListenerManager.java
new file mode 100644
index 0000000..6bd5c07
--- /dev/null
+++ b/src/main/java/com/warxim/petep/core/listener/PetepListenerManager.java
@@ -0,0 +1,68 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.core.listener;
+
+import java.util.ArrayList;
+import java.util.List;
+import com.warxim.petep.helper.PetepHelper;
+
+/** Listener manager that allows modules to register their own listener. */
+public final class PetepListenerManager implements PetepListener {
+ private final List listeners;
+
+ public PetepListenerManager() {
+ listeners = new ArrayList<>();
+ }
+
+ public void registerListener(PetepListener listener) {
+ listeners.add(listener);
+ }
+
+ public void unregisterListener(PetepListener listener) {
+ listeners.remove(listener);
+ }
+
+ @Override
+ public void beforePrepare(PetepHelper helper) {
+ listeners.parallelStream().forEach(listener -> listener.beforePrepare(helper));
+ }
+
+ @Override
+ public void afterPrepare(PetepHelper helper) {
+ listeners.parallelStream().forEach(listener -> listener.afterPrepare(helper));
+ }
+
+ @Override
+ public void beforeStart(PetepHelper helper) {
+ listeners.parallelStream().forEach(listener -> listener.beforeStart(helper));
+ }
+
+ @Override
+ public void afterStart(PetepHelper helper) {
+ listeners.parallelStream().forEach(listener -> listener.afterStart(helper));
+ }
+
+ @Override
+ public void beforeStop(PetepHelper helper) {
+ listeners.parallelStream().forEach(listener -> listener.beforeStop(helper));
+ }
+
+ @Override
+ public void afterStop(PetepHelper helper) {
+ listeners.parallelStream().forEach(listener -> listener.afterStop(helper));
+ }
+}
diff --git a/src/main/java/com/warxim/petep/core/pdu/DefaultPdu.java b/src/main/java/com/warxim/petep/core/pdu/DefaultPdu.java
new file mode 100644
index 0000000..09459d5
--- /dev/null
+++ b/src/main/java/com/warxim/petep/core/pdu/DefaultPdu.java
@@ -0,0 +1,112 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.core.pdu;
+
+import java.nio.charset.Charset;
+import java.util.HashSet;
+import java.util.Set;
+import com.warxim.petep.common.Constant;
+import com.warxim.petep.core.connection.Connection;
+import com.warxim.petep.extension.PetepAPI;
+import com.warxim.petep.proxy.worker.Proxy;
+
+/** Default PDU implementation. */
+@PetepAPI
+public class DefaultPdu extends PDU {
+ protected byte[] buffer;
+ protected int size;
+ protected Charset charset;
+
+ /** Default PDU implementation constructor. */
+ public DefaultPdu(
+ Proxy proxy,
+ Connection connection,
+ PduDestination destination,
+ byte[] buffer,
+ int size,
+ Set tags) {
+ super(proxy, connection, destination, tags);
+ this.buffer = buffer;
+ this.size = size;
+ this.charset = Constant.DEFAULT_CHARSET;
+ }
+
+ public DefaultPdu(
+ Proxy proxy,
+ Connection connection,
+ PduDestination destination,
+ byte[] buffer,
+ int size) {
+ super(proxy, connection, destination, new HashSet<>());
+ this.buffer = buffer;
+ this.size = size;
+ this.charset = Constant.DEFAULT_CHARSET;
+ }
+
+ /** Returns the buffer. */
+ @Override
+ public byte[] getBuffer() {
+ return buffer;
+ }
+
+ /** Returns size of data in the buffer. */
+ @Override
+ public int getSize() {
+ return size;
+ }
+
+ /** Sets the buffer and size of data inside the buffer. */
+ @Override
+ public void setBuffer(byte[] buffer, int size) {
+ this.buffer = buffer;
+ this.size = size;
+ }
+
+ /** Resizes the buffer (expands the buffer when needed, but does not shrink the buffer). */
+ @Override
+ public void resize(int size) {
+ if (size <= buffer.length) {
+ return;
+ }
+
+ byte[] newBuffer = new byte[size];
+
+ // Copy content of original buffer to new one.
+ System.arraycopy(buffer, 0, newBuffer, 0, this.size);
+
+ buffer = newBuffer;
+ }
+
+ @Override
+ public PDU copy() {
+ PDU pdu = new DefaultPdu(proxy, connection, destination, buffer.clone(), size);
+
+ pdu.addTags(tags);
+
+ return pdu;
+ }
+
+ @Override
+ public Charset getCharset() {
+ return charset;
+ }
+
+ @Override
+ public void setCharset(Charset charset) {
+ this.charset = charset;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/core/pdu/PDU.java b/src/main/java/com/warxim/petep/core/pdu/PDU.java
new file mode 100644
index 0000000..6e294ba
--- /dev/null
+++ b/src/main/java/com/warxim/petep/core/pdu/PDU.java
@@ -0,0 +1,150 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.core.pdu;
+
+import java.nio.charset.Charset;
+import java.util.Collection;
+import java.util.Set;
+import com.warxim.petep.core.connection.Connection;
+import com.warxim.petep.extension.PetepAPI;
+import com.warxim.petep.interceptor.worker.Interceptor;
+import com.warxim.petep.proxy.worker.Proxy;
+
+/** PDU (Protocol Data Unit) is core unit for data processed in PETEP. */
+@PetepAPI
+public abstract class PDU {
+ /** Parent proxy. */
+ protected Proxy proxy;
+
+ /** Parent connection. */
+ protected Connection connection;
+
+ /** PDU destination. */
+ protected PduDestination destination;
+
+ /** Interceptor in which was the PDU processed last time. */
+ protected Interceptor lastInterceptor;
+
+ /** PDU tags. */
+ protected Set tags;
+
+ /** PDU constructor */
+ public PDU(Proxy proxy, Connection connection, PduDestination destination, Set tags) {
+ this.proxy = proxy;
+ this.destination = destination;
+ this.connection = connection;
+ this.tags = tags;
+ }
+
+ /*
+ * TAGS
+ */
+ /** Does the PDU contain specified tag? */
+ public boolean hasTag(String tag) {
+ return tags.contains(tag);
+ }
+
+ /** Adds tag to the PDU. */
+ public void addTag(String tag) {
+ tags.add(tag);
+ }
+
+ /** Removes tag from the PDU. */
+ public void removeTag(String tag) {
+ tags.remove(tag);
+ }
+
+ /** Removes tag from the PDU. */
+ public void addTags(Collection tags) {
+ this.tags.addAll(tags);
+ }
+
+ /*
+ * GETTERS
+ */
+ /** Returns set of tags. */
+ public Set getTags() {
+ return tags;
+ }
+
+ /** Returns parent proxy. */
+ public Proxy getProxy() {
+ return proxy;
+ }
+
+ /** Returns PDU destination. */
+ public PduDestination getDestination() {
+ return destination;
+ }
+
+ /** Returns connection. */
+ public Connection getConnection() {
+ return connection;
+ }
+
+ /** Returns interceptor. */
+ public Interceptor getLastInterceptor() {
+ return lastInterceptor;
+ }
+
+ /*
+ * SETTERS
+ */
+ /** Sets parent proxy. */
+ public void setProxy(Proxy proxy) {
+ this.proxy = proxy;
+ }
+
+ /** Sets PDU destination. */
+ public void setDestination(PduDestination destination) {
+ this.destination = destination;
+ }
+
+ /** Sets connection. */
+ public void setConnection(Connection connection) {
+ this.connection = connection;
+ }
+
+ /** Sets interceptor. */
+ public void setLastInterceptor(Interceptor interceptor) {
+ this.lastInterceptor = interceptor;
+ }
+
+ /*
+ * ABSTRACT METHODS
+ */
+ /** Returns buffer. */
+ public abstract byte[] getBuffer();
+
+ /** Returns size of data in the buffer. */
+ public abstract int getSize();
+
+ /** Returns the buffer and size of data in the buffer. */
+ public abstract void setBuffer(byte[] buffer, int size);
+
+ /** Resizes the buffer. */
+ public abstract void resize(int size);
+
+ /** Returns the charset of the PDU. */
+ public abstract Charset getCharset();
+
+ /** Sets the charset of the PDU. */
+ public abstract void setCharset(Charset charset);
+
+ /** Creates deep copy of the PDU. */
+ public abstract PDU copy();
+}
diff --git a/src/main/java/com/warxim/petep/core/pdu/PduDestination.java b/src/main/java/com/warxim/petep/core/pdu/PduDestination.java
new file mode 100644
index 0000000..77c693a
--- /dev/null
+++ b/src/main/java/com/warxim/petep/core/pdu/PduDestination.java
@@ -0,0 +1,25 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.core.pdu;
+
+import com.warxim.petep.extension.PetepAPI;
+
+/** Destination of PDU. */
+@PetepAPI
+public enum PduDestination {
+ CLIENT, SERVER
+}
diff --git a/src/main/java/com/warxim/petep/core/pdu/PduQueue.java b/src/main/java/com/warxim/petep/core/pdu/PduQueue.java
new file mode 100644
index 0000000..9cac97f
--- /dev/null
+++ b/src/main/java/com/warxim/petep/core/pdu/PduQueue.java
@@ -0,0 +1,61 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.core.pdu;
+
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+import com.warxim.petep.extension.PetepAPI;
+
+/* Queue of PDUs. */
+@PetepAPI
+public class PduQueue {
+ private final BlockingQueue queue;
+
+ public PduQueue() {
+ queue = new LinkedBlockingQueue<>();
+ }
+
+ /** Add PDU to queue. */
+ public void add(PDU pdu) {
+ queue.add(pdu);
+ }
+
+ /** Returns PDU from queue (blocks until there is PDU). */
+ public PDU take() throws InterruptedException {
+ return queue.take();
+ }
+
+ /** Returns queue size. */
+ public int size() {
+ return queue.size();
+ }
+
+ /** Clears queue. */
+ public void clear() {
+ queue.clear();
+ }
+
+ /** Returns true if the queue is empty. */
+ public boolean isEmpty() {
+ return queue.isEmpty();
+ }
+
+ /** Retrieves and removes the head of the queue. */
+ public PDU poll() {
+ return queue.poll();
+ }
+}
diff --git a/src/main/java/com/warxim/petep/exception/CommandLineArgumentsException.java b/src/main/java/com/warxim/petep/exception/CommandLineArgumentsException.java
new file mode 100644
index 0000000..69c65b5
--- /dev/null
+++ b/src/main/java/com/warxim/petep/exception/CommandLineArgumentsException.java
@@ -0,0 +1,26 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.exception;
+
+/** Command line arguments exception for invalid arguments. */
+public final class CommandLineArgumentsException extends Exception {
+ private static final long serialVersionUID = 1L;
+
+ public CommandLineArgumentsException(String message) {
+ super(message);
+ }
+}
diff --git a/src/main/java/com/warxim/petep/exception/ConfigurationException.java b/src/main/java/com/warxim/petep/exception/ConfigurationException.java
new file mode 100644
index 0000000..acc04cc
--- /dev/null
+++ b/src/main/java/com/warxim/petep/exception/ConfigurationException.java
@@ -0,0 +1,33 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.exception;
+
+/**
+ * Configuration exception for configuration errors (configuration does not exist, cannot be
+ * accessed, invalid fields, ...)
+ */
+public final class ConfigurationException extends Exception {
+ private static final long serialVersionUID = 1L;
+
+ public ConfigurationException(String message) {
+ super(message);
+ }
+
+ public ConfigurationException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/src/main/java/com/warxim/petep/exception/ExtensionLoadException.java b/src/main/java/com/warxim/petep/exception/ExtensionLoadException.java
new file mode 100644
index 0000000..f720a0a
--- /dev/null
+++ b/src/main/java/com/warxim/petep/exception/ExtensionLoadException.java
@@ -0,0 +1,30 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.exception;
+
+/** Extension load exception. */
+public final class ExtensionLoadException extends Exception {
+ private static final long serialVersionUID = 1L;
+
+ public ExtensionLoadException(String message) {
+ super(message);
+ }
+
+ public ExtensionLoadException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/Extension.java b/src/main/java/com/warxim/petep/extension/Extension.java
new file mode 100644
index 0000000..eed3d10
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/Extension.java
@@ -0,0 +1,49 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension;
+
+import com.warxim.petep.helper.ExtensionHelper;
+import com.warxim.petep.helper.GuiHelper;
+
+/** Superclass for extensions. */
+@PetepAPI
+public abstract class Extension {
+ /** Path where the extension .jar file is located. */
+ protected final String path;
+
+ public Extension(String path) {
+ this.path = path;
+ }
+
+ public final String getPath() {
+ return path;
+ }
+
+ /** Initializes the extension. */
+ public abstract void init(ExtensionHelper helper);
+
+ /** Initializes the extension GUI. */
+ public abstract void initGui(GuiHelper helper);
+
+ public abstract String getCode();
+
+ public abstract String getName();
+
+ public abstract String getDescription();
+
+ public abstract String getVersion();
+}
diff --git a/src/main/java/com/warxim/petep/extension/ExtensionGuiInitListener.java b/src/main/java/com/warxim/petep/extension/ExtensionGuiInitListener.java
new file mode 100644
index 0000000..d1d33c0
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/ExtensionGuiInitListener.java
@@ -0,0 +1,28 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension;
+
+import com.warxim.petep.helper.GuiHelper;
+
+@PetepAPI
+public interface ExtensionGuiInitListener {
+ /** Runs before extension GUIs are initialized. */
+ void beforeInitGui(GuiHelper helper);
+
+ /** Runs after extension GUIs are initialized. */
+ void afterInitGui(GuiHelper helper);
+}
diff --git a/src/main/java/com/warxim/petep/extension/ExtensionInitListener.java b/src/main/java/com/warxim/petep/extension/ExtensionInitListener.java
new file mode 100644
index 0000000..31a633c
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/ExtensionInitListener.java
@@ -0,0 +1,28 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension;
+
+import com.warxim.petep.helper.ExtensionHelper;
+
+@PetepAPI
+public interface ExtensionInitListener {
+ /** Runs before extensions are initialized. */
+ void beforeInit(ExtensionHelper helper);
+
+ /** Runs after extensions are initialized. */
+ void afterInit(ExtensionHelper helper);
+}
diff --git a/src/main/java/com/warxim/petep/extension/ExtensionManager.java b/src/main/java/com/warxim/petep/extension/ExtensionManager.java
new file mode 100644
index 0000000..686c7c9
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/ExtensionManager.java
@@ -0,0 +1,100 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import com.warxim.petep.helper.ExtensionHelper;
+import com.warxim.petep.helper.GuiHelper;
+
+/** Extension manager. */
+public final class ExtensionManager {
+ /** Map of extensions (key = extension code). */
+ private final Map extensionMap;
+
+ /** List of extensions. */
+ private final List extensionList;
+
+ /**
+ * Extension manager constructor that takes list of extensions and stores them to own unmodifiable
+ * collections.
+ */
+ public ExtensionManager(List extensions) {
+ // Make list unmodifiable.
+ extensionList = Collections.unmodifiableList(extensions);
+
+ // Fill map with extensions with code as key.
+ Map map = new HashMap<>((int) (extensions.size() / 0.75 + 1), 0.75f);
+ for (Extension extension : extensions) {
+ map.put(extension.getCode(), extension);
+ }
+
+ // Make map unmodifiable
+ extensionMap = Collections.unmodifiableMap(map);
+ }
+
+ /** Returns unmodifiable extensions map . */
+ public Map getMap() {
+ return extensionMap;
+ }
+
+ /** Returns unmodifiable extensions list. */
+ public List getList() {
+ return extensionList;
+ }
+
+ /** Returns extension by code. */
+ public Extension getExtension(String code) {
+ return extensionMap.get(code);
+ }
+
+ /** Inits extensions. */
+ public void init(ExtensionHelper helper) {
+ // Call beforeInit on listeners.
+ extensionList.stream()
+ .filter(ExtensionInitListener.class::isInstance)
+ .map(ExtensionInitListener.class::cast)
+ .forEach(extension -> extension.beforeInit(helper));
+
+ extensionList.parallelStream().forEach(extension -> extension.init(helper));
+
+ // Call afterInit on listeners.
+ extensionList.stream()
+ .filter(ExtensionInitListener.class::isInstance)
+ .map(ExtensionInitListener.class::cast)
+ .forEach(extension -> extension.afterInit(helper));
+ }
+
+ /** Inits extensions GUI. */
+ public void initGui(GuiHelper helper) {
+ // Call beforeInitGui on listeners.
+ extensionList.stream()
+ .filter(ExtensionGuiInitListener.class::isInstance)
+ .map(ExtensionGuiInitListener.class::cast)
+ .forEach(extension -> extension.beforeInitGui(helper));
+
+ extensionList.parallelStream().forEach(extension -> extension.initGui(helper));
+
+ // Call afterInitGui on listeners.
+ extensionList.stream()
+ .filter(ExtensionGuiInitListener.class::isInstance)
+ .map(ExtensionGuiInitListener.class::cast)
+ .forEach(extension -> extension.afterInitGui(helper));
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/PetepAPI.java b/src/main/java/com/warxim/petep/extension/PetepAPI.java
new file mode 100644
index 0000000..b6ff78e
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/PetepAPI.java
@@ -0,0 +1,31 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension;
+
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation signaling that the annotated element is part of extension API and should be used to
+ * generate PetepLib.jar for extensions.
+ */
+@Retention(SOURCE)
+@Target(ElementType.TYPE)
+public @interface PetepAPI {
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/catcher/CatcherController.java b/src/main/java/com/warxim/petep/extension/internal/catcher/CatcherController.java
new file mode 100644
index 0000000..4ac7e83
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/catcher/CatcherController.java
@@ -0,0 +1,212 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.catcher;
+
+import java.net.URL;
+import java.util.ResourceBundle;
+import java.util.Timer;
+import java.util.TimerTask;
+import com.warxim.petep.core.pdu.PDU;
+import com.warxim.petep.core.pdu.PduQueue;
+import com.warxim.petep.gui.control.PduEditor;
+import com.warxim.petep.helper.PetepHelper;
+import javafx.application.Platform;
+import javafx.event.ActionEvent;
+import javafx.fxml.FXML;
+import javafx.fxml.Initializable;
+import javafx.scene.control.Button;
+import javafx.scene.control.Label;
+
+/** Catcher controller. */
+public final class CatcherController implements Initializable {
+ private static final int QUEUE_CHECK_PERIOD_MS = 500;
+
+ private final PetepHelper petepHelper;
+
+ /** Current PDU. */
+ private PDU pdu;
+
+ /** PDU queue. */
+ private final PduQueue queue;
+
+ /** Timer for checking queue for new PDUs. */
+ private Timer timer;
+
+ /** State of catcher (on, transition, off). */
+ private CatcherState state;
+
+ /*
+ * GUI
+ */
+ @FXML
+ private PduEditor pduEditor;
+ @FXML
+ private Label stateLabel;
+ @FXML
+ private Button forwardButton;
+ @FXML
+ private Button dropButton;
+ @FXML
+ private Button startStopButton;
+
+ /** Catcher controller constructor. */
+ public CatcherController(PetepHelper petepHelper) {
+ this.petepHelper = petepHelper;
+ this.queue = new PduQueue();
+
+ // Stopped by default.
+ state = CatcherState.OFF;
+ }
+
+ @Override
+ public void initialize(URL location, ResourceBundle resources) {
+ pduEditor.init(petepHelper);
+
+ setDisableEditor(true);
+ }
+
+ public void stop() {
+ if (timer != null) {
+ timer.cancel();
+ }
+ }
+
+ private void setDisableEditor(boolean value) {
+ forwardButton.setDisable(value);
+ dropButton.setDisable(value);
+ pduEditor.setDisable(value);
+ }
+
+ private void checkQueue() {
+ Platform.runLater(() -> {
+ if (pdu == null) {
+ pdu = queue.poll();
+
+ // No PDU in queue.
+ if (pdu == null) {
+ return;
+ }
+
+ // PDU has no_catch tag and does not have catch tag. (Let it be processed
+ // automatically in PETEP.)
+ if (pdu.hasTag("no_catch") && !pdu.hasTag("catch")) {
+ petepHelper.processPdu(pdu);
+ pdu = null;
+ checkQueue();
+ return;
+ }
+
+ // Set PDU to editor.
+ pduEditor.setPdu(pdu);
+
+ // Enable editor.
+ setDisableEditor(false);
+ }
+ });
+ }
+
+ private void disable() {
+ Platform.runLater(() -> {
+ setDisableEditor(true);
+
+ pdu = null;
+ });
+ }
+
+ @FXML
+ private void onInterceptStartStopButtonClick(ActionEvent event) {
+ if (state == CatcherState.ON) {
+ // Stop catcher.
+ // Update GUI.
+ state = CatcherState.TRANSITION;
+ stateLabel.setText("...");
+
+ // Process current PDU in PETEP.
+ if (pdu != null) {
+ petepHelper.processPdu(pdu);
+ }
+
+ // Reset GUI.
+ disable();
+
+ // Clear
+ pduEditor.clear();
+
+ // Process PDUs from queue in PETEP.
+ while ((pdu = queue.poll()) != null) {
+ petepHelper.processPdu(pdu);
+ }
+
+ // Cancel timer.
+ if (timer != null) {
+ timer.cancel();
+ timer = null;
+ }
+
+ // Update GUI.
+ stateLabel.setText("OFF");
+ startStopButton.setText("START");
+
+ state = CatcherState.OFF;
+ } else {
+ // Start catcher.
+ // Create timer and schedule queue checking.
+ timer = new Timer();
+
+ timer.schedule(new TimerTask() {
+ @Override
+ public void run() {
+ checkQueue();
+ }
+ }, 0, QUEUE_CHECK_PERIOD_MS);
+
+ // Update GUI.
+ stateLabel.setText("ON");
+ startStopButton.setText("STOP");
+
+ // Set state to ON.
+ state = CatcherState.ON;
+ }
+ }
+
+ @FXML
+ private void onDropButtonClick(ActionEvent event) {
+ disable();
+ }
+
+ @FXML
+ private void onForwardButtonClick(ActionEvent event) {
+ // Process PDU in PETEP.
+ petepHelper.processPdu(pduEditor.getPdu());
+
+ // Reset GUI.
+ disable();
+
+ // Check for new PDU.
+ checkQueue();
+ }
+
+ /** Adds PDU to catcher queue. */
+ public void catchPdu(PDU data) {
+ queue.add(data);
+ }
+
+ /** Returns catcher state. */
+ public CatcherState getState() {
+ return state;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/catcher/CatcherExtension.java b/src/main/java/com/warxim/petep/extension/internal/catcher/CatcherExtension.java
new file mode 100644
index 0000000..0636a81
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/catcher/CatcherExtension.java
@@ -0,0 +1,112 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.catcher;
+
+import java.io.IOException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import com.warxim.petep.common.ContextType;
+import com.warxim.petep.core.listener.PetepListener;
+import com.warxim.petep.extension.Extension;
+import com.warxim.petep.helper.ExtensionHelper;
+import com.warxim.petep.helper.GuiHelper;
+import com.warxim.petep.helper.PetepHelper;
+import javafx.fxml.FXMLLoader;
+import javafx.scene.Node;
+
+/** Catcher extension. */
+public final class CatcherExtension extends Extension {
+ private GuiHelper guiHelper;
+ private Node node;
+ private CatcherController controller;
+
+ /** Catcher extension constructor. */
+ public CatcherExtension(String path) {
+ super(path);
+ }
+
+ @Override
+ public void init(ExtensionHelper helper) {
+ // Register PETEP listener if GUI is enabled.
+ if (helper.getContextType() == ContextType.GUI) {
+ helper.registerPetepListener(new PetepListener() {
+ @Override
+ public void beforePrepare(PetepHelper helper) {
+ // Load catcher tab.
+ try {
+ FXMLLoader fxmlLoader = new FXMLLoader(
+ getClass().getResource("/fxml/extension/internal/catcher/Catcher.fxml"));
+
+ controller = new CatcherController(helper);
+
+ fxmlLoader.setController(controller);
+
+ node = fxmlLoader.load();
+
+ guiHelper.registerTab("Catcher", node);
+ } catch (IOException e) {
+ Logger.getGlobal().log(Level.SEVERE, "Could not load catcher GUI!", e);
+ }
+ }
+
+ @Override
+ public void beforeStop(PetepHelper helper) {
+ // Unload catcher tab.
+ guiHelper.unregisterTab(node);
+
+ // Clear memory.
+ node = null;
+ controller.stop();
+ controller = null;
+ }
+ });
+ }
+
+ helper.registerInterceptorModuleFactory(new CatcherInterceptorModuleFactory(this));
+ }
+
+ @Override
+ public void initGui(GuiHelper helper) {
+ guiHelper = helper;
+
+ helper.registerGuide(new CatcherGuide());
+ }
+
+ @Override
+ public String getCode() {
+ return "catcher";
+ }
+
+ @Override
+ public String getName() {
+ return "Catcher";
+ }
+
+ @Override
+ public String getDescription() {
+ return "Catches PDUs and allows user to edit them before relasing (manual intercepting).";
+ }
+
+ @Override
+ public String getVersion() {
+ return "1.0";
+ }
+
+ public CatcherController getController() {
+ return controller;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/catcher/CatcherGuide.java b/src/main/java/com/warxim/petep/extension/internal/catcher/CatcherGuide.java
new file mode 100644
index 0000000..0e22224
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/catcher/CatcherGuide.java
@@ -0,0 +1,32 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.catcher;
+
+import com.warxim.petep.gui.guide.Guide;
+
+/** Catcher guide. */
+public final class CatcherGuide extends Guide {
+ @Override
+ public String getTitle() {
+ return "Catcher";
+ }
+
+ @Override
+ public String getHtml() {
+ return loadHtmlResource("/html/guide/internal/CatcherGuide.html");
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/catcher/CatcherInterceptor.java b/src/main/java/com/warxim/petep/extension/internal/catcher/CatcherInterceptor.java
new file mode 100644
index 0000000..cd67552
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/catcher/CatcherInterceptor.java
@@ -0,0 +1,83 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.catcher;
+
+import com.warxim.petep.core.pdu.PDU;
+import com.warxim.petep.helper.PetepHelper;
+import com.warxim.petep.interceptor.module.InterceptorModule;
+import com.warxim.petep.interceptor.worker.Interceptor;
+
+/** Catcher interceptor. */
+public final class CatcherInterceptor extends Interceptor {
+ private static final int RECHECK_STATE_PERIOD_MS = 25;
+ private CatcherController controller;
+
+ /** Catcher interceptor constructor. */
+ public CatcherInterceptor(int id, InterceptorModule module, PetepHelper helper) {
+ super(id, module, helper);
+ }
+
+ @Override
+ public boolean prepare() {
+ // Get controller.
+ controller = ((CatcherExtension) module.getFactory().getExtension()).getController();
+ return true;
+ }
+
+ @Override
+ public boolean intercept(PDU pdu) {
+ if (controller == null) {
+ // Controller does not exist, let PDU go through.
+ return true;
+ } else {
+ // PDU has no_catch_skip tag and does not have catch tag. (Let it go through the interceptor.)
+ if (pdu.hasTag("no_catch_skip") && !pdu.hasTag("catch")) {
+ return true;
+ }
+
+ // If controller is in transition, wait, so we do not mix PDU order.
+ while (controller.getState() == CatcherState.TRANSITION) {
+ try {
+ Thread.sleep(RECHECK_STATE_PERIOD_MS);
+ } catch (InterruptedException e) {
+ // Interrupted
+ Thread.currentThread().interrupt();
+ return false;
+ }
+ }
+
+ // If catcher is disabled, let PDU go through.
+ if (controller.getState() == CatcherState.OFF) {
+ return true;
+ }
+
+ // Set this interceptor as last PDU interceptor.
+ pdu.setLastInterceptor(this);
+
+ // Intercept PDU in GUI.
+ controller.catchPdu(pdu);
+
+ // Do not let PDU go to the next interceptor.
+ return false;
+ }
+ }
+
+ @Override
+ public void stop() {
+ // No action needed.
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/catcher/CatcherInterceptorModule.java b/src/main/java/com/warxim/petep/extension/internal/catcher/CatcherInterceptorModule.java
new file mode 100644
index 0000000..06eb6dc
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/catcher/CatcherInterceptorModule.java
@@ -0,0 +1,40 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.catcher;
+
+import com.warxim.petep.helper.PetepHelper;
+import com.warxim.petep.interceptor.factory.InterceptorModuleFactory;
+import com.warxim.petep.interceptor.module.InterceptorModule;
+import com.warxim.petep.interceptor.worker.Interceptor;
+
+/** Catcher interceptor module. */
+public final class CatcherInterceptorModule extends InterceptorModule {
+ /** Catcher interceptor module constructor. */
+ public CatcherInterceptorModule(
+ InterceptorModuleFactory factory,
+ String code,
+ String name,
+ String description,
+ boolean enabled) {
+ super(factory, code, name, description, enabled);
+ }
+
+ @Override
+ public Interceptor createInterceptor(int id, PetepHelper helper) {
+ return new CatcherInterceptor(id, this, helper);
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/catcher/CatcherInterceptorModuleFactory.java b/src/main/java/com/warxim/petep/extension/internal/catcher/CatcherInterceptorModuleFactory.java
new file mode 100644
index 0000000..5f8ae2a
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/catcher/CatcherInterceptorModuleFactory.java
@@ -0,0 +1,48 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.catcher;
+
+import com.warxim.petep.extension.Extension;
+import com.warxim.petep.interceptor.factory.InterceptorModuleFactory;
+import com.warxim.petep.interceptor.module.InterceptorModule;
+
+/** Catcher interceptor module factory. */
+public final class CatcherInterceptorModuleFactory extends InterceptorModuleFactory {
+ /** Catcher interceptor module factory constructor. */
+ public CatcherInterceptorModuleFactory(Extension extension) {
+ super(extension);
+ }
+
+ @Override
+ public String getName() {
+ return "Catcher";
+ }
+
+ @Override
+ public String getCode() {
+ return "catcher";
+ }
+
+ @Override
+ public InterceptorModule createModule(
+ String code,
+ String name,
+ String description,
+ boolean enabled) {
+ return new CatcherInterceptorModule(this, code, name, description, enabled);
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/catcher/CatcherState.java b/src/main/java/com/warxim/petep/extension/internal/catcher/CatcherState.java
new file mode 100644
index 0000000..3b8a3ce
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/catcher/CatcherState.java
@@ -0,0 +1,27 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.catcher;
+
+/**
+ * Catcher state.
+ * ON = catcher is enabled.
+ * OFF = catcher is disabled.
+ * TRANSITION = catcher is in transition state between ON and OFF.
+ */
+public enum CatcherState {
+ ON, OFF, TRANSITION
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/common/rule_group/Rule.java b/src/main/java/com/warxim/petep/extension/internal/common/rule_group/Rule.java
new file mode 100644
index 0000000..0924e27
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/common/rule_group/Rule.java
@@ -0,0 +1,43 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.common.rule_group;
+
+/** Rule. */
+public class Rule {
+ protected final String name;
+ protected final String description;
+ protected final boolean enabled;
+
+ /** Rule constructor. */
+ public Rule(String name, String description, boolean enabled) {
+ this.name = name;
+ this.description = description;
+ this.enabled = enabled;
+ }
+
+ public final String getName() {
+ return name;
+ }
+
+ public final String getDescription() {
+ return description;
+ }
+
+ public final boolean isEnabled() {
+ return enabled;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/common/rule_group/RuleGroup.java b/src/main/java/com/warxim/petep/extension/internal/common/rule_group/RuleGroup.java
new file mode 100644
index 0000000..daac07c
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/common/rule_group/RuleGroup.java
@@ -0,0 +1,84 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.common.rule_group;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+/** Group of rules. */
+public class RuleGroup {
+ private String code;
+ private String name;
+
+ private final CopyOnWriteArrayList rules;
+
+ /** Rule group constructor. */
+ public RuleGroup(String code, String name) {
+ this.code = code;
+ this.name = name;
+ rules = new CopyOnWriteArrayList<>();
+ }
+
+ public final String getCode() {
+ return code;
+ }
+
+ public final String getName() {
+ return name;
+ }
+
+ public final void setCode(String code) {
+ this.code = code;
+ }
+
+ public final void setName(String code) {
+ this.name = code;
+ }
+
+ public final List getRules() {
+ return rules;
+ }
+
+ public final int size() {
+ return rules.size();
+ }
+
+ public final boolean addRule(R rule) {
+ return rules.add(rule);
+ }
+
+ public final void setRule(int index, R rule) {
+ rules.set(index, rule);
+ }
+
+ public final void replace(R oldRule, R newRule) {
+ rules.set(rules.indexOf(oldRule), newRule);
+ }
+
+ public final boolean removeRule(R rule) {
+ return rules.remove(rule);
+ }
+
+ public final void swapRules(int what, int with) {
+ Collections.swap(rules, what, with);
+ }
+
+ public final int ruleCount() {
+ return rules.size();
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/common/rule_group/RuleGroupManager.java b/src/main/java/com/warxim/petep/extension/internal/common/rule_group/RuleGroupManager.java
new file mode 100644
index 0000000..407c77b
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/common/rule_group/RuleGroupManager.java
@@ -0,0 +1,80 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.common.rule_group;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.logging.Logger;
+
+/** Manager of groups of rules. */
+public class RuleGroupManager> {
+ private final ConcurrentHashMap groups;
+
+ /** Rule group manager constructor. */
+ public RuleGroupManager() {
+ groups = new ConcurrentHashMap<>();
+ }
+
+ /** Rule group manager constructor. */
+ public RuleGroupManager(List groups) {
+ this();
+ for (G group : groups) {
+ if (!add(group)) {
+ Logger.getGlobal()
+ .severe("Rule group " + group.getCode()
+ + " was not loaded, because group with this code already exists!");
+ }
+ }
+ }
+
+ /** Returns true if manager contains specified code. */
+ public final boolean contains(String code) {
+ return groups.containsKey(code);
+ }
+
+ /** Returns group for specified code. */
+ public final G get(String code) {
+ return groups.get(code);
+ }
+
+ /** Returns true if group was successfully added. Returns false if group code is reserved. */
+ public final boolean add(G group) {
+ return groups.putIfAbsent(group.getCode(), group) == null;
+ }
+
+ /** Removes group by its code. */
+ public final void remove(String code) {
+ groups.remove(code);
+ }
+
+ /** Returns list of groups. */
+ public final List getList() {
+ return new ArrayList<>(groups.values());
+ }
+
+ /** Returns map of groups. */
+ public final Map getMap() {
+ return groups;
+ }
+
+ /** Returns number of groups. */
+ public final int size() {
+ return groups.size();
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/common/rule_group/config/RuleGroupsConfig.java b/src/main/java/com/warxim/petep/extension/internal/common/rule_group/config/RuleGroupsConfig.java
new file mode 100644
index 0000000..35c25e2
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/common/rule_group/config/RuleGroupsConfig.java
@@ -0,0 +1,35 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.common.rule_group.config;
+
+import java.util.List;
+import com.warxim.petep.extension.internal.common.rule_group.Rule;
+import com.warxim.petep.extension.internal.common.rule_group.RuleGroup;
+
+/** Configuratioon of groups of roles. */
+public final class RuleGroupsConfig {
+ private final List> groups;
+
+ /** Rule groups configuration constructor. */
+ public RuleGroupsConfig(List> groups) {
+ this.groups = groups;
+ }
+
+ public final List> getRuleGroups() {
+ return groups;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/common/rule_group/config/RuleInterceptorConfig.java b/src/main/java/com/warxim/petep/extension/internal/common/rule_group/config/RuleInterceptorConfig.java
new file mode 100644
index 0000000..1f1277a
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/common/rule_group/config/RuleInterceptorConfig.java
@@ -0,0 +1,31 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.common.rule_group.config;
+
+/** Rule interceptor configuration. */
+public final class RuleInterceptorConfig {
+ private final String ruleGroupCode;
+
+ /** Rule interceptor configuration constructor. */
+ public RuleInterceptorConfig(String ruleGroupCode) {
+ this.ruleGroupCode = ruleGroupCode;
+ }
+
+ public final String getRuleGroupCode() {
+ return ruleGroupCode;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/common/rule_group/gui/EditRuleGroupDialog.java b/src/main/java/com/warxim/petep/extension/internal/common/rule_group/gui/EditRuleGroupDialog.java
new file mode 100644
index 0000000..f573110
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/common/rule_group/gui/EditRuleGroupDialog.java
@@ -0,0 +1,66 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.common.rule_group.gui;
+
+import java.io.IOException;
+import com.warxim.petep.extension.internal.common.rule_group.Rule;
+import com.warxim.petep.extension.internal.common.rule_group.RuleGroup;
+import com.warxim.petep.extension.internal.common.rule_group.RuleGroupManager;
+import com.warxim.petep.gui.dialog.Dialogs;
+
+/** Dialog for editing of existing rule group. */
+public final class EditRuleGroupDialog extends RuleGroupDialog {
+ private final RuleGroup group;
+
+ /** Edit rule group dialog constructor. */
+ public EditRuleGroupDialog(RuleGroupManager> manager, RuleGroup group)
+ throws IOException {
+ super(manager, "Edit rule group", "Save");
+ this.group = group;
+
+ codeInput.setText(group.getCode());
+ nameInput.setText(group.getName());
+ }
+
+ @Override
+ protected boolean isValid() {
+ if (!super.isValid()) {
+ return false;
+ }
+
+ if (!group.getCode().equals(codeInput.getText()) && manager.contains(codeInput.getText())) {
+ Dialogs.createErrorDialog("Code used",
+ "The specified code is already used by other rule group.");
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ protected RuleGroup obtainResult() {
+ if (group.getCode().equals(codeInput.getText())
+ && group.getName().equals(nameInput.getText())) {
+ return null;
+ }
+
+ group.setCode(codeInput.getText());
+ group.setName(nameInput.getText());
+
+ return group;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/common/rule_group/gui/NewRuleGroupDialog.java b/src/main/java/com/warxim/petep/extension/internal/common/rule_group/gui/NewRuleGroupDialog.java
new file mode 100644
index 0000000..2d5c8f6
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/common/rule_group/gui/NewRuleGroupDialog.java
@@ -0,0 +1,51 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.common.rule_group.gui;
+
+import java.io.IOException;
+import com.warxim.petep.extension.internal.common.rule_group.Rule;
+import com.warxim.petep.extension.internal.common.rule_group.RuleGroup;
+import com.warxim.petep.extension.internal.common.rule_group.RuleGroupManager;
+import com.warxim.petep.gui.dialog.Dialogs;
+
+/** Dialog for creating new rule group. */
+public final class NewRuleGroupDialog extends RuleGroupDialog {
+ /** New rule group dialog constructor. */
+ public NewRuleGroupDialog(RuleGroupManager> manager) throws IOException {
+ super(manager, "New rule group", "Create");
+ }
+
+ @Override
+ protected boolean isValid() {
+ if (!super.isValid()) {
+ return false;
+ }
+
+ if (manager.contains(codeInput.getText())) {
+ Dialogs.createErrorDialog("Code used",
+ "The specified code is already used by other rule group.");
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ protected RuleGroup obtainResult() {
+ return new RuleGroup<>(codeInput.getText(), nameInput.getText());
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/common/rule_group/gui/RuleGroupController.java b/src/main/java/com/warxim/petep/extension/internal/common/rule_group/gui/RuleGroupController.java
new file mode 100644
index 0000000..a5cd924
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/common/rule_group/gui/RuleGroupController.java
@@ -0,0 +1,34 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.common.rule_group.gui;
+
+import com.warxim.petep.extension.internal.common.rule_group.Rule;
+import com.warxim.petep.extension.internal.common.rule_group.RuleGroup;
+
+/** Rule group controller. */
+public abstract class RuleGroupController {
+ protected final RuleGroup group;
+
+ /** Rule group controller constructor. */
+ public RuleGroupController(RuleGroup group) {
+ this.group = group;
+ }
+
+ public final RuleGroup getRuleGroup() {
+ return group;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/common/rule_group/gui/RuleGroupDialog.java b/src/main/java/com/warxim/petep/extension/internal/common/rule_group/gui/RuleGroupDialog.java
new file mode 100644
index 0000000..a2e5bd6
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/common/rule_group/gui/RuleGroupDialog.java
@@ -0,0 +1,58 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.common.rule_group.gui;
+
+import java.io.IOException;
+import com.warxim.petep.extension.internal.common.rule_group.Rule;
+import com.warxim.petep.extension.internal.common.rule_group.RuleGroup;
+import com.warxim.petep.extension.internal.common.rule_group.RuleGroupManager;
+import com.warxim.petep.gui.dialog.Dialogs;
+import com.warxim.petep.gui.dialog.SimpleInputDialog;
+import javafx.fxml.FXML;
+import javafx.scene.control.TextField;
+
+/** Rule group dialog. */
+public abstract class RuleGroupDialog extends SimpleInputDialog> {
+ @FXML
+ protected TextField nameInput;
+ @FXML
+ protected TextField codeInput;
+
+ protected final RuleGroupManager> manager;
+
+ /** Rule group dialog constructor. */
+ public RuleGroupDialog(RuleGroupManager> manager, String title, String okText)
+ throws IOException {
+ super("/fxml/extension/internal/common/rule_group/RuleGroupDialog.fxml", title, okText);
+ this.manager = manager;
+ }
+
+ @Override
+ protected boolean isValid() {
+ if (nameInput.getText().length() == 0) {
+ Dialogs.createErrorDialog("Name required", "You have to enter name.");
+ return false;
+ }
+
+ if (codeInput.getText().length() == 0) {
+ Dialogs.createErrorDialog("Code required", "You have to enter code.");
+ return false;
+ }
+
+ return true;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/common/rule_group/gui/RuleGroupsController.java b/src/main/java/com/warxim/petep/extension/internal/common/rule_group/gui/RuleGroupsController.java
new file mode 100644
index 0000000..d702a05
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/common/rule_group/gui/RuleGroupsController.java
@@ -0,0 +1,204 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.common.rule_group.gui;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+import java.util.ResourceBundle;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import com.warxim.petep.extension.internal.common.rule_group.Rule;
+import com.warxim.petep.extension.internal.common.rule_group.RuleGroup;
+import com.warxim.petep.extension.internal.common.rule_group.RuleGroupManager;
+import com.warxim.petep.extension.internal.common.rule_group.intercept.RuleInterceptorModule;
+import com.warxim.petep.gui.dialog.Dialogs;
+import com.warxim.petep.helper.ExtensionHelper;
+import com.warxim.petep.interceptor.module.InterceptorModule;
+import com.warxim.petep.util.GuiUtils;
+import javafx.event.ActionEvent;
+import javafx.fxml.FXML;
+import javafx.fxml.Initializable;
+import javafx.scene.Node;
+import javafx.scene.control.Label;
+import javafx.scene.control.TabPane;
+import javafx.util.Pair;
+
+/** Controller or rule groups (contains tabs of rule groups). */
+public abstract class RuleGroupsController implements Initializable {
+ private final ExtensionHelper helper;
+ private final RuleGroupManager> manager;
+ private final List> controllers;
+
+ private final String title;
+
+ @FXML
+ private TabPane tabs;
+ @FXML
+ private Label titleLabel;
+
+ /** Rule groups controller constrcutor. */
+ public RuleGroupsController(
+ String title,
+ RuleGroupManager> groupManager,
+ ExtensionHelper extensionHelper) {
+ this.title = title;
+ helper = extensionHelper;
+ manager = groupManager;
+ controllers = new ArrayList<>();
+ }
+
+ @Override
+ public void initialize(URL location, ResourceBundle resources) {
+ for (RuleGroup group : manager.getMap().values()) {
+ addGroupTab(group);
+ }
+
+ titleLabel.setText(title);
+ }
+
+ /** Adds new tab for rule group to the tab pane. */
+ private final void addGroupTab(RuleGroup group) {
+ try {
+ Pair> pair = createGroupTabNode(group);
+
+ controllers.add(pair.getValue());
+
+ GuiUtils.addTabToTabPane(tabs, group.getName(), pair.getKey());
+ } catch (IOException e) {
+ Logger.getGlobal().log(Level.SEVERE, "Could not load group tab!", e);
+ }
+ }
+
+ @FXML
+ private final void onNewButtonClick(ActionEvent event) {
+ try {
+ NewRuleGroupDialog dialog = new NewRuleGroupDialog<>(manager);
+
+ Optional> data = dialog.showAndWait();
+
+ if (!data.isPresent() || data.get() == null) {
+ return;
+ }
+
+ manager.add(data.get());
+
+ addGroupTab(data.get());
+ } catch (IOException e) {
+ Logger.getGlobal().log(Level.SEVERE, "Exception during openning of group dialog", e);
+ }
+ }
+
+ @FXML
+ private final void onEditButtonClick(ActionEvent event) {
+ RuleGroup group =
+ controllers.get(tabs.getSelectionModel().getSelectedIndex()).getRuleGroup();
+
+ if (group == null) {
+ return;
+ }
+
+ String oldCode = group.getCode();
+
+ try {
+ EditRuleGroupDialog dialog = new EditRuleGroupDialog<>(manager, group);
+
+ Optional> data = dialog.showAndWait();
+
+ if (!data.isPresent() || data.get() == null) {
+ return;
+ }
+
+ manager.remove(oldCode);
+ manager.add(data.get());
+
+ tabs.getSelectionModel().getSelectedItem().setText(data.get().getName());
+ } catch (IOException e) {
+ Logger.getGlobal().log(Level.SEVERE, "Exception during openning of rule group dialog", e);
+ }
+ }
+
+ @FXML
+ private final void onRemoveButtonClick(ActionEvent event) {
+ int index = tabs.getSelectionModel().getSelectedIndex();
+
+ RuleGroup group = controllers.get(index).getRuleGroup();
+
+ if (group == null) {
+ return;
+ }
+
+ if (isGroupUsed(group)) {
+ Dialogs.createErrorDialog("Rule group is used",
+ "Rule group is used by interceptors and cannot be deleted. Please, remove interceptors that use this group first.");
+ return;
+ }
+
+ // Does user really want to remove group?
+ if (!Dialogs.createYesOrNoDialog("Are you sure?",
+ "Do you really want to remove group '" + group.getName() + "'?")) {
+ return;
+ }
+
+ // Remove group
+ manager.remove(group.getCode());
+
+ // Remove controller
+ controllers.remove(index);
+
+ // Remove tab
+ tabs.getTabs().remove(index);
+ }
+
+ /** Check whether the group is used by any interceptor modules. */
+ private final boolean isGroupUsed(RuleGroup group) {
+ Class extends RuleInterceptorModule> moduleClass = getInterceptorModuleClass();
+
+ // Check modules in direction C2S (Client -> Server)
+ for (InterceptorModule module : helper.getInterceptorModulesC2S()) {
+ if (!(moduleClass.isInstance(module))) {
+ continue;
+ }
+
+ if (moduleClass.cast(module).getRuleGroup() == group) {
+ return true;
+ }
+ }
+
+ // Check modules in direction S2C (Client <- Server)
+ for (InterceptorModule module : helper.getInterceptorModulesS2C()) {
+ if (!(moduleClass.isInstance(module))) {
+ continue;
+ }
+
+ if (moduleClass.cast(module).getRuleGroup() == group) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /** Creates group tab node for rule group. */
+ protected abstract Pair> createGroupTabNode(RuleGroup group)
+ throws IOException;
+
+ /** Returns interceptor module class. */
+ protected abstract Class extends RuleInterceptorModule> getInterceptorModuleClass();
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/common/rule_group/gui/RuleGroupsGuiFactory.java b/src/main/java/com/warxim/petep/extension/internal/common/rule_group/gui/RuleGroupsGuiFactory.java
new file mode 100644
index 0000000..b68df78
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/common/rule_group/gui/RuleGroupsGuiFactory.java
@@ -0,0 +1,34 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This p am is free software: you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.common.rule_group.gui;
+
+import java.io.IOException;
+import javafx.fxml.FXMLLoader;
+import javafx.scene.Node;
+
+/** GUI factory that creates rule groups node (node for controlling groups of rules). */
+public class RuleGroupsGuiFactory {
+ private RuleGroupsGuiFactory() {}
+
+ public static Node createRoleGroupsNode(RuleGroupsController> controller) throws IOException {
+ FXMLLoader fxmlLoader = new FXMLLoader(RuleGroupsGuiFactory.class
+ .getResource("/fxml/extension/internal/common/rule_group/GroupsController.fxml"));
+
+ fxmlLoader.setController(controller);
+ return fxmlLoader.load();
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/common/rule_group/gui/RuleInterceptorConfigurator.java b/src/main/java/com/warxim/petep/extension/internal/common/rule_group/gui/RuleInterceptorConfigurator.java
new file mode 100644
index 0000000..819179b
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/common/rule_group/gui/RuleInterceptorConfigurator.java
@@ -0,0 +1,79 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.common.rule_group.gui;
+
+import java.io.IOException;
+import com.warxim.petep.extension.internal.common.rule_group.Rule;
+import com.warxim.petep.extension.internal.common.rule_group.RuleGroup;
+import com.warxim.petep.extension.internal.common.rule_group.RuleGroupManager;
+import com.warxim.petep.extension.internal.common.rule_group.config.RuleInterceptorConfig;
+import com.warxim.petep.gui.component.ConfigPane;
+import com.warxim.petep.gui.dialog.Dialogs;
+import javafx.fxml.FXML;
+import javafx.scene.control.ComboBox;
+import javafx.util.StringConverter;
+
+/** Rule interceptor configurator. */
+public final class RuleInterceptorConfigurator
+ extends ConfigPane {
+ @FXML
+ private ComboBox> groupInput;
+
+ private final RuleGroupManager> manager;
+
+ /** Rule interceptor configurator constructor. */
+ public RuleInterceptorConfigurator(RuleGroupManager> manager) throws IOException {
+ super("/fxml/extension/internal/common/rule_group/RuleInterceptorConfigurator.fxml");
+ this.manager = manager;
+
+ groupInput.getItems().setAll(manager.getList());
+
+ groupInput.setConverter(new StringConverter>() {
+ @Override
+ public String toString(RuleGroup group) {
+ return group == null ? "" : group.getName();
+ }
+
+ @Override
+ public RuleGroup fromString(String str) {
+ return null;
+ }
+ });
+
+ groupInput.getSelectionModel().selectLast();
+ }
+
+ @Override
+ public RuleInterceptorConfig getConfig() {
+ return new RuleInterceptorConfig(groupInput.getSelectionModel().getSelectedItem().getCode());
+ }
+
+ @Override
+ public void setConfig(RuleInterceptorConfig config) {
+ groupInput.getSelectionModel().select(manager.get(config.getRuleGroupCode()));
+ }
+
+ @Override
+ public boolean isValid() {
+ if (groupInput.getSelectionModel().getSelectedItem() == null) {
+ Dialogs.createErrorDialog("Replace group required", "You have to select replace group.");
+ return false;
+ }
+
+ return true;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/common/rule_group/intercept/RuleInterceptorModule.java b/src/main/java/com/warxim/petep/extension/internal/common/rule_group/intercept/RuleInterceptorModule.java
new file mode 100644
index 0000000..eacab57
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/common/rule_group/intercept/RuleInterceptorModule.java
@@ -0,0 +1,38 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.common.rule_group.intercept;
+
+import com.warxim.petep.extension.internal.common.rule_group.Rule;
+import com.warxim.petep.extension.internal.common.rule_group.RuleGroup;
+import com.warxim.petep.interceptor.factory.InterceptorModuleFactory;
+import com.warxim.petep.interceptor.module.InterceptorModule;
+
+/** Rule interceptor module. */
+public abstract class RuleInterceptorModule extends InterceptorModule {
+ /** Rule interceptor module constructor. */
+ public RuleInterceptorModule(
+ InterceptorModuleFactory factory,
+ String code,
+ String name,
+ String description,
+ boolean enabled) {
+ super(factory, code, name, description, enabled);
+ }
+
+ /** Returns rule group belonging to the interceptor. */
+ public abstract RuleGroup getRuleGroup();
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/connection_view/ConnectionViewController.java b/src/main/java/com/warxim/petep/extension/internal/connection_view/ConnectionViewController.java
new file mode 100644
index 0000000..97a8087
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/connection_view/ConnectionViewController.java
@@ -0,0 +1,90 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.connection_view;
+
+import java.net.URL;
+import java.util.ResourceBundle;
+import com.warxim.petep.core.connection.Connection;
+import com.warxim.petep.proxy.worker.Proxy;
+import javafx.beans.property.SimpleStringProperty;
+import javafx.collections.FXCollections;
+import javafx.event.ActionEvent;
+import javafx.fxml.FXML;
+import javafx.fxml.Initializable;
+import javafx.scene.control.ContextMenu;
+import javafx.scene.control.MenuItem;
+import javafx.scene.control.TableColumn;
+import javafx.scene.control.TableView;
+import javafx.scene.control.cell.PropertyValueFactory;
+
+/** Connection View controller. */
+public final class ConnectionViewController implements Initializable {
+ /** Target proxy. */
+ private final Proxy proxy;
+
+ @FXML
+ private TableView table;
+ @FXML
+ private TableColumn idColumn;
+ @FXML
+ private TableColumn infoColumn;
+
+ /** Connection View controller constructor. */
+ public ConnectionViewController(Proxy proxy) {
+ this.proxy = proxy;
+ }
+
+ @Override
+ public void initialize(URL location, ResourceBundle resources) {
+ refresh();
+
+ createContextMenu();
+ }
+
+ private void createContextMenu() {
+ MenuItem killItem = new MenuItem("Kill");
+ killItem.setOnAction(this::onKillConnectionClick);
+
+ ContextMenu menu = new ContextMenu();
+ menu.getItems().add(killItem);
+ table.setContextMenu(menu);
+ }
+
+ private void onKillConnectionClick(ActionEvent event) {
+ Connection connection = table.getSelectionModel().getSelectedItem();
+
+ if (connection == null) {
+ return;
+ }
+
+ connection.stop();
+ refresh();
+ }
+
+ public void refresh() {
+ idColumn.setCellValueFactory(new PropertyValueFactory<>("id"));
+ infoColumn.setCellValueFactory(cell -> new SimpleStringProperty(cell.getValue().toString()));
+
+ table.setItems(FXCollections.observableArrayList(proxy.getConnectionManager().getList()));
+ }
+
+ public void killAll() {
+ proxy.getConnectionManager().getList().forEach(Connection::stop);
+
+ refresh();
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/connection_view/ConnectionViewExtension.java b/src/main/java/com/warxim/petep/extension/internal/connection_view/ConnectionViewExtension.java
new file mode 100644
index 0000000..0991843
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/connection_view/ConnectionViewExtension.java
@@ -0,0 +1,94 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.connection_view;
+
+import java.io.IOException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import com.warxim.petep.common.ContextType;
+import com.warxim.petep.core.listener.PetepListener;
+import com.warxim.petep.extension.Extension;
+import com.warxim.petep.helper.ExtensionHelper;
+import com.warxim.petep.helper.GuiHelper;
+import com.warxim.petep.helper.PetepHelper;
+import javafx.application.Platform;
+import javafx.fxml.FXMLLoader;
+
+/** Connection view extension. */
+public final class ConnectionViewExtension extends Extension {
+ private ConnectionViewsController controller;
+
+ /** Connection view extension constructor. */
+ public ConnectionViewExtension(String path) {
+ super(path);
+ }
+
+ @Override
+ public void init(ExtensionHelper helper) {
+ if (helper.getContextType() != ContextType.GUI) {
+ return;
+ }
+
+ helper.registerPetepListener(new PetepListener() {
+ @Override
+ public void afterPrepare(PetepHelper helper) {
+ Platform.runLater(() -> controller.load(helper));
+ }
+
+ @Override
+ public void beforeStop(PetepHelper helper) {
+ Platform.runLater(controller::unload);
+ }
+ });
+ }
+
+ @Override
+ public void initGui(GuiHelper helper) {
+ try {
+ FXMLLoader fxmlLoader = new FXMLLoader(
+ getClass().getResource("/fxml/extension/internal/connection_view/ConnectionViews.fxml"));
+ controller = new ConnectionViewsController();
+ fxmlLoader.setController(controller);
+
+ helper.registerTab("Connections", fxmlLoader.load());
+ } catch (IOException e) {
+ Logger.getGlobal().log(Level.SEVERE, "Could not load connection view!", e);
+ }
+
+ helper.registerGuide(new ConnectionViewGuide());
+ }
+
+ @Override
+ public String getCode() {
+ return "connection_view";
+ }
+
+ @Override
+ public String getName() {
+ return "Connection View";
+ }
+
+ @Override
+ public String getDescription() {
+ return "Simple connection view.";
+ }
+
+ @Override
+ public String getVersion() {
+ return "1.0";
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/connection_view/ConnectionViewGuide.java b/src/main/java/com/warxim/petep/extension/internal/connection_view/ConnectionViewGuide.java
new file mode 100644
index 0000000..f69752a
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/connection_view/ConnectionViewGuide.java
@@ -0,0 +1,32 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.connection_view;
+
+import com.warxim.petep.gui.guide.Guide;
+
+/** Connection view guide. */
+public final class ConnectionViewGuide extends Guide {
+ @Override
+ public String getTitle() {
+ return "Connection View";
+ }
+
+ @Override
+ public String getHtml() {
+ return loadHtmlResource("/html/guide/internal/ConnectionViewGuide.html");
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/connection_view/ConnectionViewsController.java b/src/main/java/com/warxim/petep/extension/internal/connection_view/ConnectionViewsController.java
new file mode 100644
index 0000000..4a2b004
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/connection_view/ConnectionViewsController.java
@@ -0,0 +1,120 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.connection_view;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.ResourceBundle;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import com.warxim.petep.helper.PetepHelper;
+import com.warxim.petep.proxy.worker.Proxy;
+import com.warxim.petep.util.GuiUtils;
+import javafx.beans.value.ObservableValue;
+import javafx.event.ActionEvent;
+import javafx.fxml.FXML;
+import javafx.fxml.FXMLLoader;
+import javafx.fxml.Initializable;
+import javafx.scene.control.Button;
+import javafx.scene.control.ContextMenu;
+import javafx.scene.control.MenuItem;
+import javafx.scene.control.Tab;
+import javafx.scene.control.TabPane;
+
+/** Connection views controller. */
+public final class ConnectionViewsController implements Initializable {
+ private final List controllers;
+
+ @FXML
+ private TabPane tabs;
+ @FXML
+ private Button refreshButton;
+
+ public ConnectionViewsController() {
+ controllers = new ArrayList<>();
+ }
+
+ @Override
+ public void initialize(URL location, ResourceBundle resources) {
+ refreshButton.setDisable(true);
+ tabs.setVisible(false);
+
+ MenuItem killAllItem = new MenuItem("Kill All");
+ killAllItem.setOnAction(this::onKillAllClick);
+
+ ContextMenu menu = new ContextMenu();
+ menu.getItems().add(killAllItem);
+ tabs.setContextMenu(menu);
+ }
+
+ public void load(PetepHelper helper) {
+ // Create connection view tab for every proxy and its connection manager.
+ for (Proxy proxy : helper.getProxies()) {
+ try {
+ FXMLLoader fxmlLoader = new FXMLLoader(
+ getClass().getResource("/fxml/extension/internal/connection_view/ConnectionView.fxml"));
+
+ ConnectionViewController controller = new ConnectionViewController(proxy);
+ controllers.add(controller);
+ fxmlLoader.setController(controller);
+
+ GuiUtils.addTabToTabPane(tabs, proxy.getModule().getName(), fxmlLoader.load());
+ } catch (IOException e) {
+ Logger.getGlobal().log(Level.SEVERE, "Could not load connection view tab!", e);
+ }
+ }
+
+ // Refresh connection view of proxy when its tab gets selected.
+ tabs.getSelectionModel().selectedItemProperty().addListener(this::onTabSelectionChange);
+
+ refreshButton.setDisable(false);
+ tabs.setVisible(true);
+ }
+
+ public void unload() {
+ refreshButton.setDisable(true);
+ tabs.setVisible(false);
+ controllers.clear();
+ tabs.getTabs().clear();
+ }
+
+ private void onTabSelectionChange(
+ ObservableValue extends Tab> observable,
+ Tab oldTab,
+ Tab newTab) {
+ int index = tabs.getTabs().indexOf(newTab);
+ if (index != -1) {
+ controllers.get(index).refresh();
+ }
+ }
+
+ private void onKillAllClick(ActionEvent event) {
+ int index = tabs.getSelectionModel().getSelectedIndex();
+ if (index != -1) {
+ controllers.get(index).killAll();
+ }
+ }
+
+ @FXML
+ private void onRefreshButtonClick(ActionEvent event) {
+ for (ConnectionViewController controller : controllers) {
+ controller.refresh();
+ }
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/EHTTPPConfig.java b/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/EHTTPPConfig.java
new file mode 100644
index 0000000..48e3cdf
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/EHTTPPConfig.java
@@ -0,0 +1,73 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.external_http_proxy;
+
+/** External HTTP proxy configuration. */
+public final class EHTTPPConfig {
+ private String serverIp;
+ private int serverPort;
+
+ private String proxyIp;
+ private int proxyPort;
+
+ /** External HTTP configuration constructor. */
+ public EHTTPPConfig(String serverIp, int serverPort, String proxyIp, int proxyPort) {
+ this.serverIp = serverIp;
+ this.serverPort = serverPort;
+ this.proxyIp = proxyIp;
+ this.proxyPort = proxyPort;
+ }
+
+ public String getServerIp() {
+ return serverIp;
+ }
+
+ public void setServerIp(String ip) {
+ serverIp = ip;
+ }
+
+ public int getServerPort() {
+ return serverPort;
+ }
+
+ public void setServerPort(int port) {
+ serverPort = port;
+ }
+
+ public String getProxyIp() {
+ return proxyIp;
+ }
+
+ public void setProxyIp(String ip) {
+ proxyIp = ip;
+ }
+
+ public int getProxyPort() {
+ return proxyPort;
+ }
+
+ public void setProxyPort(int port) {
+ proxyPort = port;
+ }
+
+ public void set(String serverIp, int serverPort, String proxyIp, int proxyPort) {
+ this.serverIp = serverIp;
+ this.serverPort = serverPort;
+ this.proxyIp = proxyIp;
+ this.proxyPort = proxyPort;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/EHTTPPExtension.java b/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/EHTTPPExtension.java
new file mode 100644
index 0000000..12a272a
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/EHTTPPExtension.java
@@ -0,0 +1,140 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.external_http_proxy;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import com.warxim.petep.core.listener.PetepListener;
+import com.warxim.petep.core.pdu.PduQueue;
+import com.warxim.petep.extension.Extension;
+import com.warxim.petep.helper.ExtensionHelper;
+import com.warxim.petep.helper.GuiHelper;
+import com.warxim.petep.helper.PetepHelper;
+import com.warxim.petep.interceptor.worker.Interceptor;
+import com.warxim.petep.persistence.Storable;
+import javafx.fxml.FXMLLoader;
+
+/** External HTTP proxy extension. */
+public final class EHTTPPExtension extends Extension implements Storable {
+ private EHTTPPManager manager;
+ private EHTTPPConfig config;
+
+ /** External HTTP proxy extension constructor. */
+ public EHTTPPExtension(String path) {
+ super(path);
+ manager = null;
+ Logger.getGlobal().info("HTTP Proxy extension loaded.");
+ }
+
+ @Override
+ public void init(ExtensionHelper helper) {
+ Logger.getGlobal().info("HTTP Proxy extension registered.");
+
+ if (config == null) {
+ // Use defaults.
+ config = new EHTTPPConfig("127.0.0.1", 8181, "127.0.0.1", 8080);
+ }
+
+ helper.registerPetepListener(new PetepListener() {
+ /** Creates HTTP client for each HTTPP interceptor. */
+ private void processInterceptors(List interceptors) {
+ for (Interceptor interceptor : interceptors) {
+ if (interceptor instanceof EHTTPPInterceptor) {
+ if (manager == null) {
+ manager = new EHTTPPManager(config);
+ }
+
+ PduQueue queue = new PduQueue();
+
+ ((EHTTPPInterceptor) interceptor).setQueue(queue);
+
+ // Create HTTPP client for interceptor queue and set the following interceptor as
+ // a target.
+ manager.createClient(queue, interceptor.getId() + 1);
+ }
+ }
+ }
+
+ @Override
+ public void beforePrepare(PetepHelper helper) {
+ processInterceptors(helper.getInterceptorsC2S());
+ processInterceptors(helper.getInterceptorsS2C());
+
+ if (manager != null) {
+ manager.start(helper);
+ }
+ }
+
+ @Override
+ public void beforeStop(PetepHelper helper) {
+ if (manager != null) {
+ manager.stop();
+ manager = null;
+ }
+ }
+ });
+
+ helper.registerInterceptorModuleFactory(new EHTTPPInterceptorModuleFactory(this));
+ }
+
+ @Override
+ public void initGui(GuiHelper helper) {
+ try {
+ FXMLLoader fxmlLoader = new FXMLLoader(
+ getClass().getResource("/fxml/extension/internal/ehttp/HTTPPSettings.fxml"));
+ fxmlLoader.setController(new EHTTPPSettingsController(config));
+ helper.registerSettingsTab("HTTP Proxy", fxmlLoader.load());
+ Logger.getGlobal().info("HTTP Proxy extension GUI registered.");
+ } catch (IOException e) {
+ Logger.getGlobal().log(Level.SEVERE, "HTTP Proxy tab could not be created.", e);
+ }
+
+ helper.registerGuide(new EHTTPPGuide());
+ }
+
+ @Override
+ public String getCode() {
+ return "external_http_proxy";
+ }
+
+ @Override
+ public String getName() {
+ return "External HTTP Proxy";
+ }
+
+ @Override
+ public String getDescription() {
+ return "Internal extension for external HTTP proxy usage.";
+ }
+
+ @Override
+ public String getVersion() {
+ return "1.0";
+ }
+
+ @Override
+ public EHTTPPConfig saveStore() {
+ return config;
+ }
+
+ @Override
+ public void loadStore(EHTTPPConfig store) {
+ this.config = store;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/EHTTPPGuide.java b/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/EHTTPPGuide.java
new file mode 100644
index 0000000..cf670cc
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/EHTTPPGuide.java
@@ -0,0 +1,32 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.external_http_proxy;
+
+import com.warxim.petep.gui.guide.Guide;
+
+/** External HTTP Proxy guide. */
+public final class EHTTPPGuide extends Guide {
+ @Override
+ public String getTitle() {
+ return "External HTTP Proxy";
+ }
+
+ @Override
+ public String getHtml() {
+ return loadHtmlResource("/html/guide/internal/EHTTPPGuide.html");
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/EHTTPPInterceptor.java b/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/EHTTPPInterceptor.java
new file mode 100644
index 0000000..f8bee42
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/EHTTPPInterceptor.java
@@ -0,0 +1,56 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.external_http_proxy;
+
+import com.warxim.petep.core.pdu.PDU;
+import com.warxim.petep.core.pdu.PduQueue;
+import com.warxim.petep.helper.PetepHelper;
+import com.warxim.petep.interceptor.worker.Interceptor;
+
+/** External HTTP Proxy interceptor. */
+public final class EHTTPPInterceptor extends Interceptor {
+ private PduQueue queue;
+
+ /** External HTTP Proxy interceptor constructor. */
+ public EHTTPPInterceptor(int id, EHTTPPInterceptorModule module, PetepHelper helper) {
+ super(id, module, helper);
+ queue = null;
+ }
+
+ @Override
+ public boolean prepare() {
+ return true;
+ }
+
+ @Override
+ public boolean intercept(PDU pdu) {
+ if (queue != null && (pdu.hasTag("httpp") || !pdu.hasTag("no_httpp"))) {
+ queue.add(pdu);
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public void stop() {
+ // No action needed.
+ }
+
+ public void setQueue(PduQueue queue) {
+ this.queue = queue;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/EHTTPPInterceptorModule.java b/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/EHTTPPInterceptorModule.java
new file mode 100644
index 0000000..95f6ffe
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/EHTTPPInterceptorModule.java
@@ -0,0 +1,39 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.external_http_proxy;
+
+import com.warxim.petep.helper.PetepHelper;
+import com.warxim.petep.interceptor.module.InterceptorModule;
+import com.warxim.petep.interceptor.worker.Interceptor;
+
+/** External HTTP Proxy interceptor module. */
+public final class EHTTPPInterceptorModule extends InterceptorModule {
+ /** External HTTP Proxy interceptor module constructor. */
+ public EHTTPPInterceptorModule(
+ EHTTPPInterceptorModuleFactory factory,
+ String code,
+ String name,
+ String description,
+ boolean enabled) {
+ super(factory, code, name, description, enabled);
+ }
+
+ @Override
+ public Interceptor createInterceptor(int id, PetepHelper helper) {
+ return new EHTTPPInterceptor(id, this, helper);
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/EHTTPPInterceptorModuleFactory.java b/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/EHTTPPInterceptorModuleFactory.java
new file mode 100644
index 0000000..7358b14
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/EHTTPPInterceptorModuleFactory.java
@@ -0,0 +1,48 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.external_http_proxy;
+
+import com.warxim.petep.extension.Extension;
+import com.warxim.petep.interceptor.factory.InterceptorModuleFactory;
+import com.warxim.petep.interceptor.module.InterceptorModule;
+
+/** External HTTP Proxy interceptor module factory. */
+public final class EHTTPPInterceptorModuleFactory extends InterceptorModuleFactory {
+ /** External HTTP Proxy interceptor module factory constructor. */
+ public EHTTPPInterceptorModuleFactory(Extension extension) {
+ super(extension);
+ }
+
+ @Override
+ public String getName() {
+ return "External HTTP Proxy";
+ }
+
+ @Override
+ public String getCode() {
+ return "external_http_proxy";
+ }
+
+ @Override
+ public InterceptorModule createModule(
+ String code,
+ String name,
+ String description,
+ boolean enabled) {
+ return new EHTTPPInterceptorModule(this, code, name, description, enabled);
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/EHTTPPManager.java b/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/EHTTPPManager.java
new file mode 100644
index 0000000..f64ba88
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/EHTTPPManager.java
@@ -0,0 +1,75 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.external_http_proxy;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.logging.Logger;
+import com.warxim.petep.core.pdu.PduQueue;
+import com.warxim.petep.extension.internal.external_http_proxy.lighthttp.LightHttpClient;
+import com.warxim.petep.extension.internal.external_http_proxy.lighthttp.LightHttpServer;
+import com.warxim.petep.helper.PetepHelper;
+
+/** External HTTP Proxy manager. */
+public final class EHTTPPManager {
+ private final EHTTPPConfig config;
+ private final List clients;
+ private final ExecutorService executor;
+
+ private LightHttpServer server;
+
+ /** External HTTP Proxy manager constructor. */
+ public EHTTPPManager(EHTTPPConfig config) {
+ this.config = config;
+ clients = new ArrayList<>();
+ executor = Executors.newCachedThreadPool();
+ }
+
+ /** Starts HTTP server and clients. */
+ public void start(PetepHelper helper) {
+ // Create and start server.
+ server = new LightHttpServer(helper, config);
+ executor.submit(server::run);
+
+ // Start clients.
+ for (LightHttpClient client : clients) {
+ executor.submit(client::start);
+ }
+
+ Logger.getGlobal().info("HTTPP client-server started!");
+ }
+
+ /** Creates a client for specified queue. */
+ public void createClient(PduQueue queue, int targetId) {
+ clients.add(new LightHttpClient(config, queue, targetId));
+ }
+
+ /** Stops HTTP server and clients. */
+ public void stop() {
+ Logger.getGlobal().info("HTTPP client-server stopping...");
+
+ server.stop();
+
+ clients.parallelStream().forEach(LightHttpClient::stop);
+
+ executor.shutdownNow();
+
+ Logger.getGlobal().info("HTTPP client-server stopped!");
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/EHTTPPSettingsController.java b/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/EHTTPPSettingsController.java
new file mode 100644
index 0000000..67ce822
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/EHTTPPSettingsController.java
@@ -0,0 +1,93 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.external_http_proxy;
+
+import java.net.URL;
+import java.util.ResourceBundle;
+import com.warxim.petep.gui.dialog.Dialogs;
+import javafx.event.ActionEvent;
+import javafx.fxml.FXML;
+import javafx.fxml.Initializable;
+import javafx.scene.control.TextField;
+
+/** External HTTP Proxy settings controller. */
+public final class EHTTPPSettingsController implements Initializable {
+ private final EHTTPPConfig config;
+
+ @FXML
+ private TextField serverIp;
+ @FXML
+ private TextField serverPort;
+ @FXML
+ private TextField proxyIp;
+ @FXML
+ private TextField proxyPort;
+
+ public EHTTPPSettingsController(EHTTPPConfig config) {
+ this.config = config;
+ }
+
+ @Override
+ public void initialize(URL location, ResourceBundle resources) {
+ serverIp.setText(config.getServerIp());
+ serverPort.setText(String.valueOf(config.getServerPort()));
+ proxyIp.setText(config.getProxyIp());
+ proxyPort.setText(String.valueOf(config.getProxyPort()));
+ }
+
+ @FXML
+ private void onSaveButtonClick(ActionEvent event) {
+ String sIp = serverIp.getText();
+ if (sIp.length() == 0) {
+ Dialogs.createErrorDialog("Server IP required", "You have to enter server IP.");
+ return;
+ }
+
+ int sPort;
+ try {
+ sPort = Integer.parseInt(serverPort.getText());
+ if (sPort <= 0 || sPort > 65535) {
+ Dialogs.createErrorDialog("Invalid server port",
+ "Server port has to be number (1 - 65535).");
+ }
+ } catch (NumberFormatException e) {
+ Dialogs.createErrorDialog("Invalid server port", "Server port has to be number.");
+ return;
+ }
+
+ String pIp = proxyIp.getText();
+ if (pIp.length() == 0) {
+ Dialogs.createErrorDialog("Proxy IP required", "You have to enter proxy IP.");
+ return;
+ }
+
+ int pPort;
+ try {
+ pPort = Integer.parseInt(proxyPort.getText());
+ if (pPort <= 0 || pPort > 65535) {
+ Dialogs.createErrorDialog("Invalid proxy port", "Proxy port has to be number (1 - 65535).");
+ }
+ } catch (NumberFormatException e) {
+ Dialogs.createErrorDialog("Invalid proxy port", "Proxy port has to be number.");
+ return;
+ }
+
+ config.set(sIp, sPort, pIp, pPort);
+
+ Dialogs.createInfoDialog("HTTP Proxy saved", "HTTP Proxy has been saved!");
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/lighthttp/LightHttpClient.java b/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/lighthttp/LightHttpClient.java
new file mode 100644
index 0000000..d95d86e
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/lighthttp/LightHttpClient.java
@@ -0,0 +1,201 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.external_http_proxy.lighthttp;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.ConnectException;
+import java.net.Socket;
+import java.net.SocketException;
+import java.net.UnknownHostException;
+import java.nio.ByteBuffer;
+import java.util.Map;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import com.warxim.petep.core.pdu.PDU;
+import com.warxim.petep.core.pdu.PduDestination;
+import com.warxim.petep.core.pdu.PduQueue;
+import com.warxim.petep.extension.internal.external_http_proxy.EHTTPPConfig;
+
+/**
+ * Light HTTP client.
+ */
+public final class LightHttpClient {
+ private final byte[] firstLineStart;
+
+ private final EHTTPPConfig config;
+
+ private final PduQueue queue;
+
+ private final int targetInterceptorId;
+
+ private boolean running;
+
+ /** Light HTTP client constructor. */
+ public LightHttpClient(EHTTPPConfig config, PduQueue queue, int targetId) {
+ this.config = config;
+ this.queue = queue;
+ this.targetInterceptorId = targetId;
+
+ // Create first line.
+ byte[] serverIpBytes = config.getServerIp().getBytes();
+ byte[] serverPortBytes = String.valueOf(config.getServerPort()).getBytes();
+
+ ByteBuffer buffer = ByteBuffer.allocate(LightHttpConstant.FIRST_LINE_START.length + 2
+ + serverIpBytes.length + serverPortBytes.length);
+ buffer.put(LightHttpConstant.FIRST_LINE_START);
+ buffer.put(serverIpBytes);
+ buffer.put(LightHttpConstant.COLON);
+ buffer.put(serverPortBytes);
+ buffer.put(LightHttpConstant.SLASH);
+
+ firstLineStart = buffer.array();
+ }
+
+ public void start() {
+ try {
+ running = true;
+
+ work();
+ } catch (InterruptedException e) {
+ // Shutdown
+ Thread.currentThread().interrupt();
+ }
+ }
+
+ public void stop() {
+ running = false;
+ }
+
+ private void work() throws InterruptedException {
+ PDU pdu;
+
+ while (running && (pdu = queue.take()) != null) {
+ while (running && pdu != null) {
+ try (Socket socket = new Socket(config.getProxyIp(), config.getProxyPort());
+ OutputStream out = socket.getOutputStream();
+ InputStream in = socket.getInputStream()) {
+ writePduToOutput(pdu, out);
+ readFromInput(in);
+
+ pdu = null;
+ } catch (UnknownHostException e) {
+ Logger.getGlobal().log(Level.SEVERE, "Unknown host exception in HTTP Proxy!", e);
+ } catch (ConnectException e) {
+ Logger.getGlobal().log(Level.SEVERE, "Could not connect to HTTP proxy!", e);
+ } catch (SocketException e) {
+ Logger.getGlobal().log(Level.SEVERE, "Could not connect to HTTP proxy!", e);
+ // Interrupted
+ return;
+ } catch (IOException e) {
+ Logger.getGlobal().log(Level.SEVERE, "IO exception in HTTP Proxy!", e);
+ }
+ }
+ }
+ }
+
+ private void readFromInput(InputStream in) throws IOException {
+ // Read response
+ while (LightHttpUtils.readByte(in) != LightHttpConstant.CR) {
+ // Read until \r
+ }
+
+ LightHttpUtils.skipNBytes(3, in); // \n\r\n
+ }
+
+ private void writePduToOutput(PDU pdu, OutputStream out) throws IOException {
+ // First line
+ writeFirstLineToOutput(pdu, out);
+
+ // Tags
+ writeTagsToOutput(pdu.getTags(), out);
+
+ // Metadata
+ writeMetadataToOutput(
+ pdu.getProxy().getModule().getFactory().getSerializer().serializePduMetadata(pdu), out);
+
+ // Content length
+ out.write(LightHttpConstant.CONTENT_LENGTH);
+ out.write(String.valueOf(pdu.getSize()).getBytes());
+ out.write(LightHttpConstant.HEADER_END);
+
+ // Content type
+ out.write(LightHttpConstant.CONTENT_TYPE_CHARSET);
+ out.write(pdu.getCharset().name().getBytes());
+
+ // End headers
+ out.write(LightHttpConstant.HEADERS_END);
+
+ // Data
+ out.write(pdu.getBuffer(), 0, pdu.getSize());
+ }
+
+ private void writeFirstLineToOutput(PDU pdu, OutputStream out) throws IOException {
+ // First line start
+ out.write(firstLineStart);
+
+ // Proxy
+ out.write(pdu.getProxy().getModule().getCode().getBytes());
+ out.write(LightHttpConstant.SLASH);
+ // Connection
+ out.write(String.valueOf(pdu.getConnection().getId()).getBytes());
+ out.write(LightHttpConstant.SLASH);
+ // Target Interceptor Id
+ out.write(String.valueOf(targetInterceptorId).getBytes());
+ out.write(LightHttpConstant.SLASH);
+ // Destination
+ if (pdu.getDestination() == PduDestination.CLIENT) {
+ out.write(LightHttpConstant.S2C);
+ } else {
+ out.write(LightHttpConstant.C2S);
+ }
+
+ // End first line
+ out.write(LightHttpConstant.FIRST_LINE_END);
+ }
+
+ private void writeTagsToOutput(Set tags, OutputStream out) throws IOException {
+ if (!tags.isEmpty()) {
+ out.write(LightHttpConstant.TAGS_HEADER_BYTES);
+
+ int remaining = tags.size();
+ for (String tag : tags) {
+ out.write(tag.getBytes());
+
+ if (--remaining != 0) {
+ out.write(LightHttpConstant.TAGS_SEPARATOR);
+ }
+ }
+ out.write(LightHttpConstant.HEADER_END);
+ }
+ }
+
+ private void writeMetadataToOutput(Map serializedMetaData, OutputStream out)
+ throws IOException {
+ if (serializedMetaData != null) {
+ for (var item : serializedMetaData.entrySet()) {
+ out.write(LightHttpConstant.METADATA_HEADER_START_BYTES);
+ out.write(item.getKey().getBytes());
+ out.write(LightHttpConstant.HEADER_COLON);
+ out.write(item.getValue().getBytes());
+ out.write(LightHttpConstant.HEADER_END);
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/lighthttp/LightHttpConstant.java b/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/lighthttp/LightHttpConstant.java
new file mode 100644
index 0000000..46ef20c
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/lighthttp/LightHttpConstant.java
@@ -0,0 +1,67 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.external_http_proxy.lighthttp;
+
+public final class LightHttpConstant {
+ /*
+ * BYTES
+ */
+ public static final byte COLON = (byte) 0x3A;
+ public static final byte SLASH = (byte) 0x2F;
+ public static final byte C2S = (byte) 0x73;
+ public static final byte S2C = (byte) 0x63;
+ public static final byte CR = (byte) 0x0D;
+ public static final byte LF = (byte) 0x0A;
+ public static final byte TAGS_SEPARATOR = ',';
+
+ /*
+ * STRINGS
+ */
+ public static final String TAGS_HEADER = "T";
+ public static final String CONTENT_TYPE_HEADER = "Content-Type";
+ public static final String CONTENT_LENGTH_HEADER = "Content-Length";
+ public static final String METADATA_HEADER_START = "M-";
+
+ /*
+ * BYTE ARRAYS
+ */
+ public static final byte[] FIRST_LINE_START = "POST http://".getBytes();
+ public static final byte[] FIRST_LINE_END = " HTTP/1.0\r\n".getBytes();
+ public static final byte[] CONTENT_LENGTH = (CONTENT_LENGTH_HEADER + ": ").getBytes();
+ public static final byte[] CONTENT_TYPE_CHARSET =
+ (CONTENT_TYPE_HEADER + ": text/plain; charset=").getBytes();
+ public static final byte[] TAGS_HEADER_BYTES = (TAGS_HEADER + ": ").getBytes();
+ public static final byte[] METADATA_HEADER_START_BYTES = METADATA_HEADER_START.getBytes();
+ public static final byte[] HEADER_COLON = ": ".getBytes();
+ public static final byte[] HEADER_END = "\r\n".getBytes();
+ public static final byte[] HEADERS_END = "\r\n\r\n".getBytes();
+
+ /*
+ * RESPONSES
+ */
+ public static final byte[] RESPONSE_OK = "HTTP/1.0 OK\r\n\r\n".getBytes();
+ public static final byte[] RESPONSE_WRONG_PROXY =
+ "HTTP/1.0 404 Proxy not found\r\n\r\n".getBytes();
+ public static final byte[] RESPONSE_WRONG_CONNECTION =
+ "HTTP/1.0 404 Connection not found\r\n\r\n".getBytes();
+ public static final byte[] RESPONSE_WRONG_INTERCEPTOR =
+ "HTTP/1.0 404 Interceptor not found\r\n\r\n".getBytes();
+ public static final byte[] RESPONSE_DESERIALIZATION_ERROR =
+ "HTTP/1.0 500 Deserialization Error\r\n\r\n".getBytes();
+
+ private LightHttpConstant() {}
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/lighthttp/LightHttpServer.java b/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/lighthttp/LightHttpServer.java
new file mode 100644
index 0000000..c5c2c93
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/lighthttp/LightHttpServer.java
@@ -0,0 +1,357 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.external_http_proxy.lighthttp;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.InetAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketException;
+import java.net.UnknownHostException;
+import java.nio.charset.Charset;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import com.warxim.petep.core.connection.Connection;
+import com.warxim.petep.core.pdu.PDU;
+import com.warxim.petep.core.pdu.PduDestination;
+import com.warxim.petep.extension.internal.external_http_proxy.EHTTPPConfig;
+import com.warxim.petep.extension.internal.external_http_proxy.lighthttp.exception.InvalidDataException;
+import com.warxim.petep.helper.PetepHelper;
+import com.warxim.petep.proxy.worker.Proxy;
+
+/** Light HTTP server. */
+public final class LightHttpServer {
+
+ private final PetepHelper helper;
+
+ private final EHTTPPConfig config;
+
+ private ServerSocket socket;
+
+ private boolean running;
+
+ private final int lastInterceptorC2SIndex;
+ private final int lastInterceptorS2CIndex;
+
+ /** Light HTTP server constructor. */
+ public LightHttpServer(PetepHelper helper, EHTTPPConfig config) {
+ this.helper = helper;
+ this.config = config;
+ this.lastInterceptorC2SIndex = helper.getInterceptorsC2S().size() + 1;
+ this.lastInterceptorS2CIndex = helper.getInterceptorsS2C().size() + 1;
+ }
+
+ /** Runs server. */
+ public void run() {
+ try {
+ socket =
+ new ServerSocket(config.getServerPort(), 0, InetAddress.getByName(config.getServerIp()));
+
+ Logger.getGlobal()
+ .info("HTTP Server started on " + config.getServerIp() + ":" + config.getServerPort()
+ + "!");
+
+ running = true;
+
+ while (running) {
+ accept();
+ }
+ } catch (UnknownHostException e) {
+ Logger.getGlobal()
+ .log(Level.SEVERE, "Could not start HTTP server! (The host is unknown!)", e);
+ } catch (SocketException e) {
+ // Interrupted
+ } catch (IOException e) {
+ Logger.getGlobal().log(Level.SEVERE, "Could not start HTTP server!", e);
+ } finally {
+ try {
+ if (socket != null) {
+ socket.close();
+ }
+ } catch (IOException e) {
+ Logger.getGlobal().log(Level.SEVERE, "Could not close HTTP server!", e);
+ }
+ }
+ Logger.getGlobal().log(Level.INFO, "HTTP server stopped.");
+ }
+
+ /** Stops server. */
+ public void stop() {
+ running = false;
+
+ try {
+ if (socket != null) {
+ socket.close();
+ }
+ } catch (IOException e) {
+ Logger.getGlobal().log(Level.SEVERE, "Could not close HTTP server!", e);
+ }
+ }
+
+ /** Accepts new connections. */
+ private void accept() {
+ try (Socket client = socket.accept();
+ InputStream in = client.getInputStream();
+ OutputStream out = client.getOutputStream()) {
+ try {
+ process(in, out);
+ } catch (InvalidDataException e) {
+ out.write(e.getMessageBytes());
+ }
+ } catch (SocketException e) {
+ // Interrupted
+ } catch (Exception e) {
+ Logger.getGlobal().log(Level.SEVERE, "Exception during HTTP read / write!", e);
+ }
+ }
+
+ private Proxy readProxy(InputStream in, StringBuilder builder)
+ throws IOException, InvalidDataException {
+ int currentByte;
+ // Read proxy code
+ while ((currentByte = LightHttpUtils.readByte(in)) != 0x2F) {
+ builder.append((char) currentByte);
+ }
+
+ Proxy proxy = helper.getProxy(builder.toString());
+ if (proxy == null) {
+ throw new InvalidDataException(LightHttpConstant.RESPONSE_WRONG_PROXY);
+ }
+
+ return proxy;
+ }
+
+ private Connection readConnection(InputStream in, StringBuilder builder, Proxy proxy)
+ throws IOException, InvalidDataException {
+ int currentByte;
+ // Read client ID
+ while ((currentByte = LightHttpUtils.readByte(in)) != 0x2F) {
+ builder.append((char) currentByte);
+ }
+
+ Connection connection = proxy.getConnectionManager().get(Integer.parseInt(builder.toString()));
+
+ if (connection == null) {
+ throw new InvalidDataException(LightHttpConstant.RESPONSE_WRONG_CONNECTION);
+ }
+
+ return connection;
+ }
+
+ private PduDestination readDestination(InputStream in) throws IOException {
+ PduDestination destination;
+
+ if (LightHttpUtils.readByte(in) == LightHttpConstant.S2C) {
+ destination = PduDestination.CLIENT;
+ } else {
+ destination = PduDestination.SERVER;
+ }
+
+ return destination;
+ }
+
+ private int readTargetInterceptor(InputStream in, StringBuilder builder) throws IOException {
+ int currentByte;
+ // Read target interceptor id
+ while ((currentByte = LightHttpUtils.readByte(in)) != 0x2F) {
+ // End of stream reached.
+ builder.append((char) currentByte);
+ }
+ return Integer.parseInt(builder.toString());
+ }
+
+ private void validateTargetInterceptor(PduDestination destination, int targetInterceptorId)
+ throws InvalidDataException {
+ if (targetInterceptorId < 0
+ || (destination == PduDestination.SERVER && targetInterceptorId >= lastInterceptorC2SIndex)
+ || (destination == PduDestination.CLIENT
+ && targetInterceptorId >= lastInterceptorS2CIndex)) {
+ throw new InvalidDataException(LightHttpConstant.RESPONSE_WRONG_INTERCEPTOR);
+ }
+ }
+
+
+ /**
+ * Reads data from client input stream. TODO: change skip to skipNBytes in Java 12.
+ *
+ * @throws InvalidDataException
+ */
+ private void process(InputStream in, OutputStream out) throws IOException, InvalidDataException {
+ // Skip POST /
+ LightHttpUtils.skipNBytes(6, in);
+
+ StringBuilder builder = new StringBuilder();
+
+ // Proxy
+ Proxy proxy = readProxy(in, builder);
+
+ builder.setLength(0);
+
+ // Connection
+ Connection connection = readConnection(in, builder, proxy);
+
+ builder.setLength(0);
+
+ int targetInterceptorId = readTargetInterceptor(in, builder);
+
+ // Read destination
+ PduDestination destination = readDestination(in);
+
+ // Check validity of interceptor id.
+ validateTargetInterceptor(destination, targetInterceptorId);
+
+ // Skip HTTP/1.0\r\n
+ LightHttpUtils.skipNBytes(11, in);
+
+ // Read headers
+ Map serializedMetaData = new HashMap<>();
+ Set tags = new HashSet<>();
+ Charset charset = null;
+ int contentLength = 0;
+
+ int currentByte;
+
+ while (true) {
+ // Read first character to detect end of headers
+ currentByte = LightHttpUtils.readByte(in);
+
+ if (currentByte == LightHttpConstant.CR) {
+ // skip \n\r\n
+ LightHttpUtils.skipNBytes(1, in);
+ break;
+ }
+
+ // Read key
+ builder.setLength(0);
+ builder.append((char) currentByte);
+ while ((currentByte = LightHttpUtils.readByte(in)) != LightHttpConstant.COLON) {
+ builder.append((char) currentByte);
+ }
+
+ String temp = builder.toString();
+
+
+ // Skip space after :
+ LightHttpUtils.skipNBytes(1, in);
+
+ builder.setLength(0);
+
+ if (LightHttpConstant.CONTENT_LENGTH_HEADER.equals(temp)) {
+ contentLength = readContentLength(in, builder);
+ } else if (LightHttpConstant.CONTENT_TYPE_HEADER.equals(temp)) {
+ charset = readCharset(in, builder);
+ } else if (LightHttpConstant.TAGS_HEADER.equals(temp)) {
+ readTags(in, builder, tags);
+ } else if (temp.startsWith(LightHttpConstant.METADATA_HEADER_START)) {
+ serializedMetaData.put(temp.substring(2), readMetadata(in, builder));
+ } else {
+ skipHeader(in);
+ }
+
+ // Skip \n
+ LightHttpUtils.skipNBytes(1, in);
+ }
+
+ // Read data.
+ byte[] buffer = in.readNBytes(contentLength);
+
+ // Create PDU.
+ PDU pdu = proxy.getModule()
+ .getFactory()
+ .getDeserializer()
+ .deserializePdu(proxy, connection, destination, buffer, contentLength, tags,
+ serializedMetaData);
+
+ if (pdu == null) {
+ out.write(LightHttpConstant.RESPONSE_DESERIALIZATION_ERROR);
+ return;
+ }
+
+ // Set charset
+ if (charset != null) {
+ pdu.setCharset(charset);
+ }
+
+ // Process PDU in PETEP.
+ helper.processPdu(pdu, targetInterceptorId);
+
+ out.write(LightHttpConstant.RESPONSE_OK);
+ }
+
+ private void skipHeader(InputStream in) throws IOException {
+ // Unknown header, skip value.
+ while (LightHttpUtils.readByte(in) != LightHttpConstant.CR) {
+ // Read until \r
+ }
+ }
+
+ private int readContentLength(InputStream in, StringBuilder builder) throws IOException {
+ int currentByte;
+ // Read until \r
+ while ((currentByte = LightHttpUtils.readByte(in)) != LightHttpConstant.CR) {
+ builder.append((char) currentByte);
+ }
+
+ return Integer.parseInt(builder.toString());
+ }
+
+ private String readMetadata(InputStream in, StringBuilder builder) throws IOException {
+ int currentByte;
+ // Read until \r
+ while ((currentByte = LightHttpUtils.readByte(in)) != LightHttpConstant.CR) {
+ builder.append((char) currentByte);
+ }
+
+ return builder.toString();
+ }
+
+ private void readTags(InputStream in, StringBuilder builder, Set tags)
+ throws IOException {
+ int currentByte;
+ // Read until \r
+ while ((currentByte = LightHttpUtils.readByte(in)) != LightHttpConstant.CR) {
+ if (currentByte == LightHttpConstant.TAGS_SEPARATOR) {
+ tags.add(builder.toString());
+ builder.setLength(0);
+ } else {
+ builder.append((char) currentByte);
+ }
+ }
+
+ tags.add(builder.toString());
+ }
+
+ private Charset readCharset(InputStream in, StringBuilder builder) throws IOException {
+ // Skip text/plain; charset=
+ LightHttpUtils.skipNBytes(20, in);
+
+ int currentByte;
+
+ // Read until 0x0D = \r
+ while ((currentByte = LightHttpUtils.readByte(in)) != LightHttpConstant.CR) {
+ builder.append((char) currentByte);
+ }
+
+ return Charset.forName(builder.toString());
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/lighthttp/LightHttpUtils.java b/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/lighthttp/LightHttpUtils.java
new file mode 100644
index 0000000..42527a5
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/lighthttp/LightHttpUtils.java
@@ -0,0 +1,40 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.external_http_proxy.lighthttp;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+public final class LightHttpUtils {
+ private LightHttpUtils() {}
+
+ public static int readByte(InputStream in) throws IOException {
+ int c = in.read();
+
+ if (c == -1) {
+ throw new IOException("End of stream reached!");
+ }
+
+ return c;
+ }
+
+ public static void skipNBytes(int n, InputStream in) throws IOException {
+ if (in.skip(n) != n) {
+ throw new IOException("Could not skip n bytes!");
+ }
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/lighthttp/exception/InvalidDataException.java b/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/lighthttp/exception/InvalidDataException.java
new file mode 100644
index 0000000..f50e28e
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/lighthttp/exception/InvalidDataException.java
@@ -0,0 +1,30 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.external_http_proxy.lighthttp.exception;
+
+public class InvalidDataException extends Exception {
+ private static final long serialVersionUID = 1L;
+ private final byte[] message;
+
+ public InvalidDataException(byte[] message) {
+ this.message = message;
+ }
+
+ public byte[] getMessageBytes() {
+ return message;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/http/HttpExtension.java b/src/main/java/com/warxim/petep/extension/internal/http/HttpExtension.java
new file mode 100644
index 0000000..2fcc57a
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/http/HttpExtension.java
@@ -0,0 +1,108 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.http;
+
+import java.util.logging.Logger;
+import com.warxim.petep.extension.Extension;
+import com.warxim.petep.extension.ExtensionInitListener;
+import com.warxim.petep.extension.internal.http.modifier.remove_header.RemoveHeaderModifierFactory;
+import com.warxim.petep.extension.internal.http.proxy.HttpProxyModuleFactory;
+import com.warxim.petep.extension.internal.http.tagger.has_header.HasHeaderSubruleFactory;
+import com.warxim.petep.extension.internal.http.tagger.is_http.IsHttpSubruleFactory;
+import com.warxim.petep.extension.internal.http.tagger.is_websocket.IsWebSocketSubruleFactory;
+import com.warxim.petep.extension.internal.modifier.ModifierApi;
+import com.warxim.petep.extension.internal.tagger.TaggerApi;
+import com.warxim.petep.helper.ExtensionHelper;
+import com.warxim.petep.helper.GuiHelper;
+
+public final class HttpExtension extends Extension implements ExtensionInitListener {
+ /** HTTP extension constructor. */
+ public HttpExtension(String path) {
+ super(path);
+
+ Logger.getGlobal().info("HTTP extension loaded.");
+ }
+
+ /** Initializes HTTP extension (registers HTTP proxy module). */
+ @Override
+ public void init(ExtensionHelper helper) {
+ helper.registerProxyModuleFactory(new HttpProxyModuleFactory(this));
+
+ Logger.getGlobal().info("HTTP extension registered.");
+ }
+
+ @Override
+ public void initGui(GuiHelper helper) {
+ // No action needed.
+ }
+
+ @Override
+ public String getCode() {
+ return "http";
+ }
+
+ @Override
+ public String getName() {
+ return "HTTP extension";
+ }
+
+ @Override
+ public String getDescription() {
+ return "HTTP extension adds HTTP proxy to PETEP.";
+ }
+
+ @Override
+ public String getVersion() {
+ return "1.0";
+ }
+
+ @Override
+ public void beforeInit(ExtensionHelper helper) {
+ // Get TagSubruleModule registrator.
+ Extension tagger = helper.getExtension("tagger");
+
+ // Register HasHeader subrule module.
+ if (tagger != null) {
+ TaggerApi registrator = ((TaggerApi) tagger);
+ if (!registrator.registerSubruleFactory(new HasHeaderSubruleFactory())) {
+ Logger.getGlobal().info("HTTP Extension could not register HasHeader tag subrule.");
+ }
+
+ if (!registrator.registerSubruleFactory(new IsWebSocketSubruleFactory())) {
+ Logger.getGlobal().info("HTTP Extension could not register IsWebsocket tag subrule.");
+ }
+
+ if (!registrator.registerSubruleFactory(new IsHttpSubruleFactory())) {
+ Logger.getGlobal().info("HTTP Extension could not register IsHTTP tag subrule.");
+ }
+ }
+
+ // Get ModifierModule registrator.
+ Extension modifier = helper.getExtension("modifier");
+
+ // Register RemoveHeader module.
+ if (modifier != null && ((ModifierApi) modifier)
+ .registerModifierFactory(new RemoveHeaderModifierFactory())) {
+ Logger.getGlobal().info("HTTP Extension registered RemoveHeader modifier.");
+ }
+ }
+
+ @Override
+ public void afterInit(ExtensionHelper helper) {
+ // No action needed.
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/http/gui/HttpMetadataPane.java b/src/main/java/com/warxim/petep/extension/internal/http/gui/HttpMetadataPane.java
new file mode 100644
index 0000000..b99c270
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/http/gui/HttpMetadataPane.java
@@ -0,0 +1,340 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.http.gui;
+
+import java.io.IOException;
+import java.util.HashMap;
+import com.warxim.petep.core.connection.Connection;
+import com.warxim.petep.core.pdu.PDU;
+import com.warxim.petep.core.pdu.PduDestination;
+import com.warxim.petep.extension.internal.http.pdu.HttpPdu;
+import com.warxim.petep.extension.internal.http.pdu.HttpRequestPdu;
+import com.warxim.petep.extension.internal.http.pdu.HttpResponsePdu;
+import com.warxim.petep.extension.internal.http.pdu.Opcode;
+import com.warxim.petep.extension.internal.http.pdu.WebSocketPdu;
+import com.warxim.petep.gui.component.PduMetadataPane;
+import com.warxim.petep.gui.dialog.Dialogs;
+import com.warxim.petep.proxy.worker.Proxy;
+import com.warxim.petep.util.BytesUtils;
+import javafx.beans.binding.Bindings;
+import javafx.beans.value.ObservableValue;
+import javafx.collections.FXCollections;
+import javafx.collections.MapChangeListener;
+import javafx.collections.ObservableList;
+import javafx.collections.ObservableMap;
+import javafx.event.ActionEvent;
+import javafx.fxml.FXML;
+import javafx.scene.control.CheckBox;
+import javafx.scene.control.ComboBox;
+import javafx.scene.control.TableColumn;
+import javafx.scene.control.TableView;
+import javafx.scene.control.TextField;
+import javafx.scene.layout.AnchorPane;
+import javafx.util.Pair;
+
+public final class HttpMetadataPane extends PduMetadataPane {
+ /*
+ * HTTP
+ */
+ @FXML
+ private AnchorPane httpPane;
+
+ @FXML
+ private TextField httpVersionInput;
+
+ @FXML
+ private TableView httpHeadersInput;
+
+ @FXML
+ private TableColumn httpHeaderNameColumn;
+ @FXML
+ private TableColumn httpHeaderValueColumn;
+
+ @FXML
+ private AnchorPane httpRequestPane;
+
+ @FXML
+ private TextField httpMethodInput;
+
+ @FXML
+ private TextField httpPathInput;
+
+ @FXML
+ private AnchorPane httpResponsePane;
+
+ @FXML
+ private TextField httpStatusCodeInput;
+
+ @FXML
+ private TextField httpStatusMessageInput;
+
+ private final ObservableMap httpHeaderMap;
+
+ private final ObservableList httpHeaderNameList;
+
+ /*
+ * WEBSOCKET
+ */
+ @FXML
+ private AnchorPane websocketPane;
+
+ @FXML
+ private CheckBox websocketFinInput;
+
+ @FXML
+ private CheckBox websocketRsv1Input;
+
+ @FXML
+ private CheckBox websocketRsv2Input;
+
+ @FXML
+ private CheckBox websocketRsv3Input;
+
+ @FXML
+ private CheckBox websocketMaskedInput;
+
+ @FXML
+ private ComboBox websocketOpcodeInput;
+
+ @FXML
+ private TextField websocketMaskInput;
+
+ public HttpMetadataPane() throws IOException {
+ super("/fxml/extension/internal/http/HttpPduMetadata.fxml");
+
+ httpHeaderMap = FXCollections.observableHashMap();
+ httpHeaderNameList = FXCollections.observableArrayList();
+
+ httpHeaderMap.addListener(this::onHeaderMapChange);
+
+ httpHeaderNameColumn.setCellValueFactory(cd -> Bindings.createStringBinding(cd::getValue));
+ httpHeaderValueColumn.setCellValueFactory(cd -> Bindings.valueAt(httpHeaderMap, cd.getValue()));
+
+ httpHeadersInput.setItems(httpHeaderNameList);
+
+ httpPane.managedProperty().bind(httpPane.visibleProperty());
+ httpResponsePane.managedProperty().bind(httpResponsePane.visibleProperty());
+ httpRequestPane.managedProperty().bind(httpRequestPane.visibleProperty());
+ websocketPane.managedProperty().bind(websocketPane.visibleProperty());
+
+ // Disable mask input automatically.
+ websocketMaskedInput.selectedProperty().addListener(this::onWebsocketMaskedInputChange);
+
+ // Setup opcodes.
+ websocketOpcodeInput.setItems(FXCollections.observableArrayList(Opcode.TEXT, Opcode.BINARY,
+ Opcode.CLOSE, Opcode.PING, Opcode.PONG, Opcode.CONTINUATION, Opcode.NON_CONTROL_1,
+ Opcode.NON_CONTROL_2, Opcode.NON_CONTROL_3, Opcode.NON_CONTROL_4, Opcode.NON_CONTROL_5,
+ Opcode.CONTROL_1, Opcode.CONTROL_2, Opcode.CONTROL_3, Opcode.CONTROL_4, Opcode.CONTROL_5));
+ }
+
+ private void onWebsocketMaskedInputChange(
+ ObservableValue extends Boolean> observable,
+ boolean oldValue,
+ boolean newValue) {
+ websocketMaskInput.setDisable(oldValue);
+ }
+
+ private void onHeaderMapChange(
+ MapChangeListener.Change extends String, ? extends String> change) {
+ boolean removed = change.wasRemoved();
+ if (removed != change.wasAdded()) {
+ if (removed) {
+ httpHeaderNameList.remove(change.getKey());
+ } else {
+ httpHeaderNameList.add(change.getKey());
+ }
+ }
+ }
+
+ @Override
+ public PDU getPdu(
+ Proxy proxy,
+ Connection connection,
+ PduDestination destination,
+ byte[] buffer,
+ int size) {
+ if (httpPane.isVisible()) {
+ return getHttpPdu(proxy, connection, destination, buffer, size);
+ } else {
+ return getWebSocketPdu(proxy, connection, destination, buffer, size);
+ }
+ }
+
+ @Override
+ public void setPdu(PDU pdu) {
+ if (pdu instanceof HttpPdu) {
+ // HTTP
+ httpPane.setVisible(true);
+ websocketPane.setVisible(false);
+
+ httpHeaderMap.putAll(((HttpPdu) pdu).getHeaders());
+
+ httpVersionInput.setText(((HttpPdu) pdu).getVersion());
+
+ if (pdu instanceof HttpRequestPdu) {
+ // HTTP Request
+ httpRequestPane.setVisible(true);
+ httpResponsePane.setVisible(false);
+ httpMethodInput.setText(((HttpRequestPdu) pdu).getMethod());
+ httpPathInput.setText(((HttpRequestPdu) pdu).getPath());
+ } else {
+ // HTTP Response
+ httpRequestPane.setVisible(false);
+ httpResponsePane.setVisible(true);
+ httpStatusCodeInput.setText(String.valueOf(((HttpResponsePdu) pdu).getStatusCode()));
+ httpStatusMessageInput.setText(((HttpResponsePdu) pdu).getStatusMessage());
+ }
+ } else {
+ // WebSocket
+ httpPane.setVisible(false);
+ httpRequestPane.setVisible(false);
+ httpResponsePane.setVisible(false);
+ websocketPane.setVisible(true);
+
+ websocketFinInput.setSelected(((WebSocketPdu) pdu).isFinal());
+ websocketRsv1Input.setSelected(((WebSocketPdu) pdu).isRsv1());
+ websocketRsv2Input.setSelected(((WebSocketPdu) pdu).isRsv2());
+ websocketRsv3Input.setSelected(((WebSocketPdu) pdu).isRsv3());
+ websocketMaskedInput.setSelected(((WebSocketPdu) pdu).isMasked());
+
+ websocketOpcodeInput.setValue(((WebSocketPdu) pdu).getOpcode());
+
+ if (((WebSocketPdu) pdu).isMasked()) {
+ websocketMaskInput.setText(BytesUtils.bytesToString(((WebSocketPdu) pdu).getMask()));
+ } else {
+ websocketMaskInput.setText("");
+ }
+ }
+ }
+
+ @Override
+ public void clear() {
+ httpHeadersInput.getItems().clear();
+ httpVersionInput.clear();
+ httpMethodInput.clear();
+ httpPathInput.clear();
+ httpStatusCodeInput.clear();
+ httpStatusMessageInput.clear();
+ websocketOpcodeInput.getSelectionModel().clearSelection();
+ websocketFinInput.setSelected(false);
+ websocketRsv1Input.setSelected(false);
+ websocketRsv2Input.setSelected(false);
+ websocketRsv3Input.setSelected(false);
+ websocketMaskedInput.setSelected(false);
+ websocketMaskInput.clear();
+ }
+
+ private HttpPdu getHttpPdu(
+ Proxy proxy,
+ Connection connection,
+ PduDestination destination,
+ byte[] buffer,
+ int size) {
+ // HTTP
+ HttpPdu pdu;
+ if (httpRequestPane.isVisible()) {
+ // HTTP Request
+ pdu = new HttpRequestPdu(proxy, connection, destination, buffer, size);
+
+ ((HttpRequestPdu) pdu).setPath(httpPathInput.getText());
+ ((HttpRequestPdu) pdu).setMethod(httpMethodInput.getText());
+ } else {
+ // HTTP Response
+ pdu = new HttpResponsePdu(proxy, connection, destination, buffer, size);
+
+ ((HttpResponsePdu) pdu).setStatusCode(Integer.parseInt(httpStatusCodeInput.getText()));
+ ((HttpResponsePdu) pdu).setStatusMessage(httpStatusMessageInput.getText());
+ }
+
+ pdu.setVersion(httpVersionInput.getText());
+
+ pdu.addHeaders(new HashMap<>(httpHeaderMap));
+
+ return pdu;
+ }
+
+ private WebSocketPdu getWebSocketPdu(
+ Proxy proxy,
+ Connection connection,
+ PduDestination destination,
+ byte[] buffer,
+ int size) {
+ // WebSocket
+ WebSocketPdu pdu = new WebSocketPdu(proxy, connection, destination, buffer, size);
+
+ pdu.setFinal(websocketFinInput.isSelected());
+
+ pdu.setRsv1(websocketRsv1Input.isSelected());
+ pdu.setRsv2(websocketRsv2Input.isSelected());
+ pdu.setRsv3(websocketRsv3Input.isSelected());
+
+ pdu.setMasked(websocketMaskedInput.isSelected());
+
+ pdu.setOpcode(websocketOpcodeInput.getValue());
+
+ if (pdu.isMasked()) {
+ pdu.setMask(BytesUtils.stringToBytes(websocketMaskInput.getText()));
+ }
+
+ return pdu;
+ }
+
+ @FXML
+ private void onHttpHeaderAddButtonClick(ActionEvent event) {
+ Pair header = Dialogs.createTextPairDialog("Create header", "Name:", "Value:");
+
+ if (header == null) {
+ return;
+ }
+
+ httpHeaderMap.put(header.getKey(), header.getValue());
+ }
+
+ @FXML
+ private void onHttpHeaderEditButtonClick(ActionEvent event) {
+ String item = httpHeadersInput.getSelectionModel().getSelectedItem();
+
+ if (item == null) {
+ return;
+ }
+
+ Pair header = Dialogs.createTextPairDialog("Create header", "Name:", "Value:",
+ item, httpHeaderMap.get(item));
+
+ if (header == null) {
+ return;
+ }
+
+ if (header.getKey().equals(item)) {
+ httpHeaderMap.replace(item, header.getValue());
+ } else {
+ httpHeaderMap.remove(item);
+ httpHeaderMap.put(header.getKey(), header.getValue());
+ }
+ }
+
+ @FXML
+ private void onHttpHeaderRemoveButtonClick(ActionEvent event) {
+ String item = httpHeadersInput.getSelectionModel().getSelectedItem();
+
+ if (item == null) {
+ return;
+ }
+
+ httpHeaderMap.remove(item);
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/http/modifier/remove_header/RemoveHeaderData.java b/src/main/java/com/warxim/petep/extension/internal/http/modifier/remove_header/RemoveHeaderData.java
new file mode 100644
index 0000000..b7a9168
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/http/modifier/remove_header/RemoveHeaderData.java
@@ -0,0 +1,31 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.http.modifier.remove_header;
+
+import com.warxim.petep.extension.internal.modifier.factory.ModifierData;
+
+public final class RemoveHeaderData extends ModifierData {
+ private final String header;
+
+ public RemoveHeaderData(String header) {
+ this.header = header;
+ }
+
+ public String getHeader() {
+ return header;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/http/modifier/remove_header/RemoveHeaderModifier.java b/src/main/java/com/warxim/petep/extension/internal/http/modifier/remove_header/RemoveHeaderModifier.java
new file mode 100644
index 0000000..279792d
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/http/modifier/remove_header/RemoveHeaderModifier.java
@@ -0,0 +1,38 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.http.modifier.remove_header;
+
+import com.warxim.petep.core.pdu.PDU;
+import com.warxim.petep.extension.internal.http.pdu.HttpPdu;
+import com.warxim.petep.extension.internal.modifier.factory.Modifier;
+import com.warxim.petep.extension.internal.modifier.factory.ModifierData;
+import com.warxim.petep.extension.internal.modifier.factory.ModifierFactory;
+
+public final class RemoveHeaderModifier extends Modifier {
+ public RemoveHeaderModifier(ModifierFactory module, ModifierData data) {
+ super(module, data);
+ }
+
+ @Override
+ public boolean process(PDU pdu) {
+ if (pdu instanceof HttpPdu) {
+ ((HttpPdu) pdu).removeHeader(((RemoveHeaderData) data).getHeader());
+ }
+
+ return true;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/http/modifier/remove_header/RemoveHeaderModifierConfigurator.java b/src/main/java/com/warxim/petep/extension/internal/http/modifier/remove_header/RemoveHeaderModifierConfigurator.java
new file mode 100644
index 0000000..a790603
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/http/modifier/remove_header/RemoveHeaderModifierConfigurator.java
@@ -0,0 +1,54 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program free software: you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distribut n the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.http.modifier.remove_header;
+
+import java.io.IOException;
+import com.warxim.petep.extension.internal.http.pdu.HttpUtils;
+import com.warxim.petep.extension.internal.modifier.factory.ModifierConfigurator;
+import com.warxim.petep.extension.internal.modifier.factory.ModifierData;
+import com.warxim.petep.gui.dialog.Dialogs;
+import javafx.fxml.FXML;
+import javafx.scene.control.TextField;
+
+public final class RemoveHeaderModifierConfigurator extends ModifierConfigurator {
+ @FXML
+ private TextField nameInput;
+
+ public RemoveHeaderModifierConfigurator() throws IOException {
+ super("/fxml/extension/internal/http/modifier/RemoveHeader.fxml");
+ }
+
+ @Override
+ public ModifierData getConfig() {
+ return new RemoveHeaderData(HttpUtils.formatHeaderName(nameInput.getText()));
+ }
+
+ @Override
+ public void setConfig(ModifierData config) {
+ nameInput.setText(((RemoveHeaderData) config).getHeader());
+ }
+
+ @Override
+ public boolean isValid() {
+ if (nameInput.getText().length() == 0) {
+ Dialogs.createErrorDialog("Header required", "You have to enter header to remove.");
+ return false;
+ }
+
+ return true;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/http/modifier/remove_header/RemoveHeaderModifierFactory.java b/src/main/java/com/warxim/petep/extension/internal/http/modifier/remove_header/RemoveHeaderModifierFactory.java
new file mode 100644
index 0000000..784f908
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/http/modifier/remove_header/RemoveHeaderModifierFactory.java
@@ -0,0 +1,51 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.http.modifier.remove_header;
+
+import java.io.IOException;
+import java.lang.reflect.Type;
+import com.warxim.petep.extension.internal.modifier.factory.Modifier;
+import com.warxim.petep.extension.internal.modifier.factory.ModifierConfigurator;
+import com.warxim.petep.extension.internal.modifier.factory.ModifierData;
+import com.warxim.petep.extension.internal.modifier.factory.ModifierFactory;
+
+public final class RemoveHeaderModifierFactory extends ModifierFactory {
+ @Override
+ public String getCode() {
+ return "http_remove_header";
+ }
+
+ @Override
+ public String getName() {
+ return "Remove HTTP header";
+ }
+
+ @Override
+ public Type getConfigType() {
+ return RemoveHeaderData.class;
+ }
+
+ @Override
+ public Modifier createModifier(ModifierData data) {
+ return new RemoveHeaderModifier(this, data);
+ }
+
+ @Override
+ public ModifierConfigurator createConfigPane() throws IOException {
+ return new RemoveHeaderModifierConfigurator();
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/http/pdu/HttpPdu.java b/src/main/java/com/warxim/petep/extension/internal/http/pdu/HttpPdu.java
new file mode 100644
index 0000000..ce66728
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/http/pdu/HttpPdu.java
@@ -0,0 +1,83 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.http.pdu;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import com.warxim.petep.core.connection.Connection;
+import com.warxim.petep.core.pdu.PduDestination;
+import com.warxim.petep.extension.internal.tcp.proxy.base.TcpPdu;
+import com.warxim.petep.proxy.worker.Proxy;
+
+public abstract class HttpPdu extends TcpPdu {
+ protected String version;
+ protected Map headers;
+
+ public HttpPdu(
+ Proxy proxy,
+ Connection connection,
+ PduDestination destination,
+ byte[] buffer,
+ int size) {
+ super(proxy, connection, destination, buffer, size);
+ headers = new HashMap<>();
+ }
+
+ public HttpPdu(
+ Proxy proxy,
+ Connection connection,
+ PduDestination destination,
+ byte[] buffer,
+ int size,
+ Set tags) {
+ super(proxy, connection, destination, buffer, size, tags);
+ headers = new HashMap<>();
+ }
+
+ public String getVersion() {
+ return version;
+ }
+
+ public void setVersion(String version) {
+ this.version = version;
+ }
+
+ public Map getHeaders() {
+ return headers;
+ }
+
+ public void addHeaders(Map headers) {
+ this.headers.putAll(headers);
+ }
+
+ public void setHeaders(Map headers) {
+ this.headers = headers;
+ }
+
+ public void addHeader(String name, String value) {
+ headers.put(name, value);
+ }
+
+ public void removeHeader(String name) {
+ headers.remove(name);
+ }
+
+ public String getHeader(String name) {
+ return headers.get(name);
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/http/pdu/HttpRequestPdu.java b/src/main/java/com/warxim/petep/extension/internal/http/pdu/HttpRequestPdu.java
new file mode 100644
index 0000000..2c115d4
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/http/pdu/HttpRequestPdu.java
@@ -0,0 +1,77 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.http.pdu;
+
+import java.util.Set;
+import com.warxim.petep.core.connection.Connection;
+import com.warxim.petep.core.pdu.PDU;
+import com.warxim.petep.core.pdu.PduDestination;
+import com.warxim.petep.proxy.worker.Proxy;
+
+public final class HttpRequestPdu extends HttpPdu {
+ private String method;
+ private String path;
+
+ public HttpRequestPdu(
+ Proxy proxy,
+ Connection connection,
+ PduDestination destination,
+ byte[] buffer,
+ int size) {
+ super(proxy, connection, destination, buffer, size);
+ }
+
+ public HttpRequestPdu(
+ Proxy proxy,
+ Connection connection,
+ PduDestination destination,
+ byte[] buffer,
+ int size,
+ Set tags) {
+ super(proxy, connection, destination, buffer, size, tags);
+ }
+
+ public String getMethod() {
+ return method;
+ }
+
+ public void setMethod(String method) {
+ this.method = method;
+ }
+
+ public String getPath() {
+ return path;
+ }
+
+ public void setPath(String path) {
+ this.path = path;
+ }
+
+ @Override
+ public PDU copy() {
+ HttpRequestPdu pdu = new HttpRequestPdu(proxy, connection, destination, buffer.clone(), size);
+
+ pdu.addTags(tags);
+
+ pdu.setMethod(method);
+ pdu.setPath(path);
+ pdu.setVersion(version);
+ pdu.addHeaders(headers);
+
+ return pdu;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/http/pdu/HttpResponsePdu.java b/src/main/java/com/warxim/petep/extension/internal/http/pdu/HttpResponsePdu.java
new file mode 100644
index 0000000..3b00eec
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/http/pdu/HttpResponsePdu.java
@@ -0,0 +1,77 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.http.pdu;
+
+import java.util.Set;
+import com.warxim.petep.core.connection.Connection;
+import com.warxim.petep.core.pdu.PDU;
+import com.warxim.petep.core.pdu.PduDestination;
+import com.warxim.petep.proxy.worker.Proxy;
+
+public final class HttpResponsePdu extends HttpPdu {
+ private int statusCode;
+ private String statusMessage;
+
+ public HttpResponsePdu(
+ Proxy proxy,
+ Connection connection,
+ PduDestination destination,
+ byte[] buffer,
+ int size) {
+ super(proxy, connection, destination, buffer, size);
+ }
+
+ public HttpResponsePdu(
+ Proxy proxy,
+ Connection connection,
+ PduDestination destination,
+ byte[] buffer,
+ int size,
+ Set tags) {
+ super(proxy, connection, destination, buffer, size, tags);
+ }
+
+ public String getStatusMessage() {
+ return statusMessage;
+ }
+
+ public void setStatusMessage(String statusMessage) {
+ this.statusMessage = statusMessage;
+ }
+
+ public int getStatusCode() {
+ return statusCode;
+ }
+
+ public void setStatusCode(int statusCode) {
+ this.statusCode = statusCode;
+ }
+
+ @Override
+ public PDU copy() {
+ HttpResponsePdu pdu = new HttpResponsePdu(proxy, connection, destination, buffer.clone(), size);
+
+ pdu.addTags(tags);
+
+ pdu.setStatusCode(statusCode);
+ pdu.setStatusMessage(statusMessage);
+ pdu.setVersion(version);
+ pdu.addHeaders(headers);
+
+ return pdu;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/http/pdu/HttpUtils.java b/src/main/java/com/warxim/petep/extension/internal/http/pdu/HttpUtils.java
new file mode 100644
index 0000000..a4757cd
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/http/pdu/HttpUtils.java
@@ -0,0 +1,46 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.http.pdu;
+
+public final class HttpUtils {
+ private HttpUtils() {}
+
+ public static String formatHeaderName(String name) {
+ char[] array = name.toCharArray();
+
+ array[0] = Character.toUpperCase(array[0]);
+ int end = array.length - 1;
+ for (int i = 1; i < end; ++i) {
+ if (array[i] == '-') {
+ array[i + 1] = Character.toUpperCase(array[i + 1]);
+ }
+ }
+
+ return String.valueOf(array);
+ }
+
+ public static String formatHeaderName(StringBuilder builder) {
+ builder.setCharAt(0, Character.toUpperCase(builder.charAt(0)));
+ int end = builder.length() - 1;
+ for (int i = 1; i < end; ++i) {
+ if (builder.charAt(i) == '-') {
+ builder.setCharAt(i + 1, Character.toUpperCase(builder.charAt(i + 1)));
+ }
+ }
+ return builder.toString();
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/http/pdu/Opcode.java b/src/main/java/com/warxim/petep/extension/internal/http/pdu/Opcode.java
new file mode 100644
index 0000000..f6a8411
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/http/pdu/Opcode.java
@@ -0,0 +1,72 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.http.pdu;
+
+public enum Opcode {
+ CONTINUATION(0), TEXT(1), BINARY(2), NON_CONTROL_1(3), NON_CONTROL_2(4), NON_CONTROL_3(
+ 5), NON_CONTROL_4(6), NON_CONTROL_5(7), CLOSE(8), PING(
+ 9), PONG(10), CONTROL_1(11), CONTROL_2(12), CONTROL_3(13), CONTROL_4(14), CONTROL_5(15);
+
+ private final int value;
+
+ Opcode(int value) {
+ this.value = value;
+ }
+
+ public final int getValue() {
+ return value;
+ }
+
+ public static final Opcode valueOf(int value) {
+ switch (value) {
+ case 0:
+ return Opcode.CONTINUATION;
+ case 1:
+ return Opcode.TEXT;
+ case 2:
+ return Opcode.BINARY;
+ case 3:
+ return Opcode.NON_CONTROL_1;
+ case 4:
+ return Opcode.NON_CONTROL_2;
+ case 5:
+ return Opcode.NON_CONTROL_3;
+ case 6:
+ return Opcode.NON_CONTROL_4;
+ case 7:
+ return Opcode.NON_CONTROL_5;
+ case 8:
+ return Opcode.CLOSE;
+ case 9:
+ return Opcode.PING;
+ case 10:
+ return Opcode.PONG;
+ case 11:
+ return Opcode.CONTROL_1;
+ case 12:
+ return Opcode.CONTROL_2;
+ case 13:
+ return Opcode.CONTROL_3;
+ case 14:
+ return Opcode.CONTROL_4;
+ case 15:
+ return Opcode.CONTROL_5;
+ default:
+ return null;
+ }
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/http/pdu/WebSocketPdu.java b/src/main/java/com/warxim/petep/extension/internal/http/pdu/WebSocketPdu.java
new file mode 100644
index 0000000..1d71456
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/http/pdu/WebSocketPdu.java
@@ -0,0 +1,133 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.http.pdu;
+
+import java.util.Set;
+import com.warxim.petep.core.connection.Connection;
+import com.warxim.petep.core.pdu.PduDestination;
+import com.warxim.petep.extension.internal.tcp.proxy.base.TcpPdu;
+import com.warxim.petep.proxy.worker.Proxy;
+
+public final class WebSocketPdu extends TcpPdu {
+ private boolean isFinal;
+
+ private boolean isRsv1;
+ private boolean isRsv2;
+ private boolean isRsv3;
+
+ private Opcode opcode;
+
+ private boolean isMasked;
+ private byte[] mask;
+
+ public WebSocketPdu(
+ Proxy proxy,
+ Connection connection,
+ PduDestination destination,
+ byte[] buffer,
+ int size) {
+ super(proxy, connection, destination, buffer, size);
+ }
+
+ public WebSocketPdu(
+ Proxy proxy,
+ Connection connection,
+ PduDestination destination,
+ byte[] buffer,
+ int size,
+ Set tags) {
+ super(proxy, connection, destination, buffer, size, tags);
+ }
+
+ public boolean isFinal() {
+ return isFinal;
+ }
+
+ public void setFinal(boolean isFinal) {
+ this.isFinal = isFinal;
+ }
+
+ public Opcode getOpcode() {
+ return opcode;
+ }
+
+ public void setOpcode(Opcode opcode) {
+ this.opcode = opcode;
+ }
+
+ public boolean isRsv1() {
+ return isRsv1;
+ }
+
+ public void setRsv1(boolean isRsv1) {
+ this.isRsv1 = isRsv1;
+ }
+
+ public boolean isRsv2() {
+ return isRsv2;
+ }
+
+ public void setRsv2(boolean isRsv2) {
+ this.isRsv2 = isRsv2;
+ }
+
+ public boolean isRsv3() {
+ return isRsv3;
+ }
+
+ public void setRsv3(boolean isRsv3) {
+ this.isRsv3 = isRsv3;
+ }
+
+ public boolean isMasked() {
+ return isMasked;
+ }
+
+ public void setMasked(boolean isMasked) {
+ this.isMasked = isMasked;
+ }
+
+ public byte[] getMask() {
+ return mask;
+ }
+
+ public void setMask(byte[] mask) {
+ this.mask = mask;
+ }
+
+ @Override
+ public WebSocketPdu copy() {
+ WebSocketPdu pdu = new WebSocketPdu(proxy, connection, destination, buffer.clone(), size);
+
+ pdu.addTags(tags);
+
+ pdu.setFinal(isFinal);
+
+ pdu.setRsv1(isRsv1);
+ pdu.setRsv2(isRsv2);
+ pdu.setRsv3(isRsv3);
+
+ pdu.setOpcode(opcode);
+
+ pdu.setMasked(isMasked);
+ if (isMasked) {
+ pdu.setMask(mask.clone());
+ }
+
+ return pdu;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/http/proxy/HttpConnection.java b/src/main/java/com/warxim/petep/extension/internal/http/proxy/HttpConnection.java
new file mode 100644
index 0000000..b75b0e6
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/http/proxy/HttpConnection.java
@@ -0,0 +1,161 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.http.proxy;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.Socket;
+import java.nio.charset.Charset;
+import com.warxim.petep.core.pdu.PDU;
+import com.warxim.petep.core.pdu.PduDestination;
+import com.warxim.petep.extension.internal.http.pdu.HttpPdu;
+import com.warxim.petep.extension.internal.http.pdu.HttpRequestPdu;
+import com.warxim.petep.extension.internal.http.pdu.HttpResponsePdu;
+import com.warxim.petep.extension.internal.http.pdu.Opcode;
+import com.warxim.petep.extension.internal.http.pdu.WebSocketPdu;
+import com.warxim.petep.extension.internal.http.reader.HttpRequestReader;
+import com.warxim.petep.extension.internal.http.reader.HttpResponseReader;
+import com.warxim.petep.extension.internal.http.reader.PduReader;
+import com.warxim.petep.extension.internal.http.reader.WebSocketReader;
+import com.warxim.petep.extension.internal.http.writer.HttpRequestWriter;
+import com.warxim.petep.extension.internal.http.writer.HttpResponseWriter;
+import com.warxim.petep.extension.internal.http.writer.PduWriter;
+import com.warxim.petep.extension.internal.http.writer.WebSocketWriter;
+import com.warxim.petep.extension.internal.tcp.proxy.base.TcpConnection;
+import com.warxim.petep.proxy.worker.Proxy;
+
+/** HTTP connection. */
+public final class HttpConnection extends TcpConnection {
+ /** TCP connection constructor. */
+ public HttpConnection(int id, Proxy proxy, Socket socket) {
+ super(id, proxy, socket);
+ }
+
+ @Override
+ protected void readFromClient() {
+ try (InputStream in = socketClient.getInputStream()) {
+ PduReader reader = new HttpRequestReader(in, getConfig().getBufferSize(),
+ Charset.forName(getConfig().getCharset()));
+
+ PDU pdu;
+ while ((pdu = reader.read()) != null) {
+ pdu.setProxy(proxy);
+ pdu.setConnection(this);
+
+ if (pdu instanceof HttpRequestPdu) {
+ String temp = ((HttpRequestPdu) pdu).getHeader("Upgrade");
+ if (temp != null && "websocket".equals(temp)) {
+ reader = new WebSocketReader(in, PduDestination.SERVER);
+ // Do not support any extensions.
+ ((HttpPdu) pdu).removeHeader("Sec-WebSocket-Extensions");
+ }
+ }
+
+ process(pdu);
+ }
+ } catch (IOException e) {
+ // Closed
+ }
+ }
+
+ @Override
+ protected void readFromServer() {
+ try (InputStream in = socketServer.getInputStream()) {
+ PduReader reader = new HttpResponseReader(in, getConfig().getBufferSize(),
+ Charset.forName(getConfig().getCharset()));
+
+ PDU pdu;
+ while ((pdu = reader.read()) != null) {
+ pdu.setProxy(proxy);
+ pdu.setConnection(this);
+
+ if (pdu instanceof HttpResponsePdu) {
+ // HTTP
+ String temp = ((HttpResponsePdu) pdu).getHeader("Upgrade");
+ if (temp != null && "websocket".equals(temp)) {
+ reader = new WebSocketReader(in, PduDestination.CLIENT);
+ }
+ } else {
+ // WebSockets
+ if (((WebSocketPdu) pdu).getOpcode() == Opcode.CLOSE) {
+ socketServer.close();
+ }
+ }
+
+ process(pdu);
+ }
+ } catch (IOException e) {
+ // Closed
+ }
+ }
+
+ @Override
+ protected void writeToClient() {
+ PDU pdu;
+
+ try (OutputStream out = socketClient.getOutputStream()) {
+ PduWriter writer = new HttpResponseWriter(out);
+
+ // Read bytes to buffer and send it to out stream
+ while ((pdu = queueS2C.take()) != null) {
+ writer.write(pdu);
+
+ if (pdu instanceof HttpResponsePdu) {
+ // HTTP
+ String temp = ((HttpResponsePdu) pdu).getHeader("Upgrade");
+ if (temp != null && "websocket".equals(temp)) {
+ writer = new WebSocketWriter(out);
+ }
+ } else {
+ // WebSockets
+ if (((WebSocketPdu) pdu).getOpcode() == Opcode.CLOSE) {
+ socketClient.close();
+ }
+ }
+ }
+ } catch (IOException e) {
+ // Closed socket
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+ }
+
+ @Override
+ protected void writeToServer() {
+ PDU pdu;
+
+ try (OutputStream out = socketServer.getOutputStream()) {
+ PduWriter writer = new HttpRequestWriter(out);
+ // Read bytes to buffer and send it to out stream
+ while ((pdu = queueC2S.take()) != null) {
+ writer.write(pdu);
+
+ if (pdu instanceof HttpRequestPdu) {
+ String temp = ((HttpRequestPdu) pdu).getHeader("Upgrade");
+ if (temp != null && "websocket".equals(temp)) {
+ writer = new WebSocketWriter(out);
+ }
+ }
+ }
+ } catch (IOException e) {
+ // Closed socket
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/http/proxy/HttpProxy.java b/src/main/java/com/warxim/petep/extension/internal/http/proxy/HttpProxy.java
new file mode 100644
index 0000000..773bc87
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/http/proxy/HttpProxy.java
@@ -0,0 +1,37 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.http.proxy;
+
+import java.net.Socket;
+import com.warxim.petep.extension.internal.tcp.TcpConfig;
+import com.warxim.petep.extension.internal.tcp.proxy.base.TcpConnection;
+import com.warxim.petep.extension.internal.tcp.proxy.base.TcpProxy;
+import com.warxim.petep.helper.PetepHelper;
+import com.warxim.petep.proxy.module.ProxyModule;
+
+/** HTTP Proxy. */
+public final class HttpProxy extends TcpProxy {
+ /** Http proxy constructor. */
+ public HttpProxy(ProxyModule module, PetepHelper helper, TcpConfig config) {
+ super(module, helper, config);
+ }
+
+ @Override
+ protected TcpConnection createConnection(Socket socket) {
+ return new HttpConnection(connectionManager.nextId(), this, socket);
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/http/proxy/HttpProxyModule.java b/src/main/java/com/warxim/petep/extension/internal/http/proxy/HttpProxyModule.java
new file mode 100644
index 0000000..cd490ea
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/http/proxy/HttpProxyModule.java
@@ -0,0 +1,54 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.http.proxy;
+
+import com.warxim.petep.extension.internal.tcp.TcpConfig;
+import com.warxim.petep.helper.PetepHelper;
+import com.warxim.petep.persistence.Configurable;
+import com.warxim.petep.proxy.factory.ProxyModuleFactory;
+import com.warxim.petep.proxy.module.ProxyModule;
+import com.warxim.petep.proxy.worker.Proxy;
+
+/** TCP proxy module. */
+public final class HttpProxyModule extends ProxyModule implements Configurable {
+ private TcpConfig config;
+
+ /** TCP proxy module constructor. */
+ public HttpProxyModule(
+ ProxyModuleFactory factory,
+ String code,
+ String name,
+ String description,
+ boolean enabled) {
+ super(factory, code, name, description, enabled);
+ }
+
+ @Override
+ public Proxy createProxy(PetepHelper helper) {
+ return new HttpProxy(this, helper, config);
+ }
+
+ @Override
+ public TcpConfig saveConfig() {
+ return config;
+ }
+
+ @Override
+ public void loadConfig(TcpConfig config) {
+ this.config = config;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/http/proxy/HttpProxyModuleFactory.java b/src/main/java/com/warxim/petep/extension/internal/http/proxy/HttpProxyModuleFactory.java
new file mode 100644
index 0000000..a4d9eb3
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/http/proxy/HttpProxyModuleFactory.java
@@ -0,0 +1,211 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.http.proxy;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import com.warxim.petep.core.connection.Connection;
+import com.warxim.petep.core.pdu.PDU;
+import com.warxim.petep.core.pdu.PduDestination;
+import com.warxim.petep.extension.Extension;
+import com.warxim.petep.extension.internal.http.gui.HttpMetadataPane;
+import com.warxim.petep.extension.internal.http.pdu.HttpRequestPdu;
+import com.warxim.petep.extension.internal.http.pdu.HttpResponsePdu;
+import com.warxim.petep.extension.internal.http.pdu.Opcode;
+import com.warxim.petep.extension.internal.http.pdu.WebSocketPdu;
+import com.warxim.petep.extension.internal.tcp.TcpConfig;
+import com.warxim.petep.extension.internal.tcp.TcpConfigurator;
+import com.warxim.petep.gui.component.ConfigPane;
+import com.warxim.petep.gui.component.PduMetadataPane;
+import com.warxim.petep.persistence.Configurator;
+import com.warxim.petep.proxy.factory.ProxyModuleFactory;
+import com.warxim.petep.proxy.module.ProxyModule;
+import com.warxim.petep.proxy.serizalization.ProxyDeserializer;
+import com.warxim.petep.proxy.serizalization.ProxySerializer;
+import com.warxim.petep.proxy.worker.Proxy;
+import com.warxim.petep.util.BytesUtils;
+
+/** HTTP proxy module. */
+public final class HttpProxyModuleFactory extends ProxyModuleFactory
+ implements Configurator, ProxySerializer, ProxyDeserializer {
+ /** HTTP proxy module constructor. */
+ public HttpProxyModuleFactory(Extension extension) {
+ super(extension);
+ }
+
+ @Override
+ public String getName() {
+ return "HTTP";
+ }
+
+ @Override
+ public String getCode() {
+ return "http";
+ }
+
+ @Override
+ public ProxyModule createModule(String code, String name, String description, boolean enabled) {
+ return new HttpProxyModule(this, code, name, description, enabled);
+ }
+
+ @Override
+ public ConfigPane createConfigPane() throws IOException {
+ return new TcpConfigurator();
+ }
+
+ @Override
+ public PduMetadataPane createPduMetadataPane() throws IOException {
+ return new HttpMetadataPane();
+ }
+
+ @Override
+ public Map serializePduMetadata(PDU pdu) {
+ Map metadata = new HashMap<>();
+ if (pdu instanceof HttpRequestPdu) {
+ HttpRequestPdu request = (HttpRequestPdu) pdu;
+
+ if (request.getVersion() != null) {
+ metadata.put("Method", request.getMethod());
+ metadata.put("Path", request.getPath());
+ metadata.put("Version", request.getVersion());
+ }
+
+ for (var header : request.getHeaders().entrySet()) {
+ metadata.put("H-" + header.getKey(), header.getValue());
+ }
+
+ return metadata;
+ } else if (pdu instanceof HttpResponsePdu) {
+ HttpResponsePdu response = (HttpResponsePdu) pdu;
+
+ if (response.getVersion() != null) {
+ metadata.put("Status-Code", String.valueOf(response.getStatusCode()));
+ metadata.put("Status-Message", response.getStatusMessage());
+ metadata.put("Version", response.getVersion());
+ }
+
+ for (var header : response.getHeaders().entrySet()) {
+ metadata.put("H-" + header.getKey(), header.getValue());
+ }
+
+ return metadata;
+ } else if (pdu instanceof WebSocketPdu) {
+ WebSocketPdu websocketPdu = (WebSocketPdu) pdu;
+
+ metadata.put("Fin", websocketPdu.isFinal() ? "1" : "0");
+ metadata.put("RSV", (websocketPdu.isRsv1() ? "1" : "0") + ","
+ + (websocketPdu.isRsv2() ? "1" : "0") + "," + (websocketPdu.isRsv3() ? "1" : "0"));
+ metadata.put("Opcode", websocketPdu.getOpcode().name());
+ metadata.put("Masked", websocketPdu.isMasked() ? "1" : "0");
+
+ if (websocketPdu.isMasked()) {
+ metadata.put("Mask", BytesUtils.bytesToString(websocketPdu.getMask()));
+ }
+
+ return metadata;
+ }
+
+ return null;
+ }
+
+ @Override
+ public PDU deserializePdu(
+ Proxy proxy,
+ Connection connection,
+ PduDestination destination,
+ byte[] buffer,
+ int size,
+ Set tags,
+ Map serializedMetadata) {
+ // WebSockets
+ if (serializedMetadata.containsKey("Fin")) {
+ WebSocketPdu pdu = new WebSocketPdu(proxy, connection, destination, buffer, size, tags);
+
+ // FIN
+ pdu.setFinal(serializedMetadata.get("Fin").equals("1"));
+
+ // RSV
+ String[] rsv = serializedMetadata.get("RSV").split(",");
+ pdu.setRsv1(rsv[0].equals("1"));
+ pdu.setRsv2(rsv[1].equals("1"));
+ pdu.setRsv3(rsv[2].equals("1"));
+
+ pdu.setOpcode(Opcode.valueOf(serializedMetadata.get("Opcode")));
+
+ pdu.setMasked(serializedMetadata.get("Masked").equals("1"));
+
+ if (pdu.isMasked()) {
+ pdu.setMask(BytesUtils.stringToBytes(serializedMetadata.get("Mask")));
+ }
+
+ return pdu;
+ } else {
+ // HTTP
+ if (destination == PduDestination.SERVER) {
+ HttpRequestPdu request =
+ new HttpRequestPdu(proxy, connection, destination, buffer, size, tags);
+
+ for (var item : serializedMetadata.entrySet()) {
+ String key = item.getKey();
+
+ if (key.startsWith("H-")) {
+ request.addHeader(key.substring(2), item.getValue());
+ } else if (key.equals("Method")) {
+ request.setMethod(item.getValue());
+ } else if (key.equals("Path")) {
+ request.setPath(item.getValue());
+ } else if (key.equals("Version")) {
+ request.setVersion(item.getValue());
+ }
+ }
+
+ return request;
+ } else {
+ HttpResponsePdu response =
+ new HttpResponsePdu(proxy, connection, destination, buffer, size, tags);
+
+ for (var item : serializedMetadata.entrySet()) {
+ String key = item.getKey();
+
+ if (key.startsWith("H-")) {
+ response.addHeader(key.substring(2), item.getValue());
+ } else if (key.equals("Status-Code")) {
+ response.setStatusCode(Integer.parseInt(item.getValue()));
+ } else if (key.equals("Status-Message")) {
+ response.setStatusMessage(item.getValue());
+ } else if (key.equals("Version")) {
+ response.setVersion(item.getValue());
+ }
+ }
+
+ return response;
+ }
+ }
+ }
+
+ @Override
+ public ProxySerializer getSerializer() {
+ return this;
+ }
+
+ @Override
+ public ProxyDeserializer getDeserializer() {
+ return this;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/http/reader/HttpReader.java b/src/main/java/com/warxim/petep/extension/internal/http/reader/HttpReader.java
new file mode 100644
index 0000000..e45b2c9
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/http/reader/HttpReader.java
@@ -0,0 +1,250 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.http.reader;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.Charset;
+import com.warxim.petep.core.pdu.PDU;
+import com.warxim.petep.extension.internal.http.pdu.HttpPdu;
+import com.warxim.petep.extension.internal.http.pdu.HttpUtils;
+import com.warxim.petep.extension.internal.http.reader.state.BodyWithChunkedEncodingState;
+import com.warxim.petep.extension.internal.http.reader.state.BodyWithChunkedEncodingState.ChunkedBodyStep;
+import com.warxim.petep.extension.internal.http.reader.state.BodyWithContentLengthState;
+import com.warxim.petep.extension.internal.http.reader.state.InternalState;
+
+public abstract class HttpReader extends PduReader {
+ protected enum HeaderStep {
+ HEADER_NAME, HEADER_VALUE
+ }
+
+ protected final int maxLength;
+ protected final Charset defaultCharset;
+ protected InternalState internalState;
+
+ public HttpReader(InputStream in, int maxLength, Charset defaultCharset) {
+ super(in);
+ this.maxLength = maxLength;
+ this.defaultCharset = defaultCharset;
+ }
+
+ public abstract PDU read() throws IOException;
+
+ protected final boolean readHeaders(HttpPdu request) throws IOException {
+ StringBuilder builder = new StringBuilder();
+ HeaderStep step = HeaderStep.HEADER_NAME;
+ int currentByte;
+ String temp = "";
+ while ((currentByte = in.read()) != -1) {
+ if (step == HeaderStep.HEADER_NAME) {
+ if (currentByte == ':') {
+ // Skip space.
+ skip(1);
+
+ temp = HttpUtils.formatHeaderName(builder);
+ builder.setLength(0);
+
+ step = HeaderStep.HEADER_VALUE;
+ continue;
+ } else if (currentByte == '\r') { // End of headers.
+ // Skip \n.
+ skip(1);
+
+ return true;
+ }
+ } else { // HEADER_VALUE
+ if (currentByte == '\r') {
+ // Skip \n.
+ skip(1);
+
+ String oldValue;
+ if ((oldValue = request.getHeader(temp)) != null) {
+ request.addHeader(temp, oldValue + ", " + builder.toString());
+ } else {
+ request.addHeader(temp, builder.toString());
+ }
+ builder.setLength(0);
+
+ step = HeaderStep.HEADER_NAME;
+ continue;
+ }
+ }
+
+ builder.append((char) currentByte);
+ }
+
+ return false;
+ }
+
+ protected final void processHeaders(HttpPdu pdu) {
+ // Content-Type
+ String value;
+ if ((value = pdu.getHeader("Content-Type")) != null) {
+ int index = value.indexOf("charset=");
+ if (index != -1) {
+ pdu.setCharset(Charset.forName(value.substring(index + 8)));
+ } else {
+ pdu.setCharset(defaultCharset);
+ }
+ } else {
+ pdu.setCharset(defaultCharset);
+ }
+ }
+
+ protected final void processBodyWithContentLength(HttpPdu pdu) throws IOException {
+ BodyWithContentLengthState state = ((BodyWithContentLengthState) internalState);
+
+ byte[] buffer;
+ if (state.getContentLength() > maxLength) {
+ buffer = new byte[maxLength];
+
+ if (state.isChunked()) {
+ pdu.addTag("chunk");
+ }
+
+ // We are going to read just part of the message.
+ state.setContentLength(state.getContentLength() - maxLength);
+ } else {
+ buffer = new byte[state.getContentLength()];
+
+ if (state.isChunked()) {
+ pdu.addTag("last_chunk");
+ }
+
+ // We are going to read the rest.
+ internalState = null;
+ }
+
+ readNBytes(buffer, 0, buffer.length);
+
+ pdu.setBuffer(buffer, buffer.length);
+ }
+
+ protected final void processBodyWithChunkedEncoding(HttpPdu pdu) throws IOException {
+ BodyWithChunkedEncodingState state = (BodyWithChunkedEncodingState) internalState;
+
+ int index = 0;
+ byte[] buffer = new byte[maxLength];
+ StringBuilder builder = new StringBuilder();
+ int currentByte;
+
+ while (index != buffer.length) {
+ if (state.getChunkStep() == ChunkedBodyStep.LENGTH) {
+ if ((currentByte = in.read()) == -1) {
+ break;
+ }
+
+ if (currentByte == '\r') {
+ // Skip \n
+ skip(1);
+
+ int length = Integer.parseInt(builder.toString(), 16);
+
+ if (length == 0) {
+ skip(2);
+
+ pdu.setBuffer(buffer, index);
+ pdu.addTag("last_chunk");
+
+ // No more chunks.
+ internalState = null;
+ return;
+ }
+
+ state.setChunkLength(Integer.parseInt(builder.toString(), 16));
+ state.setChunkStep(ChunkedBodyStep.CHUNK);
+ builder.setLength(0);
+ } else {
+ builder.append((char) currentByte);
+ }
+ } else {
+ int remaining = maxLength - index;
+ if (state.getChunkLength() > remaining) {
+ // Not enough space.
+
+ // Next step is to parse the rest of the chunk.
+ state.setChunkLength(state.getChunkLength() - remaining);
+ state.setChunkStep(ChunkedBodyStep.CHUNK);
+
+ // Read part of a chunk.
+ readNBytes(buffer, index, remaining);
+ index += remaining;
+
+ break;
+ } else {
+ // Enough space.
+
+ // Read chunk.
+ readNBytes(buffer, index, state.getChunkLength());
+ index += state.getChunkLength();
+
+ // Next step is to parse length.
+ state.setChunkStep(ChunkedBodyStep.LENGTH);
+
+ // Skip \r\n
+ skip(2);
+ }
+ }
+ }
+
+ pdu.addTag("chunk");
+
+ pdu.setBuffer(buffer, index);
+ }
+
+ protected final void readBody(HttpPdu pdu) throws IOException {
+ if (internalState == null) {
+ // Determine type of body.
+ String temp = pdu.getHeader("Content-Length");
+ if (temp != null) {
+ int length = Integer.parseInt(temp);
+
+ internalState = new BodyWithContentLengthState(length);
+
+ // Length is above the limit. Switching to chunked encoding, so that the PDUs will be
+ // editable separately (impossible with content-length).
+ if (length > maxLength) {
+ pdu.removeHeader("Content-Length");
+ pdu.addHeader("Transfer-Encoding", "chunked");
+ ((BodyWithContentLengthState) internalState).setChunked(true);
+ }
+ } else if ((temp = pdu.getHeader("Transfer-Encoding")) != null && temp.equals("chunked")) {
+ internalState = new BodyWithChunkedEncodingState();
+ } else {
+ pdu.setBuffer(new byte[0], 0);
+ }
+ }
+
+ if (internalState instanceof BodyWithContentLengthState) {
+ processBodyWithContentLength(pdu);
+ } else if (internalState instanceof BodyWithChunkedEncodingState) {
+ processBodyWithChunkedEncoding(pdu);
+ }
+ }
+
+ protected final void skip(int n) throws IOException {
+ if (in.skip(n) != n) {
+ throw new IOException("Could not skip bytes!");
+ }
+ }
+
+ protected final void readNBytes(byte[] buffer, int offset, int length) throws IOException {
+ if (in.readNBytes(buffer, offset, length) != length) {
+ throw new IOException("Could not skip bytes!");
+ }
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/http/reader/HttpRequestReader.java b/src/main/java/com/warxim/petep/extension/internal/http/reader/HttpRequestReader.java
new file mode 100644
index 0000000..404cacd
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/http/reader/HttpRequestReader.java
@@ -0,0 +1,97 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.http.reader;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.Charset;
+import com.warxim.petep.core.pdu.PduDestination;
+import com.warxim.petep.extension.internal.http.pdu.HttpRequestPdu;
+
+public final class HttpRequestReader extends HttpReader {
+ protected enum RequestLineState {
+ METHOD, PATH, VERSION
+ }
+
+ public HttpRequestReader(InputStream in, int maxLength, Charset defaultCharset) {
+ super(in, maxLength, defaultCharset);
+ }
+
+ @Override
+ public HttpRequestPdu read() throws IOException {
+ HttpRequestPdu request = new HttpRequestPdu(null, null, PduDestination.SERVER, null, 0);
+
+ if (internalState == null) {
+ if (!readRequestLine(request) || !readHeaders(request)) {
+ return null;
+ }
+
+ processHeaders(request);
+
+ readBody(request);
+ } else {
+ readBody(request);
+ }
+
+ return request;
+ }
+
+ private boolean readRequestLine(HttpRequestPdu request) throws IOException {
+ RequestLineState state = RequestLineState.METHOD;
+
+ StringBuilder builder = new StringBuilder();
+
+ int currentByte;
+ while ((currentByte = in.read()) != -1) {
+ switch (state) {
+ case METHOD:
+ if (currentByte == ' ') {
+ request.setMethod(builder.toString());
+ builder.setLength(0);
+ state = RequestLineState.PATH;
+ break;
+ }
+
+ builder.append((char) currentByte);
+ break;
+ case PATH:
+ if (currentByte == ' ') {
+ request.setPath(builder.toString());
+ builder.setLength(0);
+ state = RequestLineState.VERSION;
+ break;
+ }
+
+ builder.append((char) currentByte);
+ break;
+ case VERSION:
+ if (currentByte == '\r') {
+ // Skip \n.
+ skip(1);
+
+ request.setVersion(builder.toString());
+ return true;
+ }
+
+ builder.append((char) currentByte);
+ break;
+ }
+ }
+
+ return false;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/http/reader/HttpResponseReader.java b/src/main/java/com/warxim/petep/extension/internal/http/reader/HttpResponseReader.java
new file mode 100644
index 0000000..b5213f8
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/http/reader/HttpResponseReader.java
@@ -0,0 +1,96 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.http.reader;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.Charset;
+import com.warxim.petep.core.pdu.PduDestination;
+import com.warxim.petep.extension.internal.http.pdu.HttpResponsePdu;
+
+public final class HttpResponseReader extends HttpReader {
+ protected enum StatusLineState {
+ VERSION, STATUS_CODE, STATUS_MESSAGE
+ }
+
+ public HttpResponseReader(InputStream in, int maxLength, Charset defaultCharset) {
+ super(in, maxLength, defaultCharset);
+ }
+
+ @Override
+ public HttpResponsePdu read() throws IOException {
+ HttpResponsePdu response = new HttpResponsePdu(null, null, PduDestination.CLIENT, null, 0);
+
+ if (internalState == null) {
+ if (!readStatusLine(response) || !readHeaders(response)) {
+ return null;
+ }
+
+ processHeaders(response);
+
+ readBody(response);
+ } else {
+ readBody(response);
+ }
+
+ return response;
+ }
+
+ private boolean readStatusLine(HttpResponsePdu response) throws IOException {
+ StatusLineState state = StatusLineState.VERSION;
+
+ StringBuilder builder = new StringBuilder();
+
+ int currentByte;
+ while ((currentByte = in.read()) != -1) {
+ switch (state) {
+ case VERSION:
+ if (currentByte == ' ') {
+ response.setVersion(builder.toString());
+ builder.setLength(0);
+ state = StatusLineState.STATUS_CODE;
+ break;
+ }
+
+ builder.append((char) currentByte);
+ break;
+ case STATUS_CODE:
+ if (currentByte == ' ') {
+ response.setStatusCode(Integer.parseInt(builder.toString()));
+ builder.setLength(0);
+ state = StatusLineState.STATUS_MESSAGE;
+ break;
+ }
+
+ builder.append((char) currentByte);
+ break;
+ case STATUS_MESSAGE:
+ if (currentByte == '\r') {
+ // Skip \n.
+ skip(1);
+
+ response.setStatusMessage(builder.toString());
+ return true;
+ }
+
+ builder.append((char) currentByte);
+ break;
+ }
+ }
+ return false;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/http/reader/PduReader.java b/src/main/java/com/warxim/petep/extension/internal/http/reader/PduReader.java
new file mode 100644
index 0000000..a754bc9
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/http/reader/PduReader.java
@@ -0,0 +1,31 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.http.reader;
+
+import java.io.IOException;
+import java.io.InputStream;
+import com.warxim.petep.core.pdu.PDU;
+
+public abstract class PduReader {
+ protected final InputStream in;
+
+ public PduReader(InputStream in) {
+ this.in = in;
+ }
+
+ public abstract PDU read() throws IOException;
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/http/reader/WebSocketReader.java b/src/main/java/com/warxim/petep/extension/internal/http/reader/WebSocketReader.java
new file mode 100644
index 0000000..42407ab
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/http/reader/WebSocketReader.java
@@ -0,0 +1,127 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.http.reader;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import com.warxim.petep.core.pdu.PduDestination;
+import com.warxim.petep.extension.internal.http.pdu.Opcode;
+import com.warxim.petep.extension.internal.http.pdu.WebSocketPdu;
+
+public final class WebSocketReader extends PduReader {
+ private final PduDestination destination;
+
+ public WebSocketReader(InputStream in, PduDestination destination) {
+ super(in);
+ this.destination = destination;
+ }
+
+ public WebSocketPdu read() throws IOException {
+ WebSocketPdu pdu = new WebSocketPdu(null, null, destination, null, 0);
+
+ readFragment(pdu);
+
+ // Set UTF8 for text.
+ if (pdu.getOpcode() == Opcode.TEXT) {
+ pdu.setCharset(StandardCharsets.UTF_8);
+ }
+
+ return pdu;
+ }
+
+ private void readFragment(WebSocketPdu pdu) throws IOException {
+ int currentByte;
+
+ currentByte = in.read();
+ if (currentByte == -1) {
+ throw new IOException("Could not read first WebSocket byte.");
+ }
+
+ // FIN
+ pdu.setFinal((currentByte & 0b1000_0000) != 0);
+
+ // RSV1
+ pdu.setRsv1((currentByte & 0b0100_0000) != 0);
+
+ // RSV2
+ pdu.setRsv2((currentByte & 0b0010_0000) != 0);
+
+ // RSV3
+ pdu.setRsv3((currentByte & 0b0001_0000) != 0);
+
+ // OPCODE
+ pdu.setOpcode(Opcode.valueOf(currentByte & 0b0000_1111));
+
+ currentByte = in.read();
+ if (currentByte == -1) {
+ throw new IOException("Could not read second WebSocket byte.");
+ }
+
+ // MASKED
+ pdu.setMasked((currentByte & 0b1000_0000) != 0);
+
+ // LENGTH
+ int length;
+ currentByte = currentByte & 0b0111_1111;
+ if (currentByte <= 125) {
+ // It's the length!
+ length = currentByte;
+ } else if (currentByte == 126) {
+ // The next 16 bits are the length.
+ currentByte = in.read();
+ if (currentByte == -1) {
+ throw new IOException("Could not read WebSocket length.");
+ }
+ length = (currentByte & 0xFF) << 8;
+
+ currentByte = in.read();
+ if (currentByte == -1) {
+ throw new IOException("Could not read WebSocket length.");
+ }
+ length |= (currentByte & 0xFF);
+ } else {
+ // The next 64 bits are the length.
+ throw new IOException("WebSocket message is too large.");
+ }
+
+ byte[] data = new byte[length];
+
+ // MASK
+ if (pdu.isMasked()) {
+ byte[] mask = in.readNBytes(4);
+
+ if (mask.length != 4) {
+ throw new IOException("Could not read WebSocket mask.");
+ }
+
+ pdu.setMask(mask);
+
+ if (in.readNBytes(data, 0, length) != length) {
+ throw new IOException("Could not read WebSocket data.");
+ }
+
+ for (int i = 0; i < data.length; ++i) {
+ data[i] ^= mask[i & 0x3];
+ }
+ } else if (in.readNBytes(data, 0, length) != length) {
+ throw new IOException("Could not read WebSocket data.");
+ }
+
+ pdu.setBuffer(data, length);
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/http/reader/state/BodyWithChunkedEncodingState.java b/src/main/java/com/warxim/petep/extension/internal/http/reader/state/BodyWithChunkedEncodingState.java
new file mode 100644
index 0000000..d19b045
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/http/reader/state/BodyWithChunkedEncodingState.java
@@ -0,0 +1,51 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.http.reader.state;
+
+public final class BodyWithChunkedEncodingState extends InternalState {
+ public enum ChunkedBodyStep {
+ LENGTH, CHUNK
+ }
+
+ private int chunkLength;
+ private ChunkedBodyStep step;
+
+ public BodyWithChunkedEncodingState() {
+ this.chunkLength = -1;
+ this.step = ChunkedBodyStep.LENGTH;
+ }
+
+ public int getChunkLength() {
+ return chunkLength;
+ }
+
+ public int decreaseChunkLength() {
+ return --chunkLength;
+ }
+
+ public void setChunkLength(int chunkLength) {
+ this.chunkLength = chunkLength;
+ }
+
+ public ChunkedBodyStep getChunkStep() {
+ return step;
+ }
+
+ public void setChunkStep(ChunkedBodyStep step) {
+ this.step = step;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/http/reader/state/BodyWithContentLengthState.java b/src/main/java/com/warxim/petep/extension/internal/http/reader/state/BodyWithContentLengthState.java
new file mode 100644
index 0000000..ab8cc58
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/http/reader/state/BodyWithContentLengthState.java
@@ -0,0 +1,43 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.http.reader.state;
+
+public final class BodyWithContentLengthState extends InternalState {
+ private int contentLength;
+ private boolean chunked;
+
+ public BodyWithContentLengthState(int contentLength) {
+ this.contentLength = contentLength;
+ this.chunked = false;
+ }
+
+ public int getContentLength() {
+ return contentLength;
+ }
+
+ public void setContentLength(int contentLength) {
+ this.contentLength = contentLength;
+ }
+
+ public boolean isChunked() {
+ return chunked;
+ }
+
+ public void setChunked(boolean chunked) {
+ this.chunked = chunked;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/http/reader/state/InternalState.java b/src/main/java/com/warxim/petep/extension/internal/http/reader/state/InternalState.java
new file mode 100644
index 0000000..f2e7025
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/http/reader/state/InternalState.java
@@ -0,0 +1,20 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.http.reader.state;
+
+public abstract class InternalState {
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/http/tagger/has_header/HasHeaderData.java b/src/main/java/com/warxim/petep/extension/internal/http/tagger/has_header/HasHeaderData.java
new file mode 100644
index 0000000..91c95b7
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/http/tagger/has_header/HasHeaderData.java
@@ -0,0 +1,37 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.http.tagger.has_header;
+
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData;
+
+public final class HasHeaderData extends TagSubruleData {
+ private final String name;
+ private final String value;
+
+ public HasHeaderData(String name, String value) {
+ this.name = name;
+ this.value = value;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getValue() {
+ return value;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/http/tagger/has_header/HasHeaderSubrule.java b/src/main/java/com/warxim/petep/extension/internal/http/tagger/has_header/HasHeaderSubrule.java
new file mode 100644
index 0000000..9703d52
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/http/tagger/has_header/HasHeaderSubrule.java
@@ -0,0 +1,46 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.http.tagger.has_header;
+
+import com.warxim.petep.core.pdu.PDU;
+import com.warxim.petep.extension.internal.http.pdu.HttpPdu;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubrule;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleFactory;
+
+public final class HasHeaderSubrule extends TagSubrule {
+ public HasHeaderSubrule(TagSubruleFactory factory, TagSubruleData data) {
+ super(factory, data);
+ }
+
+ @Override
+ public boolean test(PDU pdu) {
+ if (!(pdu instanceof HttpPdu)) {
+ return false;
+ }
+
+ String value = ((HttpPdu) pdu).getHeader(((HasHeaderData) data).getName());
+
+ return value != null && value.equals(((HasHeaderData) data).getValue());
+ }
+
+ @Override
+ public String toString() {
+ return "Has header " + ((HasHeaderData) data).getName() + " = "
+ + ((HasHeaderData) data).getValue();
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/http/tagger/has_header/HasHeaderSubruleConfigurator.java b/src/main/java/com/warxim/petep/extension/internal/http/tagger/has_header/HasHeaderSubruleConfigurator.java
new file mode 100644
index 0000000..4548772
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/http/tagger/has_header/HasHeaderSubruleConfigurator.java
@@ -0,0 +1,61 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.http.tagger.has_header;
+
+import java.io.IOException;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleConfigurator;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData;
+import com.warxim.petep.gui.dialog.Dialogs;
+import javafx.fxml.FXML;
+import javafx.scene.control.TextField;
+
+public final class HasHeaderSubruleConfigurator extends TagSubruleConfigurator {
+ @FXML
+ private TextField nameInput;
+ @FXML
+ private TextField valueInput;
+
+ public HasHeaderSubruleConfigurator() throws IOException {
+ super("/fxml/extension/internal/http/tagger/HasHeader.fxml");
+ }
+
+ @Override
+ public TagSubruleData getConfig() {
+ return new HasHeaderData(nameInput.getText(), valueInput.getText());
+ }
+
+ @Override
+ public void setConfig(TagSubruleData config) {
+ nameInput.setText(((HasHeaderData) config).getName());
+ valueInput.setText(((HasHeaderData) config).getValue());
+ }
+
+ @Override
+ public boolean isValid() {
+ if (nameInput.getText().length() == 0) {
+ Dialogs.createErrorDialog("Header name required", "You have to enter header name.");
+ return false;
+ }
+
+ if (valueInput.getText().length() == 0) {
+ Dialogs.createErrorDialog("Header value required", "You have to enter header value.");
+ return false;
+ }
+
+ return true;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/http/tagger/has_header/HasHeaderSubruleFactory.java b/src/main/java/com/warxim/petep/extension/internal/http/tagger/has_header/HasHeaderSubruleFactory.java
new file mode 100644
index 0000000..7bfd469
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/http/tagger/has_header/HasHeaderSubruleFactory.java
@@ -0,0 +1,51 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.http.tagger.has_header;
+
+import java.io.IOException;
+import java.lang.reflect.Type;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubrule;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleConfigurator;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleFactory;
+
+public final class HasHeaderSubruleFactory extends TagSubruleFactory {
+ @Override
+ public String getCode() {
+ return "header";
+ }
+
+ @Override
+ public String getName() {
+ return "Has header ...";
+ }
+
+ @Override
+ public TagSubrule createSubrule(TagSubruleData data) {
+ return new HasHeaderSubrule(this, data);
+ }
+
+ @Override
+ public TagSubruleConfigurator createConfigPane() throws IOException {
+ return new HasHeaderSubruleConfigurator();
+ }
+
+ @Override
+ public Type getConfigType() {
+ return HasHeaderData.class;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/http/tagger/is_http/IsHttpSubrule.java b/src/main/java/com/warxim/petep/extension/internal/http/tagger/is_http/IsHttpSubrule.java
new file mode 100644
index 0000000..59f2b3d
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/http/tagger/is_http/IsHttpSubrule.java
@@ -0,0 +1,39 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.http.tagger.is_http;
+
+import com.warxim.petep.core.pdu.PDU;
+import com.warxim.petep.extension.internal.http.pdu.HttpPdu;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubrule;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleFactory;
+
+public final class IsHttpSubrule extends TagSubrule {
+ public IsHttpSubrule(TagSubruleFactory factory, TagSubruleData data) {
+ super(factory, data);
+ }
+
+ @Override
+ public boolean test(PDU pdu) {
+ return pdu instanceof HttpPdu;
+ }
+
+ @Override
+ public String toString() {
+ return "Is HTTP";
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/http/tagger/is_http/IsHttpSubruleFactory.java b/src/main/java/com/warxim/petep/extension/internal/http/tagger/is_http/IsHttpSubruleFactory.java
new file mode 100644
index 0000000..66fd097
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/http/tagger/is_http/IsHttpSubruleFactory.java
@@ -0,0 +1,51 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.http.tagger.is_http;
+
+import java.io.IOException;
+import java.lang.reflect.Type;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubrule;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleConfigurator;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleFactory;
+
+public final class IsHttpSubruleFactory extends TagSubruleFactory {
+ @Override
+ public String getCode() {
+ return "is_http";
+ }
+
+ @Override
+ public String getName() {
+ return "Is HTTP?";
+ }
+
+ @Override
+ public TagSubrule createSubrule(TagSubruleData data) {
+ return new IsHttpSubrule(this, data);
+ }
+
+ @Override
+ public TagSubruleConfigurator createConfigPane() throws IOException {
+ return null;
+ }
+
+ @Override
+ public Type getConfigType() {
+ return null;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/http/tagger/is_websocket/IsWebSocketSubrule.java b/src/main/java/com/warxim/petep/extension/internal/http/tagger/is_websocket/IsWebSocketSubrule.java
new file mode 100644
index 0000000..14c5538
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/http/tagger/is_websocket/IsWebSocketSubrule.java
@@ -0,0 +1,39 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.http.tagger.is_websocket;
+
+import com.warxim.petep.core.pdu.PDU;
+import com.warxim.petep.extension.internal.http.pdu.WebSocketPdu;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubrule;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleFactory;
+
+public final class IsWebSocketSubrule extends TagSubrule {
+ public IsWebSocketSubrule(TagSubruleFactory factory, TagSubruleData data) {
+ super(factory, data);
+ }
+
+ @Override
+ public boolean test(PDU pdu) {
+ return pdu instanceof WebSocketPdu;
+ }
+
+ @Override
+ public String toString() {
+ return "Is WebSocket";
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/http/tagger/is_websocket/IsWebSocketSubruleFactory.java b/src/main/java/com/warxim/petep/extension/internal/http/tagger/is_websocket/IsWebSocketSubruleFactory.java
new file mode 100644
index 0000000..1ee5105
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/http/tagger/is_websocket/IsWebSocketSubruleFactory.java
@@ -0,0 +1,51 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.http.tagger.is_websocket;
+
+import java.io.IOException;
+import java.lang.reflect.Type;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubrule;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleConfigurator;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleFactory;
+
+public final class IsWebSocketSubruleFactory extends TagSubruleFactory {
+ @Override
+ public String getCode() {
+ return "is_websocket";
+ }
+
+ @Override
+ public String getName() {
+ return "Is WebSocket?";
+ }
+
+ @Override
+ public TagSubrule createSubrule(TagSubruleData data) {
+ return new IsWebSocketSubrule(this, data);
+ }
+
+ @Override
+ public TagSubruleConfigurator createConfigPane() throws IOException {
+ return null;
+ }
+
+ @Override
+ public Type getConfigType() {
+ return null;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/http/writer/HttpRequestWriter.java b/src/main/java/com/warxim/petep/extension/internal/http/writer/HttpRequestWriter.java
new file mode 100644
index 0000000..ba8d967
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/http/writer/HttpRequestWriter.java
@@ -0,0 +1,49 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.http.writer;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import com.warxim.petep.core.pdu.PDU;
+import com.warxim.petep.extension.internal.http.pdu.HttpPdu;
+import com.warxim.petep.extension.internal.http.pdu.HttpRequestPdu;
+
+public final class HttpRequestWriter extends HttpWriter {
+ public HttpRequestWriter(OutputStream out) {
+ super(out);
+ }
+
+ @Override
+ public void write(PDU request) throws IOException {
+ writeRequestLine((HttpRequestPdu) request);
+ writeHeaders((HttpPdu) request);
+ writeBody((HttpPdu) request);
+ }
+
+ private void writeRequestLine(HttpRequestPdu request) throws IOException {
+ if (request.getVersion() == null) {
+ return;
+ }
+
+ out.write(request.getMethod().getBytes());
+ out.write(' ');
+ out.write(request.getPath().getBytes());
+ out.write(' ');
+ out.write(request.getVersion().getBytes());
+ out.write("\r\n".getBytes());
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/http/writer/HttpResponseWriter.java b/src/main/java/com/warxim/petep/extension/internal/http/writer/HttpResponseWriter.java
new file mode 100644
index 0000000..fce7ca2
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/http/writer/HttpResponseWriter.java
@@ -0,0 +1,49 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.http.writer;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import com.warxim.petep.core.pdu.PDU;
+import com.warxim.petep.extension.internal.http.pdu.HttpPdu;
+import com.warxim.petep.extension.internal.http.pdu.HttpResponsePdu;
+
+public final class HttpResponseWriter extends HttpWriter {
+ public HttpResponseWriter(OutputStream out) {
+ super(out);
+ }
+
+ @Override
+ public void write(PDU response) throws IOException {
+ writeStatusLine((HttpResponsePdu) response);
+ writeHeaders((HttpPdu) response);
+ writeBody((HttpPdu) response);
+ }
+
+ private void writeStatusLine(HttpResponsePdu response) throws IOException {
+ if (response.getVersion() == null) {
+ return;
+ }
+
+ out.write(response.getVersion().getBytes());
+ out.write(' ');
+ out.write(String.valueOf(response.getStatusCode()).getBytes());
+ out.write(' ');
+ out.write(response.getStatusMessage().getBytes());
+ out.write("\r\n".getBytes());
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/http/writer/HttpWriter.java b/src/main/java/com/warxim/petep/extension/internal/http/writer/HttpWriter.java
new file mode 100644
index 0000000..b04ae70
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/http/writer/HttpWriter.java
@@ -0,0 +1,68 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.http.writer;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import com.warxim.petep.core.pdu.PDU;
+import com.warxim.petep.extension.internal.http.pdu.HttpPdu;
+
+public abstract class HttpWriter extends PduWriter {
+ public HttpWriter(OutputStream out) {
+ super(out);
+ }
+
+ public abstract void write(PDU pdu) throws IOException;
+
+ protected final void writeHeaders(HttpPdu pdu) throws IOException {
+ if (pdu.getHeaders().isEmpty()) {
+ return;
+ }
+
+ if (pdu.getHeader("Content-Length") != null) {
+ pdu.addHeader("Content-Length", String.valueOf(pdu.getSize()));
+ }
+
+ for (var header : pdu.getHeaders().entrySet()) {
+ out.write(header.getKey().getBytes());
+ out.write(": ".getBytes());
+ out.write(header.getValue().getBytes());
+ out.write("\r\n".getBytes());
+ }
+
+ out.write("\r\n".getBytes());
+ }
+
+ protected final void writeBody(HttpPdu pdu) throws IOException {
+ if (pdu.getSize() == 0) {
+ return;
+ }
+
+ if (pdu.hasTag("chunk") || pdu.hasTag("last_chunk")) {
+ out.write(Integer.toHexString(pdu.getSize()).getBytes());
+ out.write("\r\n".getBytes());
+ out.write(pdu.getBuffer(), 0, pdu.getSize());
+ out.write("\r\n".getBytes());
+
+ if (pdu.hasTag("last_chunk")) {
+ out.write("0\r\n\r\n".getBytes());
+ }
+ } else {
+ out.write(pdu.getBuffer(), 0, pdu.getSize());
+ }
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/http/writer/PduWriter.java b/src/main/java/com/warxim/petep/extension/internal/http/writer/PduWriter.java
new file mode 100644
index 0000000..3934912
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/http/writer/PduWriter.java
@@ -0,0 +1,31 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.http.writer;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import com.warxim.petep.core.pdu.PDU;
+
+public abstract class PduWriter {
+ protected final OutputStream out;
+
+ public PduWriter(OutputStream out) {
+ this.out = out;
+ }
+
+ public abstract void write(PDU pdu) throws IOException;
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/http/writer/WebSocketWriter.java b/src/main/java/com/warxim/petep/extension/internal/http/writer/WebSocketWriter.java
new file mode 100644
index 0000000..d243274
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/http/writer/WebSocketWriter.java
@@ -0,0 +1,97 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.http.writer;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import com.warxim.petep.core.pdu.PDU;
+import com.warxim.petep.extension.internal.http.pdu.WebSocketPdu;
+
+public final class WebSocketWriter extends PduWriter {
+ public WebSocketWriter(OutputStream out) {
+ super(out);
+ }
+
+ public void write(PDU pdu) throws IOException {
+ writeFragment((WebSocketPdu) pdu);
+ }
+
+ private void writeFragment(WebSocketPdu pdu) throws IOException {
+ int currentByte = 0;
+
+ // FIN
+ if (pdu.isFinal()) {
+ currentByte |= 0b1000_0000;
+ }
+
+ // RSV1
+ if (pdu.isRsv1()) {
+ currentByte |= 0b0100_0000;
+ }
+
+ // RSV2
+ if (pdu.isRsv2()) {
+ currentByte |= 0b0010_0000;
+ }
+
+ // RSV3
+ if (pdu.isRsv3()) {
+ currentByte |= 0b0001_0000;
+ }
+
+ // OPCODE
+ currentByte |= pdu.getOpcode().getValue() & 0b0000_1111;
+
+ out.write(currentByte);
+
+ // MASKED
+ if (pdu.isMasked()) {
+ currentByte = 0b1000_0000;
+ } else {
+ currentByte = 0b0000_0000;
+ }
+
+ // LENGTH
+ int length = pdu.getSize();
+ if (length <= 125) {
+ currentByte |= length & 0b0111_1111;
+ out.write(currentByte);
+ } else {
+ currentByte |= 126;
+ out.write(currentByte);
+
+ out.write((length >> 8) & 0xFF);
+ out.write(length & 0xFF);
+ }
+
+ if (pdu.isMasked()) {
+ byte[] mask = pdu.getMask();
+
+ out.write(mask, 0, 4);
+
+ byte[] data = pdu.getBuffer();
+
+ for (int i = 0; i < length; ++i) {
+ data[i] ^= mask[i & 0x3];
+ }
+
+ out.write(data, 0, length);
+ } else {
+ out.write(pdu.getBuffer(), 0, length);
+ }
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/logger/LoggerConfig.java b/src/main/java/com/warxim/petep/extension/internal/logger/LoggerConfig.java
new file mode 100644
index 0000000..5275013
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/logger/LoggerConfig.java
@@ -0,0 +1,31 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.logger;
+
+/** Logger configuration. */
+public final class LoggerConfig {
+ private final String path;
+
+ /** Logger configuration constructor. */
+ public LoggerConfig(String path) {
+ this.path = path;
+ }
+
+ public String getPath() {
+ return path;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/logger/LoggerConfigurator.java b/src/main/java/com/warxim/petep/extension/internal/logger/LoggerConfigurator.java
new file mode 100644
index 0000000..55de0f6
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/logger/LoggerConfigurator.java
@@ -0,0 +1,91 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.logger;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Paths;
+import com.warxim.petep.gui.component.ConfigPane;
+import com.warxim.petep.gui.dialog.Dialogs;
+import com.warxim.petep.util.FileUtils;
+import javafx.event.ActionEvent;
+import javafx.fxml.FXML;
+import javafx.scene.control.TextField;
+import javafx.stage.FileChooser;
+
+/** Logger configurator. */
+public class LoggerConfigurator extends ConfigPane {
+
+ @FXML
+ private TextField pathInput;
+
+ /** Logger configurator constructor. */
+ public LoggerConfigurator() throws IOException {
+ super("/fxml/extension/internal/logger/LoggerConfigurator.fxml");
+ }
+
+ @Override
+ public LoggerConfig getConfig() {
+ return new LoggerConfig(pathInput.getText());
+ }
+
+ @Override
+ public void setConfig(LoggerConfig config) {
+ pathInput.setText(config.getPath());
+ }
+
+ @Override
+ public boolean isValid() {
+ if (pathInput.getText().length() == 0) {
+ Dialogs.createErrorDialog("Path required", "You have to enter path.");
+ return false;
+ }
+
+ return true;
+ }
+
+ @FXML
+ private void onFileOpenButtonClick(ActionEvent event) {
+ // Choose log file
+ FileChooser fileChooser = new FileChooser();
+ fileChooser.setTitle("Log file");
+
+ if (pathInput.getText().isBlank()) {
+ fileChooser.setInitialDirectory(new File(FileUtils.getProjectDirectory()));
+ } else {
+ File temp = new File(FileUtils.getProjectFileAbsolutePath(pathInput.getText()));
+ fileChooser.setInitialDirectory(temp.getParentFile());
+ fileChooser.setInitialFileName(temp.getName());
+ }
+
+ fileChooser.getExtensionFilters()
+ .addAll(new FileChooser.ExtensionFilter("Log file (*.log)", "*.log"),
+ new FileChooser.ExtensionFilter("Text file (*.txt)", "*.txt"),
+ new FileChooser.ExtensionFilter("All files (*.*)", "*.*"));
+
+ File file = fileChooser.showSaveDialog(null);
+ if (file == null) {
+ return;
+ }
+
+ pathInput.setText(Paths.get(FileUtils.getProjectDirectory())
+ .toAbsolutePath()
+ .relativize(Paths.get(file.getAbsolutePath()))
+ .toString()
+ .replace('\\', '/'));
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/logger/LoggerExtension.java b/src/main/java/com/warxim/petep/extension/internal/logger/LoggerExtension.java
new file mode 100644
index 0000000..d0b5d4a
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/logger/LoggerExtension.java
@@ -0,0 +1,123 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.logger;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.logging.Logger;
+import com.warxim.petep.core.listener.PetepListener;
+import com.warxim.petep.extension.Extension;
+import com.warxim.petep.helper.ExtensionHelper;
+import com.warxim.petep.helper.GuiHelper;
+import com.warxim.petep.helper.PetepHelper;
+import com.warxim.petep.interceptor.worker.Interceptor;
+
+/** Logger extension. */
+public final class LoggerExtension extends Extension {
+ private ExecutorService executor;
+
+ /** Logger extension constructor. */
+ public LoggerExtension(String path) {
+ super(path);
+
+ executor = null;
+
+ Logger.getGlobal().info("Logger extension created.");
+ }
+
+ @Override
+ public void init(ExtensionHelper helper) {
+ helper.registerInterceptorModuleFactory(new LoggerInterceptorModuleFactory(this));
+
+ helper.registerPetepListener(new PetepListener() {
+ /** Creates workfer for each log file. */
+ private void processInterceptors(
+ List interceptors,
+ Map workers) {
+ for (Interceptor interceptor : interceptors) {
+ if (interceptor instanceof LoggerInterceptor) {
+ // Get or create a log worker
+ LoggerWorker worker = workers.computeIfAbsent(
+ ((LoggerInterceptorModule) interceptor.getModule()).getConfig().getPath(),
+ LoggerWorker::new);
+
+ ((LoggerInterceptor) interceptor).setWorker(worker);
+ }
+ }
+ }
+
+ @Override
+ public void beforePrepare(PetepHelper helper) {
+ Map workers = new HashMap<>();
+
+ // Process interceptors.
+
+ processInterceptors(helper.getInterceptorsC2S(), workers);
+ processInterceptors(helper.getInterceptorsS2C(), workers);
+
+ if (workers.isEmpty()) {
+ return;
+ }
+
+ // Start workers.
+ executor = Executors.newCachedThreadPool();
+
+ for (LoggerWorker worker : workers.values()) {
+ executor.submit(worker);
+ }
+ }
+
+ @Override
+ public void afterStop(PetepHelper helper) {
+ if (executor != null) {
+ executor.shutdownNow();
+ executor = null;
+ }
+ }
+ });
+
+ Logger.getGlobal().info("Logger extension registered.");
+ }
+
+ @Override
+ public String getCode() {
+ return "logger";
+ }
+
+ @Override
+ public String getName() {
+ return "Logger";
+ }
+
+ @Override
+ public String getDescription() {
+ return "Internal logger extension.";
+ }
+
+ @Override
+ public String getVersion() {
+ return "1.0";
+ }
+
+ @Override
+ public void initGui(GuiHelper helper) {
+ helper.registerGuide(new LoggerGuide());
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/logger/LoggerGuide.java b/src/main/java/com/warxim/petep/extension/internal/logger/LoggerGuide.java
new file mode 100644
index 0000000..983422d
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/logger/LoggerGuide.java
@@ -0,0 +1,32 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.logger;
+
+import com.warxim.petep.gui.guide.Guide;
+
+/** Logger guide. */
+public final class LoggerGuide extends Guide {
+ @Override
+ public String getTitle() {
+ return "Logger";
+ }
+
+ @Override
+ public String getHtml() {
+ return loadHtmlResource("/html/guide/internal/LoggerGuide.html");
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/logger/LoggerInterceptor.java b/src/main/java/com/warxim/petep/extension/internal/logger/LoggerInterceptor.java
new file mode 100644
index 0000000..0e3d513
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/logger/LoggerInterceptor.java
@@ -0,0 +1,54 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.logger;
+
+import com.warxim.petep.core.pdu.PDU;
+import com.warxim.petep.helper.PetepHelper;
+import com.warxim.petep.interceptor.worker.Interceptor;
+
+/** Logger interceptor. */
+public final class LoggerInterceptor extends Interceptor {
+ private LoggerWorker worker;
+
+ /** Logger interceptor constructor. */
+ public LoggerInterceptor(int id, LoggerInterceptorModule module, PetepHelper helper) {
+ super(id, module, helper);
+ }
+
+ @Override
+ public boolean intercept(PDU pdu) {
+ if (!pdu.hasTag("no_log") || pdu.hasTag("log")) {
+ worker.log(pdu.copy());
+ }
+
+ return true;
+ }
+
+ @Override
+ public boolean prepare() {
+ return true;
+ }
+
+ @Override
+ public void stop() {
+ // No action needed.
+ }
+
+ public void setWorker(LoggerWorker worker) {
+ this.worker = worker;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/logger/LoggerInterceptorModule.java b/src/main/java/com/warxim/petep/extension/internal/logger/LoggerInterceptorModule.java
new file mode 100644
index 0000000..7aed134
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/logger/LoggerInterceptorModule.java
@@ -0,0 +1,57 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.logger;
+
+import com.warxim.petep.helper.PetepHelper;
+import com.warxim.petep.interceptor.module.InterceptorModule;
+import com.warxim.petep.interceptor.worker.Interceptor;
+import com.warxim.petep.persistence.Configurable;
+
+/** Logger interceptor module. */
+public final class LoggerInterceptorModule extends InterceptorModule
+ implements Configurable {
+ private LoggerConfig config;
+
+ /** Logger interceptor module constructor. */
+ public LoggerInterceptorModule(
+ LoggerInterceptorModuleFactory factory,
+ String code,
+ String name,
+ String description,
+ boolean enabled) {
+ super(factory, code, name, description, enabled);
+ }
+
+ @Override
+ public LoggerConfig saveConfig() {
+ return config;
+ }
+
+ @Override
+ public void loadConfig(LoggerConfig config) {
+ this.config = config;
+ }
+
+ @Override
+ public Interceptor createInterceptor(int id, PetepHelper helper) {
+ return new LoggerInterceptor(id, this, helper);
+ }
+
+ public LoggerConfig getConfig() {
+ return config;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/logger/LoggerInterceptorModuleFactory.java b/src/main/java/com/warxim/petep/extension/internal/logger/LoggerInterceptorModuleFactory.java
new file mode 100644
index 0000000..ab04a4e
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/logger/LoggerInterceptorModuleFactory.java
@@ -0,0 +1,57 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.logger;
+
+import java.io.IOException;
+import com.warxim.petep.extension.Extension;
+import com.warxim.petep.gui.component.ConfigPane;
+import com.warxim.petep.interceptor.factory.InterceptorModuleFactory;
+import com.warxim.petep.interceptor.module.InterceptorModule;
+import com.warxim.petep.persistence.Configurator;
+
+/** Logger interceptor module factory. */
+public final class LoggerInterceptorModuleFactory extends InterceptorModuleFactory
+ implements Configurator {
+ /** Logger interceptor module factory constructor. */
+ public LoggerInterceptorModuleFactory(Extension extension) {
+ super(extension);
+ }
+
+ @Override
+ public String getName() {
+ return "Logger";
+ }
+
+ @Override
+ public String getCode() {
+ return "logger";
+ }
+
+ @Override
+ public InterceptorModule createModule(
+ String code,
+ String name,
+ String description,
+ boolean enabled) {
+ return new LoggerInterceptorModule(this, code, name, description, enabled);
+ }
+
+ @Override
+ public ConfigPane createConfigPane() throws IOException {
+ return new LoggerConfigurator();
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/logger/LoggerWorker.java b/src/main/java/com/warxim/petep/extension/internal/logger/LoggerWorker.java
new file mode 100644
index 0000000..42ca8ba
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/logger/LoggerWorker.java
@@ -0,0 +1,160 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.logger;
+
+import java.io.BufferedWriter;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Map;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import com.warxim.petep.common.Constant;
+import com.warxim.petep.core.pdu.PDU;
+import com.warxim.petep.core.pdu.PduDestination;
+import com.warxim.petep.core.pdu.PduQueue;
+import com.warxim.petep.proxy.serizalization.ProxySerializer;
+import com.warxim.petep.proxy.worker.Proxy;
+import com.warxim.petep.util.FileUtils;
+import com.warxim.petep.util.PduUtils;
+
+/** Logger worker. */
+public final class LoggerWorker implements Runnable {
+ private static final int RECORDS_PER_FILE = 10000;
+ private final PduQueue queue;
+ private final String path;
+ private final SimpleDateFormat formatter;
+
+ /** Logger worker constructor. */
+ public LoggerWorker(String path) {
+ this.queue = new PduQueue();
+ this.path = path;
+ this.formatter = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
+ }
+
+ public void log(PDU pdu) {
+ queue.add(pdu);
+ }
+
+ @Override
+ public void run() {
+ Logger.getGlobal().info("Logger for path '" + path + "' started.");
+
+ Path source = Paths.get(FileUtils.getProjectFileAbsolutePath(path));
+
+ while (log()) {
+ // Create backup
+ try {
+ if (source.getFileName().toString().contains(".")) {
+ // [FILE_NAME].backup_[timestamp].[EXTENSION]
+ Files.move(source,
+ source.resolveSibling(source.getFileName()
+ .toString()
+ .replaceFirst("(.+)[.]([^.]+)$",
+ "$1.backup_" + (System.currentTimeMillis() / 100) + ".$2")));
+ } else {
+ // [FILE_NAME]_backup_[timestamp]
+ Files.move(source, source.resolveSibling(
+ source.getFileName() + "_backup_" + (System.currentTimeMillis() / 100)));
+ }
+ } catch (IOException e) {
+ Logger.getGlobal().log(Level.SEVERE, "Logger encountered an exception.", e);
+ }
+ }
+ }
+
+ /** Logging to file. Returns true if logging should continue. */
+ private boolean log() {
+ try (PrintWriter writer = new PrintWriter(
+ new BufferedWriter(new FileWriter(FileUtils.getProjectFileAbsolutePath(path), true)))) {
+ PDU pdu;
+
+ int counter = 0;
+ while ((pdu = queue.take()) != null) {
+ // Info
+ Proxy proxy = pdu.getProxy();
+ writer.write("###############################################\r\nTime: ");
+ writer.write(formatter.format(new Date()));
+ writer.write("\r\nProxy: ");
+ writer.write(proxy.getModule().getCode());
+ writer.write("\r\nDestination: ");
+ writer.write(pdu.getDestination() == PduDestination.CLIENT ? "client" : "server");
+ writer.write("\r\nConnection: ");
+ writer.write(String.valueOf(pdu.getConnection().getId()));
+
+ // Tags
+ Set tags = pdu.getTags();
+ if (!tags.isEmpty()) {
+ writer.write("\r\nTags: ");
+ writer.write(PduUtils.tagsToString(tags));
+ }
+
+ // Meta data
+ ProxySerializer serializer = proxy.getModule().getFactory().getSerializer();
+ if (serializer != null) {
+ Map metadata = serializer.serializePduMetadata(pdu);
+
+ if (metadata != null && !metadata.isEmpty()) {
+ writer.write("\r\nMeta data:\r\n");
+ for (var item : metadata.entrySet()) {
+ writer.write("\t");
+ writer.write(item.getKey());
+ writer.write(": ");
+ writer.write(item.getValue());
+ writer.write("\r\n");
+ }
+ } else {
+ writer.write("\r\n");
+ }
+ } else {
+ writer.write("\r\n");
+ }
+
+ // Data
+ writer.write("Data [bytes]:\r\n-----------------------------\r\n");
+ writer.write(PduUtils.bufferToString(pdu));
+ writer.write(
+ "\r\n-----------------------------\r\nData [string]:\r\n-----------------------------\r\n");
+ writer.write(new String(pdu.getBuffer(), 0, pdu.getSize(), Constant.DEFAULT_CHARSET));
+ writer.write("\r\n-----------------------------\r\n\r\n");
+
+ // Create backup.
+ if (++counter == RECORDS_PER_FILE) {
+ return true;
+ }
+
+ // Save the buffered data if there are no PDUs waiting in the queue.
+ if (queue.isEmpty()) {
+ writer.flush();
+ }
+ }
+ } catch (IOException e) {
+ Logger.getGlobal().log(Level.SEVERE, "Logger stopped with exception.", e);
+ } catch (InterruptedException e) {
+ // Interrupted.
+ Thread.currentThread().interrupt();
+ }
+
+ return false;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/modifier/ModifierApi.java b/src/main/java/com/warxim/petep/extension/internal/modifier/ModifierApi.java
new file mode 100644
index 0000000..b132b26
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/modifier/ModifierApi.java
@@ -0,0 +1,27 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.modifier;
+
+import com.warxim.petep.extension.PetepAPI;
+import com.warxim.petep.extension.internal.modifier.factory.ModifierFactory;
+
+@PetepAPI
+/** Interface for registration of modifier factories. */
+public interface ModifierApi {
+ /** Registers modifier factories. */
+ boolean registerModifierFactory(ModifierFactory factory);
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/modifier/ModifierExtension.java b/src/main/java/com/warxim/petep/extension/internal/modifier/ModifierExtension.java
new file mode 100644
index 0000000..d766062
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/modifier/ModifierExtension.java
@@ -0,0 +1,172 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.modifier;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonParseException;
+import com.warxim.petep.extension.Extension;
+import com.warxim.petep.extension.internal.common.rule_group.RuleGroup;
+import com.warxim.petep.extension.internal.common.rule_group.gui.RuleGroupsGuiFactory;
+import com.warxim.petep.extension.internal.modifier.config.ModifierConfig;
+import com.warxim.petep.extension.internal.modifier.config.ModifyRuleConfig;
+import com.warxim.petep.extension.internal.modifier.config.ModifyRuleGroupConfig;
+import com.warxim.petep.extension.internal.modifier.factory.ModifierFactory;
+import com.warxim.petep.extension.internal.modifier.factory.ModifierFactoryManager;
+import com.warxim.petep.extension.internal.modifier.factory.internal.replace.ReplacerFactory;
+import com.warxim.petep.extension.internal.modifier.gui.ModifierController;
+import com.warxim.petep.extension.internal.modifier.intercept.ModifierInterceptorModuleFactory;
+import com.warxim.petep.extension.internal.modifier.rule.ModifyRule;
+import com.warxim.petep.extension.internal.modifier.rule.ModifyRuleGroupManager;
+import com.warxim.petep.helper.ExtensionHelper;
+import com.warxim.petep.helper.GuiHelper;
+import com.warxim.petep.persistence.Storable;
+
+public final class ModifierExtension extends Extension
+ implements Storable, ModifierApi {
+ private final ModifierFactoryManager moduleManager;
+ private final ModifyRuleGroupManager groupManager;
+
+ private ExtensionHelper helper;
+ private ModifierConfig config;
+
+ public ModifierExtension(String path) {
+ super(path);
+
+ moduleManager = new ModifierFactoryManager();
+ groupManager = new ModifyRuleGroupManager();
+ }
+
+ @Override
+ public void init(ExtensionHelper helper) {
+ this.helper = helper;
+
+ moduleManager.registerFactory(new ReplacerFactory());
+
+ initGroupManager();
+
+ helper.registerInterceptorModuleFactory(new ModifierInterceptorModuleFactory(this));
+ }
+
+ @Override
+ public void initGui(GuiHelper helper) {
+ try {
+ helper.registerTab("Modifier", RuleGroupsGuiFactory
+ .createRoleGroupsNode(new ModifierController(groupManager, this.helper, moduleManager)));
+ } catch (IOException e) {
+ Logger.getGlobal().log(Level.SEVERE, "Could not load modifier tab!", e);
+ }
+
+ helper.registerGuide(new ModifierGuide());
+ }
+
+ @Override
+ public String getCode() {
+ return "modifier";
+ }
+
+ @Override
+ public String getName() {
+ return "Modifier";
+ }
+
+ @Override
+ public String getDescription() {
+ return "Process PDUs using different algorithms for replacing etc.";
+ }
+
+ @Override
+ public String getVersion() {
+ return "0.5";
+ }
+
+ public ModifyRuleGroupManager getRuleGroupManager() {
+ return groupManager;
+ }
+
+ @Override
+ public ModifierConfig saveStore() {
+ List groups = new ArrayList<>(groupManager.size());
+
+ for (RuleGroup group : groupManager.getList()) {
+ List rules = new ArrayList<>(group.size());
+
+ for (ModifyRule rule : group.getRules()) {
+ rules.add(new ModifyRuleConfig(rule.getName(), rule.getDescription(), rule.isEnabled(),
+ rule.getTag(), rule.getModifier().getFactory().getCode(),
+ rule.getModifier().getData()));
+ }
+
+ groups.add(new ModifyRuleGroupConfig(group.getCode(), group.getName(), rules));
+ }
+
+ return new ModifierConfig(groups);
+ }
+
+ @Override
+ public void loadStore(ModifierConfig store) {
+ config = store;
+ }
+
+ private void initGroupManager() {
+ Gson gson = new GsonBuilder().create();
+
+ if (config != null) {
+ // Process groups.
+ for (ModifyRuleGroupConfig groupConfig : config.getGroups()) {
+ RuleGroup group = new RuleGroup<>(groupConfig.getCode(), groupConfig.getName());
+
+ // Process rules.
+ for (ModifyRuleConfig ruleConfig : groupConfig.getRules()) {
+ ModifierFactory module = moduleManager.getFactory(ruleConfig.getFactoryCode());
+
+ // No module found.
+ if (module == null) {
+ Logger.getGlobal()
+ .severe("Could not load module " + ruleConfig.getFactoryCode() + " - rule "
+ + ruleConfig.getName() + " not loaded!");
+ continue;
+ }
+
+ // Add rule.
+ try {
+ group.addRule(new ModifyRule(ruleConfig.getName(), ruleConfig.getDescription(),
+ ruleConfig.isEnabled(), ruleConfig.getTag(), module
+ .createModifier(gson.fromJson(ruleConfig.getData(), module.getConfigType()))));
+ } catch (JsonParseException e) {
+ Logger.getGlobal()
+ .log(Level.SEVERE, "Could not load rule " + ruleConfig.getName() + "!", e);
+ }
+ }
+
+ groupManager.add(group);
+ }
+
+ config = null;
+ }
+ }
+
+ @Override
+ public boolean registerModifierFactory(ModifierFactory module) {
+ return moduleManager.registerFactory(module);
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/modifier/ModifierGuide.java b/src/main/java/com/warxim/petep/extension/internal/modifier/ModifierGuide.java
new file mode 100644
index 0000000..a22a5a0
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/modifier/ModifierGuide.java
@@ -0,0 +1,32 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.modifier;
+
+import com.warxim.petep.gui.guide.Guide;
+
+/** Modifier guide. */
+public final class ModifierGuide extends Guide {
+ @Override
+ public String getTitle() {
+ return "Modifier";
+ }
+
+ @Override
+ public String getHtml() {
+ return loadHtmlResource("/html/guide/internal/ModifierGuide.html");
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/modifier/config/ModifierConfig.java b/src/main/java/com/warxim/petep/extension/internal/modifier/config/ModifierConfig.java
new file mode 100644
index 0000000..a595eaa
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/modifier/config/ModifierConfig.java
@@ -0,0 +1,32 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.modifier.config;
+
+import java.util.List;
+
+public final class ModifierConfig {
+ private final List groups;
+
+ /** Modifier configuration constructor. */
+ public ModifierConfig(List groups) {
+ this.groups = groups;
+ }
+
+ public List getGroups() {
+ return groups;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/modifier/config/ModifyRuleConfig.java b/src/main/java/com/warxim/petep/extension/internal/modifier/config/ModifyRuleConfig.java
new file mode 100644
index 0000000..a89c323
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/modifier/config/ModifyRuleConfig.java
@@ -0,0 +1,72 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.modifier.config;
+
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonElement;
+import com.warxim.petep.extension.internal.modifier.factory.ModifierData;
+
+/** Configuration of modify rule. */
+public final class ModifyRuleConfig {
+ private final String name;
+ private final String description;
+ private final boolean enabled;
+ private final String tag;
+ private final String factoryCode;
+ private final JsonElement data;
+
+ /** Modify rule config constructor. */
+ public ModifyRuleConfig(
+ String name,
+ String description,
+ boolean enabled,
+ String tag,
+ String factoryCode,
+ ModifierData data) {
+ this.name = name;
+ this.description = description;
+ this.enabled = enabled;
+ this.tag = tag;
+ this.factoryCode = factoryCode;
+
+ this.data = new GsonBuilder().setPrettyPrinting().create().toJsonTree(data);
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public boolean isEnabled() {
+ return enabled;
+ }
+
+ public String getTag() {
+ return tag;
+ }
+
+ public String getFactoryCode() {
+ return factoryCode;
+ }
+
+ public JsonElement getData() {
+ return data;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/modifier/config/ModifyRuleGroupConfig.java b/src/main/java/com/warxim/petep/extension/internal/modifier/config/ModifyRuleGroupConfig.java
new file mode 100644
index 0000000..231093b
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/modifier/config/ModifyRuleGroupConfig.java
@@ -0,0 +1,45 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.modifier.config;
+
+import java.util.List;
+
+/** Configuration of group of modify rules. */
+public final class ModifyRuleGroupConfig {
+ private final String code;
+ private final String name;
+ private final List rules;
+
+ /** Modify rule group config. */
+ public ModifyRuleGroupConfig(String code, String name, List rules) {
+ this.code = code;
+ this.name = name;
+ this.rules = rules;
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public List getRules() {
+ return rules;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/modifier/factory/Modifier.java b/src/main/java/com/warxim/petep/extension/internal/modifier/factory/Modifier.java
new file mode 100644
index 0000000..669c934
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/modifier/factory/Modifier.java
@@ -0,0 +1,52 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.modifier.factory;
+
+import com.warxim.petep.core.pdu.PDU;
+import com.warxim.petep.extension.PetepAPI;
+
+@PetepAPI
+public abstract class Modifier {
+ protected final ModifierFactory factory;
+
+ protected ModifierData data;
+
+ public Modifier(ModifierFactory factory, ModifierData data) {
+ this.factory = factory;
+ this.data = data;
+ }
+
+ public ModifierFactory getFactory() {
+ return factory;
+ }
+
+ public ModifierData getData() {
+ return data;
+ }
+
+ /**
+ * Processes PDU in the modifier.
+ *
+ * @return FALSE if PDU should be dropped.
+ */
+ public abstract boolean process(PDU pdu);
+
+ @Override
+ public String toString() {
+ return factory.getName();
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/modifier/factory/ModifierConfigurator.java b/src/main/java/com/warxim/petep/extension/internal/modifier/factory/ModifierConfigurator.java
new file mode 100644
index 0000000..b5753d3
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/modifier/factory/ModifierConfigurator.java
@@ -0,0 +1,28 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.modifier.factory;
+
+import java.io.IOException;
+import com.warxim.petep.extension.PetepAPI;
+import com.warxim.petep.gui.component.ConfigPane;
+
+@PetepAPI
+public abstract class ModifierConfigurator extends ConfigPane {
+ public ModifierConfigurator(String template) throws IOException {
+ super(template);
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/modifier/factory/ModifierData.java b/src/main/java/com/warxim/petep/extension/internal/modifier/factory/ModifierData.java
new file mode 100644
index 0000000..4c58869
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/modifier/factory/ModifierData.java
@@ -0,0 +1,24 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.modifier.factory;
+
+import com.warxim.petep.extension.PetepAPI;
+
+/** Processor data. */
+@PetepAPI
+public class ModifierData {
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/modifier/factory/ModifierFactory.java b/src/main/java/com/warxim/petep/extension/internal/modifier/factory/ModifierFactory.java
new file mode 100644
index 0000000..d291317
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/modifier/factory/ModifierFactory.java
@@ -0,0 +1,45 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.modifier.factory;
+
+import java.io.IOException;
+import java.lang.reflect.Type;
+import com.warxim.petep.extension.PetepAPI;
+
+/** Modifier factory. */
+@PetepAPI
+public abstract class ModifierFactory {
+ /** Returns factory code (for configuration purposes). */
+ public abstract String getCode();
+
+ /** Returns factory name (visible for user). */
+ public abstract String getName();
+
+ /** Creates modifier using given data. */
+ public abstract Modifier createModifier(ModifierData data);
+
+ /** Creates config pane for modifier data. */
+ public abstract ModifierConfigurator createConfigPane() throws IOException;
+
+ /** Returns type of configuration, so it can be deserialized from JSON configuration. */
+ public abstract Type getConfigType();
+
+ @Override
+ public String toString() {
+ return getName();
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/modifier/factory/ModifierFactoryManager.java b/src/main/java/com/warxim/petep/extension/internal/modifier/factory/ModifierFactoryManager.java
new file mode 100644
index 0000000..ab9455e
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/modifier/factory/ModifierFactoryManager.java
@@ -0,0 +1,44 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.modifier.factory;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/** Modifier factory manager. */
+public final class ModifierFactoryManager {
+ private final Map factories;
+
+ /** MOdifier factory manager constructor. */
+ public ModifierFactoryManager() {
+ factories = new ConcurrentHashMap<>();
+ }
+
+ public boolean registerFactory(ModifierFactory factory) {
+ return factories.putIfAbsent(factory.getCode(), factory) == null;
+ }
+
+ public ModifierFactory getFactory(String code) {
+ return factories.get(code);
+ }
+
+ public List getFactories() {
+ return new ArrayList<>(factories.values());
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/modifier/factory/internal/replace/Replacer.java b/src/main/java/com/warxim/petep/extension/internal/modifier/factory/internal/replace/Replacer.java
new file mode 100644
index 0000000..0420605
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/modifier/factory/internal/replace/Replacer.java
@@ -0,0 +1,43 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.modifier.factory.internal.replace;
+
+import com.warxim.petep.core.pdu.PDU;
+import com.warxim.petep.extension.internal.modifier.factory.Modifier;
+import com.warxim.petep.extension.internal.modifier.factory.ModifierData;
+import com.warxim.petep.extension.internal.modifier.factory.ModifierFactory;
+import com.warxim.petep.util.PduUtils;
+
+public final class Replacer extends Modifier {
+ public Replacer(ModifierFactory factory, ModifierData data) {
+ super(factory, data);
+ }
+
+ @Override
+ public boolean process(PDU pdu) {
+ ReplacerData rule = (ReplacerData) data;
+
+ // run replace
+ if (rule.getOccurrence() == -1) {
+ PduUtils.replace(pdu, rule.getWhat(), rule.getWith());
+ } else {
+ PduUtils.replace(pdu, rule.getWhat(), rule.getWith(), rule.getOccurrence());
+ }
+
+ return true;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/modifier/factory/internal/replace/ReplacerConfigurator.java b/src/main/java/com/warxim/petep/extension/internal/modifier/factory/internal/replace/ReplacerConfigurator.java
new file mode 100644
index 0000000..8f64f69
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/modifier/factory/internal/replace/ReplacerConfigurator.java
@@ -0,0 +1,70 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.modifier.factory.internal.replace;
+
+import java.io.IOException;
+import com.warxim.petep.extension.internal.modifier.factory.ModifierConfigurator;
+import com.warxim.petep.extension.internal.modifier.factory.ModifierData;
+import com.warxim.petep.gui.control.BytesEditor;
+import com.warxim.petep.gui.dialog.Dialogs;
+import javafx.fxml.FXML;
+import javafx.scene.control.TextField;
+
+public final class ReplacerConfigurator extends ModifierConfigurator {
+ @FXML
+ private TextField occurrenceInput;
+
+ @FXML
+ private BytesEditor whatInput;
+
+ @FXML
+ private BytesEditor withInput;
+
+ public ReplacerConfigurator() throws IOException {
+ super("/fxml/extension/internal/modifier/factory/Replace.fxml");
+
+ occurrenceInput.setText("-1");
+ }
+
+ @Override
+ public ModifierData getConfig() {
+ return new ReplacerData(Integer.parseInt(occurrenceInput.getText()), whatInput.getBytes(),
+ withInput.getBytes());
+ }
+
+ @Override
+ public void setConfig(ModifierData config) {
+ occurrenceInput.setText(String.valueOf(((ReplacerData) config).getOccurrence()));
+ whatInput.setBytes(((ReplacerData) config).getWhat());
+ withInput.setBytes(((ReplacerData) config).getWith());
+ }
+
+ @Override
+ public boolean isValid() {
+ if (occurrenceInput.getText().length() == 0) {
+ Dialogs.createErrorDialog("Occurrence required", "You have to enter occurrence.");
+ return false;
+ }
+
+ if (whatInput.getBytes().length == 0) {
+ Dialogs.createErrorDialog("What required", "You have to enter what.");
+ return false;
+ }
+
+ return true;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/modifier/factory/internal/replace/ReplacerData.java b/src/main/java/com/warxim/petep/extension/internal/modifier/factory/internal/replace/ReplacerData.java
new file mode 100644
index 0000000..71ae8f2
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/modifier/factory/internal/replace/ReplacerData.java
@@ -0,0 +1,45 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.modifier.factory.internal.replace;
+
+import com.warxim.petep.extension.internal.modifier.factory.ModifierData;
+
+public final class ReplacerData extends ModifierData {
+ /** 0 = replace all, 1 .. n = replace n-th occurrence. */
+ private final int occurrence;
+
+ private final byte[] what;
+ private final byte[] with;
+
+ public ReplacerData(int occurrence, byte[] what, byte[] with) {
+ this.occurrence = occurrence;
+ this.what = what;
+ this.with = with;
+ }
+
+ public int getOccurrence() {
+ return occurrence;
+ }
+
+ public byte[] getWhat() {
+ return what;
+ }
+
+ public byte[] getWith() {
+ return with;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/modifier/factory/internal/replace/ReplacerFactory.java b/src/main/java/com/warxim/petep/extension/internal/modifier/factory/internal/replace/ReplacerFactory.java
new file mode 100644
index 0000000..dcd8216
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/modifier/factory/internal/replace/ReplacerFactory.java
@@ -0,0 +1,51 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.modifier.factory.internal.replace;
+
+import java.io.IOException;
+import java.lang.reflect.Type;
+import com.warxim.petep.extension.internal.modifier.factory.Modifier;
+import com.warxim.petep.extension.internal.modifier.factory.ModifierConfigurator;
+import com.warxim.petep.extension.internal.modifier.factory.ModifierData;
+import com.warxim.petep.extension.internal.modifier.factory.ModifierFactory;
+
+public final class ReplacerFactory extends ModifierFactory {
+ @Override
+ public String getCode() {
+ return "replace";
+ }
+
+ @Override
+ public String getName() {
+ return "Replace";
+ }
+
+ @Override
+ public Type getConfigType() {
+ return ReplacerData.class;
+ }
+
+ @Override
+ public Modifier createModifier(ModifierData data) {
+ return new Replacer(this, data);
+ }
+
+ @Override
+ public ModifierConfigurator createConfigPane() throws IOException {
+ return new ReplacerConfigurator();
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/modifier/gui/ModifierController.java b/src/main/java/com/warxim/petep/extension/internal/modifier/gui/ModifierController.java
new file mode 100644
index 0000000..28eb834
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/modifier/gui/ModifierController.java
@@ -0,0 +1,61 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.modifier.gui;
+
+import java.io.IOException;
+import com.warxim.petep.extension.internal.common.rule_group.RuleGroup;
+import com.warxim.petep.extension.internal.common.rule_group.gui.RuleGroupController;
+import com.warxim.petep.extension.internal.common.rule_group.gui.RuleGroupsController;
+import com.warxim.petep.extension.internal.common.rule_group.intercept.RuleInterceptorModule;
+import com.warxim.petep.extension.internal.modifier.factory.ModifierFactoryManager;
+import com.warxim.petep.extension.internal.modifier.intercept.ModifierInterceptorModule;
+import com.warxim.petep.extension.internal.modifier.rule.ModifyRule;
+import com.warxim.petep.extension.internal.modifier.rule.ModifyRuleGroupManager;
+import com.warxim.petep.helper.ExtensionHelper;
+import javafx.fxml.FXMLLoader;
+import javafx.scene.Node;
+import javafx.util.Pair;
+
+public final class ModifierController extends RuleGroupsController {
+ private final ModifierFactoryManager factoryManager;
+
+ public ModifierController(
+ ModifyRuleGroupManager groupManager,
+ ExtensionHelper extensionHelper,
+ ModifierFactoryManager factoryManager) {
+ super("Modifier", groupManager, extensionHelper);
+ this.factoryManager = factoryManager;
+ }
+
+ @Override
+ protected Class extends RuleInterceptorModule> getInterceptorModuleClass() {
+ return ModifierInterceptorModule.class;
+ }
+
+ @Override
+ protected Pair> createGroupTabNode(
+ RuleGroup group) throws IOException {
+ FXMLLoader fxmlLoader = new FXMLLoader(
+ getClass().getResource("/fxml/extension/internal/modifier/ModifyRuleGroup.fxml"));
+
+ ModifyGroupController controller = new ModifyGroupController(group, factoryManager);
+
+ fxmlLoader.setController(controller);
+
+ return new Pair<>(fxmlLoader.load(), controller);
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/modifier/gui/ModifyGroupController.java b/src/main/java/com/warxim/petep/extension/internal/modifier/gui/ModifyGroupController.java
new file mode 100644
index 0000000..c1d5d10
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/modifier/gui/ModifyGroupController.java
@@ -0,0 +1,168 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.modifier.gui;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.Optional;
+import java.util.ResourceBundle;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import com.warxim.petep.extension.internal.common.rule_group.RuleGroup;
+import com.warxim.petep.extension.internal.common.rule_group.gui.RuleGroupController;
+import com.warxim.petep.extension.internal.modifier.factory.ModifierFactoryManager;
+import com.warxim.petep.extension.internal.modifier.gui.rule.EditModifyRuleDialog;
+import com.warxim.petep.extension.internal.modifier.gui.rule.NewProcessRuleDialog;
+import com.warxim.petep.extension.internal.modifier.rule.ModifyRule;
+import com.warxim.petep.gui.dialog.Dialogs;
+import javafx.collections.FXCollections;
+import javafx.event.ActionEvent;
+import javafx.fxml.FXML;
+import javafx.fxml.Initializable;
+import javafx.scene.control.TableColumn;
+import javafx.scene.control.TableView;
+import javafx.scene.control.cell.PropertyValueFactory;
+
+/** Modify group controller. */
+public final class ModifyGroupController extends RuleGroupController
+ implements Initializable {
+ private final ModifierFactoryManager factoryManager;
+
+ @FXML
+ private TableView table;
+
+ @FXML
+ private TableColumn nameColumn;
+
+ @FXML
+ private TableColumn tagColumn;
+
+ @FXML
+ private TableColumn factoryColumn;
+
+ @FXML
+ private TableColumn enabledColumn;
+
+ /** Modify group controller constructor. */
+ public ModifyGroupController(RuleGroup group, ModifierFactoryManager factoryManager) {
+ super(group);
+ this.factoryManager = factoryManager;
+ }
+
+ @Override
+ public void initialize(URL location, ResourceBundle resources) {
+ nameColumn.setCellValueFactory(new PropertyValueFactory<>("name"));
+ tagColumn.setCellValueFactory(new PropertyValueFactory<>("tag"));
+ factoryColumn.setCellValueFactory(new PropertyValueFactory<>("modifier"));
+ enabledColumn.setCellValueFactory(new PropertyValueFactory<>("enabled"));
+
+ table.setItems(FXCollections.observableList(group.getRules()));
+ }
+
+ @FXML
+ private void onNewButtonClick(ActionEvent event) {
+ try {
+ NewProcessRuleDialog dialog = new NewProcessRuleDialog(factoryManager);
+
+ Optional data = dialog.showAndWait();
+
+ if (!data.isPresent() || data.get() == null) {
+ return;
+ }
+
+ group.addRule(data.get());
+
+ refresh();
+ } catch (IOException e) {
+ Logger.getGlobal().log(Level.SEVERE, "Exception during openning of modify rule dialog", e);
+ }
+ }
+
+ @FXML
+ private void onEditButtonClick(ActionEvent event) {
+ ModifyRule rule = table.getSelectionModel().getSelectedItem();
+
+ if (rule == null) {
+ return;
+ }
+
+ try {
+ EditModifyRuleDialog dialog = new EditModifyRuleDialog(factoryManager, rule);
+
+ Optional data = dialog.showAndWait();
+
+ if (!data.isPresent() || data.get() == null) {
+ return;
+ }
+
+ group.replace(rule, data.get());
+
+ refresh();
+ } catch (IOException e) {
+ Logger.getGlobal().log(Level.SEVERE, "Exception during openning of modify rule dialog", e);
+ }
+ }
+
+ @FXML
+ private void onRemoveButtonClick(ActionEvent event) {
+ ModifyRule rule = table.getSelectionModel().getSelectedItem();
+
+ if (rule == null) {
+ return;
+ }
+
+ // Does user really want to remove rule?
+ if (!Dialogs.createYesOrNoDialog("Are you sure?",
+ "Do you really want to remove rule '" + rule.getName() + "'?")) {
+ return;
+ }
+
+ group.removeRule(rule);
+
+ refresh();
+ }
+
+ @FXML
+ private void onMoveUpButtonClick(ActionEvent event) {
+ int index = table.getSelectionModel().getSelectedIndex();
+
+ if (index <= 0) {
+ return;
+ }
+
+ group.swapRules(index, index - 1);
+
+ refresh();
+ }
+
+ @FXML
+ private void onMoveDownButtonClick(ActionEvent event) {
+ int index = table.getSelectionModel().getSelectedIndex();
+
+ if (index == -1 || index == group.ruleCount() - 1) {
+ return;
+ }
+
+ group.swapRules(index, index + 1);
+
+ refresh();
+ }
+
+ private void refresh() {
+ table.setItems(FXCollections.observableList(group.getRules()));
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/modifier/gui/rule/EditModifyRuleDialog.java b/src/main/java/com/warxim/petep/extension/internal/modifier/gui/rule/EditModifyRuleDialog.java
new file mode 100644
index 0000000..7722ffc
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/modifier/gui/rule/EditModifyRuleDialog.java
@@ -0,0 +1,57 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.modifier.gui.rule;
+
+import java.io.IOException;
+import com.warxim.petep.extension.internal.modifier.factory.Modifier;
+import com.warxim.petep.extension.internal.modifier.factory.ModifierData;
+import com.warxim.petep.extension.internal.modifier.factory.ModifierFactoryManager;
+import com.warxim.petep.extension.internal.modifier.rule.ModifyRule;
+import com.warxim.petep.gui.component.ConfigPane;
+
+/** Edit modify rule dialog. */
+public final class EditModifyRuleDialog extends ModifyRuleDialog {
+ /** Edit modify rule dialog constructor. */
+ public EditModifyRuleDialog(ModifierFactoryManager factoryManager, ModifyRule rule)
+ throws IOException {
+ super("Edit modify rule", "Save", factoryManager);
+
+ nameInput.setText(rule.getName());
+ descriptionInput.setText(rule.getDescription());
+ tagInput.setText(rule.getTag());
+ enabledInput.setSelected(rule.isEnabled());
+
+ Modifier processor = rule.getModifier();
+ factoryInput.getSelectionModel().select(processor.getFactory());
+
+ // Load config pane.
+ ConfigPane pane = createFactoryPane();
+ if (pane == null) {
+ return;
+ }
+ setFactoryPane(pane);
+
+ // Get configuration from instance.
+ ModifierData data = processor.getData();
+ if (data == null) {
+ return;
+ }
+
+ // Set config to pane.
+ pane.setConfig(data);
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/modifier/gui/rule/ModifyRuleDialog.java b/src/main/java/com/warxim/petep/extension/internal/modifier/gui/rule/ModifyRuleDialog.java
new file mode 100644
index 0000000..ae271f6
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/modifier/gui/rule/ModifyRuleDialog.java
@@ -0,0 +1,160 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.modifier.gui.rule;
+
+import java.io.IOException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import com.warxim.petep.extension.internal.modifier.factory.ModifierData;
+import com.warxim.petep.extension.internal.modifier.factory.ModifierFactory;
+import com.warxim.petep.extension.internal.modifier.factory.ModifierFactoryManager;
+import com.warxim.petep.extension.internal.modifier.rule.ModifyRule;
+import com.warxim.petep.gui.component.ConfigPane;
+import com.warxim.petep.gui.dialog.Dialogs;
+import com.warxim.petep.gui.dialog.SimpleInputDialog;
+import javafx.collections.FXCollections;
+import javafx.event.ActionEvent;
+import javafx.fxml.FXML;
+import javafx.scene.control.CheckBox;
+import javafx.scene.control.ComboBox;
+import javafx.scene.control.TextArea;
+import javafx.scene.control.TextField;
+import javafx.scene.layout.AnchorPane;
+import javafx.util.StringConverter;
+
+/** Modify rule dialog. */
+public abstract class ModifyRuleDialog extends SimpleInputDialog {
+ @FXML
+ protected ComboBox factoryInput;
+
+ @FXML
+ protected AnchorPane factoryPane;
+
+ @FXML
+ protected TextField nameInput;
+
+ @FXML
+ protected TextArea descriptionInput;
+
+ @FXML
+ protected TextField tagInput;
+
+ @FXML
+ protected CheckBox enabledInput;
+
+ /** Modify rule dialog constructor. */
+ public ModifyRuleDialog(String title, String okText, ModifierFactoryManager factoryManager)
+ throws IOException {
+ super("/fxml/extension/internal/modifier/ModifyRuleDialog.fxml", title, okText);
+
+ enabledInput.setSelected(true);
+
+ // Show factory name as factory input text.
+ factoryInput.setConverter(new StringConverter() {
+ @Override
+ public String toString(ModifierFactory factory) {
+ if (factory == null) {
+ return "";
+ }
+ return factory.getName();
+ }
+
+ @Override
+ public ModifierFactory fromString(String str) {
+ return null;
+ }
+ });
+
+ factoryInput.setItems(FXCollections.observableArrayList(factoryManager.getFactories()));
+ }
+
+ protected final void setFactoryPane(ConfigPane pane) {
+ if (pane == null) {
+ // Clear factory pane if config pane does not exist.
+ factoryPane.getChildren().clear();
+ return;
+ }
+
+ AnchorPane.setLeftAnchor(pane, 0D);
+ AnchorPane.setRightAnchor(pane, 0D);
+
+ // Add config pane to factory pane.
+ factoryPane.getChildren().setAll(pane);
+ }
+
+ protected final ConfigPane createFactoryPane() {
+ ModifierFactory factory = factoryInput.getSelectionModel().getSelectedItem();
+
+ if (factory == null) {
+ return null;
+ }
+
+ try {
+ return factory.createConfigPane();
+ } catch (IOException e) {
+ Logger.getGlobal().log(Level.SEVERE, "Could not load factory config pane.", e);
+ }
+
+ return null;
+ }
+
+ @FXML
+ private final void onFactoryChange(ActionEvent event) {
+ setFactoryPane(createFactoryPane());
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ protected final boolean isValid() {
+ if (nameInput.getText().isEmpty()) {
+ Dialogs.createErrorDialog("Name required", "You have to enter name.");
+ return false;
+ }
+
+ // Validate tag.
+ if (!tagInput.getText().isEmpty() && !tagInput.getText().matches("^[a-zA-Z0-9-_.]+$")) {
+ Dialogs.createErrorDialog("Tag invalid",
+ "You have entered invalid tag (allowed characters are A-Za-z0-9-_.).");
+ return false;
+ }
+
+ // Validate factory
+ ModifierFactory factory = factoryInput.getSelectionModel().getSelectedItem();
+ if (factory == null) {
+ Dialogs.createErrorDialog("Factory required", "You have to select factory.");
+ return false;
+ }
+
+ // Validate configuration pane
+ if (!factoryPane.getChildren().isEmpty()
+ && !((ConfigPane) factoryPane.getChildren().get(0)).isValid()) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ protected final ModifyRule obtainResult() {
+ ModifierFactory factory = factoryInput.getSelectionModel().getSelectedItem();
+
+ return new ModifyRule(nameInput.getText(), descriptionInput.getText(),
+ enabledInput.isSelected(), tagInput.getText(), factory.createModifier(
+ ((ConfigPane) factoryPane.getChildren().get(0)).getConfig()));
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/modifier/gui/rule/NewProcessRuleDialog.java b/src/main/java/com/warxim/petep/extension/internal/modifier/gui/rule/NewProcessRuleDialog.java
new file mode 100644
index 0000000..8730961
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/modifier/gui/rule/NewProcessRuleDialog.java
@@ -0,0 +1,28 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.modifier.gui.rule;
+
+import java.io.IOException;
+import com.warxim.petep.extension.internal.modifier.factory.ModifierFactoryManager;
+
+/** New modify rule dialog. */
+public final class NewProcessRuleDialog extends ModifyRuleDialog {
+ /** New modify rule dialog constructor. */
+ public NewProcessRuleDialog(ModifierFactoryManager factoryManager) throws IOException {
+ super("New modify rule", "Create", factoryManager);
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/modifier/intercept/ModifierInterceptor.java b/src/main/java/com/warxim/petep/extension/internal/modifier/intercept/ModifierInterceptor.java
new file mode 100644
index 0000000..f982e1f
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/modifier/intercept/ModifierInterceptor.java
@@ -0,0 +1,56 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.modifier.intercept;
+
+import com.warxim.petep.core.pdu.PDU;
+import com.warxim.petep.extension.internal.common.rule_group.RuleGroup;
+import com.warxim.petep.extension.internal.modifier.rule.ModifyRule;
+import com.warxim.petep.helper.PetepHelper;
+import com.warxim.petep.interceptor.worker.Interceptor;
+
+/** Modifier interceptor. */
+public final class ModifierInterceptor extends Interceptor {
+ private final RuleGroup group;
+
+ /** Modifier interceptor constructor. */
+ public ModifierInterceptor(int id, ModifierInterceptorModule module, PetepHelper helper) {
+ super(id, module, helper);
+
+ this.group = module.getRuleGroup();
+ }
+
+ @Override
+ public boolean prepare() {
+ return true;
+ }
+
+ @Override
+ public boolean intercept(PDU pdu) {
+ for (ModifyRule rule : group.getRules()) {
+ if (!rule.process(pdu)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ @Override
+ public void stop() {
+ // No action needed.
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/modifier/intercept/ModifierInterceptorModule.java b/src/main/java/com/warxim/petep/extension/internal/modifier/intercept/ModifierInterceptorModule.java
new file mode 100644
index 0000000..e800f59
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/modifier/intercept/ModifierInterceptorModule.java
@@ -0,0 +1,64 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.modifier.intercept;
+
+import com.warxim.petep.extension.internal.common.rule_group.RuleGroup;
+import com.warxim.petep.extension.internal.common.rule_group.config.RuleInterceptorConfig;
+import com.warxim.petep.extension.internal.common.rule_group.intercept.RuleInterceptorModule;
+import com.warxim.petep.extension.internal.modifier.ModifierExtension;
+import com.warxim.petep.extension.internal.modifier.rule.ModifyRule;
+import com.warxim.petep.helper.PetepHelper;
+import com.warxim.petep.interceptor.factory.InterceptorModuleFactory;
+import com.warxim.petep.interceptor.worker.Interceptor;
+import com.warxim.petep.persistence.Configurable;
+
+/** Modifier interceptor module. */
+public final class ModifierInterceptorModule extends RuleInterceptorModule
+ implements Configurable {
+ private RuleGroup group;
+
+ /** Modifier interceptor module constructor. */
+ public ModifierInterceptorModule(
+ InterceptorModuleFactory factory,
+ String code,
+ String name,
+ String description,
+ boolean enabled) {
+ super(factory, code, name, description, enabled);
+ }
+
+ @Override
+ public Interceptor createInterceptor(int id, PetepHelper helper) {
+ return new ModifierInterceptor(id, this, helper);
+ }
+
+ @Override
+ public RuleInterceptorConfig saveConfig() {
+ return new RuleInterceptorConfig(group.getCode());
+ }
+
+ @Override
+ public void loadConfig(RuleInterceptorConfig config) {
+ group = ((ModifierExtension) factory.getExtension()).getRuleGroupManager()
+ .get(config.getRuleGroupCode());
+ }
+
+ @Override
+ public RuleGroup getRuleGroup() {
+ return group;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/modifier/intercept/ModifierInterceptorModuleFactory.java b/src/main/java/com/warxim/petep/extension/internal/modifier/intercept/ModifierInterceptorModuleFactory.java
new file mode 100644
index 0000000..b4caec4
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/modifier/intercept/ModifierInterceptorModuleFactory.java
@@ -0,0 +1,60 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.modifier.intercept;
+
+import java.io.IOException;
+import com.warxim.petep.extension.Extension;
+import com.warxim.petep.extension.internal.common.rule_group.config.RuleInterceptorConfig;
+import com.warxim.petep.extension.internal.common.rule_group.gui.RuleInterceptorConfigurator;
+import com.warxim.petep.extension.internal.modifier.ModifierExtension;
+import com.warxim.petep.gui.component.ConfigPane;
+import com.warxim.petep.interceptor.factory.InterceptorModuleFactory;
+import com.warxim.petep.interceptor.module.InterceptorModule;
+import com.warxim.petep.persistence.Configurator;
+
+/** Modifier interceptor module. */
+public final class ModifierInterceptorModuleFactory extends InterceptorModuleFactory
+ implements Configurator {
+ /** Modifier interceptor module constructor. */
+ public ModifierInterceptorModuleFactory(Extension extension) {
+ super(extension);
+ }
+
+ @Override
+ public String getCode() {
+ return "modifier";
+ }
+
+ @Override
+ public String getName() {
+ return "Modifier";
+ }
+
+ @Override
+ public InterceptorModule createModule(
+ String code,
+ String name,
+ String description,
+ boolean enabled) {
+ return new ModifierInterceptorModule(this, code, name, description, enabled);
+ }
+
+ @Override
+ public ConfigPane createConfigPane() throws IOException {
+ return new RuleInterceptorConfigurator<>(((ModifierExtension) extension).getRuleGroupManager());
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/modifier/rule/ModifyRule.java b/src/main/java/com/warxim/petep/extension/internal/modifier/rule/ModifyRule.java
new file mode 100644
index 0000000..9549f8a
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/modifier/rule/ModifyRule.java
@@ -0,0 +1,55 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.modifier.rule;
+
+import com.warxim.petep.core.pdu.PDU;
+import com.warxim.petep.extension.internal.common.rule_group.Rule;
+import com.warxim.petep.extension.internal.modifier.factory.Modifier;
+
+/** Modify rule. */
+public final class ModifyRule extends Rule {
+ private final String tag;
+ private final Modifier modifier;
+
+ /** Modify rule constructor. */
+ public ModifyRule(
+ String name,
+ String description,
+ boolean enabled,
+ String tag,
+ Modifier modifier) {
+ super(name, description, enabled);
+ this.tag = tag;
+ this.modifier = modifier;
+ }
+
+ public String getTag() {
+ return tag;
+ }
+
+ public Modifier getModifier() {
+ return modifier;
+ }
+
+ public boolean process(PDU pdu) {
+ if ((!enabled) || (!tag.isEmpty() && !pdu.hasTag(tag))) {
+ return true;
+ }
+
+ return modifier.process(pdu);
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/modifier/rule/ModifyRuleGroupManager.java b/src/main/java/com/warxim/petep/extension/internal/modifier/rule/ModifyRuleGroupManager.java
new file mode 100644
index 0000000..03d1a04
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/modifier/rule/ModifyRuleGroupManager.java
@@ -0,0 +1,28 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.modifier.rule;
+
+import com.warxim.petep.extension.internal.common.rule_group.RuleGroup;
+import com.warxim.petep.extension.internal.common.rule_group.RuleGroupManager;
+
+/** Modify rule group manager. */
+public final class ModifyRuleGroupManager extends RuleGroupManager> {
+ /** Modify rule group manager constructor. */
+ public ModifyRuleGroupManager() {
+ super();
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/TaggerApi.java b/src/main/java/com/warxim/petep/extension/internal/tagger/TaggerApi.java
new file mode 100644
index 0000000..c898cd5
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/tagger/TaggerApi.java
@@ -0,0 +1,27 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.tagger;
+
+import com.warxim.petep.extension.PetepAPI;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleFactory;
+
+@PetepAPI
+/** Interface for registration of tag subrule factories. */
+public interface TaggerApi {
+ /** Registers tag subrule factory. */
+ boolean registerSubruleFactory(TagSubruleFactory factory);
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/TaggerExtension.java b/src/main/java/com/warxim/petep/extension/internal/tagger/TaggerExtension.java
new file mode 100644
index 0000000..8b92266
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/tagger/TaggerExtension.java
@@ -0,0 +1,228 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.tagger;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonParseException;
+import com.warxim.booleanexpressioninterpreter.InvalidExpressionException;
+import com.warxim.petep.extension.Extension;
+import com.warxim.petep.extension.internal.common.rule_group.RuleGroup;
+import com.warxim.petep.extension.internal.common.rule_group.gui.RuleGroupsGuiFactory;
+import com.warxim.petep.extension.internal.tagger.config.TagRuleConfig;
+import com.warxim.petep.extension.internal.tagger.config.TagRuleGroupConfig;
+import com.warxim.petep.extension.internal.tagger.config.TagSubruleConfig;
+import com.warxim.petep.extension.internal.tagger.config.TaggerConfig;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubrule;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleFactory;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleFactoryManager;
+import com.warxim.petep.extension.internal.tagger.factory.internal.contains.ContainsSubruleFactory;
+import com.warxim.petep.extension.internal.tagger.factory.internal.destination.DestinationSubruleFactory;
+import com.warxim.petep.extension.internal.tagger.factory.internal.ends_with.EndsWithSubruleFactory;
+import com.warxim.petep.extension.internal.tagger.factory.internal.has_tag.HasTagSubruleFactory;
+import com.warxim.petep.extension.internal.tagger.factory.internal.proxy.ProxySubruleFactory;
+import com.warxim.petep.extension.internal.tagger.factory.internal.size.SizeSubruleFactory;
+import com.warxim.petep.extension.internal.tagger.factory.internal.starts_with.StartsWithSubruleFactory;
+import com.warxim.petep.extension.internal.tagger.gui.TaggerController;
+import com.warxim.petep.extension.internal.tagger.intercept.TagInterceptorModuleFactory;
+import com.warxim.petep.extension.internal.tagger.rule.TagRule;
+import com.warxim.petep.extension.internal.tagger.rule.TagRuleGroupManager;
+import com.warxim.petep.helper.ExtensionHelper;
+import com.warxim.petep.helper.GuiHelper;
+import com.warxim.petep.persistence.Storable;
+
+/** Tagger extension. */
+public final class TaggerExtension extends Extension
+ implements Storable, TaggerApi {
+ private ExtensionHelper helper;
+
+ private final TagRuleGroupManager groupManager;
+ private final TagSubruleFactoryManager factoryManager;
+
+ private TaggerConfig config;
+
+ /** Tagger extension constructor. */
+ public TaggerExtension(String path) {
+ super(path);
+
+ factoryManager = new TagSubruleFactoryManager();
+ groupManager = new TagRuleGroupManager();
+ }
+
+ @Override
+ public void init(ExtensionHelper helper) {
+ this.helper = helper;
+
+ registerInternalModules();
+
+ initGroupManager();
+
+ helper.registerInterceptorModuleFactory(new TagInterceptorModuleFactory(this));
+ }
+
+ @Override
+ public void initGui(GuiHelper helper) {
+ try {
+ helper.registerTab("Tagger", RuleGroupsGuiFactory
+ .createRoleGroupsNode(new TaggerController(groupManager, this.helper, factoryManager)));
+ } catch (IOException e) {
+ Logger.getGlobal().log(Level.SEVERE, "Could not load replacer tab!", e);
+ }
+
+ helper.registerGuide(new TaggerGuide());
+ }
+
+ @Override
+ public String getCode() {
+ return "tagger";
+ }
+
+ @Override
+ public String getName() {
+ return "Tagger extension";
+ }
+
+ @Override
+ public String getDescription() {
+ return "Simple tagger extension.";
+ }
+
+ @Override
+ public String getVersion() {
+ return "0.9";
+ }
+
+ @Override
+ public TaggerConfig saveStore() {
+ List groups = new ArrayList<>(groupManager.size());
+
+ for (RuleGroup group : groupManager.getList()) {
+ List rules = new ArrayList<>(group.size());
+
+ for (TagRule rule : group.getRules()) {
+ List subrules = new ArrayList<>(rule.getSubrules().size());
+
+ for (TagSubrule subrule : rule.getSubrules()) {
+ subrules.add(new TagSubruleConfig(subrule.getFactory().getCode(), subrule.getData()));
+ }
+
+ rules.add(new TagRuleConfig(rule.getName(), rule.getDescription(), rule.isEnabled(),
+ rule.getTag(), subrules, rule.getExpressionString()));
+ }
+ groups.add(new TagRuleGroupConfig(group.getCode(), group.getName(), rules));
+ }
+
+ return new TaggerConfig(groups);
+ }
+
+ @Override
+ public void loadStore(TaggerConfig store) {
+ config = store;
+ }
+
+ private void registerInternalModules() {
+ registerSubruleFactory(new ContainsSubruleFactory());
+ registerSubruleFactory(new StartsWithSubruleFactory());
+ registerSubruleFactory(new EndsWithSubruleFactory());
+ registerSubruleFactory(new HasTagSubruleFactory());
+ registerSubruleFactory(new SizeSubruleFactory());
+ registerSubruleFactory(new DestinationSubruleFactory());
+ registerSubruleFactory(new ProxySubruleFactory(helper));
+ }
+
+ private void initGroupManager() {
+ Gson gson = new GsonBuilder().create();
+
+ if (config != null) {
+ // Process groups.
+ for (TagRuleGroupConfig groupConfig : config.getGroups()) {
+ RuleGroup group = new RuleGroup<>(groupConfig.getCode(), groupConfig.getName());
+
+ // Process rules.
+ for (TagRuleConfig ruleConfig : groupConfig.getRules()) {
+ List subrules = new ArrayList<>();
+
+ boolean isError = false;
+
+ // Process subrules.
+ for (TagSubruleConfig subruleConfig : ruleConfig.getSubrules()) {
+ TagSubruleFactory factory = factoryManager.getFactory(subruleConfig.getFactoryCode());
+
+ // No factory found.
+ if (factory == null) {
+ Logger.getGlobal()
+ .severe("Could not load factory " + subruleConfig.getFactoryCode() + "!");
+
+ isError = true;
+
+ break;
+ }
+
+ // Add subrule.
+ try {
+ subrules.add(factory
+ .createSubrule(gson.fromJson(subruleConfig.getData(), factory.getConfigType())));
+ } catch (JsonParseException e) {
+ Logger.getGlobal()
+ .log(Level.SEVERE, "Could not load rule " + ruleConfig.getName() + "!", e);
+
+ isError = true;
+
+ break;
+ }
+ }
+
+ // Skip rule.
+ if (isError) {
+ Logger.getGlobal()
+ .severe(
+ "Ignoring rule " + ruleConfig.getName() + ", because there an error occured!");
+ continue;
+ }
+
+ // Add rule.
+ try {
+ group.addRule(new TagRule(ruleConfig.getName(), ruleConfig.getDescription(),
+ ruleConfig.isEnabled(), ruleConfig.getTag(), subrules,
+ ruleConfig.getExpressionString()));
+ } catch (InvalidExpressionException e) {
+ Logger.getGlobal()
+ .log(Level.SEVERE, "Could not load rule " + ruleConfig.getName() + "!", e);
+ }
+ }
+
+ groupManager.add(group);
+ }
+
+ config = null;
+ }
+ }
+
+ public TagRuleGroupManager getRuleGroupManager() {
+ return groupManager;
+ }
+
+ @Override
+ public boolean registerSubruleFactory(TagSubruleFactory factory) {
+ return factoryManager.registerFactory(factory);
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/TaggerGuide.java b/src/main/java/com/warxim/petep/extension/internal/tagger/TaggerGuide.java
new file mode 100644
index 0000000..578a1a7
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/tagger/TaggerGuide.java
@@ -0,0 +1,32 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.tagger;
+
+import com.warxim.petep.gui.guide.Guide;
+
+/** Tagger guide. */
+public final class TaggerGuide extends Guide {
+ @Override
+ public String getTitle() {
+ return "Tagger";
+ }
+
+ @Override
+ public String getHtml() {
+ return loadHtmlResource("/html/guide/internal/TaggerGuide.html");
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/config/TagRuleConfig.java b/src/main/java/com/warxim/petep/extension/internal/tagger/config/TagRuleConfig.java
new file mode 100644
index 0000000..7a8368b
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/tagger/config/TagRuleConfig.java
@@ -0,0 +1,69 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.tagger.config;
+
+import java.util.List;
+
+/** Tag rule configuration. */
+public final class TagRuleConfig {
+ private final String name;
+ private final String description;
+ private final boolean enabled;
+ private final String tag;
+ private final String expressionString;
+ private final List subrules;
+
+ /** Tag rule configuration constructor. */
+ public TagRuleConfig(
+ String name,
+ String description,
+ boolean enabled,
+ String tag,
+ List subrules,
+ String expressionString) {
+ this.name = name;
+ this.description = description;
+ this.enabled = enabled;
+ this.tag = tag;
+ this.subrules = subrules;
+ this.expressionString = expressionString;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public boolean isEnabled() {
+ return enabled;
+ }
+
+ public String getTag() {
+ return tag;
+ }
+
+ public List getSubrules() {
+ return subrules;
+ }
+
+ public String getExpressionString() {
+ return expressionString;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/config/TagRuleGroupConfig.java b/src/main/java/com/warxim/petep/extension/internal/tagger/config/TagRuleGroupConfig.java
new file mode 100644
index 0000000..f42ac0b
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/tagger/config/TagRuleGroupConfig.java
@@ -0,0 +1,45 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.tagger.config;
+
+import java.util.List;
+
+/** Configuration of group of tag rules. */
+public final class TagRuleGroupConfig {
+ private final String code;
+ private final String name;
+ private final List rules;
+
+ /** Tag rule group config. */
+ public TagRuleGroupConfig(String code, String name, List rules) {
+ this.code = code;
+ this.name = name;
+ this.rules = rules;
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public List getRules() {
+ return rules;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/config/TagSubruleConfig.java b/src/main/java/com/warxim/petep/extension/internal/tagger/config/TagSubruleConfig.java
new file mode 100644
index 0000000..20f39d2
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/tagger/config/TagSubruleConfig.java
@@ -0,0 +1,41 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.tagger.config;
+
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonElement;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData;
+
+/** Configuration of tag subrules. */
+public final class TagSubruleConfig {
+ private final String factoryCode;
+ private final JsonElement data;
+
+ /** Tag subrule config constructor. */
+ public TagSubruleConfig(String factoryCode, TagSubruleData data) {
+ this.factoryCode = factoryCode;
+ this.data = new GsonBuilder().setPrettyPrinting().create().toJsonTree(data);
+ }
+
+ public String getFactoryCode() {
+ return factoryCode;
+ }
+
+ public JsonElement getData() {
+ return data;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/config/TaggerConfig.java b/src/main/java/com/warxim/petep/extension/internal/tagger/config/TaggerConfig.java
new file mode 100644
index 0000000..e01d85f
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/tagger/config/TaggerConfig.java
@@ -0,0 +1,33 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.tagger.config;
+
+import java.util.List;
+
+/** Tagger configuration. */
+public final class TaggerConfig {
+ private final List groups;
+
+ /** Tagger configuration constructor. */
+ public TaggerConfig(List groups) {
+ this.groups = groups;
+ }
+
+ public List getGroups() {
+ return groups;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/factory/TagSubrule.java b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/TagSubrule.java
new file mode 100644
index 0000000..cb48c39
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/TagSubrule.java
@@ -0,0 +1,48 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.tagger.factory;
+
+import com.warxim.petep.core.pdu.PDU;
+import com.warxim.petep.extension.PetepAPI;
+
+/** Tag subrule. */
+@PetepAPI
+public abstract class TagSubrule {
+ protected final TagSubruleFactory factory;
+ protected TagSubruleData data;
+
+ /** Tag subrule constructor. */
+ public TagSubrule(TagSubruleFactory factory, TagSubruleData data) {
+ this.factory = factory;
+ this.data = data;
+ }
+
+ public final TagSubruleFactory getFactory() {
+ return factory;
+ }
+
+ public final TagSubruleData getData() {
+ return data;
+ }
+
+ public abstract boolean test(PDU pdu);
+
+ @Override
+ public String toString() {
+ return factory.getName();
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/factory/TagSubruleConfigurator.java b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/TagSubruleConfigurator.java
new file mode 100644
index 0000000..6833e74
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/TagSubruleConfigurator.java
@@ -0,0 +1,28 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.tagger.factory;
+
+import java.io.IOException;
+import com.warxim.petep.extension.PetepAPI;
+import com.warxim.petep.gui.component.ConfigPane;
+
+@PetepAPI
+public abstract class TagSubruleConfigurator extends ConfigPane {
+ public TagSubruleConfigurator(String template) throws IOException {
+ super(template);
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/factory/TagSubruleData.java b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/TagSubruleData.java
new file mode 100644
index 0000000..ff3bed6
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/TagSubruleData.java
@@ -0,0 +1,24 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.tagger.factory;
+
+import com.warxim.petep.extension.PetepAPI;
+
+/** Tag subrule data. */
+@PetepAPI
+public class TagSubruleData {
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/factory/TagSubruleFactory.java b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/TagSubruleFactory.java
new file mode 100644
index 0000000..096abc2
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/TagSubruleFactory.java
@@ -0,0 +1,45 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.tagger.factory;
+
+import java.io.IOException;
+import java.lang.reflect.Type;
+import com.warxim.petep.extension.PetepAPI;
+
+/** Tag subrule factory. */
+@PetepAPI
+public abstract class TagSubruleFactory {
+ /** Returns factory code (for configuration purposes). */
+ public abstract String getCode();
+
+ /** Returns factory name (visible for user). */
+ public abstract String getName();
+
+ /** Creates subrule using given data. */
+ public abstract TagSubrule createSubrule(TagSubruleData data);
+
+ /** Creates config pane for subrule data. */
+ public abstract TagSubruleConfigurator createConfigPane() throws IOException;
+
+ /** Returns type of configuration, so it can be deserialized from JSON configuration. */
+ public abstract Type getConfigType();
+
+ @Override
+ public String toString() {
+ return getName();
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/factory/TagSubruleFactoryManager.java b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/TagSubruleFactoryManager.java
new file mode 100644
index 0000000..fb23c9f
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/TagSubruleFactoryManager.java
@@ -0,0 +1,44 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.tagger.factory;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/** Tag subrule factory manager. */
+public final class TagSubruleFactoryManager {
+ private final Map factories;
+
+ /** Tag subrule factory manager constructor. */
+ public TagSubruleFactoryManager() {
+ factories = new ConcurrentHashMap<>();
+ }
+
+ public boolean registerFactory(TagSubruleFactory factory) {
+ return factories.putIfAbsent(factory.getCode(), factory) == null;
+ }
+
+ public TagSubruleFactory getFactory(String code) {
+ return factories.get(code);
+ }
+
+ public List getFactories() {
+ return new ArrayList<>(factories.values());
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/contains/ContainsData.java b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/contains/ContainsData.java
new file mode 100644
index 0000000..29e8a09
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/contains/ContainsData.java
@@ -0,0 +1,43 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.tagger.factory.internal.contains;
+
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData;
+
+public final class ContainsData extends TagSubruleData {
+ private final byte[] data;
+ private final String charset;
+ private final int index;
+
+ public ContainsData(byte[] data, String charset, int index) {
+ this.data = data;
+ this.charset = charset;
+ this.index = index;
+ }
+
+ public byte[] getData() {
+ return data;
+ }
+
+ public String getCharset() {
+ return charset;
+ }
+
+ public int getIndex() {
+ return index;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/contains/ContainsSubruleConfigurator.java b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/contains/ContainsSubruleConfigurator.java
new file mode 100644
index 0000000..cdd5452
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/contains/ContainsSubruleConfigurator.java
@@ -0,0 +1,73 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.tagger.factory.internal.contains;
+
+import java.io.IOException;
+import java.nio.charset.Charset;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleConfigurator;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData;
+import com.warxim.petep.gui.control.BytesEditor;
+import com.warxim.petep.gui.dialog.Dialogs;
+import javafx.fxml.FXML;
+import javafx.scene.control.TextField;
+
+public final class ContainsSubruleConfigurator extends TagSubruleConfigurator {
+ @FXML
+ private BytesEditor dataInput;
+ @FXML
+ private TextField indexInput;
+
+ public ContainsSubruleConfigurator() throws IOException {
+ super("/fxml/extension/internal/tagger/factory/ContainsSubrule.fxml");
+ }
+
+ @Override
+ public TagSubruleData getConfig() {
+ return new ContainsData(dataInput.getBytes(), dataInput.getCharset().name(),
+ Integer.parseInt(indexInput.getText()));
+ }
+
+ @Override
+ public void setConfig(TagSubruleData config) {
+ dataInput.setData(((ContainsData) config).getData(),
+ Charset.forName(((ContainsData) config).getCharset()));
+ indexInput.setText(String.valueOf(((ContainsData) config).getIndex()));
+ }
+
+ @Override
+ public boolean isValid() {
+ if (dataInput.getBytes().length == 0) {
+ Dialogs.createErrorDialog("Data required", "You have enter data.");
+ return false;
+ }
+
+ try {
+ int index = Integer.parseInt(indexInput.getText());
+ if (index < 0 && index != -1) {
+ Dialogs.createErrorDialog("Invalid index",
+ "Index has to be -1 or number greater or equal to 0.");
+ return false;
+ }
+ } catch (NumberFormatException e) {
+ Dialogs.createErrorDialog("Invalid index",
+ "Index has to be -1 or number greater or equal to 0.");
+ return false;
+ }
+
+ return true;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/contains/ContainsSubruleFactory.java b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/contains/ContainsSubruleFactory.java
new file mode 100644
index 0000000..aec79d8
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/contains/ContainsSubruleFactory.java
@@ -0,0 +1,51 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.tagger.factory.internal.contains;
+
+import java.io.IOException;
+import java.lang.reflect.Type;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubrule;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleConfigurator;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleFactory;
+
+public final class ContainsSubruleFactory extends TagSubruleFactory {
+ @Override
+ public String getCode() {
+ return "contains";
+ }
+
+ @Override
+ public String getName() {
+ return "Contains ...";
+ }
+
+ @Override
+ public TagSubrule createSubrule(TagSubruleData data) {
+ return new ContainsTagSubrule(this, data);
+ }
+
+ @Override
+ public TagSubruleConfigurator createConfigPane() throws IOException {
+ return new ContainsSubruleConfigurator();
+ }
+
+ @Override
+ public Type getConfigType() {
+ return ContainsData.class;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/contains/ContainsTagSubrule.java b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/contains/ContainsTagSubrule.java
new file mode 100644
index 0000000..293ac5d
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/contains/ContainsTagSubrule.java
@@ -0,0 +1,40 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.tagger.factory.internal.contains;
+
+import com.warxim.petep.core.pdu.PDU;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubrule;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleFactory;
+import com.warxim.petep.util.PduUtils;
+
+public final class ContainsTagSubrule extends TagSubrule {
+ public ContainsTagSubrule(TagSubruleFactory factory, TagSubruleData data) {
+ super(factory, data);
+ }
+
+ @Override
+ public boolean test(PDU pdu) {
+ ContainsData data = (ContainsData) this.data;
+
+ if (data.getIndex() == -1) {
+ return PduUtils.contains(pdu, data.getData());
+ } else {
+ return PduUtils.containsAt(pdu, data.getData(), data.getIndex());
+ }
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/destination/DestinationData.java b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/destination/DestinationData.java
new file mode 100644
index 0000000..39f4a36
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/destination/DestinationData.java
@@ -0,0 +1,32 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.tagger.factory.internal.destination;
+
+import com.warxim.petep.core.pdu.PduDestination;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData;
+
+public final class DestinationData extends TagSubruleData {
+ private final PduDestination destination;
+
+ public DestinationData(PduDestination destination) {
+ this.destination = destination;
+ }
+
+ public PduDestination getDestination() {
+ return destination;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/destination/DestinationSubruleConfigurator.java b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/destination/DestinationSubruleConfigurator.java
new file mode 100644
index 0000000..b29cc0b
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/destination/DestinationSubruleConfigurator.java
@@ -0,0 +1,75 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.tagger.factory.internal.destination;
+
+import java.io.IOException;
+import com.warxim.petep.core.pdu.PduDestination;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleConfigurator;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData;
+import com.warxim.petep.gui.dialog.Dialogs;
+import javafx.collections.FXCollections;
+import javafx.fxml.FXML;
+import javafx.scene.control.ComboBox;
+import javafx.util.StringConverter;
+
+public final class DestinationSubruleConfigurator extends TagSubruleConfigurator {
+ @FXML
+ private ComboBox destinationInput;
+
+ public DestinationSubruleConfigurator() throws IOException {
+ super("/fxml/extension/internal/tagger/factory/DestinationSubrule.fxml");
+
+ destinationInput.setConverter(new StringConverter() {
+ @Override
+ public String toString(PduDestination destination) {
+ if (destination == null) {
+ return "";
+ }
+
+ return destination == PduDestination.CLIENT ? "To client" : "To server";
+ }
+
+ @Override
+ public PduDestination fromString(String str) {
+ return null;
+ }
+ });
+
+ destinationInput
+ .setItems(FXCollections.observableArrayList(PduDestination.CLIENT, PduDestination.SERVER));
+ }
+
+ @Override
+ public TagSubruleData getConfig() {
+ return new DestinationData(destinationInput.getSelectionModel().getSelectedItem());
+ }
+
+ @Override
+ public void setConfig(TagSubruleData config) {
+ destinationInput.getSelectionModel().select(((DestinationData) config).getDestination());
+ }
+
+ @Override
+ public boolean isValid() {
+ if (destinationInput.getSelectionModel().getSelectedItem() == null) {
+ Dialogs.createErrorDialog("Destination required", "You have to select destination.");
+ return false;
+ }
+
+ return true;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/destination/DestinationSubruleFactory.java b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/destination/DestinationSubruleFactory.java
new file mode 100644
index 0000000..5a71582
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/destination/DestinationSubruleFactory.java
@@ -0,0 +1,51 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.tagger.factory.internal.destination;
+
+import java.io.IOException;
+import java.lang.reflect.Type;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubrule;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleConfigurator;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleFactory;
+
+public final class DestinationSubruleFactory extends TagSubruleFactory {
+ @Override
+ public String getCode() {
+ return "destination";
+ }
+
+ @Override
+ public String getName() {
+ return "Destination ...";
+ }
+
+ @Override
+ public TagSubrule createSubrule(TagSubruleData data) {
+ return new DestinationTagSubrule(this, data);
+ }
+
+ @Override
+ public TagSubruleConfigurator createConfigPane() throws IOException {
+ return new DestinationSubruleConfigurator();
+ }
+
+ @Override
+ public Type getConfigType() {
+ return DestinationData.class;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/destination/DestinationTagSubrule.java b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/destination/DestinationTagSubrule.java
new file mode 100644
index 0000000..852232a
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/destination/DestinationTagSubrule.java
@@ -0,0 +1,40 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.tagger.factory.internal.destination;
+
+import com.warxim.petep.core.pdu.PDU;
+import com.warxim.petep.core.pdu.PduDestination;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubrule;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleFactory;
+
+public final class DestinationTagSubrule extends TagSubrule {
+ public DestinationTagSubrule(TagSubruleFactory factory, TagSubruleData data) {
+ super(factory, data);
+ }
+
+ @Override
+ public boolean test(PDU pdu) {
+ return pdu.getDestination() == ((DestinationData) data).getDestination();
+ }
+
+ @Override
+ public String toString() {
+ return "To " + (((DestinationData) data).getDestination() == PduDestination.CLIENT ? "client"
+ : "server");
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/ends_with/EndsWithData.java b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/ends_with/EndsWithData.java
new file mode 100644
index 0000000..078cdb2
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/ends_with/EndsWithData.java
@@ -0,0 +1,37 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.tagger.factory.internal.ends_with;
+
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData;
+
+public final class EndsWithData extends TagSubruleData {
+ private final byte[] data;
+ private final String charset;
+
+ public EndsWithData(byte[] data, String charset) {
+ this.data = data;
+ this.charset = charset;
+ }
+
+ public byte[] getData() {
+ return data;
+ }
+
+ public String getCharset() {
+ return charset;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/ends_with/EndsWithSubruleConfigurator.java b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/ends_with/EndsWithSubruleConfigurator.java
new file mode 100644
index 0000000..f83b1d8
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/ends_with/EndsWithSubruleConfigurator.java
@@ -0,0 +1,55 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.tagger.factory.internal.ends_with;
+
+import java.io.IOException;
+import java.nio.charset.Charset;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleConfigurator;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData;
+import com.warxim.petep.gui.control.BytesEditor;
+import com.warxim.petep.gui.dialog.Dialogs;
+import javafx.fxml.FXML;
+
+public final class EndsWithSubruleConfigurator extends TagSubruleConfigurator {
+ @FXML
+ private BytesEditor dataInput;
+
+ public EndsWithSubruleConfigurator() throws IOException {
+ super("/fxml/extension/internal/tagger/factory/EndsWithSubrule.fxml");
+ }
+
+ @Override
+ public TagSubruleData getConfig() {
+ return new EndsWithData(dataInput.getBytes(), dataInput.getCharset().name());
+ }
+
+ @Override
+ public void setConfig(TagSubruleData config) {
+ dataInput.setData(((EndsWithData) config).getData(),
+ Charset.forName(((EndsWithData) config).getCharset()));
+ }
+
+ @Override
+ public boolean isValid() {
+ if (dataInput.getBytes().length == 0) {
+ Dialogs.createErrorDialog("Data required", "You have enter data.");
+ return false;
+ }
+
+ return true;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/ends_with/EndsWithSubruleFactory.java b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/ends_with/EndsWithSubruleFactory.java
new file mode 100644
index 0000000..5a7ba83
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/ends_with/EndsWithSubruleFactory.java
@@ -0,0 +1,51 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.tagger.factory.internal.ends_with;
+
+import java.io.IOException;
+import java.lang.reflect.Type;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubrule;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleConfigurator;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleFactory;
+
+public final class EndsWithSubruleFactory extends TagSubruleFactory {
+ @Override
+ public String getCode() {
+ return "ends_with";
+ }
+
+ @Override
+ public String getName() {
+ return "Ends with ...";
+ }
+
+ @Override
+ public TagSubrule createSubrule(TagSubruleData data) {
+ return new EndsWithTagSubrule(this, data);
+ }
+
+ @Override
+ public TagSubruleConfigurator createConfigPane() throws IOException {
+ return new EndsWithSubruleConfigurator();
+ }
+
+ @Override
+ public Type getConfigType() {
+ return EndsWithData.class;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/ends_with/EndsWithTagSubrule.java b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/ends_with/EndsWithTagSubrule.java
new file mode 100644
index 0000000..09f533e
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/ends_with/EndsWithTagSubrule.java
@@ -0,0 +1,34 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.tagger.factory.internal.ends_with;
+
+import com.warxim.petep.core.pdu.PDU;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubrule;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleFactory;
+import com.warxim.petep.util.PduUtils;
+
+public final class EndsWithTagSubrule extends TagSubrule {
+ public EndsWithTagSubrule(TagSubruleFactory factory, TagSubruleData data) {
+ super(factory, data);
+ }
+
+ @Override
+ public boolean test(PDU pdu) {
+ return PduUtils.endsWith(pdu, ((EndsWithData) data).getData());
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/has_tag/HasTagData.java b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/has_tag/HasTagData.java
new file mode 100644
index 0000000..7007873
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/has_tag/HasTagData.java
@@ -0,0 +1,31 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.tagger.factory.internal.has_tag;
+
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData;
+
+public final class HasTagData extends TagSubruleData {
+ private final String tag;
+
+ public HasTagData(String tag) {
+ this.tag = tag;
+ }
+
+ public String getTag() {
+ return tag;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/has_tag/HasTagSubruleConfigurator.java b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/has_tag/HasTagSubruleConfigurator.java
new file mode 100644
index 0000000..683d849
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/has_tag/HasTagSubruleConfigurator.java
@@ -0,0 +1,53 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.tagger.factory.internal.has_tag;
+
+import java.io.IOException;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleConfigurator;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData;
+import com.warxim.petep.gui.dialog.Dialogs;
+import javafx.fxml.FXML;
+import javafx.scene.control.TextField;
+
+public final class HasTagSubruleConfigurator extends TagSubruleConfigurator {
+ @FXML
+ private TextField tagInput;
+
+ public HasTagSubruleConfigurator() throws IOException {
+ super("/fxml/extension/internal/tagger/factory/HasTagSubrule.fxml");
+ }
+
+ @Override
+ public TagSubruleData getConfig() {
+ return new HasTagData(tagInput.getText());
+ }
+
+ @Override
+ public void setConfig(TagSubruleData config) {
+ tagInput.setText(((HasTagData) config).getTag());
+ }
+
+ @Override
+ public boolean isValid() {
+ if (tagInput.getText().length() == 0) {
+ Dialogs.createErrorDialog("Tag required", "You have to enter tag.");
+ return false;
+ }
+
+ return true;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/has_tag/HasTagSubruleFactory.java b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/has_tag/HasTagSubruleFactory.java
new file mode 100644
index 0000000..c37b959
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/has_tag/HasTagSubruleFactory.java
@@ -0,0 +1,51 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.tagger.factory.internal.has_tag;
+
+import java.io.IOException;
+import java.lang.reflect.Type;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubrule;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleConfigurator;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleFactory;
+
+public final class HasTagSubruleFactory extends TagSubruleFactory {
+ @Override
+ public String getCode() {
+ return "tag";
+ }
+
+ @Override
+ public String getName() {
+ return "Has tag ...";
+ }
+
+ @Override
+ public TagSubrule createSubrule(TagSubruleData data) {
+ return new HasTagTagSubrule(this, data);
+ }
+
+ @Override
+ public TagSubruleConfigurator createConfigPane() throws IOException {
+ return new HasTagSubruleConfigurator();
+ }
+
+ @Override
+ public Type getConfigType() {
+ return HasTagData.class;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/has_tag/HasTagTagSubrule.java b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/has_tag/HasTagTagSubrule.java
new file mode 100644
index 0000000..00f03ca
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/has_tag/HasTagTagSubrule.java
@@ -0,0 +1,38 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.tagger.factory.internal.has_tag;
+
+import com.warxim.petep.core.pdu.PDU;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubrule;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleFactory;
+
+public final class HasTagTagSubrule extends TagSubrule {
+ public HasTagTagSubrule(TagSubruleFactory factory, TagSubruleData data) {
+ super(factory, data);
+ }
+
+ @Override
+ public boolean test(PDU pdu) {
+ return pdu.hasTag(((HasTagData) data).getTag());
+ }
+
+ @Override
+ public String toString() {
+ return "Has tag " + ((HasTagData) data).getTag();
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/proxy/ProxyData.java b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/proxy/ProxyData.java
new file mode 100644
index 0000000..87a9083
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/proxy/ProxyData.java
@@ -0,0 +1,31 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.tagger.factory.internal.proxy;
+
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData;
+
+public final class ProxyData extends TagSubruleData {
+ private final String proxyCode;
+
+ public ProxyData(String proxyCode) {
+ this.proxyCode = proxyCode;
+ }
+
+ public String getProxyCode() {
+ return proxyCode;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/proxy/ProxySubruleConfigurator.java b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/proxy/ProxySubruleConfigurator.java
new file mode 100644
index 0000000..84c9b64
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/proxy/ProxySubruleConfigurator.java
@@ -0,0 +1,65 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.tagger.factory.internal.proxy;
+
+import java.io.IOException;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleConfigurator;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData;
+import com.warxim.petep.gui.dialog.Dialogs;
+import com.warxim.petep.helper.ExtensionHelper;
+import com.warxim.petep.proxy.module.ProxyModule;
+import javafx.collections.FXCollections;
+import javafx.collections.ObservableList;
+import javafx.fxml.FXML;
+import javafx.scene.control.ComboBox;
+
+public final class ProxySubruleConfigurator extends TagSubruleConfigurator {
+ @FXML
+ private ComboBox proxyInput;
+
+ public ProxySubruleConfigurator(ExtensionHelper helper) throws IOException {
+ super("/fxml/extension/internal/tagger/factory/ProxySubrule.fxml");
+
+ proxyInput.setItems(FXCollections.observableList(helper.getProxyModules()));
+ }
+
+ @Override
+ public TagSubruleData getConfig() {
+ return new ProxyData(proxyInput.getSelectionModel().getSelectedItem().getCode());
+ }
+
+ @Override
+ public void setConfig(TagSubruleData config) {
+ ObservableList modules = proxyInput.getItems();
+ for (int i = 0; i < modules.size(); ++i) {
+ if (modules.get(i).getCode().equals((((ProxyData) config).getProxyCode()))) {
+ proxyInput.getSelectionModel().select(i);
+ return;
+ }
+ }
+ }
+
+ @Override
+ public boolean isValid() {
+ if (proxyInput.getSelectionModel().getSelectedItem() == null) {
+ Dialogs.createErrorDialog("Proxy required", "You have to select proxy.");
+ return false;
+ }
+
+ return true;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/proxy/ProxySubruleFactory.java b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/proxy/ProxySubruleFactory.java
new file mode 100644
index 0000000..b4fa4db
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/proxy/ProxySubruleFactory.java
@@ -0,0 +1,58 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.tagger.factory.internal.proxy;
+
+import java.io.IOException;
+import java.lang.reflect.Type;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubrule;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleConfigurator;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleFactory;
+import com.warxim.petep.helper.ExtensionHelper;
+
+public final class ProxySubruleFactory extends TagSubruleFactory {
+ private ExtensionHelper helper;
+
+ public ProxySubruleFactory(ExtensionHelper helper) {
+ this.helper = helper;
+ }
+
+ @Override
+ public String getCode() {
+ return "proxy";
+ }
+
+ @Override
+ public String getName() {
+ return "Proxy ...";
+ }
+
+ @Override
+ public TagSubrule createSubrule(TagSubruleData data) {
+ return new ProxyTagSubrule(this, data);
+ }
+
+ @Override
+ public TagSubruleConfigurator createConfigPane() throws IOException {
+ return new ProxySubruleConfigurator(helper);
+ }
+
+ @Override
+ public Type getConfigType() {
+ return ProxyData.class;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/proxy/ProxyTagSubrule.java b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/proxy/ProxyTagSubrule.java
new file mode 100644
index 0000000..7696358
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/proxy/ProxyTagSubrule.java
@@ -0,0 +1,38 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.tagger.factory.internal.proxy;
+
+import com.warxim.petep.core.pdu.PDU;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubrule;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleFactory;
+
+public final class ProxyTagSubrule extends TagSubrule {
+ public ProxyTagSubrule(TagSubruleFactory factory, TagSubruleData data) {
+ super(factory, data);
+ }
+
+ @Override
+ public boolean test(PDU pdu) {
+ return pdu.getProxy().getModule().getCode().equals(((ProxyData) data).getProxyCode());
+ }
+
+ @Override
+ public String toString() {
+ return "Proxy " + ((ProxyData) data).getProxyCode();
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/size/SizeData.java b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/size/SizeData.java
new file mode 100644
index 0000000..bbdef24
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/size/SizeData.java
@@ -0,0 +1,31 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.tagger.factory.internal.size;
+
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData;
+
+public final class SizeData extends TagSubruleData {
+ private final int size;
+
+ public SizeData(int size) {
+ this.size = size;
+ }
+
+ public int getSize() {
+ return size;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/size/SizeSubruleConfigurator.java b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/size/SizeSubruleConfigurator.java
new file mode 100644
index 0000000..f0d36c9
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/size/SizeSubruleConfigurator.java
@@ -0,0 +1,59 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.tagger.factory.internal.size;
+
+import java.io.IOException;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleConfigurator;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData;
+import com.warxim.petep.gui.dialog.Dialogs;
+import javafx.fxml.FXML;
+import javafx.scene.control.TextField;
+
+public final class SizeSubruleConfigurator extends TagSubruleConfigurator {
+ @FXML
+ private TextField sizeInput;
+
+ public SizeSubruleConfigurator() throws IOException {
+ super("/fxml/extension/internal/tagger/factory/SizeSubrule.fxml");
+ }
+
+ @Override
+ public TagSubruleData getConfig() {
+ return new SizeData(Integer.parseInt(sizeInput.getText()));
+ }
+
+ @Override
+ public void setConfig(TagSubruleData config) {
+ sizeInput.setText(String.valueOf(((SizeData) config).getSize()));
+ }
+
+ @Override
+ public boolean isValid() {
+ try {
+ int size = Integer.parseInt(sizeInput.getText());
+ if (size < 0) {
+ Dialogs.createErrorDialog("Invalid size", "Size has to be number greater or equal to 0.");
+ return false;
+ }
+ } catch (NumberFormatException e) {
+ Dialogs.createErrorDialog("Invalid size", "Size has to be number greater or equal to 0.");
+ return false;
+ }
+
+ return true;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/size/SizeSubruleFactory.java b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/size/SizeSubruleFactory.java
new file mode 100644
index 0000000..c7f7133
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/size/SizeSubruleFactory.java
@@ -0,0 +1,51 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.tagger.factory.internal.size;
+
+import java.io.IOException;
+import java.lang.reflect.Type;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubrule;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleConfigurator;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleFactory;
+
+public final class SizeSubruleFactory extends TagSubruleFactory {
+ @Override
+ public String getCode() {
+ return "size";
+ }
+
+ @Override
+ public String getName() {
+ return "Size ...";
+ }
+
+ @Override
+ public TagSubrule createSubrule(TagSubruleData data) {
+ return new SizeTagSubrule(this, data);
+ }
+
+ @Override
+ public TagSubruleConfigurator createConfigPane() throws IOException {
+ return new SizeSubruleConfigurator();
+ }
+
+ @Override
+ public Type getConfigType() {
+ return SizeData.class;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/size/SizeTagSubrule.java b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/size/SizeTagSubrule.java
new file mode 100644
index 0000000..2a2a630
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/size/SizeTagSubrule.java
@@ -0,0 +1,38 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.tagger.factory.internal.size;
+
+import com.warxim.petep.core.pdu.PDU;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubrule;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleFactory;
+
+public final class SizeTagSubrule extends TagSubrule {
+ public SizeTagSubrule(TagSubruleFactory factory, TagSubruleData data) {
+ super(factory, data);
+ }
+
+ @Override
+ public boolean test(PDU pdu) {
+ return pdu.getSize() == ((SizeData) data).getSize();
+ }
+
+ @Override
+ public String toString() {
+ return "Size equals " + ((SizeData) data).getSize();
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/starts_with/StartsWithData.java b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/starts_with/StartsWithData.java
new file mode 100644
index 0000000..2b72a02
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/starts_with/StartsWithData.java
@@ -0,0 +1,31 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.tagger.factory.internal.starts_with;
+
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData;
+
+public final class StartsWithData extends TagSubruleData {
+ private final byte[] data;
+
+ public StartsWithData(byte[] data) {
+ this.data = data;
+ }
+
+ public byte[] getData() {
+ return data;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/starts_with/StartsWithSubruleConfigurator.java b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/starts_with/StartsWithSubruleConfigurator.java
new file mode 100644
index 0000000..ac4d714
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/starts_with/StartsWithSubruleConfigurator.java
@@ -0,0 +1,53 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.tagger.factory.internal.starts_with;
+
+import java.io.IOException;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleConfigurator;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData;
+import com.warxim.petep.gui.control.BytesEditor;
+import com.warxim.petep.gui.dialog.Dialogs;
+import javafx.fxml.FXML;
+
+public final class StartsWithSubruleConfigurator extends TagSubruleConfigurator {
+ @FXML
+ private BytesEditor dataInput;
+
+ public StartsWithSubruleConfigurator() throws IOException {
+ super("/fxml/extension/internal/tagger/factory/StartsWithSubrule.fxml");
+ }
+
+ @Override
+ public TagSubruleData getConfig() {
+ return new StartsWithData(dataInput.getBytes());
+ }
+
+ @Override
+ public void setConfig(TagSubruleData config) {
+ dataInput.setBytes(((StartsWithData) config).getData());
+ }
+
+ @Override
+ public boolean isValid() {
+ if (dataInput.getBytes().length == 0) {
+ Dialogs.createErrorDialog("Data required", "You have enter data.");
+ return false;
+ }
+
+ return true;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/starts_with/StartsWithSubruleFactory.java b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/starts_with/StartsWithSubruleFactory.java
new file mode 100644
index 0000000..1b1fd35
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/starts_with/StartsWithSubruleFactory.java
@@ -0,0 +1,51 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.tagger.factory.internal.starts_with;
+
+import java.io.IOException;
+import java.lang.reflect.Type;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubrule;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleConfigurator;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleFactory;
+
+public final class StartsWithSubruleFactory extends TagSubruleFactory {
+ @Override
+ public String getCode() {
+ return "starts_with";
+ }
+
+ @Override
+ public String getName() {
+ return "Starts with ...";
+ }
+
+ @Override
+ public TagSubrule createSubrule(TagSubruleData data) {
+ return new StartsWithTagSubrule(this, data);
+ }
+
+ @Override
+ public TagSubruleConfigurator createConfigPane() throws IOException {
+ return new StartsWithSubruleConfigurator();
+ }
+
+ @Override
+ public Type getConfigType() {
+ return StartsWithData.class;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/starts_with/StartsWithTagSubrule.java b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/starts_with/StartsWithTagSubrule.java
new file mode 100644
index 0000000..5c7745b
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/starts_with/StartsWithTagSubrule.java
@@ -0,0 +1,34 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.tagger.factory.internal.starts_with;
+
+import com.warxim.petep.core.pdu.PDU;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubrule;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleFactory;
+import com.warxim.petep.util.PduUtils;
+
+public final class StartsWithTagSubrule extends TagSubrule {
+ public StartsWithTagSubrule(TagSubruleFactory factory, TagSubruleData data) {
+ super(factory, data);
+ }
+
+ @Override
+ public boolean test(PDU pdu) {
+ return PduUtils.startsWith(pdu, ((StartsWithData) data).getData());
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/gui/TagGroupController.java b/src/main/java/com/warxim/petep/extension/internal/tagger/gui/TagGroupController.java
new file mode 100644
index 0000000..226206b
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/tagger/gui/TagGroupController.java
@@ -0,0 +1,164 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.tagger.gui;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.Optional;
+import java.util.ResourceBundle;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import com.warxim.petep.extension.internal.common.rule_group.RuleGroup;
+import com.warxim.petep.extension.internal.common.rule_group.gui.RuleGroupController;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleFactoryManager;
+import com.warxim.petep.extension.internal.tagger.gui.rule.EditTagRuleDialog;
+import com.warxim.petep.extension.internal.tagger.gui.rule.NewTagRuleDialog;
+import com.warxim.petep.extension.internal.tagger.rule.TagRule;
+import com.warxim.petep.gui.dialog.Dialogs;
+import javafx.collections.FXCollections;
+import javafx.event.ActionEvent;
+import javafx.fxml.FXML;
+import javafx.fxml.Initializable;
+import javafx.scene.control.TableColumn;
+import javafx.scene.control.TableView;
+import javafx.scene.control.cell.PropertyValueFactory;
+
+/** Tag group controller. */
+public final class TagGroupController extends RuleGroupController
+ implements Initializable {
+ private final TagSubruleFactoryManager moduleManager;
+
+ @FXML
+ private TableView table;
+
+ @FXML
+ private TableColumn nameColumn;
+
+ @FXML
+ private TableColumn tagColumn;
+
+ @FXML
+ private TableColumn enabledColumn;
+
+ /** Tag group controller constructor. */
+ public TagGroupController(RuleGroup group, TagSubruleFactoryManager moduleManager) {
+ super(group);
+ this.moduleManager = moduleManager;
+ }
+
+ @Override
+ public void initialize(URL location, ResourceBundle resources) {
+ nameColumn.setCellValueFactory(new PropertyValueFactory<>("name"));
+ tagColumn.setCellValueFactory(new PropertyValueFactory<>("tag"));
+ enabledColumn.setCellValueFactory(new PropertyValueFactory<>("enabled"));
+
+ table.setItems(FXCollections.observableList(group.getRules()));
+ }
+
+ @FXML
+ private void onNewButtonClick(ActionEvent event) {
+ try {
+ NewTagRuleDialog dialog = new NewTagRuleDialog(moduleManager);
+
+ Optional data = dialog.showAndWait();
+
+ if (!data.isPresent() || data.get() == null) {
+ return;
+ }
+
+ group.addRule(data.get());
+
+ refresh();
+ } catch (IOException e) {
+ Logger.getGlobal().log(Level.SEVERE, "Exception during openning of tag rule dialog", e);
+ }
+ }
+
+ @FXML
+ private void onEditButtonClick(ActionEvent event) {
+ TagRule rule = table.getSelectionModel().getSelectedItem();
+
+ if (rule == null) {
+ return;
+ }
+
+ try {
+ EditTagRuleDialog dialog = new EditTagRuleDialog(moduleManager, rule);
+
+ Optional data = dialog.showAndWait();
+
+ if (!data.isPresent() || data.get() == null) {
+ return;
+ }
+
+ group.replace(rule, data.get());
+
+ refresh();
+ } catch (IOException e) {
+ Logger.getGlobal().log(Level.SEVERE, "Exception during openning of tag rule dialog", e);
+ }
+ }
+
+ @FXML
+ private void onRemoveButtonClick(ActionEvent event) {
+ TagRule rule = table.getSelectionModel().getSelectedItem();
+
+ if (rule == null) {
+ return;
+ }
+
+ // Does user really want to remove rule?
+ if (!Dialogs.createYesOrNoDialog("Are you sure?",
+ "Do you really want to remove rule '" + rule.getName() + "'?")) {
+ return;
+ }
+
+ group.removeRule(rule);
+
+ refresh();
+ }
+
+ @FXML
+ private void onMoveUpButtonClick(ActionEvent event) {
+ int index = table.getSelectionModel().getSelectedIndex();
+
+ if (index <= 0) {
+ return;
+ }
+
+ group.swapRules(index, index - 1);
+
+ refresh();
+ }
+
+ @FXML
+ private void onMoveDownButtonClick(ActionEvent event) {
+ int index = table.getSelectionModel().getSelectedIndex();
+
+ if (index == -1 || index == group.ruleCount() - 1) {
+ return;
+ }
+
+ group.swapRules(index, index + 1);
+
+ refresh();
+ }
+
+ private void refresh() {
+ table.setItems(FXCollections.observableList(group.getRules()));
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/gui/TaggerController.java b/src/main/java/com/warxim/petep/extension/internal/tagger/gui/TaggerController.java
new file mode 100644
index 0000000..f7bac87
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/tagger/gui/TaggerController.java
@@ -0,0 +1,68 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.tagger.gui;
+
+import java.io.IOException;
+import com.warxim.petep.extension.internal.common.rule_group.RuleGroup;
+import com.warxim.petep.extension.internal.common.rule_group.gui.RuleGroupController;
+import com.warxim.petep.extension.internal.common.rule_group.gui.RuleGroupsController;
+import com.warxim.petep.extension.internal.common.rule_group.intercept.RuleInterceptorModule;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleFactoryManager;
+import com.warxim.petep.extension.internal.tagger.intercept.TagInterceptorModule;
+import com.warxim.petep.extension.internal.tagger.rule.TagRule;
+import com.warxim.petep.extension.internal.tagger.rule.TagRuleGroupManager;
+import com.warxim.petep.helper.ExtensionHelper;
+import javafx.fxml.FXML;
+import javafx.fxml.FXMLLoader;
+import javafx.scene.Node;
+import javafx.scene.control.TabPane;
+import javafx.util.Pair;
+
+/** Tagger controller. */
+public final class TaggerController extends RuleGroupsController {
+ private final TagSubruleFactoryManager factoryManager;
+
+ @FXML
+ private TabPane tabs;
+
+ /** Tagger controller constructor. */
+ public TaggerController(
+ TagRuleGroupManager groupManager,
+ ExtensionHelper extensionHelper,
+ TagSubruleFactoryManager factoryManager) {
+ super("Tagger", groupManager, extensionHelper);
+ this.factoryManager = factoryManager;
+ }
+
+ @Override
+ protected Class extends RuleInterceptorModule> getInterceptorModuleClass() {
+ return TagInterceptorModule.class;
+ }
+
+ @Override
+ protected Pair> createGroupTabNode(RuleGroup group)
+ throws IOException {
+ FXMLLoader fxmlLoader =
+ new FXMLLoader(getClass().getResource("/fxml/extension/internal/tagger/TagRuleGroup.fxml"));
+
+ TagGroupController controller = new TagGroupController(group, factoryManager);
+
+ fxmlLoader.setController(controller);
+
+ return new Pair<>(fxmlLoader.load(), controller);
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/gui/rule/EditTagRuleDialog.java b/src/main/java/com/warxim/petep/extension/internal/tagger/gui/rule/EditTagRuleDialog.java
new file mode 100644
index 0000000..457dee2
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/tagger/gui/rule/EditTagRuleDialog.java
@@ -0,0 +1,45 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.tagger.gui.rule;
+
+import java.io.IOException;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubrule;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleFactoryManager;
+import com.warxim.petep.extension.internal.tagger.rule.TagRule;
+
+/** Edit tag rule dialog. */
+public final class EditTagRuleDialog extends TagRuleDialog {
+ /** Edit tag rule dialog constructor. */
+ public EditTagRuleDialog(TagSubruleFactoryManager moduleManager, TagRule rule)
+ throws IOException {
+ super("Edit tag rule", "Save", moduleManager);
+
+ nameInput.setText(rule.getName());
+ descriptionInput.setText(rule.getDescription());
+ tagInput.setText(rule.getTag());
+ enabledInput.setSelected(rule.isEnabled());
+ expressionInput.setText(rule.getExpressionString());
+
+ for (TagSubrule subrule : rule.getSubrules()) {
+ subrules.add(subrule);
+ }
+
+ if (!generateExpression().equals(rule.getExpressionString())) {
+ customExpressionInput.setSelected(true);
+ }
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/gui/rule/NewTagRuleDialog.java b/src/main/java/com/warxim/petep/extension/internal/tagger/gui/rule/NewTagRuleDialog.java
new file mode 100644
index 0000000..be0ac22
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/tagger/gui/rule/NewTagRuleDialog.java
@@ -0,0 +1,28 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.tagger.gui.rule;
+
+import java.io.IOException;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleFactoryManager;
+
+/** New tag rule dialog. */
+public final class NewTagRuleDialog extends TagRuleDialog {
+ /** New tag rule dialog constructor. */
+ public NewTagRuleDialog(TagSubruleFactoryManager moduleManager) throws IOException {
+ super("New tag rule", "Create", moduleManager);
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/gui/rule/TagRuleDialog.java b/src/main/java/com/warxim/petep/extension/internal/tagger/gui/rule/TagRuleDialog.java
new file mode 100644
index 0000000..7fed309
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/tagger/gui/rule/TagRuleDialog.java
@@ -0,0 +1,325 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.tagger.gui.rule;
+
+import java.io.IOException;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Optional;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import com.warxim.booleanexpressioninterpreter.ExpressionParser;
+import com.warxim.booleanexpressioninterpreter.InvalidExpressionException;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubrule;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleFactoryManager;
+import com.warxim.petep.extension.internal.tagger.gui.subrule.EditTagSubruleDialog;
+import com.warxim.petep.extension.internal.tagger.gui.subrule.NewTagSubruleDialog;
+import com.warxim.petep.extension.internal.tagger.rule.TagRule;
+import com.warxim.petep.gui.dialog.Dialogs;
+import com.warxim.petep.gui.dialog.SimpleInputDialog;
+import javafx.beans.binding.Bindings;
+import javafx.beans.property.SimpleStringProperty;
+import javafx.beans.value.ObservableValue;
+import javafx.collections.FXCollections;
+import javafx.collections.ObservableList;
+import javafx.event.ActionEvent;
+import javafx.fxml.FXML;
+import javafx.scene.control.CheckBox;
+import javafx.scene.control.TableCell;
+import javafx.scene.control.TableColumn;
+import javafx.scene.control.TableView;
+import javafx.scene.control.TextArea;
+import javafx.scene.control.TextField;
+
+/** Tag rule dialog. */
+public abstract class TagRuleDialog extends SimpleInputDialog {
+ private static final String INDEX_REGEX =
+ "[^0-9()!]{0}[^0-9()!]|[^0-9()!]{0}$|^{0}$|^{0}[^0-9()!]";
+
+ private TagSubruleFactoryManager moduleManager;
+
+ @FXML
+ protected TextField nameInput;
+
+ @FXML
+ protected TextArea descriptionInput;
+
+ @FXML
+ protected TextField tagInput;
+
+ @FXML
+ protected CheckBox enabledInput;
+
+ @FXML
+ protected TextField expressionInput;
+
+ @FXML
+ protected CheckBox customExpressionInput;
+
+ @FXML
+ private TableView subrulesTable;
+
+ @FXML
+ private TableColumn indexColumn;
+
+ @FXML
+ private TableColumn typeColumn;
+
+ protected ObservableList subrules;
+
+ private TagRule rule;
+
+ /** Tag rule constructor. */
+ public TagRuleDialog(String title, String okText, TagSubruleFactoryManager moduleManager)
+ throws IOException {
+ super("/fxml/extension/internal/tagger/TagRuleDialog.fxml", title, okText);
+
+ this.moduleManager = moduleManager;
+
+ enabledInput.setSelected(true);
+
+ // Event when on custom expression checkbox is selected / deselected.
+ customExpressionInput.selectedProperty().addListener(this::onCustomExpressionSelectionChange);
+
+ // Run prepare on expression input change.
+ expressionInput.focusedProperty().addListener(this::onExpressionInputFocusChange);
+
+ // Allow only specific characters for expression input.
+ expressionInput.textProperty().addListener(this::onExpressionInputTextChange);
+
+ // Index number calculation.
+ indexColumn.setCellFactory(this::createIndexCell);
+
+ typeColumn.setCellValueFactory(cell -> new SimpleStringProperty(cell.getValue().toString()));
+
+ subrules = FXCollections.observableArrayList();
+ subrulesTable.setItems(subrules);
+ }
+
+ /** Generates expression using logical ANDs. */
+ protected final String generateExpression() {
+ StringBuilder builder = new StringBuilder();
+ for (int i = 0; i < subrules.size(); ++i) {
+ builder.append(i);
+ builder.append(" & ");
+ }
+
+ if (builder.length() > 3) {
+ builder.delete(builder.length() - 3, builder.length());
+ }
+
+ return builder.toString();
+ }
+
+ private final TableCell createIndexCell(
+ TableColumn column) {
+ TableCell cell = new TableCell<>();
+ cell.textProperty()
+ .bind(Bindings.createStringBinding(
+ () -> cell.isEmpty() ? null : Integer.toString(cell.getIndex()), cell.emptyProperty(),
+ cell.indexProperty()));
+ return cell;
+ }
+
+ private final void onCustomExpressionSelectionChange(
+ ObservableValue extends Boolean> observable,
+ boolean oldValue,
+ boolean newValue) {
+ if (newValue) {
+ expressionInput.setDisable(false);
+ } else {
+ expressionInput.setDisable(true);
+
+ refreshExpression();
+ }
+ }
+
+ private final void onExpressionInputTextChange(
+ ObservableValue extends String> observable,
+ String oldValue,
+ String newValue) {
+ if (!newValue.matches("\\s0-9!&\\(\\)\\{\\}\\[\\]\\|\\^")) {
+ expressionInput.setText(newValue.replaceAll("[^\\s0-9!&\\(\\)\\{\\}\\[\\]\\^\\|]", ""));
+ }
+ }
+
+ private final void onExpressionInputFocusChange(
+ ObservableValue extends Boolean> observable,
+ boolean oldValue,
+ boolean newValue) {
+ if (oldValue) {
+ try {
+ expressionInput
+ .setText(ExpressionParser.prepare(expressionInput.getText()).replace("! ", "!"));
+ } catch (InvalidExpressionException e) {
+ Dialogs.createErrorDialog("Expression is invalid", "Entered expression is invalid!");
+ }
+ }
+ }
+
+ /** Refreshes expression if custom expression is disabled. */
+ private final void refreshExpression() {
+ if (!customExpressionInput.isSelected()) {
+ expressionInput.setText(generateExpression());
+ }
+ }
+
+ @FXML
+ private final void onNewButtonClick(ActionEvent event) {
+ try {
+ NewTagSubruleDialog dialog = new NewTagSubruleDialog(moduleManager);
+
+ Optional data = dialog.showAndWait();
+
+ if (!data.isPresent() || data.get() == null) {
+ return;
+ }
+
+ subrules.add(data.get());
+
+ refreshExpression();
+ } catch (IOException e) {
+ Logger.getGlobal().log(Level.SEVERE, "Exception during openning of tag rule dialog", e);
+ }
+ }
+
+ @FXML
+ private final void onEditButtonClick(ActionEvent event) {
+ TagSubrule subrule = subrulesTable.getSelectionModel().getSelectedItem();
+
+ if (subrule == null) {
+ return;
+ }
+
+ try {
+ EditTagSubruleDialog dialog = new EditTagSubruleDialog(moduleManager, subrule);
+
+ Optional data = dialog.showAndWait();
+
+ if (!data.isPresent() || data.get() == null) {
+ return;
+ }
+
+ subrules.set(subrules.indexOf(subrule), data.get());
+ } catch (IOException e) {
+ Logger.getGlobal().log(Level.SEVERE, "Exception during openning of tag rule dialog", e);
+ }
+ }
+
+ @FXML
+ private final void onRemoveButtonClick(ActionEvent event) {
+ int index = subrulesTable.getSelectionModel().getSelectedIndex();
+
+ if (index == -1) {
+ return;
+ }
+
+ if (!Dialogs.createYesOrNoDialog("Are you sure?", "Do you really want to remove subrule?")) {
+ return;
+ }
+
+ subrules.remove(index);
+
+ if (customExpressionInput.isSelected()) {
+ try {
+ expressionInput.setText(ExpressionParser.prepare(
+ expressionInput.getText().replaceAll(MessageFormat.format(INDEX_REGEX, index), "")));
+ } catch (InvalidExpressionException e) {
+ Dialogs.createErrorDialog("Expression is invalid", "Entered expression is invalid!");
+ }
+ } else {
+ refreshExpression();
+ }
+ }
+
+ private final void swap(int what, int with) {
+ Collections.swap(subrules, what, with);
+
+ if (customExpressionInput.isSelected()) {
+ String newExpression = expressionInput.getText()
+ .replace("!", "! ")
+ .replaceAll(MessageFormat.format(INDEX_REGEX, what), "_TMP_");
+
+ newExpression =
+ newExpression.replaceAll(MessageFormat.format(INDEX_REGEX, with), String.valueOf(what));
+
+ newExpression = newExpression.replace("_TMP_", String.valueOf(with));
+
+ try {
+ expressionInput.setText(ExpressionParser.prepare(newExpression).replace("! ", "!"));
+ } catch (InvalidExpressionException e) {
+ Dialogs.createErrorDialog("Expression is invalid", "Entered expression is invalid!");
+ }
+ }
+ }
+
+ /** Move instance up */
+ @FXML
+ private final void onMoveUpButtonClick(ActionEvent event) {
+ int index = subrulesTable.getSelectionModel().getSelectedIndex();
+
+ if (index <= 0) {
+ return;
+ }
+
+ swap(index, index - 1);
+ }
+
+ /** Move instance down */
+ @FXML
+ private final void onMoveDownButtonClick(ActionEvent event) {
+ int index = subrulesTable.getSelectionModel().getSelectedIndex();
+
+ if (index == -1 || index == subrules.size() - 1) {
+ return;
+ }
+
+ swap(index, index + 1);
+ }
+
+ @Override
+ protected final boolean isValid() {
+ // Validate name.
+ if (nameInput.getText().isBlank()) {
+ Dialogs.createErrorDialog("Name required", "You have to enter name.");
+ return false;
+ }
+
+ // Validate tag.
+ if (tagInput.getText().isEmpty() || !tagInput.getText().matches("^[a-zA-Z0-9-_.]+$")) {
+ Dialogs.createErrorDialog("Tag required",
+ "You have to enter tag (allowed characters are A-Za-z0-9-_.).");
+ return false;
+ }
+
+ try {
+ rule = new TagRule(nameInput.getText(), descriptionInput.getText(), enabledInput.isSelected(),
+ tagInput.getText(), new ArrayList<>(subrules), expressionInput.getText());
+ } catch (InvalidExpressionException e) {
+ Dialogs.createErrorDialog("Invalid expression", "Entered expression is not valid!");
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ protected final TagRule obtainResult() {
+ return rule;
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/gui/subrule/EditTagSubruleDialog.java b/src/main/java/com/warxim/petep/extension/internal/tagger/gui/subrule/EditTagSubruleDialog.java
new file mode 100644
index 0000000..dc2aa37
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/tagger/gui/subrule/EditTagSubruleDialog.java
@@ -0,0 +1,50 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.tagger.gui.subrule;
+
+import java.io.IOException;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubrule;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleFactoryManager;
+import com.warxim.petep.gui.component.ConfigPane;
+
+/** Edit tag subrule dialog. */
+public final class EditTagSubruleDialog extends TagSubruleDialog {
+ /** Edit tag subrule dialog constructor. */
+ public EditTagSubruleDialog(TagSubruleFactoryManager factoryManager, TagSubrule subrule)
+ throws IOException {
+ super("Edit tag subrule", "Save", factoryManager);
+
+ factoryInput.getSelectionModel().select(subrule.getFactory());
+
+ // Load config pane.
+ ConfigPane pane = createFactoryPane();
+ if (pane == null) {
+ return;
+ }
+ setFactoryPane(pane);
+
+ // Get configuration from instance.
+ TagSubruleData data = subrule.getData();
+ if (data == null) {
+ return;
+ }
+
+ // Set config to pane.
+ pane.setConfig(data);
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/gui/subrule/NewTagSubruleDialog.java b/src/main/java/com/warxim/petep/extension/internal/tagger/gui/subrule/NewTagSubruleDialog.java
new file mode 100644
index 0000000..3570674
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/tagger/gui/subrule/NewTagSubruleDialog.java
@@ -0,0 +1,28 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.tagger.gui.subrule;
+
+import java.io.IOException;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleFactoryManager;
+
+/** New tag subrule dialog. */
+public final class NewTagSubruleDialog extends TagSubruleDialog {
+ /** New tag subrule dialog constructor. */
+ public NewTagSubruleDialog(TagSubruleFactoryManager factoryManager) throws IOException {
+ super("New tag subrule", "Create", factoryManager);
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/gui/subrule/TagSubruleDialog.java b/src/main/java/com/warxim/petep/extension/internal/tagger/gui/subrule/TagSubruleDialog.java
new file mode 100644
index 0000000..ce30834
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/tagger/gui/subrule/TagSubruleDialog.java
@@ -0,0 +1,134 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.tagger.gui.subrule;
+
+import java.io.IOException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubrule;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleFactory;
+import com.warxim.petep.extension.internal.tagger.factory.TagSubruleFactoryManager;
+import com.warxim.petep.gui.component.ConfigPane;
+import com.warxim.petep.gui.dialog.Dialogs;
+import com.warxim.petep.gui.dialog.SimpleInputDialog;
+import javafx.collections.FXCollections;
+import javafx.event.ActionEvent;
+import javafx.fxml.FXML;
+import javafx.scene.control.ComboBox;
+import javafx.scene.layout.AnchorPane;
+import javafx.util.StringConverter;
+
+/** Tag subrule dialog. */
+public abstract class TagSubruleDialog extends SimpleInputDialog {
+ @FXML
+ protected ComboBox factoryInput;
+
+ @FXML
+ protected AnchorPane factoryPane;
+
+ /** Tag subrule dialog constructor. */
+ public TagSubruleDialog(String title, String okText, TagSubruleFactoryManager factoryManager)
+ throws IOException {
+ super("/fxml/extension/internal/tagger/TagSubruleDialog.fxml", title, okText);
+
+ // Show factory name as factory input text.
+ factoryInput.setConverter(new StringConverter() {
+ @Override
+ public String toString(TagSubruleFactory factory) {
+ if (factory == null) {
+ return "";
+ }
+ return factory.getName();
+ }
+
+ @Override
+ public TagSubruleFactory fromString(String str) {
+ return null;
+ }
+ });
+
+ factoryInput.setItems(FXCollections.observableArrayList(factoryManager.getFactories()));
+ }
+
+ protected final void setFactoryPane(ConfigPane pane) {
+ if (pane == null) {
+ // Clear factory pane if config pane does not exist.
+ factoryPane.getChildren().clear();
+ return;
+ }
+
+ AnchorPane.setLeftAnchor(pane, 0D);
+ AnchorPane.setRightAnchor(pane, 0D);
+
+ // Add config pane to factory pane.
+ factoryPane.getChildren().setAll(pane);
+ }
+
+ protected final ConfigPane createFactoryPane() {
+ TagSubruleFactory factory = factoryInput.getSelectionModel().getSelectedItem();
+
+ if (factory == null) {
+ return null;
+ }
+
+ try {
+ return factory.createConfigPane();
+ } catch (IOException e) {
+ Logger.getGlobal().log(Level.SEVERE, "Could not load factory config pane.", e);
+ }
+
+ return null;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ protected final boolean isValid() {
+ // Validate factory
+ TagSubruleFactory factory = factoryInput.getSelectionModel().getSelectedItem();
+ if (factory == null) {
+ Dialogs.createErrorDialog("Factory required", "You have to select factory.");
+ return false;
+ }
+
+ // Validate configuration pane
+ if (!factoryPane.getChildren().isEmpty()
+ && !((ConfigPane) factoryPane.getChildren().get(0)).isValid()) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ protected final TagSubrule obtainResult() {
+ TagSubruleFactory factory = factoryInput.getSelectionModel().getSelectedItem();
+
+ if (factoryPane.getChildren().isEmpty()) {
+ return factory.createSubrule(null);
+ } else {
+ return factory.createSubrule(
+ ((ConfigPane) factoryPane.getChildren().get(0)).getConfig());
+ }
+ }
+
+ @FXML
+ private final void onFactoryChange(ActionEvent event) {
+ setFactoryPane(createFactoryPane());
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/intercept/TagInterceptor.java b/src/main/java/com/warxim/petep/extension/internal/tagger/intercept/TagInterceptor.java
new file mode 100644
index 0000000..3574245
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/tagger/intercept/TagInterceptor.java
@@ -0,0 +1,61 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.tagger.intercept;
+
+import com.warxim.petep.core.pdu.PDU;
+import com.warxim.petep.extension.internal.common.rule_group.RuleGroup;
+import com.warxim.petep.extension.internal.tagger.rule.TagRule;
+import com.warxim.petep.helper.PetepHelper;
+import com.warxim.petep.interceptor.worker.Interceptor;
+
+/** Tag interceptor. */
+public final class TagInterceptor extends Interceptor {
+ private final RuleGroup group;
+
+ /** Tag interceptor constructor. */
+ public TagInterceptor(int id, TagInterceptorModule module, PetepHelper helper) {
+ super(id, module, helper);
+
+ this.group = module.getRuleGroup();
+ }
+
+ @Override
+ public boolean prepare() {
+ return true;
+ }
+
+ @Override
+ public boolean intercept(PDU pdu) {
+ for (TagRule rule : group.getRules()) {
+ if (rule.test(pdu)) {
+ // Drop PDU if the tag is "drop".
+ if (rule.getTag().equals("drop")) {
+ return false;
+ }
+
+ pdu.addTag(rule.getTag());
+ }
+ }
+
+ return true;
+ }
+
+ @Override
+ public void stop() {
+ // No action needed.
+ }
+}
diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/intercept/TagInterceptorModule.java b/src/main/java/com/warxim/petep/extension/internal/tagger/intercept/TagInterceptorModule.java
new file mode 100644
index 0000000..1a882bb
--- /dev/null
+++ b/src/main/java/com/warxim/petep/extension/internal/tagger/intercept/TagInterceptorModule.java
@@ -0,0 +1,64 @@
+/*
+ * PEnetration TEsting Proxy (PETEP)
+ *
+ * Copyright (C) 2020 Michal Válka
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ */
+package com.warxim.petep.extension.internal.tagger.intercept;
+
+import com.warxim.petep.extension.internal.common.rule_group.RuleGroup;
+import com.warxim.petep.extension.internal.common.rule_group.config.RuleInterceptorConfig;
+import com.warxim.petep.extension.internal.common.rule_group.intercept.RuleInterceptorModule;
+import com.warxim.petep.extension.internal.tagger.TaggerExtension;
+import com.warxim.petep.extension.internal.tagger.rule.TagRule;
+import com.warxim.petep.helper.PetepHelper;
+import com.warxim.petep.interceptor.factory.InterceptorModuleFactory;
+import com.warxim.petep.interceptor.worker.Interceptor;
+import com.warxim.petep.persistence.Configurable;
+
+/** Tag interceptor module. */
+public final class TagInterceptorModule extends RuleInterceptorModule
+ implements Configurable {
+ private RuleGroup group;
+
+ /** Tag interceptor module constructor. */
+ public TagInterceptorModule(
+ InterceptorModuleFactory factory,
+ String code,
+ String name,
+ String description,
+ boolean enabled) {
+ super(factory, code, name, description, enabled);
+ }
+
+ @Override
+ public Interceptor createInterceptor(int id, PetepHelper helper) {
+ return new TagInterceptor(id, this, helper);
+ }
+
+ @Override
+ public RuleInterceptorConfig saveConfig() {
+ return new RuleInterceptorConfig(group.getCode());
+ }
+
+ @Override
+ public void loadConfig(RuleInterceptorConfig config) {
+ group = ((TaggerExtension) factory.getExtension()).getRuleGroupManager()
+ .get(config.getRuleGroupCode());
+ }
+
+ @Override
+ public RuleGroup