AbstractExploit.java

1
/*******************************************************************************
2
 * Copyhacked (H) 2012-2025.
3
 * This program and the accompanying materials
4
 * are made available under no term at all, use it like
5
 * you want, but share and discuss it
6
 * every time possible with every body.
7
 * 
8
 * Contributors:
9
 *      ron190 at ymail dot com - initial implementation
10
 ******************************************************************************/
11
package com.jsql.view.swing.terminal;
12
13
import com.jsql.util.LogLevelUtil;
14
import com.jsql.view.swing.terminal.util.BlockCaret;
15
import com.jsql.view.swing.terminal.util.KeyAdapterTerminal;
16
import com.jsql.view.swing.util.MediatorHelper;
17
import com.jsql.view.swing.util.UiUtil;
18
import org.apache.commons.lang3.StringUtils;
19
import org.apache.logging.log4j.LogManager;
20
import org.apache.logging.log4j.Logger;
21
22
import javax.swing.*;
23
import javax.swing.text.BadLocationException;
24
import javax.swing.text.Style;
25
import javax.swing.text.StyleConstants;
26
import java.awt.*;
27
import java.awt.event.MouseMotionListener;
28
import java.net.MalformedURLException;
29
import java.net.URI;
30
import java.net.URISyntaxException;
31
import java.net.URL;
32
import java.util.UUID;
33
import java.util.concurrent.atomic.AtomicBoolean;
34
35
/**
36
 * A Terminal completely built from swing text pane.
37
 */
38
public abstract class AbstractExploit extends JTextPane {
39
    
40
    private static final Logger LOGGER = LogManager.getRootLogger();
41
42
    /**
43
     * True if terminal is processing command.
44
     */
45
    private final AtomicBoolean isEdited = new AtomicBoolean(false);
46
47
    /**
48
     * Server name or IP to display on prompt.
49
     */
50
    private final String host;
51
52
    /**
53
     * User and password for database.
54
     */
55
    private String[] loginPassword = null;
56
    private final UUID uuidShell;
57
    private final String urlShell;
58
59
    /**
60
     * Style used for coloring text.
61
     */
62
    private final transient Style style = this.addStyle("Necrophagist's next album is 2014.", null);
63
64
    /**
65
     * Length of prompt.
66
     */
67
    private String prompt = StringUtils.EMPTY;
68
69
    /**
70
     * Text to display next caret.
71
     */
72
    private final String labelShell;
73
    
74
    /**
75
     * Build a shell instance.
76
     * @param uuidShell Unique identifier to discriminate beyond multiple opened terminals
77
     * @param urlShell URL of current shell
78
     * @param labelShell Type of shell to display on prompt
79
     */
80
    protected AbstractExploit(UUID uuidShell, String urlShell, String labelShell) throws MalformedURLException, URISyntaxException {
81
        this(uuidShell, urlShell, labelShell, true);
82
    }
83
    protected AbstractExploit(UUID uuidShell, String urlShell, String labelShell, boolean isAddingPrompt) throws MalformedURLException, URISyntaxException {
84
        this.uuidShell = uuidShell;
85
        this.urlShell = urlShell;
86
        this.labelShell = labelShell;
87
88
        URL url;
89 1 1. <init> : negated conditional → NO_COVERAGE
        if (StringUtils.isEmpty(urlShell)) {  // udf
90
            url = new URI(MediatorHelper.model().getMediatorUtils().getConnectionUtil().getUrlByUser()).toURL();
91
        } else {
92
            url = new URI(urlShell).toURL();
93
        }
94
        this.host = url.getHost();
95
96 1 1. <init> : removed call to com/jsql/view/swing/terminal/AbstractExploit::setFont → NO_COVERAGE
        this.setFont(new Font(UiUtil.FONT_NAME_MONO_NON_ASIAN, Font.PLAIN, UIManager.getFont("TextArea.font").getSize()));
97 1 1. <init> : removed call to com/jsql/view/swing/terminal/AbstractExploit::setCaret → NO_COVERAGE
        this.setCaret(new BlockCaret());
98 1 1. <init> : removed call to com/jsql/view/swing/terminal/AbstractExploit::setBackground → NO_COVERAGE
        this.setBackground(Color.BLACK);
99 1 1. <init> : removed call to com/jsql/view/swing/terminal/AbstractExploit::setForeground → NO_COVERAGE
        this.setForeground(Color.LIGHT_GRAY);
100
101 1 1. <init> : negated conditional → NO_COVERAGE
        if (isAddingPrompt) {
102 1 1. <init> : removed call to com/jsql/view/swing/terminal/AbstractExploit::displayPrompt → NO_COVERAGE
            this.displayPrompt(true);
103
        } else {
104 1 1. <init> : removed call to com/jsql/view/swing/terminal/AbstractExploit::append → NO_COVERAGE
            this.append("Waiting for reverse connection...\n");
105
        }
106
107 1 1. <init> : removed call to com/jsql/view/swing/terminal/AbstractExploit::setCursor → NO_COVERAGE
        this.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
108 1 1. <init> : removed call to com/jsql/view/swing/terminal/AbstractExploit::setTransferHandler → NO_COVERAGE
        this.setTransferHandler(null);
109 1 1. <init> : removed call to com/jsql/view/swing/terminal/AbstractExploit::setHighlighter → NO_COVERAGE
        this.setHighlighter(null);
110
111 1 1. <init> : removed call to com/jsql/view/swing/terminal/AbstractExploit::addMouseListener → NO_COVERAGE
        this.addMouseListener(new EmptyFocusCopy(this));
112 1 1. <init> : removed call to com/jsql/view/swing/terminal/AbstractExploit::addKeyListener → NO_COVERAGE
        this.addKeyListener(new KeyAdapterTerminal(this));
113
    }
114
115
    /**
116
     * Run when cmd is validated.
117
     * @param cmd Command to execute
118
     * @param terminalID Unique ID for terminal instance
119
     * @param wbhPath URL of shell
120
     * @param arg Additional parameters (User and password for SQLShell)
121
     */
122
    public abstract void action(String cmd, UUID terminalID, String wbhPath, String... arg);
123
    
124
    /**
125
     * Update terminal and use default behavior.
126
     */
127
    public void reset() {
128 1 1. reset : removed call to com/jsql/view/swing/terminal/AbstractExploit::reset → NO_COVERAGE
        this.reset(true);
129
    }
130
    public void reset(boolean isPromptVisible) {
131 1 1. reset : removed call to java/util/concurrent/atomic/AtomicBoolean::set → NO_COVERAGE
        this.isEdited.set(false);
132 1 1. reset : removed call to com/jsql/view/swing/terminal/AbstractExploit::setEditable → NO_COVERAGE
        this.setEditable(true);
133 1 1. reset : negated conditional → NO_COVERAGE
        if (isPromptVisible) {
134 1 1. reset : removed call to com/jsql/view/swing/terminal/AbstractExploit::displayPrompt → NO_COVERAGE
            this.displayPrompt(false);
135
        }
136 1 1. reset : removed call to com/jsql/view/swing/terminal/AbstractExploit::setCaretPosition → NO_COVERAGE
        this.setCaretPosition(this.getDocument().getLength());
137 1 1. reset : removed call to com/jsql/view/swing/terminal/AbstractExploit::setCursor → NO_COVERAGE
        this.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
138
    }
139
140
    /**
141
     * Add a text at the end of textpane.
142
     * @param string Text to add
143
     */
144
    public void append(String string) {
145
        try {
146
            var doc = this.getDocument();
147 1 1. append : removed call to javax/swing/text/Document::insertString → NO_COVERAGE
            doc.insertString(doc.getLength(), string, null);
148
        } catch (BadLocationException e) {
149
            LOGGER.log(LogLevelUtil.CONSOLE_JAVA, e, e);
150
        }
151
    }
152
    
153
    /**
154
     * Append prompt to textpane, measure prompt the first time is used.
155
     * @param isAddingPrompt Should we measure prompt length?
156
     */
157
    public void displayPrompt(boolean isAddingPrompt) {
158 1 1. displayPrompt : removed call to javax/swing/text/StyleConstants::setUnderline → NO_COVERAGE
        StyleConstants.setUnderline(this.style, true);
159 1 1. displayPrompt : removed call to com/jsql/view/swing/terminal/AbstractExploit::appendPrompt → NO_COVERAGE
        this.appendPrompt("jsql", Color.LIGHT_GRAY, isAddingPrompt);
160 1 1. displayPrompt : removed call to javax/swing/text/StyleConstants::setUnderline → NO_COVERAGE
        StyleConstants.setUnderline(this.style, false);
161
162 1 1. displayPrompt : removed call to com/jsql/view/swing/terminal/AbstractExploit::appendPrompt → NO_COVERAGE
        this.appendPrompt(StringUtils.SPACE + this.labelShell, Color.LIGHT_GRAY, isAddingPrompt);
163 1 1. displayPrompt : removed call to com/jsql/view/swing/terminal/AbstractExploit::appendPrompt → NO_COVERAGE
        this.appendPrompt("[", new Color(0x32BF32), isAddingPrompt);
164 1 1. displayPrompt : removed call to com/jsql/view/swing/terminal/AbstractExploit::appendPrompt → NO_COVERAGE
        this.appendPrompt(this.host, new Color(0xBFBF19), isAddingPrompt);
165 1 1. displayPrompt : removed call to com/jsql/view/swing/terminal/AbstractExploit::appendPrompt → NO_COVERAGE
        this.appendPrompt("]", new Color(0x32BF32), isAddingPrompt);
166 1 1. displayPrompt : removed call to com/jsql/view/swing/terminal/AbstractExploit::appendPrompt → NO_COVERAGE
        this.appendPrompt(" >", new Color(0xBF6464), isAddingPrompt);
167 1 1. displayPrompt : removed call to com/jsql/view/swing/terminal/AbstractExploit::appendPrompt → NO_COVERAGE
        this.appendPrompt(StringUtils.SPACE, Color.LIGHT_GRAY, isAddingPrompt);
168
    }
169
170
    /**
171
     * Add a colored string to the textpane, measure prompt at the same time.
172
     * @param string Text to append
173
     * @param color Color of text
174
     * @param isAddingPrompt Should we measure prompt length?
175
     */
176
    private void appendPrompt(String string, Color color, boolean isAddingPrompt) {
177
        try {
178 1 1. appendPrompt : removed call to javax/swing/text/StyleConstants::setForeground → NO_COVERAGE
            StyleConstants.setForeground(this.style, color);
179 1 1. appendPrompt : removed call to javax/swing/text/StyledDocument::insertString → NO_COVERAGE
            this.getStyledDocument().insertString(this.getStyledDocument().getLength(), string, this.style);
180 1 1. appendPrompt : negated conditional → NO_COVERAGE
            if (isAddingPrompt) {
181
                this.prompt += string;
182
            }
183
        } catch (BadLocationException e) {
184
            LOGGER.log(LogLevelUtil.CONSOLE_JAVA, e, e);
185
        }
186
    }
187
188
    /**
189
     * NoWrap.
190
     */
191
    @Override
192
    public boolean getScrollableTracksViewportWidth() {
193 3 1. getScrollableTracksViewportWidth : negated conditional → NO_COVERAGE
2. getScrollableTracksViewportWidth : replaced boolean return with true for com/jsql/view/swing/terminal/AbstractExploit::getScrollableTracksViewportWidth → NO_COVERAGE
3. getScrollableTracksViewportWidth : changed conditional boundary → NO_COVERAGE
        return this.getUI().getPreferredSize(this).width <= this.getParent().getSize().width;
194
    }
195
196
    /**
197
     * Cancel every mouse movement processing like drag/drop.
198
     */
199
    @Override
200
    public synchronized void addMouseMotionListener(MouseMotionListener l) {
201
        // Do nothing
202
    }
203
204
    /**
205
     * Get index of line for current offset (generally cursor position).
206
     * @param offset Position on the line
207
     * @return Index of the line
208
     */
209
    public int getLineOfOffset(int offset) throws BadLocationException {
210
        var errorMsg = "Can't translate offset to line";
211
        var doc = this.getDocument();
212
        
213 2 1. getLineOfOffset : negated conditional → NO_COVERAGE
2. getLineOfOffset : changed conditional boundary → NO_COVERAGE
        if (offset < 0) {
214
            throw new BadLocationException(errorMsg, -1);
215 2 1. getLineOfOffset : changed conditional boundary → NO_COVERAGE
2. getLineOfOffset : negated conditional → NO_COVERAGE
        } else if (offset > doc.getLength()) {
216 1 1. getLineOfOffset : Replaced integer addition with subtraction → NO_COVERAGE
            throw new BadLocationException(errorMsg, doc.getLength() + 1);
217
        } else {
218
            var map = doc.getDefaultRootElement();
219 1 1. getLineOfOffset : replaced int return with 0 for com/jsql/view/swing/terminal/AbstractExploit::getLineOfOffset → NO_COVERAGE
            return map.getElementIndex(offset);
220
        }
221
    }
222
223
    /**
224
     * Get position of the beginning of the line.
225
     * @param line Index of the line
226
     * @return Offset of line
227
     */
228
    public int getLineStartOffset(int line) throws BadLocationException {
229
        var map = this.getDocument().getDefaultRootElement();
230
        
231 2 1. getLineStartOffset : negated conditional → NO_COVERAGE
2. getLineStartOffset : changed conditional boundary → NO_COVERAGE
        if (line < 0) {
232
            throw new BadLocationException("Negative line", -1);
233 2 1. getLineStartOffset : changed conditional boundary → NO_COVERAGE
2. getLineStartOffset : negated conditional → NO_COVERAGE
        } else if (line >= map.getElementCount()) {
234 1 1. getLineStartOffset : Replaced integer addition with subtraction → NO_COVERAGE
            throw new BadLocationException("No such line", this.getDocument().getLength() + 1);
235
        } else {
236
            var lineElem = map.getElement(line);
237 1 1. getLineStartOffset : replaced int return with 0 for com/jsql/view/swing/terminal/AbstractExploit::getLineStartOffset → NO_COVERAGE
            return lineElem.getStartOffset();
238
        }
239
    }
240
241
    
242
    // Getter and setter
243
    
244
    public AtomicBoolean getIsEdited() {
245 1 1. getIsEdited : replaced return value with null for com/jsql/view/swing/terminal/AbstractExploit::getIsEdited → NO_COVERAGE
        return this.isEdited;
246
    }
247
248
    public UUID getUuidShell() {
249 1 1. getUuidShell : replaced return value with null for com/jsql/view/swing/terminal/AbstractExploit::getUuidShell → NO_COVERAGE
        return this.uuidShell;
250
    }
251
252
    public String getUrlShell() {
253 1 1. getUrlShell : replaced return value with "" for com/jsql/view/swing/terminal/AbstractExploit::getUrlShell → NO_COVERAGE
        return this.urlShell;
254
    }
255
256
    public String getPrompt() {
257 1 1. getPrompt : replaced return value with "" for com/jsql/view/swing/terminal/AbstractExploit::getPrompt → NO_COVERAGE
        return this.prompt;
258
    }
259
260
    public String[] getLoginPassword() {
261 1 1. getLoginPassword : replaced return value with null for com/jsql/view/swing/terminal/AbstractExploit::getLoginPassword → NO_COVERAGE
        return this.loginPassword;
262
    }
263
264
    public void setLoginPassword(String[] loginPassword) {
265
        this.loginPassword = loginPassword;
266
    }
267
}

Mutations

89

1.1
Location : <init>
Killed by : none
negated conditional → NO_COVERAGE

96

1.1
Location : <init>
Killed by : none
removed call to com/jsql/view/swing/terminal/AbstractExploit::setFont → NO_COVERAGE

97

1.1
Location : <init>
Killed by : none
removed call to com/jsql/view/swing/terminal/AbstractExploit::setCaret → NO_COVERAGE

98

1.1
Location : <init>
Killed by : none
removed call to com/jsql/view/swing/terminal/AbstractExploit::setBackground → NO_COVERAGE

99

1.1
Location : <init>
Killed by : none
removed call to com/jsql/view/swing/terminal/AbstractExploit::setForeground → NO_COVERAGE

101

1.1
Location : <init>
Killed by : none
negated conditional → NO_COVERAGE

102

1.1
Location : <init>
Killed by : none
removed call to com/jsql/view/swing/terminal/AbstractExploit::displayPrompt → NO_COVERAGE

104

1.1
Location : <init>
Killed by : none
removed call to com/jsql/view/swing/terminal/AbstractExploit::append → NO_COVERAGE

107

1.1
Location : <init>
Killed by : none
removed call to com/jsql/view/swing/terminal/AbstractExploit::setCursor → NO_COVERAGE

108

1.1
Location : <init>
Killed by : none
removed call to com/jsql/view/swing/terminal/AbstractExploit::setTransferHandler → NO_COVERAGE

109

1.1
Location : <init>
Killed by : none
removed call to com/jsql/view/swing/terminal/AbstractExploit::setHighlighter → NO_COVERAGE

111

1.1
Location : <init>
Killed by : none
removed call to com/jsql/view/swing/terminal/AbstractExploit::addMouseListener → NO_COVERAGE

112

1.1
Location : <init>
Killed by : none
removed call to com/jsql/view/swing/terminal/AbstractExploit::addKeyListener → NO_COVERAGE

128

1.1
Location : reset
Killed by : none
removed call to com/jsql/view/swing/terminal/AbstractExploit::reset → NO_COVERAGE

131

1.1
Location : reset
Killed by : none
removed call to java/util/concurrent/atomic/AtomicBoolean::set → NO_COVERAGE

132

1.1
Location : reset
Killed by : none
removed call to com/jsql/view/swing/terminal/AbstractExploit::setEditable → NO_COVERAGE

133

1.1
Location : reset
Killed by : none
negated conditional → NO_COVERAGE

134

1.1
Location : reset
Killed by : none
removed call to com/jsql/view/swing/terminal/AbstractExploit::displayPrompt → NO_COVERAGE

136

1.1
Location : reset
Killed by : none
removed call to com/jsql/view/swing/terminal/AbstractExploit::setCaretPosition → NO_COVERAGE

137

1.1
Location : reset
Killed by : none
removed call to com/jsql/view/swing/terminal/AbstractExploit::setCursor → NO_COVERAGE

147

1.1
Location : append
Killed by : none
removed call to javax/swing/text/Document::insertString → NO_COVERAGE

158

1.1
Location : displayPrompt
Killed by : none
removed call to javax/swing/text/StyleConstants::setUnderline → NO_COVERAGE

159

1.1
Location : displayPrompt
Killed by : none
removed call to com/jsql/view/swing/terminal/AbstractExploit::appendPrompt → NO_COVERAGE

160

1.1
Location : displayPrompt
Killed by : none
removed call to javax/swing/text/StyleConstants::setUnderline → NO_COVERAGE

162

1.1
Location : displayPrompt
Killed by : none
removed call to com/jsql/view/swing/terminal/AbstractExploit::appendPrompt → NO_COVERAGE

163

1.1
Location : displayPrompt
Killed by : none
removed call to com/jsql/view/swing/terminal/AbstractExploit::appendPrompt → NO_COVERAGE

164

1.1
Location : displayPrompt
Killed by : none
removed call to com/jsql/view/swing/terminal/AbstractExploit::appendPrompt → NO_COVERAGE

165

1.1
Location : displayPrompt
Killed by : none
removed call to com/jsql/view/swing/terminal/AbstractExploit::appendPrompt → NO_COVERAGE

166

1.1
Location : displayPrompt
Killed by : none
removed call to com/jsql/view/swing/terminal/AbstractExploit::appendPrompt → NO_COVERAGE

167

1.1
Location : displayPrompt
Killed by : none
removed call to com/jsql/view/swing/terminal/AbstractExploit::appendPrompt → NO_COVERAGE

178

1.1
Location : appendPrompt
Killed by : none
removed call to javax/swing/text/StyleConstants::setForeground → NO_COVERAGE

179

1.1
Location : appendPrompt
Killed by : none
removed call to javax/swing/text/StyledDocument::insertString → NO_COVERAGE

180

1.1
Location : appendPrompt
Killed by : none
negated conditional → NO_COVERAGE

193

1.1
Location : getScrollableTracksViewportWidth
Killed by : none
negated conditional → NO_COVERAGE

2.2
Location : getScrollableTracksViewportWidth
Killed by : none
replaced boolean return with true for com/jsql/view/swing/terminal/AbstractExploit::getScrollableTracksViewportWidth → NO_COVERAGE

3.3
Location : getScrollableTracksViewportWidth
Killed by : none
changed conditional boundary → NO_COVERAGE

213

1.1
Location : getLineOfOffset
Killed by : none
negated conditional → NO_COVERAGE

2.2
Location : getLineOfOffset
Killed by : none
changed conditional boundary → NO_COVERAGE

215

1.1
Location : getLineOfOffset
Killed by : none
changed conditional boundary → NO_COVERAGE

2.2
Location : getLineOfOffset
Killed by : none
negated conditional → NO_COVERAGE

216

1.1
Location : getLineOfOffset
Killed by : none
Replaced integer addition with subtraction → NO_COVERAGE

219

1.1
Location : getLineOfOffset
Killed by : none
replaced int return with 0 for com/jsql/view/swing/terminal/AbstractExploit::getLineOfOffset → NO_COVERAGE

231

1.1
Location : getLineStartOffset
Killed by : none
negated conditional → NO_COVERAGE

2.2
Location : getLineStartOffset
Killed by : none
changed conditional boundary → NO_COVERAGE

233

1.1
Location : getLineStartOffset
Killed by : none
changed conditional boundary → NO_COVERAGE

2.2
Location : getLineStartOffset
Killed by : none
negated conditional → NO_COVERAGE

234

1.1
Location : getLineStartOffset
Killed by : none
Replaced integer addition with subtraction → NO_COVERAGE

237

1.1
Location : getLineStartOffset
Killed by : none
replaced int return with 0 for com/jsql/view/swing/terminal/AbstractExploit::getLineStartOffset → NO_COVERAGE

245

1.1
Location : getIsEdited
Killed by : none
replaced return value with null for com/jsql/view/swing/terminal/AbstractExploit::getIsEdited → NO_COVERAGE

249

1.1
Location : getUuidShell
Killed by : none
replaced return value with null for com/jsql/view/swing/terminal/AbstractExploit::getUuidShell → NO_COVERAGE

253

1.1
Location : getUrlShell
Killed by : none
replaced return value with "" for com/jsql/view/swing/terminal/AbstractExploit::getUrlShell → NO_COVERAGE

257

1.1
Location : getPrompt
Killed by : none
replaced return value with "" for com/jsql/view/swing/terminal/AbstractExploit::getPrompt → NO_COVERAGE

261

1.1
Location : getLoginPassword
Killed by : none
replaced return value with null for com/jsql/view/swing/terminal/AbstractExploit::getLoginPassword → NO_COVERAGE

Active mutators

Tests examined


Report generated by PIT 1.19.1