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

Mutations

92

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

99

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

100

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

101

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

102

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

104

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

105

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

107

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

110

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

111

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

112

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

114

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

115

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

131

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

134

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

135

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

136

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

137

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

139

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

140

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

150

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

161

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 javax/swing/text/StyleConstants::setUnderline → 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

168

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

169

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

170

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

181

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

182

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

183

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

196

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

216

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

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

218

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

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

219

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

222

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

234

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

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

236

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

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

237

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

240

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

248

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

252

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

256

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

260

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

264

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