1
2
3
4
5
6
7
8
9
10
11 package com.jsql.view.swing.terminal;
12
13 import com.jsql.util.LogLevelUtil;
14 import org.apache.commons.lang3.StringUtils;
15 import org.apache.logging.log4j.LogManager;
16 import org.apache.logging.log4j.Logger;
17
18 import javax.swing.*;
19 import javax.swing.text.BadLocationException;
20 import javax.swing.text.Element;
21 import java.awt.event.InputEvent;
22 import java.awt.event.KeyAdapter;
23 import java.awt.event.KeyEvent;
24 import java.util.ArrayList;
25 import java.util.List;
26 import java.util.concurrent.atomic.AtomicReference;
27
28
29
30
31 public class KeyAdapterTerminal extends KeyAdapter {
32
33
34
35
36 private static final Logger LOGGER = LogManager.getRootLogger();
37
38
39
40
41 private final AbstractExploit terminal;
42
43
44
45
46 private final List<String> commandsHistory = new ArrayList<>();
47
48
49
50
51 private int indexCommandsHistory = 0;
52
53
54
55
56
57 public KeyAdapterTerminal(AbstractExploit terminal) {
58 this.terminal = terminal;
59 }
60
61 @Override
62 public void keyPressed(KeyEvent keyEvent) {
63 try {
64 var root = this.terminal.getDocument().getDefaultRootElement();
65 int caretPosition = this.terminal.getCaretPosition();
66 int lineNumber = this.terminal.getLineOfOffset(caretPosition);
67
68 if (this.terminal.getIsEdited().get()) {
69 keyEvent.consume();
70 return;
71 }
72
73
74 var command = new AtomicReference<>(StringUtils.EMPTY);
75 command.set(
76 this.terminal.getText(
77 root.getElement(lineNumber).getStartOffset(),
78 root.getElement(lineNumber).getEndOffset() - root.getElement(lineNumber).getStartOffset()
79 )
80 .replace(this.terminal.getPrompt(), StringUtils.EMPTY)
81 .trim()
82 );
83
84 if (keyEvent.getKeyCode() == KeyEvent.VK_ENTER) {
85 this.runCommand(keyEvent, command);
86 } else if (keyEvent.getKeyCode() == KeyEvent.VK_UP) {
87 this.appendPreviousCommand(keyEvent, root, lineNumber, command);
88 } else if (keyEvent.getKeyCode() == KeyEvent.VK_DOWN) {
89 this.appendNextCommand(keyEvent, root, lineNumber, command);
90 } else if (keyEvent.getKeyCode() == KeyEvent.VK_LEFT || keyEvent.getKeyCode() == KeyEvent.VK_BACK_SPACE) {
91 this.moveCaretLeft(keyEvent, caretPosition, lineNumber);
92 } else if (keyEvent.getKeyCode() == KeyEvent.VK_HOME) {
93 this.moveCaretHome(keyEvent, lineNumber);
94 } else if (this.isKeyNotAllowed(keyEvent, caretPosition)) {
95 keyEvent.consume();
96 } else if (keyEvent.getKeyCode() == KeyEvent.VK_C && (keyEvent.getModifiersEx() & InputEvent.CTRL_DOWN_MASK) != 0) {
97 this.cancelCommand(keyEvent);
98 }
99 } catch (BadLocationException e) {
100 LOGGER.log(LogLevelUtil.CONSOLE_JAVA, e, e);
101 }
102 }
103
104 private boolean isKeyNotAllowed(KeyEvent keyEvent, int caretPosition) {
105 return
106
107 keyEvent.getKeyCode() == KeyEvent.VK_A && (keyEvent.getModifiersEx() & InputEvent.CTRL_DOWN_MASK) != 0
108
109 || keyEvent.getKeyCode() == KeyEvent.VK_DELETE && caretPosition == this.terminal.getDocument().getLength()
110 || (keyEvent.getModifiersEx() & InputEvent.CTRL_DOWN_MASK) != 0 && (keyEvent.getModifiersEx() & InputEvent.SHIFT_DOWN_MASK) != 0
111 || keyEvent.getKeyCode() == KeyEvent.VK_PAGE_UP
112 || keyEvent.getKeyCode() == KeyEvent.VK_PAGE_DOWN
113 || keyEvent.getKeyCode() == KeyEvent.VK_TAB;
114 }
115
116 private void cancelCommand(KeyEvent keyEvent) {
117 keyEvent.consume();
118 this.terminal.append("\n");
119 this.terminal.reset();
120 }
121
122 private void moveCaretHome(KeyEvent keyEvent, int lineNumber) throws BadLocationException {
123 keyEvent.consume();
124 this.terminal.setCaretPosition(this.terminal.getLineStartOffset(lineNumber) + this.terminal.getPrompt().length());
125 }
126
127 private void moveCaretLeft(KeyEvent keyEvent, int caretPosition, int lineNumber) throws BadLocationException {
128 int newCaretPosition = caretPosition - this.terminal.getLineStartOffset(lineNumber);
129 if (newCaretPosition <= this.terminal.getPrompt().length()) {
130 keyEvent.consume();
131 }
132 }
133
134 private void appendNextCommand(
135 KeyEvent keyEvent,
136 Element root,
137 int lineNumber,
138 AtomicReference<String> command
139 ) throws BadLocationException {
140 keyEvent.consume();
141
142 if (this.indexCommandsHistory < this.commandsHistory.size()) {
143 this.indexCommandsHistory++;
144 }
145
146 if (!this.commandsHistory.isEmpty() && this.indexCommandsHistory < this.commandsHistory.size()) {
147 this.terminal.getDocument().remove(
148 root.getElement(lineNumber).getStartOffset() + this.terminal.getPrompt().length(),
149 command.get().length() - 1
150 );
151
152 this.terminal.append(this.commandsHistory.get(this.indexCommandsHistory));
153 this.terminal.setCaretPosition(this.terminal.getDocument().getLength());
154 }
155 }
156
157 private void appendPreviousCommand(
158 KeyEvent keyEvent,
159 Element root,
160 int lineNumber,
161 AtomicReference<String> command
162 ) throws BadLocationException {
163 keyEvent.consume();
164
165 if (this.indexCommandsHistory > 0) {
166 this.indexCommandsHistory--;
167 }
168
169 if (!this.commandsHistory.isEmpty()) {
170 if (
171 this.commandsHistory.size() > 1
172 && this.indexCommandsHistory == this.commandsHistory.size() - 1
173 && StringUtils.isNotEmpty(command.get())
174 ) {
175 this.indexCommandsHistory--;
176 }
177
178 this.terminal.getDocument().remove(
179 root.getElement(lineNumber).getStartOffset() + this.terminal.getPrompt().length(),
180 command.get().length() - 1
181 );
182
183 this.terminal.append(this.commandsHistory.get(this.indexCommandsHistory));
184 this.terminal.setCaretPosition(this.terminal.getDocument().getLength());
185 }
186 }
187
188 private void runCommand(KeyEvent keyEvent, AtomicReference<String> command) {
189 this.terminal.getIsEdited().set(true);
190 keyEvent.consume();
191 this.terminal.setEditable(false);
192
193
194 if (StringUtils.isNotEmpty(command.get())) {
195 this.commandsHistory.add(command.get());
196 this.indexCommandsHistory = this.commandsHistory.size();
197 }
198
199 new SwingWorker<>() {
200 @Override
201 protected Object doInBackground() {
202
203 Thread.currentThread().setName("SwingWorkerKeyAdapterTerminal");
204
205 AbstractExploit terminalCommand = KeyAdapterTerminal.this.terminal;
206 terminalCommand.append("\n");
207
208 if (StringUtils.isNotEmpty(command.get())) {
209 terminalCommand.setCaretPosition(terminalCommand.getDocument().getLength());
210 terminalCommand.action(
211 command.get(),
212 terminalCommand.getUuidShell(),
213 terminalCommand.getUrlShell(),
214 terminalCommand.loginPassword
215 );
216 } else {
217 terminalCommand.reset();
218 }
219 return null;
220 }
221 }.execute();
222 }
223 }