From fd454bbfab5c10561adc2f15c84a25742e34fcd4 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Wed, 30 Sep 2020 17:57:27 -0400 Subject: [PATCH 01/81] 6773 initial commit of code for Domain details viewers --- .../discovery/search/DiscoveryEventUtils.java | 43 +++++- .../ui/AbstractArtifactDetailsPanel.java | 26 ++++ .../discovery/ui/ArtifactsListPanel.form | 31 ++++ .../discovery/ui/ArtifactsListPanel.java | 135 ++++++++++++++++++ .../autopsy/discovery/ui/ArtifactsWorker.java | 72 ++++++++++ .../autopsy/discovery/ui/Bundle.properties | 4 +- .../discovery/ui/Bundle.properties-MERGED | 2 + .../discovery/ui/CookieDetailsPanel.form | 66 +++++++++ .../discovery/ui/CookieDetailsPanel.java | 119 +++++++++++++++ .../discovery/ui/DiscoveryTopComponent.form | 3 +- .../discovery/ui/DiscoveryTopComponent.java | 25 ++-- .../discovery/ui/DomainArtifactsTabPanel.form | 28 ++++ .../discovery/ui/DomainArtifactsTabPanel.java | 112 +++++++++++++++ .../discovery/ui/DomainDetailsPanel.form | 17 +++ .../discovery/ui/DomainDetailsPanel.java | 61 ++++++++ ...etailsPanel.form => FileDetailsPanel.form} | 4 +- ...etailsPanel.java => FileDetailsPanel.java} | 6 +- 17 files changed, 735 insertions(+), 19 deletions(-) create mode 100644 Core/src/org/sleuthkit/autopsy/discovery/ui/AbstractArtifactDetailsPanel.java create mode 100644 Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.form create mode 100644 Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java create mode 100644 Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsWorker.java create mode 100644 Core/src/org/sleuthkit/autopsy/discovery/ui/CookieDetailsPanel.form create mode 100644 Core/src/org/sleuthkit/autopsy/discovery/ui/CookieDetailsPanel.java create mode 100644 Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.form create mode 100644 Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.java create mode 100644 Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.form create mode 100644 Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.java rename Core/src/org/sleuthkit/autopsy/discovery/ui/{DetailsPanel.form => FileDetailsPanel.form} (96%) rename Core/src/org/sleuthkit/autopsy/discovery/ui/{DetailsPanel.java => FileDetailsPanel.java} (98%) diff --git a/Core/src/org/sleuthkit/autopsy/discovery/search/DiscoveryEventUtils.java b/Core/src/org/sleuthkit/autopsy/discovery/search/DiscoveryEventUtils.java index e224c02d51..18dd83dfe1 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/search/DiscoveryEventUtils.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/search/DiscoveryEventUtils.java @@ -19,12 +19,14 @@ package org.sleuthkit.autopsy.discovery.search; import com.google.common.eventbus.EventBus; +import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import org.sleuthkit.autopsy.discovery.search.DiscoveryKeyUtils.GroupKey; import org.sleuthkit.autopsy.discovery.search.SearchData.Type; import org.sleuthkit.datamodel.AbstractFile; +import org.sleuthkit.datamodel.BlackboardArtifact; /** * Class to handle event bus and events for discovery tool. @@ -88,13 +90,13 @@ public final class DiscoveryEventUtils { //no arg constructor } } - + /** - * Event to signal that any background tasks currently running should - * be cancelled. + * Event to signal that any background tasks currently running should be + * cancelled. */ public static final class CancelBackgroundTasksEvent { - + public CancelBackgroundTasksEvent() { //no-arg constructor } @@ -203,6 +205,39 @@ public final class DiscoveryEventUtils { } + /** + * Event to signal the completion of a search being performed. + */ + public static final class ArtifactListRetrievedEvent { + + private final List listOfArtifacts = new ArrayList<>(); + private final BlackboardArtifact.ARTIFACT_TYPE artifactType; + + /** + * + * @param listOfArtifacts + */ + public ArtifactListRetrievedEvent(BlackboardArtifact.ARTIFACT_TYPE artifactType, List listOfArtifacts) { + if (listOfArtifacts != null) { + this.listOfArtifacts.addAll(listOfArtifacts); + } + this.artifactType = artifactType; + } + + public List getListOfArtifacts() { + return Collections.unmodifiableList(listOfArtifacts); + } + + /** + * Get the type of BlackboardArtifact type of which exist in the list. + * + * @return The BlackboardArtifact type of which exist in the list. + */ + public BlackboardArtifact.ARTIFACT_TYPE getArtifactType() { + return artifactType; + } + } + /** * Event to signal the completion of page retrieval and include the page * contents. diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/AbstractArtifactDetailsPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/AbstractArtifactDetailsPanel.java new file mode 100644 index 0000000000..f1feb975a5 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/AbstractArtifactDetailsPanel.java @@ -0,0 +1,26 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.sleuthkit.autopsy.discovery.ui; + +import javax.swing.JPanel; +import org.sleuthkit.datamodel.BlackboardArtifact; + +/** + * + * @author wschaefer + */ +abstract class AbstractArtifactDetailsPanel extends JPanel { + + private static final long serialVersionUID = 1L; + + /** + * Called to display the contents of the given artifact. + * + * @param artifact the artifact to display. + */ + abstract void setArtifact(BlackboardArtifact artifact); + +} diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.form b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.form new file mode 100644 index 0000000000..a5a6f66c1c --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.form @@ -0,0 +1,31 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java new file mode 100644 index 0000000000..4ae027cdc9 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java @@ -0,0 +1,135 @@ +/* + * Autopsy + * + * Copyright 2020 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.discovery.ui; + +import java.util.ArrayList; +import java.util.List; +import javax.swing.event.ListSelectionListener; +import javax.swing.table.AbstractTableModel; +import org.openide.util.NbBundle; +import org.sleuthkit.datamodel.BlackboardArtifact; + +/** + * + * @author wschaefer + */ +public class ArtifactsListPanel extends javax.swing.JScrollPane { + + private static final long serialVersionUID = 1L; + + /** + * Creates new form ArtifactsListPanel + */ + public ArtifactsListPanel() { + initComponents(); + } + + public void addSelectionListener(ListSelectionListener listener) { + jTable1.getSelectionModel().addListSelectionListener(listener); + } + + public BlackboardArtifact getSelectedArtifact() { + return ((DomainArtifactTableModel) jTable1.getSelectionModel()).getArtifactByRow(jTable1.getSelectionModel().getLeadSelectionIndex()); + } + + public boolean isEmpty() { + return false; + } + + public void addArtifacts(List artifactList) { + jTable1.setModel(new DomainArtifactTableModel(artifactList)); + } + + public void clearArtifacts() { + jTable1.setModel(new DomainArtifactTableModel()); + } + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + // //GEN-BEGIN:initComponents + private void initComponents() { + + jTable1 = new javax.swing.JTable(); + + setLayout(new java.awt.BorderLayout()); + + jTable1.setModel(new DomainArtifactTableModel()); + add(jTable1, java.awt.BorderLayout.PAGE_START); + }// //GEN-END:initComponents + private class DomainArtifactTableModel extends AbstractTableModel { + + private static final long serialVersionUID = 1L; + private final List artifactList = new ArrayList<>(); + + DomainArtifactTableModel(){ + //No arg constructor to create empty model + } + + DomainArtifactTableModel(List artifactList) { + this.artifactList.addAll(artifactList); + } + + @Override + public int getRowCount() { + return artifactList.size(); + } + + @Override + public int getColumnCount() { + return 2; + } + + public BlackboardArtifact getArtifactByRow(int rowIndex) { + return artifactList.get(rowIndex); + } + + @Override + public Object getValueAt(int rowIndex, int columnIndex) { + switch (columnIndex) { + case 0: + return getArtifactByRow(rowIndex); + case 1: + return getArtifactByRow(rowIndex); + default: + return getArtifactByRow(rowIndex); + } + } + + @NbBundle.Messages({"ArtifactsListPanel.urlColumn.name=URL", + "ArtifactsListPanel.dateColumn.name=Date/Time"}) + @Override + public String getColumnName(int column) { + switch (column) { + case 0: + return Bundle.ArtifactsListPanel_urlColumn_name(); + case 1: + return Bundle.ArtifactsListPanel_dateColumn_name(); + default: + return ""; + } + } + } + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JTable jTable1; + // End of variables declaration//GEN-END:variables +} diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsWorker.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsWorker.java new file mode 100644 index 0000000000..d07499583c --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsWorker.java @@ -0,0 +1,72 @@ +/* + * Autopsy + * + * Copyright 2019-2020 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.discovery.ui; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.ExecutionException; +import java.util.logging.Level; +import static javax.swing.JComponent.TOOL_TIP_TEXT_KEY; +import javax.swing.SwingWorker; +import org.apache.commons.lang3.StringUtils; +import org.openide.util.Exceptions; +import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoException; +import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository; +import org.sleuthkit.autopsy.discovery.search.DiscoveryEventUtils; +import org.sleuthkit.autopsy.discovery.search.DomainSearch; +import org.sleuthkit.autopsy.discovery.search.DomainSearchArtifactsRequest; +import org.sleuthkit.datamodel.BlackboardArtifact; + +/** + * + * @author wschaefer + */ +public class ArtifactsWorker extends SwingWorker, Void> { + + private final BlackboardArtifact.ARTIFACT_TYPE artifactType = null; + private final static Logger logger = Logger.getLogger(ArtifactsWorker.class.getName()); + private final String domain = null; + + @Override + protected List doInBackground() throws Exception { + if (artifactType != null && !StringUtils.isBlank(domain)) { + DomainSearch domainSearch = new DomainSearch(); + return domainSearch.getArtifacts(new DomainSearchArtifactsRequest(Case.getCurrentCase().getSleuthkitCase(), domain, artifactType)); + } + return new ArrayList<>(); + } + + @Override + protected void done() { + List listOfArtifacts = new ArrayList<>(); + if (!isCancelled()) { + try { + listOfArtifacts.addAll(get()); + } catch (InterruptedException | ExecutionException ex) { + logger.log(Level.SEVERE, "Exception while trying to get list of artifacts for Domain details for artifact type: " + + artifactType.getDisplayName() + " and domain: " + domain, ex); + } + } + DiscoveryEventUtils.getDiscoveryEventBus().post(new DiscoveryEventUtils.ArtifactListRetrievedEvent(artifactType, listOfArtifacts)); + } + +} diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/Bundle.properties b/Core/src/org/sleuthkit/autopsy/discovery/ui/Bundle.properties index 5fc4ff56e6..851045c71a 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/Bundle.properties @@ -51,10 +51,12 @@ HashSetFilterPanel.hashSetCheckbox.text=Hash Set: PastOccurrencesFilterPanel.pastOccurrencesCheckbox.text=Past Occurrences: DocumentFilterPanel.documentsFiltersSplitPane.border.title=Step 2: Filter which documents to show ObjectDetectedFilterPanel.text=Object Detected: -DetailsPanel.instancesList.border.title=Instances DateFilterPanel.mostRecentRadioButton.text=Only last: DateFilterPanel.dateFilterCheckBox.text=Date Filter: DomainSummaryPanel.activityLabel.text= DomainSummaryPanel.pagesLabel.text= DomainSummaryPanel.filesDownloadedLabel.text= DomainSummaryPanel.totalVisitsLabel.text= +FileDetailsPanel.instancesList.border.title=Instances +CookieDetailsPanel.jLabel1.text=Artifact: +CookieDetailsPanel.jLabel2.text= diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/discovery/ui/Bundle.properties-MERGED index 7c2c5e6757..a35e8113e2 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/Bundle.properties-MERGED @@ -133,6 +133,8 @@ DomainSummaryPanel.activityLabel.text= DomainSummaryPanel.pagesLabel.text= DomainSummaryPanel.filesDownloadedLabel.text= DomainSummaryPanel.totalVisitsLabel.text= +CookiesDetailsPanel.jLabel1.text=Artifact: +CookiesDetailsPanel.jLabel2.text= VideoThumbnailPanel.bytes.text=bytes VideoThumbnailPanel.deleted.text=All instances of file are deleted. VideoThumbnailPanel.gigaBytes.text=GB diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/CookieDetailsPanel.form b/Core/src/org/sleuthkit/autopsy/discovery/ui/CookieDetailsPanel.form new file mode 100644 index 0000000000..037c904fe5 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/CookieDetailsPanel.form @@ -0,0 +1,66 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/CookieDetailsPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/CookieDetailsPanel.java new file mode 100644 index 0000000000..cf382d1795 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/CookieDetailsPanel.java @@ -0,0 +1,119 @@ +/* + * Autopsy + * + * Copyright 2020 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.discovery.ui; + +import java.awt.Component; +import org.openide.util.lookup.ServiceProvider; +import org.sleuthkit.autopsy.contentviewers.artifactviewers.ArtifactContentViewer; +import org.sleuthkit.datamodel.BlackboardArtifact; + +/** + * + * @author wschaefer + */ +@ServiceProvider(service = ArtifactContentViewer.class) +public class CookieDetailsPanel extends AbstractArtifactDetailsPanel implements ArtifactContentViewer { + + private static final long serialVersionUID = 1L; + private BlackboardArtifact artifact; + + /** + * Creates new form CookiesDetailsPanel + */ + public CookieDetailsPanel() { + initComponents(); + } + + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + jLabel1 = new javax.swing.JLabel(); + jLabel2 = new javax.swing.JLabel(); + + org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(CookieDetailsPanel.class, "CookieDetailsPanel.jLabel1.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(jLabel2, org.openide.util.NbBundle.getMessage(CookieDetailsPanel.class, "CookieDetailsPanel.jLabel2.text")); // NOI18N + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addGap(120, 120, 120) + .addComponent(jLabel1) + .addContainerGap(234, Short.MAX_VALUE)) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addGap(0, 0, Short.MAX_VALUE) + .addComponent(jLabel2) + .addGap(0, 0, Short.MAX_VALUE))) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addContainerGap(143, Short.MAX_VALUE) + .addComponent(jLabel1) + .addGap(141, 141, 141)) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addGap(0, 0, Short.MAX_VALUE) + .addComponent(jLabel2) + .addGap(0, 0, Short.MAX_VALUE))) + ); + }// //GEN-END:initComponents + + @Override + public void setArtifact(BlackboardArtifact artifact) { + this.artifact = artifact; + if (this.artifact == null) { + resetComponent(); + return; + } + jLabel2.setText(artifact.getDisplayName()); + + } + + private void resetComponent() { + jLabel2.setText(""); + } + + @Override + public Component getComponent() { + return this; + } + + @Override + public boolean isSupported(BlackboardArtifact artifact) { + return (artifact != null) + && (artifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_COOKIE.getTypeID()); + } + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JLabel jLabel1; + private javax.swing.JLabel jLabel2; + // End of variables declaration//GEN-END:variables +} diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/DiscoveryTopComponent.form b/Core/src/org/sleuthkit/autopsy/discovery/ui/DiscoveryTopComponent.form index 54630599ec..2c828a28bc 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/DiscoveryTopComponent.form +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/DiscoveryTopComponent.form @@ -1,6 +1,6 @@ -
+ @@ -50,6 +50,7 @@ + diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/DiscoveryTopComponent.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/DiscoveryTopComponent.java index 03a271dcdd..628b706e11 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/DiscoveryTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/DiscoveryTopComponent.java @@ -55,7 +55,6 @@ public final class DiscoveryTopComponent extends TopComponent { private static final int ANIMATION_INCREMENT = 30; private volatile static int resultsAreaSize = 250; private final GroupListPanel groupListPanel; - private final DetailsPanel detailsPanel; private final ResultsPanel resultsPanel; private Type searchType; private int dividerLocation = -1; @@ -70,10 +69,7 @@ public final class DiscoveryTopComponent extends TopComponent { setName(Bundle.DiscoveryTopComponent_name()); groupListPanel = new GroupListPanel(); resultsPanel = new ResultsPanel(); - detailsPanel = new DetailsPanel(); mainSplitPane.setLeftComponent(groupListPanel); - rightSplitPane.setTopComponent(resultsPanel); - rightSplitPane.setBottomComponent(detailsPanel); //set color of divider rightSplitPane.setUI(new BasicSplitPaneUI() { @Override @@ -141,7 +137,6 @@ public final class DiscoveryTopComponent extends TopComponent { DiscoveryEventUtils.getDiscoveryEventBus().register(this); DiscoveryEventUtils.getDiscoveryEventBus().register(resultsPanel); DiscoveryEventUtils.getDiscoveryEventBus().register(groupListPanel); - DiscoveryEventUtils.getDiscoveryEventBus().register(detailsPanel); } @Override @@ -152,7 +147,10 @@ public final class DiscoveryTopComponent extends TopComponent { DiscoveryEventUtils.getDiscoveryEventBus().unregister(this); DiscoveryEventUtils.getDiscoveryEventBus().unregister(groupListPanel); DiscoveryEventUtils.getDiscoveryEventBus().unregister(resultsPanel); - DiscoveryEventUtils.getDiscoveryEventBus().unregister(detailsPanel); + DiscoveryEventUtils.getDiscoveryEventBus().unregister(rightSplitPane.getBottomComponent()); + setDetailsVisible(false); + rightSplitPane.setBottomComponent(null); + super.componentClosed(); } @@ -183,6 +181,9 @@ public final class DiscoveryTopComponent extends TopComponent { rightSplitPane.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT); rightSplitPane.setResizeWeight(1.0); rightSplitPane.setPreferredSize(new java.awt.Dimension(800, 700)); + + setDetailsVisible(false); + mainSplitPane.setRightComponent(rightSplitPane); add(mainSplitPane, java.awt.BorderLayout.CENTER); @@ -293,8 +294,11 @@ public final class DiscoveryTopComponent extends TopComponent { progressMessageTextArea.setForeground(Color.red); searchType = searchStartedEvent.getType(); progressMessageTextArea.setText(Bundle.DiscoveryTopComponent_searchInProgress_text(searchType.name())); - rightSplitPane.getComponent(1).setVisible(searchStartedEvent.getType() != DOMAIN); - rightSplitPane.getComponent(2).setVisible(searchStartedEvent.getType() != DOMAIN); + } + + private void setDetailsVisible(boolean isVisible) { + rightSplitPane.getComponent(1).setVisible(isVisible); + rightSplitPane.getComponent(2).setVisible(isVisible); } /** @@ -319,7 +323,12 @@ public final class DiscoveryTopComponent extends TopComponent { if (!searchCompleteEvent.getFilters().isEmpty()) { descriptionText += Bundle.DiscoveryTopComponent_additionalFilters_text(); } + rightSplitPane.setBottomComponent(new DomainDetailsPanel()); + } else { + rightSplitPane.setBottomComponent(new FileDetailsPanel()); } + setDetailsVisible(true); + DiscoveryEventUtils.getDiscoveryEventBus().register(rightSplitPane.getBottomComponent()); descriptionText += searchCompleteEvent.getFilters().stream().map(AbstractFilter::getDesc).collect(Collectors.joining("; ")); progressMessageTextArea.setText(Bundle.DiscoveryTopComponent_searchComplete_text(descriptionText)); progressMessageTextArea.setCaretPosition(0); diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.form b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.form new file mode 100644 index 0000000000..4f9abb50dc --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.form @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.java new file mode 100644 index 0000000000..c9c1282329 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.java @@ -0,0 +1,112 @@ +/* + * Autopsy + * + * Copyright 2020 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.discovery.ui; + +import com.google.common.eventbus.Subscribe; +import javax.swing.JPanel; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; +import org.sleuthkit.autopsy.contentviewers.artifactviewers.ArtifactContentViewer; +import org.sleuthkit.autopsy.discovery.search.DiscoveryEventUtils; +import org.sleuthkit.datamodel.BlackboardArtifact; + +/** + * + * @author wschaefer + */ +public final class DomainArtifactsTabPanel extends javax.swing.JSplitPane { + + private static final long serialVersionUID = 1L; + private final ArtifactsListPanel listPanel = new ArtifactsListPanel(); + private final BlackboardArtifact.ARTIFACT_TYPE artifactType; + private AbstractArtifactDetailsPanel rightPanel = null; + + /** + * Creates new form CookiesPanel + */ + public DomainArtifactsTabPanel(BlackboardArtifact.ARTIFACT_TYPE artifactType) { + initComponents(); + this.artifactType = artifactType; + this.setLeftComponent(listPanel); + setRightComponent(); + update(); + } + + private void setRightComponent() { + + switch (artifactType) { + case TSK_WEB_COOKIE: + rightPanel = new CookieDetailsPanel(); + break; + default: + break; + } + if (rightPanel == null) { + getComponent(1).setVisible(false); + getComponent(2).setVisible(false); + } else { + this.setRightComponent(rightPanel); + getComponent(1).setVisible(true); + getComponent(2).setVisible(true); + } + } + + private void update() { + this.setEnabled(!this.listPanel.isEmpty()); + } + + @Subscribe + void handleArtifactListRetrievedEvent(DiscoveryEventUtils.ArtifactListRetrievedEvent artifactListEvent) { + if (artifactType == artifactListEvent.getArtifactType()) { + listPanel.addArtifacts(artifactListEvent.getListOfArtifacts()); + listPanel.addSelectionListener(new ListSelectionListener() { + public void valueChanged(ListSelectionEvent event) { + if (!event.getValueIsAdjusting()){ + rightPanel.setArtifact(listPanel.getSelectedArtifact()); + } + } + }); + } + } + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 400, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 300, Short.MAX_VALUE) + ); + }// //GEN-END:initComponents + + + // Variables declaration - do not modify//GEN-BEGIN:variables + // End of variables declaration//GEN-END:variables +} diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.form b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.form new file mode 100644 index 0000000000..b6bc3eb975 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.form @@ -0,0 +1,17 @@ + + +
+ + + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.java new file mode 100644 index 0000000000..2a6fdfc4b0 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.java @@ -0,0 +1,61 @@ +/* + * Autopsy + * + * Copyright 2020 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.discovery.ui; + +import org.sleuthkit.datamodel.BlackboardArtifact; + +/** + * + * @author wschaefer + */ +final class DomainDetailsPanel extends javax.swing.JTabbedPane { + + private static final long serialVersionUID = 1L; + + /** + * Creates new form ArtifactDetailsPanel + */ + DomainDetailsPanel() { + initComponents(); + addArtifactTabs(); + } + + private void addArtifactTabs() { + DomainArtifactsTabPanel cookiesPanel = new DomainArtifactsTabPanel(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_COOKIE); + cookiesPanel.setRightComponent(new CookieDetailsPanel()); + add(cookiesPanel); + } + + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + setLayout(new java.awt.BorderLayout()); + }// //GEN-END:initComponents + + + // Variables declaration - do not modify//GEN-BEGIN:variables + // End of variables declaration//GEN-END:variables +} diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/DetailsPanel.form b/Core/src/org/sleuthkit/autopsy/discovery/ui/FileDetailsPanel.form similarity index 96% rename from Core/src/org/sleuthkit/autopsy/discovery/ui/DetailsPanel.form rename to Core/src/org/sleuthkit/autopsy/discovery/ui/FileDetailsPanel.form index bd3d8c5af9..1cac146780 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/DetailsPanel.form +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/FileDetailsPanel.form @@ -105,8 +105,8 @@ - - + + diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/DetailsPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/FileDetailsPanel.java similarity index 98% rename from Core/src/org/sleuthkit/autopsy/discovery/ui/DetailsPanel.java rename to Core/src/org/sleuthkit/autopsy/discovery/ui/FileDetailsPanel.java index e302669278..b38ff7aaa4 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/DetailsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/FileDetailsPanel.java @@ -48,7 +48,7 @@ import org.sleuthkit.datamodel.TskCoreException; /** * Panel to display the details of the selected result. */ -final class DetailsPanel extends javax.swing.JPanel { +final class FileDetailsPanel extends javax.swing.JPanel { private static final long serialVersionUID = 1L; @@ -59,7 +59,7 @@ final class DetailsPanel extends javax.swing.JPanel { /** * Creates new form DetailsPanel. */ - DetailsPanel() { + FileDetailsPanel() { initComponents(); dataContentPanel = DataContentPanel.createInstance(); detailsSplitPane.setBottomComponent(dataContentPanel); @@ -186,7 +186,7 @@ final class DetailsPanel extends javax.swing.JPanel { instancesScrollPane.setPreferredSize(new java.awt.Dimension(775, 60)); - instancesList.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(DetailsPanel.class, "DetailsPanel.instancesList.border.title"))); // NOI18N + instancesList.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(FileDetailsPanel.class, "FileDetailsPanel.instancesList.border.title"))); // NOI18N instancesList.setModel(instancesListModel); instancesList.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION); instancesList.setCellRenderer(new InstancesCellRenderer()); From dd87146065e21f26b92ef15632776f34b53f0aa6 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Thu, 22 Oct 2020 18:26:17 -0400 Subject: [PATCH 02/81] 6773 web history working --- .../discovery/search/DiscoveryEventUtils.java | 21 ++ .../ui/AbstractArtifactDetailsPanel.java | 27 ++- .../discovery/ui/ArtifactsListPanel.form | 23 +- .../discovery/ui/ArtifactsListPanel.java | 99 ++++++--- .../autopsy/discovery/ui/ArtifactsWorker.java | 20 +- .../discovery/ui/Bundle.properties-MERGED | 8 +- .../discovery/ui/CookieDetailsPanel.form | 66 ------ .../discovery/ui/CookieDetailsPanel.java | 119 ---------- .../discovery/ui/DiscoveryTopComponent.java | 25 +-- .../discovery/ui/DomainArtifactsTabPanel.form | 26 +-- .../discovery/ui/DomainArtifactsTabPanel.java | 106 +++++---- .../discovery/ui/DomainDetailsPanel.form | 15 ++ .../discovery/ui/DomainDetailsPanel.java | 100 ++++++++- .../discovery/ui/DomainSummaryViewer.form | 2 - .../discovery/ui/DomainSummaryViewer.java | 31 ++- .../autopsy/discovery/ui/ResultsPanel.java | 19 +- .../discovery/ui/WebHistoryDetailsPanel.form | 28 +++ .../discovery/ui/WebHistoryDetailsPanel.java | 210 ++++++++++++++++++ 18 files changed, 621 insertions(+), 324 deletions(-) delete mode 100644 Core/src/org/sleuthkit/autopsy/discovery/ui/CookieDetailsPanel.form delete mode 100644 Core/src/org/sleuthkit/autopsy/discovery/ui/CookieDetailsPanel.java create mode 100644 Core/src/org/sleuthkit/autopsy/discovery/ui/WebHistoryDetailsPanel.form create mode 100644 Core/src/org/sleuthkit/autopsy/discovery/ui/WebHistoryDetailsPanel.java diff --git a/Core/src/org/sleuthkit/autopsy/discovery/search/DiscoveryEventUtils.java b/Core/src/org/sleuthkit/autopsy/discovery/search/DiscoveryEventUtils.java index 18dd83dfe1..80201715fb 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/search/DiscoveryEventUtils.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/search/DiscoveryEventUtils.java @@ -126,6 +126,27 @@ public final class DiscoveryEventUtils { } } + public static final class PopulateDomainTabsEvent { + + private final String domain; + + /** + * Construct a new PopulateDomainTabsEvent. + */ + public PopulateDomainTabsEvent(String domain) { + this.domain = domain; + } + + /** + * Get the domain for the details area. + * + * @return The the domain for the details area. + */ + public String getDomain() { + return domain; + } + } + /** * Event to signal the completion of a search being performed. */ diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/AbstractArtifactDetailsPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/AbstractArtifactDetailsPanel.java index f1feb975a5..57d7029e3d 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/AbstractArtifactDetailsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/AbstractArtifactDetailsPanel.java @@ -1,18 +1,27 @@ /* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. + * Autopsy + * + * Copyright 2020 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.sleuthkit.autopsy.discovery.ui; import javax.swing.JPanel; import org.sleuthkit.datamodel.BlackboardArtifact; -/** - * - * @author wschaefer - */ -abstract class AbstractArtifactDetailsPanel extends JPanel { +public abstract class AbstractArtifactDetailsPanel extends JPanel { private static final long serialVersionUID = 1L; @@ -21,6 +30,6 @@ abstract class AbstractArtifactDetailsPanel extends JPanel { * * @param artifact the artifact to display. */ - abstract void setArtifact(BlackboardArtifact artifact); + abstract public void setArtifact(BlackboardArtifact artifact); } diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.form b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.form index a5a6f66c1c..c7ca652303 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.form +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.form @@ -1,6 +1,6 @@ -
+ @@ -11,21 +11,28 @@ + - - - - - - + - + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java index 4ae027cdc9..7b63ae69ab 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java @@ -20,44 +20,55 @@ package org.sleuthkit.autopsy.discovery.ui; import java.util.ArrayList; import java.util.List; +import javax.swing.JPanel; import javax.swing.event.ListSelectionListener; import javax.swing.table.AbstractTableModel; +import org.apache.commons.lang.StringUtils; +import org.openide.util.Exceptions; import org.openide.util.NbBundle; import org.sleuthkit.datamodel.BlackboardArtifact; +import org.sleuthkit.datamodel.BlackboardAttribute; +import org.sleuthkit.datamodel.TskCoreException; -/** - * - * @author wschaefer - */ -public class ArtifactsListPanel extends javax.swing.JScrollPane { +public class ArtifactsListPanel extends JPanel { private static final long serialVersionUID = 1L; + private final DomainArtifactTableModel tableModel = new DomainArtifactTableModel(); /** * Creates new form ArtifactsListPanel */ public ArtifactsListPanel() { initComponents(); + } public void addSelectionListener(ListSelectionListener listener) { jTable1.getSelectionModel().addListSelectionListener(listener); } + public void removeListSelectionListener(ListSelectionListener listener) { + jTable1.getSelectionModel().removeListSelectionListener(listener); + } + public BlackboardArtifact getSelectedArtifact() { - return ((DomainArtifactTableModel) jTable1.getSelectionModel()).getArtifactByRow(jTable1.getSelectionModel().getLeadSelectionIndex()); + return ((DomainArtifactTableModel) jTable1.getModel()).getArtifactByRow(jTable1.getSelectionModel().getLeadSelectionIndex()); } public boolean isEmpty() { - return false; + return tableModel.getRowCount() <= 0; } public void addArtifacts(List artifactList) { - jTable1.setModel(new DomainArtifactTableModel(artifactList)); + tableModel.setContents(artifactList); + jTable1.validate(); + jTable1.repaint(); + tableModel.fireTableDataChanged(); } public void clearArtifacts() { - jTable1.setModel(new DomainArtifactTableModel()); + tableModel.setContents(new ArrayList<>()); + tableModel.fireTableDataChanged(); } /** @@ -68,24 +79,33 @@ public class ArtifactsListPanel extends javax.swing.JScrollPane { // //GEN-BEGIN:initComponents private void initComponents() { + jScrollPane1 = new javax.swing.JScrollPane(); jTable1 = new javax.swing.JTable(); setLayout(new java.awt.BorderLayout()); - jTable1.setModel(new DomainArtifactTableModel()); - add(jTable1, java.awt.BorderLayout.PAGE_START); + jTable1.setModel(tableModel); + jScrollPane1.setViewportView(jTable1); + + add(jScrollPane1, java.awt.BorderLayout.PAGE_START); }// //GEN-END:initComponents - private class DomainArtifactTableModel extends AbstractTableModel { + + void addListener(ListSelectionListener listSelectionListener) { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + + private class DomainArtifactTableModel extends AbstractTableModel { private static final long serialVersionUID = 1L; private final List artifactList = new ArrayList<>(); - DomainArtifactTableModel(){ + DomainArtifactTableModel() { //No arg constructor to create empty model } - - DomainArtifactTableModel(List artifactList) { - this.artifactList.addAll(artifactList); + + void setContents(List artifacts) { + artifactList.clear(); + artifactList.addAll(artifacts); } @Override @@ -104,25 +124,51 @@ public class ArtifactsListPanel extends javax.swing.JScrollPane { @Override public Object getValueAt(int rowIndex, int columnIndex) { - switch (columnIndex) { - case 0: - return getArtifactByRow(rowIndex); - case 1: - return getArtifactByRow(rowIndex); - default: - return getArtifactByRow(rowIndex); + Object returnValue = null; + String url = ""; + try { + for (BlackboardAttribute bba : getArtifactByRow(rowIndex).getAttributes()) { + if (bba.getAttributeType().getTypeName().startsWith("TSK_URL")) { + url = bba.getDisplayString(); + continue; + } + switch (columnIndex) { + case 0: + if (bba.getAttributeType().getTypeName().startsWith("TSK_DATETIME_ACCESSED") && !StringUtils.isBlank(bba.getDisplayString())) { + returnValue = bba.getDisplayString(); + } + break; + case 1: + if (bba.getAttributeType().getTypeName().startsWith("TSK_TITLE") && !StringUtils.isBlank(bba.getDisplayString())) { + returnValue = bba.getDisplayString(); + } + break; + default: + break; + } + } + } catch (TskCoreException ex) { + Exceptions.printStackTrace(ex); } + if (returnValue == null) { + if (columnIndex == 0) { + returnValue = "No Date"; + } else { + returnValue = url; + } + } + return returnValue; } - @NbBundle.Messages({"ArtifactsListPanel.urlColumn.name=URL", + @NbBundle.Messages({"ArtifactsListPanel.titleColumn.name=Title", "ArtifactsListPanel.dateColumn.name=Date/Time"}) @Override public String getColumnName(int column) { switch (column) { case 0: - return Bundle.ArtifactsListPanel_urlColumn_name(); - case 1: return Bundle.ArtifactsListPanel_dateColumn_name(); + case 1: + return Bundle.ArtifactsListPanel_titleColumn_name(); default: return ""; } @@ -130,6 +176,7 @@ public class ArtifactsListPanel extends javax.swing.JScrollPane { } // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JScrollPane jScrollPane1; private javax.swing.JTable jTable1; // End of variables declaration//GEN-END:variables } diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsWorker.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsWorker.java index d07499583c..bf2b3ee2cb 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsWorker.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsWorker.java @@ -19,33 +19,29 @@ package org.sleuthkit.autopsy.discovery.ui; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.concurrent.ExecutionException; import java.util.logging.Level; -import static javax.swing.JComponent.TOOL_TIP_TEXT_KEY; import javax.swing.SwingWorker; import org.apache.commons.lang3.StringUtils; -import org.openide.util.Exceptions; -import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoException; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository; import org.sleuthkit.autopsy.discovery.search.DiscoveryEventUtils; import org.sleuthkit.autopsy.discovery.search.DomainSearch; import org.sleuthkit.autopsy.discovery.search.DomainSearchArtifactsRequest; import org.sleuthkit.datamodel.BlackboardArtifact; -/** - * - * @author wschaefer - */ public class ArtifactsWorker extends SwingWorker, Void> { - private final BlackboardArtifact.ARTIFACT_TYPE artifactType = null; + private BlackboardArtifact.ARTIFACT_TYPE artifactType = null; private final static Logger logger = Logger.getLogger(ArtifactsWorker.class.getName()); - private final String domain = null; + private final String domain; + ArtifactsWorker(BlackboardArtifact.ARTIFACT_TYPE artifactType, String domain){ + this.artifactType = artifactType; + this.domain = domain; + } + @Override protected List doInBackground() throws Exception { if (artifactType != null && !StringUtils.isBlank(domain)) { @@ -55,6 +51,8 @@ public class ArtifactsWorker extends SwingWorker, Void> return new ArrayList<>(); } + + @Override protected void done() { List listOfArtifacts = new ArrayList<>(); diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/discovery/ui/Bundle.properties-MERGED index a35e8113e2..bfe0cc5d8a 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/Bundle.properties-MERGED @@ -1,3 +1,5 @@ +ArtifactsListPanel.dateColumn.name=Date/Time +ArtifactsListPanel.titleColumn.name=Title ArtifactTypeFilterPanel.selectionNeeded.text=At least one Result type must be selected. CTL_OpenDiscoveryAction=Discovery DataSourceFilterPanel.error.text=At least one data source must be selected. @@ -126,15 +128,15 @@ HashSetFilterPanel.hashSetCheckbox.text=Hash Set: PastOccurrencesFilterPanel.pastOccurrencesCheckbox.text=Past Occurrences: DocumentFilterPanel.documentsFiltersSplitPane.border.title=Step 2: Filter which documents to show ObjectDetectedFilterPanel.text=Object Detected: -DetailsPanel.instancesList.border.title=Instances DateFilterPanel.mostRecentRadioButton.text=Only last: DateFilterPanel.dateFilterCheckBox.text=Date Filter: DomainSummaryPanel.activityLabel.text= DomainSummaryPanel.pagesLabel.text= DomainSummaryPanel.filesDownloadedLabel.text= DomainSummaryPanel.totalVisitsLabel.text= -CookiesDetailsPanel.jLabel1.text=Artifact: -CookiesDetailsPanel.jLabel2.text= +FileDetailsPanel.instancesList.border.title=Instances +CookieDetailsPanel.jLabel1.text=Artifact: +CookieDetailsPanel.jLabel2.text= VideoThumbnailPanel.bytes.text=bytes VideoThumbnailPanel.deleted.text=All instances of file are deleted. VideoThumbnailPanel.gigaBytes.text=GB diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/CookieDetailsPanel.form b/Core/src/org/sleuthkit/autopsy/discovery/ui/CookieDetailsPanel.form deleted file mode 100644 index 037c904fe5..0000000000 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/CookieDetailsPanel.form +++ /dev/null @@ -1,66 +0,0 @@ - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/CookieDetailsPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/CookieDetailsPanel.java deleted file mode 100644 index cf382d1795..0000000000 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/CookieDetailsPanel.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Autopsy - * - * Copyright 2020 Basis Technology Corp. - * Contact: carrier sleuthkit org - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.sleuthkit.autopsy.discovery.ui; - -import java.awt.Component; -import org.openide.util.lookup.ServiceProvider; -import org.sleuthkit.autopsy.contentviewers.artifactviewers.ArtifactContentViewer; -import org.sleuthkit.datamodel.BlackboardArtifact; - -/** - * - * @author wschaefer - */ -@ServiceProvider(service = ArtifactContentViewer.class) -public class CookieDetailsPanel extends AbstractArtifactDetailsPanel implements ArtifactContentViewer { - - private static final long serialVersionUID = 1L; - private BlackboardArtifact artifact; - - /** - * Creates new form CookiesDetailsPanel - */ - public CookieDetailsPanel() { - initComponents(); - } - - - /** - * This method is called from within the constructor to initialize the form. - * WARNING: Do NOT modify this code. The content of this method is always - * regenerated by the Form Editor. - */ - @SuppressWarnings("unchecked") - // //GEN-BEGIN:initComponents - private void initComponents() { - - jLabel1 = new javax.swing.JLabel(); - jLabel2 = new javax.swing.JLabel(); - - org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(CookieDetailsPanel.class, "CookieDetailsPanel.jLabel1.text")); // NOI18N - - org.openide.awt.Mnemonics.setLocalizedText(jLabel2, org.openide.util.NbBundle.getMessage(CookieDetailsPanel.class, "CookieDetailsPanel.jLabel2.text")); // NOI18N - - javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); - this.setLayout(layout); - layout.setHorizontalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addGap(120, 120, 120) - .addComponent(jLabel1) - .addContainerGap(234, Short.MAX_VALUE)) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addGap(0, 0, Short.MAX_VALUE) - .addComponent(jLabel2) - .addGap(0, 0, Short.MAX_VALUE))) - ); - layout.setVerticalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() - .addContainerGap(143, Short.MAX_VALUE) - .addComponent(jLabel1) - .addGap(141, 141, 141)) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addGap(0, 0, Short.MAX_VALUE) - .addComponent(jLabel2) - .addGap(0, 0, Short.MAX_VALUE))) - ); - }// //GEN-END:initComponents - - @Override - public void setArtifact(BlackboardArtifact artifact) { - this.artifact = artifact; - if (this.artifact == null) { - resetComponent(); - return; - } - jLabel2.setText(artifact.getDisplayName()); - - } - - private void resetComponent() { - jLabel2.setText(""); - } - - @Override - public Component getComponent() { - return this; - } - - @Override - public boolean isSupported(BlackboardArtifact artifact) { - return (artifact != null) - && (artifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_COOKIE.getTypeID()); - } - - - // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.JLabel jLabel1; - private javax.swing.JLabel jLabel2; - // End of variables declaration//GEN-END:variables -} diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/DiscoveryTopComponent.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/DiscoveryTopComponent.java index 628b706e11..16f5b1b16e 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/DiscoveryTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/DiscoveryTopComponent.java @@ -91,6 +91,7 @@ public final class DiscoveryTopComponent extends TopComponent { } } }); + rightSplitPane.setTopComponent(resultsPanel); } /** @@ -149,8 +150,6 @@ public final class DiscoveryTopComponent extends TopComponent { DiscoveryEventUtils.getDiscoveryEventBus().unregister(resultsPanel); DiscoveryEventUtils.getDiscoveryEventBus().unregister(rightSplitPane.getBottomComponent()); setDetailsVisible(false); - rightSplitPane.setBottomComponent(null); - super.componentClosed(); } @@ -263,19 +262,17 @@ public final class DiscoveryTopComponent extends TopComponent { */ @Subscribe void handleDetailsVisibleEvent(DiscoveryEventUtils.DetailsVisibleEvent detailsVisibleEvent) { - if (resultsPanel.getActiveType() != DOMAIN) { - if (animator != null && animator.isRunning()) { - animator.stop(); - animator = null; - } - dividerLocation = rightSplitPane.getDividerLocation(); - if (detailsVisibleEvent.isShowDetailsArea()) { - animator = new SwingAnimator(new ShowDetailsAreaCallback()); - } else { - animator = new SwingAnimator(new HideDetailsAreaCallback()); - } - animator.start(); + if (animator != null && animator.isRunning()) { + animator.stop(); + animator = null; } + dividerLocation = rightSplitPane.getDividerLocation(); + if (detailsVisibleEvent.isShowDetailsArea()) { + animator = new SwingAnimator(new ShowDetailsAreaCallback()); + } else { + animator = new SwingAnimator(new HideDetailsAreaCallback()); + } + animator.start(); } /** diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.form b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.form index 4f9abb50dc..80cfa517c7 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.form +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.form @@ -1,6 +1,6 @@ -
+ @@ -13,16 +13,16 @@ - - - - - - - - - - - - + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.java index c9c1282329..8eece4ce1d 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.java @@ -20,69 +20,95 @@ package org.sleuthkit.autopsy.discovery.ui; import com.google.common.eventbus.Subscribe; import javax.swing.JPanel; +import javax.swing.SwingUtilities; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; -import org.sleuthkit.autopsy.contentviewers.artifactviewers.ArtifactContentViewer; +import org.sleuthkit.autopsy.contentviewers.artifactviewers.DefaultArtifactContentViewer; import org.sleuthkit.autopsy.discovery.search.DiscoveryEventUtils; import org.sleuthkit.datamodel.BlackboardArtifact; -/** - * - * @author wschaefer - */ -public final class DomainArtifactsTabPanel extends javax.swing.JSplitPane { +public final class DomainArtifactsTabPanel extends JPanel { private static final long serialVersionUID = 1L; private final ArtifactsListPanel listPanel = new ArtifactsListPanel(); private final BlackboardArtifact.ARTIFACT_TYPE artifactType; private AbstractArtifactDetailsPanel rightPanel = null; + private volatile ARTIFACT_RETRIEVAL_STATUS status = ARTIFACT_RETRIEVAL_STATUS.UNPOPULATED; + private final ListSelectionListener listener = new ListSelectionListener() { + @Override + public void valueChanged(ListSelectionEvent event) { + if (!event.getValueIsAdjusting()) { + rightPanel.setArtifact(listPanel.getSelectedArtifact()); + } + } + }; + /** * Creates new form CookiesPanel */ public DomainArtifactsTabPanel(BlackboardArtifact.ARTIFACT_TYPE artifactType) { initComponents(); this.artifactType = artifactType; - this.setLeftComponent(listPanel); + jSplitPane1.setLeftComponent(listPanel); setRightComponent(); - update(); } private void setRightComponent() { - + switch (artifactType) { - case TSK_WEB_COOKIE: - rightPanel = new CookieDetailsPanel(); + case TSK_WEB_HISTORY: + rightPanel = new WebHistoryDetailsPanel(); break; + case TSK_WEB_COOKIE: + case TSK_WEB_SEARCH_QUERY: + case TSK_WEB_BOOKMARK: + case TSK_WEB_DOWNLOAD: + case TSK_WEB_CACHE: default: + rightPanel = new DefaultArtifactContentViewer(); break; } - if (rightPanel == null) { - getComponent(1).setVisible(false); - getComponent(2).setVisible(false); - } else { - this.setRightComponent(rightPanel); - getComponent(1).setVisible(true); - getComponent(2).setVisible(true); + if (rightPanel != null) { + jSplitPane1.setRightComponent(rightPanel); } } - private void update() { - this.setEnabled(!this.listPanel.isEmpty()); + ARTIFACT_RETRIEVAL_STATUS getStatus() { + return status; + } + + void setStatus(ARTIFACT_RETRIEVAL_STATUS status) { + this.status = status; } @Subscribe void handleArtifactListRetrievedEvent(DiscoveryEventUtils.ArtifactListRetrievedEvent artifactListEvent) { - if (artifactType == artifactListEvent.getArtifactType()) { - listPanel.addArtifacts(artifactListEvent.getListOfArtifacts()); - listPanel.addSelectionListener(new ListSelectionListener() { - public void valueChanged(ListSelectionEvent event) { - if (!event.getValueIsAdjusting()){ - rightPanel.setArtifact(listPanel.getSelectedArtifact()); - } + SwingUtilities.invokeLater(() -> { + if (artifactType == artifactListEvent.getArtifactType()) { + if (artifactListEvent.getListOfArtifacts().isEmpty()) { + listPanel.clearArtifacts(); + setEnabled(false); + } else { + setEnabled(true); + listPanel.removeListSelectionListener(listener); + listPanel.addArtifacts(artifactListEvent.getListOfArtifacts()); + listPanel.addSelectionListener(listener); } - }); - } + try { + DiscoveryEventUtils.getDiscoveryEventBus().unregister(this); + } catch (IllegalArgumentException notRegistered) { + // attempting to remove a tab that was never registered + } + status = ARTIFACT_RETRIEVAL_STATUS.POPULATED; + validate(); + repaint(); + } + }); + } + + BlackboardArtifact.ARTIFACT_TYPE getArtifactType() { + return artifactType; } /** @@ -94,19 +120,21 @@ public final class DomainArtifactsTabPanel extends javax.swing.JSplitPane { // //GEN-BEGIN:initComponents private void initComponents() { - javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); - this.setLayout(layout); - layout.setHorizontalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGap(0, 400, Short.MAX_VALUE) - ); - layout.setVerticalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGap(0, 300, Short.MAX_VALUE) - ); + jSplitPane1 = new javax.swing.JSplitPane(); + + setLayout(new java.awt.BorderLayout()); + add(jSplitPane1, java.awt.BorderLayout.CENTER); }// //GEN-END:initComponents // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JSplitPane jSplitPane1; // End of variables declaration//GEN-END:variables + + public enum ARTIFACT_RETRIEVAL_STATUS { + UNPOPULATED(), + POPULATING(), + POPULATED(); + } + } diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.form b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.form index b6bc3eb975..162d346225 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.form +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.form @@ -1,6 +1,9 @@
+ + + @@ -11,7 +14,19 @@ + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.java index 2a6fdfc4b0..639713d1a1 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.java @@ -18,15 +18,24 @@ */ package org.sleuthkit.autopsy.discovery.ui; +import com.google.common.eventbus.Subscribe; +import java.awt.Component; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import org.apache.commons.lang.StringUtils; +import org.sleuthkit.autopsy.discovery.search.DiscoveryEventUtils; import org.sleuthkit.datamodel.BlackboardArtifact; +import org.sleuthkit.autopsy.discovery.search.SearchData; -/** - * - * @author wschaefer - */ -final class DomainDetailsPanel extends javax.swing.JTabbedPane { + +final class DomainDetailsPanel extends JPanel { private static final long serialVersionUID = 1L; + private static ArtifactsWorker detailsWorker; + private static String domain; + private static String selectedTabName; /** * Creates new form ArtifactDetailsPanel @@ -37,12 +46,79 @@ final class DomainDetailsPanel extends javax.swing.JTabbedPane { } private void addArtifactTabs() { - DomainArtifactsTabPanel cookiesPanel = new DomainArtifactsTabPanel(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_COOKIE); - cookiesPanel.setRightComponent(new CookieDetailsPanel()); - add(cookiesPanel); + for (BlackboardArtifact.ARTIFACT_TYPE type : SearchData.Type.DOMAIN.getArtifactTypes()) { + DomainArtifactsTabPanel newTab = new DomainArtifactsTabPanel(type); + jTabbedPane1.add(type.getDisplayName(), newTab); + if (!StringUtils.isBlank(selectedTabName) && type.getDisplayName().equals(selectedTabName) && newTab.isEnabled()) { + jTabbedPane1.setSelectedComponent(newTab); + } + } + jTabbedPane1.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + if (jTabbedPane1.getSelectedIndex() >= 0) { + String newTabTitle = jTabbedPane1.getTitleAt(jTabbedPane1.getSelectedIndex()); + if (selectedTabName == null || !selectedTabName.equals(newTabTitle)) { + selectedTabName = newTabTitle; + runDomainWorker(); + } + } + } + }); + } + + private void runDomainWorker() { + SwingUtilities.invokeLater(() -> { + Component selectedComponent = jTabbedPane1.getSelectedComponent(); + if (selectedComponent != null && selectedComponent instanceof DomainArtifactsTabPanel) { + if (detailsWorker != null && !detailsWorker.isDone()) { + detailsWorker.cancel(true); + } + DomainArtifactsTabPanel selectedTab = (DomainArtifactsTabPanel) selectedComponent; + if (selectedTab.getStatus() == DomainArtifactsTabPanel.ARTIFACT_RETRIEVAL_STATUS.UNPOPULATED) { + selectedTab.setStatus(DomainArtifactsTabPanel.ARTIFACT_RETRIEVAL_STATUS.POPULATING); + DiscoveryEventUtils.getDiscoveryEventBus().register(selectedTab); + detailsWorker = new ArtifactsWorker(selectedTab.getArtifactType(), domain); + detailsWorker.execute(); + } + } + }); + } + + private void clearTabs() { + int tabCount = jTabbedPane1.getTabCount(); + // We invoke removeTabAt for each tab, otherwise we may end up + // removing Components added by the UI. + while (tabCount > 0) { + tabCount--; + jTabbedPane1.removeTabAt(tabCount); + } + addArtifactTabs(); + + } + + /** + * Populate the the details tabs. + * + * @param populateEvent The PopulateDomainTabsEvent which indicates which + * domain the details tabs should be populated for. + */ + @Subscribe + synchronized void handlePopulateDomainTabsEvent(DiscoveryEventUtils.PopulateDomainTabsEvent populateEvent) { + SwingUtilities.invokeLater(() -> { + domain = populateEvent.getDomain(); + runDomainWorker(); + clearTabs(); + if (StringUtils.isBlank(domain)) { + //send fade out event + DiscoveryEventUtils.getDiscoveryEventBus().post(new DiscoveryEventUtils.DetailsVisibleEvent(false)); + } else { + //send fade in event + DiscoveryEventUtils.getDiscoveryEventBus().post(new DiscoveryEventUtils.DetailsVisibleEvent(true)); + } + }); } - /** * This method is called from within the constructor to initialize the form. * WARNING: Do NOT modify this code. The content of this method is always @@ -52,10 +128,14 @@ final class DomainDetailsPanel extends javax.swing.JTabbedPane { // //GEN-BEGIN:initComponents private void initComponents() { + jTabbedPane1 = new javax.swing.JTabbedPane(); + + setEnabled(false); setLayout(new java.awt.BorderLayout()); + add(jTabbedPane1, java.awt.BorderLayout.CENTER); }// //GEN-END:initComponents - // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JTabbedPane jTabbedPane1; // End of variables declaration//GEN-END:variables } diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainSummaryViewer.form b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainSummaryViewer.form index 22296c0178..9f1e3516b9 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainSummaryViewer.form +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainSummaryViewer.form @@ -39,8 +39,6 @@
- - diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainSummaryViewer.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainSummaryViewer.java index 593ae49949..935af9fa37 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainSummaryViewer.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainSummaryViewer.java @@ -19,6 +19,7 @@ package org.sleuthkit.autopsy.discovery.ui; import javax.swing.DefaultListModel; +import javax.swing.event.ListSelectionListener; /** * A JPanel to display domain summaries. @@ -56,7 +57,7 @@ public class DomainSummaryViewer extends javax.swing.JPanel { private void initComponents() { domainScrollPane = new javax.swing.JScrollPane(); - javax.swing.JList domainList = new javax.swing.JList<>(); + domainList = new javax.swing.JList<>(); setLayout(new java.awt.BorderLayout()); @@ -69,6 +70,7 @@ public class DomainSummaryViewer extends javax.swing.JPanel { // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JList domainList; private javax.swing.JScrollPane domainScrollPane; // End of variables declaration//GEN-END:variables @@ -83,4 +85,31 @@ public class DomainSummaryViewer extends javax.swing.JPanel { domainListModel.addElement(domainWrapper); } } + + /** + * Get the list of AbstractFiles which are represented by the selected + * document preview. + * + * @return The list of AbstractFiles which are represented by the selected + * document preview. + */ + String getDomainForSelected() { + synchronized (this) { + if (domainList.getSelectedIndex() == -1) { + return ""; + } else { + return domainListModel.getElementAt(domainList.getSelectedIndex()).getResultDomain().getDomain(); + } + } + } + + /** + * Add a selection listener to the list of document previews being + * displayed. + * + * @param listener The ListSelectionListener to add to the selection model. + */ + void addListSelectionListener(ListSelectionListener listener) { + domainList.getSelectionModel().addListSelectionListener(listener); + } } diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/ResultsPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/ResultsPanel.java index c077f65f22..4c958d2c61 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/ResultsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/ResultsPanel.java @@ -20,6 +20,7 @@ package org.sleuthkit.autopsy.discovery.ui; import org.sleuthkit.autopsy.discovery.search.AbstractFilter; import com.google.common.eventbus.Subscribe; +import java.awt.Component; import java.awt.Cursor; import java.awt.Image; import java.awt.event.ItemEvent; @@ -32,6 +33,8 @@ import javax.swing.DefaultComboBoxModel; import javax.swing.JOptionPane; import javax.swing.SwingUtilities; import javax.swing.SwingWorker; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; @@ -125,7 +128,17 @@ final class ResultsPanel extends javax.swing.JPanel { } } }); - //JIRA-TODO 6307 Add listener for domainSummaryViewer when 6782, 6773, and the other details area related stories are done + domainSummaryViewer.addListSelectionListener((e) -> { + if (resultType == SearchData.Type.DOMAIN) { + if (!e.getValueIsAdjusting()) { + //send populateMesage + DiscoveryEventUtils.getDiscoveryEventBus().post(new DiscoveryEventUtils.PopulateDomainTabsEvent(domainSummaryViewer.getDomainForSelected())); + } else { + //send clearSelection message + DiscoveryEventUtils.getDiscoveryEventBus().post(new DiscoveryEventUtils.PopulateDomainTabsEvent("")); + } + } + }); } SearchData.Type getActiveType() { @@ -209,7 +222,7 @@ final class ResultsPanel extends javax.swing.JPanel { } ); } - + @Subscribe void handleCancelBackgroundTasksEvent(DiscoveryEventUtils.CancelBackgroundTasksEvent cancelEvent) { for (SwingWorker thumbWorker : resultContentWorkers) { @@ -217,7 +230,7 @@ final class ResultsPanel extends javax.swing.JPanel { thumbWorker.cancel(true); } } - + resultContentWorkers.clear(); } diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/WebHistoryDetailsPanel.form b/Core/src/org/sleuthkit/autopsy/discovery/ui/WebHistoryDetailsPanel.form new file mode 100644 index 0000000000..5f3eab1a5f --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/WebHistoryDetailsPanel.form @@ -0,0 +1,28 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/WebHistoryDetailsPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/WebHistoryDetailsPanel.java new file mode 100644 index 0000000000..9226f85b96 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/WebHistoryDetailsPanel.java @@ -0,0 +1,210 @@ +/* + * Autopsy + * + * Copyright 2020 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.discovery.ui; + +import java.awt.Component; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.util.ArrayList; +import java.util.List; +import javax.swing.JScrollPane; +import org.openide.util.Exceptions; +import org.openide.util.lookup.ServiceProvider; +import org.sleuthkit.autopsy.contentviewers.artifactviewers.ArtifactContentViewer; +import org.sleuthkit.autopsy.contentviewers.artifactviewers.CommunicationArtifactViewerHelper; +import org.sleuthkit.datamodel.BlackboardArtifact; +import org.sleuthkit.datamodel.BlackboardAttribute; +import org.sleuthkit.datamodel.TskCoreException; + +@ServiceProvider(service = ArtifactContentViewer.class) +public class WebHistoryDetailsPanel extends AbstractArtifactDetailsPanel implements ArtifactContentViewer { + + private static final long serialVersionUID = 1L; + private BlackboardArtifact webHistoryArtifact; + private final GridBagLayout gridBagLayout = new GridBagLayout(); + private final List urlList = new ArrayList<>(); + private final List dateAccessedList = new ArrayList<>(); + private final List referrerUrlList = new ArrayList<>(); + private final List titleList = new ArrayList<>(); + private final List programNameList = new ArrayList<>(); + private final List domainList = new ArrayList<>(); + private final List otherList = new ArrayList<>(); + private final List artifactAttributesList = new ArrayList<>(); + private final GridBagConstraints gridBagConstraints = new GridBagConstraints(); + private String dataSourceName; + + /** + * Creates new form WebHistoryDetailsPanel. + */ + public WebHistoryDetailsPanel() { + initComponents(); + } + + @Override + public void setArtifact(BlackboardArtifact artifact) { + + resetComponent(); + if (artifact != null) { + + try { + extractArtifactData(artifact); + } catch (TskCoreException ex) { + Exceptions.printStackTrace(ex); + } + updateView(); + } + + this.setLayout(this.gridBagLayout); + this.revalidate(); + this.repaint(); + } + + /** + * Extracts data from the artifact to be displayed in the panel. + * + * @param artifact Artifact to show. + * + * @throws TskCoreException + */ + private void extractArtifactData(BlackboardArtifact artifact) throws TskCoreException { + + webHistoryArtifact = artifact; + + urlList.clear(); + dateAccessedList.clear(); + referrerUrlList.clear(); + titleList.clear(); + programNameList.clear(); + domainList.clear(); + otherList.clear(); + artifactAttributesList.clear(); + artifactAttributesList.addAll(webHistoryArtifact.getAttributes()); + // Get all the attributes and group them by the section panels they go in + for (BlackboardAttribute bba : artifactAttributesList) { + if (bba.getAttributeType().getTypeName().startsWith("TSK_URL")) { + urlList.add(bba); + } else if (bba.getAttributeType().getTypeName().startsWith("TSK_PROG_NAME")) { + programNameList.add(bba); + } else if (bba.getAttributeType().getTypeName().startsWith("TSK_DOMAIN")) { + domainList.add(bba); + } else if (bba.getAttributeType().getTypeName().startsWith("TSK_REFERRER")) { + referrerUrlList.add(bba); + } else if (bba.getAttributeType().getTypeName().startsWith("TSK_DATETIME_ACCESSED")) { + dateAccessedList.add(bba); + } else if (bba.getAttributeType().getTypeName().startsWith("TSK_TITLE")) { + titleList.add(bba); + } else { + otherList.add(bba); + } + + } + + dataSourceName = webHistoryArtifact.getDataSource().getName(); + } + + private void resetComponent() { + gridBagConstraints.anchor = GridBagConstraints.FIRST_LINE_START; + gridBagConstraints.gridy = 0; + gridBagConstraints.gridx = 0; + gridBagConstraints.weighty = 0.0; + gridBagConstraints.weightx = 0.0; // keep components fixed horizontally. + gridBagConstraints.insets = new java.awt.Insets(0, 12, 0, 0); + gridBagConstraints.fill = GridBagConstraints.NONE; + webHistoryArtifact = null; + dataSourceName = null; + urlList.clear(); + dateAccessedList.clear(); + referrerUrlList.clear(); + titleList.clear(); + programNameList.clear(); + domainList.clear(); + artifactAttributesList.clear(); + // clear the panel + this.removeAll(); + this.setLayout(null); + } + + @Override + public Component getComponent() { + // Slap a vertical scrollbar on the panel. + return new JScrollPane(this, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + } + + @Override + public boolean isSupported(BlackboardArtifact artifact) { + return (artifact != null) + && (artifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY.getTypeID()); + } + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 400, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 300, Short.MAX_VALUE) + ); + }// //GEN-END:initComponents + + private void updateView() { + CommunicationArtifactViewerHelper.addHeader(this, gridBagLayout, gridBagConstraints, "Attributes"); + + for (BlackboardAttribute bba : this.titleList) { + CommunicationArtifactViewerHelper.addRow(this, gridBagLayout, gridBagConstraints, bba.getAttributeType().getDisplayName(), bba.getDisplayString()); + } +// CommunicationArtifactViewerHelper.addHeader(this, gridBagLayout, gridBagConstraints, sectionHeader); + for (BlackboardAttribute bba : dateAccessedList) { + CommunicationArtifactViewerHelper.addRow(this, gridBagLayout, gridBagConstraints, bba.getAttributeType().getDisplayName(), bba.getDisplayString()); + } + for (BlackboardAttribute bba : domainList) { + CommunicationArtifactViewerHelper.addRow(this, gridBagLayout, gridBagConstraints, bba.getAttributeType().getDisplayName(), bba.getDisplayString()); + } + for (BlackboardAttribute bba : urlList) { + CommunicationArtifactViewerHelper.addRow(this, gridBagLayout, gridBagConstraints, bba.getAttributeType().getDisplayName(), bba.getDisplayString()); + } + for (BlackboardAttribute bba : referrerUrlList) { + CommunicationArtifactViewerHelper.addRow(this, gridBagLayout, gridBagConstraints, bba.getAttributeType().getDisplayName(), bba.getDisplayString()); + } + for (BlackboardAttribute bba : programNameList) { + CommunicationArtifactViewerHelper.addRow(this, gridBagLayout, gridBagConstraints, bba.getAttributeType().getDisplayName(), bba.getDisplayString()); + } + for (BlackboardAttribute bba : otherList) { + CommunicationArtifactViewerHelper.addRow(this, gridBagLayout, gridBagConstraints, bba.getAttributeType().getDisplayName(), bba.getDisplayString()); + } + CommunicationArtifactViewerHelper.addHeader(this, gridBagLayout, gridBagConstraints, "Source"); + CommunicationArtifactViewerHelper.addRow(this, gridBagLayout, gridBagConstraints, "Data Source", dataSourceName); + // add veritcal glue at the end + CommunicationArtifactViewerHelper.addPageEndGlue(this, gridBagLayout, this.gridBagConstraints); + } + + + // Variables declaration - do not modify//GEN-BEGIN:variables + // End of variables declaration//GEN-END:variables +} From 6f179d3274b1582281d9f08c9c8c186c17563259 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Thu, 22 Oct 2020 18:41:04 -0400 Subject: [PATCH 03/81] 6773 improve date column: --- .../autopsy/discovery/ui/ArtifactsListPanel.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java index 7b63ae69ab..7098cdbcbc 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java @@ -122,10 +122,12 @@ public class ArtifactsListPanel extends JPanel { return artifactList.get(rowIndex); } + @NbBundle.Messages({"ArtifactsListPanel.value.noValue=No value available."}) @Override public Object getValueAt(int rowIndex, int columnIndex) { Object returnValue = null; String url = ""; + String otherDate = ""; try { for (BlackboardAttribute bba : getArtifactByRow(rowIndex).getAttributes()) { if (bba.getAttributeType().getTypeName().startsWith("TSK_URL")) { @@ -136,6 +138,8 @@ public class ArtifactsListPanel extends JPanel { case 0: if (bba.getAttributeType().getTypeName().startsWith("TSK_DATETIME_ACCESSED") && !StringUtils.isBlank(bba.getDisplayString())) { returnValue = bba.getDisplayString(); + } else if (bba.getAttributeType().getTypeName().startsWith("TSK_DATETIME") && !StringUtils.isBlank(bba.getDisplayString())) { + otherDate = bba.getDisplayString(); } break; case 1: @@ -151,10 +155,12 @@ public class ArtifactsListPanel extends JPanel { Exceptions.printStackTrace(ex); } if (returnValue == null) { - if (columnIndex == 0) { - returnValue = "No Date"; - } else { + if (columnIndex == 0 && !StringUtils.isBlank(otherDate)) { + returnValue = otherDate; + } else if (columnIndex == 1 && !StringUtils.isBlank(url)) { returnValue = url; + } else { + returnValue = Bundle.ArtifactsListPanel_value_noValue(); } } return returnValue; From 33dc3a8ad91b36cece031b571112510a1bc114ee Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Fri, 23 Oct 2020 09:47:49 -0400 Subject: [PATCH 04/81] 6773 fix unselection --- .../discovery/search/DiscoveryEventUtils.java | 3 + .../discovery/ui/ArtifactsListPanel.form | 9 ++ .../discovery/ui/ArtifactsListPanel.java | 91 ++++++++++++++++--- .../discovery/ui/Bundle.properties-MERGED | 5 + .../discovery/ui/DomainArtifactsTabPanel.java | 29 +++--- .../autopsy/discovery/ui/ResultsPanel.java | 3 - .../discovery/ui/WebHistoryDetailsPanel.java | 58 +++++------- 7 files changed, 131 insertions(+), 67 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/discovery/search/DiscoveryEventUtils.java b/Core/src/org/sleuthkit/autopsy/discovery/search/DiscoveryEventUtils.java index 80201715fb..2992c37a80 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/search/DiscoveryEventUtils.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/search/DiscoveryEventUtils.java @@ -126,6 +126,9 @@ public final class DiscoveryEventUtils { } } + /** + * Event to signal that the list should be populated. + */ public static final class PopulateDomainTabsEvent { private final String domain; diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.form b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.form index c7ca652303..d7a9ff9b6c 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.form +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.form @@ -17,6 +17,11 @@ + + + + + @@ -27,9 +32,13 @@ + + + + diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java index 7098cdbcbc..1d2a92a5e5 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java @@ -30,43 +30,84 @@ import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.TskCoreException; -public class ArtifactsListPanel extends JPanel { +/** + * Panel to display list of artifacts for selected domain. + * + */ +class ArtifactsListPanel extends JPanel { private static final long serialVersionUID = 1L; private final DomainArtifactTableModel tableModel = new DomainArtifactTableModel(); /** - * Creates new form ArtifactsListPanel + * Creates new form ArtifactsListPanel. */ - public ArtifactsListPanel() { + ArtifactsListPanel() { initComponents(); } - public void addSelectionListener(ListSelectionListener listener) { + /** + * Add a listener to the table of artifacts to perform actions when an + * artifact is selected. + * + * @param listener The listener to add to the table of artifacts. + */ + void addSelectionListener(ListSelectionListener listener) { jTable1.getSelectionModel().addListSelectionListener(listener); } - public void removeListSelectionListener(ListSelectionListener listener) { + /** + * Remove a listener from the table of artifacts. + * + * @param listener The listener to remove from the table of artifacts. + */ + void removeListSelectionListener(ListSelectionListener listener) { jTable1.getSelectionModel().removeListSelectionListener(listener); } - public BlackboardArtifact getSelectedArtifact() { - return ((DomainArtifactTableModel) jTable1.getModel()).getArtifactByRow(jTable1.getSelectionModel().getLeadSelectionIndex()); + /** + * The artifact which is currently selected, null if no artifact is + * selected. + * + * @return The currently selected BlackboardArtifact or null if none is + * selected. + */ + BlackboardArtifact getSelectedArtifact() { + int selectedIndex = jTable1.getSelectionModel().getLeadSelectionIndex(); + if (selectedIndex < 0 || jTable1.getSelectionModel().getMaxSelectionIndex() < 0 || selectedIndex >= jTable1.getSelectionModel().getMaxSelectionIndex()) { + return null; + } + return tableModel.getArtifactByRow(selectedIndex); } - public boolean isEmpty() { + /** + * Whether the list of artifacts is empty. + * + * @return true if the list of artifacts is empty, false if there are + * artifacts. + */ + boolean isEmpty() { return tableModel.getRowCount() <= 0; } - public void addArtifacts(List artifactList) { + /** + * Add the specified list of artifacts to the list of artifacts which should + * be displayed. + * + * @param artifactList + */ + void addArtifacts(List artifactList) { tableModel.setContents(artifactList); jTable1.validate(); jTable1.repaint(); tableModel.fireTableDataChanged(); } - public void clearArtifacts() { + /** + * Remove all artifacts from the list of artifacts displayed. + */ + void clearArtifacts() { tableModel.setContents(new ArrayList<>()); tableModel.fireTableDataChanged(); } @@ -84,25 +125,38 @@ public class ArtifactsListPanel extends JPanel { setLayout(new java.awt.BorderLayout()); + jScrollPane1.setPreferredSize(null); + + jTable1.setAutoCreateRowSorter(true); jTable1.setModel(tableModel); + jTable1.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION); jScrollPane1.setViewportView(jTable1); add(jScrollPane1, java.awt.BorderLayout.PAGE_START); }// //GEN-END:initComponents - void addListener(ListSelectionListener listSelectionListener) { - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. - } - + /** + * Table model which allows the artifact table in this panel to mimic a list + * of artifacts. + */ private class DomainArtifactTableModel extends AbstractTableModel { private static final long serialVersionUID = 1L; private final List artifactList = new ArrayList<>(); + /** + * Construct a new DomainArtifactTableModel. + */ DomainArtifactTableModel() { //No arg constructor to create empty model } + /** + * Set the list of artifacts which should be represented by this table + * model. + * + * @param artifacts The list of BlackboardArtifacts to represent. + */ void setContents(List artifacts) { artifactList.clear(); artifactList.addAll(artifacts); @@ -118,7 +172,14 @@ public class ArtifactsListPanel extends JPanel { return 2; } - public BlackboardArtifact getArtifactByRow(int rowIndex) { + /** + * Get the BlackboardArtifact at the specified row. + * + * @param rowIndex The row the artifact to return is at. + * + * @return The BlackboardArtifact at the specified row. + */ + BlackboardArtifact getArtifactByRow(int rowIndex) { return artifactList.get(rowIndex); } diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/discovery/ui/Bundle.properties-MERGED index bfe0cc5d8a..470ddd99a2 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/Bundle.properties-MERGED @@ -1,5 +1,6 @@ ArtifactsListPanel.dateColumn.name=Date/Time ArtifactsListPanel.titleColumn.name=Title +ArtifactsListPanel.value.noValue=No value available. ArtifactTypeFilterPanel.selectionNeeded.text=At least one Result type must be selected. CTL_OpenDiscoveryAction=Discovery DataSourceFilterPanel.error.text=At least one data source must be selected. @@ -148,3 +149,7 @@ VideoThumbnailPanel.nameLabel.more.text=\ and {0} more # {1} - units VideoThumbnailPanel.sizeLabel.text=Size: {0} {1} VideoThumbnailPanel.terraBytes.text=TB +WebHistoryDetailsPanel.details.attrHeader=Attributes +WebHistoryDetailsPanel.details.dataSource=Data Source +WebHistoryDetailsPanel.details.file=File +WebHistoryDetailsPanel.details.sourceHeader=Source diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.java index 8eece4ce1d..a337e61944 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.java @@ -20,6 +20,7 @@ package org.sleuthkit.autopsy.discovery.ui; import com.google.common.eventbus.Subscribe; import javax.swing.JPanel; +import javax.swing.JScrollPane; import javax.swing.SwingUtilities; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; @@ -27,7 +28,10 @@ import org.sleuthkit.autopsy.contentviewers.artifactviewers.DefaultArtifactConte import org.sleuthkit.autopsy.discovery.search.DiscoveryEventUtils; import org.sleuthkit.datamodel.BlackboardArtifact; -public final class DomainArtifactsTabPanel extends JPanel { +/** + * JPanel which should be used as a tab in the domain artifacts details area. + */ +final class DomainArtifactsTabPanel extends JPanel { private static final long serialVersionUID = 1L; private final ArtifactsListPanel listPanel = new ArtifactsListPanel(); @@ -47,11 +51,12 @@ public final class DomainArtifactsTabPanel extends JPanel { /** * Creates new form CookiesPanel */ - public DomainArtifactsTabPanel(BlackboardArtifact.ARTIFACT_TYPE artifactType) { + DomainArtifactsTabPanel(BlackboardArtifact.ARTIFACT_TYPE artifactType) { initComponents(); this.artifactType = artifactType; jSplitPane1.setLeftComponent(listPanel); setRightComponent(); + listPanel.addSelectionListener(listener); } private void setRightComponent() { @@ -70,7 +75,7 @@ public final class DomainArtifactsTabPanel extends JPanel { break; } if (rightPanel != null) { - jSplitPane1.setRightComponent(rightPanel); + jSplitPane1.setRightComponent(new JScrollPane(rightPanel)); } } @@ -86,21 +91,16 @@ public final class DomainArtifactsTabPanel extends JPanel { void handleArtifactListRetrievedEvent(DiscoveryEventUtils.ArtifactListRetrievedEvent artifactListEvent) { SwingUtilities.invokeLater(() -> { if (artifactType == artifactListEvent.getArtifactType()) { - if (artifactListEvent.getListOfArtifacts().isEmpty()) { - listPanel.clearArtifacts(); - setEnabled(false); - } else { - setEnabled(true); - listPanel.removeListSelectionListener(listener); - listPanel.addArtifacts(artifactListEvent.getListOfArtifacts()); - listPanel.addSelectionListener(listener); - } + listPanel.removeListSelectionListener(listener); + listPanel.addArtifacts(artifactListEvent.getListOfArtifacts()); + listPanel.addSelectionListener(listener); try { DiscoveryEventUtils.getDiscoveryEventBus().unregister(this); } catch (IllegalArgumentException notRegistered) { // attempting to remove a tab that was never registered } status = ARTIFACT_RETRIEVAL_STATUS.POPULATED; + setEnabled(!listPanel.isEmpty()); validate(); repaint(); } @@ -131,7 +131,10 @@ public final class DomainArtifactsTabPanel extends JPanel { private javax.swing.JSplitPane jSplitPane1; // End of variables declaration//GEN-END:variables - public enum ARTIFACT_RETRIEVAL_STATUS { + /** + * Enum to keep track of the populated state of this panel. + */ + enum ARTIFACT_RETRIEVAL_STATUS { UNPOPULATED(), POPULATING(), POPULATED(); diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/ResultsPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/ResultsPanel.java index 4c958d2c61..01981127e4 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/ResultsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/ResultsPanel.java @@ -20,7 +20,6 @@ package org.sleuthkit.autopsy.discovery.ui; import org.sleuthkit.autopsy.discovery.search.AbstractFilter; import com.google.common.eventbus.Subscribe; -import java.awt.Component; import java.awt.Cursor; import java.awt.Image; import java.awt.event.ItemEvent; @@ -33,8 +32,6 @@ import javax.swing.DefaultComboBoxModel; import javax.swing.JOptionPane; import javax.swing.SwingUtilities; import javax.swing.SwingWorker; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/WebHistoryDetailsPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/WebHistoryDetailsPanel.java index 9226f85b96..b7c7cee2fd 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/WebHistoryDetailsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/WebHistoryDetailsPanel.java @@ -1,20 +1,7 @@ /* - * Autopsy - * - * Copyright 2020 Basis Technology Corp. - * Contact: carrier sleuthkit org - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. */ package org.sleuthkit.autopsy.discovery.ui; @@ -25,6 +12,7 @@ import java.util.ArrayList; import java.util.List; import javax.swing.JScrollPane; import org.openide.util.Exceptions; +import org.openide.util.NbBundle; import org.openide.util.lookup.ServiceProvider; import org.sleuthkit.autopsy.contentviewers.artifactviewers.ArtifactContentViewer; import org.sleuthkit.autopsy.contentviewers.artifactviewers.CommunicationArtifactViewerHelper; @@ -48,6 +36,7 @@ public class WebHistoryDetailsPanel extends AbstractArtifactDetailsPanel impleme private final List artifactAttributesList = new ArrayList<>(); private final GridBagConstraints gridBagConstraints = new GridBagConstraints(); private String dataSourceName; + private String sourceFileName; /** * Creates new form WebHistoryDetailsPanel. @@ -58,18 +47,17 @@ public class WebHistoryDetailsPanel extends AbstractArtifactDetailsPanel impleme @Override public void setArtifact(BlackboardArtifact artifact) { - resetComponent(); if (artifact != null) { - try { extractArtifactData(artifact); } catch (TskCoreException ex) { Exceptions.printStackTrace(ex); } updateView(); - } + } else { + } this.setLayout(this.gridBagLayout); this.revalidate(); this.repaint(); @@ -85,15 +73,6 @@ public class WebHistoryDetailsPanel extends AbstractArtifactDetailsPanel impleme private void extractArtifactData(BlackboardArtifact artifact) throws TskCoreException { webHistoryArtifact = artifact; - - urlList.clear(); - dateAccessedList.clear(); - referrerUrlList.clear(); - titleList.clear(); - programNameList.clear(); - domainList.clear(); - otherList.clear(); - artifactAttributesList.clear(); artifactAttributesList.addAll(webHistoryArtifact.getAttributes()); // Get all the attributes and group them by the section panels they go in for (BlackboardAttribute bba : artifactAttributesList) { @@ -112,13 +91,16 @@ public class WebHistoryDetailsPanel extends AbstractArtifactDetailsPanel impleme } else { otherList.add(bba); } - + } dataSourceName = webHistoryArtifact.getDataSource().getName(); + sourceFileName = webHistoryArtifact.getParent().getName(); } private void resetComponent() { + // clear the panel + this.removeAll(); gridBagConstraints.anchor = GridBagConstraints.FIRST_LINE_START; gridBagConstraints.gridy = 0; gridBagConstraints.gridx = 0; @@ -128,16 +110,16 @@ public class WebHistoryDetailsPanel extends AbstractArtifactDetailsPanel impleme gridBagConstraints.fill = GridBagConstraints.NONE; webHistoryArtifact = null; dataSourceName = null; + sourceFileName = null; urlList.clear(); dateAccessedList.clear(); referrerUrlList.clear(); titleList.clear(); programNameList.clear(); domainList.clear(); + otherList.clear(); artifactAttributesList.clear(); - // clear the panel - this.removeAll(); - this.setLayout(null); + } @Override @@ -152,6 +134,10 @@ public class WebHistoryDetailsPanel extends AbstractArtifactDetailsPanel impleme && (artifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY.getTypeID()); } + @NbBundle.Messages({"WebHistoryDetailsPanel.details.attrHeader=Attributes", + "WebHistoryDetailsPanel.details.sourceHeader=Source", + "WebHistoryDetailsPanel.details.dataSource=Data Source", + "WebHistoryDetailsPanel.details.file=File"}) /** * This method is called from within the constructor to initialize the form. * WARNING: Do NOT modify this code. The content of this method is always @@ -174,12 +160,11 @@ public class WebHistoryDetailsPanel extends AbstractArtifactDetailsPanel impleme }// //GEN-END:initComponents private void updateView() { - CommunicationArtifactViewerHelper.addHeader(this, gridBagLayout, gridBagConstraints, "Attributes"); + CommunicationArtifactViewerHelper.addHeader(this, gridBagLayout, gridBagConstraints, Bundle.WebHistoryDetailsPanel_details_attrHeader()); for (BlackboardAttribute bba : this.titleList) { CommunicationArtifactViewerHelper.addRow(this, gridBagLayout, gridBagConstraints, bba.getAttributeType().getDisplayName(), bba.getDisplayString()); } -// CommunicationArtifactViewerHelper.addHeader(this, gridBagLayout, gridBagConstraints, sectionHeader); for (BlackboardAttribute bba : dateAccessedList) { CommunicationArtifactViewerHelper.addRow(this, gridBagLayout, gridBagConstraints, bba.getAttributeType().getDisplayName(), bba.getDisplayString()); } @@ -198,8 +183,9 @@ public class WebHistoryDetailsPanel extends AbstractArtifactDetailsPanel impleme for (BlackboardAttribute bba : otherList) { CommunicationArtifactViewerHelper.addRow(this, gridBagLayout, gridBagConstraints, bba.getAttributeType().getDisplayName(), bba.getDisplayString()); } - CommunicationArtifactViewerHelper.addHeader(this, gridBagLayout, gridBagConstraints, "Source"); - CommunicationArtifactViewerHelper.addRow(this, gridBagLayout, gridBagConstraints, "Data Source", dataSourceName); + CommunicationArtifactViewerHelper.addHeader(this, gridBagLayout, gridBagConstraints, Bundle.WebHistoryDetailsPanel_details_sourceHeader()); + CommunicationArtifactViewerHelper.addRow(this, gridBagLayout, gridBagConstraints, Bundle.WebHistoryDetailsPanel_details_dataSource(), dataSourceName); + CommunicationArtifactViewerHelper.addRow(this, gridBagLayout, gridBagConstraints, Bundle.WebHistoryDetailsPanel_details_file(), sourceFileName); // add veritcal glue at the end CommunicationArtifactViewerHelper.addPageEndGlue(this, gridBagLayout, this.gridBagConstraints); } From 240ab041134eabb9ac968d3920023801bc9a051d Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Fri, 23 Oct 2020 09:48:59 -0400 Subject: [PATCH 05/81] 6773 changes to artifact Viewers --- .../CommunicationArtifactViewerHelper.java | 11 ++++++++--- .../artifactviewers/DefaultArtifactContentViewer.java | 3 ++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/CommunicationArtifactViewerHelper.java b/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/CommunicationArtifactViewerHelper.java index a911ac20d7..dd63606b05 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/CommunicationArtifactViewerHelper.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/CommunicationArtifactViewerHelper.java @@ -44,7 +44,7 @@ import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository; * A class to help display a communication artifact in a panel using a * gridbaglayout. */ -final class CommunicationArtifactViewerHelper { +public final class CommunicationArtifactViewerHelper { // Number of columns in the gridbag layout. private final static int MAX_COLS = 4; @@ -68,7 +68,7 @@ final class CommunicationArtifactViewerHelper { * * @return JLabel Heading label added. */ - static JLabel addHeader(JPanel panel, GridBagLayout gridbagLayout, GridBagConstraints constraints, String headerString) { + public static JLabel addHeader(JPanel panel, GridBagLayout gridbagLayout, GridBagConstraints constraints, String headerString) { Insets savedInsets = constraints.insets; @@ -109,6 +109,11 @@ final class CommunicationArtifactViewerHelper { return headingLabel; } + public static void addRow(JPanel panel, GridBagLayout gridbagLayout, GridBagConstraints constraints, String keyString, String valueString) { + addKey(panel, gridbagLayout, constraints, keyString); + addValue(panel, gridbagLayout, constraints, valueString); + } + /** * Adds the given component to the panel. * @@ -161,7 +166,7 @@ final class CommunicationArtifactViewerHelper { * @param gridbagLayout Layout to use. * @param constraints Constrains to use. */ - static void addPageEndGlue(JPanel panel, GridBagLayout gridbagLayout, GridBagConstraints constraints) { + public static void addPageEndGlue(JPanel panel, GridBagLayout gridbagLayout, GridBagConstraints constraints) { constraints.gridx = 0; diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/DefaultArtifactContentViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/DefaultArtifactContentViewer.java index 8c0c89a865..799993ceee 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/DefaultArtifactContentViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/DefaultArtifactContentViewer.java @@ -54,6 +54,7 @@ import com.google.gson.JsonArray; import java.util.Locale; import java.util.Map; import javax.swing.SwingUtilities; +import org.sleuthkit.autopsy.discovery.ui.AbstractArtifactDetailsPanel; //import org.sleuthkit.autopsy.contentviewers.Bundle; /** @@ -62,7 +63,7 @@ import javax.swing.SwingUtilities; */ @SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives -public class DefaultArtifactContentViewer extends javax.swing.JPanel implements ArtifactContentViewer { +public class DefaultArtifactContentViewer extends AbstractArtifactDetailsPanel implements ArtifactContentViewer { @NbBundle.Messages({ "DefaultArtifactContentViewer.attrsTableHeader.type=Type", From d649931c369f66432160ca77f2a3879bb8945350 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Fri, 23 Oct 2020 09:59:40 -0400 Subject: [PATCH 06/81] 6773 fix unselection again and refactor method name --- .../CommunicationArtifactViewerHelper.java | 16 ++++++++++++++-- .../discovery/ui/ArtifactsListPanel.java | 2 +- .../discovery/ui/WebHistoryDetailsPanel.java | 18 +++++++++--------- 3 files changed, 24 insertions(+), 12 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/CommunicationArtifactViewerHelper.java b/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/CommunicationArtifactViewerHelper.java index dd63606b05..ebee74ada2 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/CommunicationArtifactViewerHelper.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/CommunicationArtifactViewerHelper.java @@ -109,7 +109,19 @@ public final class CommunicationArtifactViewerHelper { return headingLabel; } - public static void addRow(JPanel panel, GridBagLayout gridbagLayout, GridBagConstraints constraints, String keyString, String valueString) { + /** + * Add a key value row to the specified panel with the specified layout and + * constraints. + * + * + * @param panel Panel to update. + * @param gridbagLayout Layout to use. + * @param constraints Constrains to use. + * @param keyString Key name to display. + * @param valueString Value string to display. + * + */ + public static void addNameValueRow(JPanel panel, GridBagLayout gridbagLayout, GridBagConstraints constraints, String keyString, String valueString) { addKey(panel, gridbagLayout, constraints, keyString); addValue(panel, gridbagLayout, constraints, valueString); } @@ -252,7 +264,7 @@ public final class CommunicationArtifactViewerHelper { * @param panel Panel to update. * @param gridbagLayout Layout to use. * @param constraints Constrains to use. - * @param keyString Value string to display. + * @param valueString Value string to display. * * @return Label added. */ diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java index 1d2a92a5e5..8a003e7eb2 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java @@ -75,7 +75,7 @@ class ArtifactsListPanel extends JPanel { */ BlackboardArtifact getSelectedArtifact() { int selectedIndex = jTable1.getSelectionModel().getLeadSelectionIndex(); - if (selectedIndex < 0 || jTable1.getSelectionModel().getMaxSelectionIndex() < 0 || selectedIndex >= jTable1.getSelectionModel().getMaxSelectionIndex()) { + if (selectedIndex < jTable1.getSelectionModel().getMinSelectionIndex() || jTable1.getSelectionModel().getMaxSelectionIndex() < 0 || selectedIndex > jTable1.getSelectionModel().getMaxSelectionIndex()) { return null; } return tableModel.getArtifactByRow(selectedIndex); diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/WebHistoryDetailsPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/WebHistoryDetailsPanel.java index b7c7cee2fd..0aee1e4e62 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/WebHistoryDetailsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/WebHistoryDetailsPanel.java @@ -163,29 +163,29 @@ public class WebHistoryDetailsPanel extends AbstractArtifactDetailsPanel impleme CommunicationArtifactViewerHelper.addHeader(this, gridBagLayout, gridBagConstraints, Bundle.WebHistoryDetailsPanel_details_attrHeader()); for (BlackboardAttribute bba : this.titleList) { - CommunicationArtifactViewerHelper.addRow(this, gridBagLayout, gridBagConstraints, bba.getAttributeType().getDisplayName(), bba.getDisplayString()); + CommunicationArtifactViewerHelper.addNameValueRow(this, gridBagLayout, gridBagConstraints, bba.getAttributeType().getDisplayName(), bba.getDisplayString()); } for (BlackboardAttribute bba : dateAccessedList) { - CommunicationArtifactViewerHelper.addRow(this, gridBagLayout, gridBagConstraints, bba.getAttributeType().getDisplayName(), bba.getDisplayString()); + CommunicationArtifactViewerHelper.addNameValueRow(this, gridBagLayout, gridBagConstraints, bba.getAttributeType().getDisplayName(), bba.getDisplayString()); } for (BlackboardAttribute bba : domainList) { - CommunicationArtifactViewerHelper.addRow(this, gridBagLayout, gridBagConstraints, bba.getAttributeType().getDisplayName(), bba.getDisplayString()); + CommunicationArtifactViewerHelper.addNameValueRow(this, gridBagLayout, gridBagConstraints, bba.getAttributeType().getDisplayName(), bba.getDisplayString()); } for (BlackboardAttribute bba : urlList) { - CommunicationArtifactViewerHelper.addRow(this, gridBagLayout, gridBagConstraints, bba.getAttributeType().getDisplayName(), bba.getDisplayString()); + CommunicationArtifactViewerHelper.addNameValueRow(this, gridBagLayout, gridBagConstraints, bba.getAttributeType().getDisplayName(), bba.getDisplayString()); } for (BlackboardAttribute bba : referrerUrlList) { - CommunicationArtifactViewerHelper.addRow(this, gridBagLayout, gridBagConstraints, bba.getAttributeType().getDisplayName(), bba.getDisplayString()); + CommunicationArtifactViewerHelper.addNameValueRow(this, gridBagLayout, gridBagConstraints, bba.getAttributeType().getDisplayName(), bba.getDisplayString()); } for (BlackboardAttribute bba : programNameList) { - CommunicationArtifactViewerHelper.addRow(this, gridBagLayout, gridBagConstraints, bba.getAttributeType().getDisplayName(), bba.getDisplayString()); + CommunicationArtifactViewerHelper.addNameValueRow(this, gridBagLayout, gridBagConstraints, bba.getAttributeType().getDisplayName(), bba.getDisplayString()); } for (BlackboardAttribute bba : otherList) { - CommunicationArtifactViewerHelper.addRow(this, gridBagLayout, gridBagConstraints, bba.getAttributeType().getDisplayName(), bba.getDisplayString()); + CommunicationArtifactViewerHelper.addNameValueRow(this, gridBagLayout, gridBagConstraints, bba.getAttributeType().getDisplayName(), bba.getDisplayString()); } CommunicationArtifactViewerHelper.addHeader(this, gridBagLayout, gridBagConstraints, Bundle.WebHistoryDetailsPanel_details_sourceHeader()); - CommunicationArtifactViewerHelper.addRow(this, gridBagLayout, gridBagConstraints, Bundle.WebHistoryDetailsPanel_details_dataSource(), dataSourceName); - CommunicationArtifactViewerHelper.addRow(this, gridBagLayout, gridBagConstraints, Bundle.WebHistoryDetailsPanel_details_file(), sourceFileName); + CommunicationArtifactViewerHelper.addNameValueRow(this, gridBagLayout, gridBagConstraints, Bundle.WebHistoryDetailsPanel_details_dataSource(), dataSourceName); + CommunicationArtifactViewerHelper.addNameValueRow(this, gridBagLayout, gridBagConstraints, Bundle.WebHistoryDetailsPanel_details_file(), sourceFileName); // add veritcal glue at the end CommunicationArtifactViewerHelper.addPageEndGlue(this, gridBagLayout, this.gridBagConstraints); } From 4168cb1c49f261d36f3f3d4464b85d3c4e9cecb8 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Fri, 23 Oct 2020 10:19:07 -0400 Subject: [PATCH 07/81] 6773 clean up comments --- .../discovery/search/DiscoveryEventUtils.java | 12 ++++++-- .../ui/AbstractArtifactDetailsPanel.java | 4 +++ .../autopsy/discovery/ui/ArtifactsWorker.java | 17 +++++++---- .../discovery/ui/DomainArtifactsTabPanel.form | 1 + .../discovery/ui/DomainArtifactsTabPanel.java | 20 ++++++++++++- .../discovery/ui/DomainDetailsPanel.java | 13 +++++++-- .../discovery/ui/WebHistoryDetailsPanel.java | 28 +++++++++++++++++-- 7 files changed, 82 insertions(+), 13 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/discovery/search/DiscoveryEventUtils.java b/Core/src/org/sleuthkit/autopsy/discovery/search/DiscoveryEventUtils.java index 2992c37a80..4171dc989c 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/search/DiscoveryEventUtils.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/search/DiscoveryEventUtils.java @@ -126,7 +126,7 @@ public final class DiscoveryEventUtils { } } - /** + /** * Event to signal that the list should be populated. */ public static final class PopulateDomainTabsEvent { @@ -238,8 +238,11 @@ public final class DiscoveryEventUtils { private final BlackboardArtifact.ARTIFACT_TYPE artifactType; /** + * Construct a new ArtifactListRetrievedEvent with a list of specified + * artifacts and an artifact type. * - * @param listOfArtifacts + * @param artifactType The type of artifacts in the list. + * @param listOfArtifacts The list of artifacts retrieved. */ public ArtifactListRetrievedEvent(BlackboardArtifact.ARTIFACT_TYPE artifactType, List listOfArtifacts) { if (listOfArtifacts != null) { @@ -248,6 +251,11 @@ public final class DiscoveryEventUtils { this.artifactType = artifactType; } + /** + * Get the list of artifacts included in the event. + * + * @return The list of artifacts retrieved. + */ public List getListOfArtifacts() { return Collections.unmodifiableList(listOfArtifacts); } diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/AbstractArtifactDetailsPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/AbstractArtifactDetailsPanel.java index 57d7029e3d..1be1324300 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/AbstractArtifactDetailsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/AbstractArtifactDetailsPanel.java @@ -21,6 +21,10 @@ package org.sleuthkit.autopsy.discovery.ui; import javax.swing.JPanel; import org.sleuthkit.datamodel.BlackboardArtifact; +/** + * Class for ensuring all ArtifactDetailsPanels have a setArtifact method. + * + */ public abstract class AbstractArtifactDetailsPanel extends JPanel { private static final long serialVersionUID = 1L; diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsWorker.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsWorker.java index bf2b3ee2cb..a16edcb45c 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsWorker.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsWorker.java @@ -31,17 +31,26 @@ import org.sleuthkit.autopsy.discovery.search.DomainSearch; import org.sleuthkit.autopsy.discovery.search.DomainSearchArtifactsRequest; import org.sleuthkit.datamodel.BlackboardArtifact; -public class ArtifactsWorker extends SwingWorker, Void> { +/** + * SwingWorker to retrieve a list of artifacts for a specified type and domain. + */ +class ArtifactsWorker extends SwingWorker, Void> { private BlackboardArtifact.ARTIFACT_TYPE artifactType = null; private final static Logger logger = Logger.getLogger(ArtifactsWorker.class.getName()); private final String domain; - ArtifactsWorker(BlackboardArtifact.ARTIFACT_TYPE artifactType, String domain){ + /** + * Construct a new ArtifactsWorker. + * + * @param artifactType The type of artifact being retrieved. + * @param domain The domain the artifacts should have as an attribute. + */ + ArtifactsWorker(BlackboardArtifact.ARTIFACT_TYPE artifactType, String domain) { this.artifactType = artifactType; this.domain = domain; } - + @Override protected List doInBackground() throws Exception { if (artifactType != null && !StringUtils.isBlank(domain)) { @@ -51,8 +60,6 @@ public class ArtifactsWorker extends SwingWorker, Void> return new ArrayList<>(); } - - @Override protected void done() { List listOfArtifacts = new ArrayList<>(); diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.form b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.form index 80cfa517c7..1e93e06f86 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.form +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.form @@ -11,6 +11,7 @@ + diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.java index a337e61944..d2cf6054a0 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.java @@ -59,8 +59,11 @@ final class DomainArtifactsTabPanel extends JPanel { listPanel.addSelectionListener(listener); } + /** + * Set the right component of the tab panel, which will display the details + * for the artifact. + */ private void setRightComponent() { - switch (artifactType) { case TSK_WEB_HISTORY: rightPanel = new WebHistoryDetailsPanel(); @@ -79,10 +82,20 @@ final class DomainArtifactsTabPanel extends JPanel { } } + /** + * Get the status of the panel which indicates if it is populated. + * + * @return The ARTIFACT_RETRIEVAL_STATUS of the panel. + */ ARTIFACT_RETRIEVAL_STATUS getStatus() { return status; } + /** + * Manually set the status of the panel. + * + * @param status The ARTIFACT_RETRIEVAL_STATUS of the panel. + */ void setStatus(ARTIFACT_RETRIEVAL_STATUS status) { this.status = status; } @@ -107,6 +120,11 @@ final class DomainArtifactsTabPanel extends JPanel { }); } + /** + * Get the type of Artifact the panel exists for. + * + * @return The ARTIFACT_TYPE of the BlackboardArtifact being displayed. + */ BlackboardArtifact.ARTIFACT_TYPE getArtifactType() { return artifactType; } diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.java index 639713d1a1..42bf146a92 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.java @@ -29,7 +29,6 @@ import org.sleuthkit.autopsy.discovery.search.DiscoveryEventUtils; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.autopsy.discovery.search.SearchData; - final class DomainDetailsPanel extends JPanel { private static final long serialVersionUID = 1L; @@ -45,11 +44,14 @@ final class DomainDetailsPanel extends JPanel { addArtifactTabs(); } + /** + * Add the tabs for each of the artifact types which we will be displaying. + */ private void addArtifactTabs() { for (BlackboardArtifact.ARTIFACT_TYPE type : SearchData.Type.DOMAIN.getArtifactTypes()) { DomainArtifactsTabPanel newTab = new DomainArtifactsTabPanel(type); jTabbedPane1.add(type.getDisplayName(), newTab); - if (!StringUtils.isBlank(selectedTabName) && type.getDisplayName().equals(selectedTabName) && newTab.isEnabled()) { + if (!StringUtils.isBlank(selectedTabName)) { jTabbedPane1.setSelectedComponent(newTab); } } @@ -67,6 +69,10 @@ final class DomainDetailsPanel extends JPanel { }); } + /** + * Run the worker which retrieves the list of artifacts for the domain to + * populate the details area. + */ private void runDomainWorker() { SwingUtilities.invokeLater(() -> { Component selectedComponent = jTabbedPane1.getSelectedComponent(); @@ -85,6 +91,9 @@ final class DomainDetailsPanel extends JPanel { }); } + /** + * Clear the tabs of any previous content. + */ private void clearTabs() { int tabCount = jTabbedPane1.getTabCount(); // We invoke removeTabAt for each tab, otherwise we may end up diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/WebHistoryDetailsPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/WebHistoryDetailsPanel.java index 0aee1e4e62..c0d61bc7ec 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/WebHistoryDetailsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/WebHistoryDetailsPanel.java @@ -1,7 +1,20 @@ /* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. + * Autopsy + * + * Copyright 2020 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.sleuthkit.autopsy.discovery.ui; @@ -20,6 +33,9 @@ import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.TskCoreException; +/** + * Panel to display the details for a Web History Artifact. + */ @ServiceProvider(service = ArtifactContentViewer.class) public class WebHistoryDetailsPanel extends AbstractArtifactDetailsPanel implements ArtifactContentViewer { @@ -98,6 +114,9 @@ public class WebHistoryDetailsPanel extends AbstractArtifactDetailsPanel impleme sourceFileName = webHistoryArtifact.getParent().getName(); } + /** + * Reset the panel so that it is empty. + */ private void resetComponent() { // clear the panel this.removeAll(); @@ -159,6 +178,9 @@ public class WebHistoryDetailsPanel extends AbstractArtifactDetailsPanel impleme ); }// //GEN-END:initComponents + /** + * Update the view to reflect the current artifacts details. + */ private void updateView() { CommunicationArtifactViewerHelper.addHeader(this, gridBagLayout, gridBagConstraints, Bundle.WebHistoryDetailsPanel_details_attrHeader()); From 421b5972977784d5420cd76ae667bb997ef23e14 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Fri, 23 Oct 2020 10:48:23 -0400 Subject: [PATCH 08/81] 6774 add content viewer artifact details area for downloads and cache artifacts --- .../ui/ContentViewerDetailsPanel.form | 17 ++++++ .../ui/ContentViewerDetailsPanel.java | 53 +++++++++++++++++++ .../discovery/ui/DomainArtifactsTabPanel.java | 4 ++ 3 files changed, 74 insertions(+) create mode 100644 Core/src/org/sleuthkit/autopsy/discovery/ui/ContentViewerDetailsPanel.form create mode 100644 Core/src/org/sleuthkit/autopsy/discovery/ui/ContentViewerDetailsPanel.java diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/ContentViewerDetailsPanel.form b/Core/src/org/sleuthkit/autopsy/discovery/ui/ContentViewerDetailsPanel.form new file mode 100644 index 0000000000..ec22ddd1a6 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/ContentViewerDetailsPanel.form @@ -0,0 +1,17 @@ + + +
+ + + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/ContentViewerDetailsPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/ContentViewerDetailsPanel.java new file mode 100644 index 0000000000..a2ee50a775 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/ContentViewerDetailsPanel.java @@ -0,0 +1,53 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.sleuthkit.autopsy.discovery.ui; + +import org.openide.nodes.Node; +import org.sleuthkit.autopsy.corecomponents.DataContentPanel; +import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode; +import org.sleuthkit.datamodel.BlackboardArtifact; + +/** + * Details panel for displaying the collection of content viewers. + */ +class ContentViewerDetailsPanel extends AbstractArtifactDetailsPanel { + + private static final long serialVersionUID = 1L; + private final DataContentPanel contentViewer = DataContentPanel.createInstance(); + + /** + * Creates new form ContentViewerDetailsPanel + */ + ContentViewerDetailsPanel() { + initComponents(); + add(contentViewer); + } + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + setLayout(new java.awt.BorderLayout()); + }// //GEN-END:initComponents + + @Override + public void setArtifact(BlackboardArtifact artifact) { + Node node = Node.EMPTY; + if (artifact != null) { + node = new BlackboardArtifactNode(artifact); + } + contentViewer.setNode(node); + } + + + // Variables declaration - do not modify//GEN-BEGIN:variables + // End of variables declaration//GEN-END:variables +} diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.java index d2cf6054a0..3767321e11 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.java @@ -71,8 +71,12 @@ final class DomainArtifactsTabPanel extends JPanel { case TSK_WEB_COOKIE: case TSK_WEB_SEARCH_QUERY: case TSK_WEB_BOOKMARK: + rightPanel = new DefaultArtifactContentViewer(); + break; case TSK_WEB_DOWNLOAD: case TSK_WEB_CACHE: + rightPanel = new ContentViewerDetailsPanel(); + break; default: rightPanel = new DefaultArtifactContentViewer(); break; From 424fb9759989afb35b31b760a2c504be15c89c06 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Fri, 23 Oct 2020 12:31:30 -0400 Subject: [PATCH 09/81] 6773 codacy clean up --- .../discovery/ui/ArtifactsListPanel.form | 9 ++++----- .../discovery/ui/ArtifactsListPanel.java | 11 +++-------- .../autopsy/discovery/ui/ArtifactsWorker.java | 2 +- .../discovery/ui/DomainArtifactsTabPanel.java | 18 +++++++++++------- .../discovery/ui/DomainDetailsPanel.java | 10 +++++++--- .../discovery/ui/WebHistoryDetailsPanel.java | 2 -- 6 files changed, 26 insertions(+), 26 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.form b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.form index d7a9ff9b6c..28dd667601 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.form +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.form @@ -17,11 +17,10 @@ - - - - - + + + + diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java index 8a003e7eb2..5fa50f44ee 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java @@ -120,13 +120,11 @@ class ArtifactsListPanel extends JPanel { // //GEN-BEGIN:initComponents private void initComponents() { - jScrollPane1 = new javax.swing.JScrollPane(); + javax.swing.JScrollPane jScrollPane1 = new javax.swing.JScrollPane(); jTable1 = new javax.swing.JTable(); setLayout(new java.awt.BorderLayout()); - jScrollPane1.setPreferredSize(null); - jTable1.setAutoCreateRowSorter(true); jTable1.setModel(tableModel); jTable1.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION); @@ -191,10 +189,6 @@ class ArtifactsListPanel extends JPanel { String otherDate = ""; try { for (BlackboardAttribute bba : getArtifactByRow(rowIndex).getAttributes()) { - if (bba.getAttributeType().getTypeName().startsWith("TSK_URL")) { - url = bba.getDisplayString(); - continue; - } switch (columnIndex) { case 0: if (bba.getAttributeType().getTypeName().startsWith("TSK_DATETIME_ACCESSED") && !StringUtils.isBlank(bba.getDisplayString())) { @@ -206,6 +200,8 @@ class ArtifactsListPanel extends JPanel { case 1: if (bba.getAttributeType().getTypeName().startsWith("TSK_TITLE") && !StringUtils.isBlank(bba.getDisplayString())) { returnValue = bba.getDisplayString(); + } else if (bba.getAttributeType().getTypeName().startsWith("TSK_URL") && !StringUtils.isBlank(bba.getDisplayString())) { + url = bba.getDisplayString(); } break; default: @@ -243,7 +239,6 @@ class ArtifactsListPanel extends JPanel { } // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.JScrollPane jScrollPane1; private javax.swing.JTable jTable1; // End of variables declaration//GEN-END:variables } diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsWorker.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsWorker.java index a16edcb45c..fb53ec95ac 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsWorker.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsWorker.java @@ -36,7 +36,7 @@ import org.sleuthkit.datamodel.BlackboardArtifact; */ class ArtifactsWorker extends SwingWorker, Void> { - private BlackboardArtifact.ARTIFACT_TYPE artifactType = null; + private final BlackboardArtifact.ARTIFACT_TYPE artifactType; private final static Logger logger = Logger.getLogger(ArtifactsWorker.class.getName()); private final String domain; diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.java index d2cf6054a0..e33ec8e14c 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.java @@ -19,12 +19,14 @@ package org.sleuthkit.autopsy.discovery.ui; import com.google.common.eventbus.Subscribe; +import java.util.logging.Level; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.SwingUtilities; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import org.sleuthkit.autopsy.contentviewers.artifactviewers.DefaultArtifactContentViewer; +import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.discovery.search.DiscoveryEventUtils; import org.sleuthkit.datamodel.BlackboardArtifact; @@ -34,11 +36,12 @@ import org.sleuthkit.datamodel.BlackboardArtifact; final class DomainArtifactsTabPanel extends JPanel { private static final long serialVersionUID = 1L; + private final static Logger logger = Logger.getLogger(DomainArtifactsTabPanel.class.getName()); private final ArtifactsListPanel listPanel = new ArtifactsListPanel(); private final BlackboardArtifact.ARTIFACT_TYPE artifactType; private AbstractArtifactDetailsPanel rightPanel = null; - private volatile ARTIFACT_RETRIEVAL_STATUS status = ARTIFACT_RETRIEVAL_STATUS.UNPOPULATED; + private volatile ArtifactRetrievalStatus status = ArtifactRetrievalStatus.UNPOPULATED; private final ListSelectionListener listener = new ListSelectionListener() { @Override public void valueChanged(ListSelectionEvent event) { @@ -85,18 +88,18 @@ final class DomainArtifactsTabPanel extends JPanel { /** * Get the status of the panel which indicates if it is populated. * - * @return The ARTIFACT_RETRIEVAL_STATUS of the panel. + * @return The ArtifactRetrievalStatuss of the panel. */ - ARTIFACT_RETRIEVAL_STATUS getStatus() { + ArtifactRetrievalStatus getStatus() { return status; } /** * Manually set the status of the panel. * - * @param status The ARTIFACT_RETRIEVAL_STATUS of the panel. + * @param status The ArtifactRetrievalStatus of the panel. */ - void setStatus(ARTIFACT_RETRIEVAL_STATUS status) { + void setStatus(ArtifactRetrievalStatus status) { this.status = status; } @@ -110,9 +113,10 @@ final class DomainArtifactsTabPanel extends JPanel { try { DiscoveryEventUtils.getDiscoveryEventBus().unregister(this); } catch (IllegalArgumentException notRegistered) { + logger.log(Level.INFO, "Attempting to unregister tab which was not registered"); // attempting to remove a tab that was never registered } - status = ARTIFACT_RETRIEVAL_STATUS.POPULATED; + status = ArtifactRetrievalStatus.POPULATED; setEnabled(!listPanel.isEmpty()); validate(); repaint(); @@ -152,7 +156,7 @@ final class DomainArtifactsTabPanel extends JPanel { /** * Enum to keep track of the populated state of this panel. */ - enum ARTIFACT_RETRIEVAL_STATUS { + enum ArtifactRetrievalStatus { UNPOPULATED(), POPULATING(), POPULATED(); diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.java index 42bf146a92..5e4c3597b2 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.java @@ -29,6 +29,10 @@ import org.sleuthkit.autopsy.discovery.search.DiscoveryEventUtils; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.autopsy.discovery.search.SearchData; +/** + * Panel to display details area for domain discovery results. + * + */ final class DomainDetailsPanel extends JPanel { private static final long serialVersionUID = 1L; @@ -76,13 +80,13 @@ final class DomainDetailsPanel extends JPanel { private void runDomainWorker() { SwingUtilities.invokeLater(() -> { Component selectedComponent = jTabbedPane1.getSelectedComponent(); - if (selectedComponent != null && selectedComponent instanceof DomainArtifactsTabPanel) { + if (selectedComponent instanceof DomainArtifactsTabPanel) { if (detailsWorker != null && !detailsWorker.isDone()) { detailsWorker.cancel(true); } DomainArtifactsTabPanel selectedTab = (DomainArtifactsTabPanel) selectedComponent; - if (selectedTab.getStatus() == DomainArtifactsTabPanel.ARTIFACT_RETRIEVAL_STATUS.UNPOPULATED) { - selectedTab.setStatus(DomainArtifactsTabPanel.ARTIFACT_RETRIEVAL_STATUS.POPULATING); + if (selectedTab.getStatus() == DomainArtifactsTabPanel.ArtifactRetrievalStatus.UNPOPULATED) { + selectedTab.setStatus(DomainArtifactsTabPanel.ArtifactRetrievalStatus.POPULATING); DiscoveryEventUtils.getDiscoveryEventBus().register(selectedTab); detailsWorker = new ArtifactsWorker(selectedTab.getArtifactType(), domain); detailsWorker.execute(); diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/WebHistoryDetailsPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/WebHistoryDetailsPanel.java index c0d61bc7ec..8965581720 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/WebHistoryDetailsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/WebHistoryDetailsPanel.java @@ -71,8 +71,6 @@ public class WebHistoryDetailsPanel extends AbstractArtifactDetailsPanel impleme Exceptions.printStackTrace(ex); } updateView(); - } else { - } this.setLayout(this.gridBagLayout); this.revalidate(); From 02d309b26d89be70fe3a34d8d4aca6ba9ee34595 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Fri, 23 Oct 2020 14:57:52 -0400 Subject: [PATCH 10/81] 6773 reduce npcomplexity of method for codacy --- .../discovery/ui/ArtifactsListPanel.java | 67 ++++++++++--------- 1 file changed, 36 insertions(+), 31 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java index 5fa50f44ee..6b23195480 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java @@ -20,12 +20,13 @@ package org.sleuthkit.autopsy.discovery.ui; import java.util.ArrayList; import java.util.List; +import java.util.logging.Level; import javax.swing.JPanel; import javax.swing.event.ListSelectionListener; import javax.swing.table.AbstractTableModel; import org.apache.commons.lang.StringUtils; -import org.openide.util.Exceptions; import org.openide.util.NbBundle; +import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.TskCoreException; @@ -38,6 +39,7 @@ class ArtifactsListPanel extends JPanel { private static final long serialVersionUID = 1L; private final DomainArtifactTableModel tableModel = new DomainArtifactTableModel(); + private static final Logger logger = Logger.getLogger(ArtifactsListPanel.class.getName()); /** * Creates new form ArtifactsListPanel. @@ -184,49 +186,52 @@ class ArtifactsListPanel extends JPanel { @NbBundle.Messages({"ArtifactsListPanel.value.noValue=No value available."}) @Override public Object getValueAt(int rowIndex, int columnIndex) { - Object returnValue = null; - String url = ""; - String otherDate = ""; try { for (BlackboardAttribute bba : getArtifactByRow(rowIndex).getAttributes()) { - switch (columnIndex) { - case 0: - if (bba.getAttributeType().getTypeName().startsWith("TSK_DATETIME_ACCESSED") && !StringUtils.isBlank(bba.getDisplayString())) { - returnValue = bba.getDisplayString(); - } else if (bba.getAttributeType().getTypeName().startsWith("TSK_DATETIME") && !StringUtils.isBlank(bba.getDisplayString())) { - otherDate = bba.getDisplayString(); - } - break; - case 1: - if (bba.getAttributeType().getTypeName().startsWith("TSK_TITLE") && !StringUtils.isBlank(bba.getDisplayString())) { - returnValue = bba.getDisplayString(); - } else if (bba.getAttributeType().getTypeName().startsWith("TSK_URL") && !StringUtils.isBlank(bba.getDisplayString())) { - url = bba.getDisplayString(); - } - break; - default: - break; + if (columnIndex == 0 && bba.getAttributeType().getTypeName().startsWith("TSK_DATETIME_ACCESSED") && !StringUtils.isBlank(bba.getDisplayString())) { + return bba.getDisplayString(); + } else if (columnIndex == 1 && bba.getAttributeType().getTypeName().startsWith("TSK_TITLE") && !StringUtils.isBlank(bba.getDisplayString())) { + return bba.getDisplayString(); } + } + return getFallbackValue(rowIndex, columnIndex); } catch (TskCoreException ex) { - Exceptions.printStackTrace(ex); + logger.log(Level.WARNING, "Error getting attributes for artifact " + getArtifactByRow(rowIndex).getArtifactID(), ex); + return Bundle.ArtifactsListPanel_value_noValue(); } - if (returnValue == null) { - if (columnIndex == 0 && !StringUtils.isBlank(otherDate)) { - returnValue = otherDate; - } else if (columnIndex == 1 && !StringUtils.isBlank(url)) { - returnValue = url; - } else { - returnValue = Bundle.ArtifactsListPanel_value_noValue(); + } + + /** + * Private helper method to use when the value we want for either date + * or title is not available. + * + * + * @param rowIndex The row the artifact to return is at. + * @param columnIndex The column index the attribute will be displayed + * at. + * + * @return A string that can be used in place of the accessed date time + * attribute title when they are not avaiable. + * + * @throws TskCoreException + */ + private String getFallbackValue(int rowIndex, int columnIndex) throws TskCoreException { + for (BlackboardAttribute bba : getArtifactByRow(rowIndex).getAttributes()) { + if (columnIndex == 0 && bba.getAttributeType().getTypeName().startsWith("TSK_DATETIME") && !StringUtils.isBlank(bba.getDisplayString())) { + return bba.getDisplayString(); + } else if (columnIndex == 1 && bba.getAttributeType().getTypeName().startsWith("TSK_URL") && !StringUtils.isBlank(bba.getDisplayString())) { + return bba.getDisplayString(); } } - return returnValue; + return Bundle.ArtifactsListPanel_value_noValue(); } @NbBundle.Messages({"ArtifactsListPanel.titleColumn.name=Title", "ArtifactsListPanel.dateColumn.name=Date/Time"}) @Override - public String getColumnName(int column) { + public String getColumnName(int column + ) { switch (column) { case 0: return Bundle.ArtifactsListPanel_dateColumn_name(); From b0bbfffdb216fd95eff28b07714bcf87beac42ad Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Fri, 23 Oct 2020 15:02:26 -0400 Subject: [PATCH 11/81] 6773 use logger instead of printstacktrace --- .../autopsy/discovery/ui/WebHistoryDetailsPanel.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/WebHistoryDetailsPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/WebHistoryDetailsPanel.java index 8965581720..28001b82d4 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/WebHistoryDetailsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/WebHistoryDetailsPanel.java @@ -23,12 +23,13 @@ import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.util.ArrayList; import java.util.List; +import java.util.logging.Level; import javax.swing.JScrollPane; -import org.openide.util.Exceptions; import org.openide.util.NbBundle; import org.openide.util.lookup.ServiceProvider; import org.sleuthkit.autopsy.contentviewers.artifactviewers.ArtifactContentViewer; import org.sleuthkit.autopsy.contentviewers.artifactviewers.CommunicationArtifactViewerHelper; +import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.TskCoreException; @@ -40,6 +41,7 @@ import org.sleuthkit.datamodel.TskCoreException; public class WebHistoryDetailsPanel extends AbstractArtifactDetailsPanel implements ArtifactContentViewer { private static final long serialVersionUID = 1L; + private static final Logger logger = Logger.getLogger(WebHistoryDetailsPanel.class.getName()); private BlackboardArtifact webHistoryArtifact; private final GridBagLayout gridBagLayout = new GridBagLayout(); private final List urlList = new ArrayList<>(); @@ -68,7 +70,7 @@ public class WebHistoryDetailsPanel extends AbstractArtifactDetailsPanel impleme try { extractArtifactData(artifact); } catch (TskCoreException ex) { - Exceptions.printStackTrace(ex); + logger.log(Level.WARNING, "Unable to get attributes for artifact " + artifact.getArtifactID(), ex); } updateView(); } From 1ad5703dab22866c8274a7ede92a5e03d066311b Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Fri, 23 Oct 2020 15:21:45 -0400 Subject: [PATCH 12/81] 6774 change downloads and cache to have file name in title column instead of url --- .../sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java index 6b23195480..1678bf896f 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java @@ -46,6 +46,7 @@ class ArtifactsListPanel extends JPanel { */ ArtifactsListPanel() { initComponents(); + jTable1.getRowSorter().toggleSortOrder(0); } @@ -187,13 +188,16 @@ class ArtifactsListPanel extends JPanel { @Override public Object getValueAt(int rowIndex, int columnIndex) { try { + int artifactTypeId = getArtifactByRow(rowIndex).getArtifactTypeID(); + if (columnIndex == 1 && (artifactTypeId == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE.getTypeID() || artifactTypeId == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD.getTypeID())) { + return getArtifactByRow(rowIndex).getParent().getName(); + } for (BlackboardAttribute bba : getArtifactByRow(rowIndex).getAttributes()) { if (columnIndex == 0 && bba.getAttributeType().getTypeName().startsWith("TSK_DATETIME_ACCESSED") && !StringUtils.isBlank(bba.getDisplayString())) { return bba.getDisplayString(); } else if (columnIndex == 1 && bba.getAttributeType().getTypeName().startsWith("TSK_TITLE") && !StringUtils.isBlank(bba.getDisplayString())) { return bba.getDisplayString(); } - } return getFallbackValue(rowIndex, columnIndex); } catch (TskCoreException ex) { From 50d28ecd3fbf5632310b05e5ef63a5fe548585ea Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Fri, 23 Oct 2020 15:27:42 -0400 Subject: [PATCH 13/81] 6774 toggle sort order --- .../org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java index 1678bf896f..d245f98561 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java @@ -47,7 +47,7 @@ class ArtifactsListPanel extends JPanel { ArtifactsListPanel() { initComponents(); jTable1.getRowSorter().toggleSortOrder(0); - + jTable1.getRowSorter().toggleSortOrder(0); } /** From 98f30bfc72e4cdd226f993c60992df6425d2f015 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Fri, 23 Oct 2020 15:42:46 -0400 Subject: [PATCH 14/81] 6774 convert row index to model --- .../org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java index d245f98561..cc2bb03ed3 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java @@ -77,7 +77,7 @@ class ArtifactsListPanel extends JPanel { * selected. */ BlackboardArtifact getSelectedArtifact() { - int selectedIndex = jTable1.getSelectionModel().getLeadSelectionIndex(); + int selectedIndex = jTable1.convertRowIndexToModel(jTable1.getSelectionModel().getLeadSelectionIndex()); if (selectedIndex < jTable1.getSelectionModel().getMinSelectionIndex() || jTable1.getSelectionModel().getMaxSelectionIndex() < 0 || selectedIndex > jTable1.getSelectionModel().getMaxSelectionIndex()) { return null; } From 5d71dee1556122bfa0e94db23fa11142b4b8a4d6 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Fri, 23 Oct 2020 16:29:13 -0400 Subject: [PATCH 15/81] 6774 fix indexing for getting artifact --- .../autopsy/discovery/ui/ArtifactsListPanel.java | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java index cc2bb03ed3..8822a3f9c0 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java @@ -77,11 +77,11 @@ class ArtifactsListPanel extends JPanel { * selected. */ BlackboardArtifact getSelectedArtifact() { - int selectedIndex = jTable1.convertRowIndexToModel(jTable1.getSelectionModel().getLeadSelectionIndex()); + int selectedIndex = jTable1.getSelectionModel().getLeadSelectionIndex(); if (selectedIndex < jTable1.getSelectionModel().getMinSelectionIndex() || jTable1.getSelectionModel().getMaxSelectionIndex() < 0 || selectedIndex > jTable1.getSelectionModel().getMaxSelectionIndex()) { return null; } - return tableModel.getArtifactByRow(selectedIndex); + return tableModel.getArtifactByRow(jTable1.convertRowIndexToView(selectedIndex)); } /** @@ -187,21 +187,22 @@ class ArtifactsListPanel extends JPanel { @NbBundle.Messages({"ArtifactsListPanel.value.noValue=No value available."}) @Override public Object getValueAt(int rowIndex, int columnIndex) { + int convertedRowIndex = rowIndex;//jTable1.convertRowIndexToModel(rowIndex); try { - int artifactTypeId = getArtifactByRow(rowIndex).getArtifactTypeID(); + int artifactTypeId = getArtifactByRow(convertedRowIndex).getArtifactTypeID(); if (columnIndex == 1 && (artifactTypeId == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE.getTypeID() || artifactTypeId == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD.getTypeID())) { - return getArtifactByRow(rowIndex).getParent().getName(); + return getArtifactByRow(convertedRowIndex).getParent().getName(); } - for (BlackboardAttribute bba : getArtifactByRow(rowIndex).getAttributes()) { + for (BlackboardAttribute bba : getArtifactByRow(convertedRowIndex).getAttributes()) { if (columnIndex == 0 && bba.getAttributeType().getTypeName().startsWith("TSK_DATETIME_ACCESSED") && !StringUtils.isBlank(bba.getDisplayString())) { return bba.getDisplayString(); } else if (columnIndex == 1 && bba.getAttributeType().getTypeName().startsWith("TSK_TITLE") && !StringUtils.isBlank(bba.getDisplayString())) { return bba.getDisplayString(); } } - return getFallbackValue(rowIndex, columnIndex); + return getFallbackValue(convertedRowIndex, columnIndex); } catch (TskCoreException ex) { - logger.log(Level.WARNING, "Error getting attributes for artifact " + getArtifactByRow(rowIndex).getArtifactID(), ex); + logger.log(Level.WARNING, "Error getting attributes for artifact " + getArtifactByRow(convertedRowIndex).getArtifactID(), ex); return Bundle.ArtifactsListPanel_value_noValue(); } } From f4830580422c1f48948ec9bd23ac817139ac1cdf Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Fri, 23 Oct 2020 16:31:59 -0400 Subject: [PATCH 16/81] 6773 fix index when sorted --- .../org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java index 6b23195480..bc29daac32 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java @@ -80,7 +80,7 @@ class ArtifactsListPanel extends JPanel { if (selectedIndex < jTable1.getSelectionModel().getMinSelectionIndex() || jTable1.getSelectionModel().getMaxSelectionIndex() < 0 || selectedIndex > jTable1.getSelectionModel().getMaxSelectionIndex()) { return null; } - return tableModel.getArtifactByRow(selectedIndex); + return tableModel.getArtifactByRow(jTable1.convertRowIndexToView(selectedIndex)); } /** From 34850bf7596693992e44219512c762f7a9fc0e36 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Fri, 23 Oct 2020 16:33:21 -0400 Subject: [PATCH 17/81] 6774 remove unused code --- .../autopsy/discovery/ui/ArtifactsListPanel.java | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java index 8822a3f9c0..9fa783a816 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java @@ -187,22 +187,21 @@ class ArtifactsListPanel extends JPanel { @NbBundle.Messages({"ArtifactsListPanel.value.noValue=No value available."}) @Override public Object getValueAt(int rowIndex, int columnIndex) { - int convertedRowIndex = rowIndex;//jTable1.convertRowIndexToModel(rowIndex); try { - int artifactTypeId = getArtifactByRow(convertedRowIndex).getArtifactTypeID(); + int artifactTypeId = getArtifactByRow(rowIndex).getArtifactTypeID(); if (columnIndex == 1 && (artifactTypeId == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE.getTypeID() || artifactTypeId == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD.getTypeID())) { - return getArtifactByRow(convertedRowIndex).getParent().getName(); + return getArtifactByRow(rowIndex).getParent().getName(); } - for (BlackboardAttribute bba : getArtifactByRow(convertedRowIndex).getAttributes()) { + for (BlackboardAttribute bba : getArtifactByRow(rowIndex).getAttributes()) { if (columnIndex == 0 && bba.getAttributeType().getTypeName().startsWith("TSK_DATETIME_ACCESSED") && !StringUtils.isBlank(bba.getDisplayString())) { return bba.getDisplayString(); } else if (columnIndex == 1 && bba.getAttributeType().getTypeName().startsWith("TSK_TITLE") && !StringUtils.isBlank(bba.getDisplayString())) { return bba.getDisplayString(); } } - return getFallbackValue(convertedRowIndex, columnIndex); + return getFallbackValue(rowIndex, columnIndex); } catch (TskCoreException ex) { - logger.log(Level.WARNING, "Error getting attributes for artifact " + getArtifactByRow(convertedRowIndex).getArtifactID(), ex); + logger.log(Level.WARNING, "Error getting attributes for artifact " + getArtifactByRow(rowIndex).getArtifactID(), ex); return Bundle.ArtifactsListPanel_value_noValue(); } } From 26144984d895711c15b5943368c75d604dfc8e57 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Fri, 23 Oct 2020 17:09:26 -0400 Subject: [PATCH 18/81] 6773 fix saving of selected tab and resizing of list --- .../discovery/ui/ArtifactsListPanel.form | 35 +++++++++++++++---- .../discovery/ui/ArtifactsListPanel.java | 19 +++++++--- .../autopsy/discovery/ui/Bundle.properties | 1 + .../discovery/ui/Bundle.properties-MERGED | 1 + .../discovery/ui/DomainDetailsPanel.java | 33 +++++++---------- 5 files changed, 57 insertions(+), 32 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.form b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.form index 28dd667601..2dbdf435bc 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.form +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.form @@ -1,6 +1,9 @@
+ + + @@ -11,21 +14,39 @@ - + - + + + + + + + + + + + + + + + + + + + + + + + + - - - - - diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java index bc29daac32..9f88c1e91b 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java @@ -46,7 +46,6 @@ class ArtifactsListPanel extends JPanel { */ ArtifactsListPanel() { initComponents(); - } /** @@ -125,14 +124,26 @@ class ArtifactsListPanel extends JPanel { javax.swing.JScrollPane jScrollPane1 = new javax.swing.JScrollPane(); jTable1 = new javax.swing.JTable(); - setLayout(new java.awt.BorderLayout()); + setOpaque(false); + + jScrollPane1.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(ArtifactsListPanel.class, "ArtifactsListPanel.jScrollPane1.border.title"))); // NOI18N + jScrollPane1.setPreferredSize(null); jTable1.setAutoCreateRowSorter(true); jTable1.setModel(tableModel); jTable1.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION); jScrollPane1.setViewportView(jTable1); - add(jScrollPane1, java.awt.BorderLayout.PAGE_START); + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 400, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 607, Short.MAX_VALUE) + ); }// //GEN-END:initComponents /** @@ -212,7 +223,7 @@ class ArtifactsListPanel extends JPanel { * at. * * @return A string that can be used in place of the accessed date time - * attribute title when they are not avaiable. + * attribute title when they are not available. * * @throws TskCoreException */ diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/Bundle.properties b/Core/src/org/sleuthkit/autopsy/discovery/ui/Bundle.properties index 851045c71a..bf0db90a22 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/Bundle.properties @@ -60,3 +60,4 @@ DomainSummaryPanel.totalVisitsLabel.text= FileDetailsPanel.instancesList.border.title=Instances CookieDetailsPanel.jLabel1.text=Artifact: CookieDetailsPanel.jLabel2.text= +ArtifactsListPanel.jScrollPane1.border.title=scrollPane diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/discovery/ui/Bundle.properties-MERGED index 470ddd99a2..fffaa86f77 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/Bundle.properties-MERGED @@ -138,6 +138,7 @@ DomainSummaryPanel.totalVisitsLabel.text= FileDetailsPanel.instancesList.border.title=Instances CookieDetailsPanel.jLabel1.text=Artifact: CookieDetailsPanel.jLabel2.text= +ArtifactsListPanel.jScrollPane1.border.title=scrollPane VideoThumbnailPanel.bytes.text=bytes VideoThumbnailPanel.deleted.text=All instances of file are deleted. VideoThumbnailPanel.gigaBytes.text=GB diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.java index 5e4c3597b2..cbd830dcd1 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.java @@ -53,12 +53,9 @@ final class DomainDetailsPanel extends JPanel { */ private void addArtifactTabs() { for (BlackboardArtifact.ARTIFACT_TYPE type : SearchData.Type.DOMAIN.getArtifactTypes()) { - DomainArtifactsTabPanel newTab = new DomainArtifactsTabPanel(type); - jTabbedPane1.add(type.getDisplayName(), newTab); - if (!StringUtils.isBlank(selectedTabName)) { - jTabbedPane1.setSelectedComponent(newTab); - } + jTabbedPane1.add(type.getDisplayName(), new DomainArtifactsTabPanel(type)); } + selectTab(); jTabbedPane1.addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { @@ -73,6 +70,15 @@ final class DomainDetailsPanel extends JPanel { }); } + private void selectTab() { + for (int i = 0; i < jTabbedPane1.getTabCount(); i++) { + if (!StringUtils.isBlank(selectedTabName) && selectedTabName.equals(jTabbedPane1.getTitleAt(i))) { + jTabbedPane1.setSelectedIndex(i); + return; + } + } + } + /** * Run the worker which retrieves the list of artifacts for the domain to * populate the details area. @@ -95,21 +101,6 @@ final class DomainDetailsPanel extends JPanel { }); } - /** - * Clear the tabs of any previous content. - */ - private void clearTabs() { - int tabCount = jTabbedPane1.getTabCount(); - // We invoke removeTabAt for each tab, otherwise we may end up - // removing Components added by the UI. - while (tabCount > 0) { - tabCount--; - jTabbedPane1.removeTabAt(tabCount); - } - addArtifactTabs(); - - } - /** * Populate the the details tabs. * @@ -120,8 +111,8 @@ final class DomainDetailsPanel extends JPanel { synchronized void handlePopulateDomainTabsEvent(DiscoveryEventUtils.PopulateDomainTabsEvent populateEvent) { SwingUtilities.invokeLater(() -> { domain = populateEvent.getDomain(); + selectTab(); runDomainWorker(); - clearTabs(); if (StringUtils.isBlank(domain)) { //send fade out event DiscoveryEventUtils.getDiscoveryEventBus().post(new DiscoveryEventUtils.DetailsVisibleEvent(false)); From dcf8da3bfeee0c9e7df3b577befe1ba3ee46ad09 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Fri, 23 Oct 2020 17:13:56 -0400 Subject: [PATCH 19/81] 6773 remove titled border used for debugging --- .../autopsy/discovery/ui/ArtifactsListPanel.form | 9 +-------- .../autopsy/discovery/ui/ArtifactsListPanel.java | 3 +-- .../org/sleuthkit/autopsy/discovery/ui/Bundle.properties | 1 - 3 files changed, 2 insertions(+), 11 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.form b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.form index 2dbdf435bc..dc5a9fb0c6 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.form +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.form @@ -33,14 +33,7 @@ - - - - - - - - + diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java index 9f88c1e91b..bc0c8a89b0 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java @@ -126,8 +126,7 @@ class ArtifactsListPanel extends JPanel { setOpaque(false); - jScrollPane1.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(ArtifactsListPanel.class, "ArtifactsListPanel.jScrollPane1.border.title"))); // NOI18N - jScrollPane1.setPreferredSize(null); + jScrollPane1.setBorder(null); jTable1.setAutoCreateRowSorter(true); jTable1.setModel(tableModel); diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/Bundle.properties b/Core/src/org/sleuthkit/autopsy/discovery/ui/Bundle.properties index bf0db90a22..851045c71a 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/Bundle.properties @@ -60,4 +60,3 @@ DomainSummaryPanel.totalVisitsLabel.text= FileDetailsPanel.instancesList.border.title=Instances CookieDetailsPanel.jLabel1.text=Artifact: CookieDetailsPanel.jLabel2.text= -ArtifactsListPanel.jScrollPane1.border.title=scrollPane From 1db593e212491c86548e7eee542a0099b421704a Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Mon, 26 Oct 2020 08:32:27 -0400 Subject: [PATCH 20/81] 6773 update MERGED file --- .../org/sleuthkit/autopsy/discovery/ui/Bundle.properties-MERGED | 1 - 1 file changed, 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/discovery/ui/Bundle.properties-MERGED index fffaa86f77..470ddd99a2 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/Bundle.properties-MERGED @@ -138,7 +138,6 @@ DomainSummaryPanel.totalVisitsLabel.text= FileDetailsPanel.instancesList.border.title=Instances CookieDetailsPanel.jLabel1.text=Artifact: CookieDetailsPanel.jLabel2.text= -ArtifactsListPanel.jScrollPane1.border.title=scrollPane VideoThumbnailPanel.bytes.text=bytes VideoThumbnailPanel.deleted.text=All instances of file are deleted. VideoThumbnailPanel.gigaBytes.text=GB From fd7c802c46cae56a6b6842946f9f7958a3d593d6 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Mon, 26 Oct 2020 10:28:45 -0400 Subject: [PATCH 21/81] 6774 address feedback regarding mime type display --- .../discovery/search/SearchFiltering.java | 12 ++++++ .../discovery/ui/ArtifactsListPanel.java | 40 ++++++++++++++----- .../discovery/ui/DiscoveryTopComponent.java | 12 +++++- .../discovery/ui/DomainArtifactsTabPanel.java | 7 ++-- .../discovery/ui/DomainDetailsPanel.java | 6 ++- 5 files changed, 62 insertions(+), 15 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/discovery/search/SearchFiltering.java b/Core/src/org/sleuthkit/autopsy/discovery/search/SearchFiltering.java index 9505cfa5e2..2e10305f2a 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/search/SearchFiltering.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/search/SearchFiltering.java @@ -217,6 +217,18 @@ public class SearchFiltering { this.types = types; } + /** + * Get the first artifact type specified by the filter. + * + * @return The first artifact type specified by the filter. + */ + public ARTIFACT_TYPE getFirstType() { + if (!types.isEmpty()) { + return types.get(0); + } + return null; + } + @Override public String getWhereClause() { StringJoiner joiner = new StringJoiner(","); diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java index ae854f9f46..23136e7015 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java @@ -24,9 +24,11 @@ import java.util.logging.Level; import javax.swing.JPanel; import javax.swing.event.ListSelectionListener; import javax.swing.table.AbstractTableModel; +import org.apache.commons.io.FilenameUtils; import org.apache.commons.lang.StringUtils; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.TskCoreException; @@ -38,13 +40,16 @@ import org.sleuthkit.datamodel.TskCoreException; class ArtifactsListPanel extends JPanel { private static final long serialVersionUID = 1L; - private final DomainArtifactTableModel tableModel = new DomainArtifactTableModel(); + private final DomainArtifactTableModel tableModel; private static final Logger logger = Logger.getLogger(ArtifactsListPanel.class.getName()); /** * Creates new form ArtifactsListPanel. + * + * @param artifactType The type of artifact displayed in this table. */ - ArtifactsListPanel() { + ArtifactsListPanel(BlackboardArtifact.ARTIFACT_TYPE artifactType) { + tableModel = new DomainArtifactTableModel(artifactType); initComponents(); jTable1.getRowSorter().toggleSortOrder(0); jTable1.getRowSorter().toggleSortOrder(0); @@ -155,12 +160,15 @@ class ArtifactsListPanel extends JPanel { private static final long serialVersionUID = 1L; private final List artifactList = new ArrayList<>(); + private final BlackboardArtifact.ARTIFACT_TYPE resultType; /** * Construct a new DomainArtifactTableModel. + * + * @param resultType The type of artifact displayed in this table. */ - DomainArtifactTableModel() { - //No arg constructor to create empty model + DomainArtifactTableModel(BlackboardArtifact.ARTIFACT_TYPE resultType) { + this.resultType = resultType; } /** @@ -181,7 +189,11 @@ class ArtifactsListPanel extends JPanel { @Override public int getColumnCount() { - return 2; + if (resultType == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE) { + return 3; + } else { + return 2; + } } /** @@ -200,14 +212,20 @@ class ArtifactsListPanel extends JPanel { public Object getValueAt(int rowIndex, int columnIndex) { try { int artifactTypeId = getArtifactByRow(rowIndex).getArtifactTypeID(); - if (columnIndex == 1 && (artifactTypeId == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE.getTypeID() || artifactTypeId == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD.getTypeID())) { + if (columnIndex == 1 && artifactTypeId == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE.getTypeID()) { return getArtifactByRow(rowIndex).getParent().getName(); + } else if (columnIndex == 2 && artifactTypeId == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE.getTypeID() && getArtifactByRow(rowIndex).getParent() instanceof AbstractFile) { + return ((AbstractFile) getArtifactByRow(rowIndex).getParent()).getMIMEType(); + } else if (columnIndex == 2) { + return ""; } for (BlackboardAttribute bba : getArtifactByRow(rowIndex).getAttributes()) { - if (columnIndex == 0 && bba.getAttributeType().getTypeName().startsWith("TSK_DATETIME_ACCESSED") && !StringUtils.isBlank(bba.getDisplayString())) { + if (columnIndex == 0 && bba.getAttributeType().getTypeName().startsWith("TSK_DATETIME_ACCESSED") && !StringUtils.isBlank(bba.getDisplayString()) && artifactTypeId != BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD.getTypeID()) { return bba.getDisplayString(); } else if (columnIndex == 1 && bba.getAttributeType().getTypeName().startsWith("TSK_TITLE") && !StringUtils.isBlank(bba.getDisplayString())) { return bba.getDisplayString(); + } else if (columnIndex == 1 && bba.getAttributeType().getTypeName().startsWith("TSK_PATH") && artifactTypeId == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD.getTypeID()) { + return FilenameUtils.getName(bba.getDisplayString()); } } return getFallbackValue(rowIndex, columnIndex); @@ -243,15 +261,17 @@ class ArtifactsListPanel extends JPanel { } @NbBundle.Messages({"ArtifactsListPanel.titleColumn.name=Title", - "ArtifactsListPanel.dateColumn.name=Date/Time"}) + "ArtifactsListPanel.dateColumn.name=Date/Time", + "ArtifactsListPanel.mimeTypeColumn.name=MIME Type"}) @Override - public String getColumnName(int column - ) { + public String getColumnName(int column) { switch (column) { case 0: return Bundle.ArtifactsListPanel_dateColumn_name(); case 1: return Bundle.ArtifactsListPanel_titleColumn_name(); + case 3: + return Bundle.ArtifactsListPanel_mimeTypeColumn_name(); default: return ""; } diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/DiscoveryTopComponent.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/DiscoveryTopComponent.java index 16f5b1b16e..ec5f4158ba 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/DiscoveryTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/DiscoveryTopComponent.java @@ -40,6 +40,8 @@ import org.sleuthkit.autopsy.coreutils.ThreadConfined; import org.sleuthkit.autopsy.discovery.search.DiscoveryEventUtils; import org.sleuthkit.autopsy.discovery.search.SearchData.Type; import static org.sleuthkit.autopsy.discovery.search.SearchData.Type.DOMAIN; +import org.sleuthkit.autopsy.discovery.search.SearchFiltering.ArtifactTypeFilter; +import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE; /** * Create a dialog for displaying the Discovery results. @@ -320,7 +322,15 @@ public final class DiscoveryTopComponent extends TopComponent { if (!searchCompleteEvent.getFilters().isEmpty()) { descriptionText += Bundle.DiscoveryTopComponent_additionalFilters_text(); } - rightSplitPane.setBottomComponent(new DomainDetailsPanel()); + ARTIFACT_TYPE selectedType = null; + for (AbstractFilter filter : searchCompleteEvent.getFilters()) { + if (filter instanceof ArtifactTypeFilter) { + selectedType = ((ArtifactTypeFilter) filter).getFirstType(); + break; + } + } + + rightSplitPane.setBottomComponent(new DomainDetailsPanel(selectedType)); } else { rightSplitPane.setBottomComponent(new FileDetailsPanel()); } diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.java index 0e9ff9d627..ad66d28237 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.java @@ -37,7 +37,7 @@ final class DomainArtifactsTabPanel extends JPanel { private static final long serialVersionUID = 1L; private final static Logger logger = Logger.getLogger(DomainArtifactsTabPanel.class.getName()); - private final ArtifactsListPanel listPanel = new ArtifactsListPanel(); + private final ArtifactsListPanel listPanel; private final BlackboardArtifact.ARTIFACT_TYPE artifactType; private AbstractArtifactDetailsPanel rightPanel = null; @@ -54,9 +54,10 @@ final class DomainArtifactsTabPanel extends JPanel { /** * Creates new form CookiesPanel */ - DomainArtifactsTabPanel(BlackboardArtifact.ARTIFACT_TYPE artifactType) { + DomainArtifactsTabPanel(BlackboardArtifact.ARTIFACT_TYPE type) { initComponents(); - this.artifactType = artifactType; + this.artifactType = type; + listPanel = new ArtifactsListPanel(artifactType); jSplitPane1.setLeftComponent(listPanel); setRightComponent(); listPanel.addSelectionListener(listener); diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.java index cbd830dcd1..049b5aad33 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.java @@ -28,6 +28,7 @@ import org.apache.commons.lang.StringUtils; import org.sleuthkit.autopsy.discovery.search.DiscoveryEventUtils; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.autopsy.discovery.search.SearchData; +import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE; /** * Panel to display details area for domain discovery results. @@ -42,8 +43,11 @@ final class DomainDetailsPanel extends JPanel { /** * Creates new form ArtifactDetailsPanel + * + * @param initialSelectedTab Specifies which specific details tab should be selected initially. */ - DomainDetailsPanel() { + DomainDetailsPanel(ARTIFACT_TYPE initialSelectedTab) { + selectedTabName = initialSelectedTab.getDisplayName(); initComponents(); addArtifactTabs(); } From 2192288b09e3bc9e35323b1819a74e01b0eef672 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Mon, 26 Oct 2020 12:38:28 -0400 Subject: [PATCH 22/81] 6774 fix fields for download and cache in table --- .../discovery/ui/ArtifactsListPanel.java | 54 ++++++++++++------- .../discovery/ui/Bundle.properties-MERGED | 1 + .../discovery/ui/DomainDetailsPanel.java | 7 ++- 3 files changed, 40 insertions(+), 22 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java index 23136e7015..794968d04a 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java @@ -27,8 +27,8 @@ import javax.swing.table.AbstractTableModel; import org.apache.commons.io.FilenameUtils; import org.apache.commons.lang.StringUtils; import org.openide.util.NbBundle; +import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.TskCoreException; @@ -160,15 +160,15 @@ class ArtifactsListPanel extends JPanel { private static final long serialVersionUID = 1L; private final List artifactList = new ArrayList<>(); - private final BlackboardArtifact.ARTIFACT_TYPE resultType; + private final BlackboardArtifact.ARTIFACT_TYPE artifactType; /** * Construct a new DomainArtifactTableModel. * - * @param resultType The type of artifact displayed in this table. + * @param artifactType The type of artifact displayed in this table. */ - DomainArtifactTableModel(BlackboardArtifact.ARTIFACT_TYPE resultType) { - this.resultType = resultType; + DomainArtifactTableModel(BlackboardArtifact.ARTIFACT_TYPE artifactType) { + this.artifactType = artifactType; } /** @@ -189,7 +189,7 @@ class ArtifactsListPanel extends JPanel { @Override public int getColumnCount() { - if (resultType == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE) { + if (artifactType == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE) { return 3; } else { return 2; @@ -211,21 +211,27 @@ class ArtifactsListPanel extends JPanel { @Override public Object getValueAt(int rowIndex, int columnIndex) { try { - int artifactTypeId = getArtifactByRow(rowIndex).getArtifactTypeID(); - if (columnIndex == 1 && artifactTypeId == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE.getTypeID()) { - return getArtifactByRow(rowIndex).getParent().getName(); - } else if (columnIndex == 2 && artifactTypeId == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE.getTypeID() && getArtifactByRow(rowIndex).getParent() instanceof AbstractFile) { - return ((AbstractFile) getArtifactByRow(rowIndex).getParent()).getMIMEType(); - } else if (columnIndex == 2) { + if (columnIndex == 2 && artifactType != BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE) { return ""; } for (BlackboardAttribute bba : getArtifactByRow(rowIndex).getAttributes()) { - if (columnIndex == 0 && bba.getAttributeType().getTypeName().startsWith("TSK_DATETIME_ACCESSED") && !StringUtils.isBlank(bba.getDisplayString()) && artifactTypeId != BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD.getTypeID()) { + System.out.println("ATTR NAME: " + bba.getAttributeType().getTypeName()); + if (columnIndex == 0 && bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID() && !StringUtils.isBlank(bba.getDisplayString())) { return bba.getDisplayString(); - } else if (columnIndex == 1 && bba.getAttributeType().getTypeName().startsWith("TSK_TITLE") && !StringUtils.isBlank(bba.getDisplayString())) { - return bba.getDisplayString(); - } else if (columnIndex == 1 && bba.getAttributeType().getTypeName().startsWith("TSK_PATH") && artifactTypeId == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD.getTypeID()) { - return FilenameUtils.getName(bba.getDisplayString()); + } else if (columnIndex == 1) { + if (bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TITLE.getTypeID() && artifactType != BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD && !StringUtils.isBlank(bba.getDisplayString())) { + System.out.println("TITLE"); + return bba.getDisplayString(); + } else if (artifactType == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE && bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL.getTypeID()) { + System.out.println("GET FILE NAME FROM URL"); + return FilenameUtils.getName(bba.getDisplayString()); + } else if (bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH.getTypeID() && artifactType == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD) { + System.out.println("GET FILE NAME DOWNLOAD: "); + return FilenameUtils.getName(bba.getDisplayString()); + } + } else if (columnIndex == 2 && artifactType == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE && bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH_ID.getTypeID() && !StringUtils.isBlank(bba.getDisplayString())) { + System.out.println("MIMETYPE"); + return Case.getCurrentCase().getSleuthkitCase().getAbstractFileById(bba.getValueLong()).getMIMEType(); } } return getFallbackValue(rowIndex, columnIndex); @@ -252,15 +258,19 @@ class ArtifactsListPanel extends JPanel { private String getFallbackValue(int rowIndex, int columnIndex) throws TskCoreException { for (BlackboardAttribute bba : getArtifactByRow(rowIndex).getAttributes()) { if (columnIndex == 0 && bba.getAttributeType().getTypeName().startsWith("TSK_DATETIME") && !StringUtils.isBlank(bba.getDisplayString())) { + System.out.println("FALLBACK TIME"); return bba.getDisplayString(); - } else if (columnIndex == 1 && bba.getAttributeType().getTypeName().startsWith("TSK_URL") && !StringUtils.isBlank(bba.getDisplayString())) { + } else if (columnIndex == 1 && bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL.getTypeID() && !StringUtils.isBlank(bba.getDisplayString())) { + System.out.println("FALLBACK TITLE"); return bba.getDisplayString(); } } + System.out.println("NO VALUE"); return Bundle.ArtifactsListPanel_value_noValue(); } @NbBundle.Messages({"ArtifactsListPanel.titleColumn.name=Title", + "ArtifactsListPanel.fileNameColumn.name=Name", "ArtifactsListPanel.dateColumn.name=Date/Time", "ArtifactsListPanel.mimeTypeColumn.name=MIME Type"}) @Override @@ -269,8 +279,12 @@ class ArtifactsListPanel extends JPanel { case 0: return Bundle.ArtifactsListPanel_dateColumn_name(); case 1: - return Bundle.ArtifactsListPanel_titleColumn_name(); - case 3: + if (artifactType == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE || artifactType == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD) { + return Bundle.ArtifactsListPanel_fileNameColumn_name(); + } else { + return Bundle.ArtifactsListPanel_titleColumn_name(); + } + case 2: return Bundle.ArtifactsListPanel_mimeTypeColumn_name(); default: return ""; diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/discovery/ui/Bundle.properties-MERGED index 470ddd99a2..f786639dbe 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/Bundle.properties-MERGED @@ -1,4 +1,5 @@ ArtifactsListPanel.dateColumn.name=Date/Time +ArtifactsListPanel.mimeTypeColumn.name=MIME Type ArtifactsListPanel.titleColumn.name=Title ArtifactsListPanel.value.noValue=No value available. ArtifactTypeFilterPanel.selectionNeeded.text=At least one Result type must be selected. diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.java index 049b5aad33..72d70dca82 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.java @@ -44,10 +44,13 @@ final class DomainDetailsPanel extends JPanel { /** * Creates new form ArtifactDetailsPanel * - * @param initialSelectedTab Specifies which specific details tab should be selected initially. + * @param initialSelectedTab Specifies which specific details tab should be + * selected initially. */ DomainDetailsPanel(ARTIFACT_TYPE initialSelectedTab) { - selectedTabName = initialSelectedTab.getDisplayName(); + if (initialSelectedTab != null) { + selectedTabName = initialSelectedTab.getDisplayName(); + } initComponents(); addArtifactTabs(); } From 90344f0358ce05b2c777eabab067b0bfa33cfe1a Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Mon, 26 Oct 2020 13:59:22 -0400 Subject: [PATCH 23/81] 6773 fix population of tabs for domains after first selected --- .../autopsy/discovery/ui/DomainDetailsPanel.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.java index cbd830dcd1..d4713b55b1 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.java @@ -111,6 +111,7 @@ final class DomainDetailsPanel extends JPanel { synchronized void handlePopulateDomainTabsEvent(DiscoveryEventUtils.PopulateDomainTabsEvent populateEvent) { SwingUtilities.invokeLater(() -> { domain = populateEvent.getDomain(); + resetTabsStatus(); selectTab(); runDomainWorker(); if (StringUtils.isBlank(domain)) { @@ -123,6 +124,18 @@ final class DomainDetailsPanel extends JPanel { }); } + /** + * Private helper method to ensure tabs will re-populate after a new domain + * is selected. + */ + private void resetTabsStatus() { + for (Component comp : jTabbedPane1.getComponents()) { + if (comp instanceof DomainArtifactsTabPanel) { + ((DomainArtifactsTabPanel) comp).setStatus(DomainArtifactsTabPanel.ArtifactRetrievalStatus.UNPOPULATED); + } + } + } + /** * This method is called from within the constructor to initialize the form. * WARNING: Do NOT modify this code. The content of this method is always From 75acecd2dfdc931b9aad744c7d2422e7f72c947d Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Mon, 26 Oct 2020 14:02:04 -0400 Subject: [PATCH 24/81] 6774 remove print lines --- .../autopsy/discovery/ui/ArtifactsListPanel.java | 8 -------- 1 file changed, 8 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java index 794968d04a..b0bc162fa6 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java @@ -215,22 +215,17 @@ class ArtifactsListPanel extends JPanel { return ""; } for (BlackboardAttribute bba : getArtifactByRow(rowIndex).getAttributes()) { - System.out.println("ATTR NAME: " + bba.getAttributeType().getTypeName()); if (columnIndex == 0 && bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID() && !StringUtils.isBlank(bba.getDisplayString())) { return bba.getDisplayString(); } else if (columnIndex == 1) { if (bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TITLE.getTypeID() && artifactType != BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD && !StringUtils.isBlank(bba.getDisplayString())) { - System.out.println("TITLE"); return bba.getDisplayString(); } else if (artifactType == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE && bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL.getTypeID()) { - System.out.println("GET FILE NAME FROM URL"); return FilenameUtils.getName(bba.getDisplayString()); } else if (bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH.getTypeID() && artifactType == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD) { - System.out.println("GET FILE NAME DOWNLOAD: "); return FilenameUtils.getName(bba.getDisplayString()); } } else if (columnIndex == 2 && artifactType == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE && bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH_ID.getTypeID() && !StringUtils.isBlank(bba.getDisplayString())) { - System.out.println("MIMETYPE"); return Case.getCurrentCase().getSleuthkitCase().getAbstractFileById(bba.getValueLong()).getMIMEType(); } } @@ -258,14 +253,11 @@ class ArtifactsListPanel extends JPanel { private String getFallbackValue(int rowIndex, int columnIndex) throws TskCoreException { for (BlackboardAttribute bba : getArtifactByRow(rowIndex).getAttributes()) { if (columnIndex == 0 && bba.getAttributeType().getTypeName().startsWith("TSK_DATETIME") && !StringUtils.isBlank(bba.getDisplayString())) { - System.out.println("FALLBACK TIME"); return bba.getDisplayString(); } else if (columnIndex == 1 && bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL.getTypeID() && !StringUtils.isBlank(bba.getDisplayString())) { - System.out.println("FALLBACK TITLE"); return bba.getDisplayString(); } } - System.out.println("NO VALUE"); return Bundle.ArtifactsListPanel_value_noValue(); } From 18546e6a8897dcc374c004bfa8b6879f64bfce65 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Mon, 26 Oct 2020 14:09:31 -0400 Subject: [PATCH 25/81] 6774 update name column for TSK_WEB_CACHE in discovery --- .../org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java | 2 +- .../org/sleuthkit/autopsy/discovery/ui/Bundle.properties-MERGED | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java index b0bc162fa6..329a06c090 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java @@ -220,7 +220,7 @@ class ArtifactsListPanel extends JPanel { } else if (columnIndex == 1) { if (bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TITLE.getTypeID() && artifactType != BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD && !StringUtils.isBlank(bba.getDisplayString())) { return bba.getDisplayString(); - } else if (artifactType == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE && bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL.getTypeID()) { + } else if (artifactType == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE && bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH_ID.getTypeID() && !StringUtils.isBlank(bba.getDisplayString())) { return FilenameUtils.getName(bba.getDisplayString()); } else if (bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH.getTypeID() && artifactType == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD) { return FilenameUtils.getName(bba.getDisplayString()); diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/discovery/ui/Bundle.properties-MERGED index f786639dbe..a5305503b5 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/Bundle.properties-MERGED @@ -1,4 +1,5 @@ ArtifactsListPanel.dateColumn.name=Date/Time +ArtifactsListPanel.fileNameColumn.name=Name ArtifactsListPanel.mimeTypeColumn.name=MIME Type ArtifactsListPanel.titleColumn.name=Title ArtifactsListPanel.value.noValue=No value available. From 1606da87a444e462534de146761a34b660808fb0 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Mon, 26 Oct 2020 14:28:26 -0400 Subject: [PATCH 26/81] 6773 fix selection clearing --- .../autopsy/discovery/ui/ArtifactsListPanel.java | 11 ++++++++++- .../autopsy/discovery/ui/DomainArtifactsTabPanel.java | 4 ++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java index bc0c8a89b0..50663c168c 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java @@ -92,11 +92,19 @@ class ArtifactsListPanel extends JPanel { return tableModel.getRowCount() <= 0; } + void selectFirst() { + if (!isEmpty()) { + jTable1.setRowSelectionInterval(0, 0); + } else { + jTable1.clearSelection(); + } + } + /** * Add the specified list of artifacts to the list of artifacts which should * be displayed. * - * @param artifactList + * @param artifactList The list of artifacts to display. */ void addArtifacts(List artifactList) { tableModel.setContents(artifactList); @@ -168,6 +176,7 @@ class ArtifactsListPanel extends JPanel { * @param artifacts The list of BlackboardArtifacts to represent. */ void setContents(List artifacts) { + jTable1.clearSelection(); artifactList.clear(); artifactList.addAll(artifacts); } diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.java index e33ec8e14c..2cc9815574 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.java @@ -101,6 +101,9 @@ final class DomainArtifactsTabPanel extends JPanel { */ void setStatus(ArtifactRetrievalStatus status) { this.status = status; + if (status == ArtifactRetrievalStatus.UNPOPULATED) { + rightPanel.setArtifact(null); + } } @Subscribe @@ -110,6 +113,7 @@ final class DomainArtifactsTabPanel extends JPanel { listPanel.removeListSelectionListener(listener); listPanel.addArtifacts(artifactListEvent.getListOfArtifacts()); listPanel.addSelectionListener(listener); + listPanel.selectFirst(); try { DiscoveryEventUtils.getDiscoveryEventBus().unregister(this); } catch (IllegalArgumentException notRegistered) { From 993c620455b4bbc8978940511266ee1e5fda48f2 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Mon, 26 Oct 2020 15:04:44 -0400 Subject: [PATCH 27/81] 6773 fix resetting of details panel --- .../DefaultArtifactContentViewer.java | 67 +++++++++---------- .../discovery/ui/DomainArtifactsTabPanel.java | 4 +- 2 files changed, 35 insertions(+), 36 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/DefaultArtifactContentViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/DefaultArtifactContentViewer.java index 799993ceee..eff2ed4561 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/DefaultArtifactContentViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/DefaultArtifactContentViewer.java @@ -58,10 +58,9 @@ import org.sleuthkit.autopsy.discovery.ui.AbstractArtifactDetailsPanel; //import org.sleuthkit.autopsy.contentviewers.Bundle; /** - * This class displays a Blackboard artifact as a table listing all it's + * This class displays a Blackboard artifact as a table listing all it's * attributes names and values. */ - @SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives public class DefaultArtifactContentViewer extends AbstractArtifactDetailsPanel implements ArtifactContentViewer { @@ -72,11 +71,11 @@ public class DefaultArtifactContentViewer extends AbstractArtifactDetailsPanel i "DataContentViewerArtifact.failedToGetSourcePath.message=Failed to get source file path from case database", "DataContentViewerArtifact.failedToGetAttributes.message=Failed to get some or all attributes from case database" }) - + private final static Logger logger = Logger.getLogger(DefaultArtifactContentViewer.class.getName()); - + private static final long serialVersionUID = 1L; - + private static final String[] COLUMN_HEADERS = { Bundle.DefaultArtifactContentViewer_attrsTableHeader_type(), Bundle.DefaultArtifactContentViewer_attrsTableHeader_value(), @@ -125,7 +124,7 @@ public class DefaultArtifactContentViewer extends AbstractArtifactDetailsPanel i // do nothing } - @Override + @Override public void columnMarginChanged(ChangeEvent e) { updateRowHeights(); //When the user changes column width we may need to resize row height } @@ -154,12 +153,12 @@ public class DefaultArtifactContentViewer extends AbstractArtifactDetailsPanel i Component comp = resultsTable.prepareRenderer( resultsTable.getCellRenderer(row, valueColIndex), row, valueColIndex); final int rowHeight; - if (comp instanceof JTextArea) { + if (comp instanceof JTextArea) { final JTextArea tc = (JTextArea) comp; final View rootView = tc.getUI().getRootView(tc); java.awt.Insets i = tc.getInsets(); rootView.setSize(resultsTable.getColumnModel().getColumn(valueColIndex) - .getWidth() - (i.left + i.right +CELL_RIGHT_MARGIN), //current width minus borders + .getWidth() - (i.left + i.right + CELL_RIGHT_MARGIN), //current width minus borders Integer.MAX_VALUE); rowHeight = (int) rootView.getPreferredSpan(View.Y_AXIS); } else { @@ -268,7 +267,7 @@ public class DefaultArtifactContentViewer extends AbstractArtifactDetailsPanel i * Resets the components to an empty view state. */ private void resetComponents() { - + ((DefaultTableModel) resultsTable.getModel()).setRowCount(0); } @@ -280,7 +279,7 @@ public class DefaultArtifactContentViewer extends AbstractArtifactDetailsPanel i @Override public void setArtifact(BlackboardArtifact artifact) { try { - ResultsTableArtifact resultsTableArtifact = new ResultsTableArtifact(artifact, artifact.getParent()); + ResultsTableArtifact resultsTableArtifact = artifact == null ? null : new ResultsTableArtifact(artifact, artifact.getParent()); SwingUtilities.invokeLater(new Runnable() { @Override @@ -290,7 +289,7 @@ public class DefaultArtifactContentViewer extends AbstractArtifactDetailsPanel i }); } catch (TskCoreException ex) { - logger.log(Level.SEVERE, String.format("Error getting parent content for artifact (artifact_id=%d, obj_id=%d)", artifact.getArtifactID(), artifact.getObjectID()), ex); + logger.log(Level.SEVERE, String.format("Error getting parent content for artifact (artifact_id=%d, obj_id=%d)", artifact.getArtifactID(), artifact.getObjectID()), ex); } } @@ -302,7 +301,7 @@ public class DefaultArtifactContentViewer extends AbstractArtifactDetailsPanel i } /** - * This class is a container to hold the data necessary for the artifact + * This class is a container to hold the data necessary for the artifact * being viewed. */ private class ResultsTableArtifact { @@ -341,20 +340,20 @@ public class DefaultArtifactContentViewer extends AbstractArtifactDetailsPanel i */ String value; switch (attr.getAttributeType().getValueType()) { - + // Use Autopsy date formatting settings, not TSK defaults case DATETIME: value = epochTimeToString(attr.getValueLong()); break; - case JSON: + case JSON: // Get the attribute's JSON value and convert to indented multiline display string String jsonVal = attr.getValueString(); JsonParser parser = new JsonParser(); JsonObject json = parser.parse(jsonVal).getAsJsonObject(); - + value = toJsonDisplayString(json, ""); break; - + case STRING: case INTEGER: case LONG: @@ -399,43 +398,43 @@ public class DefaultArtifactContentViewer extends AbstractArtifactDetailsPanel i String getArtifactDisplayName() { return artifactDisplayName; } - + private static final String INDENT_RIGHT = " "; private static final String NEW_LINE = "\n"; - + /** * Recursively converts a JSON element into an indented multi-line * display string. * - * @param element JSON element to convert + * @param element JSON element to convert * @param startIndent Starting indentation for the element. * * @return A multi-line display string. */ private String toJsonDisplayString(JsonElement element, String startIndent) { - + StringBuilder sb = new StringBuilder(""); JsonObject obj = element.getAsJsonObject(); for (Map.Entry entry : obj.entrySet()) { - appendJsonElementToString(entry.getKey(), entry.getValue(), startIndent, sb ); + appendJsonElementToString(entry.getKey(), entry.getValue(), startIndent, sb); } String returnString = sb.toString(); - if (startIndent.length() == 0 && returnString.startsWith(NEW_LINE)) { + if (startIndent.length() == 0 && returnString.startsWith(NEW_LINE)) { returnString = returnString.substring(NEW_LINE.length()); } return returnString; } - - + /** - * Converts the given JSON element into string and appends to the given string builder. - * + * Converts the given JSON element into string and appends to the given + * string builder. + * * @param jsonKey * @param jsonElement * @param startIndent Starting indentation for the element. - * @param sb String builder to append to. + * @param sb String builder to append to. */ private void appendJsonElementToString(String jsonKey, JsonElement jsonElement, String startIndent, StringBuilder sb) { if (jsonElement.isJsonArray()) { @@ -464,11 +463,12 @@ public class DefaultArtifactContentViewer extends AbstractArtifactDetailsPanel i sb.append(NEW_LINE).append(String.format("%s%s = null", startIndent, jsonKey)); } } - + /** * Converts epoch time to readable string. - * + * * @param epochTime epoch time value to be converted to string. + * * @return String with human readable time. */ private String epochTimeToString(long epochTime) { @@ -483,21 +483,20 @@ public class DefaultArtifactContentViewer extends AbstractArtifactDetailsPanel i } /** - * Updates the table view with the given artifact data. - * + * Updates the table view with the given artifact data. + * * It should be called on EDT. * * @param resultsTableArtifact Artifact data to display in the view. */ private void updateView(ResultsTableArtifact resultsTableArtifact) { this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); - DefaultTableModel tModel = ((DefaultTableModel) resultsTable.getModel()); - tModel.setDataVector(resultsTableArtifact.getRows(), COLUMN_HEADERS); + String[][] rows = resultsTableArtifact == null ? new String[0][0] : resultsTableArtifact.getRows(); + tModel.setDataVector(rows, COLUMN_HEADERS); updateColumnSizes(); updateRowHeights(); resultsTable.clearSelection(); - this.setCursor(null); } diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.java index 2cc9815574..2d5bafbbc8 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.java @@ -101,8 +101,8 @@ final class DomainArtifactsTabPanel extends JPanel { */ void setStatus(ArtifactRetrievalStatus status) { this.status = status; - if (status == ArtifactRetrievalStatus.UNPOPULATED) { - rightPanel.setArtifact(null); + if (status == ArtifactRetrievalStatus.UNPOPULATED && rightPanel != null) { + rightPanel.setArtifact(null); } } From aabea84939330481b58ae3b639d4a4f6ba63c30e Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Mon, 26 Oct 2020 15:07:05 -0400 Subject: [PATCH 28/81] 6774 fix file name --- .../org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java index 418828a422..4b72c2cb8f 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java @@ -230,7 +230,7 @@ class ArtifactsListPanel extends JPanel { if (bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TITLE.getTypeID() && artifactType != BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD && !StringUtils.isBlank(bba.getDisplayString())) { return bba.getDisplayString(); } else if (artifactType == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE && bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH_ID.getTypeID() && !StringUtils.isBlank(bba.getDisplayString())) { - return FilenameUtils.getName(bba.getDisplayString()); + return Case.getCurrentCase().getSleuthkitCase().getAbstractFileById(bba.getValueLong()).getName(); } else if (bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH.getTypeID() && artifactType == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD) { return FilenameUtils.getName(bba.getDisplayString()); } From cda0a04878f04aa074e29fdcb303a9962df0bec8 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Mon, 26 Oct 2020 16:40:51 -0400 Subject: [PATCH 29/81] 6774 use file for content viewers when artifact type is TSK_WEB_CACHE --- .../ui/ContentViewerDetailsPanel.form | 3 ++- .../ui/ContentViewerDetailsPanel.java | 27 +++++++++++++++++-- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/ContentViewerDetailsPanel.form b/Core/src/org/sleuthkit/autopsy/discovery/ui/ContentViewerDetailsPanel.form index ec22ddd1a6..2c7924e2a4 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/ContentViewerDetailsPanel.form +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/ContentViewerDetailsPanel.form @@ -1,6 +1,6 @@ - + @@ -11,6 +11,7 @@ + diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/ContentViewerDetailsPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/ContentViewerDetailsPanel.java index a2ee50a775..79f81c04c8 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/ContentViewerDetailsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/ContentViewerDetailsPanel.java @@ -5,10 +5,17 @@ */ package org.sleuthkit.autopsy.discovery.ui; +import java.util.logging.Level; import org.openide.nodes.Node; +import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.corecomponents.DataContentPanel; +import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode; +import org.sleuthkit.autopsy.datamodel.FileNode; import org.sleuthkit.datamodel.BlackboardArtifact; +import org.sleuthkit.datamodel.BlackboardAttribute; +import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH_ID; +import org.sleuthkit.datamodel.TskCoreException; /** * Details panel for displaying the collection of content viewers. @@ -16,7 +23,8 @@ import org.sleuthkit.datamodel.BlackboardArtifact; class ContentViewerDetailsPanel extends AbstractArtifactDetailsPanel { private static final long serialVersionUID = 1L; - private final DataContentPanel contentViewer = DataContentPanel.createInstance(); + private final static Logger logger = Logger.getLogger(ContentViewerDetailsPanel.class.getName()); + private final DataContentPanel contentViewer = DataContentPanel.createInstance(); /** * Creates new form ContentViewerDetailsPanel @@ -42,7 +50,22 @@ class ContentViewerDetailsPanel extends AbstractArtifactDetailsPanel { public void setArtifact(BlackboardArtifact artifact) { Node node = Node.EMPTY; if (artifact != null) { - node = new BlackboardArtifactNode(artifact); + if (artifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE.getTypeID()) { + try { + for (BlackboardAttribute attr : artifact.getAttributes()) { + if (attr.getAttributeType().getTypeID() == TSK_PATH_ID.getTypeID()) { + node = new FileNode(Case.getCurrentCase().getSleuthkitCase().getAbstractFileById(attr.getValueLong())); + break; + } + } + } catch (TskCoreException ex) { + logger.log(Level.WARNING, "Unable to retrieve attributes for artifact with ID: " + artifact.getArtifactID(), ex); + } + } + if (node.equals(Node.EMPTY)) { + node = new BlackboardArtifactNode(artifact); + } + } contentViewer.setNode(node); } From 7a76f253bef9d48bd56707a33e64f331161cb22a Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Mon, 26 Oct 2020 16:41:53 -0400 Subject: [PATCH 30/81] 6773 fix indexing into model --- .../org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java index 50663c168c..2d0d9e6dc7 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java @@ -79,7 +79,7 @@ class ArtifactsListPanel extends JPanel { if (selectedIndex < jTable1.getSelectionModel().getMinSelectionIndex() || jTable1.getSelectionModel().getMaxSelectionIndex() < 0 || selectedIndex > jTable1.getSelectionModel().getMaxSelectionIndex()) { return null; } - return tableModel.getArtifactByRow(jTable1.convertRowIndexToView(selectedIndex)); + return tableModel.getArtifactByRow(jTable1.convertRowIndexToModel(selectedIndex)); } /** From 555c9037556af9e8f2e09cb0c8e7d53ed6e87497 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Tue, 27 Oct 2020 12:06:11 -0400 Subject: [PATCH 31/81] 6774 get content for lookup for downloads and caches based on path id --- .../datamodel/BlackboardArtifactNode.java | 51 +++++++++++++++---- 1 file changed, 40 insertions(+), 11 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java index c7ccf32099..596e800a95 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java @@ -128,8 +128,8 @@ public class BlackboardArtifactNode extends AbstractContentNode artifact.getSleuthkitCase().getContentById(objectID)); - if (content == null) { - return Lookups.fixed(artifact); - } else { - return Lookups.fixed(artifact, content); + Content content = null; + if (artifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD.getTypeID() || artifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE.getTypeID()) { + content = getPathIdFile(artifact); + } else { + try { + content = contentCache.get(objectID, () -> artifact.getSleuthkitCase().getContentById(objectID)); + } catch (ExecutionException ex) { + logger.log(Level.SEVERE, MessageFormat.format("Error getting source content (artifact objID={0}", artifact.getId()), ex); //NON-NLS + content = null; } - } catch (ExecutionException ex) { - logger.log(Level.SEVERE, MessageFormat.format("Error getting source content (artifact objID={0}", artifact.getId()), ex); //NON-NLS - return Lookups.fixed(artifact); } + if (content == null) { + return Lookups.fixed(artifact); + } else { + return Lookups.fixed(artifact, content); + } + + } + + /** + * Private helper method to allow content specified in a path id attribute + * to be retrieved. + * + * @param artifact The artifact which content may be specified as a tsk path + * attribute. + * + * @return The Content specified by the artifact's path id attribute or null + * if there was no content available. + */ + private static Content getPathIdFile(BlackboardArtifact artifact) { + try { + for (BlackboardAttribute attribute : artifact.getAttributes()) { + if (attribute.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH_ID.getTypeID()) { + return artifact.getSleuthkitCase().getContentById(attribute.getValueLong()); + } + } + } catch (TskCoreException ex) { + logger.log(Level.WARNING, MessageFormat.format("Error getting content for path id attrbiute for artifact: ", artifact.getId()), ex); //NON-NLS + } + return null; } /** From 2dd79d668cbd71cbcdc46f9a35fdac5b83bf6d87 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Tue, 27 Oct 2020 12:47:19 -0400 Subject: [PATCH 32/81] 6774 remove changes for path id from discovery --- .../ui/ContentViewerDetailsPanel.java | 46 ++++++++----------- 1 file changed, 18 insertions(+), 28 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/ContentViewerDetailsPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/ContentViewerDetailsPanel.java index 79f81c04c8..850dc26bd0 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/ContentViewerDetailsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/ContentViewerDetailsPanel.java @@ -1,29 +1,34 @@ /* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. + * Autopsy + * + * Copyright 2020 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.sleuthkit.autopsy.discovery.ui; -import java.util.logging.Level; import org.openide.nodes.Node; -import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.corecomponents.DataContentPanel; -import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode; -import org.sleuthkit.autopsy.datamodel.FileNode; import org.sleuthkit.datamodel.BlackboardArtifact; -import org.sleuthkit.datamodel.BlackboardAttribute; -import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH_ID; -import org.sleuthkit.datamodel.TskCoreException; /** * Details panel for displaying the collection of content viewers. */ -class ContentViewerDetailsPanel extends AbstractArtifactDetailsPanel { +final class ContentViewerDetailsPanel extends AbstractArtifactDetailsPanel { private static final long serialVersionUID = 1L; - private final static Logger logger = Logger.getLogger(ContentViewerDetailsPanel.class.getName()); private final DataContentPanel contentViewer = DataContentPanel.createInstance(); /** @@ -50,22 +55,7 @@ class ContentViewerDetailsPanel extends AbstractArtifactDetailsPanel { public void setArtifact(BlackboardArtifact artifact) { Node node = Node.EMPTY; if (artifact != null) { - if (artifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE.getTypeID()) { - try { - for (BlackboardAttribute attr : artifact.getAttributes()) { - if (attr.getAttributeType().getTypeID() == TSK_PATH_ID.getTypeID()) { - node = new FileNode(Case.getCurrentCase().getSleuthkitCase().getAbstractFileById(attr.getValueLong())); - break; - } - } - } catch (TskCoreException ex) { - logger.log(Level.WARNING, "Unable to retrieve attributes for artifact with ID: " + artifact.getArtifactID(), ex); - } - } - if (node.equals(Node.EMPTY)) { - node = new BlackboardArtifactNode(artifact); - } - + node = new BlackboardArtifactNode(artifact); } contentViewer.setNode(node); } From f6fa07b5d5bb31fe7d69a825ef63bce8dae249f7 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Tue, 27 Oct 2020 13:08:18 -0400 Subject: [PATCH 33/81] 6773 adjust comments remove unnecessary code --- .../autopsy/discovery/ui/ArtifactsListPanel.java | 4 ++++ .../autopsy/discovery/ui/ArtifactsWorker.java | 2 +- .../autopsy/discovery/ui/DiscoveryTopComponent.form | 1 - .../autopsy/discovery/ui/DiscoveryTopComponent.java | 10 ---------- .../autopsy/discovery/ui/DomainArtifactsTabPanel.java | 8 +++++++- 5 files changed, 12 insertions(+), 13 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java index 2d0d9e6dc7..c717efed38 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java @@ -92,6 +92,10 @@ class ArtifactsListPanel extends JPanel { return tableModel.getRowCount() <= 0; } + /** + * Select the first available artifact in the list if it is not empty to + * populate the panel to the right. + */ void selectFirst() { if (!isEmpty()) { jTable1.setRowSelectionInterval(0, 0); diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsWorker.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsWorker.java index fb53ec95ac..eeb6870df2 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsWorker.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsWorker.java @@ -1,7 +1,7 @@ /* * Autopsy * - * Copyright 2019-2020 Basis Technology Corp. + * Copyright 2020 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/DiscoveryTopComponent.form b/Core/src/org/sleuthkit/autopsy/discovery/ui/DiscoveryTopComponent.form index 2c828a28bc..c84525148c 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/DiscoveryTopComponent.form +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/DiscoveryTopComponent.form @@ -50,7 +50,6 @@ - diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/DiscoveryTopComponent.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/DiscoveryTopComponent.java index 16f5b1b16e..1b51a6fa54 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/DiscoveryTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/DiscoveryTopComponent.java @@ -149,7 +149,6 @@ public final class DiscoveryTopComponent extends TopComponent { DiscoveryEventUtils.getDiscoveryEventBus().unregister(groupListPanel); DiscoveryEventUtils.getDiscoveryEventBus().unregister(resultsPanel); DiscoveryEventUtils.getDiscoveryEventBus().unregister(rightSplitPane.getBottomComponent()); - setDetailsVisible(false); super.componentClosed(); } @@ -180,9 +179,6 @@ public final class DiscoveryTopComponent extends TopComponent { rightSplitPane.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT); rightSplitPane.setResizeWeight(1.0); rightSplitPane.setPreferredSize(new java.awt.Dimension(800, 700)); - - setDetailsVisible(false); - mainSplitPane.setRightComponent(rightSplitPane); add(mainSplitPane, java.awt.BorderLayout.CENTER); @@ -293,11 +289,6 @@ public final class DiscoveryTopComponent extends TopComponent { progressMessageTextArea.setText(Bundle.DiscoveryTopComponent_searchInProgress_text(searchType.name())); } - private void setDetailsVisible(boolean isVisible) { - rightSplitPane.getComponent(1).setVisible(isVisible); - rightSplitPane.getComponent(2).setVisible(isVisible); - } - /** * Subscribe to the SearchCompleteEvent for updating the UI accordingly. * @@ -324,7 +315,6 @@ public final class DiscoveryTopComponent extends TopComponent { } else { rightSplitPane.setBottomComponent(new FileDetailsPanel()); } - setDetailsVisible(true); DiscoveryEventUtils.getDiscoveryEventBus().register(rightSplitPane.getBottomComponent()); descriptionText += searchCompleteEvent.getFilters().stream().map(AbstractFilter::getDesc).collect(Collectors.joining("; ")); progressMessageTextArea.setText(Bundle.DiscoveryTopComponent_searchComplete_text(descriptionText)); diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.java index 2d5bafbbc8..c793e3306e 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.java @@ -102,10 +102,16 @@ final class DomainArtifactsTabPanel extends JPanel { void setStatus(ArtifactRetrievalStatus status) { this.status = status; if (status == ArtifactRetrievalStatus.UNPOPULATED && rightPanel != null) { - rightPanel.setArtifact(null); + rightPanel.setArtifact(null); } } + /** + * Handle the event which indicates the artifacts have been retrieved. + * + * @param artifactListEvent The event which indicates the artifacts have + * been retrieved. + */ @Subscribe void handleArtifactListRetrievedEvent(DiscoveryEventUtils.ArtifactListRetrievedEvent artifactListEvent) { SwingUtilities.invokeLater(() -> { From 71696390a094fe2f75a5e63f2a77e64ae6a7f20a Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Tue, 27 Oct 2020 13:14:21 -0400 Subject: [PATCH 34/81] 6774 attempt to address codacy issues --- .../discovery/ui/ArtifactsListPanel.java | 22 ++++++++++--------- .../discovery/ui/DomainDetailsPanel.java | 2 ++ 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java index 8751458633..a08076529c 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java @@ -228,18 +228,20 @@ class ArtifactsListPanel extends JPanel { return ""; } for (BlackboardAttribute bba : getArtifactByRow(rowIndex).getAttributes()) { - if (columnIndex == 0 && bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID() && !StringUtils.isBlank(bba.getDisplayString())) { - return bba.getDisplayString(); - } else if (columnIndex == 1) { - if (bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TITLE.getTypeID() && artifactType != BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD && !StringUtils.isBlank(bba.getDisplayString())) { + if (!StringUtils.isBlank(bba.getDisplayString())) { + if (columnIndex == 0 && bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID()) { return bba.getDisplayString(); - } else if (artifactType == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE && bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH_ID.getTypeID() && !StringUtils.isBlank(bba.getDisplayString())) { - return Case.getCurrentCase().getSleuthkitCase().getAbstractFileById(bba.getValueLong()).getName(); - } else if (bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH.getTypeID() && artifactType == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD) { - return FilenameUtils.getName(bba.getDisplayString()); + } else if (columnIndex == 1) { + if (bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TITLE.getTypeID() && artifactType != BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD) { + return bba.getDisplayString(); + } else if (artifactType == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE && bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH_ID.getTypeID()) { + return Case.getCurrentCase().getSleuthkitCase().getAbstractFileById(bba.getValueLong()).getName(); + } else if (bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH.getTypeID() && artifactType == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD) { + return FilenameUtils.getName(bba.getDisplayString()); + } + } else if (columnIndex == 2 && artifactType == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE && bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH_ID.getTypeID()) { + return Case.getCurrentCase().getSleuthkitCase().getAbstractFileById(bba.getValueLong()).getMIMEType(); } - } else if (columnIndex == 2 && artifactType == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE && bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH_ID.getTypeID() && !StringUtils.isBlank(bba.getDisplayString())) { - return Case.getCurrentCase().getSleuthkitCase().getAbstractFileById(bba.getValueLong()).getMIMEType(); } } return getFallbackValue(rowIndex, columnIndex); diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.java index 5fcde7ca77..634fe86ffe 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.java @@ -50,6 +50,8 @@ final class DomainDetailsPanel extends JPanel { DomainDetailsPanel(ARTIFACT_TYPE initialSelectedTab) { if (initialSelectedTab != null) { selectedTabName = initialSelectedTab.getDisplayName(); + } else { + selectedTabName = null; } initComponents(); addArtifactTabs(); From 634a2bbdbbcbf5c8e348400725abeb62ba586f9e Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Tue, 27 Oct 2020 13:23:11 -0400 Subject: [PATCH 35/81] 6774 fix assignment to static variable in constructor --- .../sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.java index 634fe86ffe..1eb09933f5 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.java @@ -39,7 +39,7 @@ final class DomainDetailsPanel extends JPanel { private static final long serialVersionUID = 1L; private static ArtifactsWorker detailsWorker; private static String domain; - private static String selectedTabName; + private String selectedTabName; /** * Creates new form ArtifactDetailsPanel @@ -50,9 +50,7 @@ final class DomainDetailsPanel extends JPanel { DomainDetailsPanel(ARTIFACT_TYPE initialSelectedTab) { if (initialSelectedTab != null) { selectedTabName = initialSelectedTab.getDisplayName(); - } else { - selectedTabName = null; - } + } initComponents(); addArtifactTabs(); } From b198b9e31afb89346765433a7041e5b90b63041c Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Tue, 27 Oct 2020 13:43:04 -0400 Subject: [PATCH 36/81] 6774 attempt to lower cyclomatic complexity --- .../discovery/ui/ArtifactsListPanel.java | 46 ++++++++++++++----- 1 file changed, 34 insertions(+), 12 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java index a08076529c..05ceac3333 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java @@ -227,11 +227,30 @@ class ArtifactsListPanel extends JPanel { if (columnIndex == 2 && artifactType != BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE) { return ""; } - for (BlackboardAttribute bba : getArtifactByRow(rowIndex).getAttributes()) { - if (!StringUtils.isBlank(bba.getDisplayString())) { - if (columnIndex == 0 && bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID()) { - return bba.getDisplayString(); - } else if (columnIndex == 1) { + return getStringForArtifact(rowIndex, columnIndex); + } catch (TskCoreException ex) { + logger.log(Level.WARNING, "Error getting attributes for artifact " + getArtifactByRow(rowIndex).getArtifactID(), ex); + return Bundle.ArtifactsListPanel_value_noValue(); + } + } + + /** + * + * @param rowIndex + * @param columnIndex + * @return + * @throws TskCoreException + */ + private String getStringForArtifact(int rowIndex, int columnIndex) throws TskCoreException { + for (BlackboardAttribute bba : getArtifactByRow(rowIndex).getAttributes()) { + if (!StringUtils.isBlank(bba.getDisplayString())) { + switch (columnIndex) { + case 0: + if (bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID()) { + return bba.getDisplayString(); + } + break; + case 1: if (bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TITLE.getTypeID() && artifactType != BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD) { return bba.getDisplayString(); } else if (artifactType == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE && bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH_ID.getTypeID()) { @@ -239,16 +258,19 @@ class ArtifactsListPanel extends JPanel { } else if (bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH.getTypeID() && artifactType == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD) { return FilenameUtils.getName(bba.getDisplayString()); } - } else if (columnIndex == 2 && artifactType == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE && bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH_ID.getTypeID()) { - return Case.getCurrentCase().getSleuthkitCase().getAbstractFileById(bba.getValueLong()).getMIMEType(); - } + break; + case 2: + if (artifactType == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE && bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH_ID.getTypeID()) { + return Case.getCurrentCase().getSleuthkitCase().getAbstractFileById(bba.getValueLong()).getMIMEType(); + } + break; + default: + //default is to do nothing } } - return getFallbackValue(rowIndex, columnIndex); - } catch (TskCoreException ex) { - logger.log(Level.WARNING, "Error getting attributes for artifact " + getArtifactByRow(rowIndex).getArtifactID(), ex); - return Bundle.ArtifactsListPanel_value_noValue(); } + return getFallbackValue(rowIndex, columnIndex); + } /** From f45f4e72c9517ad4752124c91ec97c1a50253eb0 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Tue, 27 Oct 2020 13:54:03 -0400 Subject: [PATCH 37/81] 6774 attempt to lower cyclomatic complexity --- .../discovery/ui/ArtifactsListPanel.java | 67 ++++++++++--------- 1 file changed, 36 insertions(+), 31 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java index 05ceac3333..0437095f69 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java @@ -227,7 +227,15 @@ class ArtifactsListPanel extends JPanel { if (columnIndex == 2 && artifactType != BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE) { return ""; } - return getStringForArtifact(rowIndex, columnIndex); + for (BlackboardAttribute bba : getArtifactByRow(rowIndex).getAttributes()) { + if (!StringUtils.isBlank(bba.getDisplayString())) { + String stringFromAttribute = getStringForColumn(bba, columnIndex); + if (!StringUtils.isBlank(stringFromAttribute)) { + return stringFromAttribute; + } + } + } + return getFallbackValue(rowIndex, columnIndex); } catch (TskCoreException ex) { logger.log(Level.WARNING, "Error getting attributes for artifact " + getArtifactByRow(rowIndex).getArtifactID(), ex); return Bundle.ArtifactsListPanel_value_noValue(); @@ -235,42 +243,39 @@ class ArtifactsListPanel extends JPanel { } /** - * + * * @param rowIndex * @param columnIndex + * * @return - * @throws TskCoreException + * + * @throws TskCoreException */ - private String getStringForArtifact(int rowIndex, int columnIndex) throws TskCoreException { - for (BlackboardAttribute bba : getArtifactByRow(rowIndex).getAttributes()) { - if (!StringUtils.isBlank(bba.getDisplayString())) { - switch (columnIndex) { - case 0: - if (bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID()) { - return bba.getDisplayString(); - } - break; - case 1: - if (bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TITLE.getTypeID() && artifactType != BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD) { - return bba.getDisplayString(); - } else if (artifactType == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE && bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH_ID.getTypeID()) { - return Case.getCurrentCase().getSleuthkitCase().getAbstractFileById(bba.getValueLong()).getName(); - } else if (bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH.getTypeID() && artifactType == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD) { - return FilenameUtils.getName(bba.getDisplayString()); - } - break; - case 2: - if (artifactType == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE && bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH_ID.getTypeID()) { - return Case.getCurrentCase().getSleuthkitCase().getAbstractFileById(bba.getValueLong()).getMIMEType(); - } - break; - default: - //default is to do nothing + private String getStringForColumn(BlackboardAttribute bba, int columnIndex) throws TskCoreException { + switch (columnIndex) { + case 0: + if (bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID()) { + return bba.getDisplayString(); } - } + break; + case 1: + if (bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TITLE.getTypeID() && artifactType != BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD) { + return bba.getDisplayString(); + } else if (artifactType == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE && bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH_ID.getTypeID()) { + return Case.getCurrentCase().getSleuthkitCase().getAbstractFileById(bba.getValueLong()).getName(); + } else if (bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH.getTypeID() && artifactType == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD) { + return FilenameUtils.getName(bba.getDisplayString()); + } + break; + case 2: + if (artifactType == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE && bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH_ID.getTypeID()) { + return Case.getCurrentCase().getSleuthkitCase().getAbstractFileById(bba.getValueLong()).getMIMEType(); + } + break; + default: + //default is to do nothing } - return getFallbackValue(rowIndex, columnIndex); - + return ""; } /** From c050f52087c3b8faab904876478c22683e7a977a Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Tue, 27 Oct 2020 14:04:54 -0400 Subject: [PATCH 38/81] 6774 attempt to lower cyclomatic complexity --- .../discovery/ui/ArtifactsListPanel.java | 74 +++++++++---------- 1 file changed, 34 insertions(+), 40 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java index 0437095f69..dc0d522657 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java @@ -223,59 +223,53 @@ class ArtifactsListPanel extends JPanel { @NbBundle.Messages({"ArtifactsListPanel.value.noValue=No value available."}) @Override public Object getValueAt(int rowIndex, int columnIndex) { - try { - if (columnIndex == 2 && artifactType != BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE) { - return ""; - } - for (BlackboardAttribute bba : getArtifactByRow(rowIndex).getAttributes()) { - if (!StringUtils.isBlank(bba.getDisplayString())) { - String stringFromAttribute = getStringForColumn(bba, columnIndex); - if (!StringUtils.isBlank(stringFromAttribute)) { - return stringFromAttribute; + if (columnIndex < 2 || artifactType == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE) { + try { + for (BlackboardAttribute bba : getArtifactByRow(rowIndex).getAttributes()) { + if (!StringUtils.isBlank(bba.getDisplayString())) { + String stringFromAttribute = getStringForColumn(bba, columnIndex); + if (!StringUtils.isBlank(stringFromAttribute)) { + return stringFromAttribute; + } } } + return getFallbackValue(rowIndex, columnIndex); + } catch (TskCoreException ex) { + logger.log(Level.WARNING, "Error getting attributes for artifact " + getArtifactByRow(rowIndex).getArtifactID(), ex); } - return getFallbackValue(rowIndex, columnIndex); - } catch (TskCoreException ex) { - logger.log(Level.WARNING, "Error getting attributes for artifact " + getArtifactByRow(rowIndex).getArtifactID(), ex); - return Bundle.ArtifactsListPanel_value_noValue(); } + return Bundle.ArtifactsListPanel_value_noValue(); } /** + * Get the appropriate String for the specified column from the + * BlackboardAttribute. * - * @param rowIndex - * @param columnIndex + * @param bba The BlackboardAttribute which may contain a value. + * @param columnIndex The column the value will be displayed in. * - * @return + * @return The value from the specified attribute which should be + * displayed in the specified column, null if the specified + * attribute does not contain a value for that column. * - * @throws TskCoreException + * @throws TskCoreException When unable to get abstract files based on + * the TSK_PATH_ID. */ private String getStringForColumn(BlackboardAttribute bba, int columnIndex) throws TskCoreException { - switch (columnIndex) { - case 0: - if (bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID()) { - return bba.getDisplayString(); - } - break; - case 1: - if (bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TITLE.getTypeID() && artifactType != BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD) { - return bba.getDisplayString(); - } else if (artifactType == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE && bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH_ID.getTypeID()) { - return Case.getCurrentCase().getSleuthkitCase().getAbstractFileById(bba.getValueLong()).getName(); - } else if (bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH.getTypeID() && artifactType == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD) { - return FilenameUtils.getName(bba.getDisplayString()); - } - break; - case 2: - if (artifactType == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE && bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH_ID.getTypeID()) { - return Case.getCurrentCase().getSleuthkitCase().getAbstractFileById(bba.getValueLong()).getMIMEType(); - } - break; - default: - //default is to do nothing + if (columnIndex == 0 && bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID()) { + return bba.getDisplayString(); + } else if (columnIndex == 1) { + if (bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TITLE.getTypeID() && artifactType != BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD) { + return bba.getDisplayString(); + } else if (artifactType == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE && bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH_ID.getTypeID()) { + return Case.getCurrentCase().getSleuthkitCase().getAbstractFileById(bba.getValueLong()).getName(); + } else if (bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH.getTypeID() && artifactType == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD) { + return FilenameUtils.getName(bba.getDisplayString()); + } + } else if (columnIndex == 2 && artifactType == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE && bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH_ID.getTypeID()) { + return Case.getCurrentCase().getSleuthkitCase().getAbstractFileById(bba.getValueLong()).getMIMEType(); } - return ""; + return null; } /** From f773075767b3404ddd1d10127b1997c97c8c943a Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Tue, 27 Oct 2020 14:13:49 -0400 Subject: [PATCH 39/81] 6774 attempt to lower cyclomatic complexity --- .../autopsy/discovery/ui/ArtifactsListPanel.java | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java index dc0d522657..6b9f0a0534 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java @@ -259,14 +259,16 @@ class ArtifactsListPanel extends JPanel { if (columnIndex == 0 && bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID()) { return bba.getDisplayString(); } else if (columnIndex == 1) { - if (bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TITLE.getTypeID() && artifactType != BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD) { + if (artifactType == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD || artifactType == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE) { + if (bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH_ID.getTypeID()) { + return Case.getCurrentCase().getSleuthkitCase().getAbstractFileById(bba.getValueLong()).getName(); + } else if (bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH.getTypeID()) { + return FilenameUtils.getName(bba.getDisplayString()); + } + } else if (bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TITLE.getTypeID()) { return bba.getDisplayString(); - } else if (artifactType == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE && bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH_ID.getTypeID()) { - return Case.getCurrentCase().getSleuthkitCase().getAbstractFileById(bba.getValueLong()).getName(); - } else if (bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH.getTypeID() && artifactType == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD) { - return FilenameUtils.getName(bba.getDisplayString()); } - } else if (columnIndex == 2 && artifactType == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE && bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH_ID.getTypeID()) { + } else if (columnIndex == 2 && bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH_ID.getTypeID()) { return Case.getCurrentCase().getSleuthkitCase().getAbstractFileById(bba.getValueLong()).getMIMEType(); } return null; From 7756f5c7b7c1ad1ee63e7facac4b01ad4eff9e05 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Fri, 30 Oct 2020 12:00:46 -0400 Subject: [PATCH 40/81] Bug fix --- .../src/org/sleuthkit/autopsy/keywordsearch/Chunker.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Chunker.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Chunker.java index 08ca0ab511..9c9923181d 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Chunker.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Chunker.java @@ -185,7 +185,7 @@ class Chunker implements Iterator, Iterable { } private static StringBuilder sanitize(String s) { - String normStr = Normalizer.normalize(s, Normalizer.Form.NFKC); + String normStr = Normalizer.normalize(s, Normalizer.Form.NFC); return sanitizeToUTF8(replaceInvalidUTF16(normStr)); } From 60e304337e98a3ee63323152b54259001a75ab72 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Mon, 2 Nov 2020 09:39:20 -0500 Subject: [PATCH 41/81] test integration in appveyor and travis --- appveyor.yml | 4 +++- travis_build.sh | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index bc3c7fa82d..c8a705e659 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -42,4 +42,6 @@ build_script: - cd %APPVEYOR_BUILD_FOLDER% - cmd: ant -q build -test: off +test_script: + - cd %APPVEYOR_BUILD_FOLDER% + - cmd: ant -q test \ No newline at end of file diff --git a/travis_build.sh b/travis_build.sh index 5f574d5726..bf3a97e0f9 100755 --- a/travis_build.sh +++ b/travis_build.sh @@ -9,4 +9,36 @@ pushd bindings/java && ant -q dist && popd echo "Building Autopsy..." && echo -en 'travis_fold:start:script.build\\r' cd $TRAVIS_BUILD_DIR/ ant build +build_rc=$? echo -en 'travis_fold:end:script.build\\r' + +# don't continue to test if build failed. +if [[ $build_rc != 0 ]]; then + echo "Build failed. Not continuing to tests." + exit $build_rc +fi + +echo "Testing Autopsy..." && echo -en 'travis_fold:start:script.tests\\r' +cd Core/ +echo "Testing Autopsy Core..." +echo "Free Space:" +echo `df -h .` +xvfb-run ant -q test +core_test_rc=$? +cd ../KeywordSearch +echo "Testing Autopsy Keyword Search..." +echo "Free Space:" +echo `df -h .` +xvfb-run ant -q test +keywordsearch_test_rc=$? +echo -en 'travis_fold:end:script.tests\\r' + +if [ $core_test_rc != 0 ] || [$keywordsearch_test_rc != 0]; then + echo "There was a test failure." + + if [$core_test_rc != 0]; then + exit $core_test_rc + elif [$keywordsearch_test_rc != 0]; then + exit $keywordsearch_test_rc + fi +fi \ No newline at end of file From 40f35e713c485b80b9b6f94f440292a1f4eb950c Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Mon, 2 Nov 2020 10:20:54 -0500 Subject: [PATCH 42/81] just run all tests --- travis_build.sh | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/travis_build.sh b/travis_build.sh index bf3a97e0f9..974558161e 100755 --- a/travis_build.sh +++ b/travis_build.sh @@ -19,26 +19,14 @@ if [[ $build_rc != 0 ]]; then fi echo "Testing Autopsy..." && echo -en 'travis_fold:start:script.tests\\r' -cd Core/ -echo "Testing Autopsy Core..." echo "Free Space:" echo `df -h .` xvfb-run ant -q test -core_test_rc=$? -cd ../KeywordSearch -echo "Testing Autopsy Keyword Search..." -echo "Free Space:" -echo `df -h .` -xvfb-run ant -q test -keywordsearch_test_rc=$? +test_rc=$? echo -en 'travis_fold:end:script.tests\\r' +exit $test_rc -if [ $core_test_rc != 0 ] || [$keywordsearch_test_rc != 0]; then +if [[ $test_rc != 0 ]]; then echo "There was a test failure." - - if [$core_test_rc != 0]; then - exit $core_test_rc - elif [$keywordsearch_test_rc != 0]; then - exit $keywordsearch_test_rc - fi + exit $test_rc fi \ No newline at end of file From b0c66538ec2f64d0a38bd09a38e45a1bd382cc99 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Mon, 2 Nov 2020 12:21:08 -0500 Subject: [PATCH 43/81] Fixed a bug in 32k chunking --- .../autopsy/keywordsearch/Chunker.java | 39 +++++++++++++------ 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Chunker.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Chunker.java index 9c9923181d..fd0f11ab74 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Chunker.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Chunker.java @@ -185,9 +185,8 @@ class Chunker implements Iterator, Iterable { } private static StringBuilder sanitize(String s) { - String normStr = Normalizer.normalize(s, Normalizer.Form.NFC); + String normStr = Normalizer.normalize(s, Normalizer.Form.NFKC); return sanitizeToUTF8(replaceInvalidUTF16(normStr)); - } @Override @@ -336,8 +335,9 @@ class Chunker implements Iterator, Iterable { String chunkSegment; if (Character.isHighSurrogate(ch)) { //read another char into the buffer. - charsRead = reader.read(tempChunkBuf, 1, 1); - if (charsRead == -1) { + int surrogateCharsRead = reader.read(tempChunkBuf, 1, 1); + charsRead += surrogateCharsRead; + if (surrogateCharsRead == -1) { //this is the last chunk, so just drop the unpaired surrogate endOfReaderReached = true; return; @@ -352,17 +352,32 @@ class Chunker implements Iterator, Iterable { //cleanup any invalid utf-16 sequences StringBuilder sanitizedChunkSegment = sanitize(chunkSegment); - //check for whitespace. - whitespaceFound = Character.isWhitespace(sanitizedChunkSegment.codePointAt(0)); - //add read chars to the chunk and update the length. - currentChunk.append(sanitizedChunkSegment); - chunkSizeBytes += sanitizedChunkSegment.toString().getBytes(UTF_8).length; - + //get the length in utf8 bytes of the read chars + int segmentSize = chunkSegment.getBytes(UTF_8).length; + // lower case the string and get it's size. NOTE: lower casing can // change the size of the string. String lowerCasedSegment = sanitizedChunkSegment.toString().toLowerCase(); - lowerCasedChunk.append(lowerCasedSegment); - lowerCasedChunkSizeBytes += lowerCasedSegment.getBytes(UTF_8).length; + int lowerCasedSegmentSize = lowerCasedSegment.getBytes(UTF_8).length; + + //if it will not put us past maxBytes + if ((chunkSizeBytes + segmentSize < maxBytes - MAX_CHAR_SIZE_INCREASE_IN_BYTES) + && (lowerCasedChunkSizeBytes + lowerCasedSegmentSize < maxBytes - MAX_CHAR_SIZE_INCREASE_IN_BYTES)) { + + //add read chars to the chunk and update the length. + currentChunk.append(sanitizedChunkSegment); + chunkSizeBytes += segmentSize; + + lowerCasedChunk.append(lowerCasedSegment); + lowerCasedChunkSizeBytes += lowerCasedSegmentSize; + + //check for whitespace. + whitespaceFound = Character.isWhitespace(sanitizedChunkSegment.codePointAt(0)); + } else { + //unread it, and break out of read loop. + reader.unread(tempChunkBuf, 0, charsRead); + return; + } } } } From eee465f77028a2200bbce804af6cbc27f43c7634 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Mon, 2 Nov 2020 13:51:40 -0500 Subject: [PATCH 44/81] create and use new test-no-regression ant target in root build.xml --- appveyor.yml | 2 +- build.xml | 88 +++++++++++++++++++++++++++++++++---------------- travis_build.sh | 18 ++-------- 3 files changed, 63 insertions(+), 45 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index c8a705e659..7a83f20590 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -44,4 +44,4 @@ build_script: test_script: - cd %APPVEYOR_BUILD_FOLDER% - - cmd: ant -q test \ No newline at end of file + - cmd: ant -q test-no-regression \ No newline at end of file diff --git a/build.xml b/build.xml index 7377d59c04..c4cb67b944 100644 --- a/build.xml +++ b/build.xml @@ -24,7 +24,7 @@ + unless="supported-java-versions"/> @@ -68,22 +68,54 @@ - + - + - + + + + + + + + + + + + + + + + + + ZIP target and then opens it up and adds in any files that we want. This is where we customize the + version number. --> @@ -128,15 +160,15 @@ - - - - - - - - - + + + + + + + + + @@ -146,9 +178,9 @@ + shadow the files in the autopsy/modules/lib/ARCHITECTURE folder in the JAR. + These files are legacy from when we used to copy the dlls to this location. + This check should do away in the future. Added Sept '13--> @@ -188,9 +220,9 @@ + message="Enter the desired build type:" + validargs="DEVELOPMENT,RELEASE" + defaultvalue="DEVELOPMENT"/> @@ -228,21 +260,21 @@ ${app.name} branding + file="${branding.dir}/core/core.jar/org/netbeans/core/startup/Bundle.properties" + comment="Updated by build script"> + file="${branding.dir}/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties" + comment="Updated by build script"> + file="${basedir}/Core/src/org/sleuthkit/autopsy/coreutils/Version.properties" + comment="Updated by build script"> @@ -329,7 +361,7 @@ - + diff --git a/travis_build.sh b/travis_build.sh index 974558161e..aec6d5a5ea 100755 --- a/travis_build.sh +++ b/travis_build.sh @@ -9,24 +9,10 @@ pushd bindings/java && ant -q dist && popd echo "Building Autopsy..." && echo -en 'travis_fold:start:script.build\\r' cd $TRAVIS_BUILD_DIR/ ant build -build_rc=$? echo -en 'travis_fold:end:script.build\\r' -# don't continue to test if build failed. -if [[ $build_rc != 0 ]]; then - echo "Build failed. Not continuing to tests." - exit $build_rc -fi - echo "Testing Autopsy..." && echo -en 'travis_fold:start:script.tests\\r' echo "Free Space:" echo `df -h .` -xvfb-run ant -q test -test_rc=$? -echo -en 'travis_fold:end:script.tests\\r' -exit $test_rc - -if [[ $test_rc != 0 ]]; then - echo "There was a test failure." - exit $test_rc -fi \ No newline at end of file +xvfb-run ant -q test-no-regression +echo -en 'travis_fold:end:script.tests\\r' \ No newline at end of file From 7f54d0d1a5a70bb7b6cd3299451e0d30be0c4d20 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Mon, 2 Nov 2020 21:26:23 -0500 Subject: [PATCH 45/81] don't use xvfb on osx --- travis_build.sh | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/travis_build.sh b/travis_build.sh index aec6d5a5ea..35b1cd542e 100755 --- a/travis_build.sh +++ b/travis_build.sh @@ -14,5 +14,13 @@ echo -en 'travis_fold:end:script.build\\r' echo "Testing Autopsy..." && echo -en 'travis_fold:start:script.tests\\r' echo "Free Space:" echo `df -h .` -xvfb-run ant -q test-no-regression + +if [ "${TRAVIS_OS_NAME}" = "osx" ]; then + # if os x, just run it + ant -q test-no-regression +elif [ "${TRAVIS_OS_NAME}" = "linux" ]; then + # if linux use xvfb + xvfb-run ant -q test-no-regression +fi + echo -en 'travis_fold:end:script.tests\\r' \ No newline at end of file From 65a1062ce2c8f311d8af62818a9d2fad64f3219e Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Tue, 3 Nov 2020 06:52:35 -0500 Subject: [PATCH 46/81] quiet build output --- travis_build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/travis_build.sh b/travis_build.sh index 35b1cd542e..ba708e420b 100755 --- a/travis_build.sh +++ b/travis_build.sh @@ -8,7 +8,7 @@ pushd bindings/java && ant -q dist && popd echo "Building Autopsy..." && echo -en 'travis_fold:start:script.build\\r' cd $TRAVIS_BUILD_DIR/ -ant build +ant -q build echo -en 'travis_fold:end:script.build\\r' echo "Testing Autopsy..." && echo -en 'travis_fold:start:script.tests\\r' From b7c05e42797ddf3833cf7c69a0a8ffb44f883c33 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Tue, 3 Nov 2020 08:17:33 -0500 Subject: [PATCH 47/81] formatting fix --- appveyor.yml | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 7a83f20590..fe70c36850 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -6,14 +6,13 @@ cache: - C:\ProgramData\chocolatey\lib - '%APPVEYOR_BUILD_FOLDER%\Core\test\qa-functional\data' - image: Visual Studio 2015 platform: x64 environment: - global: - TSK_HOME: "C:\\sleuthkit" - JDK_HOME: C:\Program Files\Java\jdk1.8.0 - PYTHON: "C:\\Python36-x64" + global: + TSK_HOME: "C:\\sleuthkit" + JDK_HOME: C:\Program Files\Java\jdk1.8.0 + PYTHON: "C:\\Python36-x64" install: - ps: choco install nuget.commandline @@ -44,4 +43,4 @@ build_script: test_script: - cd %APPVEYOR_BUILD_FOLDER% - - cmd: ant -q test-no-regression \ No newline at end of file + - cmd: ant -q test-no-regression From 7c6d3453e2d10156eabdc7e5049078e7f6c193fa Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Tue, 3 Nov 2020 08:19:37 -0500 Subject: [PATCH 48/81] formatting fix --- travis_build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/travis_build.sh b/travis_build.sh index ba708e420b..d3753fd934 100755 --- a/travis_build.sh +++ b/travis_build.sh @@ -23,4 +23,4 @@ elif [ "${TRAVIS_OS_NAME}" = "linux" ]; then xvfb-run ant -q test-no-regression fi -echo -en 'travis_fold:end:script.tests\\r' \ No newline at end of file +echo -en 'travis_fold:end:script.tests\\r' From 69635cbe7327f91d15aa4b951411340a6d1b23fc Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Tue, 3 Nov 2020 13:48:08 -0500 Subject: [PATCH 49/81] 6774 fix resultsviewer priority and source for cache and downloads --- .../DataContentViewerArtifact.java | 4 +++- .../datamodel/BlackboardArtifactNode.java | 24 +++++++++++-------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerArtifact.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerArtifact.java index 6ccc70c920..b015dbf3ad 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerArtifact.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerArtifact.java @@ -357,7 +357,9 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat || (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID()) || (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_OBJECT_DETECTED.getTypeID()) || (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_METADATA_EXIF.getTypeID()) - || (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_EXT_MISMATCH_DETECTED.getTypeID())) { + || (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_EXT_MISMATCH_DETECTED.getTypeID()) + || (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_WEB_DOWNLOAD.getTypeID()) + || (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_WEB_CACHE.getTypeID())) { return 3; } else { return 6; diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java index 596e800a95..51e9991eb0 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java @@ -285,15 +285,16 @@ public class BlackboardArtifactNode extends AbstractContentNode artifact.getSleuthkitCase().getContentById(objectID)); - } catch (ExecutionException ex) { - logger.log(Level.SEVERE, MessageFormat.format("Error getting source content (artifact objID={0}", artifact.getId()), ex); //NON-NLS - content = null; + try { + if (artifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD.getTypeID() || artifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE.getTypeID()) { + content = getPathIdFile(artifact); } + if (content == null) { + content = contentCache.get(objectID, () -> artifact.getSleuthkitCase().getContentById(objectID)); + } + } catch (ExecutionException ex) { + logger.log(Level.SEVERE, MessageFormat.format("Error getting source content (artifact objID={0}", artifact.getId()), ex); //NON-NLS + content = null; } if (content == null) { return Lookups.fixed(artifact); @@ -312,12 +313,15 @@ public class BlackboardArtifactNode extends AbstractContentNode artifact.getSleuthkitCase().getContentById(attribute.getValueLong())); } } } catch (TskCoreException ex) { From 988d1a1427c334a5606e1db96cf84f9641884718 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Tue, 3 Nov 2020 13:51:10 -0500 Subject: [PATCH 50/81] 6773 fix spelling of constraints --- .../CommunicationArtifactViewerHelper.java | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/CommunicationArtifactViewerHelper.java b/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/CommunicationArtifactViewerHelper.java index ebee74ada2..13e11d2a2d 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/CommunicationArtifactViewerHelper.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/CommunicationArtifactViewerHelper.java @@ -63,7 +63,7 @@ public final class CommunicationArtifactViewerHelper { * * @param panel Panel to update. * @param gridbagLayout Layout to use. - * @param constraints Constrains to use. + * @param constraints Constraints to use. * @param headerString Heading string to display. * * @return JLabel Heading label added. @@ -116,7 +116,7 @@ public final class CommunicationArtifactViewerHelper { * * @param panel Panel to update. * @param gridbagLayout Layout to use. - * @param constraints Constrains to use. + * @param constraints Constraints to use. * @param keyString Key name to display. * @param valueString Value string to display. * @@ -133,7 +133,7 @@ public final class CommunicationArtifactViewerHelper { * * @param panel Panel to update. * @param gridbagLayout Layout to use. - * @param constraints Constrains to use. + * @param constraints Constraints to use. * @param component Component to add. */ static void addComponent(JPanel panel, GridBagLayout gridbagLayout, GridBagConstraints constraints, JComponent component) { @@ -149,7 +149,7 @@ public final class CommunicationArtifactViewerHelper { * * @param panel Panel to update. * @param gridbagLayout Layout to use. - * @param constraints Constrains to use. + * @param constraints Constraints to use. */ static void addLineEndGlue(JPanel panel, GridBagLayout gridbagLayout, GridBagConstraints constraints) { // Place the filler just past the last column. @@ -176,7 +176,7 @@ public final class CommunicationArtifactViewerHelper { * * @param panel Panel to update. * @param gridbagLayout Layout to use. - * @param constraints Constrains to use. + * @param constraints Constraints to use. */ public static void addPageEndGlue(JPanel panel, GridBagLayout gridbagLayout, GridBagConstraints constraints) { @@ -202,7 +202,7 @@ public final class CommunicationArtifactViewerHelper { * * @param panel Panel to update. * @param gridbagLayout Layout to use. - * @param constraints Constrains to use. + * @param constraints Constraints to use. */ static void addBlankLine(JPanel panel, GridBagLayout gridbagLayout, GridBagConstraints constraints) { constraints.gridy++; @@ -220,7 +220,7 @@ public final class CommunicationArtifactViewerHelper { * * @param panel Panel to update. * @param gridbagLayout Layout to use. - * @param constraints Constrains to use. + * @param constraints Constraints to use. * @param keyString Key name to display. * * @return Label added. @@ -234,7 +234,7 @@ public final class CommunicationArtifactViewerHelper { * * @param panel Panel to update. * @param gridbagLayout Layout to use. - * @param constraints Constrains to use. + * @param constraints Constraints to use. * @param keyString Key name to display. * @param gridx column index, must be less than MAX_COLS - 1. * @@ -263,7 +263,7 @@ public final class CommunicationArtifactViewerHelper { * * @param panel Panel to update. * @param gridbagLayout Layout to use. - * @param constraints Constrains to use. + * @param constraints Constraints to use. * @param valueString Value string to display. * * @return Label added. @@ -277,7 +277,7 @@ public final class CommunicationArtifactViewerHelper { * * @param panel Panel to update. * @param gridbagLayout Layout to use. - * @param constraints Constrains to use. + * @param constraints Constraints to use. * @param keyString Value string to display. * @param gridx Column index, must be less than MAX_COLS; * @@ -384,7 +384,7 @@ public final class CommunicationArtifactViewerHelper { * * @param panel Panel to update. * @param gridbagLayout Layout to use. - * @param constraints Constrains to use. + * @param constraints Constraints to use. * @param accountIdentifier Account identifier to search the persona. * * @return List of AccountPersonaSearcherData objects. @@ -452,7 +452,7 @@ public final class CommunicationArtifactViewerHelper { * * @param panel Panel to update. * @param gridbagLayout Layout to use. - * @param constraints Constrains to use. + * @param constraints Constraints to use. * @param contactId Contact name to display. * * @return A JLabel with the contact information. From 56b095046c99ab818b28cf1237f53b0dd9441ff9 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Tue, 3 Nov 2020 13:53:19 -0500 Subject: [PATCH 51/81] 6773 fix apostraphe --- .../sleuthkit/autopsy/discovery/ui/WebHistoryDetailsPanel.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/WebHistoryDetailsPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/WebHistoryDetailsPanel.java index 28001b82d4..72f33f993e 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/WebHistoryDetailsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/WebHistoryDetailsPanel.java @@ -179,7 +179,7 @@ public class WebHistoryDetailsPanel extends AbstractArtifactDetailsPanel impleme }// //GEN-END:initComponents /** - * Update the view to reflect the current artifacts details. + * Update the view to reflect the current artifact's details. */ private void updateView() { CommunicationArtifactViewerHelper.addHeader(this, gridBagLayout, gridBagConstraints, Bundle.WebHistoryDetailsPanel_details_attrHeader()); From 8fe134cf45acc9d1055858b94a6f3b1a8ea53935 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Tue, 3 Nov 2020 13:55:43 -0500 Subject: [PATCH 52/81] 6773 fix comment --- .../artifactviewers/DefaultArtifactContentViewer.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/DefaultArtifactContentViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/DefaultArtifactContentViewer.java index eff2ed4561..0c9e41afd6 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/DefaultArtifactContentViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/DefaultArtifactContentViewer.java @@ -58,8 +58,7 @@ import org.sleuthkit.autopsy.discovery.ui.AbstractArtifactDetailsPanel; //import org.sleuthkit.autopsy.contentviewers.Bundle; /** - * This class displays a Blackboard artifact as a table listing all it's - * attributes names and values. + * This class displays a Blackboard artifact as a table of its attributes. */ @SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives public class DefaultArtifactContentViewer extends AbstractArtifactDetailsPanel implements ArtifactContentViewer { From d83bd002300130dd761f1ce279f5c3e84bd16baf Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Tue, 3 Nov 2020 14:34:23 -0500 Subject: [PATCH 53/81] 6773 refactor code for clarity --- .../discovery/search/DiscoveryEventUtils.java | 6 ++--- .../autopsy/discovery/ui/ArtifactsWorker.java | 2 +- .../discovery/ui/DomainArtifactsTabPanel.java | 10 ++++---- .../discovery/ui/DomainSummaryViewer.java | 25 +++++++++++-------- .../autopsy/discovery/ui/ResultsPanel.java | 8 +----- 5 files changed, 25 insertions(+), 26 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/discovery/search/DiscoveryEventUtils.java b/Core/src/org/sleuthkit/autopsy/discovery/search/DiscoveryEventUtils.java index 4171dc989c..0b9a0a98c1 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/search/DiscoveryEventUtils.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/search/DiscoveryEventUtils.java @@ -232,19 +232,19 @@ public final class DiscoveryEventUtils { /** * Event to signal the completion of a search being performed. */ - public static final class ArtifactListRetrievedEvent { + public static final class ArtifactSearchResultEvent { private final List listOfArtifacts = new ArrayList<>(); private final BlackboardArtifact.ARTIFACT_TYPE artifactType; /** - * Construct a new ArtifactListRetrievedEvent with a list of specified + * Construct a new ArtifactSearchResultEvent with a list of specified * artifacts and an artifact type. * * @param artifactType The type of artifacts in the list. * @param listOfArtifacts The list of artifacts retrieved. */ - public ArtifactListRetrievedEvent(BlackboardArtifact.ARTIFACT_TYPE artifactType, List listOfArtifacts) { + public ArtifactSearchResultEvent(BlackboardArtifact.ARTIFACT_TYPE artifactType, List listOfArtifacts) { if (listOfArtifacts != null) { this.listOfArtifacts.addAll(listOfArtifacts); } diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsWorker.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsWorker.java index eeb6870df2..4dd577db49 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsWorker.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsWorker.java @@ -71,7 +71,7 @@ class ArtifactsWorker extends SwingWorker, Void> { + artifactType.getDisplayName() + " and domain: " + domain, ex); } } - DiscoveryEventUtils.getDiscoveryEventBus().post(new DiscoveryEventUtils.ArtifactListRetrievedEvent(artifactType, listOfArtifacts)); + DiscoveryEventUtils.getDiscoveryEventBus().post(new DiscoveryEventUtils.ArtifactSearchResultEvent(artifactType, listOfArtifacts)); } } diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.java index c793e3306e..ad727fddc7 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.java @@ -109,15 +109,15 @@ final class DomainArtifactsTabPanel extends JPanel { /** * Handle the event which indicates the artifacts have been retrieved. * - * @param artifactListEvent The event which indicates the artifacts have - * been retrieved. + * @param artifactresultEvent The event which indicates the artifacts have + * been retrieved. */ @Subscribe - void handleArtifactListRetrievedEvent(DiscoveryEventUtils.ArtifactListRetrievedEvent artifactListEvent) { + void handleArtifactSearchResultEvent(DiscoveryEventUtils.ArtifactSearchResultEvent artifactresultEvent) { SwingUtilities.invokeLater(() -> { - if (artifactType == artifactListEvent.getArtifactType()) { + if (artifactType == artifactresultEvent.getArtifactType()) { listPanel.removeListSelectionListener(listener); - listPanel.addArtifacts(artifactListEvent.getListOfArtifacts()); + listPanel.addArtifacts(artifactresultEvent.getListOfArtifacts()); listPanel.addSelectionListener(listener); listPanel.selectFirst(); try { diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainSummaryViewer.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainSummaryViewer.java index 935af9fa37..331fb8fa9d 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainSummaryViewer.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainSummaryViewer.java @@ -20,6 +20,7 @@ package org.sleuthkit.autopsy.discovery.ui; import javax.swing.DefaultListModel; import javax.swing.event.ListSelectionListener; +import org.sleuthkit.autopsy.discovery.search.DiscoveryEventUtils; /** * A JPanel to display domain summaries. @@ -87,20 +88,24 @@ public class DomainSummaryViewer extends javax.swing.JPanel { } /** - * Get the list of AbstractFiles which are represented by the selected - * document preview. + * Send an event to perform the population of the domain details tabs to + * reflect the currently selected domain. Will populate the list with + * nothing when a domain is not used. * - * @return The list of AbstractFiles which are represented by the selected - * document preview. + * @param useDomain If the currently selected domain should be used to + * retrieve a list. */ - String getDomainForSelected() { - synchronized (this) { - if (domainList.getSelectedIndex() == -1) { - return ""; - } else { - return domainListModel.getElementAt(domainList.getSelectedIndex()).getResultDomain().getDomain(); + void sendPopulateEvent(boolean useDomain) { + String domain = ""; + if (useDomain) { + synchronized (this) { + if (domainList.getSelectedIndex() != -1) { + domain = domainListModel.getElementAt(domainList.getSelectedIndex()).getResultDomain().getDomain(); + } } } + //send populateMesage + DiscoveryEventUtils.getDiscoveryEventBus().post(new DiscoveryEventUtils.PopulateDomainTabsEvent(domain)); } /** diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/ResultsPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/ResultsPanel.java index 01981127e4..5f67582afc 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/ResultsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/ResultsPanel.java @@ -127,13 +127,7 @@ final class ResultsPanel extends javax.swing.JPanel { }); domainSummaryViewer.addListSelectionListener((e) -> { if (resultType == SearchData.Type.DOMAIN) { - if (!e.getValueIsAdjusting()) { - //send populateMesage - DiscoveryEventUtils.getDiscoveryEventBus().post(new DiscoveryEventUtils.PopulateDomainTabsEvent(domainSummaryViewer.getDomainForSelected())); - } else { - //send clearSelection message - DiscoveryEventUtils.getDiscoveryEventBus().post(new DiscoveryEventUtils.PopulateDomainTabsEvent("")); - } + domainSummaryViewer.sendPopulateEvent(!e.getValueIsAdjusting()); } }); } From 629f9abf7332dbe8d9344c3a9b4219ba54da8547 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Tue, 3 Nov 2020 20:35:59 -0500 Subject: [PATCH 54/81] 6773 catch cancelation exception, instance variables --- .../autopsy/discovery/ui/ArtifactsWorker.java | 3 +++ .../discovery/ui/DiscoveryTopComponent.java | 6 +++++- .../discovery/ui/DomainDetailsPanel.java | 20 ++++++++++++------- 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsWorker.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsWorker.java index 4dd577db49..9a47e164cf 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsWorker.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsWorker.java @@ -20,6 +20,7 @@ package org.sleuthkit.autopsy.discovery.ui; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.CancellationException; import java.util.concurrent.ExecutionException; import java.util.logging.Level; import javax.swing.SwingWorker; @@ -69,6 +70,8 @@ class ArtifactsWorker extends SwingWorker, Void> { } catch (InterruptedException | ExecutionException ex) { logger.log(Level.SEVERE, "Exception while trying to get list of artifacts for Domain details for artifact type: " + artifactType.getDisplayName() + " and domain: " + domain, ex); + } catch (CancellationException ignored) { + //Worker was cancelled after previously finishing its background work, exception ignored to cut down on non-helpful logging } } DiscoveryEventUtils.getDiscoveryEventBus().post(new DiscoveryEventUtils.ArtifactSearchResultEvent(artifactType, listOfArtifacts)); diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/DiscoveryTopComponent.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/DiscoveryTopComponent.java index 1b51a6fa54..538a08c858 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/DiscoveryTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/DiscoveryTopComponent.java @@ -56,6 +56,7 @@ public final class DiscoveryTopComponent extends TopComponent { private volatile static int resultsAreaSize = 250; private final GroupListPanel groupListPanel; private final ResultsPanel resultsPanel; + private String selectedDomainTabName; private Type searchType; private int dividerLocation = -1; private SwingAnimator animator = null; @@ -149,6 +150,9 @@ public final class DiscoveryTopComponent extends TopComponent { DiscoveryEventUtils.getDiscoveryEventBus().unregister(groupListPanel); DiscoveryEventUtils.getDiscoveryEventBus().unregister(resultsPanel); DiscoveryEventUtils.getDiscoveryEventBus().unregister(rightSplitPane.getBottomComponent()); + if (rightSplitPane.getBottomComponent() instanceof DomainDetailsPanel){ + selectedDomainTabName = ((DomainDetailsPanel)rightSplitPane.getBottomComponent()).getSelectedTabName(); + } super.componentClosed(); } @@ -311,7 +315,7 @@ public final class DiscoveryTopComponent extends TopComponent { if (!searchCompleteEvent.getFilters().isEmpty()) { descriptionText += Bundle.DiscoveryTopComponent_additionalFilters_text(); } - rightSplitPane.setBottomComponent(new DomainDetailsPanel()); + rightSplitPane.setBottomComponent(new DomainDetailsPanel(selectedDomainTabName)); } else { rightSplitPane.setBottomComponent(new FileDetailsPanel()); } diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.java index d4713b55b1..74495c4736 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.java @@ -36,25 +36,27 @@ import org.sleuthkit.autopsy.discovery.search.SearchData; final class DomainDetailsPanel extends JPanel { private static final long serialVersionUID = 1L; - private static ArtifactsWorker detailsWorker; - private static String domain; - private static String selectedTabName; + private ArtifactsWorker detailsWorker; + private String domain; + private String selectedTabName; /** - * Creates new form ArtifactDetailsPanel + * Creates new form ArtifactDetailsPanel. */ - DomainDetailsPanel() { + DomainDetailsPanel(String selectedTabName) { initComponents(); - addArtifactTabs(); + addArtifactTabs(selectedTabName); + } /** * Add the tabs for each of the artifact types which we will be displaying. */ - private void addArtifactTabs() { + private void addArtifactTabs(String tabName) { for (BlackboardArtifact.ARTIFACT_TYPE type : SearchData.Type.DOMAIN.getArtifactTypes()) { jTabbedPane1.add(type.getDisplayName(), new DomainArtifactsTabPanel(type)); } + selectedTabName = tabName; selectTab(); jTabbedPane1.addChangeListener(new ChangeListener() { @Override @@ -135,6 +137,10 @@ final class DomainDetailsPanel extends JPanel { } } } + + String getSelectedTabName(){ + return selectedTabName; + } /** * This method is called from within the constructor to initialize the form. From c98c2838dee2ac604a047ad0e4d592b987d388e8 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Tue, 3 Nov 2020 20:37:16 -0500 Subject: [PATCH 55/81] 6773 add comment --- .../sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.java index 74495c4736..9ff722ce4c 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.java @@ -138,6 +138,11 @@ final class DomainDetailsPanel extends JPanel { } } + /** + * Get the name of the tab that was most recently selected. + * + * @return The name of the tab that was most recently selected. + */ String getSelectedTabName(){ return selectedTabName; } From 8363f220999e7955af064b9a16d68d0966480f05 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Thu, 5 Nov 2020 12:49:30 -0500 Subject: [PATCH 56/81] 6773 remove ui synchronization annotate thread confined --- .../ui/AbstractArtifactDetailsPanel.java | 2 + .../ui/AbstractDiscoveryFilterPanel.java | 9 ++ .../discovery/ui/AbstractFiltersPanel.java | 30 +++++-- .../discovery/ui/ArtifactTypeFilterPanel.java | 8 ++ .../discovery/ui/ArtifactsListPanel.java | 18 +++- .../discovery/ui/DataSourceFilterPanel.java | 8 ++ .../autopsy/discovery/ui/DateFilterPanel.java | 8 ++ .../autopsy/discovery/ui/DiscoveryDialog.java | 14 ++- .../ui/DiscoveryThumbnailChildren.java | 10 ++- .../discovery/ui/DiscoveryTopComponent.java | 88 +++++++++++-------- .../discovery/ui/DiscoveryUiUtils.java | 5 ++ .../discovery/ui/DocumentFilterPanel.java | 2 + .../autopsy/discovery/ui/DocumentPanel.form | 8 +- .../autopsy/discovery/ui/DocumentPanel.java | 5 +- .../discovery/ui/DocumentPreviewViewer.java | 26 +++--- .../discovery/ui/DomainArtifactsTabPanel.java | 12 ++- .../discovery/ui/DomainDetailsPanel.java | 10 ++- .../discovery/ui/DomainFilterPanel.java | 2 + .../discovery/ui/DomainSummaryPanel.java | 4 + .../discovery/ui/DomainSummaryViewer.java | 32 +++---- .../discovery/ui/FileDetailsPanel.java | 12 ++- .../autopsy/discovery/ui/GroupListPanel.java | 56 ++++++------ .../discovery/ui/HashSetFilterPanel.java | 8 ++ .../discovery/ui/ImageFilterPanel.java | 2 + .../discovery/ui/ImageThumbnailPanel.form | 10 +-- .../discovery/ui/ImageThumbnailPanel.java | 4 + .../discovery/ui/ImageThumbnailViewer.java | 27 +++--- .../ui/InterestingItemsFilterPanel.java | 8 ++ .../ui/ObjectDetectedFilterPanel.java | 9 ++ .../discovery/ui/OpenDiscoveryAction.java | 4 + .../discovery/ui/ParentFolderFilterPanel.java | 10 +++ .../ui/PastOccurrencesFilterPanel.java | 8 ++ .../autopsy/discovery/ui/ResultsPanel.java | 79 ++++++++++------- .../discovery/ui/ResultsSplitPaneDivider.java | 2 + .../autopsy/discovery/ui/SizeFilterPanel.java | 8 ++ .../discovery/ui/UserCreatedFilterPanel.java | 5 ++ .../discovery/ui/VideoFilterPanel.java | 2 + .../discovery/ui/VideoThumbnailPanel.java | 4 + .../discovery/ui/VideoThumbnailViewer.java | 26 +++--- .../discovery/ui/WebHistoryDetailsPanel.java | 14 +-- 40 files changed, 416 insertions(+), 183 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/AbstractArtifactDetailsPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/AbstractArtifactDetailsPanel.java index 1be1324300..b36e93728a 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/AbstractArtifactDetailsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/AbstractArtifactDetailsPanel.java @@ -19,6 +19,7 @@ package org.sleuthkit.autopsy.discovery.ui; import javax.swing.JPanel; +import org.sleuthkit.autopsy.coreutils.ThreadConfined; import org.sleuthkit.datamodel.BlackboardArtifact; /** @@ -34,6 +35,7 @@ public abstract class AbstractArtifactDetailsPanel extends JPanel { * * @param artifact the artifact to display. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) abstract public void setArtifact(BlackboardArtifact artifact); } diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/AbstractDiscoveryFilterPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/AbstractDiscoveryFilterPanel.java index 3e4ab45592..7fc964ad52 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/AbstractDiscoveryFilterPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/AbstractDiscoveryFilterPanel.java @@ -24,6 +24,7 @@ import javax.swing.JCheckBox; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.event.ListSelectionListener; +import org.sleuthkit.autopsy.coreutils.ThreadConfined; /** * Abstract class extending JPanel for filter controls. @@ -41,6 +42,7 @@ abstract class AbstractDiscoveryFilterPanel extends javax.swing.JPanel { * selected, null to indicate leaving selected items * unchanged or that there are no items to select. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) abstract void configurePanel(boolean selected, int[] indicesSelected); /** @@ -48,6 +50,7 @@ abstract class AbstractDiscoveryFilterPanel extends javax.swing.JPanel { * * @return The JCheckBox which enables and disables this filter. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) abstract JCheckBox getCheckbox(); /** @@ -57,6 +60,7 @@ abstract class AbstractDiscoveryFilterPanel extends javax.swing.JPanel { * @return The JList which contains the values available for selection for * this filter. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) abstract JList getList(); /** @@ -65,6 +69,7 @@ abstract class AbstractDiscoveryFilterPanel extends javax.swing.JPanel { * * @return The JLabel to display under the JCheckBox. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) abstract JLabel getAdditionalLabel(); /** @@ -73,6 +78,7 @@ abstract class AbstractDiscoveryFilterPanel extends javax.swing.JPanel { * @return If the settings are invalid returns the error that has occurred, * otherwise returns empty string. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) abstract String checkForError(); /** @@ -82,6 +88,7 @@ abstract class AbstractDiscoveryFilterPanel extends javax.swing.JPanel { * @param actionlistener The listener for the checkbox selection events. * @param listListener The listener for the list selection events. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) void addListeners(ActionListener actionListener, ListSelectionListener listListener) { if (getCheckbox() != null) { getCheckbox().addActionListener(actionListener); @@ -97,11 +104,13 @@ abstract class AbstractDiscoveryFilterPanel extends javax.swing.JPanel { * @return The AbstractFilter for the selected settings, null if the * settings are not in use. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) abstract AbstractFilter getFilter(); /** * Remove listeners from the checkbox and the list if they exist. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) void removeListeners() { if (getCheckbox() != null) { for (ActionListener listener : getCheckbox().getActionListeners()) { diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/AbstractFiltersPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/AbstractFiltersPanel.java index 6e8137a6ed..c8f71a5d99 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/AbstractFiltersPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/AbstractFiltersPanel.java @@ -32,6 +32,7 @@ import javax.swing.JSplitPane; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import org.apache.commons.lang3.StringUtils; +import org.sleuthkit.autopsy.coreutils.ThreadConfined; import org.sleuthkit.autopsy.discovery.search.DiscoveryAttributes.GroupingAttributeType; import org.sleuthkit.autopsy.discovery.search.Group; import org.sleuthkit.autopsy.discovery.search.ResultsSorter.SortingMethod; @@ -65,6 +66,7 @@ abstract class AbstractFiltersPanel extends JPanel implements ActionListener, Li /** * Setup necessary for implementations of this abstract class. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) AbstractFiltersPanel() { firstColumnPanel.setLayout(new GridBagLayout()); secondColumnPanel.setLayout(new GridBagLayout()); @@ -75,6 +77,7 @@ abstract class AbstractFiltersPanel extends JPanel implements ActionListener, Li * * @return The type of results this panel filters. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) abstract SearchData.Type getType(); /** @@ -88,7 +91,8 @@ abstract class AbstractFiltersPanel extends JPanel implements ActionListener, Li * list, null if none are selected. * @param column The column to add the DiscoveryFilterPanel to. */ - final synchronized void addFilter(AbstractDiscoveryFilterPanel filterPanel, boolean isSelected, int[] indicesSelected, int column) { + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) + final void addFilter(AbstractDiscoveryFilterPanel filterPanel, boolean isSelected, int[] indicesSelected, int column) { if (!isInitialized) { constraints.gridy = 0; constraints.anchor = GridBagConstraints.FIRST_LINE_START; @@ -132,6 +136,7 @@ abstract class AbstractFiltersPanel extends JPanel implements ActionListener, Li * * @param splitPane The JSplitPane which the columns are added to. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) final void addPanelsToScrollPane(JSplitPane splitPane) { splitPane.setLeftComponent(firstColumnPanel); splitPane.setRightComponent(secondColumnPanel); @@ -142,7 +147,8 @@ abstract class AbstractFiltersPanel extends JPanel implements ActionListener, Li /** * Clear the filters from the panel */ - final synchronized void clearFilters() { + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) + final void clearFilters() { for (AbstractDiscoveryFilterPanel filterPanel : filters) { filterPanel.removeListeners(); } @@ -159,6 +165,7 @@ abstract class AbstractFiltersPanel extends JPanel implements ActionListener, Li * column. * @param columnIndex The column to add the Component to. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) private void addToGridBagLayout(Component componentToAdd, Component additionalComponentToAdd, int columnIndex) { addToColumn(componentToAdd, columnIndex); if (additionalComponentToAdd != null) { @@ -174,6 +181,7 @@ abstract class AbstractFiltersPanel extends JPanel implements ActionListener, Li * @param component The Component to add. * @param columnNumber The column to add the Component to. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) private void addToColumn(Component component, int columnNumber) { if (columnNumber == 0) { firstColumnPanel.add(component, constraints); @@ -186,7 +194,8 @@ abstract class AbstractFiltersPanel extends JPanel implements ActionListener, Li * Check if the fields are valid, and fire a property change event to * indicate any errors. */ - synchronized void validateFields() { + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) + void validateFields() { String errorString = null; for (AbstractDiscoveryFilterPanel filterPanel : filters) { errorString = filterPanel.checkForError(); @@ -197,6 +206,7 @@ abstract class AbstractFiltersPanel extends JPanel implements ActionListener, Li firePropertyChange("FilterError", null, errorString); } + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override public void actionPerformed(ActionEvent e) { validateFields(); @@ -209,6 +219,7 @@ abstract class AbstractFiltersPanel extends JPanel implements ActionListener, Li * * @return True if the ObjectsDetectedFilter is supported, false otherwise. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) boolean isObjectsFilterSupported() { for (AbstractDiscoveryFilterPanel filter : filters) { if (filter instanceof ObjectDetectedFilterPanel) { @@ -223,6 +234,7 @@ abstract class AbstractFiltersPanel extends JPanel implements ActionListener, Li * * @return True if the HashSetFilter is supported, false otherwise. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) boolean isHashSetFilterSupported() { for (AbstractDiscoveryFilterPanel filter : filters) { if (filter instanceof HashSetFilterPanel) { @@ -237,6 +249,7 @@ abstract class AbstractFiltersPanel extends JPanel implements ActionListener, Li * * @return True if the InterestingItemsFilter is supported, false otherwise. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) boolean isInterestingItemsFilterSupported() { for (AbstractDiscoveryFilterPanel filter : filters) { if (filter instanceof InterestingItemsFilterPanel) { @@ -251,8 +264,8 @@ abstract class AbstractFiltersPanel extends JPanel implements ActionListener, Li * * @return The list of filters selected by the user. */ - synchronized List getFilters() { - + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) + List getFilters() { List filtersToUse = new ArrayList<>(); if (getType() != SearchData.Type.DOMAIN) { //Domain type does not have a file type filtersToUse.add(new SearchFiltering.FileTypeFilter(getType())); @@ -268,6 +281,7 @@ abstract class AbstractFiltersPanel extends JPanel implements ActionListener, Li return filtersToUse; } + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override public void valueChanged(ListSelectionEvent evt) { if (!evt.getValueIsAdjusting()) { @@ -282,6 +296,7 @@ abstract class AbstractFiltersPanel extends JPanel implements ActionListener, Li * * @return The most recently used sorting method. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) SortingMethod getLastSortingMethod() { return lastSortingMethod; } @@ -291,6 +306,7 @@ abstract class AbstractFiltersPanel extends JPanel implements ActionListener, Li * * @param lastSortingMethod The most recently used sorting method. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) final void setLastSortingMethod(SortingMethod lastSortingMethod) { this.lastSortingMethod = lastSortingMethod; } @@ -300,6 +316,7 @@ abstract class AbstractFiltersPanel extends JPanel implements ActionListener, Li * * @return The most recently used grouping attribute. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) GroupingAttributeType getLastGroupingAttributeType() { return lastGroupingAttributeType; } @@ -310,6 +327,7 @@ abstract class AbstractFiltersPanel extends JPanel implements ActionListener, Li * @param lastGroupingAttributeType The most recently used grouping * attribute. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) final void setLastGroupingAttributeType(GroupingAttributeType lastGroupingAttributeType) { this.lastGroupingAttributeType = lastGroupingAttributeType; } @@ -319,6 +337,7 @@ abstract class AbstractFiltersPanel extends JPanel implements ActionListener, Li * * @return The most recently used group sorting algorithm. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) Group.GroupSortingAlgorithm getLastGroupSortingAlg() { return lastGroupSortingAlg; } @@ -329,6 +348,7 @@ abstract class AbstractFiltersPanel extends JPanel implements ActionListener, Li * @param lastGroupSortingAlg The most recently used group sorting * algorithm. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) final void setLastGroupSortingAlg(Group.GroupSortingAlgorithm lastGroupSortingAlg) { this.lastGroupSortingAlg = lastGroupSortingAlg; } diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactTypeFilterPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactTypeFilterPanel.java index 089c18bf13..e6a1ccaaed 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactTypeFilterPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactTypeFilterPanel.java @@ -26,6 +26,7 @@ import javax.swing.JCheckBox; import javax.swing.JLabel; import javax.swing.JList; import org.openide.util.NbBundle; +import org.sleuthkit.autopsy.coreutils.ThreadConfined; import org.sleuthkit.autopsy.discovery.search.SearchData; import org.sleuthkit.autopsy.discovery.search.SearchFiltering.ArtifactTypeFilter; import org.sleuthkit.datamodel.BlackboardArtifact; @@ -40,6 +41,7 @@ class ArtifactTypeFilterPanel extends AbstractDiscoveryFilterPanel { /** * Creates new form ArtifactTypeFilterPanel */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) ArtifactTypeFilterPanel() { initComponents(); setUpArtifactTypeFilter(); @@ -49,6 +51,7 @@ class ArtifactTypeFilterPanel extends AbstractDiscoveryFilterPanel { /** * Initialize the data source filter. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) private void setUpArtifactTypeFilter() { int count = 0; DefaultListModel artifactTypeModel = (DefaultListModel) artifactList.getModel(); @@ -104,6 +107,7 @@ class ArtifactTypeFilterPanel extends AbstractDiscoveryFilterPanel { artifactList.setEnabled(artifactTypeCheckbox.isSelected()); }//GEN-LAST:event_artifactTypeCheckboxActionPerformed + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override void configurePanel(boolean selected, int[] indicesSelected) { artifactTypeCheckbox.setSelected(selected); @@ -119,11 +123,13 @@ class ArtifactTypeFilterPanel extends AbstractDiscoveryFilterPanel { } } + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override JCheckBox getCheckbox() { return artifactTypeCheckbox; } + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override JList getList() { return artifactList; @@ -134,6 +140,7 @@ class ArtifactTypeFilterPanel extends AbstractDiscoveryFilterPanel { return null; } + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @NbBundle.Messages({"ArtifactTypeFilterPanel.selectionNeeded.text=At least one Result type must be selected."}) @Override String checkForError() { @@ -143,6 +150,7 @@ class ArtifactTypeFilterPanel extends AbstractDiscoveryFilterPanel { return ""; } + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override AbstractFilter getFilter() { if (artifactTypeCheckbox.isSelected() && !artifactList.getSelectedValuesList().isEmpty()) { diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java index c717efed38..5493c4c70d 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java @@ -27,6 +27,7 @@ import javax.swing.table.AbstractTableModel; import org.apache.commons.lang.StringUtils; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.coreutils.ThreadConfined; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.TskCoreException; @@ -44,6 +45,7 @@ class ArtifactsListPanel extends JPanel { /** * Creates new form ArtifactsListPanel. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) ArtifactsListPanel() { initComponents(); } @@ -54,6 +56,7 @@ class ArtifactsListPanel extends JPanel { * * @param listener The listener to add to the table of artifacts. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) void addSelectionListener(ListSelectionListener listener) { jTable1.getSelectionModel().addListSelectionListener(listener); } @@ -63,6 +66,7 @@ class ArtifactsListPanel extends JPanel { * * @param listener The listener to remove from the table of artifacts. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) void removeListSelectionListener(ListSelectionListener listener) { jTable1.getSelectionModel().removeListSelectionListener(listener); } @@ -74,6 +78,7 @@ class ArtifactsListPanel extends JPanel { * @return The currently selected BlackboardArtifact or null if none is * selected. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) BlackboardArtifact getSelectedArtifact() { int selectedIndex = jTable1.getSelectionModel().getLeadSelectionIndex(); if (selectedIndex < jTable1.getSelectionModel().getMinSelectionIndex() || jTable1.getSelectionModel().getMaxSelectionIndex() < 0 || selectedIndex > jTable1.getSelectionModel().getMaxSelectionIndex()) { @@ -88,6 +93,7 @@ class ArtifactsListPanel extends JPanel { * @return true if the list of artifacts is empty, false if there are * artifacts. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) boolean isEmpty() { return tableModel.getRowCount() <= 0; } @@ -96,6 +102,7 @@ class ArtifactsListPanel extends JPanel { * Select the first available artifact in the list if it is not empty to * populate the panel to the right. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) void selectFirst() { if (!isEmpty()) { jTable1.setRowSelectionInterval(0, 0); @@ -110,6 +117,7 @@ class ArtifactsListPanel extends JPanel { * * @param artifactList The list of artifacts to display. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) void addArtifacts(List artifactList) { tableModel.setContents(artifactList); jTable1.validate(); @@ -120,6 +128,7 @@ class ArtifactsListPanel extends JPanel { /** * Remove all artifacts from the list of artifacts displayed. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) void clearArtifacts() { tableModel.setContents(new ArrayList<>()); tableModel.fireTableDataChanged(); @@ -169,6 +178,7 @@ class ArtifactsListPanel extends JPanel { /** * Construct a new DomainArtifactTableModel. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) DomainArtifactTableModel() { //No arg constructor to create empty model } @@ -179,17 +189,20 @@ class ArtifactsListPanel extends JPanel { * * @param artifacts The list of BlackboardArtifacts to represent. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) void setContents(List artifacts) { jTable1.clearSelection(); artifactList.clear(); artifactList.addAll(artifacts); } + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override public int getRowCount() { return artifactList.size(); } + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override public int getColumnCount() { return 2; @@ -202,10 +215,12 @@ class ArtifactsListPanel extends JPanel { * * @return The BlackboardArtifact at the specified row. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) BlackboardArtifact getArtifactByRow(int rowIndex) { return artifactList.get(rowIndex); } + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @NbBundle.Messages({"ArtifactsListPanel.value.noValue=No value available."}) @Override public Object getValueAt(int rowIndex, int columnIndex) { @@ -216,7 +231,6 @@ class ArtifactsListPanel extends JPanel { } else if (columnIndex == 1 && bba.getAttributeType().getTypeName().startsWith("TSK_TITLE") && !StringUtils.isBlank(bba.getDisplayString())) { return bba.getDisplayString(); } - } return getFallbackValue(rowIndex, columnIndex); } catch (TskCoreException ex) { @@ -239,6 +253,7 @@ class ArtifactsListPanel extends JPanel { * * @throws TskCoreException */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) private String getFallbackValue(int rowIndex, int columnIndex) throws TskCoreException { for (BlackboardAttribute bba : getArtifactByRow(rowIndex).getAttributes()) { if (columnIndex == 0 && bba.getAttributeType().getTypeName().startsWith("TSK_DATETIME") && !StringUtils.isBlank(bba.getDisplayString())) { @@ -250,6 +265,7 @@ class ArtifactsListPanel extends JPanel { return Bundle.ArtifactsListPanel_value_noValue(); } + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @NbBundle.Messages({"ArtifactsListPanel.titleColumn.name=Title", "ArtifactsListPanel.dateColumn.name=Date/Time"}) @Override diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/DataSourceFilterPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/DataSourceFilterPanel.java index ab54df4341..065c989ddb 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/DataSourceFilterPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/DataSourceFilterPanel.java @@ -30,6 +30,7 @@ import javax.swing.JList; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.coreutils.ThreadConfined; import org.sleuthkit.autopsy.discovery.search.SearchFiltering; import org.sleuthkit.datamodel.DataSource; import org.sleuthkit.datamodel.TskCoreException; @@ -45,6 +46,7 @@ final class DataSourceFilterPanel extends AbstractDiscoveryFilterPanel { /** * Creates new form DataSourceFilterPanel. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) DataSourceFilterPanel() { initComponents(); setUpDataSourceFilter(); @@ -109,6 +111,7 @@ final class DataSourceFilterPanel extends AbstractDiscoveryFilterPanel { private javax.swing.JScrollPane dataSourceScrollPane; // End of variables declaration//GEN-END:variables + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override void configurePanel(boolean selected, int[] indicesSelected) { dataSourceCheckbox.setSelected(selected); @@ -124,6 +127,7 @@ final class DataSourceFilterPanel extends AbstractDiscoveryFilterPanel { } } + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override JCheckBox getCheckbox() { return dataSourceCheckbox; @@ -137,6 +141,7 @@ final class DataSourceFilterPanel extends AbstractDiscoveryFilterPanel { /** * Initialize the data source filter. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) private void setUpDataSourceFilter() { int count = 0; try { @@ -156,6 +161,7 @@ final class DataSourceFilterPanel extends AbstractDiscoveryFilterPanel { } } + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override JList getList() { return dataSourceList; @@ -193,6 +199,7 @@ final class DataSourceFilterPanel extends AbstractDiscoveryFilterPanel { } } + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @NbBundle.Messages({"DataSourceFilterPanel.error.text=At least one data source must be selected."}) @Override String checkForError() { @@ -202,6 +209,7 @@ final class DataSourceFilterPanel extends AbstractDiscoveryFilterPanel { return ""; } + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override AbstractFilter getFilter() { if (dataSourceCheckbox.isSelected()) { diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/DateFilterPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/DateFilterPanel.java index 528a5d1bc2..2fbe6610ff 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/DateFilterPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/DateFilterPanel.java @@ -33,6 +33,7 @@ import javax.swing.JSpinner; import javax.swing.event.ListSelectionListener; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.communications.Utils; +import org.sleuthkit.autopsy.coreutils.ThreadConfined; import org.sleuthkit.autopsy.discovery.search.SearchFiltering; /** @@ -48,6 +49,7 @@ class DateFilterPanel extends AbstractDiscoveryFilterPanel { */ @NbBundle.Messages({"# {0} - timeZone", "DateFilterPanel.dateRange.text=Date Range ({0}):"}) + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) DateFilterPanel() { initComponents(); rangeRadioButton.setText(Bundle.DateFilterPanel_dateRange_text(Utils.getUserPreferredZoneId().toString())); @@ -225,6 +227,7 @@ class DateFilterPanel extends AbstractDiscoveryFilterPanel { endCheckBox.firePropertyChange("EndButtonChange", true, false); }//GEN-LAST:event_rangeRadioButtonStateChanged + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override void configurePanel(boolean selected, int[] indicesSelected) { dateFilterCheckBox.setSelected(selected); @@ -238,6 +241,7 @@ class DateFilterPanel extends AbstractDiscoveryFilterPanel { } } + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override JCheckBox getCheckbox() { return dateFilterCheckBox; @@ -253,6 +257,7 @@ class DateFilterPanel extends AbstractDiscoveryFilterPanel { return null; } + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override void addListeners(ActionListener actionListener, ListSelectionListener listListener) { dateFilterCheckBox.addActionListener(actionListener); @@ -274,6 +279,7 @@ class DateFilterPanel extends AbstractDiscoveryFilterPanel { }); } + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override void removeListeners() { for (ActionListener listener : dateFilterCheckBox.getActionListeners()) { @@ -302,6 +308,7 @@ class DateFilterPanel extends AbstractDiscoveryFilterPanel { } } + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @NbBundle.Messages({"DateFilterPanel.invalidRange.text=Range or Only Last must be selected.", "DateFilterPanel.startOrEndNeeded.text=A start or end date must be specified to use the range filter.", "DateFilterPanel.startAfterEnd.text=Start date should be before the end date when both are enabled."}) @@ -320,6 +327,7 @@ class DateFilterPanel extends AbstractDiscoveryFilterPanel { return ""; } + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override AbstractFilter getFilter() { if (dateFilterCheckBox.isSelected()) { diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/DiscoveryDialog.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/DiscoveryDialog.java index f2f42bd113..565dad8a88 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/DiscoveryDialog.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/DiscoveryDialog.java @@ -40,6 +40,7 @@ import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoException; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository; import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.coreutils.ThreadConfined; import org.sleuthkit.autopsy.discovery.search.DiscoveryAttributes; import org.sleuthkit.autopsy.discovery.search.DiscoveryEventUtils; import org.sleuthkit.autopsy.discovery.search.Group; @@ -99,6 +100,7 @@ final class DiscoveryDialog extends javax.swing.JDialog { /** * Private constructor to construct a new DiscoveryDialog */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Messages("DiscoveryDialog.name.text=Discovery") private DiscoveryDialog() { super(WindowManager.getDefault().getMainWindow(), Bundle.DiscoveryDialog_name_text(), true); @@ -151,6 +153,7 @@ final class DiscoveryDialog extends javax.swing.JDialog { /** * Update the search settings to a default state. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) void updateSearchSettings() { removeAllPanels(); imageFilterPanel = null; @@ -176,6 +179,7 @@ final class DiscoveryDialog extends javax.swing.JDialog { /** * Set the type buttons to a default state where none are selected. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) private void unselectAllButtons() { imagesButton.setSelected(false); imagesButton.setEnabled(true); @@ -194,6 +198,7 @@ final class DiscoveryDialog extends javax.swing.JDialog { /** * Private helper method to perform update of comboboxes update. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) private void updateComboBoxes() { // Set up the grouping attributes List groupingAttrs = new ArrayList<>(); @@ -230,6 +235,7 @@ final class DiscoveryDialog extends javax.swing.JDialog { * * @return The panel that corresponds to the currently selected type. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) private AbstractFiltersPanel getSelectedFilterPanel() { switch (type) { case IMAGE: @@ -251,6 +257,7 @@ final class DiscoveryDialog extends javax.swing.JDialog { * * @param type The Type of GroupingAttribute to add. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) private void addTypeToGroupByComboBox(GroupingAttributeType type) { switch (type) { case FREQUENCY: @@ -282,7 +289,8 @@ final class DiscoveryDialog extends javax.swing.JDialog { /** * Validate the filter settings for File type filters. */ - synchronized void validateDialog() { + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) + void validateDialog() { AbstractFiltersPanel panel = getSelectedFilterPanel(); if (panel != null) { panel.validateFields(); @@ -551,6 +559,7 @@ final class DiscoveryDialog extends javax.swing.JDialog { /** * Helper method to remove all filter panels and their listeners */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) private void removeAllPanels() { if (imageFilterPanel != null) { remove(imageFilterPanel); @@ -635,6 +644,7 @@ final class DiscoveryDialog extends javax.swing.JDialog { repaint(); }//GEN-LAST:event_domainsButtonActionPerformed + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override public void dispose() { setVisible(false); @@ -643,6 +653,7 @@ final class DiscoveryDialog extends javax.swing.JDialog { /** * Cancel the searchWorker if it exists. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) void cancelSearch() { if (searchWorker != null) { searchWorker.cancel(true); @@ -656,6 +667,7 @@ final class DiscoveryDialog extends javax.swing.JDialog { * @param error The error message to display, empty string if there is no * error. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) private void setValid(String error) { if (StringUtils.isBlank(error)) { errorLabel.setText(""); diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/DiscoveryThumbnailChildren.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/DiscoveryThumbnailChildren.java index dce68e3a41..229c7510e3 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/DiscoveryThumbnailChildren.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/DiscoveryThumbnailChildren.java @@ -27,6 +27,7 @@ import org.openide.nodes.Children; import org.openide.nodes.Node; import org.openide.nodes.Sheet; import org.openide.util.NbBundle; +import org.sleuthkit.autopsy.coreutils.ThreadConfined; import org.sleuthkit.autopsy.datamodel.AbstractAbstractFileNode; import org.sleuthkit.autopsy.datamodel.FileNode; import org.sleuthkit.datamodel.AbstractFile; @@ -42,28 +43,27 @@ class DiscoveryThumbnailChildren extends Children.Keys { /* * Creates the list of thumbnails from the given list of AbstractFiles. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) DiscoveryThumbnailChildren(List files) { super(false); - this.files = files; - } + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override protected Node[] createNodes(AbstractFile t) { return new Node[]{new ThumbnailNode(t)}; } + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override protected void addNotify() { super.addNotify(); - Set thumbnails = new TreeSet<>((AbstractFile file1, AbstractFile file2) -> { int result = Long.compare(file1.getSize(), file2.getSize()); if (result == 0) { result = file1.getName().compareTo(file2.getName()); } - return result; }); thumbnails.addAll(files); @@ -75,10 +75,12 @@ class DiscoveryThumbnailChildren extends Children.Keys { */ static class ThumbnailNode extends FileNode { + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) ThumbnailNode(AbstractFile file) { super(file, false); } + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override protected Sheet createSheet() { Sheet sheet = super.createSheet(); diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/DiscoveryTopComponent.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/DiscoveryTopComponent.java index 538a08c858..421a9bebe1 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/DiscoveryTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/DiscoveryTopComponent.java @@ -28,6 +28,7 @@ import java.beans.PropertyChangeListener; import java.util.List; import java.util.stream.Collectors; import javax.swing.JSplitPane; +import javax.swing.SwingUtilities; import javax.swing.plaf.basic.BasicSplitPaneDivider; import javax.swing.plaf.basic.BasicSplitPaneUI; import org.openide.util.NbBundle; @@ -106,6 +107,7 @@ public final class DiscoveryTopComponent extends TopComponent { * @param ui The component which contains the split pane this divider is * in. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) BasicSplitPaneDividerImpl(BasicSplitPaneUI ui) { super(ui); this.setLayout(new BorderLayout()); @@ -127,6 +129,7 @@ public final class DiscoveryTopComponent extends TopComponent { /** * Reset the top component so it isn't displaying any results. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) public void resetTopComponent() { resultsPanel.resetResultViewer(); groupListPanel.resetGroupList(); @@ -150,8 +153,8 @@ public final class DiscoveryTopComponent extends TopComponent { DiscoveryEventUtils.getDiscoveryEventBus().unregister(groupListPanel); DiscoveryEventUtils.getDiscoveryEventBus().unregister(resultsPanel); DiscoveryEventUtils.getDiscoveryEventBus().unregister(rightSplitPane.getBottomComponent()); - if (rightSplitPane.getBottomComponent() instanceof DomainDetailsPanel){ - selectedDomainTabName = ((DomainDetailsPanel)rightSplitPane.getBottomComponent()).getSelectedTabName(); + if (rightSplitPane.getBottomComponent() instanceof DomainDetailsPanel) { + selectedDomainTabName = ((DomainDetailsPanel) rightSplitPane.getBottomComponent()).getSelectedTabName(); } super.componentClosed(); } @@ -262,17 +265,19 @@ public final class DiscoveryTopComponent extends TopComponent { */ @Subscribe void handleDetailsVisibleEvent(DiscoveryEventUtils.DetailsVisibleEvent detailsVisibleEvent) { - if (animator != null && animator.isRunning()) { - animator.stop(); - animator = null; - } - dividerLocation = rightSplitPane.getDividerLocation(); - if (detailsVisibleEvent.isShowDetailsArea()) { - animator = new SwingAnimator(new ShowDetailsAreaCallback()); - } else { - animator = new SwingAnimator(new HideDetailsAreaCallback()); - } - animator.start(); + SwingUtilities.invokeLater(() -> { + if (animator != null && animator.isRunning()) { + animator.stop(); + animator = null; + } + dividerLocation = rightSplitPane.getDividerLocation(); + if (detailsVisibleEvent.isShowDetailsArea()) { + animator = new SwingAnimator(new ShowDetailsAreaCallback()); + } else { + animator = new SwingAnimator(new HideDetailsAreaCallback()); + } + animator.start(); + }); } /** @@ -287,10 +292,12 @@ public final class DiscoveryTopComponent extends TopComponent { "DiscoveryTopComponent.searchError.text=Error no type specified for search."}) @Subscribe void handleSearchStartedEvent(DiscoveryEventUtils.SearchStartedEvent searchStartedEvent) { - newSearchButton.setText(Bundle.DiscoveryTopComponent_cancelButton_text()); - progressMessageTextArea.setForeground(Color.red); - searchType = searchStartedEvent.getType(); - progressMessageTextArea.setText(Bundle.DiscoveryTopComponent_searchInProgress_text(searchType.name())); + SwingUtilities.invokeLater(() -> { + newSearchButton.setText(Bundle.DiscoveryTopComponent_cancelButton_text()); + progressMessageTextArea.setForeground(Color.red); + searchType = searchStartedEvent.getType(); + progressMessageTextArea.setText(Bundle.DiscoveryTopComponent_searchInProgress_text(searchType.name())); + }); } /** @@ -306,23 +313,25 @@ public final class DiscoveryTopComponent extends TopComponent { "DiscoveryTopComponent.domainSearch.text=Type: Domain", "DiscoveryTopComponent.additionalFilters.text=; "}) void handleSearchCompleteEvent(DiscoveryEventUtils.SearchCompleteEvent searchCompleteEvent) { - newSearchButton.setText(Bundle.DiscoveryTopComponent_newSearch_text()); - progressMessageTextArea.setForeground(Color.black); - String descriptionText = ""; - if (searchType == DOMAIN) { - //domain does not have a file type filter to add the type information so it is manually added - descriptionText = Bundle.DiscoveryTopComponent_domainSearch_text(); - if (!searchCompleteEvent.getFilters().isEmpty()) { - descriptionText += Bundle.DiscoveryTopComponent_additionalFilters_text(); + SwingUtilities.invokeLater(() -> { + newSearchButton.setText(Bundle.DiscoveryTopComponent_newSearch_text()); + progressMessageTextArea.setForeground(Color.black); + String descriptionText = ""; + if (searchType == DOMAIN) { + //domain does not have a file type filter to add the type information so it is manually added + descriptionText = Bundle.DiscoveryTopComponent_domainSearch_text(); + if (!searchCompleteEvent.getFilters().isEmpty()) { + descriptionText += Bundle.DiscoveryTopComponent_additionalFilters_text(); + } + rightSplitPane.setBottomComponent(new DomainDetailsPanel(selectedDomainTabName)); + } else { + rightSplitPane.setBottomComponent(new FileDetailsPanel()); } - rightSplitPane.setBottomComponent(new DomainDetailsPanel(selectedDomainTabName)); - } else { - rightSplitPane.setBottomComponent(new FileDetailsPanel()); - } - DiscoveryEventUtils.getDiscoveryEventBus().register(rightSplitPane.getBottomComponent()); - descriptionText += searchCompleteEvent.getFilters().stream().map(AbstractFilter::getDesc).collect(Collectors.joining("; ")); - progressMessageTextArea.setText(Bundle.DiscoveryTopComponent_searchComplete_text(descriptionText)); - progressMessageTextArea.setCaretPosition(0); + DiscoveryEventUtils.getDiscoveryEventBus().register(rightSplitPane.getBottomComponent()); + descriptionText += searchCompleteEvent.getFilters().stream().map(AbstractFilter::getDesc).collect(Collectors.joining("; ")); + progressMessageTextArea.setText(Bundle.DiscoveryTopComponent_searchComplete_text(descriptionText)); + progressMessageTextArea.setCaretPosition(0); + }); } /** @@ -334,9 +343,11 @@ public final class DiscoveryTopComponent extends TopComponent { @Messages({"DiscoveryTopComponent.searchCancelled.text=Search has been cancelled."}) @Subscribe void handleSearchCancelledEvent(DiscoveryEventUtils.SearchCancelledEvent searchCancelledEvent) { - newSearchButton.setText(Bundle.DiscoveryTopComponent_newSearch_text()); - progressMessageTextArea.setForeground(Color.red); - progressMessageTextArea.setText(Bundle.DiscoveryTopComponent_searchCancelled_text()); + SwingUtilities.invokeLater(() -> { + newSearchButton.setText(Bundle.DiscoveryTopComponent_newSearch_text()); + progressMessageTextArea.setForeground(Color.red); + progressMessageTextArea.setText(Bundle.DiscoveryTopComponent_searchCancelled_text()); + }); } @@ -345,12 +356,14 @@ public final class DiscoveryTopComponent extends TopComponent { */ private final class ShowDetailsAreaCallback implements SwingAnimatorCallback { + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override public void callback(Object caller) { dividerLocation -= ANIMATION_INCREMENT; repaint(); } + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override public boolean hasTerminated() { if (dividerLocation != JSplitPane.UNDEFINED_CONDITION && dividerLocation < resultsAreaSize) { @@ -368,12 +381,14 @@ public final class DiscoveryTopComponent extends TopComponent { */ private final class HideDetailsAreaCallback implements SwingAnimatorCallback { + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override public void callback(Object caller) { dividerLocation += ANIMATION_INCREMENT; repaint(); } + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override public boolean hasTerminated() { if (dividerLocation > rightSplitPane.getHeight() || dividerLocation == JSplitPane.UNDEFINED_CONDITION) { @@ -399,6 +414,7 @@ public final class DiscoveryTopComponent extends TopComponent { private static final long serialVersionUID = 1L; + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override public void paintComponent(Graphics g) { if (animator != null && animator.isRunning() && (dividerLocation == JSplitPane.UNDEFINED_CONDITION diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/DiscoveryUiUtils.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/DiscoveryUiUtils.java index a1a15616e7..7b4287a0b6 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/DiscoveryUiUtils.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/DiscoveryUiUtils.java @@ -51,6 +51,7 @@ import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.corelibs.ScalrWrapper; import org.sleuthkit.autopsy.coreutils.ImageUtils; import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.coreutils.ThreadConfined; import static org.sleuthkit.autopsy.coreutils.VideoUtils.getVideoFileInTempDir; import org.sleuthkit.autopsy.datamodel.ContentUtils; import org.sleuthkit.autopsy.discovery.search.ResultFile; @@ -173,6 +174,7 @@ final class DiscoveryUiUtils { * * @return True if the point is over the icon, false otherwise. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) static boolean isPointOnIcon(Component comp, Point point) { return comp instanceof JComponent && point.x >= comp.getX() && point.x <= comp.getX() + ICON_SIZE && point.y >= comp.getY() && point.y <= comp.getY() + ICON_SIZE; } @@ -186,6 +188,7 @@ final class DiscoveryUiUtils { * @param isDeletedLabel The label to set the icon and tooltip for. */ @NbBundle.Messages({"DiscoveryUiUtils.isDeleted.text=All instances of file are deleted."}) + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) static void setDeletedIcon(boolean isDeleted, javax.swing.JLabel isDeletedLabel) { if (isDeleted) { isDeletedLabel.setIcon(DELETED_ICON); @@ -203,6 +206,7 @@ final class DiscoveryUiUtils { * score of. * @param scoreLabel The label to set the icon and tooltip for. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) static void setScoreIcon(ResultFile resultFile, javax.swing.JLabel scoreLabel) { switch (resultFile.getScore()) { case NOTABLE_SCORE: @@ -232,6 +236,7 @@ final class DiscoveryUiUtils { * Helper method to display an error message when the results of the * Discovery Top component may be incomplete. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @NbBundle.Messages({"DiscoveryUiUtils.resultsIncomplete.text=Discovery results may be incomplete"}) static void displayErrorMessage(DiscoveryDialog dialog) { //check if modules run and assemble message diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/DocumentFilterPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/DocumentFilterPanel.java index 44e303ccc1..fe2dfe4b1f 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/DocumentFilterPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/DocumentFilterPanel.java @@ -19,6 +19,7 @@ package org.sleuthkit.autopsy.discovery.ui; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository; +import org.sleuthkit.autopsy.coreutils.ThreadConfined; import org.sleuthkit.autopsy.discovery.search.SearchData; /** @@ -32,6 +33,7 @@ final class DocumentFilterPanel extends AbstractFiltersPanel { /** * Constructs a new DocumentFilterPanel. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) DocumentFilterPanel() { super(); initComponents(); diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/DocumentPanel.form b/Core/src/org/sleuthkit/autopsy/discovery/ui/DocumentPanel.form index 9329d6f976..7f61fbd6fb 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/DocumentPanel.form +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/DocumentPanel.form @@ -79,9 +79,6 @@ - - - @@ -91,6 +88,9 @@ + + + @@ -98,7 +98,6 @@ - @@ -108,6 +107,7 @@ + diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/DocumentPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/DocumentPanel.java index 08bdd70791..a0c37e8639 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/DocumentPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/DocumentPanel.java @@ -29,6 +29,7 @@ import javax.swing.JList; import javax.swing.ListCellRenderer; import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.corecomponents.AutoWrappingJTextPane; +import org.sleuthkit.autopsy.coreutils.ThreadConfined; import org.sleuthkit.autopsy.discovery.search.SearchData; /** @@ -43,6 +44,7 @@ class DocumentPanel extends javax.swing.JPanel implements ListCellRenderer list, DocumentWrapper value, int index, boolean isSelected, boolean cellHasFocus) { fileSizeLabel.setText(DiscoveryUiUtils.getFileSizeString(value.getResultFile().getFirstInstance().getSize())); @@ -180,6 +182,7 @@ class DocumentPanel extends javax.swing.JPanel implements ListCellRenderer getInstancesForSelected() { - synchronized (this) { - if (documentList.getSelectedIndex() == -1) { - return new ArrayList<>(); - } else { - return documentListModel.getElementAt(documentList.getSelectedIndex()).getResultFile().getAllInstances(); - } + if (documentList.getSelectedIndex() == -1) { + return new ArrayList<>(); + } else { + return documentListModel.getElementAt(documentList.getSelectedIndex()).getResultFile().getAllInstances(); } } @@ -120,9 +121,8 @@ final class DocumentPreviewViewer extends javax.swing.JPanel { * @param documentWrapper The object which contains the document preview * which will be displayed. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) void addDocument(DocumentWrapper documentWrapper) { - synchronized (this) { - documentListModel.addElement(documentWrapper); - } + documentListModel.addElement(documentWrapper); } } diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.java index ad727fddc7..c42c687878 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.java @@ -27,6 +27,7 @@ import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import org.sleuthkit.autopsy.contentviewers.artifactviewers.DefaultArtifactContentViewer; import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.coreutils.ThreadConfined; import org.sleuthkit.autopsy.discovery.search.DiscoveryEventUtils; import org.sleuthkit.datamodel.BlackboardArtifact; @@ -53,10 +54,13 @@ final class DomainArtifactsTabPanel extends JPanel { /** * Creates new form CookiesPanel + * + * @param type The type of Artifact this tab is displaying information for. */ - DomainArtifactsTabPanel(BlackboardArtifact.ARTIFACT_TYPE artifactType) { + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) + DomainArtifactsTabPanel(BlackboardArtifact.ARTIFACT_TYPE type) { initComponents(); - this.artifactType = artifactType; + this.artifactType = type; jSplitPane1.setLeftComponent(listPanel); setRightComponent(); listPanel.addSelectionListener(listener); @@ -66,6 +70,7 @@ final class DomainArtifactsTabPanel extends JPanel { * Set the right component of the tab panel, which will display the details * for the artifact. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) private void setRightComponent() { switch (artifactType) { case TSK_WEB_HISTORY: @@ -90,6 +95,7 @@ final class DomainArtifactsTabPanel extends JPanel { * * @return The ArtifactRetrievalStatuss of the panel. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) ArtifactRetrievalStatus getStatus() { return status; } @@ -99,6 +105,7 @@ final class DomainArtifactsTabPanel extends JPanel { * * @param status The ArtifactRetrievalStatus of the panel. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) void setStatus(ArtifactRetrievalStatus status) { this.status = status; if (status == ArtifactRetrievalStatus.UNPOPULATED && rightPanel != null) { @@ -139,6 +146,7 @@ final class DomainArtifactsTabPanel extends JPanel { * * @return The ARTIFACT_TYPE of the BlackboardArtifact being displayed. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) BlackboardArtifact.ARTIFACT_TYPE getArtifactType() { return artifactType; } diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.java index 9ff722ce4c..cc08f606ea 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.java @@ -25,6 +25,7 @@ import javax.swing.SwingUtilities; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import org.apache.commons.lang.StringUtils; +import org.sleuthkit.autopsy.coreutils.ThreadConfined; import org.sleuthkit.autopsy.discovery.search.DiscoveryEventUtils; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.autopsy.discovery.search.SearchData; @@ -43,6 +44,7 @@ final class DomainDetailsPanel extends JPanel { /** * Creates new form ArtifactDetailsPanel. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) DomainDetailsPanel(String selectedTabName) { initComponents(); addArtifactTabs(selectedTabName); @@ -52,6 +54,7 @@ final class DomainDetailsPanel extends JPanel { /** * Add the tabs for each of the artifact types which we will be displaying. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) private void addArtifactTabs(String tabName) { for (BlackboardArtifact.ARTIFACT_TYPE type : SearchData.Type.DOMAIN.getArtifactTypes()) { jTabbedPane1.add(type.getDisplayName(), new DomainArtifactsTabPanel(type)); @@ -72,6 +75,7 @@ final class DomainDetailsPanel extends JPanel { }); } + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) private void selectTab() { for (int i = 0; i < jTabbedPane1.getTabCount(); i++) { if (!StringUtils.isBlank(selectedTabName) && selectedTabName.equals(jTabbedPane1.getTitleAt(i))) { @@ -110,7 +114,7 @@ final class DomainDetailsPanel extends JPanel { * domain the details tabs should be populated for. */ @Subscribe - synchronized void handlePopulateDomainTabsEvent(DiscoveryEventUtils.PopulateDomainTabsEvent populateEvent) { + void handlePopulateDomainTabsEvent(DiscoveryEventUtils.PopulateDomainTabsEvent populateEvent) { SwingUtilities.invokeLater(() -> { domain = populateEvent.getDomain(); resetTabsStatus(); @@ -130,6 +134,7 @@ final class DomainDetailsPanel extends JPanel { * Private helper method to ensure tabs will re-populate after a new domain * is selected. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) private void resetTabsStatus() { for (Component comp : jTabbedPane1.getComponents()) { if (comp instanceof DomainArtifactsTabPanel) { @@ -143,7 +148,8 @@ final class DomainDetailsPanel extends JPanel { * * @return The name of the tab that was most recently selected. */ - String getSelectedTabName(){ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) + String getSelectedTabName() { return selectedTabName; } diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainFilterPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainFilterPanel.java index bce5577054..3216110694 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainFilterPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainFilterPanel.java @@ -19,6 +19,7 @@ package org.sleuthkit.autopsy.discovery.ui; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository; +import org.sleuthkit.autopsy.coreutils.ThreadConfined; import org.sleuthkit.autopsy.discovery.search.DiscoveryAttributes; import org.sleuthkit.autopsy.discovery.search.ResultsSorter; import org.sleuthkit.autopsy.discovery.search.SearchData; @@ -34,6 +35,7 @@ public class DomainFilterPanel extends AbstractFiltersPanel { /** * Creates new form DomainFilterPanel. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) public DomainFilterPanel() { super(); initComponents(); diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainSummaryPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainSummaryPanel.java index c6979663a7..74e0d7d0ba 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainSummaryPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainSummaryPanel.java @@ -30,6 +30,7 @@ import javax.swing.JComponent; import javax.swing.JList; import javax.swing.ListCellRenderer; import org.openide.util.NbBundle; +import org.sleuthkit.autopsy.coreutils.ThreadConfined; /** * Class which displays a preview and details about a domain. @@ -43,6 +44,7 @@ class DomainSummaryPanel extends javax.swing.JPanel implements ListCellRenderer< /** * Creates new form DomainPanel. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) DomainSummaryPanel() { initComponents(); domainNameLabel.setFont(domainNameLabel.getFont().deriveFont(domainNameLabel.getFont().getStyle(), domainNameLabel.getFont().getSize() + 6)); @@ -136,6 +138,7 @@ class DomainSummaryPanel extends javax.swing.JPanel implements ListCellRenderer< private javax.swing.JLabel totalVisitsLabel; // End of variables declaration//GEN-END:variables + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @NbBundle.Messages({"# {0} - startDate", "# {1} - endDate", "DomainSummaryPanel.activity.text=Activity: {0} to {1}", @@ -163,6 +166,7 @@ class DomainSummaryPanel extends javax.swing.JPanel implements ListCellRenderer< return this; } + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override public String getToolTipText(MouseEvent event) { if (event != null) { diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainSummaryViewer.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainSummaryViewer.java index 331fb8fa9d..66125e36d0 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainSummaryViewer.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainSummaryViewer.java @@ -20,6 +20,7 @@ package org.sleuthkit.autopsy.discovery.ui; import javax.swing.DefaultListModel; import javax.swing.event.ListSelectionListener; +import org.sleuthkit.autopsy.coreutils.ThreadConfined; import org.sleuthkit.autopsy.discovery.search.DiscoveryEventUtils; /** @@ -32,20 +33,20 @@ public class DomainSummaryViewer extends javax.swing.JPanel { private final DefaultListModel domainListModel = new DefaultListModel<>(); /** - * Clear the list of documents being displayed. + * Creates new form DomainSummaryPanel */ - void clearViewer() { - synchronized (this) { - domainListModel.removeAllElements(); - domainScrollPane.getVerticalScrollBar().setValue(0); - } + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) + public DomainSummaryViewer() { + initComponents(); } /** - * Creates new form DomainSummaryPanel + * Clear the list of documents being displayed. */ - public DomainSummaryViewer() { - initComponents(); + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) + void clearViewer() { + domainListModel.removeAllElements(); + domainScrollPane.getVerticalScrollBar().setValue(0); } /** @@ -81,10 +82,9 @@ public class DomainSummaryViewer extends javax.swing.JPanel { * @param domainWrapper The object which contains the domain summary which * will be displayed. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) void addDomain(DomainWrapper domainWrapper) { - synchronized (this) { - domainListModel.addElement(domainWrapper); - } + domainListModel.addElement(domainWrapper); } /** @@ -95,13 +95,12 @@ public class DomainSummaryViewer extends javax.swing.JPanel { * @param useDomain If the currently selected domain should be used to * retrieve a list. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) void sendPopulateEvent(boolean useDomain) { String domain = ""; if (useDomain) { - synchronized (this) { - if (domainList.getSelectedIndex() != -1) { - domain = domainListModel.getElementAt(domainList.getSelectedIndex()).getResultDomain().getDomain(); - } + if (domainList.getSelectedIndex() != -1) { + domain = domainListModel.getElementAt(domainList.getSelectedIndex()).getResultDomain().getDomain(); } } //send populateMesage @@ -114,6 +113,7 @@ public class DomainSummaryViewer extends javax.swing.JPanel { * * @param listener The ListSelectionListener to add to the selection model. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) void addListSelectionListener(ListSelectionListener listener) { domainList.getSelectionModel().addListSelectionListener(listener); } diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/FileDetailsPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/FileDetailsPanel.java index b38ff7aaa4..9230459d6d 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/FileDetailsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/FileDetailsPanel.java @@ -36,6 +36,7 @@ import org.sleuthkit.autopsy.actions.AddContentTagAction; import org.sleuthkit.autopsy.actions.DeleteFileContentTagAction; import org.sleuthkit.autopsy.corecomponents.DataContentPanel; import org.sleuthkit.autopsy.corecomponents.TableFilterNode; +import org.sleuthkit.autopsy.coreutils.ThreadConfined; import org.sleuthkit.autopsy.datamodel.FileNode; import org.sleuthkit.autopsy.directorytree.ExternalViewerAction; import org.sleuthkit.autopsy.directorytree.ViewContextAction; @@ -59,6 +60,7 @@ final class FileDetailsPanel extends javax.swing.JPanel { /** * Creates new form DetailsPanel. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) FileDetailsPanel() { initComponents(); dataContentPanel = DataContentPanel.createInstance(); @@ -112,7 +114,9 @@ final class FileDetailsPanel extends javax.swing.JPanel { */ @Subscribe void handleClearSelectionListener(DiscoveryEventUtils.ClearInstanceSelectionEvent clearEvent) { - instancesList.clearSelection(); + SwingUtilities.invokeLater(() -> { + instancesList.clearSelection(); + }); } /** @@ -122,7 +126,7 @@ final class FileDetailsPanel extends javax.swing.JPanel { * instances list should be populated */ @Subscribe - synchronized void handlePopulateInstancesListEvent(DiscoveryEventUtils.PopulateInstancesListEvent populateEvent) { + void handlePopulateInstancesListEvent(DiscoveryEventUtils.PopulateInstancesListEvent populateEvent) { SwingUtilities.invokeLater(() -> { List files = populateEvent.getInstances(); if (files.isEmpty()) { @@ -154,7 +158,8 @@ final class FileDetailsPanel extends javax.swing.JPanel { * * @return The AbstractFile which is currently selected. */ - synchronized AbstractFile getSelectedFile() { + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) + AbstractFile getSelectedFile() { if (instancesList.getSelectedIndex() == -1) { return null; } else { @@ -241,6 +246,7 @@ final class FileDetailsPanel extends javax.swing.JPanel { private static final long serialVersionUID = 1L; + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/GroupListPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/GroupListPanel.java index 714d5202f0..5a3b5393af 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/GroupListPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/GroupListPanel.java @@ -31,6 +31,7 @@ import javax.swing.JList; import javax.swing.JOptionPane; import javax.swing.SwingUtilities; import org.openide.util.NbBundle.Messages; +import org.sleuthkit.autopsy.coreutils.ThreadConfined; import org.sleuthkit.autopsy.discovery.search.DiscoveryAttributes; import org.sleuthkit.autopsy.discovery.search.DiscoveryEventUtils; import org.sleuthkit.autopsy.discovery.search.DiscoveryKeyUtils.GroupKey; @@ -56,6 +57,7 @@ final class GroupListPanel extends javax.swing.JPanel { /** * Creates new form GroupListPanel. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) GroupListPanel() { initComponents(); } @@ -67,8 +69,10 @@ final class GroupListPanel extends javax.swing.JPanel { */ @Subscribe void handleSearchStartedEvent(DiscoveryEventUtils.SearchStartedEvent searchStartedEvent) { - type = searchStartedEvent.getType(); - groupKeyList.setListData(new GroupKey[0]); + SwingUtilities.invokeLater(() -> { + type = searchStartedEvent.getType(); + groupKeyList.setListData(new GroupKey[0]); + }); } @Messages({"GroupsListPanel.noFileResults.message.text=No files were found for the selected filters.\n\n" @@ -90,27 +94,29 @@ final class GroupListPanel extends javax.swing.JPanel { */ @Subscribe void handleSearchCompleteEvent(DiscoveryEventUtils.SearchCompleteEvent searchCompleteEvent) { - groupMap = searchCompleteEvent.getGroupMap(); - searchfilters = searchCompleteEvent.getFilters(); - groupingAttribute = searchCompleteEvent.getGroupingAttr(); - groupSort = searchCompleteEvent.getGroupSort(); - resultSortMethod = searchCompleteEvent.getResultSort(); - groupKeyList.setListData(groupMap.keySet().toArray(new GroupKey[groupMap.keySet().size()])); SwingUtilities.invokeLater(() -> { - if (groupKeyList.getModel().getSize() > 0) { - groupKeyList.setSelectedIndex(0); - } else if (type == DOMAIN) { - JOptionPane.showMessageDialog(DiscoveryTopComponent.getTopComponent(), - Bundle.GroupsListPanel_noDomainResults_message_text(), - Bundle.GroupsListPanel_noResults_title_text(), - JOptionPane.PLAIN_MESSAGE); - } else { - JOptionPane.showMessageDialog(DiscoveryTopComponent.getTopComponent(), - Bundle.GroupsListPanel_noFileResults_message_text(), - Bundle.GroupsListPanel_noResults_title_text(), - JOptionPane.PLAIN_MESSAGE); - } - setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + groupMap = searchCompleteEvent.getGroupMap(); + searchfilters = searchCompleteEvent.getFilters(); + groupingAttribute = searchCompleteEvent.getGroupingAttr(); + groupSort = searchCompleteEvent.getGroupSort(); + resultSortMethod = searchCompleteEvent.getResultSort(); + groupKeyList.setListData(groupMap.keySet().toArray(new GroupKey[groupMap.keySet().size()])); + SwingUtilities.invokeLater(() -> { + if (groupKeyList.getModel().getSize() > 0) { + groupKeyList.setSelectedIndex(0); + } else if (type == DOMAIN) { + JOptionPane.showMessageDialog(DiscoveryTopComponent.getTopComponent(), + Bundle.GroupsListPanel_noDomainResults_message_text(), + Bundle.GroupsListPanel_noResults_title_text(), + JOptionPane.PLAIN_MESSAGE); + } else { + JOptionPane.showMessageDialog(DiscoveryTopComponent.getTopComponent(), + Bundle.GroupsListPanel_noFileResults_message_text(), + Bundle.GroupsListPanel_noResults_title_text(), + JOptionPane.PLAIN_MESSAGE); + } + setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + }); }); } @@ -168,10 +174,9 @@ final class GroupListPanel extends javax.swing.JPanel { /** * Reset the group list to be empty. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) void resetGroupList() { - SwingUtilities.invokeLater(() -> { - setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); - }); + setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); groupKeyList.setListData(new GroupKey[0]); } @@ -211,6 +216,7 @@ final class GroupListPanel extends javax.swing.JPanel { private static final long serialVersionUID = 1L; + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override public java.awt.Component getListCellRendererComponent( JList list, diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/HashSetFilterPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/HashSetFilterPanel.java index 4698c43dc3..0257352a16 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/HashSetFilterPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/HashSetFilterPanel.java @@ -27,6 +27,7 @@ import javax.swing.JLabel; import javax.swing.JList; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.coreutils.ThreadConfined; import org.sleuthkit.autopsy.discovery.search.SearchFiltering; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardAttribute; @@ -43,6 +44,7 @@ final class HashSetFilterPanel extends AbstractDiscoveryFilterPanel { /** * Creates new form HashSetFilterPaenl. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) HashSetFilterPanel() { initComponents(); setUpHashFilter(); @@ -51,6 +53,7 @@ final class HashSetFilterPanel extends AbstractDiscoveryFilterPanel { /** * Initialize the hash filter. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) private void setUpHashFilter() { int count = 0; try { @@ -123,6 +126,7 @@ final class HashSetFilterPanel extends AbstractDiscoveryFilterPanel { private javax.swing.JScrollPane hashSetScrollPane; // End of variables declaration//GEN-END:variables + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override void configurePanel(boolean selected, int[] indicesSelected) { boolean hasHashSets = hashSetList.getModel().getSize() > 0; @@ -140,6 +144,7 @@ final class HashSetFilterPanel extends AbstractDiscoveryFilterPanel { } } + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override JCheckBox getCheckbox() { return hashSetCheckbox; @@ -150,6 +155,7 @@ final class HashSetFilterPanel extends AbstractDiscoveryFilterPanel { return null; } + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @NbBundle.Messages({"HashSetFilterPanel.error.text=At least one hash set name must be selected."}) @Override String checkForError() { @@ -159,11 +165,13 @@ final class HashSetFilterPanel extends AbstractDiscoveryFilterPanel { return ""; } + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override JList getList() { return hashSetList; } + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override AbstractFilter getFilter() { if (hashSetCheckbox.isSelected()) { diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/ImageFilterPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/ImageFilterPanel.java index 308cdd569b..4557b02d74 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/ImageFilterPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/ImageFilterPanel.java @@ -19,6 +19,7 @@ package org.sleuthkit.autopsy.discovery.ui; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository; +import org.sleuthkit.autopsy.coreutils.ThreadConfined; import org.sleuthkit.autopsy.discovery.search.SearchData; /** @@ -32,6 +33,7 @@ final class ImageFilterPanel extends AbstractFiltersPanel { /** * Creates new form ImageFilterPanel. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) ImageFilterPanel() { super(); initComponents(); diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/ImageThumbnailPanel.form b/Core/src/org/sleuthkit/autopsy/discovery/ui/ImageThumbnailPanel.form index 46c5d3601f..2a52cb88d3 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/ImageThumbnailPanel.form +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/ImageThumbnailPanel.form @@ -84,7 +84,6 @@ - @@ -94,6 +93,7 @@ + @@ -101,9 +101,6 @@ - - - @@ -113,6 +110,9 @@ + + + @@ -120,7 +120,6 @@ - @@ -130,6 +129,7 @@ + diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/ImageThumbnailPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/ImageThumbnailPanel.java index d294fa866d..22ce4a0809 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/ImageThumbnailPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/ImageThumbnailPanel.java @@ -28,6 +28,7 @@ import javax.swing.JComponent; import javax.swing.JList; import javax.swing.ListCellRenderer; import org.openide.util.NbBundle; +import org.sleuthkit.autopsy.coreutils.ThreadConfined; /** * Class which displays a thumbnail and information for an image file. @@ -41,6 +42,7 @@ final class ImageThumbnailPanel extends javax.swing.JPanel implements ListCellRe /** * Creates new form ImageThumbnailPanel */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) ImageThumbnailPanel() { initComponents(); } @@ -129,6 +131,7 @@ final class ImageThumbnailPanel extends javax.swing.JPanel implements ListCellRe private javax.swing.JLabel thumbnailLabel; // End of variables declaration//GEN-END:variables + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @NbBundle.Messages({ "# {0} - otherInstanceCount", "ImageThumbnailPanel.nameLabel.more.text= and {0} more", @@ -152,6 +155,7 @@ final class ImageThumbnailPanel extends javax.swing.JPanel implements ListCellRe return this; } + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override public String getToolTipText(MouseEvent event) { if (event != null) { diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/ImageThumbnailViewer.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/ImageThumbnailViewer.java index 273cca8023..cd9fd4909a 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/ImageThumbnailViewer.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/ImageThumbnailViewer.java @@ -22,6 +22,7 @@ import java.util.ArrayList; import java.util.List; import javax.swing.DefaultListModel; import javax.swing.event.ListSelectionListener; +import org.sleuthkit.autopsy.coreutils.ThreadConfined; import org.sleuthkit.datamodel.AbstractFile; /** @@ -37,6 +38,7 @@ final class ImageThumbnailViewer extends javax.swing.JPanel { /** * Creates new form ImageThumbnailViewer. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) ImageThumbnailViewer() { initComponents(); @@ -77,6 +79,7 @@ final class ImageThumbnailViewer extends javax.swing.JPanel { * * @param listener The ListSelectionListener to add to the selection model. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) void addListSelectionListener(ListSelectionListener listener) { thumbnailList.getSelectionModel().addListSelectionListener(listener); } @@ -88,24 +91,23 @@ final class ImageThumbnailViewer extends javax.swing.JPanel { * @return The list of AbstractFiles which are represented by the selected * image thumbnail. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) List getInstancesForSelected() { - synchronized (this) { - if (thumbnailList.getSelectedIndex() == -1) { - return new ArrayList<>(); - } else { - return thumbnailListModel.getElementAt(thumbnailList.getSelectedIndex()).getResultFile().getAllInstances(); - } + if (thumbnailList.getSelectedIndex() == -1) { + return new ArrayList<>(); + } else { + return thumbnailListModel.getElementAt(thumbnailList.getSelectedIndex()).getResultFile().getAllInstances(); } } /** * Clear the list of thumbnails being displayed. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) void clearViewer() { - synchronized (this) { - thumbnailListModel.removeAllElements(); - thumbnailListScrollPane.getVerticalScrollBar().setValue(0); - } + thumbnailListModel.removeAllElements(); + thumbnailListScrollPane.getVerticalScrollBar().setValue(0); + } /** @@ -114,9 +116,8 @@ final class ImageThumbnailViewer extends javax.swing.JPanel { * @param thumbnailWrapper The object which contains the thumbnail which * will be displayed. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) void addImage(ImageThumbnailWrapper thumbnailWrapper) { - synchronized (this) { - thumbnailListModel.addElement(thumbnailWrapper); - } + thumbnailListModel.addElement(thumbnailWrapper); } } diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/InterestingItemsFilterPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/InterestingItemsFilterPanel.java index b77956937d..184ddb1d29 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/InterestingItemsFilterPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/InterestingItemsFilterPanel.java @@ -27,6 +27,7 @@ import javax.swing.JLabel; import javax.swing.JList; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.coreutils.ThreadConfined; import org.sleuthkit.autopsy.discovery.search.SearchFiltering; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardAttribute; @@ -43,6 +44,7 @@ final class InterestingItemsFilterPanel extends AbstractDiscoveryFilterPanel { /** * Creates new form InterestingItemsFilterPanel. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) InterestingItemsFilterPanel() { initComponents(); setUpInterestingItemsFilter(); @@ -51,6 +53,7 @@ final class InterestingItemsFilterPanel extends AbstractDiscoveryFilterPanel { /** * Initialize the interesting items filter. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) private void setUpInterestingItemsFilter() { int count = 0; try { @@ -118,6 +121,7 @@ final class InterestingItemsFilterPanel extends AbstractDiscoveryFilterPanel { interestingItemsList.setEnabled(interestingItemsCheckbox.isSelected()); }//GEN-LAST:event_interestingItemsCheckboxActionPerformed + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override void configurePanel(boolean selected, int[] indicesSelected) { boolean hasInterestingItems = interestingItemsList.getModel().getSize() > 0; @@ -135,6 +139,7 @@ final class InterestingItemsFilterPanel extends AbstractDiscoveryFilterPanel { } } + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override JCheckBox getCheckbox() { return interestingItemsCheckbox; @@ -145,6 +150,7 @@ final class InterestingItemsFilterPanel extends AbstractDiscoveryFilterPanel { return null; } + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @NbBundle.Messages({"InterestingItemsFilterPanel.error.text=At least one interesting file set name must be selected."}) @Override String checkForError() { @@ -161,11 +167,13 @@ final class InterestingItemsFilterPanel extends AbstractDiscoveryFilterPanel { private javax.swing.JScrollPane interestingItemsScrollPane; // End of variables declaration//GEN-END:variables + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override JList getList() { return interestingItemsList; } + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override AbstractFilter getFilter() { if (interestingItemsCheckbox.isSelected()) { diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/ObjectDetectedFilterPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/ObjectDetectedFilterPanel.java index eb1c1525c5..a6eb3de1c5 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/ObjectDetectedFilterPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/ObjectDetectedFilterPanel.java @@ -27,6 +27,7 @@ import javax.swing.JLabel; import javax.swing.JList; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.coreutils.ThreadConfined; import org.sleuthkit.autopsy.discovery.search.SearchFiltering; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardAttribute; @@ -43,6 +44,7 @@ final class ObjectDetectedFilterPanel extends AbstractDiscoveryFilterPanel { /** * Creates new form ObjectDetectedFilter. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) ObjectDetectedFilterPanel() { initComponents(); setUpObjectFilter(); @@ -51,6 +53,7 @@ final class ObjectDetectedFilterPanel extends AbstractDiscoveryFilterPanel { /** * Initialize the object filter. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) private void setUpObjectFilter() { int count = 0; try { @@ -129,6 +132,7 @@ final class ObjectDetectedFilterPanel extends AbstractDiscoveryFilterPanel { private javax.swing.JScrollPane objectsScrollPane; // End of variables declaration//GEN-END:variables + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override void configurePanel(boolean selected, int[] indicesSelected) { boolean hasObjects = objectsList.getModel().getSize() > 0; @@ -146,6 +150,7 @@ final class ObjectDetectedFilterPanel extends AbstractDiscoveryFilterPanel { } } + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override JCheckBox getCheckbox() { return objectsCheckbox; @@ -155,6 +160,8 @@ final class ObjectDetectedFilterPanel extends AbstractDiscoveryFilterPanel { JLabel getAdditionalLabel() { return null; } + + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @NbBundle.Messages({"ObjectDetectedFilterPanel.error.text=At least one object type name must be selected."}) @Override String checkForError() { @@ -164,11 +171,13 @@ final class ObjectDetectedFilterPanel extends AbstractDiscoveryFilterPanel { return ""; } + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override JList getList() { return objectsList; } + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override AbstractFilter getFilter() { if (objectsCheckbox.isSelected()) { diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/OpenDiscoveryAction.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/OpenDiscoveryAction.java index 33228a6a9b..26f18f8660 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/OpenDiscoveryAction.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/OpenDiscoveryAction.java @@ -31,6 +31,7 @@ import org.openide.util.NbBundle; import org.openide.util.actions.CallableSystemAction; import org.openide.util.actions.Presenter; import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.coreutils.ThreadConfined; /** * Class to open the Discovery dialog. Allows the user to run searches and see @@ -51,6 +52,7 @@ public final class OpenDiscoveryAction extends CallableSystemAction implements P /** * Construct a new OpenDiscoveryAction. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) public OpenDiscoveryAction() { toolbarButton.addActionListener(OpenDiscoveryAction.this::actionPerformed); this.setEnabled(false); @@ -76,6 +78,7 @@ public final class OpenDiscoveryAction extends CallableSystemAction implements P * * @return The toolbar button */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override public Component getToolbarPresenter() { ImageIcon icon = new ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/discovery-icon-24.png")); //NON-NLS @@ -89,6 +92,7 @@ public final class OpenDiscoveryAction extends CallableSystemAction implements P * * @param value whether to enable this action or not */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override public void setEnabled(boolean value) { super.setEnabled(value); diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/ParentFolderFilterPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/ParentFolderFilterPanel.java index a2a0d9615f..2a77c28873 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/ParentFolderFilterPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/ParentFolderFilterPanel.java @@ -26,6 +26,7 @@ import javax.swing.JCheckBox; import javax.swing.JLabel; import javax.swing.JList; import org.openide.util.NbBundle; +import org.sleuthkit.autopsy.coreutils.ThreadConfined; import org.sleuthkit.autopsy.discovery.search.SearchFiltering; import org.sleuthkit.autopsy.discovery.search.SearchFiltering.ParentSearchTerm; @@ -41,6 +42,7 @@ final class ParentFolderFilterPanel extends AbstractDiscoveryFilterPanel { /** * Creates new form ParentFolderFilterPanel. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) ParentFolderFilterPanel() { initComponents(); setUpParentPathFilter(); @@ -49,6 +51,7 @@ final class ParentFolderFilterPanel extends AbstractDiscoveryFilterPanel { /** * Initialize the parent path filter. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) private void setUpParentPathFilter() { fullRadioButton.setSelected(true); includeRadioButton.setSelected(true); @@ -239,6 +242,7 @@ final class ParentFolderFilterPanel extends AbstractDiscoveryFilterPanel { private javax.swing.JRadioButton substringRadioButton; // End of variables declaration//GEN-END:variables + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override void configurePanel(boolean selected, int[] indicesSelected) { parentCheckbox.setSelected(selected); @@ -270,16 +274,19 @@ final class ParentFolderFilterPanel extends AbstractDiscoveryFilterPanel { } } + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override JCheckBox getCheckbox() { return parentCheckbox; } + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override JLabel getAdditionalLabel() { return parentLabel; } + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @NbBundle.Messages({"ParentFolderFilterPanel.error.text=At least one parent path must be entered."}) @Override String checkForError() { @@ -290,6 +297,7 @@ final class ParentFolderFilterPanel extends AbstractDiscoveryFilterPanel { return ""; } + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) /** * Utility method to get the parent path objects out of the JList. * @@ -303,11 +311,13 @@ final class ParentFolderFilterPanel extends AbstractDiscoveryFilterPanel { return results; } + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override JList getList() { return parentList; } + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override AbstractFilter getFilter() { if (parentCheckbox.isSelected()) { diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/PastOccurrencesFilterPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/PastOccurrencesFilterPanel.java index b19c793556..bedd0a24c8 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/PastOccurrencesFilterPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/PastOccurrencesFilterPanel.java @@ -24,6 +24,7 @@ import javax.swing.JLabel; import javax.swing.JList; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository; +import org.sleuthkit.autopsy.coreutils.ThreadConfined; import org.sleuthkit.autopsy.discovery.search.AbstractFilter; import org.sleuthkit.autopsy.discovery.search.SearchData; import org.sleuthkit.autopsy.discovery.search.SearchData.Frequency; @@ -41,6 +42,7 @@ final class PastOccurrencesFilterPanel extends AbstractDiscoveryFilterPanel { /** * Creates new form PastOccurrencesFilterPanel. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) PastOccurrencesFilterPanel(Type type) { initComponents(); this.type = type; @@ -101,6 +103,7 @@ final class PastOccurrencesFilterPanel extends AbstractDiscoveryFilterPanel { /** * Initialize the frequency filter. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) private void setUpFrequencyFilter() { int count = 0; DefaultListModel frequencyListModel = (DefaultListModel) crFrequencyList.getModel(); @@ -126,6 +129,7 @@ final class PastOccurrencesFilterPanel extends AbstractDiscoveryFilterPanel { private javax.swing.JCheckBox pastOccurrencesCheckbox; // End of variables declaration//GEN-END:variables + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override void configurePanel(boolean selected, int[] indicesSelected) { boolean canBeFilteredOn = type != Type.DOMAIN || CentralRepository.isEnabled(); @@ -144,6 +148,7 @@ final class PastOccurrencesFilterPanel extends AbstractDiscoveryFilterPanel { } } + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override JCheckBox getCheckbox() { return pastOccurrencesCheckbox; @@ -154,6 +159,7 @@ final class PastOccurrencesFilterPanel extends AbstractDiscoveryFilterPanel { return null; } + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @NbBundle.Messages({"PastOccurrencesFilterPanel.error.text=At least one value in the past occurrence filter must be selected."}) @Override String checkForError() { @@ -163,11 +169,13 @@ final class PastOccurrencesFilterPanel extends AbstractDiscoveryFilterPanel { return ""; } + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override JList getList() { return crFrequencyList; } + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override AbstractFilter getFilter() { if (pastOccurrencesCheckbox.isSelected()) { diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/ResultsPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/ResultsPanel.java index 5f67582afc..b6aad696ce 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/ResultsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/ResultsPanel.java @@ -40,6 +40,7 @@ import org.sleuthkit.autopsy.coreutils.ImageUtils; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository; +import org.sleuthkit.autopsy.coreutils.ThreadConfined; import org.sleuthkit.autopsy.discovery.search.DiscoveryAttributes; import org.sleuthkit.autopsy.discovery.search.DiscoveryEventUtils; import org.sleuthkit.autopsy.discovery.search.DiscoveryKeyUtils.GroupKey; @@ -85,6 +86,7 @@ final class ResultsPanel extends javax.swing.JPanel { */ @Messages({"ResultsPanel.viewFileInDir.name=View File in Directory", "ResultsPanel.openInExternalViewer.name=Open in External Viewer"}) + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) ResultsPanel() { initComponents(); imageThumbnailViewer = new ImageThumbnailViewer(); @@ -132,6 +134,7 @@ final class ResultsPanel extends javax.swing.JPanel { }); } + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) SearchData.Type getActiveType() { return resultType; } @@ -143,6 +146,7 @@ final class ResultsPanel extends javax.swing.JPanel { * @return The list of AbstractFiles which are represented by the item * selected in the results viewer area. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) private List getInstancesForSelected() { if (null != resultType) { switch (resultType) { @@ -216,20 +220,22 @@ final class ResultsPanel extends javax.swing.JPanel { @Subscribe void handleCancelBackgroundTasksEvent(DiscoveryEventUtils.CancelBackgroundTasksEvent cancelEvent) { - for (SwingWorker thumbWorker : resultContentWorkers) { - if (!thumbWorker.isDone()) { - thumbWorker.cancel(true); + SwingUtilities.invokeLater(() -> { + for (SwingWorker thumbWorker : resultContentWorkers) { + if (!thumbWorker.isDone()) { + thumbWorker.cancel(true); + } } - } - - resultContentWorkers.clear(); + resultContentWorkers.clear(); + }); } /** * Reset the result viewer and any associate workers to a default empty * state. */ - synchronized void resetResultViewer() { + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) + void resetResultViewer() { resultsViewerPanel.remove(imageThumbnailViewer); resultsViewerPanel.remove(videoThumbnailViewer); resultsViewerPanel.remove(documentPreviewViewer); @@ -254,7 +260,8 @@ final class ResultsPanel extends javax.swing.JPanel { * * @param results The list of ResultFiles to populate the video viewer with. */ - synchronized void populateVideoViewer(List results) { + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) + void populateVideoViewer(List results) { for (Result result : results) { VideoThumbnailWorker thumbWorker = new VideoThumbnailWorker((ResultFile) result); thumbWorker.execute(); @@ -269,7 +276,8 @@ final class ResultsPanel extends javax.swing.JPanel { * * @param results The list of ResultFiles to populate the image viewer with. */ - synchronized void populateImageViewer(List results) { + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) + void populateImageViewer(List results) { for (Result result : results) { ImageThumbnailWorker thumbWorker = new ImageThumbnailWorker((ResultFile) result); thumbWorker.execute(); @@ -285,7 +293,8 @@ final class ResultsPanel extends javax.swing.JPanel { * @param results The list of ResultFiles to populate the document viewer * with. */ - synchronized void populateDocumentViewer(List results) { + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) + void populateDocumentViewer(List results) { for (Result result : results) { DocumentPreviewWorker documentWorker = new DocumentPreviewWorker((ResultFile) result); documentWorker.execute(); @@ -301,7 +310,8 @@ final class ResultsPanel extends javax.swing.JPanel { * @param results The list of ResultDomains to populate the domain summary * viewer with. */ - synchronized void populateDomainViewer(List results) { + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) + void populateDomainViewer(List results) { SleuthkitCase currentCase; try { currentCase = Case.getCurrentCaseThrows().getSleuthkitCase(); @@ -378,37 +388,33 @@ final class ResultsPanel extends javax.swing.JPanel { * @param startingEntry The index of the first file in the group to include * in this page. */ - @Subscribe - private synchronized void setPage(int startingEntry - ) { + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) + private void setPage(int startingEntry) { int pageSize = pageSizeComboBox.getItemAt(pageSizeComboBox.getSelectedIndex()); - synchronized (this) { - if (pageWorker != null && !pageWorker.isDone()) { - pageWorker.cancel(true); - } - CentralRepository centralRepo = null; - if (CentralRepository.isEnabled()) { - try { - centralRepo = CentralRepository.getInstance(); - } catch (CentralRepoException ex) { - centralRepo = null; - logger.log(Level.SEVERE, "Error loading central repository database, no central repository options will be available for Discovery", ex); - } - } - if (groupSize != 0) { - pageWorker = new PageWorker(searchFilters, groupingAttribute, groupSort, fileSortMethod, selectedGroupKey, startingEntry, pageSize, resultType, centralRepo); - pageWorker.execute(); - } else { - SwingUtilities.invokeLater(() -> { - pageSizeComboBox.setEnabled(true); - }); + if (pageWorker != null && !pageWorker.isDone()) { + pageWorker.cancel(true); + } + CentralRepository centralRepo = null; + if (CentralRepository.isEnabled()) { + try { + centralRepo = CentralRepository.getInstance(); + } catch (CentralRepoException ex) { + centralRepo = null; + logger.log(Level.SEVERE, "Error loading central repository database, no central repository options will be available for Discovery", ex); } } + if (groupSize != 0) { + pageWorker = new PageWorker(searchFilters, groupingAttribute, groupSort, fileSortMethod, selectedGroupKey, startingEntry, pageSize, resultType, centralRepo); + pageWorker.execute(); + } else { + pageSizeComboBox.setEnabled(true); + } } /** * Enable the paging controls based on what exists in the page. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Messages({"# {0} - currentPage", "# {1} - totalPages", "ResultsPanel.currentPage.displayValue=Page: {0} of {1}"}) @@ -682,6 +688,7 @@ final class ResultsPanel extends javax.swing.JPanel { /** * Disable all the paging controls. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) private void disablePagingControls() { nextPageButton.setEnabled(false); previousPageButton.setEnabled(false); @@ -712,6 +719,7 @@ final class ResultsPanel extends javax.swing.JPanel { * @param file The ResultFile which represents the video file thumbnails * are being retrieved for. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) VideoThumbnailWorker(ResultFile file) { thumbnailWrapper = new VideoThumbnailsWrapper(file); videoThumbnailViewer.addVideo(thumbnailWrapper); @@ -750,6 +758,7 @@ final class ResultsPanel extends javax.swing.JPanel { * @param file The ResultFile which represents the image file thumbnails * are being retrieved for. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) ImageThumbnailWorker(ResultFile file) { thumbnailWrapper = new ImageThumbnailWrapper(file); imageThumbnailViewer.addImage(thumbnailWrapper); @@ -792,6 +801,7 @@ final class ResultsPanel extends javax.swing.JPanel { * @param file The ResultFile which represents the document file a * preview is being retrieved for. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) DocumentPreviewWorker(ResultFile file) { documentWrapper = new DocumentWrapper(file); documentPreviewViewer.addDocument(documentWrapper); @@ -840,6 +850,7 @@ final class ResultsPanel extends javax.swing.JPanel { * @param file The ResultFile which represents the domain attribute the * preview is being retrieved for. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) DomainThumbnailWorker(SleuthkitCase caseDb, ResultDomain domain) { this.caseDb = caseDb; domainWrapper = new DomainWrapper(domain); diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/ResultsSplitPaneDivider.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/ResultsSplitPaneDivider.java index cffb2dac7f..87c42fbc39 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/ResultsSplitPaneDivider.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/ResultsSplitPaneDivider.java @@ -19,6 +19,7 @@ package org.sleuthkit.autopsy.discovery.ui; import java.awt.Cursor; +import org.sleuthkit.autopsy.coreutils.ThreadConfined; import org.sleuthkit.autopsy.discovery.search.DiscoveryEventUtils; @@ -32,6 +33,7 @@ final class ResultsSplitPaneDivider extends javax.swing.JPanel { /** * Creates new form LabeledSplitPaneDivider. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) ResultsSplitPaneDivider() { initComponents(); } diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/SizeFilterPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/SizeFilterPanel.java index 0585750aa4..e037f1f8ee 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/SizeFilterPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/SizeFilterPanel.java @@ -26,6 +26,7 @@ import javax.swing.JCheckBox; import javax.swing.JLabel; import javax.swing.JList; import org.openide.util.NbBundle; +import org.sleuthkit.autopsy.coreutils.ThreadConfined; import org.sleuthkit.autopsy.discovery.search.SearchData; import org.sleuthkit.autopsy.discovery.search.SearchData.FileSize; import org.sleuthkit.autopsy.discovery.search.SearchFiltering; @@ -42,6 +43,7 @@ final class SizeFilterPanel extends AbstractDiscoveryFilterPanel { * * @param type The type of result being searched for. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) SizeFilterPanel(SearchData.Type type) { initComponents(); setUpSizeFilter(type); @@ -109,6 +111,7 @@ final class SizeFilterPanel extends AbstractDiscoveryFilterPanel { private javax.swing.JScrollPane sizeScrollPane; // End of variables declaration//GEN-END:variables + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override void configurePanel(boolean selected, int[] indicesSelected) { sizeCheckbox.setSelected(selected); @@ -124,6 +127,7 @@ final class SizeFilterPanel extends AbstractDiscoveryFilterPanel { } } + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override JCheckBox getCheckbox() { return sizeCheckbox; @@ -137,6 +141,7 @@ final class SizeFilterPanel extends AbstractDiscoveryFilterPanel { /** * Initialize the file size filter. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) private void setUpSizeFilter(SearchData.Type fileType) { int count = 0; DefaultListModel sizeListModel = (DefaultListModel) sizeList.getModel(); @@ -169,6 +174,7 @@ final class SizeFilterPanel extends AbstractDiscoveryFilterPanel { @NbBundle.Messages({"SizeFilterPanel.error.text=At least one size must be selected."}) @Override + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) String checkForError() { if (sizeCheckbox.isSelected() && sizeList.getSelectedValuesList().isEmpty()) { return Bundle.SizeFilterPanel_error_text(); @@ -177,11 +183,13 @@ final class SizeFilterPanel extends AbstractDiscoveryFilterPanel { } + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override JList getList() { return sizeList; } + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override AbstractFilter getFilter() { if (sizeCheckbox.isSelected()) { diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/UserCreatedFilterPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/UserCreatedFilterPanel.java index d65596633a..10d976f7fe 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/UserCreatedFilterPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/UserCreatedFilterPanel.java @@ -22,6 +22,7 @@ import org.sleuthkit.autopsy.discovery.search.AbstractFilter; import javax.swing.JCheckBox; import javax.swing.JLabel; import javax.swing.JList; +import org.sleuthkit.autopsy.coreutils.ThreadConfined; import org.sleuthkit.autopsy.discovery.search.SearchFiltering; /** @@ -34,6 +35,7 @@ final class UserCreatedFilterPanel extends AbstractDiscoveryFilterPanel { /** * Creates new form UserCreatedFilterPanel. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) UserCreatedFilterPanel() { initComponents(); } @@ -69,11 +71,13 @@ final class UserCreatedFilterPanel extends AbstractDiscoveryFilterPanel { ); }// //GEN-END:initComponents + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override void configurePanel(boolean selected, int[] indicesSelected) { userCreatedCheckbox.setSelected(selected); } + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override JCheckBox getCheckbox() { return userCreatedCheckbox; @@ -99,6 +103,7 @@ final class UserCreatedFilterPanel extends AbstractDiscoveryFilterPanel { return null; } + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override AbstractFilter getFilter() { if (userCreatedCheckbox.isSelected()) { diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/VideoFilterPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/VideoFilterPanel.java index 82b0d030bc..ca96c217c4 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/VideoFilterPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/VideoFilterPanel.java @@ -19,6 +19,7 @@ package org.sleuthkit.autopsy.discovery.ui; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository; +import org.sleuthkit.autopsy.coreutils.ThreadConfined; import org.sleuthkit.autopsy.discovery.search.SearchData; /** @@ -32,6 +33,7 @@ final class VideoFilterPanel extends AbstractFiltersPanel { /** * Creates new form VideoFilterPanel. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) VideoFilterPanel() { super(); initComponents(); diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/VideoThumbnailPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/VideoThumbnailPanel.java index 7a62937582..34e7293a7c 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/VideoThumbnailPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/VideoThumbnailPanel.java @@ -32,6 +32,7 @@ import javax.swing.JLabel; import javax.swing.JList; import javax.swing.ListCellRenderer; import org.openide.util.NbBundle.Messages; +import org.sleuthkit.autopsy.coreutils.ThreadConfined; /** * Class which displays thumbnails and information for a video file. @@ -47,6 +48,7 @@ final class VideoThumbnailPanel extends javax.swing.JPanel implements ListCellRe /** * Creates new form VideoThumbnailPanel. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) VideoThumbnailPanel() { initComponents(); this.setFocusable(true); @@ -58,6 +60,7 @@ final class VideoThumbnailPanel extends javax.swing.JPanel implements ListCellRe * @param thumbnailWrapper The object which contains the video thumbnails to * add. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) private void addThumbnails(VideoThumbnailsWrapper thumbnailWrapper) { imagePanel.removeAll(); GridBagConstraints gridBagConstraints = new GridBagConstraints(); @@ -164,6 +167,7 @@ final class VideoThumbnailPanel extends javax.swing.JPanel implements ListCellRe private javax.swing.JLabel scoreLabel; // End of variables declaration//GEN-END:variables + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Messages({ "# {0} - otherInstanceCount", "VideoThumbnailPanel.nameLabel.more.text= and {0} more", diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/VideoThumbnailViewer.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/VideoThumbnailViewer.java index 8824e6f5d8..f2c250344d 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/VideoThumbnailViewer.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/VideoThumbnailViewer.java @@ -22,6 +22,7 @@ import java.util.ArrayList; import java.util.List; import javax.swing.DefaultListModel; import javax.swing.event.ListSelectionListener; +import org.sleuthkit.autopsy.coreutils.ThreadConfined; import org.sleuthkit.datamodel.AbstractFile; /** @@ -36,6 +37,7 @@ final class VideoThumbnailViewer extends javax.swing.JPanel { /** * Creates new form VideoThumbnailViewer. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) VideoThumbnailViewer() { initComponents(); } @@ -45,6 +47,7 @@ final class VideoThumbnailViewer extends javax.swing.JPanel { * * @param listener The ListSelectionListener to add to the selection model. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) void addListSelectionListener(ListSelectionListener listener) { thumbnailList.getSelectionModel().addListSelectionListener(listener); } @@ -56,24 +59,22 @@ final class VideoThumbnailViewer extends javax.swing.JPanel { * @return The list of AbstractFiles which are represented by the selected * Video thumbnails. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) List getInstancesForSelected() { - synchronized (this) { - if (thumbnailList.getSelectedIndex() == -1) { - return new ArrayList<>(); - } else { - return thumbnailListModel.getElementAt(thumbnailList.getSelectedIndex()).getResultFile().getAllInstances(); - } + if (thumbnailList.getSelectedIndex() == -1) { + return new ArrayList<>(); + } else { + return thumbnailListModel.getElementAt(thumbnailList.getSelectedIndex()).getResultFile().getAllInstances(); } } /** * Clear the list of thumbnails being displayed. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) void clearViewer() { - synchronized (this) { - thumbnailListModel.removeAllElements(); - thumbnailListScrollPane.getVerticalScrollBar().setValue(0); - } + thumbnailListModel.removeAllElements(); + thumbnailListScrollPane.getVerticalScrollBar().setValue(0); } /** @@ -82,10 +83,9 @@ final class VideoThumbnailViewer extends javax.swing.JPanel { * @param thumbnailWrapper The object which contains the thumbnails which * will be displayed. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) void addVideo(VideoThumbnailsWrapper thumbnailWrapper) { - synchronized (this) { - thumbnailListModel.addElement(thumbnailWrapper); - } + thumbnailListModel.addElement(thumbnailWrapper); } /** diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/WebHistoryDetailsPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/WebHistoryDetailsPanel.java index 72f33f993e..deaef104f5 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/WebHistoryDetailsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/WebHistoryDetailsPanel.java @@ -30,6 +30,7 @@ import org.openide.util.lookup.ServiceProvider; import org.sleuthkit.autopsy.contentviewers.artifactviewers.ArtifactContentViewer; import org.sleuthkit.autopsy.contentviewers.artifactviewers.CommunicationArtifactViewerHelper; import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.coreutils.ThreadConfined; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.TskCoreException; @@ -51,7 +52,6 @@ public class WebHistoryDetailsPanel extends AbstractArtifactDetailsPanel impleme private final List programNameList = new ArrayList<>(); private final List domainList = new ArrayList<>(); private final List otherList = new ArrayList<>(); - private final List artifactAttributesList = new ArrayList<>(); private final GridBagConstraints gridBagConstraints = new GridBagConstraints(); private String dataSourceName; private String sourceFileName; @@ -59,10 +59,12 @@ public class WebHistoryDetailsPanel extends AbstractArtifactDetailsPanel impleme /** * Creates new form WebHistoryDetailsPanel. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) public WebHistoryDetailsPanel() { initComponents(); } + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override public void setArtifact(BlackboardArtifact artifact) { resetComponent(); @@ -86,12 +88,12 @@ public class WebHistoryDetailsPanel extends AbstractArtifactDetailsPanel impleme * * @throws TskCoreException */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) private void extractArtifactData(BlackboardArtifact artifact) throws TskCoreException { webHistoryArtifact = artifact; - artifactAttributesList.addAll(webHistoryArtifact.getAttributes()); // Get all the attributes and group them by the section panels they go in - for (BlackboardAttribute bba : artifactAttributesList) { + for (BlackboardAttribute bba : webHistoryArtifact.getAttributes()) { if (bba.getAttributeType().getTypeName().startsWith("TSK_URL")) { urlList.add(bba); } else if (bba.getAttributeType().getTypeName().startsWith("TSK_PROG_NAME")) { @@ -117,6 +119,7 @@ public class WebHistoryDetailsPanel extends AbstractArtifactDetailsPanel impleme /** * Reset the panel so that it is empty. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) private void resetComponent() { // clear the panel this.removeAll(); @@ -137,16 +140,16 @@ public class WebHistoryDetailsPanel extends AbstractArtifactDetailsPanel impleme programNameList.clear(); domainList.clear(); otherList.clear(); - artifactAttributesList.clear(); - } + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override public Component getComponent() { // Slap a vertical scrollbar on the panel. return new JScrollPane(this, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); } + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override public boolean isSupported(BlackboardArtifact artifact) { return (artifact != null) @@ -181,6 +184,7 @@ public class WebHistoryDetailsPanel extends AbstractArtifactDetailsPanel impleme /** * Update the view to reflect the current artifact's details. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) private void updateView() { CommunicationArtifactViewerHelper.addHeader(this, gridBagLayout, gridBagConstraints, Bundle.WebHistoryDetailsPanel_details_attrHeader()); From e2634a4535b1054835d6725bdd8224d5ee8ff8a5 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Thu, 5 Nov 2020 15:24:42 -0500 Subject: [PATCH 57/81] 6773 fix annotations --- .../sleuthkit/autopsy/discovery/ui/DiscoveryTopComponent.java | 2 ++ .../org/sleuthkit/autopsy/discovery/ui/OpenDiscoveryAction.java | 2 -- .../org/sleuthkit/autopsy/discovery/ui/VideoThumbnailPanel.java | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/DiscoveryTopComponent.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/DiscoveryTopComponent.java index 421a9bebe1..56892c55dd 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/DiscoveryTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/DiscoveryTopComponent.java @@ -135,6 +135,7 @@ public final class DiscoveryTopComponent extends TopComponent { groupListPanel.resetGroupList(); } + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override public void componentOpened() { super.componentOpened(); @@ -144,6 +145,7 @@ public final class DiscoveryTopComponent extends TopComponent { DiscoveryEventUtils.getDiscoveryEventBus().register(groupListPanel); } + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override protected void componentClosed() { DiscoveryDialog.getDiscoveryDialogInstance().cancelSearch(); diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/OpenDiscoveryAction.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/OpenDiscoveryAction.java index 26f18f8660..ec767c4c83 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/OpenDiscoveryAction.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/OpenDiscoveryAction.java @@ -52,7 +52,6 @@ public final class OpenDiscoveryAction extends CallableSystemAction implements P /** * Construct a new OpenDiscoveryAction. */ - @ThreadConfined(type = ThreadConfined.ThreadType.AWT) public OpenDiscoveryAction() { toolbarButton.addActionListener(OpenDiscoveryAction.this::actionPerformed); this.setEnabled(false); @@ -92,7 +91,6 @@ public final class OpenDiscoveryAction extends CallableSystemAction implements P * * @param value whether to enable this action or not */ - @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override public void setEnabled(boolean value) { super.setEnabled(value); diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/VideoThumbnailPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/VideoThumbnailPanel.java index 34e7293a7c..161e6a0770 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/VideoThumbnailPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/VideoThumbnailPanel.java @@ -235,6 +235,7 @@ final class VideoThumbnailPanel extends javax.swing.JPanel implements ListCellRe return Bundle.VideoThumbnailPanel_sizeLabel_text(size, units); } + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override public String getToolTipText(MouseEvent event) { if (event != null) { From d61550c76319254a66d0878cf4131ef42659048b Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Thu, 5 Nov 2020 15:45:52 -0500 Subject: [PATCH 58/81] 6774 fix merge conflict --- .../sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.java | 1 + 1 file changed, 1 insertion(+) diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.java index f3755802b3..295107ef78 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.java @@ -61,6 +61,7 @@ final class DomainArtifactsTabPanel extends JPanel { DomainArtifactsTabPanel(BlackboardArtifact.ARTIFACT_TYPE type) { initComponents(); this.artifactType = type; + listPanel = new ArtifactsListPanel(artifactType); jSplitPane1.setLeftComponent(listPanel); setRightComponent(); listPanel.addSelectionListener(listener); From 74d64056663efd4cfde89d86fe675c43ad98fe8a Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Thu, 5 Nov 2020 15:53:15 -0500 Subject: [PATCH 59/81] 6774 fix merge conflict --- .../org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java index ea08e6f887..adfc49d526 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java @@ -51,8 +51,8 @@ class ArtifactsListPanel extends JPanel { */ @ThreadConfined(type = ThreadConfined.ThreadType.AWT) ArtifactsListPanel(BlackboardArtifact.ARTIFACT_TYPE artifactType) { - initComponents(); tableModel = new DomainArtifactTableModel(artifactType); + initComponents(); jTable1.getRowSorter().toggleSortOrder(0); jTable1.getRowSorter().toggleSortOrder(0); } From 087d91d3f8ab5510d719f891fb5bb26d530728eb Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Thu, 5 Nov 2020 16:11:15 -0500 Subject: [PATCH 60/81] 6774 fix error resolving merge conflict --- .../discovery/ui/DiscoveryTopComponent.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/DiscoveryTopComponent.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/DiscoveryTopComponent.java index 5eda52a840..a99d5ae51b 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/DiscoveryTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/DiscoveryTopComponent.java @@ -327,6 +327,7 @@ public final class DiscoveryTopComponent extends TopComponent { if (!searchCompleteEvent.getFilters().isEmpty()) { descriptionText += Bundle.DiscoveryTopComponent_additionalFilters_text(); } + selectedDomainTabName = validateLastSelectedType(searchCompleteEvent); rightSplitPane.setBottomComponent(new DomainDetailsPanel(selectedDomainTabName)); } else { rightSplitPane.setBottomComponent(new FileDetailsPanel()); @@ -338,6 +339,30 @@ public final class DiscoveryTopComponent extends TopComponent { }); } + /** + * Get the name of the tab which was last selected unless the tab last + * selected would not be included in the types currently being displayed or + * was not previously set. + * + * @return The name of the tab which should be selected in the new + * DomainDetailsPanel. + */ + private String validateLastSelectedType(DiscoveryEventUtils.SearchCompleteEvent searchCompleteEvent) { + String typeFilteredOn = selectedDomainTabName; + for (AbstractFilter filter : searchCompleteEvent.getFilters()) { + if (filter instanceof ArtifactTypeFilter) { + for (ARTIFACT_TYPE type : ((ArtifactTypeFilter) filter).getTypes()) { + typeFilteredOn = type.getDisplayName(); + if (selectedDomainTabName == null || typeFilteredOn.equalsIgnoreCase(selectedDomainTabName)) { + break; + } + } + break; + } + } + return typeFilteredOn; + } + /** * Subscribe to the SearchCancelledEvent for updating the UI accordingly. * From 7038bd9f73d249a6b6c02d5d6245e798d069eb8f Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Thu, 5 Nov 2020 16:24:07 -0500 Subject: [PATCH 61/81] 6774 fix saving of perviously selected tab --- .../autopsy/discovery/search/SearchFiltering.java | 12 +++++------- .../autopsy/discovery/ui/ArtifactsListPanel.java | 1 + .../discovery/ui/ContentViewerDetailsPanel.java | 3 +++ .../autopsy/discovery/ui/DiscoveryTopComponent.java | 1 + 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/discovery/search/SearchFiltering.java b/Core/src/org/sleuthkit/autopsy/discovery/search/SearchFiltering.java index 2e10305f2a..f39bb56634 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/search/SearchFiltering.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/search/SearchFiltering.java @@ -33,6 +33,7 @@ import org.sleuthkit.datamodel.TagName; import org.sleuthkit.datamodel.TskCoreException; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.Date; import java.util.List; import java.util.Locale; @@ -218,15 +219,12 @@ public class SearchFiltering { } /** - * Get the first artifact type specified by the filter. + * Get the list of artifact types specified by the filter. * - * @return The first artifact type specified by the filter. + * @return The list of artifact types specified by the filter. */ - public ARTIFACT_TYPE getFirstType() { - if (!types.isEmpty()) { - return types.get(0); - } - return null; + public List getTypes() { + return Collections.unmodifiableList(types); } @Override diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java index adfc49d526..6235761d6e 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java @@ -270,6 +270,7 @@ class ArtifactsListPanel extends JPanel { * @throws TskCoreException When unable to get abstract files based on * the TSK_PATH_ID. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) private String getStringForColumn(BlackboardAttribute bba, int columnIndex) throws TskCoreException { if (columnIndex == 0 && bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID()) { return bba.getDisplayString(); diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/ContentViewerDetailsPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/ContentViewerDetailsPanel.java index 850dc26bd0..81e4fcaddc 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/ContentViewerDetailsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/ContentViewerDetailsPanel.java @@ -20,6 +20,7 @@ package org.sleuthkit.autopsy.discovery.ui; import org.openide.nodes.Node; import org.sleuthkit.autopsy.corecomponents.DataContentPanel; +import org.sleuthkit.autopsy.coreutils.ThreadConfined; import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode; import org.sleuthkit.datamodel.BlackboardArtifact; @@ -34,6 +35,7 @@ final class ContentViewerDetailsPanel extends AbstractArtifactDetailsPanel { /** * Creates new form ContentViewerDetailsPanel */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) ContentViewerDetailsPanel() { initComponents(); add(contentViewer); @@ -51,6 +53,7 @@ final class ContentViewerDetailsPanel extends AbstractArtifactDetailsPanel { setLayout(new java.awt.BorderLayout()); }// //GEN-END:initComponents + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override public void setArtifact(BlackboardArtifact artifact) { Node node = Node.EMPTY; diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/DiscoveryTopComponent.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/DiscoveryTopComponent.java index a99d5ae51b..371f329f00 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/DiscoveryTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/DiscoveryTopComponent.java @@ -347,6 +347,7 @@ public final class DiscoveryTopComponent extends TopComponent { * @return The name of the tab which should be selected in the new * DomainDetailsPanel. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) private String validateLastSelectedType(DiscoveryEventUtils.SearchCompleteEvent searchCompleteEvent) { String typeFilteredOn = selectedDomainTabName; for (AbstractFilter filter : searchCompleteEvent.getFilters()) { From 4af6490d1b2545ffce5d9e78316f15c97973bd3c Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Sun, 8 Nov 2020 16:08:46 -0500 Subject: [PATCH 62/81] update to use star notation --- Core/build.xml | 65 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) diff --git a/Core/build.xml b/Core/build.xml index e54c4eda97..3a2b99eb6d 100644 --- a/Core/build.xml +++ b/Core/build.xml @@ -197,7 +197,7 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + From a2496aac1e3f238e20b133fc23c331a19dc6cb20 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Mon, 9 Nov 2020 08:28:51 -0500 Subject: [PATCH 63/81] comment fix --- Core/build.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/build.xml b/Core/build.xml index 3a2b99eb6d..43715c6778 100644 --- a/Core/build.xml +++ b/Core/build.xml @@ -240,14 +240,14 @@ - From b08b161b53765b849c7b867eedaaaa0d06da0428 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Mon, 9 Nov 2020 10:56:23 -0500 Subject: [PATCH 64/81] start of timeline summary --- .../datamodel/TimelineSummary.java | 90 +++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TimelineSummary.java diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TimelineSummary.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TimelineSummary.java new file mode 100644 index 0000000000..e37eb6da95 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TimelineSummary.java @@ -0,0 +1,90 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2020 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.datasourcesummary.datamodel; + +import java.util.Date; +import java.util.List; +import static java.util.Locale.filter; +import org.joda.time.Interval; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; +import org.sleuthkit.datamodel.DataSource; +import org.sleuthkit.datamodel.TimelineEvent; +import org.sleuthkit.datamodel.TimelineManager; +import org.sleuthkit.datamodel.TskCoreException; + +/** + * Provides data source summary information pertaining to Timeline data. + */ +public class TimelineSummary { + + private final SleuthkitCaseProvider provider; + + /** + * Default constructor. + */ + public TimelineSummary() { + this(SleuthkitCaseProvider.DEFAULT); + } + + /** + * Construct object with given SleuthkitCaseProvider + * + * @param provider SleuthkitCaseProvider provider, cannot be null. + */ + public TimelineSummary(SleuthkitCaseProvider provider) { + this.provider = provider; + } + + private Date getDateOrNull(Long secsFromEpoch) { + if (secsFromEpoch == null || secsFromEpoch == 0) { + return null; + } + + return new Date(secsFromEpoch * 1000); + } + + + + + private void getData(DataSource dataSource) throws SleuthkitCaseProviderException, TskCoreException { + TimelineManager timelineManager = this.provider.get().getTimelineManager(); + + + + List events = timelineManager.getEvents(new Interval(0, System.currentTimeMillis()), new RootTimelineFilter); + } + + + + public static class TimelineSummaryData { + private final DataSource dataSource; + private final Date minDate; + private final Date maxDate; + private final List histogramActivity; + + + } + + + + public static class DailyActivityAmount { + private final Date day; + private final long magnitude; + } +} From d0aa58569ccf8866c9f1d8b414a4b887ec1a724f Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Mon, 9 Nov 2020 13:38:05 -0500 Subject: [PATCH 65/81] timeline panel beginnings --- .../datamodel/TimelineSummary.java | 188 ++++++++++++--- .../datasourcesummary/ui/Bundle.properties | 2 + .../datasourcesummary/ui/TimelinePanel.form | 219 ++++++++++++++++++ .../datasourcesummary/ui/TimelinePanel.java | 174 ++++++++++++++ 4 files changed, 557 insertions(+), 26 deletions(-) create mode 100644 Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.form create mode 100644 Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.java diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TimelineSummary.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TimelineSummary.java index e37eb6da95..33ea5194f7 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TimelineSummary.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TimelineSummary.java @@ -18,21 +18,47 @@ */ package org.sleuthkit.autopsy.datasourcesummary.datamodel; +import java.util.Arrays; +import java.util.Collections; import java.util.Date; +import java.util.HashSet; import java.util.List; -import static java.util.Locale.filter; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; +import org.apache.commons.lang3.tuple.Pair; import org.joda.time.Interval; import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; +import org.sleuthkit.autopsy.datasourcesummary.uiutils.DefaultUpdateGovernor; +import org.sleuthkit.autopsy.ingest.IngestManager; +import org.sleuthkit.autopsy.ingest.ModuleContentEvent; +import org.sleuthkit.autopsy.timeline.utils.FilterUtils; +import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.DataSource; import org.sleuthkit.datamodel.TimelineEvent; +import org.sleuthkit.datamodel.TimelineEventType; +import org.sleuthkit.datamodel.TimelineFilter; +import org.sleuthkit.datamodel.TimelineFilter.DataSourcesFilter; +import org.sleuthkit.datamodel.TimelineFilter.EventTypeFilter; +import org.sleuthkit.datamodel.TimelineFilter.HashHitsFilter; +import org.sleuthkit.datamodel.TimelineFilter.HideKnownFilter; +import org.sleuthkit.datamodel.TimelineFilter.RootFilter; +import org.sleuthkit.datamodel.TimelineFilter.TagsFilter; +import org.sleuthkit.datamodel.TimelineFilter.TextFilter; import org.sleuthkit.datamodel.TimelineManager; import org.sleuthkit.datamodel.TskCoreException; /** * Provides data source summary information pertaining to Timeline data. */ -public class TimelineSummary { +public class TimelineSummary implements DefaultUpdateGovernor { + private static final long DAY_SECS = 24 * 60 * 60; + + + private static final Set INGEST_JOB_EVENTS = new HashSet<>( + Arrays.asList(IngestManager.IngestJobEvent.COMPLETED, IngestManager.IngestJobEvent.CANCELLED)); + private final SleuthkitCaseProvider provider; /** @@ -50,41 +76,151 @@ public class TimelineSummary { public TimelineSummary(SleuthkitCaseProvider provider) { this.provider = provider; } + - private Date getDateOrNull(Long secsFromEpoch) { - if (secsFromEpoch == null || secsFromEpoch == 0) { - return null; - } - - return new Date(secsFromEpoch * 1000); + @Override + public boolean isRefreshRequired(ModuleContentEvent evt) { + return true; } - - - - - private void getData(DataSource dataSource) throws SleuthkitCaseProviderException, TskCoreException { - TimelineManager timelineManager = this.provider.get().getTimelineManager(); - - - - List events = timelineManager.getEvents(new Interval(0, System.currentTimeMillis()), new RootTimelineFilter); + + @Override + public boolean isRefreshRequired(AbstractFile file) { + return true; + } + + @Override + public boolean isRefreshRequired(IngestManager.IngestJobEvent evt) { + return (evt != null && INGEST_JOB_EVENTS.contains(evt)); + } + + @Override + public Set getIngestJobEventUpdates() { + return INGEST_JOB_EVENTS; } - + + private static Long getMinOrNull(Long first, Long second) { + if (first == null) { + return second; + } else if (second == null) { + return first; + } else { + return Math.min(first, second); + } + } + + private static Long getMaxOrNull(Long first, Long second) { + if (first == null) { + return second; + } else if (second == null) { + return first; + } else { + return Math.max(first, second); + } + } + + public TimelineSummaryData getData(DataSource dataSource) throws SleuthkitCaseProviderException, TskCoreException { + TimelineManager timelineManager = this.provider.get().getTimelineManager(); + + DataSourcesFilter dataSourceFilter = new DataSourcesFilter(); + dataSourceFilter.addSubFilter(new TimelineFilter.DataSourceFilter(dataSource.getName(), dataSource.getId())); + + // TODO check that this isn't filtering more than it should + RootFilter dataSourceRootFilter = new RootFilter( + new HideKnownFilter(), + new TagsFilter(), + new HashHitsFilter(), + new TextFilter(), + new EventTypeFilter(TimelineEventType.ROOT_EVENT_TYPE), + new DataSourcesFilter(), + FilterUtils.createDefaultFileTypesFilter(), + Collections.emptySet()); + + // get events for data source + long curRunTime = System.currentTimeMillis(); + List events = timelineManager.getEvents(new Interval(0, curRunTime), dataSourceRootFilter); + + // get counts of events per day + Map dateCounts = events.stream().collect(Collectors.toMap( + (evt) -> evt.getTime() / DAY_SECS, + (evt) -> 1, + (count1, count2) -> count1 + count2)); + + // get minimum and maximum usage date + Pair minMax = dateCounts.keySet().stream().reduce( + Pair.of((Long) null, (Long) null), + (curMinMax, thisDay) -> Pair.of(getMinOrNull(curMinMax.getLeft(), thisDay), getMaxOrNull(curMinMax.getRight(), thisDay)), + (minMax1, minMax2) -> Pair.of(getMinOrNull(minMax1.getLeft(), minMax2.getLeft()), getMaxOrNull(minMax1.getRight(), minMax2.getRight()))); + + Long minDay = minMax.getLeft(); + Long maxDay = minMax.getRight(); + + // if no min date or max date, no usage; return null. + if (minDay == null || maxDay == null) { + return null; + } + + Date minDate = new Date(minDay * 1000); + Date maxDate = new Date(maxDay * 1000); + + List mostRecentActivityAmt = dateCounts.entrySet().stream() + // reverse sort to get latest activity + .sorted((e1, e2) -> -Long.compare(e1.getKey(), e2.getKey())) + // get last 30 days + .limit(30) + // convert to object to return + .map(entry -> new DailyActivityAmount(new Date(entry.getKey() * 1000), entry.getValue())) + // create list + .collect(Collectors.toList()); + + // get in ascending order + Collections.reverse(mostRecentActivityAmt); + + return new TimelineSummaryData(minDate, maxDate, mostRecentActivityAmt); + } + public static class TimelineSummaryData { - private final DataSource dataSource; + private final Date minDate; private final Date maxDate; private final List histogramActivity; - - + + TimelineSummaryData(Date minDate, Date maxDate, List histogramActivity) { + this.minDate = minDate; + this.maxDate = maxDate; + this.histogramActivity = (histogramActivity == null) ? Collections.emptyList() : Collections.unmodifiableList(histogramActivity); + } + + public Date getMinDate() { + return minDate; + } + + public Date getMaxDate() { + return maxDate; + } + + public List getHistogramActivity() { + return histogramActivity; + } } - - - + public static class DailyActivityAmount { + private final Date day; - private final long magnitude; + private final int magnitude; + + DailyActivityAmount(Date day, int magnitude) { + this.day = day; + this.magnitude = magnitude; + } + + public Date getDay() { + return day; + } + + public int getMagnitude() { + return magnitude; + } } } diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties index 94b497d2ff..25a9a71f5b 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties @@ -42,3 +42,5 @@ RecentFilesPanel.attachmentLabel.text=Recent Attachments PastCasesPanel.notableFileLabel.text=Cases with Common Items That Were Tagged as Notable PastCasesPanel.sameIdLabel.text=Past Cases with the Same Device IDs DataSourceSummaryTabbedPane.noDataSourceLabel.text=No data source has been selected. +TimelinePanel.sameIdLabel.text=Past Cases with the Same Device IDs +TimelinePanel.notableFileLabel.text=Cases with Common Items That Were Tagged as Notable diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.form b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.form new file mode 100644 index 0000000000..1da8e1af7a --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.form @@ -0,0 +1,219 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.java new file mode 100644 index 0000000000..148b6653e2 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.java @@ -0,0 +1,174 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2020 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.datasourcesummary.ui; + +import java.util.Arrays; +import java.util.List; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.TimelineSummary; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.TimelineSummary.TimelineSummaryData; +import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchResult; +import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker; +import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker.DataFetchComponents; +import org.sleuthkit.autopsy.datasourcesummary.uiutils.IngestRunningLabel; +import org.sleuthkit.autopsy.datasourcesummary.uiutils.JTablePanel; +import org.sleuthkit.datamodel.DataSource; + +/** + * A tab shown in data source summary displaying information about a datasource + * and how it pertains to other cases. + */ +public class TimelinePanel extends BaseDataSourceSummaryPanel { + + private static final long serialVersionUID = 1L; + + + private final List> tables = Arrays.asList( + ); + + private final List> dataFetchComponents; + + private final IngestRunningLabel ingestRunningLabel = new IngestRunningLabel(); + + public TimelinePanel() { + this(new TimelineSummary()); + } + + /** + * Creates new form PastCasesPanel + */ + public TimelinePanel(TimelineSummary timelineData) { + // set up data acquisition methods + dataFetchComponents = Arrays.asList( + new DataFetchWorker.DataFetchComponents<>( + (dataSource) -> timelineData.getData(dataSource), + (result) -> handleResult(result)) + ); + + initComponents(); + } + + /** + * Handles displaying the result for each table by breaking apart subdata + * items into seperate results for each table. + * + * @param result The result. + */ + private void handleResult(DataFetchResult result) { + if (result == null) { + // TODO + } else { + // TODO + } + } + + @Override + protected void fetchInformation(DataSource dataSource) { + fetchInformation(dataFetchComponents, dataSource); + } + + @Override + protected void onNewDataSource(DataSource dataSource) { + onNewDataSource(dataFetchComponents, tables, dataSource); + } + + @Override + public void close() { + ingestRunningLabel.unregister(); + super.close(); + } + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + javax.swing.JScrollPane mainScrollPane = new javax.swing.JScrollPane(); + javax.swing.JPanel mainContentPanel = new javax.swing.JPanel(); + javax.swing.JPanel ingestRunningPanel = ingestRunningLabel; + javax.swing.JLabel notableFileLabel = new javax.swing.JLabel(); + javax.swing.Box.Filler filler1 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 2), new java.awt.Dimension(0, 2), new java.awt.Dimension(0, 2)); + javax.swing.JPanel notableFilePanel = notableFileTable; + javax.swing.Box.Filler filler2 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 20), new java.awt.Dimension(0, 20), new java.awt.Dimension(0, 20)); + javax.swing.JLabel sameIdLabel = new javax.swing.JLabel(); + javax.swing.Box.Filler filler3 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 2), new java.awt.Dimension(0, 2), new java.awt.Dimension(0, 2)); + javax.swing.JPanel sameIdPanel = sameIdTable; + javax.swing.Box.Filler filler5 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 32767)); + + mainContentPanel.setBorder(javax.swing.BorderFactory.createEmptyBorder(10, 10, 10, 10)); + mainContentPanel.setLayout(new javax.swing.BoxLayout(mainContentPanel, javax.swing.BoxLayout.PAGE_AXIS)); + + ingestRunningPanel.setAlignmentX(0.0F); + ingestRunningPanel.setMaximumSize(new java.awt.Dimension(32767, 25)); + ingestRunningPanel.setMinimumSize(new java.awt.Dimension(10, 25)); + ingestRunningPanel.setPreferredSize(new java.awt.Dimension(10, 25)); + mainContentPanel.add(ingestRunningPanel); + + org.openide.awt.Mnemonics.setLocalizedText(notableFileLabel, org.openide.util.NbBundle.getMessage(TimelinePanel.class, "TimelinePanel.notableFileLabel.text")); // NOI18N + mainContentPanel.add(notableFileLabel); + notableFileLabel.getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getMessage(TimelinePanel.class, "PastCasesPanel.notableFileLabel.text")); // NOI18N + + filler1.setAlignmentX(0.0F); + mainContentPanel.add(filler1); + + notableFilePanel.setAlignmentX(0.0F); + notableFilePanel.setMaximumSize(new java.awt.Dimension(32767, 106)); + notableFilePanel.setMinimumSize(new java.awt.Dimension(100, 106)); + notableFilePanel.setPreferredSize(new java.awt.Dimension(100, 106)); + mainContentPanel.add(notableFilePanel); + + filler2.setAlignmentX(0.0F); + mainContentPanel.add(filler2); + + org.openide.awt.Mnemonics.setLocalizedText(sameIdLabel, org.openide.util.NbBundle.getMessage(TimelinePanel.class, "TimelinePanel.sameIdLabel.text")); // NOI18N + mainContentPanel.add(sameIdLabel); + + filler3.setAlignmentX(0.0F); + mainContentPanel.add(filler3); + + sameIdPanel.setAlignmentX(0.0F); + sameIdPanel.setMaximumSize(new java.awt.Dimension(32767, 106)); + sameIdPanel.setMinimumSize(new java.awt.Dimension(100, 106)); + sameIdPanel.setPreferredSize(new java.awt.Dimension(100, 106)); + mainContentPanel.add(sameIdPanel); + + filler5.setAlignmentX(0.0F); + mainContentPanel.add(filler5); + + mainScrollPane.setViewportView(mainContentPanel); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(mainScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 400, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(mainScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 300, Short.MAX_VALUE) + ); + }// //GEN-END:initComponents + + + // Variables declaration - do not modify//GEN-BEGIN:variables + // End of variables declaration//GEN-END:variables +} From ea7c03aa1dd8a2cbeaa9542a0efa781796c4b220 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Mon, 9 Nov 2020 15:20:10 -0500 Subject: [PATCH 66/81] working through panel --- .../datamodel/TimelineSummary.java | 37 +++- .../datasourcesummary/ui/Bundle.properties | 2 +- .../datasourcesummary/ui/TimelinePanel.form | 4 +- .../datasourcesummary/ui/TimelinePanel.java | 30 ++- .../datasourcesummary/ui/TypesPanel.java | 41 +--- .../uiutils/BarChartPanel.java | 195 ++++++++++++++++++ .../uiutils/ChartMessageOverlay.java | 63 ++++++ .../uiutils/LoadableLabel.java | 63 ++++++ .../uiutils/PieChartPanel.java | 42 +--- 9 files changed, 372 insertions(+), 105 deletions(-) create mode 100644 Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/BarChartPanel.java create mode 100644 Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/ChartMessageOverlay.java create mode 100644 Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/LoadableLabel.java diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TimelineSummary.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TimelineSummary.java index 33ea5194f7..a5981de6ac 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TimelineSummary.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TimelineSummary.java @@ -18,6 +18,7 @@ */ package org.sleuthkit.autopsy.datasourcesummary.datamodel; +import com.google.common.collect.Sets; import java.util.Arrays; import java.util.Collections; import java.util.Date; @@ -59,6 +60,14 @@ public class TimelineSummary implements DefaultUpdateGovernor { Arrays.asList(IngestManager.IngestJobEvent.COMPLETED, IngestManager.IngestJobEvent.CANCELLED)); + private static final Set FILE_SYSTEM_EVENTS = + new HashSet<>(Arrays.asList( + TimelineEventType.FILE_MODIFIED, + TimelineEventType.FILE_ACCESSED, + TimelineEventType.FILE_CREATED, + TimelineEventType.FILE_CHANGED)); + + private final SleuthkitCaseProvider provider; /** @@ -141,11 +150,11 @@ public class TimelineSummary implements DefaultUpdateGovernor { long curRunTime = System.currentTimeMillis(); List events = timelineManager.getEvents(new Interval(0, curRunTime), dataSourceRootFilter); - // get counts of events per day - Map dateCounts = events.stream().collect(Collectors.toMap( + // get counts of events per day (left is file system events, right is everything else) + Map> dateCounts = events.stream().collect(Collectors.toMap( (evt) -> evt.getTime() / DAY_SECS, - (evt) -> 1, - (count1, count2) -> count1 + count2)); + (evt) -> FILE_SYSTEM_EVENTS.contains(evt.getEventType()) ? Pair.of(1, 0) : Pair.of(0, 1), + (count1, count2) -> Pair.of(count1.getLeft() + count2.getLeft(), count1.getRight() + count2.getRight()))); // get minimum and maximum usage date Pair minMax = dateCounts.keySet().stream().reduce( @@ -170,7 +179,7 @@ public class TimelineSummary implements DefaultUpdateGovernor { // get last 30 days .limit(30) // convert to object to return - .map(entry -> new DailyActivityAmount(new Date(entry.getKey() * 1000), entry.getValue())) + .map(entry -> new DailyActivityAmount(new Date(entry.getKey() * 1000), entry.getValue().getLeft(), entry.getValue().getRight())) // create list .collect(Collectors.toList()); @@ -208,19 +217,27 @@ public class TimelineSummary implements DefaultUpdateGovernor { public static class DailyActivityAmount { private final Date day; - private final int magnitude; + private final int fileActivityCount; + private final int artifactActivityCount; - DailyActivityAmount(Date day, int magnitude) { + public DailyActivityAmount(Date day, int fileActivityCount, int artifactActivityCount) { this.day = day; - this.magnitude = magnitude; + this.fileActivityCount = fileActivityCount; + this.artifactActivityCount = artifactActivityCount; } public Date getDay() { return day; } - public int getMagnitude() { - return magnitude; + public int getFileActivityCount() { + return fileActivityCount; } + + public int getArtifactActivityCount() { + return artifactActivityCount; + } + + } } diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties index 25a9a71f5b..33292cab98 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties @@ -43,4 +43,4 @@ PastCasesPanel.notableFileLabel.text=Cases with Common Items That Were Tagged as PastCasesPanel.sameIdLabel.text=Past Cases with the Same Device IDs DataSourceSummaryTabbedPane.noDataSourceLabel.text=No data source has been selected. TimelinePanel.sameIdLabel.text=Past Cases with the Same Device IDs -TimelinePanel.notableFileLabel.text=Cases with Common Items That Were Tagged as Notable +TimelinePanel.activityRangeLabel.text=Activity Range: diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.form b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.form index 1da8e1af7a..6b68566967 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.form +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.form @@ -72,10 +72,10 @@ - + - + diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.java index 148b6653e2..b88954c317 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.java @@ -20,29 +20,37 @@ package org.sleuthkit.autopsy.datasourcesummary.ui; import java.util.Arrays; import java.util.List; +import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.datasourcesummary.datamodel.TimelineSummary; import org.sleuthkit.autopsy.datasourcesummary.datamodel.TimelineSummary.TimelineSummaryData; +import org.sleuthkit.autopsy.datasourcesummary.uiutils.BarChartPanel; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchResult; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker.DataFetchComponents; import org.sleuthkit.autopsy.datasourcesummary.uiutils.IngestRunningLabel; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.JTablePanel; +import org.sleuthkit.autopsy.datasourcesummary.uiutils.LoadableComponent; +import org.sleuthkit.autopsy.datasourcesummary.uiutils.LoadableLabel; import org.sleuthkit.datamodel.DataSource; /** * A tab shown in data source summary displaying information about a datasource * and how it pertains to other cases. */ +@Messages({ + "TimelinePanel_earliestLabel_title=Earliest", + "TimelinePanel_latestLabel_title=Latest", + "TimlinePanel_last30DaysChart_title=Last 30 Days" +}) public class TimelinePanel extends BaseDataSourceSummaryPanel { private static final long serialVersionUID = 1L; - - private final List> tables = Arrays.asList( - ); - + private final LoadableLabel earliestLabel = new LoadableLabel(Bundle.TimelinePanel_earliestLabel_title()); + private final LoadableLabel latestLabel = new LoadableLabel(Bundle.TimelinePanel_latestLabel_title()); + private final BarChartPanel last30DaysChart = new BarChartPanel(Bundle.TimlinePanel_last30DaysChart_title(), "", ""); + + private final List> loadableComponents = Arrays.asList(earliestLabel, latestLabel, last30DaysChart); private final List> dataFetchComponents; - private final IngestRunningLabel ingestRunningLabel = new IngestRunningLabel(); public TimelinePanel() { @@ -84,7 +92,7 @@ public class TimelinePanel extends BaseDataSourceSummaryPanel { @Override protected void onNewDataSource(DataSource dataSource) { - onNewDataSource(dataFetchComponents, tables, dataSource); + onNewDataSource(dataFetchComponents, loadableComponents, dataSource); } @Override @@ -105,7 +113,7 @@ public class TimelinePanel extends BaseDataSourceSummaryPanel { javax.swing.JScrollPane mainScrollPane = new javax.swing.JScrollPane(); javax.swing.JPanel mainContentPanel = new javax.swing.JPanel(); javax.swing.JPanel ingestRunningPanel = ingestRunningLabel; - javax.swing.JLabel notableFileLabel = new javax.swing.JLabel(); + javax.swing.JLabel activityRangeLabel = new javax.swing.JLabel(); javax.swing.Box.Filler filler1 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 2), new java.awt.Dimension(0, 2), new java.awt.Dimension(0, 2)); javax.swing.JPanel notableFilePanel = notableFileTable; javax.swing.Box.Filler filler2 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 20), new java.awt.Dimension(0, 20), new java.awt.Dimension(0, 20)); @@ -123,9 +131,9 @@ public class TimelinePanel extends BaseDataSourceSummaryPanel { ingestRunningPanel.setPreferredSize(new java.awt.Dimension(10, 25)); mainContentPanel.add(ingestRunningPanel); - org.openide.awt.Mnemonics.setLocalizedText(notableFileLabel, org.openide.util.NbBundle.getMessage(TimelinePanel.class, "TimelinePanel.notableFileLabel.text")); // NOI18N - mainContentPanel.add(notableFileLabel); - notableFileLabel.getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getMessage(TimelinePanel.class, "PastCasesPanel.notableFileLabel.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(activityRangeLabel, org.openide.util.NbBundle.getMessage(TimelinePanel.class, "TimelinePanel.activityRangeLabel.text")); // NOI18N + mainContentPanel.add(activityRangeLabel); + activityRangeLabel.getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getMessage(TimelinePanel.class, "PastCasesPanel.notableFileLabel.text")); // NOI18N filler1.setAlignmentX(0.0F); mainContentPanel.add(filler1); diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TypesPanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TypesPanel.java index 448bf6bbea..509cd9257d 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TypesPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TypesPanel.java @@ -47,6 +47,7 @@ import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker.DataFetchComponents; import org.sleuthkit.autopsy.datasourcesummary.uiutils.IngestRunningLabel; import org.sleuthkit.autopsy.datasourcesummary.uiutils.LoadableComponent; +import org.sleuthkit.autopsy.datasourcesummary.uiutils.LoadableLabel; import org.sleuthkit.autopsy.datasourcesummary.uiutils.PieChartPanel; import org.sleuthkit.autopsy.datasourcesummary.uiutils.PieChartPanel.PieChartItem; import org.sleuthkit.autopsy.modules.filetypeid.FileTypeIdModuleFactory; @@ -78,46 +79,6 @@ import org.sleuthkit.datamodel.TskCoreException; "TypesPanel_sizeLabel_title=Size"}) class TypesPanel extends BaseDataSourceSummaryPanel { - /** - * A label that allows for displaying loading messages and can be used with - * a DataFetchResult. Text displays as ":". - */ - private static class LoadableLabel extends AbstractLoadableComponent { - - private static final long serialVersionUID = 1L; - - private final JLabel label = new JLabel(); - private final String key; - - /** - * Main constructor for the label. - * - * @param key The key to be displayed. - */ - LoadableLabel(String key) { - this.key = key; - setLayout(new BorderLayout()); - add(label, BorderLayout.CENTER); - this.showResults(null); - } - - private void setValue(String value) { - String formattedKey = StringUtils.isBlank(key) ? "" : key; - String formattedValue = StringUtils.isBlank(value) ? "" : value; - label.setText(String.format("%s: %s", formattedKey, formattedValue)); - } - - @Override - protected void setMessage(boolean visible, String message) { - setValue(message); - } - - @Override - protected void setResults(String data) { - setValue(data); - } - } - /** * Data for types pie chart. */ diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/BarChartPanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/BarChartPanel.java new file mode 100644 index 0000000000..d9a29efa6b --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/BarChartPanel.java @@ -0,0 +1,195 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2019 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.datasourcesummary.uiutils; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Font; +import java.util.Collections; +import java.util.List; +import javax.swing.JLabel; +import org.jfree.chart.ChartFactory; +import org.jfree.chart.ChartPanel; +import org.jfree.chart.JFreeChart; +import org.jfree.chart.plot.PiePlot; +import org.jfree.chart.plot.PlotOrientation; +import org.jfree.data.category.DefaultCategoryDataset; + +/** + * A bar chart panel. + */ +public class BarChartPanel extends AbstractLoadableComponent { + + public static class BarChartSeries { + + private final Color color; + private final List items; + + public BarChartSeries(Color color, List items) { + this.color = color; + this.items = (items == null) ? Collections.emptyList() : Collections.unmodifiableList(items); + } + + public Color getColor() { + return color; + } + + public List getItems() { + return items; + } + } + + /** + * An individual pie chart slice in the pie chart. + */ + public static class BarChartItem { + + private final String label; + private final double value; + + /** + * Main constructor. + * + * @param label The label for this bar. + * @param value The value for this item. + * @param color The color for the bar. Can be null for auto-determined. + */ + public BarChartItem(String label, double value) { + this.label = label; + this.value = value; + } + + /** + * @return The label for this item. + */ + public String getLabel() { + return label; + } + + /** + * @return The value for this item. + */ + public double getValue() { + return value; + } + } + + private static final long serialVersionUID = 1L; + + private static final Font DEFAULT_FONT = new JLabel().getFont(); + private static final Font DEFAULT_HEADER_FONT = new Font(DEFAULT_FONT.getName(), DEFAULT_FONT.getStyle(), (int) (DEFAULT_FONT.getSize() * 1.5)); + + private final ChartMessageOverlay overlay = new ChartMessageOverlay(); + private final DefaultCategoryDataset dataset = new DefaultCategoryDataset(); + private final JFreeChart chart; + private final PiePlot plot; + + /** + * Main constructor. + */ + public BarChartPanel() { + this(null, null, null); + } + + /** + * Main constructor for the pie chart. + * + * @param title The title for this pie chart. + */ + public BarChartPanel(String title, String categoryLabel, String valueLabel) { + this.chart = ChartFactory.createBarChart( + title, + categoryLabel, + valueLabel, + dataset, + PlotOrientation.VERTICAL, + false, false, false); + + chart.setBackgroundPaint(null); + chart.getTitle().setFont(DEFAULT_HEADER_FONT); + + this.plot = ((PiePlot) chart.getPlot()); + plot.setLabelFont(DEFAULT_FONT); + plot.setBackgroundPaint(null); + plot.setOutlinePaint(null); + + // Create Panel + ChartPanel panel = new ChartPanel(chart); + panel.addOverlay(overlay); + panel.setPopupMenu(null); + + this.setLayout(new BorderLayout()); + this.add(panel, BorderLayout.CENTER); + } + + /** + * @return The title for this chart if one exists. + */ + public String getTitle() { + return (this.chart == null || this.chart.getTitle() == null) + ? null + : this.chart.getTitle().getText(); + } + + /** + * Sets the title for this pie chart. + * + * @param title The title. + * + * @return As a utility, returns this. + */ + public BarChartPanel setTitle(String title) { + this.chart.getTitle().setText(title); + return this; + } + + @Override + protected void setMessage(boolean visible, String message) { + this.overlay.setVisible(visible); + this.overlay.setMessage(message); + } + + // only one category for now. + private static final String DEFAULT_CATEGORY = ""; + + @Override + protected void setResults(BarChartPanel.BarChartSeries data) { + this.dataset.clear(); + this.plot.clearSectionPaints(false); + + if (data != null && data.getItems() != null && !data.getItems().isEmpty()) { + this.plot.setSectionPaint(DEFAULT_CATEGORY, data.getColor()); + for (BarChartPanel.BarChartItem bar : data.getItems()) { + this.dataset.setValue(bar.getValue(), DEFAULT_CATEGORY, bar.getLabel()); + } + } + } + + /** + * Shows a message on top of data. + * + * @param data The data. + * @param message The message. + */ + public synchronized void showDataWithMessage(BarChartPanel.BarChartSeries data, String message) { + setResults(data); + setMessage(true, message); + repaint(); + } +} diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/ChartMessageOverlay.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/ChartMessageOverlay.java new file mode 100644 index 0000000000..2e21dfb796 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/ChartMessageOverlay.java @@ -0,0 +1,63 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2020 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.datasourcesummary.uiutils; + +import java.awt.Graphics2D; +import org.jfree.chart.ChartPanel; +import org.jfree.chart.panel.AbstractOverlay; +import org.jfree.chart.panel.Overlay; + +/** + * A JFreeChart message overlay that can show a message for the purposes of the + * LoadableComponent. + */ +class ChartMessageOverlay extends AbstractOverlay implements Overlay { + + private static final long serialVersionUID = 1L; + private final BaseMessageOverlay overlay = new BaseMessageOverlay(); + + // multiply this value by the smaller dimension (height or width) of the component + // to determine width of text to be displayed. + private static final double MESSAGE_WIDTH_FACTOR = .6; + + /** + * Sets this layer visible when painted. In order to be shown in UI, this + * component needs to be repainted. + * + * @param visible Whether or not it is visible. + */ + void setVisible(boolean visible) { + overlay.setVisible(visible); + } + + /** + * Sets the message to be displayed in the child jlabel. + * + * @param message The message to be displayed. + */ + void setMessage(String message) { + overlay.setMessage(message); + } + + @Override + public void paintOverlay(Graphics2D gd, ChartPanel cp) { + int labelWidth = (int) (Math.min(cp.getWidth(), cp.getHeight()) * MESSAGE_WIDTH_FACTOR); + overlay.paintOverlay(gd, cp.getWidth(), cp.getHeight(), labelWidth); + } +} diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/LoadableLabel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/LoadableLabel.java new file mode 100644 index 0000000000..3fdf81ad18 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/LoadableLabel.java @@ -0,0 +1,63 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2020 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.datasourcesummary.uiutils; + +import java.awt.BorderLayout; +import javax.swing.JLabel; +import org.apache.commons.lang3.StringUtils; + +/** + * A label that allows for displaying loading messages and can be used with a + * DataFetchResult. Text displays as ":". + */ +public class LoadableLabel extends AbstractLoadableComponent { + + private static final long serialVersionUID = 1L; + + private final JLabel label = new JLabel(); + private final String key; + + /** + * Main constructor for the label. + * + * @param key The key to be displayed. + */ + public LoadableLabel(String key) { + this.key = key; + setLayout(new BorderLayout()); + add(label, BorderLayout.CENTER); + this.showResults(null); + } + + private void setValue(String value) { + String formattedKey = StringUtils.isBlank(key) ? "" : key; + String formattedValue = StringUtils.isBlank(value) ? "" : value; + label.setText(String.format("%s: %s", formattedKey, formattedValue)); + } + + @Override + protected void setMessage(boolean visible, String message) { + setValue(message); + } + + @Override + protected void setResults(String data) { + setValue(data); + } +} diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/PieChartPanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/PieChartPanel.java index 971cb83367..7f9a1e218b 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/PieChartPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/PieChartPanel.java @@ -89,46 +89,6 @@ public class PieChartPanel extends AbstractLoadableComponent Date: Tue, 10 Nov 2020 07:59:46 -0500 Subject: [PATCH 67/81] added timeline panel --- .../datamodel/TimelineSummary.java | 7 +- .../datasourcesummary/ui/Bundle.properties | 3 +- .../ui/DataSourceSummaryTabbedPane.java | 4 +- .../datasourcesummary/ui/PastCasesPanel.java | 29 +------ .../datasourcesummary/ui/TimelinePanel.form | 73 ++++++++-------- .../datasourcesummary/ui/TimelinePanel.java | 86 ++++++++++++++----- .../uiutils/DataFetchResult.java | 30 ++++++- 7 files changed, 134 insertions(+), 98 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TimelineSummary.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TimelineSummary.java index a5981de6ac..af056387dd 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TimelineSummary.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TimelineSummary.java @@ -18,7 +18,6 @@ */ package org.sleuthkit.autopsy.datasourcesummary.datamodel; -import com.google.common.collect.Sets; import java.util.Arrays; import java.util.Collections; import java.util.Date; @@ -195,10 +194,10 @@ public class TimelineSummary implements DefaultUpdateGovernor { private final Date maxDate; private final List histogramActivity; - TimelineSummaryData(Date minDate, Date maxDate, List histogramActivity) { + TimelineSummaryData(Date minDate, Date maxDate, List recentDaysActivity) { this.minDate = minDate; this.maxDate = maxDate; - this.histogramActivity = (histogramActivity == null) ? Collections.emptyList() : Collections.unmodifiableList(histogramActivity); + this.histogramActivity = (recentDaysActivity == null) ? Collections.emptyList() : Collections.unmodifiableList(recentDaysActivity); } public Date getMinDate() { @@ -209,7 +208,7 @@ public class TimelineSummary implements DefaultUpdateGovernor { return maxDate; } - public List getHistogramActivity() { + public List getMostRecentDaysActivity() { return histogramActivity; } } diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties index 33292cab98..5d9e6adf0c 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties @@ -42,5 +42,4 @@ RecentFilesPanel.attachmentLabel.text=Recent Attachments PastCasesPanel.notableFileLabel.text=Cases with Common Items That Were Tagged as Notable PastCasesPanel.sameIdLabel.text=Past Cases with the Same Device IDs DataSourceSummaryTabbedPane.noDataSourceLabel.text=No data source has been selected. -TimelinePanel.sameIdLabel.text=Past Cases with the Same Device IDs -TimelinePanel.activityRangeLabel.text=Activity Range: +TimelinePanel.activityRangeLabel.text=Activity Range diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceSummaryTabbedPane.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceSummaryTabbedPane.java index 55320f7dbb..f758f9716f 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceSummaryTabbedPane.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceSummaryTabbedPane.java @@ -38,7 +38,8 @@ import org.sleuthkit.datamodel.DataSource; "DataSourceSummaryTabbedPane_ingestHistoryTab_title=Ingest History", "DataSourceSummaryTabbedPane_recentFileTab_title=Recent Files", "DataSourceSummaryTabbedPane_pastCasesTab_title=Past Cases", - "DataSourceSummaryTabbedPane_analysisTab_title=Analysis" + "DataSourceSummaryTabbedPane_analysisTab_title=Analysis", + "DataSourceSummaryTabbedPane_timelineTab_title=Timeline" }) public class DataSourceSummaryTabbedPane extends javax.swing.JPanel { @@ -123,6 +124,7 @@ public class DataSourceSummaryTabbedPane extends javax.swing.JPanel { new DataSourceTab(Bundle.DataSourceSummaryTabbedPane_analysisTab_title(), new AnalysisPanel()), new DataSourceTab(Bundle.DataSourceSummaryTabbedPane_recentFileTab_title(), new RecentFilesPanel()), new DataSourceTab(Bundle.DataSourceSummaryTabbedPane_pastCasesTab_title(), new PastCasesPanel()), + new DataSourceTab(Bundle.DataSourceSummaryTabbedPane_timelineTab_title(), new TimelinePanel()), // do nothing on closing new DataSourceTab(Bundle.DataSourceSummaryTabbedPane_ingestHistoryTab_title(), ingestHistoryPanel, ingestHistoryPanel::setDataSource, () -> { }), diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/PastCasesPanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/PastCasesPanel.java index 76d36f4785..d99f4a1778 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/PastCasesPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/PastCasesPanel.java @@ -20,7 +20,6 @@ package org.sleuthkit.autopsy.datasourcesummary.ui; import java.util.Arrays; import java.util.List; -import java.util.function.Function; import org.apache.commons.lang3.tuple.Pair; import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.centralrepository.ingestmodule.CentralRepoIngestModuleFactory; @@ -28,7 +27,6 @@ import org.sleuthkit.autopsy.datasourcesummary.datamodel.PastCasesSummary; import org.sleuthkit.autopsy.datasourcesummary.datamodel.PastCasesSummary.PastCasesResult; import org.sleuthkit.autopsy.datasourcesummary.uiutils.CellModelTableCellRenderer.DefaultCellModel; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchResult; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchResult.ResultType; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker.DataFetchComponents; import org.sleuthkit.autopsy.datasourcesummary.uiutils.IngestRunningLabel; @@ -103,32 +101,11 @@ public class PastCasesPanel extends BaseDataSourceSummaryPanel { * @param result The result. */ private void handleResult(DataFetchResult result) { - showResultWithModuleCheck(notableFileTable, getSubResult(result, (res) -> res.getTaggedNotable()), CR_FACTORY, CR_NAME); - showResultWithModuleCheck(sameIdTable, getSubResult(result, (res) -> res.getSameIdsResults()), CR_FACTORY, CR_NAME); + showResultWithModuleCheck(notableFileTable, DataFetchResult.getSubResult(result, (res) -> res.getTaggedNotable()), CR_FACTORY, CR_NAME); + showResultWithModuleCheck(sameIdTable, DataFetchResult.getSubResult(result, (res) -> res.getSameIdsResults()), CR_FACTORY, CR_NAME); } - /** - * Given an input data fetch result, creates an error result if the original - * is an error. Otherwise, uses the getSubResult function on the underlying - * data to create a new DataFetchResult. - * - * @param inputResult The input result. - * @param getSubComponent The means of getting the data given the original - * data. - * - * @return The new result with the error of the original or the processed - * data. - */ - private DataFetchResult getSubResult(DataFetchResult inputResult, Function getSubResult) { - if (inputResult == null) { - return null; - } else if (inputResult.getResultType() == ResultType.SUCCESS) { - O innerData = (inputResult.getData() == null) ? null : getSubResult.apply(inputResult.getData()); - return DataFetchResult.getSuccessResult(innerData); - } else { - return DataFetchResult.getErrorResult(inputResult.getException()); - } - } + @Override protected void fetchInformation(DataSource dataSource) { diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.form b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.form index 6b68566967..e824d632f6 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.form +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.form @@ -74,6 +74,9 @@
+ + + @@ -107,21 +110,42 @@ - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + @@ -147,51 +171,22 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + + - + diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.java index b88954c317..906de8eef1 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.java @@ -18,12 +18,22 @@ */ package org.sleuthkit.autopsy.datasourcesummary.ui; +import java.awt.Color; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.ArrayList; import java.util.Arrays; +import java.util.Date; import java.util.List; +import java.util.Locale; +import org.apache.commons.collections.CollectionUtils; import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.datasourcesummary.datamodel.TimelineSummary; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.TimelineSummary.DailyActivityAmount; import org.sleuthkit.autopsy.datasourcesummary.datamodel.TimelineSummary.TimelineSummaryData; import org.sleuthkit.autopsy.datasourcesummary.uiutils.BarChartPanel; +import org.sleuthkit.autopsy.datasourcesummary.uiutils.BarChartPanel.BarChartItem; +import org.sleuthkit.autopsy.datasourcesummary.uiutils.BarChartPanel.BarChartSeries; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchResult; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker.DataFetchComponents; @@ -44,6 +54,9 @@ import org.sleuthkit.datamodel.DataSource; public class TimelinePanel extends BaseDataSourceSummaryPanel { private static final long serialVersionUID = 1L; + private static final DateFormat EARLIEST_LATEST_FORMAT = new SimpleDateFormat("MMM d, yyyy", Locale.getDefault()); + private static final DateFormat CHART_FORMAT = new SimpleDateFormat("MMM d", Locale.getDefault()); + private static final Color CHART_COLOR = Color.BLUE; private final LoadableLabel earliestLabel = new LoadableLabel(Bundle.TimelinePanel_earliestLabel_title()); private final LoadableLabel latestLabel = new LoadableLabel(Bundle.TimelinePanel_latestLabel_title()); @@ -70,6 +83,34 @@ public class TimelinePanel extends BaseDataSourceSummaryPanel { initComponents(); } + + + private static String parseEarliestLatest(Date date) { + return date == null ? null : EARLIEST_LATEST_FORMAT.format(date); + } + + private BarChartSeries parseChartData(List recentDaysActivity) { + if (CollectionUtils.isEmpty(recentDaysActivity)) { + return null; + } + + List items = new ArrayList<>(); + for (int i = 0; i < recentDaysActivity.size(); i++) { + DailyActivityAmount curItem = recentDaysActivity.get(i); + long amount = curItem.getArtifactActivityCount() * 1000 + curItem.getFileActivityCount(); + + if (i == 0 || i == recentDaysActivity.size() - 1) { + String formattedDate = curItem.getDay() == null ? "" : CHART_FORMAT.format(curItem.getDay()); + items.add(new BarChartItem(formattedDate, amount)); + } else { + items.add(new BarChartItem("", amount)); + } + } + + return new BarChartSeries(CHART_COLOR, items); + } + + /** * Handles displaying the result for each table by breaking apart subdata @@ -78,11 +119,9 @@ public class TimelinePanel extends BaseDataSourceSummaryPanel { * @param result The result. */ private void handleResult(DataFetchResult result) { - if (result == null) { - // TODO - } else { - // TODO - } + earliestLabel.showDataFetchResult(DataFetchResult.getSubResult(result, r -> parseEarliestLatest(r.getMinDate()))); + latestLabel.showDataFetchResult(DataFetchResult.getSubResult(result, r -> parseEarliestLatest(r.getMaxDate()))); + last30DaysChart.showDataFetchResult(DataFetchResult.getSubResult(result, r -> parseChartData(r.getMostRecentDaysActivity()))); } @Override @@ -115,11 +154,10 @@ public class TimelinePanel extends BaseDataSourceSummaryPanel { javax.swing.JPanel ingestRunningPanel = ingestRunningLabel; javax.swing.JLabel activityRangeLabel = new javax.swing.JLabel(); javax.swing.Box.Filler filler1 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 2), new java.awt.Dimension(0, 2), new java.awt.Dimension(0, 2)); - javax.swing.JPanel notableFilePanel = notableFileTable; + javax.swing.JPanel earliestLabelPanel = earliestLabel; + javax.swing.JPanel latestLabelPanel = latestLabel; javax.swing.Box.Filler filler2 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 20), new java.awt.Dimension(0, 20), new java.awt.Dimension(0, 20)); - javax.swing.JLabel sameIdLabel = new javax.swing.JLabel(); - javax.swing.Box.Filler filler3 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 2), new java.awt.Dimension(0, 2), new java.awt.Dimension(0, 2)); - javax.swing.JPanel sameIdPanel = sameIdTable; + javax.swing.JPanel sameIdPanel = last30DaysChart; javax.swing.Box.Filler filler5 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 32767)); mainContentPanel.setBorder(javax.swing.BorderFactory.createEmptyBorder(10, 10, 10, 10)); @@ -131,6 +169,7 @@ public class TimelinePanel extends BaseDataSourceSummaryPanel { ingestRunningPanel.setPreferredSize(new java.awt.Dimension(10, 25)); mainContentPanel.add(ingestRunningPanel); + activityRangeLabel.setFont(new java.awt.Font("Segoe UI", 1, 12)); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(activityRangeLabel, org.openide.util.NbBundle.getMessage(TimelinePanel.class, "TimelinePanel.activityRangeLabel.text")); // NOI18N mainContentPanel.add(activityRangeLabel); activityRangeLabel.getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getMessage(TimelinePanel.class, "PastCasesPanel.notableFileLabel.text")); // NOI18N @@ -138,25 +177,26 @@ public class TimelinePanel extends BaseDataSourceSummaryPanel { filler1.setAlignmentX(0.0F); mainContentPanel.add(filler1); - notableFilePanel.setAlignmentX(0.0F); - notableFilePanel.setMaximumSize(new java.awt.Dimension(32767, 106)); - notableFilePanel.setMinimumSize(new java.awt.Dimension(100, 106)); - notableFilePanel.setPreferredSize(new java.awt.Dimension(100, 106)); - mainContentPanel.add(notableFilePanel); + earliestLabelPanel.setAlignmentX(0.0F); + earliestLabelPanel.setMaximumSize(new java.awt.Dimension(32767, 20)); + earliestLabelPanel.setMinimumSize(new java.awt.Dimension(100, 20)); + earliestLabelPanel.setPreferredSize(new java.awt.Dimension(32767, 20)); + mainContentPanel.add(earliestLabelPanel); + + latestLabelPanel.setAlignmentX(0.0F); + latestLabelPanel.setMaximumSize(new java.awt.Dimension(32767, 20)); + latestLabelPanel.setMinimumSize(new java.awt.Dimension(100, 20)); + latestLabelPanel.setPreferredSize(new java.awt.Dimension(32767, 20)); + mainContentPanel.add(latestLabelPanel); filler2.setAlignmentX(0.0F); mainContentPanel.add(filler2); - org.openide.awt.Mnemonics.setLocalizedText(sameIdLabel, org.openide.util.NbBundle.getMessage(TimelinePanel.class, "TimelinePanel.sameIdLabel.text")); // NOI18N - mainContentPanel.add(sameIdLabel); - - filler3.setAlignmentX(0.0F); - mainContentPanel.add(filler3); - sameIdPanel.setAlignmentX(0.0F); - sameIdPanel.setMaximumSize(new java.awt.Dimension(32767, 106)); - sameIdPanel.setMinimumSize(new java.awt.Dimension(100, 106)); - sameIdPanel.setPreferredSize(new java.awt.Dimension(100, 106)); + sameIdPanel.setMaximumSize(new java.awt.Dimension(600, 300)); + sameIdPanel.setMinimumSize(new java.awt.Dimension(600, 300)); + sameIdPanel.setPreferredSize(new java.awt.Dimension(600, 300)); + sameIdPanel.setVerifyInputWhenFocusTarget(false); mainContentPanel.add(sameIdPanel); filler5.setAlignmentX(0.0F); diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/DataFetchResult.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/DataFetchResult.java index 93cc24f5fe..6e2d8f4991 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/DataFetchResult.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/DataFetchResult.java @@ -18,6 +18,8 @@ */ package org.sleuthkit.autopsy.datasourcesummary.uiutils; +import java.util.function.Function; + /** * The result of a loading process. */ @@ -30,6 +32,29 @@ public final class DataFetchResult { SUCCESS, ERROR } + /** + * A utility method that, given an input data fetch result, creates an error + * result if the original is an error. Otherwise, uses the getSubResult + * function on the underlying data to create a new DataFetchResult. + * + * @param inputResult The input result. + * @param getSubComponent The means of getting the data given the original + * data. + * + * @return The new result with the error of the original or the processed + * data. + */ + public static DataFetchResult getSubResult(DataFetchResult inputResult, Function getSubResult) { + if (inputResult == null) { + return null; + } else if (inputResult.getResultType() == ResultType.SUCCESS) { + O innerData = (inputResult.getData() == null) ? null : getSubResult.apply(inputResult.getData()); + return DataFetchResult.getSuccessResult(innerData); + } else { + return DataFetchResult.getErrorResult(inputResult.getException()); + } + } + /** * Creates a DataFetchResult of loaded data including the data. * @@ -59,9 +84,8 @@ public final class DataFetchResult { /** * Main constructor for the DataLoadingResult. * - * @param state The state of the result. - * @param data If the result is SUCCESS, the data related to this - * result. + * @param state The state of the result. + * @param data If the result is SUCCESS, the data related to this result. * @param exception If the result is ERROR, the related exception. */ private DataFetchResult(ResultType state, R data, Throwable exception) { From 34f5a00932d6162d4abd2b77d0a12fd971f15706 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Tue, 10 Nov 2020 09:38:31 -0500 Subject: [PATCH 68/81] a few small fixes --- .../datamodel/TimelineSummary.java | 93 ++++++++----------- .../ui/Bundle.properties-MERGED | 5 + .../datasourcesummary/ui/TimelinePanel.form | 4 +- .../datasourcesummary/ui/TimelinePanel.java | 15 ++- .../uiutils/BarChartPanel.java | 62 +++++++++++-- 5 files changed, 113 insertions(+), 66 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TimelineSummary.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TimelineSummary.java index af056387dd..4d65e095a6 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TimelineSummary.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TimelineSummary.java @@ -18,6 +18,7 @@ */ package org.sleuthkit.autopsy.datasourcesummary.datamodel; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Date; @@ -26,25 +27,20 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; +import java.util.stream.IntStream; import org.apache.commons.lang3.tuple.Pair; import org.joda.time.Interval; import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DefaultUpdateGovernor; import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.autopsy.ingest.ModuleContentEvent; -import org.sleuthkit.autopsy.timeline.utils.FilterUtils; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.DataSource; import org.sleuthkit.datamodel.TimelineEvent; import org.sleuthkit.datamodel.TimelineEventType; import org.sleuthkit.datamodel.TimelineFilter; import org.sleuthkit.datamodel.TimelineFilter.DataSourcesFilter; -import org.sleuthkit.datamodel.TimelineFilter.EventTypeFilter; -import org.sleuthkit.datamodel.TimelineFilter.HashHitsFilter; -import org.sleuthkit.datamodel.TimelineFilter.HideKnownFilter; import org.sleuthkit.datamodel.TimelineFilter.RootFilter; -import org.sleuthkit.datamodel.TimelineFilter.TagsFilter; -import org.sleuthkit.datamodel.TimelineFilter.TextFilter; import org.sleuthkit.datamodel.TimelineManager; import org.sleuthkit.datamodel.TskCoreException; @@ -52,21 +48,20 @@ import org.sleuthkit.datamodel.TskCoreException; * Provides data source summary information pertaining to Timeline data. */ public class TimelineSummary implements DefaultUpdateGovernor { - private static final long DAY_SECS = 24 * 60 * 60; - - - private static final Set INGEST_JOB_EVENTS = new HashSet<>( - Arrays.asList(IngestManager.IngestJobEvent.COMPLETED, IngestManager.IngestJobEvent.CANCELLED)); - - private static final Set FILE_SYSTEM_EVENTS = - new HashSet<>(Arrays.asList( - TimelineEventType.FILE_MODIFIED, - TimelineEventType.FILE_ACCESSED, - TimelineEventType.FILE_CREATED, + private static final long DAY_SECS = 24 * 60 * 60; + private static final int MOST_RECENT_DAYS_COUNT = 30; + + private static final Set INGEST_JOB_EVENTS = new HashSet<>( + Arrays.asList(IngestManager.IngestJobEvent.COMPLETED, IngestManager.IngestJobEvent.CANCELLED)); + + private static final Set FILE_SYSTEM_EVENTS + = new HashSet<>(Arrays.asList( + TimelineEventType.FILE_MODIFIED, + TimelineEventType.FILE_ACCESSED, + TimelineEventType.FILE_CREATED, TimelineEventType.FILE_CHANGED)); - - + private final SleuthkitCaseProvider provider; /** @@ -85,7 +80,6 @@ public class TimelineSummary implements DefaultUpdateGovernor { this.provider = provider; } - @Override public boolean isRefreshRequired(ModuleContentEvent evt) { return true; @@ -105,8 +99,6 @@ public class TimelineSummary implements DefaultUpdateGovernor { public Set getIngestJobEventUpdates() { return INGEST_JOB_EVENTS; } - - private static Long getMinOrNull(Long first, Long second) { if (first == null) { @@ -136,13 +128,13 @@ public class TimelineSummary implements DefaultUpdateGovernor { // TODO check that this isn't filtering more than it should RootFilter dataSourceRootFilter = new RootFilter( - new HideKnownFilter(), - new TagsFilter(), - new HashHitsFilter(), - new TextFilter(), - new EventTypeFilter(TimelineEventType.ROOT_EVENT_TYPE), - new DataSourcesFilter(), - FilterUtils.createDefaultFileTypesFilter(), + null, + null, + null, + null, + null, + dataSourceFilter, + null, Collections.emptySet()); // get events for data source @@ -150,9 +142,9 @@ public class TimelineSummary implements DefaultUpdateGovernor { List events = timelineManager.getEvents(new Interval(0, curRunTime), dataSourceRootFilter); // get counts of events per day (left is file system events, right is everything else) - Map> dateCounts = events.stream().collect(Collectors.toMap( - (evt) -> evt.getTime() / DAY_SECS, - (evt) -> FILE_SYSTEM_EVENTS.contains(evt.getEventType()) ? Pair.of(1, 0) : Pair.of(0, 1), + Map> dateCounts = events.stream().collect(Collectors.toMap( + (evt) -> (evt.getTime() / DAY_SECS), + (evt) -> FILE_SYSTEM_EVENTS.contains(evt.getEventType()) ? Pair.of(1L, 0L) : Pair.of(0L, 1L), (count1, count2) -> Pair.of(count1.getLeft() + count2.getLeft(), count1.getRight() + count2.getRight()))); // get minimum and maximum usage date @@ -169,21 +161,19 @@ public class TimelineSummary implements DefaultUpdateGovernor { return null; } - Date minDate = new Date(minDay * 1000); - Date maxDate = new Date(maxDay * 1000); + Date minDate = new Date(minDay * 1000 * DAY_SECS); + Date maxDate = new Date(maxDay * 1000 * DAY_SECS); - List mostRecentActivityAmt = dateCounts.entrySet().stream() - // reverse sort to get latest activity - .sorted((e1, e2) -> -Long.compare(e1.getKey(), e2.getKey())) - // get last 30 days - .limit(30) - // convert to object to return - .map(entry -> new DailyActivityAmount(new Date(entry.getKey() * 1000), entry.getValue().getLeft(), entry.getValue().getRight())) - // create list - .collect(Collectors.toList()); + List mostRecentActivityAmt = new ArrayList<>(); - // get in ascending order - Collections.reverse(mostRecentActivityAmt); + long minRecentDay = Math.max(maxDay - MOST_RECENT_DAYS_COUNT + 1, minDay); + for (long curRecentDay = minRecentDay; curRecentDay <= maxDay; curRecentDay++) { + Pair counts = dateCounts.get(curRecentDay); + long fileSystemEvts = counts == null ? 0L : counts.getLeft(); + long otherEvts = counts == null ? 0L : counts.getRight(); + + mostRecentActivityAmt.add(new DailyActivityAmount(new Date(curRecentDay * DAY_SECS * 1000), fileSystemEvts, otherEvts)); + } return new TimelineSummaryData(minDate, maxDate, mostRecentActivityAmt); } @@ -216,10 +206,10 @@ public class TimelineSummary implements DefaultUpdateGovernor { public static class DailyActivityAmount { private final Date day; - private final int fileActivityCount; - private final int artifactActivityCount; + private final long fileActivityCount; + private final long artifactActivityCount; - public DailyActivityAmount(Date day, int fileActivityCount, int artifactActivityCount) { + public DailyActivityAmount(Date day, long fileActivityCount, long artifactActivityCount) { this.day = day; this.fileActivityCount = fileActivityCount; this.artifactActivityCount = artifactActivityCount; @@ -229,14 +219,13 @@ public class TimelineSummary implements DefaultUpdateGovernor { return day; } - public int getFileActivityCount() { + public long getFileActivityCount() { return fileActivityCount; } - public int getArtifactActivityCount() { + public long getArtifactActivityCount() { return artifactActivityCount; } - - + } } diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties-MERGED index f03f55df38..fffa2bfb87 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties-MERGED @@ -47,6 +47,7 @@ DataSourceSummaryTabbedPane_detailsTab_title=Container DataSourceSummaryTabbedPane_ingestHistoryTab_title=Ingest History DataSourceSummaryTabbedPane_pastCasesTab_title=Past Cases DataSourceSummaryTabbedPane_recentFileTab_title=Recent Files +DataSourceSummaryTabbedPane_timelineTab_title=Timeline DataSourceSummaryTabbedPane_typesTab_title=Types DataSourceSummaryTabbedPane_userActivityTab_title=User Activity PastCasesPanel_caseColumn_title=Case @@ -64,6 +65,9 @@ SizeRepresentationUtil_units_kilobytes=\ kB SizeRepresentationUtil_units_megabytes=\ MB SizeRepresentationUtil_units_petabytes=\ PB SizeRepresentationUtil_units_terabytes=\ TB +TimelinePanel_earliestLabel_title=Earliest +TimelinePanel_latestLabel_title=Latest +TimlinePanel_last30DaysChart_title=Last 30 Days TypesPanel_artifactsTypesPieChart_title=Artifact Types TypesPanel_fileMimeTypesChart_audio_title=Audio TypesPanel_fileMimeTypesChart_documents_title=Documents @@ -95,6 +99,7 @@ RecentFilesPanel.attachmentLabel.text=Recent Attachments PastCasesPanel.notableFileLabel.text=Cases with Common Items That Were Tagged as Notable PastCasesPanel.sameIdLabel.text=Past Cases with the Same Device IDs DataSourceSummaryTabbedPane.noDataSourceLabel.text=No data source has been selected. +TimelinePanel.activityRangeLabel.text=Activity Range UserActivityPanel_noDataExists=No communication data exists UserActivityPanel_tab_title=User Activity UserActivityPanel_TopAccountTableModel_accountType_header=Account Type diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.form b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.form index e824d632f6..e3493d7a0d 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.form +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.form @@ -120,7 +120,7 @@ - + @@ -141,7 +141,7 @@ - + diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.java index 906de8eef1..ff578fb57b 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.java @@ -54,10 +54,12 @@ import org.sleuthkit.datamodel.DataSource; public class TimelinePanel extends BaseDataSourceSummaryPanel { private static final long serialVersionUID = 1L; - private static final DateFormat EARLIEST_LATEST_FORMAT = new SimpleDateFormat("MMM d, yyyy", Locale.getDefault()); - private static final DateFormat CHART_FORMAT = new SimpleDateFormat("MMM d", Locale.getDefault()); + private static final DateFormat EARLIEST_LATEST_FORMAT = getUtcFormat("MMM d, yyyy"); + private static final DateFormat CHART_FORMAT = getUtcFormat("MMM d"); private static final Color CHART_COLOR = Color.BLUE; + + private final LoadableLabel earliestLabel = new LoadableLabel(Bundle.TimelinePanel_earliestLabel_title()); private final LoadableLabel latestLabel = new LoadableLabel(Bundle.TimelinePanel_latestLabel_title()); private final BarChartPanel last30DaysChart = new BarChartPanel(Bundle.TimlinePanel_last30DaysChart_title(), "", ""); @@ -66,6 +68,11 @@ public class TimelinePanel extends BaseDataSourceSummaryPanel { private final List> dataFetchComponents; private final IngestRunningLabel ingestRunningLabel = new IngestRunningLabel(); + + private static DateFormat getUtcFormat(String formatString) { + return new SimpleDateFormat(formatString, Locale.getDefault()); + } + public TimelinePanel() { this(new TimelineSummary()); } @@ -180,13 +187,13 @@ public class TimelinePanel extends BaseDataSourceSummaryPanel { earliestLabelPanel.setAlignmentX(0.0F); earliestLabelPanel.setMaximumSize(new java.awt.Dimension(32767, 20)); earliestLabelPanel.setMinimumSize(new java.awt.Dimension(100, 20)); - earliestLabelPanel.setPreferredSize(new java.awt.Dimension(32767, 20)); + earliestLabelPanel.setPreferredSize(new java.awt.Dimension(100, 20)); mainContentPanel.add(earliestLabelPanel); latestLabelPanel.setAlignmentX(0.0F); latestLabelPanel.setMaximumSize(new java.awt.Dimension(32767, 20)); latestLabelPanel.setMinimumSize(new java.awt.Dimension(100, 20)); - latestLabelPanel.setPreferredSize(new java.awt.Dimension(32767, 20)); + latestLabelPanel.setPreferredSize(new java.awt.Dimension(100, 20)); mainContentPanel.add(latestLabelPanel); filler2.setAlignmentX(0.0F); diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/BarChartPanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/BarChartPanel.java index d9a29efa6b..e40eb4bf0d 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/BarChartPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/BarChartPanel.java @@ -27,8 +27,11 @@ import javax.swing.JLabel; import org.jfree.chart.ChartFactory; import org.jfree.chart.ChartPanel; import org.jfree.chart.JFreeChart; -import org.jfree.chart.plot.PiePlot; +import org.jfree.chart.axis.ValueAxis; +import org.jfree.chart.plot.CategoryPlot; import org.jfree.chart.plot.PlotOrientation; +import org.jfree.chart.renderer.category.BarRenderer; +import org.jfree.chart.renderer.category.StandardBarPainter; import org.jfree.data.category.DefaultCategoryDataset; /** @@ -98,7 +101,7 @@ public class BarChartPanel extends AbstractLoadableComponent { + + private final Object keyValue; + private final int keyIndex; + + OrderedKey(Object keyValue, int keyIndex) { + this.keyValue = keyValue; + this.keyIndex = keyIndex; + } + + Object getKeyValue() { + return keyValue; + } + + int getKeyIndex() { + return keyIndex; + } + + @Override + public int compareTo(OrderedKey o) { + if (o == null) { + return 1; + } + + return Integer.compare(this.getKeyIndex(), o.getKeyIndex()); + } + + @Override + public String toString() { + return this.getKeyValue() == null ? null : this.getKeyValue().toString(); + } + } + @Override protected void setResults(BarChartPanel.BarChartSeries data) { this.dataset.clear(); - this.plot.clearSectionPaints(false); if (data != null && data.getItems() != null && !data.getItems().isEmpty()) { - this.plot.setSectionPaint(DEFAULT_CATEGORY, data.getColor()); - for (BarChartPanel.BarChartItem bar : data.getItems()) { - this.dataset.setValue(bar.getValue(), DEFAULT_CATEGORY, bar.getLabel()); + if (data.getColor() != null) { + this.plot.getRenderer().setSeriesPaint(0, data.getColor()); + } + + for (int i = 0; i < data.getItems().size(); i++) { + BarChartItem bar = data.getItems().get(i); + this.dataset.setValue(bar.getValue(), DEFAULT_CATEGORY, new OrderedKey(bar.getLabel(), i)); } } } From a75479d8061a23102f94222bc4fd84b37e4d86f1 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Tue, 10 Nov 2020 12:24:14 -0500 Subject: [PATCH 69/81] refactoring and commenting --- .../datamodel/TimelineSummary.java | 201 +++++++++++++----- .../datasourcesummary/ui/TimelinePanel.java | 87 +++++--- .../uiutils/BarChartPanel.java | 117 ++++++---- 3 files changed, 278 insertions(+), 127 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TimelineSummary.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TimelineSummary.java index 4d65e095a6..6e16ee5f63 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TimelineSummary.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TimelineSummary.java @@ -18,17 +18,17 @@ */ package org.sleuthkit.autopsy.datasourcesummary.datamodel; +import java.time.Instant; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Date; +import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; -import java.util.stream.Collectors; -import java.util.stream.IntStream; -import org.apache.commons.lang3.tuple.Pair; +import java.util.TimeZone; import org.joda.time.Interval; import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DefaultUpdateGovernor; @@ -43,6 +43,8 @@ import org.sleuthkit.datamodel.TimelineFilter.DataSourcesFilter; import org.sleuthkit.datamodel.TimelineFilter.RootFilter; import org.sleuthkit.datamodel.TimelineManager; import org.sleuthkit.datamodel.TskCoreException; +import java.util.function.Supplier; +import org.sleuthkit.autopsy.core.UserPreferences; /** * Provides data source summary information pertaining to Timeline data. @@ -50,8 +52,6 @@ import org.sleuthkit.datamodel.TskCoreException; public class TimelineSummary implements DefaultUpdateGovernor { private static final long DAY_SECS = 24 * 60 * 60; - private static final int MOST_RECENT_DAYS_COUNT = 30; - private static final Set INGEST_JOB_EVENTS = new HashSet<>( Arrays.asList(IngestManager.IngestJobEvent.COMPLETED, IngestManager.IngestJobEvent.CANCELLED)); @@ -62,22 +62,25 @@ public class TimelineSummary implements DefaultUpdateGovernor { TimelineEventType.FILE_CREATED, TimelineEventType.FILE_CHANGED)); - private final SleuthkitCaseProvider provider; + private final SleuthkitCaseProvider caseProvider; + private final Supplier timeZoneProvider; /** * Default constructor. */ public TimelineSummary() { - this(SleuthkitCaseProvider.DEFAULT); + this(SleuthkitCaseProvider.DEFAULT, () -> TimeZone.getTimeZone(UserPreferences.getTimeZoneForDisplays())); } /** * Construct object with given SleuthkitCaseProvider * - * @param provider SleuthkitCaseProvider provider, cannot be null. + * @param caseProvider SleuthkitCaseProvider provider, cannot be null. + * @param timeZoneProvider The timezone provider, cannot be null. */ - public TimelineSummary(SleuthkitCaseProvider provider) { - this.provider = provider; + public TimelineSummary(SleuthkitCaseProvider caseProvider, Supplier timeZoneProvider) { + this.caseProvider = caseProvider; + this.timeZoneProvider = timeZoneProvider; } @Override @@ -100,33 +103,90 @@ public class TimelineSummary implements DefaultUpdateGovernor { return INGEST_JOB_EVENTS; } - private static Long getMinOrNull(Long first, Long second) { - if (first == null) { - return second; - } else if (second == null) { - return first; - } else { - return Math.min(first, second); + /** + * Retrieves timeline summary data. + * + * @param dataSource The data source for which timeline data will be + * retrieved. + * @param recentDaysNum The maximum number of most recent days' activity to + * include. + * @return The retrieved data. + * @throws SleuthkitCaseProviderException + * @throws TskCoreException + */ + public TimelineSummaryData getData(DataSource dataSource, int recentDaysNum) throws SleuthkitCaseProviderException, TskCoreException { + TimeZone timeZone = this.timeZoneProvider.get(); + TimelineManager timelineManager = this.caseProvider.get().getTimelineManager(); + + // get a mapping of days from epoch to the activity for that day + Map dateCounts = getTimelineEventsByDay(dataSource, timelineManager, timeZone); + + // get minimum and maximum usage date by iterating through + Long minDay = null; + Long maxDay = null; + for (long daysFromEpoch : dateCounts.keySet()) { + minDay = (minDay == null) ? daysFromEpoch : Math.min(minDay, daysFromEpoch); + maxDay = (maxDay == null) ? daysFromEpoch : Math.max(maxDay, daysFromEpoch); } + + // if no min date or max date, no usage; return null. + if (minDay == null || maxDay == null) { + return null; + } + + Date minDate = new Date(minDay * 1000 * DAY_SECS); + Date maxDate = new Date(maxDay * 1000 * DAY_SECS); + + // The minimum recent day will be within recentDaysNum from the maximum day + // (+1 since maxDay included) or the minimum day of activity + long minRecentDay = Math.max(maxDay - recentDaysNum + 1, minDay); + + // get most recent days activity + List mostRecentActivityAmt = getMostRecentActivityAmounts(dateCounts, minRecentDay, maxDay); + + return new TimelineSummaryData(minDate, maxDate, mostRecentActivityAmt); } - private static Long getMaxOrNull(Long first, Long second) { - if (first == null) { - return second; - } else if (second == null) { - return first; - } else { - return Math.max(first, second); + /** + * Given activity by day, converts to most recent days' activity handling + * empty values. + * + * @param dateCounts The day from epoch mapped to activity amounts for that + * day. + * @param minRecentDay The minimum recent day in days from epoch. + * @param maxDay The maximum recent day in days from epoch; + * @return The most recent daily activity amounts. + */ + private List getMostRecentActivityAmounts(Map dateCounts, long minRecentDay, long maxDay) { + List mostRecentActivityAmt = new ArrayList<>(); + + for (long curRecentDay = minRecentDay; curRecentDay <= maxDay; curRecentDay++) { + DailyActivityAmount prevCounts = dateCounts.get(curRecentDay); + DailyActivityAmount countsHandleNotFound = prevCounts != null + ? prevCounts + : new DailyActivityAmount(new Date(curRecentDay * DAY_SECS * 1000), 0, 0); + + mostRecentActivityAmt.add(countsHandleNotFound); } + return mostRecentActivityAmt; } - public TimelineSummaryData getData(DataSource dataSource) throws SleuthkitCaseProviderException, TskCoreException { - TimelineManager timelineManager = this.provider.get().getTimelineManager(); + /** + * Fetches timeline events per day for a particular data source. + * + * @param dataSource The data source. + * @param timelineManager The timeline manager to use while fetching the + * data. + * @param timeZone The time zone to use to determine which day activity + * belongs. + * @return A Map mapping days from epoch to the activity for that day. + * @throws TskCoreException + */ + private Map getTimelineEventsByDay(DataSource dataSource, TimelineManager timelineManager, TimeZone timeZone) throws TskCoreException { DataSourcesFilter dataSourceFilter = new DataSourcesFilter(); dataSourceFilter.addSubFilter(new TimelineFilter.DataSourceFilter(dataSource.getName(), dataSource.getId())); - // TODO check that this isn't filtering more than it should RootFilter dataSourceRootFilter = new RootFilter( null, null, @@ -142,87 +202,114 @@ public class TimelineSummary implements DefaultUpdateGovernor { List events = timelineManager.getEvents(new Interval(0, curRunTime), dataSourceRootFilter); // get counts of events per day (left is file system events, right is everything else) - Map> dateCounts = events.stream().collect(Collectors.toMap( - (evt) -> (evt.getTime() / DAY_SECS), - (evt) -> FILE_SYSTEM_EVENTS.contains(evt.getEventType()) ? Pair.of(1L, 0L) : Pair.of(0L, 1L), - (count1, count2) -> Pair.of(count1.getLeft() + count2.getLeft(), count1.getRight() + count2.getRight()))); + Map dateCounts = new HashMap<>(); + for (TimelineEvent evt : events) { + long curSecondsFromEpoch = evt.getTime(); + long curDaysFromEpoch = Instant.ofEpochMilli(curSecondsFromEpoch * 1000) + .atZone(timeZone.toZoneId()) + .toLocalDate() + .toEpochDay(); - // get minimum and maximum usage date - Pair minMax = dateCounts.keySet().stream().reduce( - Pair.of((Long) null, (Long) null), - (curMinMax, thisDay) -> Pair.of(getMinOrNull(curMinMax.getLeft(), thisDay), getMaxOrNull(curMinMax.getRight(), thisDay)), - (minMax1, minMax2) -> Pair.of(getMinOrNull(minMax1.getLeft(), minMax2.getLeft()), getMaxOrNull(minMax1.getRight(), minMax2.getRight()))); + DailyActivityAmount prevAmt = dateCounts.get(curDaysFromEpoch); + long prevFileEvtCount = prevAmt == null ? 0 : prevAmt.getFileActivityCount(); + long prevArtifactEvtCount = prevAmt == null ? 0 : prevAmt.getArtifactActivityCount(); + Date thisDay = prevAmt == null ? new Date(curDaysFromEpoch * 1000 * DAY_SECS) : prevAmt.getDay(); - Long minDay = minMax.getLeft(); - Long maxDay = minMax.getRight(); + boolean isFileEvt = FILE_SYSTEM_EVENTS.contains(evt.getEventType()); + long curFileEvtCount = prevFileEvtCount + (isFileEvt ? 1 : 0); + long curArtifactEvtCount = prevArtifactEvtCount + (isFileEvt ? 0 : 1); - // if no min date or max date, no usage; return null. - if (minDay == null || maxDay == null) { - return null; + dateCounts.put(curDaysFromEpoch, new DailyActivityAmount(thisDay, curFileEvtCount, curArtifactEvtCount)); } - Date minDate = new Date(minDay * 1000 * DAY_SECS); - Date maxDate = new Date(maxDay * 1000 * DAY_SECS); - - List mostRecentActivityAmt = new ArrayList<>(); - - long minRecentDay = Math.max(maxDay - MOST_RECENT_DAYS_COUNT + 1, minDay); - for (long curRecentDay = minRecentDay; curRecentDay <= maxDay; curRecentDay++) { - Pair counts = dateCounts.get(curRecentDay); - long fileSystemEvts = counts == null ? 0L : counts.getLeft(); - long otherEvts = counts == null ? 0L : counts.getRight(); - - mostRecentActivityAmt.add(new DailyActivityAmount(new Date(curRecentDay * DAY_SECS * 1000), fileSystemEvts, otherEvts)); - } - - return new TimelineSummaryData(minDate, maxDate, mostRecentActivityAmt); + return dateCounts; } + /** + * All the data to be represented in the timeline summary tab. + */ public static class TimelineSummaryData { private final Date minDate; private final Date maxDate; private final List histogramActivity; + /** + * Main constructor. + * + * @param minDate Earliest usage date recorded for the data source. + * @param maxDate Latest usage date recorded for the data source. + * @param recentDaysActivity A list of activity prior to and including + * the latest usage date by day. + */ TimelineSummaryData(Date minDate, Date maxDate, List recentDaysActivity) { this.minDate = minDate; this.maxDate = maxDate; this.histogramActivity = (recentDaysActivity == null) ? Collections.emptyList() : Collections.unmodifiableList(recentDaysActivity); } + /** + * @return Earliest usage date recorded for the data source. + */ public Date getMinDate() { return minDate; } + /** + * @return Latest usage date recorded for the data source. + */ public Date getMaxDate() { return maxDate; } + /** + * @return A list of activity prior to and including the latest usage + * date by day. + */ public List getMostRecentDaysActivity() { return histogramActivity; } } + /** + * Represents the amount of usage based on timeline events for a day. + */ public static class DailyActivityAmount { private final Date day; private final long fileActivityCount; private final long artifactActivityCount; - public DailyActivityAmount(Date day, long fileActivityCount, long artifactActivityCount) { + /** + * Main constructor. + * + * @param day The day for which activity is being measured. + * @param fileActivityCount The amount of file activity timeline events. + * @param artifactActivityCount The amount of artifact timeline events. + */ + DailyActivityAmount(Date day, long fileActivityCount, long artifactActivityCount) { this.day = day; this.fileActivityCount = fileActivityCount; this.artifactActivityCount = artifactActivityCount; } + /** + * @return The day for which activity is being measured. + */ public Date getDay() { return day; } + /** + * @return The amount of file activity timeline events. + */ public long getFileActivityCount() { return fileActivityCount; } + /** + * @return The amount of artifact timeline events. + */ public long getArtifactActivityCount() { return artifactActivityCount; } diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.java index ff578fb57b..3d4e8cb5d0 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.java @@ -43,8 +43,8 @@ import org.sleuthkit.autopsy.datasourcesummary.uiutils.LoadableLabel; import org.sleuthkit.datamodel.DataSource; /** - * A tab shown in data source summary displaying information about a datasource - * and how it pertains to other cases. + * A tab shown in data source summary displaying information about a data + * source's timeline events. */ @Messages({ "TimelinePanel_earliestLabel_title=Earliest", @@ -57,22 +57,30 @@ public class TimelinePanel extends BaseDataSourceSummaryPanel { private static final DateFormat EARLIEST_LATEST_FORMAT = getUtcFormat("MMM d, yyyy"); private static final DateFormat CHART_FORMAT = getUtcFormat("MMM d"); private static final Color CHART_COLOR = Color.BLUE; + private static final int MOST_RECENT_DAYS_COUNT = 30; - - - private final LoadableLabel earliestLabel = new LoadableLabel(Bundle.TimelinePanel_earliestLabel_title()); - private final LoadableLabel latestLabel = new LoadableLabel(Bundle.TimelinePanel_latestLabel_title()); - private final BarChartPanel last30DaysChart = new BarChartPanel(Bundle.TimlinePanel_last30DaysChart_title(), "", ""); - - private final List> loadableComponents = Arrays.asList(earliestLabel, latestLabel, last30DaysChart); - private final List> dataFetchComponents; - private final IngestRunningLabel ingestRunningLabel = new IngestRunningLabel(); - - + /** + * Creates a DateFormat formatter that uses UTC for time zone. + * + * @param formatString The date format string. + * @return The data format. + */ private static DateFormat getUtcFormat(String formatString) { return new SimpleDateFormat(formatString, Locale.getDefault()); } - + + // components displayed in the tab + private final IngestRunningLabel ingestRunningLabel = new IngestRunningLabel(); + private final LoadableLabel earliestLabel = new LoadableLabel(Bundle.TimelinePanel_earliestLabel_title()); + private final LoadableLabel latestLabel = new LoadableLabel(Bundle.TimelinePanel_latestLabel_title()); + private final BarChartPanel last30DaysChart = new BarChartPanel(Bundle.TimlinePanel_last30DaysChart_title(), "", ""); + + // all loadable components on this tab + private final List> loadableComponents = Arrays.asList(earliestLabel, latestLabel, last30DaysChart); + + // actions to load data for this tab + private final List> dataFetchComponents; + public TimelinePanel() { this(new TimelineSummary()); } @@ -84,50 +92,67 @@ public class TimelinePanel extends BaseDataSourceSummaryPanel { // set up data acquisition methods dataFetchComponents = Arrays.asList( new DataFetchWorker.DataFetchComponents<>( - (dataSource) -> timelineData.getData(dataSource), + (dataSource) -> timelineData.getData(dataSource, MOST_RECENT_DAYS_COUNT), (result) -> handleResult(result)) ); initComponents(); } - - - private static String parseEarliestLatest(Date date) { - return date == null ? null : EARLIEST_LATEST_FORMAT.format(date); + + /** + * Formats a date using a DateFormat. In the event that the date is null, + * returns a null string. + * + * @param date The date to format. + * @param formatter The DateFormat to use to format the date. + * @return The formatted string generated from the formatter or null if the + * date is null. + */ + private static String formatDate(Date date, DateFormat formatter) { + return date == null ? null : formatter.format(date); } - + + /** + * Converts DailyActivityAmount data retrieved from TimelineSummary into + * data to be displayed as a bar chart. + * + * @param recentDaysActivity The data retrieved from TimelineSummary. + * @return The data to be displayed in the BarChart. + */ private BarChartSeries parseChartData(List recentDaysActivity) { + // if no data, return null indicating no result. if (CollectionUtils.isEmpty(recentDaysActivity)) { return null; } - + + // Create a bar chart item for each recent days activity item List items = new ArrayList<>(); for (int i = 0; i < recentDaysActivity.size(); i++) { DailyActivityAmount curItem = recentDaysActivity.get(i); long amount = curItem.getArtifactActivityCount() * 1000 + curItem.getFileActivityCount(); - + if (i == 0 || i == recentDaysActivity.size() - 1) { - String formattedDate = curItem.getDay() == null ? "" : CHART_FORMAT.format(curItem.getDay()); + String formattedDate = formatDate(curItem.getDay(), CHART_FORMAT); items.add(new BarChartItem(formattedDate, amount)); } else { items.add(new BarChartItem("", amount)); } } - + return new BarChartSeries(CHART_COLOR, items); } - - /** - * Handles displaying the result for each table by breaking apart subdata - * items into seperate results for each table. + * Handles displaying the result for each displayable item in the + * TimelinePanel by breaking the TimelineSummaryData result into its + * constituent parts and then sending each data item to the pertinent + * component. * - * @param result The result. + * @param result The result to be displayed on this tab. */ private void handleResult(DataFetchResult result) { - earliestLabel.showDataFetchResult(DataFetchResult.getSubResult(result, r -> parseEarliestLatest(r.getMinDate()))); - latestLabel.showDataFetchResult(DataFetchResult.getSubResult(result, r -> parseEarliestLatest(r.getMaxDate()))); + earliestLabel.showDataFetchResult(DataFetchResult.getSubResult(result, r -> formatDate(r.getMinDate(), EARLIEST_LATEST_FORMAT))); + latestLabel.showDataFetchResult(DataFetchResult.getSubResult(result, r -> formatDate(r.getMaxDate(), EARLIEST_LATEST_FORMAT))); last30DaysChart.showDataFetchResult(DataFetchResult.getSubResult(result, r -> parseChartData(r.getMostRecentDaysActivity()))); } diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/BarChartPanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/BarChartPanel.java index e40eb4bf0d..f7b5b618e2 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/BarChartPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/BarChartPanel.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2019 Basis Technology Corp. + * Copyright 2020 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -39,27 +39,43 @@ import org.jfree.data.category.DefaultCategoryDataset; */ public class BarChartPanel extends AbstractLoadableComponent { + /** + * Represents a series in a bar chart where all items pertain to one + * category. + */ public static class BarChartSeries { private final Color color; private final List items; + /** + * Main constructor. + * + * @param color The color for this series. + * @param items The bars to be displayed for this series. + */ public BarChartSeries(Color color, List items) { this.color = color; this.items = (items == null) ? Collections.emptyList() : Collections.unmodifiableList(items); } + /** + * @return The color for this series. + */ public Color getColor() { return color; } + /** + * @return The bars to be displayed for this series. + */ public List getItems() { return items; } } /** - * An individual pie chart slice in the pie chart. + * An individual bar to be displayed in the bar chart. */ public static class BarChartItem { @@ -71,7 +87,6 @@ public class BarChartPanel extends AbstractLoadableComponent { + + private final Object keyValue; + private final int keyIndex; + + /** + * Main constructor. + * @param keyValue The value for the key to be displayed in the domain axis. + * @param keyIndex The index at which it will be displayed. + */ + OrderedKey(Object keyValue, int keyIndex) { + this.keyValue = keyValue; + this.keyIndex = keyIndex; + } + + /** + * @return The value for the key to be displayed in the domain axis. + */ + Object getKeyValue() { + return keyValue; + } + + /** + * @return The index at which it will be displayed. + */ + int getKeyIndex() { + return keyIndex; + } + + @Override + public int compareTo(OrderedKey o) { + // this will have a higher value than null. + if (o == null) { + return 1; + } + + // compare by index + return Integer.compare(this.getKeyIndex(), o.getKeyIndex()); + } + + @Override + public String toString() { + // use toString on the key. + return this.getKeyValue() == null ? null : this.getKeyValue().toString(); + } + } + private static final long serialVersionUID = 1L; private static final Font DEFAULT_FONT = new JLabel().getFont(); @@ -104,7 +171,7 @@ public class BarChartPanel extends AbstractLoadableComponent { - - private final Object keyValue; - private final int keyIndex; - - OrderedKey(Object keyValue, int keyIndex) { - this.keyValue = keyValue; - this.keyIndex = keyIndex; - } - - Object getKeyValue() { - return keyValue; - } - - int getKeyIndex() { - return keyIndex; - } - - @Override - public int compareTo(OrderedKey o) { - if (o == null) { - return 1; - } - - return Integer.compare(this.getKeyIndex(), o.getKeyIndex()); - } - - @Override - public String toString() { - return this.getKeyValue() == null ? null : this.getKeyValue().toString(); - } - } - @Override protected void setResults(BarChartPanel.BarChartSeries data) { this.dataset.clear(); From be88084127c0ee92c621b3ce220718d8e1d15ce5 Mon Sep 17 00:00:00 2001 From: Mark McKinnon Date: Tue, 10 Nov 2020 13:51:19 -0500 Subject: [PATCH 70/81] Update shellactivities.pl Fix infinite loop in plugin --- thirdparty/rr-full/plugins/shellactivities.pl | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/thirdparty/rr-full/plugins/shellactivities.pl b/thirdparty/rr-full/plugins/shellactivities.pl index 8b16917536..5df9f5615f 100644 --- a/thirdparty/rr-full/plugins/shellactivities.pl +++ b/thirdparty/rr-full/plugins/shellactivities.pl @@ -70,6 +70,7 @@ sub processShellActivities { ::rptMsg(""); while ($offset < ($sz - 10)) { + # Code to locate the appropriate identifier $tag = 1; while ($tag) { @@ -78,9 +79,15 @@ sub processShellActivities { } else { $offset++; + # Check if at end of file and exit loop if it is + last if ($offset >= $sz ); } } - + + # Check if at end of file and exit loop if it is + last if ($offset >= $sz ); + + $offset += 2; $l = unpack("C",substr($data,$offset,1)); # ::rptMsg("String Length: ".sprintf "0x%x",$l); From 6cbeb2a2c6cca92fbd2cf12afe9f79acecff21ab Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Tue, 10 Nov 2020 14:21:44 -0500 Subject: [PATCH 71/81] stacked bar chart --- .../ui/Bundle.properties-MERGED | 2 + .../datasourcesummary/ui/TimelinePanel.java | 36 ++++--- .../uiutils/BarChartPanel.java | 101 +++++++++++------- 3 files changed, 89 insertions(+), 50 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties-MERGED index fffa2bfb87..0e3dcf5969 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties-MERGED @@ -67,6 +67,8 @@ SizeRepresentationUtil_units_petabytes=\ PB SizeRepresentationUtil_units_terabytes=\ TB TimelinePanel_earliestLabel_title=Earliest TimelinePanel_latestLabel_title=Latest +TimlinePanel_last30DaysChart_artifactEvts_title=Artifact Events +TimlinePanel_last30DaysChart_fileEvts_title=File Events TimlinePanel_last30DaysChart_title=Last 30 Days TypesPanel_artifactsTypesPieChart_title=Artifact Types TypesPanel_fileMimeTypesChart_audio_title=Audio diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.java index 3d4e8cb5d0..1b198cccb6 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.java @@ -34,6 +34,7 @@ import org.sleuthkit.autopsy.datasourcesummary.datamodel.TimelineSummary.Timelin import org.sleuthkit.autopsy.datasourcesummary.uiutils.BarChartPanel; import org.sleuthkit.autopsy.datasourcesummary.uiutils.BarChartPanel.BarChartItem; import org.sleuthkit.autopsy.datasourcesummary.uiutils.BarChartPanel.BarChartSeries; +import org.sleuthkit.autopsy.datasourcesummary.uiutils.BarChartPanel.OrderedKey; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchResult; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker.DataFetchComponents; @@ -49,8 +50,9 @@ import org.sleuthkit.datamodel.DataSource; @Messages({ "TimelinePanel_earliestLabel_title=Earliest", "TimelinePanel_latestLabel_title=Latest", - "TimlinePanel_last30DaysChart_title=Last 30 Days" -}) + "TimlinePanel_last30DaysChart_title=Last 30 Days", + "TimlinePanel_last30DaysChart_fileEvts_title=File Events", + "TimlinePanel_last30DaysChart_artifactEvts_title=Artifact Events",}) public class TimelinePanel extends BaseDataSourceSummaryPanel { private static final long serialVersionUID = 1L; @@ -58,7 +60,7 @@ public class TimelinePanel extends BaseDataSourceSummaryPanel { private static final DateFormat CHART_FORMAT = getUtcFormat("MMM d"); private static final Color CHART_COLOR = Color.BLUE; private static final int MOST_RECENT_DAYS_COUNT = 30; - + /** * Creates a DateFormat formatter that uses UTC for time zone. * @@ -112,6 +114,9 @@ public class TimelinePanel extends BaseDataSourceSummaryPanel { return date == null ? null : formatter.format(date); } + private static final Color FILE_EVT_COLOR = new Color(1, 87, 155); + private static final Color ARTIFACT_EVT_COLOR = new Color(76, 175, 80); + /** * Converts DailyActivityAmount data retrieved from TimelineSummary into * data to be displayed as a bar chart. @@ -119,27 +124,32 @@ public class TimelinePanel extends BaseDataSourceSummaryPanel { * @param recentDaysActivity The data retrieved from TimelineSummary. * @return The data to be displayed in the BarChart. */ - private BarChartSeries parseChartData(List recentDaysActivity) { + private List parseChartData(List recentDaysActivity) { // if no data, return null indicating no result. if (CollectionUtils.isEmpty(recentDaysActivity)) { return null; } // Create a bar chart item for each recent days activity item - List items = new ArrayList<>(); + List fileEvtCounts = new ArrayList<>(); + List artifactEvtCounts = new ArrayList<>(); + for (int i = 0; i < recentDaysActivity.size(); i++) { DailyActivityAmount curItem = recentDaysActivity.get(i); - long amount = curItem.getArtifactActivityCount() * 1000 + curItem.getFileActivityCount(); - if (i == 0 || i == recentDaysActivity.size() - 1) { - String formattedDate = formatDate(curItem.getDay(), CHART_FORMAT); - items.add(new BarChartItem(formattedDate, amount)); - } else { - items.add(new BarChartItem("", amount)); - } + long fileAmt = curItem.getFileActivityCount(); + long artifactAmt = curItem.getArtifactActivityCount() * 100; + String formattedDate = (i == 0 || i == recentDaysActivity.size() - 1) + ? formatDate(curItem.getDay(), CHART_FORMAT) : ""; + + OrderedKey thisKey = new OrderedKey(formattedDate, i); + fileEvtCounts.add(new BarChartItem(thisKey, fileAmt)); + artifactEvtCounts.add(new BarChartItem(thisKey, artifactAmt)); } - return new BarChartSeries(CHART_COLOR, items); + return Arrays.asList( + new BarChartSeries(Bundle.TimlinePanel_last30DaysChart_fileEvts_title(), FILE_EVT_COLOR, fileEvtCounts), + new BarChartSeries(Bundle.TimlinePanel_last30DaysChart_artifactEvts_title(), ARTIFACT_EVT_COLOR, artifactEvtCounts)); } /** diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/BarChartPanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/BarChartPanel.java index f7b5b618e2..4656e93815 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/BarChartPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/BarChartPanel.java @@ -24,6 +24,7 @@ import java.awt.Font; import java.util.Collections; import java.util.List; import javax.swing.JLabel; +import org.apache.commons.collections4.CollectionUtils; import org.jfree.chart.ChartFactory; import org.jfree.chart.ChartPanel; import org.jfree.chart.JFreeChart; @@ -37,7 +38,7 @@ import org.jfree.data.category.DefaultCategoryDataset; /** * A bar chart panel. */ -public class BarChartPanel extends AbstractLoadableComponent { +public class BarChartPanel extends AbstractLoadableComponent> { /** * Represents a series in a bar chart where all items pertain to one @@ -45,6 +46,7 @@ public class BarChartPanel extends AbstractLoadableComponent items; @@ -54,7 +56,8 @@ public class BarChartPanel extends AbstractLoadableComponent items) { + public BarChartSeries(Comparable key, Color color, List items) { + this.key = key; this.color = color; this.items = (items == null) ? Collections.emptyList() : Collections.unmodifiableList(items); } @@ -72,6 +75,13 @@ public class BarChartPanel extends AbstractLoadableComponent getItems() { return items; } + + /** + * @return The key for this item. + */ + public Comparable getKey() { + return key; + } } /** @@ -79,25 +89,26 @@ public class BarChartPanel extends AbstractLoadableComponent { + public static class OrderedKey implements Comparable { private final Object keyValue; private final int keyIndex; /** * Main constructor. - * @param keyValue The value for the key to be displayed in the domain axis. + * + * @param keyValue The value for the key to be displayed in the domain + * axis. * @param keyIndex The index at which it will be displayed. */ - OrderedKey(Object keyValue, int keyIndex) { + public OrderedKey(Object keyValue, int keyIndex) { this.keyValue = keyValue; this.keyIndex = keyIndex; } @@ -153,6 +166,30 @@ public class BarChartPanel extends AbstractLoadableComponent data) { this.dataset.clear(); - if (data != null && data.getItems() != null && !data.getItems().isEmpty()) { - if (data.getColor() != null) { - this.plot.getRenderer().setSeriesPaint(0, data.getColor()); - } + if (CollectionUtils.isNotEmpty(data)) { + for (int s = 0; s < data.size(); s++) { + BarChartPanel.BarChartSeries series = data.get(s); + if (series != null && CollectionUtils.isNotEmpty(series.getItems())) { + if (series.getColor() != null) { + this.plot.getRenderer().setSeriesPaint(s, series.getColor()); + } - for (int i = 0; i < data.getItems().size(); i++) { - BarChartItem bar = data.getItems().get(i); - this.dataset.setValue(bar.getValue(), DEFAULT_CATEGORY, new OrderedKey(bar.getLabel(), i)); + for (int i = 0; i < series.getItems().size(); i++) { + BarChartItem bar = series.getItems().get(i); + this.dataset.setValue(bar.getValue(), series.getKey(), bar.getKey()); + } + } } } } - - /** - * Shows a message on top of data. - * - * @param data The data. - * @param message The message. - */ - public synchronized void showDataWithMessage(BarChartPanel.BarChartSeries data, String message) { - setResults(data); - setMessage(true, message); - repaint(); - } } From 8e186293392fe13a330a514553eb48d50de8646c Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Tue, 10 Nov 2020 15:14:05 -0500 Subject: [PATCH 72/81] show NA for some fields --- .../ui/Bundle.properties-MERGED | 1 + .../datasourcesummary/ui/ContainerPanel.java | 50 ++++++++++++++----- 2 files changed, 39 insertions(+), 12 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties-MERGED index f03f55df38..173fbf513d 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties-MERGED @@ -3,6 +3,7 @@ AnalysisPanel_keyColumn_title=Name AnalysisPanel_keywordSearchModuleName=Keyword Search # {0} - module name BaseDataSourceSummaryPanel_defaultNotIngestMessage=The {0} ingest module has not been run on this data source. +ContainerPanel_setFieldsForNonImageDataSource_na=N/A CTL_DataSourceSummaryAction=Data Source Summary DataSourceSummaryDialog.closeButton.text=Close ContainerPanel.displayNameLabel.text=Display Name: diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ContainerPanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ContainerPanel.java index a852a0b886..5977ad525f 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ContainerPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ContainerPanel.java @@ -26,6 +26,7 @@ import java.util.Set; import java.util.logging.Level; import org.sleuthkit.autopsy.coreutils.Logger; import javax.swing.table.DefaultTableModel; +import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.datasourcesummary.datamodel.ContainerSummary; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchResult.ResultType; @@ -34,6 +35,7 @@ import org.sleuthkit.autopsy.datasourcesummary.uiutils.DefaultUpdateGovernor; import org.sleuthkit.autopsy.datasourcesummary.uiutils.UpdateGovernor; import org.sleuthkit.datamodel.DataSource; import org.sleuthkit.datamodel.Image; +import org.sleuthkit.datamodel.LocalFilesDataSource; import org.sleuthkit.datamodel.TskCoreException; /** @@ -52,7 +54,7 @@ class ContainerPanel extends BaseDataSourceSummaryPanel { /** * Main constructor. * - * @param dataSource The original datasource. + * @param dataSource The original datasource. * @param unallocatedFilesSize The unallocated file size. */ ContainerPanelData(DataSource dataSource, Long unallocatedFilesSize) { @@ -165,42 +167,66 @@ class ContainerPanel extends BaseDataSourceSummaryPanel { private void updateDetailsPanelData(DataSource selectedDataSource, Long unallocatedFilesSize) { clearTableValues(); if (selectedDataSource != null) { - unallocatedSizeValue.setText(SizeRepresentationUtil.getSizeString(unallocatedFilesSize)); - timeZoneValue.setText(selectedDataSource.getTimeZone()); displayNameValue.setText(selectedDataSource.getName()); originalNameValue.setText(selectedDataSource.getName()); deviceIdValue.setText(selectedDataSource.getDeviceId()); - try { - acquisitionDetailsTextArea.setText(selectedDataSource.getAcquisitionDetails()); - } catch (TskCoreException ex) { - logger.log(Level.WARNING, "Unable to get aquisition details for selected data source", ex); - } - if (selectedDataSource instanceof Image) { - setFieldsForImage((Image) selectedDataSource); + setFieldsForImage((Image) selectedDataSource, unallocatedFilesSize); + } else { + setFieldsForNonImageDataSource(); } } - + this.repaint(); } + + @Messages({ + "ContainerPanel_setFieldsForNonImageDataSource_na=N/A" + }) + private void setFieldsForNonImageDataSource() { + String NA = Bundle.ContainerPanel_setFieldsForNonImageDataSource_na(); + + unallocatedSizeValue.setText(NA); + imageTypeValue.setText(NA); + sizeValue.setText(NA); + sectorSizeValue.setText(NA); + timeZoneValue.setText(NA); + + ((DefaultTableModel) filePathsTable.getModel()).addRow(new Object[]{NA}); + + acquisitionDetailsTextArea.setText(NA); + md5HashValue.setText(NA); + sha1HashValue.setText(NA); + sha256HashValue.setText(NA); + } + /** * Sets text fields for an image. This should be called after * clearTableValues and before updateFieldVisibility to ensure the proper * rendering. * * @param selectedImage The selected image. + * @param unallocatedFilesSize Unallocated file size in bytes. */ - private void setFieldsForImage(Image selectedImage) { + private void setFieldsForImage(Image selectedImage, Long unallocatedFilesSize) { + unallocatedSizeValue.setText(SizeRepresentationUtil.getSizeString(unallocatedFilesSize)); imageTypeValue.setText(selectedImage.getType().getName()); sizeValue.setText(SizeRepresentationUtil.getSizeString(selectedImage.getSize())); sectorSizeValue.setText(SizeRepresentationUtil.getSizeString(selectedImage.getSsize())); + timeZoneValue.setText(selectedImage.getTimeZone()); for (String path : selectedImage.getPaths()) { ((DefaultTableModel) filePathsTable.getModel()).addRow(new Object[]{path}); } + try { + acquisitionDetailsTextArea.setText(selectedImage.getAcquisitionDetails()); + } catch (TskCoreException ex) { + logger.log(Level.WARNING, "Unable to get aquisition details for selected data source", ex); + } + try { //older databases may have null as the hash values String md5String = selectedImage.getMd5(); From a90529aa4c1f43b732bab2bfa4487d7cc70ae056 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Tue, 10 Nov 2020 15:18:12 -0500 Subject: [PATCH 73/81] dependency cleanup --- .../sleuthkit/autopsy/datasourcesummary/ui/ContainerPanel.java | 1 - 1 file changed, 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ContainerPanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ContainerPanel.java index 5977ad525f..f69f2793a3 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ContainerPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ContainerPanel.java @@ -35,7 +35,6 @@ import org.sleuthkit.autopsy.datasourcesummary.uiutils.DefaultUpdateGovernor; import org.sleuthkit.autopsy.datasourcesummary.uiutils.UpdateGovernor; import org.sleuthkit.datamodel.DataSource; import org.sleuthkit.datamodel.Image; -import org.sleuthkit.datamodel.LocalFilesDataSource; import org.sleuthkit.datamodel.TskCoreException; /** From a92a37e259e21059b536d72d7a0b3d4ab85b2a57 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Tue, 10 Nov 2020 15:31:50 -0500 Subject: [PATCH 74/81] color fix and raw types fix --- .../autopsy/datasourcesummary/ui/TimelinePanel.java | 5 ++--- .../datasourcesummary/uiutils/BarChartPanel.java | 12 ++++++------ 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.java index 1b198cccb6..87f170ccab 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.java @@ -58,7 +58,6 @@ public class TimelinePanel extends BaseDataSourceSummaryPanel { private static final long serialVersionUID = 1L; private static final DateFormat EARLIEST_LATEST_FORMAT = getUtcFormat("MMM d, yyyy"); private static final DateFormat CHART_FORMAT = getUtcFormat("MMM d"); - private static final Color CHART_COLOR = Color.BLUE; private static final int MOST_RECENT_DAYS_COUNT = 30; /** @@ -114,8 +113,8 @@ public class TimelinePanel extends BaseDataSourceSummaryPanel { return date == null ? null : formatter.format(date); } - private static final Color FILE_EVT_COLOR = new Color(1, 87, 155); - private static final Color ARTIFACT_EVT_COLOR = new Color(76, 175, 80); + private static final Color FILE_EVT_COLOR = new Color(228, 22, 28); + private static final Color ARTIFACT_EVT_COLOR = new Color(21, 227, 100); /** * Converts DailyActivityAmount data retrieved from TimelineSummary into diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/BarChartPanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/BarChartPanel.java index 4656e93815..3f3822f7c2 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/BarChartPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/BarChartPanel.java @@ -46,7 +46,7 @@ public class BarChartPanel extends AbstractLoadableComponent key; private final Color color; private final List items; @@ -56,7 +56,7 @@ public class BarChartPanel extends AbstractLoadableComponent items) { + public BarChartSeries(Comparable key, Color color, List items) { this.key = key; this.color = color; this.items = (items == null) ? Collections.emptyList() : Collections.unmodifiableList(items); @@ -79,7 +79,7 @@ public class BarChartPanel extends AbstractLoadableComponent getKey() { return key; } } @@ -89,7 +89,7 @@ public class BarChartPanel extends AbstractLoadableComponent key; private final double value; /** @@ -99,7 +99,7 @@ public class BarChartPanel extends AbstractLoadableComponent key, double value) { this.key = key; this.value = value; } @@ -107,7 +107,7 @@ public class BarChartPanel extends AbstractLoadableComponent getKey() { return key; } From e0ce0e44a71488ac7779d9e68ccb10157629b40e Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Tue, 10 Nov 2020 15:37:17 -0500 Subject: [PATCH 75/81] always show acquisition details --- .../datasourcesummary/ui/ContainerPanel.java | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ContainerPanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ContainerPanel.java index f69f2793a3..eda979132f 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ContainerPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ContainerPanel.java @@ -170,6 +170,12 @@ class ContainerPanel extends BaseDataSourceSummaryPanel { originalNameValue.setText(selectedDataSource.getName()); deviceIdValue.setText(selectedDataSource.getDeviceId()); + try { + acquisitionDetailsTextArea.setText(selectedDataSource.getAcquisitionDetails()); + } catch (TskCoreException ex) { + logger.log(Level.WARNING, "Unable to get aquisition details for selected data source", ex); + } + if (selectedDataSource instanceof Image) { setFieldsForImage((Image) selectedDataSource, unallocatedFilesSize); } else { @@ -180,22 +186,20 @@ class ContainerPanel extends BaseDataSourceSummaryPanel { this.repaint(); } - @Messages({ "ContainerPanel_setFieldsForNonImageDataSource_na=N/A" }) private void setFieldsForNonImageDataSource() { String NA = Bundle.ContainerPanel_setFieldsForNonImageDataSource_na(); - + unallocatedSizeValue.setText(NA); imageTypeValue.setText(NA); sizeValue.setText(NA); sectorSizeValue.setText(NA); timeZoneValue.setText(NA); - + ((DefaultTableModel) filePathsTable.getModel()).addRow(new Object[]{NA}); - - acquisitionDetailsTextArea.setText(NA); + md5HashValue.setText(NA); sha1HashValue.setText(NA); sha256HashValue.setText(NA); @@ -220,12 +224,6 @@ class ContainerPanel extends BaseDataSourceSummaryPanel { ((DefaultTableModel) filePathsTable.getModel()).addRow(new Object[]{path}); } - try { - acquisitionDetailsTextArea.setText(selectedImage.getAcquisitionDetails()); - } catch (TskCoreException ex) { - logger.log(Level.WARNING, "Unable to get aquisition details for selected data source", ex); - } - try { //older databases may have null as the hash values String md5String = selectedImage.getMd5(); From 30cd7d35acd13fc1c7521c52a096527be5501363 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Tue, 10 Nov 2020 15:38:20 -0500 Subject: [PATCH 76/81] formatting --- .../sleuthkit/autopsy/datasourcesummary/ui/ContainerPanel.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ContainerPanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ContainerPanel.java index eda979132f..bc331d952b 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ContainerPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ContainerPanel.java @@ -175,7 +175,7 @@ class ContainerPanel extends BaseDataSourceSummaryPanel { } catch (TskCoreException ex) { logger.log(Level.WARNING, "Unable to get aquisition details for selected data source", ex); } - + if (selectedDataSource instanceof Image) { setFieldsForImage((Image) selectedDataSource, unallocatedFilesSize); } else { From ab1712042e447edea9a6afea7652f027a369385d Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Tue, 10 Nov 2020 15:45:53 -0500 Subject: [PATCH 77/81] formatting --- .../ui/DataSourceSummaryTabbedPane.java | 8 +++---- .../datasourcesummary/ui/PastCasesPanel.java | 2 -- .../datasourcesummary/ui/TypesPanel.java | 21 ++++++++----------- .../uiutils/PieChartPanel.java | 7 ++----- 4 files changed, 15 insertions(+), 23 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceSummaryTabbedPane.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceSummaryTabbedPane.java index f758f9716f..3670124fa2 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceSummaryTabbedPane.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceSummaryTabbedPane.java @@ -57,10 +57,10 @@ public class DataSourceSummaryTabbedPane extends javax.swing.JPanel { /** * Main constructor. * - * @param tabTitle The title of the tab. - * @param component The component to be displayed. + * @param tabTitle The title of the tab. + * @param component The component to be displayed. * @param onDataSource The function to be called on a new data source. - * @param onClose Called to cleanup resources when closing tabs. + * @param onClose Called to cleanup resources when closing tabs. */ DataSourceTab(String tabTitle, Component component, Consumer onDataSource, Runnable onClose) { this.tabTitle = tabTitle; @@ -73,7 +73,7 @@ public class DataSourceSummaryTabbedPane extends javax.swing.JPanel { * Main constructor. * * @param tabTitle The title of the tab. - * @param panel The component to be displayed in the tab. + * @param panel The component to be displayed in the tab. */ DataSourceTab(String tabTitle, BaseDataSourceSummaryPanel panel) { this.tabTitle = tabTitle; diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/PastCasesPanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/PastCasesPanel.java index d99f4a1778..2400334ee3 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/PastCasesPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/PastCasesPanel.java @@ -105,8 +105,6 @@ public class PastCasesPanel extends BaseDataSourceSummaryPanel { showResultWithModuleCheck(sameIdTable, DataFetchResult.getSubResult(result, (res) -> res.getSameIdsResults()), CR_FACTORY, CR_NAME); } - - @Override protected void fetchInformation(DataSource dataSource) { fetchInformation(dataFetchComponents, dataSource); diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TypesPanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TypesPanel.java index 509cd9257d..247aa0c304 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TypesPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TypesPanel.java @@ -18,7 +18,6 @@ */ package org.sleuthkit.autopsy.datasourcesummary.ui; -import java.awt.BorderLayout; import java.awt.Color; import java.sql.SQLException; import java.text.DecimalFormat; @@ -30,7 +29,6 @@ import java.util.Set; import java.util.logging.Level; import java.util.stream.Collectors; import java.util.stream.Stream; -import javax.swing.JLabel; import org.apache.commons.lang3.StringUtils; import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.coreutils.FileTypeUtils.FileTypeCategory; @@ -40,7 +38,6 @@ import org.sleuthkit.autopsy.datasourcesummary.datamodel.ContainerSummary; import org.sleuthkit.autopsy.datasourcesummary.datamodel.IngestModuleCheckUtil; import org.sleuthkit.autopsy.datasourcesummary.datamodel.MimeTypeSummary; import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.AbstractLoadableComponent; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchResult; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchResult.ResultType; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker; @@ -90,9 +87,9 @@ class TypesPanel extends BaseDataSourceSummaryPanel { /** * Main constructor. * - * @param pieSlices The pie slices. + * @param pieSlices The pie slices. * @param usefulContent True if this is useful content; false if there - * is 0 mime type information. + * is 0 mime type information. */ public TypesPieChartData(List pieSlices, boolean usefulContent) { this.pieSlices = pieSlices; @@ -126,9 +123,9 @@ class TypesPanel extends BaseDataSourceSummaryPanel { /** * Main constructor. * - * @param label The label for this slice. + * @param label The label for this slice. * @param mimeTypes The mime types associated with this slice. - * @param color The color associated with this slice. + * @param color The color associated with this slice. */ TypesPieCategory(String label, Set mimeTypes, Color color) { this.label = label; @@ -139,9 +136,9 @@ class TypesPanel extends BaseDataSourceSummaryPanel { /** * Constructor that accepts FileTypeCategory. * - * @param label The label for this slice. + * @param label The label for this slice. * @param mimeTypes The mime types associated with this slice. - * @param color The color associated with this slice. + * @param color The color associated with this slice. */ TypesPieCategory(String label, FileTypeCategory fileCategory, Color color) { this(label, fileCategory.getMediaTypes(), color); @@ -239,8 +236,8 @@ class TypesPanel extends BaseDataSourceSummaryPanel { /** * Creates a new TypesPanel. * - * @param mimeTypeData The service for mime types. - * @param typeData The service for file types data. + * @param mimeTypeData The service for mime types. + * @param typeData The service for file types data. * @param containerData The service for container information. */ public TypesPanel( @@ -319,7 +316,7 @@ class TypesPanel extends BaseDataSourceSummaryPanel { * Gets all the data for the file type pie chart. * * @param mimeTypeData The means of acquiring data. - * @param dataSource The datasource. + * @param dataSource The datasource. * * @return The pie chart items. */ diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/PieChartPanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/PieChartPanel.java index 7f9a1e218b..fa0d00dab6 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/PieChartPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/PieChartPanel.java @@ -21,7 +21,6 @@ package org.sleuthkit.autopsy.datasourcesummary.uiutils; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Font; -import java.awt.Graphics2D; import java.text.DecimalFormat; import java.util.List; import javax.swing.JLabel; @@ -30,8 +29,6 @@ import org.jfree.chart.ChartPanel; import org.jfree.chart.JFreeChart; import org.jfree.chart.labels.PieSectionLabelGenerator; import org.jfree.chart.labels.StandardPieSectionLabelGenerator; -import org.jfree.chart.panel.AbstractOverlay; -import org.jfree.chart.panel.Overlay; import org.jfree.chart.plot.PiePlot; import org.jfree.data.general.DefaultPieDataset; import org.openide.util.NbBundle.Messages; @@ -59,7 +56,7 @@ public class PieChartPanel extends AbstractLoadableComponent data, String message) { From eeb1ef6963c53d877639f3f2d906fe22cbba592e Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Tue, 10 Nov 2020 15:59:50 -0500 Subject: [PATCH 78/81] remove any 0 dates --- .../autopsy/datasourcesummary/datamodel/TimelineSummary.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TimelineSummary.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TimelineSummary.java index 6e16ee5f63..1d634211be 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TimelineSummary.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TimelineSummary.java @@ -199,7 +199,7 @@ public class TimelineSummary implements DefaultUpdateGovernor { // get events for data source long curRunTime = System.currentTimeMillis(); - List events = timelineManager.getEvents(new Interval(0, curRunTime), dataSourceRootFilter); + List events = timelineManager.getEvents(new Interval(1, curRunTime), dataSourceRootFilter); // get counts of events per day (left is file system events, right is everything else) Map dateCounts = new HashMap<>(); From 81ec9ea113eef9bd007f2cfbcd8c2b4fd0cc6fa4 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dsmyda" Date: Wed, 11 Nov 2020 19:55:31 -0500 Subject: [PATCH 79/81] Made the nightly db dump script ignore size and hash for TIFF files extracted from PDFs --- test/script/tskdbdiff.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/test/script/tskdbdiff.py b/test/script/tskdbdiff.py index f152cd923a..856a46b658 100644 --- a/test/script/tskdbdiff.py +++ b/test/script/tskdbdiff.py @@ -464,6 +464,16 @@ def normalize_db_entry(line, files_table, vs_parts_table, vs_info_table, fs_info # remove object ID if files_index: + + # Ignore TIFF size and hash if extracted from PDFs. + # See JIRA-6951 for more details. + # index: -1 = last element in the list, which is extension + # index: -3 = 3rd from the end, which is the parent path. + if fields_list[-1] == "'tif'" and fields_list[-3].endswith(".pdf/'"): + fields_list[15] = "'SIZE_IGNORED'" + fields_list[23] = "'MD5_IGNORED'" + fields_list[24] = "'SHA256_IGNORED'" + newLine = ('INSERT INTO "tsk_files" VALUES(' + ', '.join(fields_list[1:]) + ');') # Remove object ID from Unalloc file name newLine = re.sub('Unalloc_[0-9]+_', 'Unalloc_', newLine) From 75c258d22e36932bc8eb42ddda3a67e7dc61c333 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dsmyda" Date: Wed, 11 Nov 2020 19:57:47 -0500 Subject: [PATCH 80/81] Updated comment --- test/script/tskdbdiff.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/script/tskdbdiff.py b/test/script/tskdbdiff.py index 856a46b658..e202c3e111 100644 --- a/test/script/tskdbdiff.py +++ b/test/script/tskdbdiff.py @@ -467,8 +467,8 @@ def normalize_db_entry(line, files_table, vs_parts_table, vs_info_table, fs_info # Ignore TIFF size and hash if extracted from PDFs. # See JIRA-6951 for more details. - # index: -1 = last element in the list, which is extension - # index: -3 = 3rd from the end, which is the parent path. + # index -1 = last element in the list, which is extension + # index -3 = 3rd from the end, which is the parent path. if fields_list[-1] == "'tif'" and fields_list[-3].endswith(".pdf/'"): fields_list[15] = "'SIZE_IGNORED'" fields_list[23] = "'MD5_IGNORED'" From 8457cecff7919051b741fc1e4ed778a4d6452987 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Fri, 13 Nov 2020 13:02:00 -0500 Subject: [PATCH 81/81] 6774 simplify getPathIdFile code and fix comment --- .../autopsy/datamodel/BlackboardArtifactNode.java | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java index 51e9991eb0..34a6859292 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java @@ -308,8 +308,8 @@ public class BlackboardArtifactNode extends AbstractContentNode artifact.getSleuthkitCase().getContentById(attribute.getValueLong())); - } + BlackboardAttribute attribute = artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH_ID)); + if (attribute != null) { + return contentCache.get(attribute.getValueLong(), () -> artifact.getSleuthkitCase().getContentById(attribute.getValueLong())); } } catch (TskCoreException ex) { logger.log(Level.WARNING, MessageFormat.format("Error getting content for path id attrbiute for artifact: ", artifact.getId()), ex); //NON-NLS