From e448f55c22981c9399a62d259b20ba73f2a5c1d0 Mon Sep 17 00:00:00 2001 From: Ramana Reddy Date: Thu, 5 Sep 2024 19:32:16 +0530 Subject: [PATCH] allow links clickable in tempalte editor --- .../nuclei/gui/TemplateGeneratorTab.java | 74 +++++++++++++++---- 1 file changed, 60 insertions(+), 14 deletions(-) diff --git a/src/main/java/io/projectdiscovery/nuclei/gui/TemplateGeneratorTab.java b/src/main/java/io/projectdiscovery/nuclei/gui/TemplateGeneratorTab.java index cc99196..61d4e2c 100644 --- a/src/main/java/io/projectdiscovery/nuclei/gui/TemplateGeneratorTab.java +++ b/src/main/java/io/projectdiscovery/nuclei/gui/TemplateGeneratorTab.java @@ -20,15 +20,20 @@ import org.yaml.snakeyaml.error.YAMLException; import javax.swing.*; +import javax.swing.event.MouseInputAdapter; +import javax.swing.text.BadLocationException; import javax.swing.text.JTextComponent; import java.awt.*; import java.awt.datatransfer.Clipboard; import java.awt.datatransfer.StringSelection; import java.awt.event.InputEvent; import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; import java.io.File; import java.io.IOException; import java.io.InputStream; +import java.net.URI; +import java.net.URISyntaxException; import java.net.URL; import java.nio.file.Files; import java.nio.file.Path; @@ -121,14 +126,14 @@ private String createCommand(Path nucleiPath, URL targetUrl) { } return String.format("%s -v -t %s -u %s", - wrapWithQuotesIfNecessary(nucleiPath.toString()), - wrapWithQuotesIfNecessary(this.templatePath.toString()), - wrapWithQuotesIfNecessary(targetUrl.toString())); + wrapWithQuotesIfNecessary(nucleiPath.toString()), + wrapWithQuotesIfNecessary(this.templatePath.toString()), + wrapWithQuotesIfNecessary(targetUrl.toString())); } private static String wrapWithQuotesIfNecessary(String input) { return input.contains(" ") ? String.format("\"%s\"", input) - : input; + : input; } private void setKeyboardShortcuts() { @@ -221,6 +226,7 @@ private void setupAutoCompletion(RSyntaxTextArea textEditor) { } } + private RSyntaxTextArea createSmartTextEditor(String templateYaml) { // TODO https://github.com/bobbylight/RSyntaxTextArea/issues/269 JTextComponent.removeKeymap("RTextAreaKeymap"); @@ -249,9 +255,49 @@ private RSyntaxTextArea createSmartTextEditor(String templateYaml) { setupAutoCompletion(textEditor); + textEditor.addMouseListener(new MouseInputAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + if (e.getClickCount() == 2) { // Trigger on double-click + int offset = textEditor.viewToModel2D(e.getPoint()); + String url = getUrlAtOffset(textEditor, offset); + if (url != null) { + try { + Desktop.getDesktop().browse(new URI(url)); + } catch (IOException | URISyntaxException ex) { + ex.printStackTrace(); + } + } + } + } + }); + return textEditor; } + + private String getUrlAtOffset(RSyntaxTextArea textEditor, int offset) { + try { + int start = offset; + int end = offset; + while (start > 0 && !Character.isWhitespace(textEditor.getText(start - 1, 1).charAt(0))) { + start--; + } + while (end < textEditor.getDocument().getLength() && !Character.isWhitespace(textEditor.getText(end, 1).charAt(0))) { + end++; + } + + String potentialUrl = textEditor.getText(start, end - start); + if (potentialUrl.startsWith("http://") || potentialUrl.startsWith("https://")) { + return potentialUrl; + } + } catch (BadLocationException e) { + e.printStackTrace(); + } + return null; + } + + private JMenu createTemplateEditorMenuItems() { final JMenu templateMenu = new JMenu("Add"); templateMenu.add(createTemplateEditorClassificationMenu()); @@ -476,8 +522,8 @@ public void approveSelection() { final File selectedFile = getSelectedFile(); if (selectedFile.exists() && getDialogType() == SAVE_DIALOG) { final int result = JOptionPane.showConfirmDialog(this, "The selected file already exists. Do you want to overwrite it?", - "Overwrite existing file?", - JOptionPane.YES_NO_CANCEL_OPTION); + "Overwrite existing file?", + JOptionPane.YES_NO_CANCEL_OPTION); switch (result) { case JOptionPane.YES_OPTION: super.approveSelection(); @@ -511,14 +557,14 @@ private void executeButtonClick() { } CommandLineUtils.asyncExecuteCommand(command, - bufferedReader -> bufferedReader.lines() - .map(line -> line + "\n") - .forEach(line -> SwingUtilities.invokeLater(() -> { - this.outputPane.appendText(line, noColor); - this.outputPane.repaint(); - })), - exitCode -> SwingUtilities.invokeLater(() -> this.outputPane.appendText("\nThe process exited with code " + exitCode)), - this.nucleiGeneratorSettings::logError); + bufferedReader -> bufferedReader.lines() + .map(line -> line + "\n") + .forEach(line -> SwingUtilities.invokeLater(() -> { + this.outputPane.appendText(line, noColor); + this.outputPane.repaint(); + })), + exitCode -> SwingUtilities.invokeLater(() -> this.outputPane.appendText("\nThe process exited with code " + exitCode)), + this.nucleiGeneratorSettings::logError); } } }