Projects STRLCPY LoggerPlusPlus Commits 79134a2c
🤬
Revision indexing in progress... (symbol navigation in revisions will be accurate after indexed)
  • ■ ■ ■ ■ ■ ■
    src/main/java/com/nccgroup/loggerplusplus/logentry/LogEntry.java
    skipped 34 lines
    35 35   public transient IHttpRequestResponse requestResponse;
    36 36   public int tool;
    37 37   public String toolName;
    38  - public String host="";
     38 + public String hostname ="";
     39 + public String host = ""; //TODO better name?
    39 40   public String method="";
    40 41   public URL url;
    41  - public String relativeURL="";
    42 42   public boolean params=false;
    43 43   public Short status=-1;
    44 44   public boolean hasBodyParam=false;
    skipped 19 lines
    64 64   public boolean complete = false;
    65 65   public CookieJarStatus usesCookieJar = CookieJarStatus.NO;
    66 66   public String comment="";
    67  - public String[] regexAllReq = {"","","","",""};
    68  - public String[] regexAllResp = {"","","","",""};
     67 +// public String[] regexAllReq = {"","","","",""};
     68 +// public String[] regexAllResp = {"","","","",""};
    69 69   
    70 70   public ArrayList<UUID> matchingColorFilters;
    71 71   public int requestBodyOffset;
    skipped 5 lines
    77 77   public String responseHeaders;
    78 78   public String requestHeaders;
    79 79   
    80  - private boolean requestProcessed;
    81  - private boolean responseProcessed;
    82  - 
    83 80   public LogEntry(){
    84 81   this.identifier = UUID.randomUUID();
    85 82   this.matchingColorFilters = new ArrayList<UUID>();
    skipped 31 lines
    117 114   requestHeaders = StringUtils.join(lstFullRequestHeader, ", ");
    118 115   
    119 116   this.url = tempAnalyzedReq.getUrl();
    120  - this.relativeURL = this.url.getPath();
    121  - this.host = tempRequestResponseHttpService.getHost();
     117 + this.hostname = tempRequestResponseHttpService.getHost();
    122 118   this.protocol = tempRequestResponseHttpService.getProtocol();
    123 119   this.isSSL= this.protocol.equals("https");
    124 120   this.targetPort = tempRequestResponseHttpService.getPort();
     121 + 
     122 + boolean isDefaultPort = (this.protocol.equals("https") && this.targetPort == 443)
     123 + || (this.protocol.equals("http") && this.targetPort == 80);
     124 + 
     125 + this.host = this.protocol+"://"+this.hostname+(isDefaultPort ? "" : this.targetPort);
     126 + 
     127 + 
    125 128   this.method = tempAnalyzedReq.getMethod();
    126 129   try{
    127 130   // I don't want to delete special characters such as ; or : from the extension as it may really be part of the extension! (burp proxy log ignores them)
    skipped 30 lines
    158 161   boolean anyParamMatched = false;
    159 162   
    160 163   for(ICookie cookieItem : cookieJars){
    161  - if(cookieItem.getDomain().equals(this.host)){
     164 + if(cookieItem.getDomain().equals(this.hostname)){
    162 165   // now we want to see if any of these cookies have been set here!
    163 166   String currentCookieJarParam = cookieItem.getName()+"="+cookieItem.getValue()+";";
    164 167   if(this.sentCookies.contains(currentCookieJarParam)){
    skipped 69 lines
    234 237  // }
    235 238  // }
    236 239   
    237  - this.requestProcessed = true;
     240 +// this.requestProcessed = true;
    238 241   }
    239 242   
    240 243   public void addResponse(Date arrivalTime, IHttpRequestResponse requestResponse){
    skipped 97 lines
    338 341  // this.requestResponse = null;
    339 342  // }
    340 343   
    341  - this.responseProcessed = true;
     344 +// this.responseProcessed = true;
    342 345   this.complete = true;
    343 346   }
    344 347   
    skipped 112 lines
    457 460   case URL:
    458 461   return this.url;
    459 462   case PATH:
    460  - return this.relativeURL;
     463 + return this.url.getPath();
    461 464   case QUERY:
    462 465   return this.url.getQuery();
    463 466   case STATUS:
    skipped 1 lines
    465 468   case PROTOCOL:
    466 469   return this.protocol;
    467 470   case HOSTNAME:
    468  - return this.host;
     471 + return this.hostname;
    469 472   case HOST:
    470  - return this.protocol+"://"+this.host;
     473 + return this.host;
    471 474   case MIME_TYPE:
    472 475   return this.responseMimeType;
    473 476   case RESPONSE_LENGTH:
    skipped 135 lines
  • ■ ■ ■ ■ ■ ■
    src/main/java/com/nccgroup/loggerplusplus/logentry/LogManager.java
    skipped 344 lines
    345 345   return modelIndex;
    346 346   }
    347 347   
     348 + public void removeLogEntry(LogEntry logEntry){
     349 + synchronized (logEntries) {
     350 + int index = logEntries.indexOf(logEntry);
     351 + if (index > 0) {
     352 + logEntries.remove(logEntry);
     353 + for (LogEntryListener listener : logEntryListeners) {
     354 + listener.onRequestRemoved(index, logEntry);
     355 + }
     356 + }
     357 + }
     358 + }
     359 + 
    348 360   private EntryPendingResponse moveEntryToPendingResponse(LogEntry logEntry){
    349 361   EntryPendingResponse entryAwaitingResponse = new EntryPendingResponse(logEntry);
    350 362   pendingRequests.remove(logEntry.getIdentifier());
    skipped 113 lines
  • ■ ■ ■ ■ ■ ■
    src/main/java/com/nccgroup/loggerplusplus/logentry/logger/ElasticSearchLogger.java
    skipped 107 lines
    108 108   jsonBuilder().startObject()
    109 109   .field("protocol", logEntry.protocol)
    110 110   .field("method", logEntry.method)
    111  - .field("host", logEntry.host)
    112  - .field("path", logEntry.relativeURL)
     111 + .field("host", logEntry.hostname)
     112 + .field("path", logEntry.url.getPath())
    113 113   .field("requesttime", logEntry.requestTime.equals("NA") ? null : logEntry.requestTime)
    114 114   .field("responsetime", logEntry.responseTime.equals("NA") ? null : logEntry.responseTime)
    115 115   .field("responsedelay", logEntry.requestResponseDelay)
    skipped 89 lines
  • ■ ■ ■ ■ ■ ■
    src/main/java/com/nccgroup/loggerplusplus/logview/MultipleLogEntryMenu.java
     1 +package com.nccgroup.loggerplusplus.logview;
     2 + 
     3 +import com.nccgroup.loggerplusplus.LoggerPlusPlus;
     4 +import com.nccgroup.loggerplusplus.logentry.LogEntry;
     5 +import com.nccgroup.loggerplusplus.logview.logtable.LogTable;
     6 + 
     7 +import javax.swing.*;
     8 +import java.awt.datatransfer.Clipboard;
     9 +import java.awt.datatransfer.StringSelection;
     10 +import java.awt.event.ActionEvent;
     11 +import java.util.*;
     12 +import java.util.stream.Collectors;
     13 + 
     14 +/**
     15 + * Created by corey on 24/08/17.
     16 + */
     17 +public class MultipleLogEntryMenu extends JPopupMenu {
     18 + 
     19 + public MultipleLogEntryMenu(final LogTable logTable, final List<LogEntry> selectedEntries){
     20 + final boolean isPro = LoggerPlusPlus.callbacks.getBurpVersion()[0].equals("Burp Suite Professional");
     21 + 
     22 + this.add(new JMenuItem(selectedEntries.size() + " items"));
     23 + this.add(new Separator());
     24 + 
     25 + JMenuItem copySelectedDomains = new JMenu("Copy selected hostnames");
     26 + copySelectedDomains.add(new JMenuItem(new AbstractAction("All") {
     27 + @Override
     28 + public void actionPerformed(ActionEvent actionEvent) {
     29 + copySelected(selectedEntries, Scope.DOMAIN, false);
     30 + }
     31 + }));
     32 + copySelectedDomains.add(new JMenuItem(new AbstractAction("Unique") {
     33 + @Override
     34 + public void actionPerformed(ActionEvent actionEvent) {
     35 + copySelected(selectedEntries, Scope.DOMAIN, true);
     36 + }
     37 + }));
     38 + this.add(copySelectedDomains);
     39 + 
     40 + JMenuItem copySelectedPaths = new JMenu("Copy selected paths");
     41 + copySelectedPaths.add(new JMenuItem(new AbstractAction("All") {
     42 + @Override
     43 + public void actionPerformed(ActionEvent actionEvent) {
     44 + copySelected(selectedEntries, Scope.PATH, false);
     45 + }
     46 + }));
     47 + copySelectedPaths.add(new JMenuItem(new AbstractAction("Unique") {
     48 + @Override
     49 + public void actionPerformed(ActionEvent actionEvent) {
     50 + copySelected(selectedEntries, Scope.PATH, true);
     51 + }
     52 + }));
     53 + this.add(copySelectedPaths);
     54 + 
     55 + JMenuItem copySelectedUrls = new JMenu("Copy selected URLs");
     56 + copySelectedUrls.add(new JMenuItem(new AbstractAction("All") {
     57 + @Override
     58 + public void actionPerformed(ActionEvent actionEvent) {
     59 + copySelected(selectedEntries, Scope.URL, false);
     60 + }
     61 + }));
     62 + copySelectedUrls.add(new JMenuItem(new AbstractAction("Unique") {
     63 + @Override
     64 + public void actionPerformed(ActionEvent actionEvent) {
     65 + copySelected(selectedEntries, Scope.URL, true);
     66 + }
     67 + }));
     68 + this.add(copySelectedUrls);
     69 + 
     70 + this.add(new Separator());
     71 + 
     72 + JMenuItem spider = new JMenuItem(new AbstractAction("Spider selected " + selectedEntries.size() + " urls") {
     73 + @Override
     74 + public void actionPerformed(ActionEvent actionEvent) {
     75 + for (LogEntry entry : selectedEntries) {
     76 + LoggerPlusPlus.callbacks.sendToSpider(entry.url);
     77 + }
     78 + }
     79 + });
     80 + this.add(spider);
     81 + 
     82 + JMenuItem activeScan = new JMenuItem(new AbstractAction("Active scan selected " + selectedEntries.size() + " urls") {
     83 + @Override
     84 + public void actionPerformed(ActionEvent actionEvent) {
     85 + for (LogEntry entry : selectedEntries) {
     86 + LoggerPlusPlus.callbacks.doActiveScan(entry.hostname, entry.targetPort, entry.isSSL, entry.requestResponse.getRequest());
     87 + }
     88 + }
     89 + });
     90 + this.add(activeScan);
     91 + activeScan.setEnabled(isPro);
     92 + 
     93 + JMenuItem passiveScan = new JMenuItem(new AbstractAction("Passive scan selected " + selectedEntries.size() + " urls") {
     94 + @Override
     95 + public void actionPerformed(ActionEvent actionEvent) {
     96 + for (LogEntry entry : selectedEntries) {
     97 + if(entry.complete) { //Cannot scan entries without response
     98 + LoggerPlusPlus.callbacks.doPassiveScan(entry.hostname, entry.targetPort, entry.isSSL, entry.requestResponse.getRequest(), entry.requestResponse.getResponse());
     99 + }
     100 + }
     101 + }
     102 + });
     103 + passiveScan.setEnabled(isPro);
     104 + this.add(passiveScan);
     105 + 
     106 + this.add(new Separator());
     107 + 
     108 + JMenuItem sendToRepeater = new JMenuItem(new AbstractAction("Send " + selectedEntries.size() + " selected items to Repeater") {
     109 + @Override
     110 + public void actionPerformed(ActionEvent actionEvent) {
     111 + for (LogEntry entry : selectedEntries) {
     112 + LoggerPlusPlus.callbacks.sendToRepeater(entry.hostname, entry.targetPort, entry.isSSL, entry.requestResponse.getRequest(), "L++");
     113 + }
     114 + }
     115 + });
     116 + this.add(sendToRepeater);
     117 + 
     118 + JMenuItem sendToIntruder = new JMenuItem(new AbstractAction("Send " + selectedEntries.size() + " selected items to Intruder") {
     119 + @Override
     120 + public void actionPerformed(ActionEvent actionEvent) {
     121 + for (LogEntry entry : selectedEntries) {
     122 + LoggerPlusPlus.callbacks.sendToIntruder(entry.hostname, entry.targetPort, entry.isSSL, entry.requestResponse.getRequest());
     123 + }
     124 + }
     125 + });
     126 + this.add(sendToIntruder);
     127 + 
     128 + JMenu sendToComparer = new JMenu("Send " + selectedEntries.size() + " selected items to Comparer");
     129 + JMenuItem comparerRequest = new JMenuItem(new AbstractAction("Requests") {
     130 + @Override
     131 + public void actionPerformed(ActionEvent actionEvent) {
     132 + for (LogEntry entry : selectedEntries) {
     133 + LoggerPlusPlus.callbacks.sendToComparer(entry.requestResponse.getRequest());
     134 + }
     135 + }
     136 + });
     137 + sendToComparer.add(comparerRequest);
     138 + JMenuItem comparerResponse = new JMenuItem(new AbstractAction("Responses") {
     139 + @Override
     140 + public void actionPerformed(ActionEvent actionEvent) {
     141 + for (LogEntry entry : selectedEntries) {
     142 + if(entry.complete) { //Do not add entries without a response
     143 + LoggerPlusPlus.callbacks.sendToComparer(entry.requestResponse.getRequest());
     144 + }
     145 + }
     146 + }
     147 + });
     148 + sendToComparer.add(comparerResponse);
     149 + this.add(sendToComparer);
     150 + 
     151 + this.add(new Separator());
     152 + 
     153 + JMenuItem removeItem = new JMenuItem(new AbstractAction("Remove " + selectedEntries.size() + " selected items") {
     154 + @Override
     155 + public void actionPerformed(ActionEvent actionEvent) {
     156 + for (LogEntry selectedEntry : selectedEntries) {
     157 + LoggerPlusPlus.instance.getLogManager().removeLogEntry(selectedEntry);
     158 + }
     159 + 
     160 + }
     161 + });
     162 + this.add(removeItem);
     163 + }
     164 + 
     165 + enum Scope {URL, DOMAIN, PATH}
     166 + private void copySelected(List<LogEntry> items, Scope scope, boolean onlyUnique){
     167 + Clipboard clipboard = getToolkit().getSystemClipboard();
     168 + Collection<String> values;
     169 + if(onlyUnique) values = new LinkedHashSet<String>();
     170 + else values = new LinkedList<>();
     171 + for (LogEntry item : items) {
     172 + switch (scope){
     173 + case URL: values.add(String.valueOf(item.url)); break;
     174 + case PATH: values.add(item.url.getPath()); break;
     175 + case DOMAIN: values.add(item.hostname); break;
     176 + }
     177 + }
     178 + 
     179 + String result = values.stream().collect(Collectors.joining("\n"));
     180 + clipboard.setContents(new StringSelection(result), null);
     181 + }
     182 +}
     183 + 
  • ■ ■ ■ ■ ■ ■
    src/main/java/com/nccgroup/loggerplusplus/logview/LogEntryMenu.java src/main/java/com/nccgroup/loggerplusplus/logview/SingleLogEntryMenu.java
    skipped 20 lines
    21 21  /**
    22 22   * Created by corey on 24/08/17.
    23 23   */
    24  -public class LogEntryMenu extends JPopupMenu {
     24 +public class SingleLogEntryMenu extends JPopupMenu {
    25 25   
    26  - public LogEntryMenu(final LogTable logTable, final int modelRow, final int modelColumn){
    27  - final LogEntry entry = logTable.getModel().getRow(modelRow);
    28  - final LogEntryField selectedField = (logTable.getColumnModel().getModelColumn(modelColumn)).getIdentifier();
     26 + public SingleLogEntryMenu(final LogTable logTable, final LogEntry entry, final LogEntryField selectedField){
    29 27   final String columnName = selectedField.getFullLabel();
    30  - final Object columnValue = logTable.getModel().getValueAt(modelRow, modelColumn);
     28 + final Object columnValue = entry.getValueByKey(selectedField);
    31 29   final String columnValueString;
    32 30   
    33 31   if(columnValue != null){
    skipped 65 lines
    99 97   @Override
    100 98   public void actionPerformed(ActionEvent actionEvent) {
    101 99   try {
    102  - URL domainURL = new URL(entry.protocol, entry.host, entry.targetPort, "");
     100 + URL domainURL = new URL(entry.protocol, entry.hostname, entry.targetPort, "");
    103 101   LoggerPlusPlus.callbacks.includeInScope(domainURL);
    104 102   } catch (MalformedURLException e) {
    105 103   JOptionPane.showMessageDialog(scopeItem, "Could not build URL for scope entry. Sorry!", "Add to scope", JOptionPane.ERROR_MESSAGE);
    skipped 29 lines
    135 133   JMenuItem activeScan = new JMenuItem(new AbstractAction("Do an active scan") {
    136 134   @Override
    137 135   public void actionPerformed(ActionEvent actionEvent) {
    138  - LoggerPlusPlus.callbacks.doActiveScan(entry.host, entry.targetPort, entry.isSSL, entry.requestResponse.getRequest());
     136 + LoggerPlusPlus.callbacks.doActiveScan(entry.hostname, entry.targetPort, entry.isSSL, entry.requestResponse.getRequest());
    139 137   }
    140 138   });
    141 139   this.add(activeScan);
    skipped 2 lines
    144 142   JMenuItem passiveScan = new JMenuItem(new AbstractAction("Do a passive scan") {
    145 143   @Override
    146 144   public void actionPerformed(ActionEvent actionEvent) {
    147  - LoggerPlusPlus.callbacks.doPassiveScan(entry.host, entry.targetPort, entry.isSSL, entry.requestResponse.getRequest(), entry.requestResponse.getResponse());
     145 + LoggerPlusPlus.callbacks.doPassiveScan(entry.hostname, entry.targetPort, entry.isSSL, entry.requestResponse.getRequest(), entry.requestResponse.getResponse());
    148 146   }
    149 147   });
    150 148   passiveScan.setEnabled(entry.complete && isPro);
    skipped 4 lines
    155 153   JMenuItem sendToRepeater = new JMenuItem(new AbstractAction("Send to Repeater") {
    156 154   @Override
    157 155   public void actionPerformed(ActionEvent actionEvent) {
    158  - LoggerPlusPlus.callbacks.sendToRepeater(entry.host, entry.targetPort, entry.isSSL, entry.requestResponse.getRequest(), "L++");
     156 + LoggerPlusPlus.callbacks.sendToRepeater(entry.hostname, entry.targetPort, entry.isSSL, entry.requestResponse.getRequest(), "L++");
    159 157   }
    160 158   });
    161 159   this.add(sendToRepeater);
    skipped 1 lines
    163 161   JMenuItem sendToIntruder = new JMenuItem(new AbstractAction("Send to Intruder") {
    164 162   @Override
    165 163   public void actionPerformed(ActionEvent actionEvent) {
    166  - LoggerPlusPlus.callbacks.sendToIntruder(entry.host, entry.targetPort, entry.isSSL, entry.requestResponse.getRequest());
     164 + LoggerPlusPlus.callbacks.sendToIntruder(entry.hostname, entry.targetPort, entry.isSSL, entry.requestResponse.getRequest());
    167 165   }
    168 166   });
    169 167   this.add(sendToIntruder);
    skipped 20 lines
    190 188   JMenuItem removeItem = new JMenuItem(new AbstractAction("Remove Item") {
    191 189   @Override
    192 190   public void actionPerformed(ActionEvent actionEvent) {
    193  - logTable.getModel().removeRow(modelRow);
     191 + LoggerPlusPlus.instance.getLogManager().removeLogEntry(entry);
    194 192   }
    195 193   });
    196 194   this.add(removeItem);
    skipped 3 lines
  • ■ ■ ■ ■ ■ ■
    src/main/java/com/nccgroup/loggerplusplus/logview/logtable/LogTable.java
    skipped 10 lines
    11 11  import com.nccgroup.loggerplusplus.filter.logfilter.LogFilterListener;
    12 12  import com.nccgroup.loggerplusplus.filter.parser.ParseException;
    13 13  import com.nccgroup.loggerplusplus.logentry.LogEntry;
     14 +import com.nccgroup.loggerplusplus.logentry.LogEntryField;
    14 15  import com.nccgroup.loggerplusplus.logentry.LogEntryListener;
    15  -import com.nccgroup.loggerplusplus.logview.LogEntryMenu;
     16 +import com.nccgroup.loggerplusplus.logview.MultipleLogEntryMenu;
     17 +import com.nccgroup.loggerplusplus.logview.SingleLogEntryMenu;
    16 18  import com.nccgroup.loggerplusplus.logview.LogTableFilterStatusListener;
    17 19  import com.nccgroup.loggerplusplus.logview.RequestViewerController;
    18 20  import com.nccgroup.loggerplusplus.userinterface.LogTableModel;
    19 21  import com.nccgroup.loggerplusplus.userinterface.renderer.BooleanRenderer;
    20 22  import com.nccgroup.loggerplusplus.util.Globals;
    21  -import org.jdesktop.swingx.JXTable;
    22 23   
    23 24  import javax.swing.*;
    24 25  import javax.swing.event.RowSorterEvent;
    skipped 4 lines
    29 30  import java.awt.event.MouseEvent;
    30 31  import java.util.List;
    31 32  import java.util.*;
     33 +import java.util.stream.Collectors;
     34 +import java.util.stream.IntStream;
    32 35   
    33 36  public class LogTable extends JTable implements LogFilterListener, ColorFilterListener, LogEntryListener
    34 37  {
    skipped 6 lines
    41 44   filterStatusListeners = new ArrayList<>();
    42 45   this.setTableHeader(new TableHeader(getColumnModel(),this)); // This was used to create tool tips
    43 46   this.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); // to have horizontal scroll bar
    44  - this.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); // selecting one row at a time
    45 47   this.setRowHeight(20); // As we are not using Burp customised UI, we have to define the row height to make it more pretty
    46 48   this.setDefaultRenderer(Boolean.class, new BooleanRenderer()); //Fix grey checkbox background
    47 49   ((JComponent) this.getDefaultRenderer(Boolean.class)).setOpaque(true); // to remove the white background of the checkboxes!
    skipped 35 lines
    83 85   }
    84 86   }
    85 87   });
    86  - //TODO Multi selection + relevant context menu changes
    87  - this.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
     88 + 
     89 + this.getSelectionModel().setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
    88 90   
    89 91   registerListeners();
    90 92   }
    skipped 23 lines
    114 116   
    115 117   Component c = super.prepareRenderer(renderer, row, column);
    116 118   
    117  - if(this.getSelectedRow() == row){
     119 + IntStream selectedRows = IntStream.of(this.getSelectedRows());
     120 + 
     121 + if(selectedRows.anyMatch(i -> i == row)){
    118 122   c.setBackground(this.getSelectionBackground());
    119 123   c.setForeground(this.getSelectionForeground());
    120 124   }else {
    skipped 42 lines
    163 167   if ( SwingUtilities.isRightMouseButton( e )){
    164 168   Point p = e.getPoint();
    165 169   int rowAtPoint = rowAtPoint(p);
    166  - if(rowAtPoint > -1){
     170 + if(rowAtPoint == -1) return;
     171 + 
     172 + if(IntStream.of(LogTable.this.getSelectedRows()).noneMatch(i -> i == rowAtPoint)){
     173 + //We right clicked an unselected row. Set it as the selected row and update our selected
    167 174   setRowSelectionInterval(rowAtPoint, rowAtPoint);
    168 175   }
    169 176   
    170  - final int row = convertRowIndexToModel(rowAtPoint);
    171  - final int modelCol = convertColumnIndexToModel(columnAtPoint(p));
     177 + LogTableModel model = LogTable.this.getModel();
     178 + if(LogTable.this.getSelectedRowCount() == 1){
     179 + LogEntry logEntry = model.getRow(convertRowIndexToModel(rowAtPoint));
     180 + LogEntryField logField = LogTable.this.getColumnModel()
     181 + .getModelColumn(convertColumnIndexToModel(columnAtPoint(p))).getIdentifier();
    172 182   
    173  - if (e.isPopupTrigger() && e.getComponent() instanceof JTable ) {
    174  - new LogEntryMenu(LogTable.this, row, modelCol).show(e.getComponent(), e.getX(), e.getY());
     183 + if (e.isPopupTrigger() && e.getComponent() instanceof JTable ) {
     184 + new SingleLogEntryMenu(LogTable.this, logEntry, logField).show(e.getComponent(), e.getX(), e.getY());
     185 + }
     186 + }else{
     187 + List<LogEntry> selectedEntries = IntStream.of(LogTable.this.getSelectedRows())
     188 + .mapToObj(selectedRow -> model.getRow(convertRowIndexToModel(selectedRow)))
     189 + .collect(Collectors.toList());
     190 + 
     191 + if (e.isPopupTrigger() && e.getComponent() instanceof JTable ) {
     192 + new MultipleLogEntryMenu(LogTable.this, selectedEntries).show(e.getComponent(), e.getX(), e.getY());
     193 + }
    175 194   }
    176 195   }
    177 196   }
    skipped 151 lines
Please wait...
Page is in error, reload to recover