diff --git a/Core/src/org/sleuthkit/autopsy/discovery/AbstractFiltersPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/AbstractFiltersPanel.java index e36963feac..6abe6ee557 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/AbstractFiltersPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/AbstractFiltersPanel.java @@ -62,7 +62,7 @@ abstract class AbstractFiltersPanel extends JPanel implements ActionListener, Li } abstract SearchData.ResultType getResultType(); - + /** * Get the type of results this filters panel is for. * @@ -70,6 +70,13 @@ abstract class AbstractFiltersPanel extends JPanel implements ActionListener, Li */ abstract FileSearchData.FileType getFileType(); + /** + * Get the type of results this filters panel is for. + * + * @return The type of results this panel filters. + */ + abstract ArtifactSearchData.ArtifactType getArtifactType(); + /** * Add a DiscoveryFilterPanel to the specified column with the specified * settings. @@ -245,14 +252,14 @@ abstract class AbstractFiltersPanel extends JPanel implements ActionListener, Li * @return The list of filters selected by the user. */ synchronized List getFilters() { - + List filtersToUse = new ArrayList<>(); if (getResultType().equals(SearchData.ResultType.FILE)) { - filtersToUse.add(new SearchFiltering.FileTypeFilter(getFileType())); - } else if (getResultType().equals(SearchData.ResultType.ARTIFACT)){ - + filtersToUse.add(new SearchFiltering.FileTypeFilter(getFileType())); + } else if (getResultType().equals(SearchData.ResultType.ARTIFACT)) { + } - + for (AbstractDiscoveryFilterPanel filterPanel : filters) { if (filterPanel.getCheckbox().isSelected()) { AbstractFilter filter = filterPanel.getFilter(); diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ArtifactTypeFilterPanel.form b/Core/src/org/sleuthkit/autopsy/discovery/ArtifactTypeFilterPanel.form new file mode 100644 index 0000000000..1e6d77593d --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/discovery/ArtifactTypeFilterPanel.form @@ -0,0 +1,53 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ArtifactTypeFilterPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ArtifactTypeFilterPanel.java new file mode 100644 index 0000000000..fb14ceaeef --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/discovery/ArtifactTypeFilterPanel.java @@ -0,0 +1,105 @@ +/* + * 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; + +import javax.swing.JCheckBox; +import javax.swing.JLabel; +import javax.swing.JList; + +/** + * + * @author wschaefer + */ +class ArtifactTypeFilterPanel extends AbstractDiscoveryFilterPanel { + + private static final long serialVersionUID = 1L; + + /** + * Creates new form ArtifactTypeFilterPanel + */ + ArtifactTypeFilterPanel() { + 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() { + + artifactTypeCheckbox = new javax.swing.JCheckBox(); + artifactTypeScrollPane = new javax.swing.JScrollPane(); + + org.openide.awt.Mnemonics.setLocalizedText(artifactTypeCheckbox, org.openide.util.NbBundle.getMessage(ArtifactTypeFilterPanel.class, "ArtifactTypeFilterPanel.artifactTypeCheckbox.text")); // NOI18N + + setPreferredSize(new java.awt.Dimension(27, 27)); + + artifactTypeScrollPane.setPreferredSize(new java.awt.Dimension(27, 27)); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(artifactTypeScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 229, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(artifactTypeScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 38, Short.MAX_VALUE) + ); + }// //GEN-END:initComponents + + @Override + void configurePanel(boolean selected, int[] indicesSelected) { + artifactTypeCheckbox.setSelected(selected); + } + + @Override + JCheckBox getCheckbox() { + return artifactTypeCheckbox; + } + + @Override + JList getList() { + return null; + } + + @Override + JLabel getAdditionalLabel() { + return null; + } + + @Override + String checkForError() { + return "Domain search is not implemented."; + } + + @Override + AbstractFilter getFilter() { + return null; + } + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JCheckBox artifactTypeCheckbox; + private javax.swing.JScrollPane artifactTypeScrollPane; + // End of variables declaration//GEN-END:variables +} diff --git a/Core/src/org/sleuthkit/autopsy/discovery/Bundle.properties b/Core/src/org/sleuthkit/autopsy/discovery/Bundle.properties index 795018f1ac..90e86aab72 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/discovery/Bundle.properties @@ -104,3 +104,9 @@ DiscoveryDialog.step1Label.text=Step 1: Choose result type ResultsSplitPaneDivider.hideButton.text= ResultsSplitPaneDivider.showButton.text= ResultsSplitPaneDivider.detailsLabel.text=Details Area +DiscoveryDialog.domainsButton.text=Domains +DomainFilterPanel.domainFiltersSplitPane.border.title=Step 2: Filter which domains to show +DomainFilterPanel.domainFiltersSplitPane.toolTipText= +DateFilterPanel.dateFilterCheckbox.text=Date Filter +ArtifactTypeFilterPanel.artifactTypeCheckbox.text=Artifact Type +DomainUniquenessFilterPanel.domainUniquenessCheckbox.text=Domain Uniqueness diff --git a/Core/src/org/sleuthkit/autopsy/discovery/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/discovery/Bundle.properties-MERGED index 74512110fe..1b61a3f9a6 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/discovery/Bundle.properties-MERGED @@ -14,6 +14,7 @@ DiscoveryTopComponent.newSearch.text=New Search DiscoveryTopComponent.searchCancelled.text=Search has been cancelled. # {0} - search DiscoveryTopComponent.searchComplete.text=Results with {0} +DiscoveryTopComponent.searchError.text=Error no type specified for search. # {0} - searchType DiscoveryTopComponent.searchInProgress.text=Performing search for results of type {0}. Please wait. DiscoveryUiUtility.bytes.text=bytes @@ -269,6 +270,12 @@ DiscoveryDialog.step1Label.text=Step 1: Choose result type ResultsSplitPaneDivider.hideButton.text= ResultsSplitPaneDivider.showButton.text= ResultsSplitPaneDivider.detailsLabel.text=Details Area +DiscoveryDialog.domainsButton.text=Domains +DomainFilterPanel.domainFiltersSplitPane.border.title=Step 2: Filter which domains to show +DomainFilterPanel.domainFiltersSplitPane.toolTipText= +DateFilterPanel.dateFilterCheckbox.text=Date Filter +ArtifactTypeFilterPanel.artifactTypeCheckbox.text=Artifact Type +DomainUniquenessFilterPanel.domainUniquenessCheckbox.text=Domain Uniqueness 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/DateFilterPanel.form b/Core/src/org/sleuthkit/autopsy/discovery/DateFilterPanel.form new file mode 100644 index 0000000000..5e523cc270 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/discovery/DateFilterPanel.form @@ -0,0 +1,43 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/Core/src/org/sleuthkit/autopsy/discovery/DateFilterPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/DateFilterPanel.java new file mode 100644 index 0000000000..5409cebbdc --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/discovery/DateFilterPanel.java @@ -0,0 +1,101 @@ +/* + * 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; + +import javax.swing.JCheckBox; +import javax.swing.JLabel; +import javax.swing.JList; + +/** + * + * @author wschaefer + */ +class DateFilterPanel extends AbstractDiscoveryFilterPanel { + + private static final long serialVersionUID = 1L; + + /** + * Creates new form DateFilterPanel + */ + DateFilterPanel() { + 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() { + + dateFilterCheckbox = new javax.swing.JCheckBox(); + dateFilterScrollPane = new javax.swing.JScrollPane(); + + org.openide.awt.Mnemonics.setLocalizedText(dateFilterCheckbox, org.openide.util.NbBundle.getMessage(DateFilterPanel.class, "DateFilterPanel.dateFilterCheckbox.text")); // NOI18N + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(dateFilterScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 223, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(dateFilterScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 43, Short.MAX_VALUE) + ); + }// //GEN-END:initComponents + + @Override + void configurePanel(boolean selected, int[] indicesSelected) { + dateFilterCheckbox.setSelected(selected); + } + + @Override + JCheckBox getCheckbox() { + return dateFilterCheckbox; + } + + @Override + JList getList() { + return null; + } + + @Override + JLabel getAdditionalLabel() { + return null; + } + + @Override + String checkForError() { + return "Domain search is not implemented."; + } + + @Override + AbstractFilter getFilter() { + return null; + } + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JCheckBox dateFilterCheckbox; + private javax.swing.JScrollPane dateFilterScrollPane; + // End of variables declaration//GEN-END:variables +} diff --git a/Core/src/org/sleuthkit/autopsy/discovery/DiscoveryDialog.form b/Core/src/org/sleuthkit/autopsy/discovery/DiscoveryDialog.form index 19116a24fe..f53408d443 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/DiscoveryDialog.form +++ b/Core/src/org/sleuthkit/autopsy/discovery/DiscoveryDialog.form @@ -48,12 +48,14 @@ - + - + - - + + + + @@ -78,6 +80,7 @@ + @@ -191,6 +194,26 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/discovery/DiscoveryDialog.java b/Core/src/org/sleuthkit/autopsy/discovery/DiscoveryDialog.java index 8c080e2b18..a5884beb61 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/DiscoveryDialog.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/DiscoveryDialog.java @@ -22,6 +22,7 @@ import static java.awt.BorderLayout.CENTER; import java.awt.Color; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; +import java.util.ArrayList; import java.util.EnumSet; import java.util.HashSet; import java.util.List; @@ -52,7 +53,7 @@ import static org.sleuthkit.autopsy.discovery.FileSorter.SortingMethod.BY_FILE_N * Discovery search. */ final class DiscoveryDialog extends javax.swing.JDialog { - + private static final Set CASE_EVENTS_OF_INTEREST = EnumSet.of(Case.Events.CURRENT_CASE, Case.Events.DATA_SOURCE_ADDED, Case.Events.DATA_SOURCE_DELETED); private static final Set INGEST_MODULE_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestModuleEvent.DATA_ADDED); @@ -61,12 +62,15 @@ final class DiscoveryDialog extends javax.swing.JDialog { private ImageFilterPanel imageFilterPanel = null; private VideoFilterPanel videoFilterPanel = null; private DocumentFilterPanel documentFilterPanel = null; + private DomainFilterPanel domainFilterPanel = null; private static final Color SELECTED_COLOR = new Color(216, 230, 242); private static final Color UNSELECTED_COLOR = new Color(240, 240, 240); private SearchWorker searchWorker = null; private static DiscoveryDialog discDialog; private static volatile boolean shouldUpdate = false; + private SearchData.ResultType resultType = SearchData.ResultType.FILE; private FileSearchData.FileType fileType = FileSearchData.FileType.IMAGE; + private ArtifactSearchData.ArtifactType artifactType = null; private final PropertyChangeListener listener; private final Set objectsDetected = new HashSet<>(); private final Set interestingItems = new HashSet<>(); @@ -122,17 +126,15 @@ final class DiscoveryDialog extends javax.swing.JDialog { imageFilterPanel = new ImageFilterPanel(); videoFilterPanel = new VideoFilterPanel(); documentFilterPanel = new DocumentFilterPanel(); + domainFilterPanel = new DomainFilterPanel(); + unselectAllButtons(); imagesButton.setSelected(true); imagesButton.setEnabled(false); imagesButton.setBackground(SELECTED_COLOR); imagesButton.setForeground(Color.BLACK); - videosButton.setSelected(false); - videosButton.setEnabled(true); - videosButton.setBackground(UNSELECTED_COLOR); - documentsButton.setSelected(false); - documentsButton.setEnabled(true); - documentsButton.setBackground(UNSELECTED_COLOR); + resultType = SearchData.ResultType.FILE; fileType = FileSearchData.FileType.IMAGE; + artifactType = null; add(imageFilterPanel, CENTER); imageFilterPanel.addPropertyChangeListener(listener); updateComboBoxes(); @@ -141,6 +143,21 @@ final class DiscoveryDialog extends javax.swing.JDialog { repaint(); } + private void unselectAllButtons() { + imagesButton.setSelected(false); + imagesButton.setEnabled(true); + imagesButton.setBackground(UNSELECTED_COLOR); + videosButton.setSelected(false); + videosButton.setEnabled(true); + videosButton.setBackground(UNSELECTED_COLOR); + documentsButton.setSelected(false); + documentsButton.setEnabled(true); + documentsButton.setBackground(UNSELECTED_COLOR); + domainsButton.setSelected(false); + domainsButton.setEnabled(true); + domainsButton.setBackground(UNSELECTED_COLOR); + } + /** * Private helper method to perform update of comboboxes update. */ @@ -199,17 +216,31 @@ final class DiscoveryDialog extends javax.swing.JDialog { * Validate the current filter settings of the selected type. */ synchronized void validateDialog() { + switch (resultType) { + case FILE: + validateFileDialog(); + break; + case ARTIFACT: + validateArtifactDialog(); + break; + } + } + + /** + * Validate the filter settings for File type filters. + */ + private synchronized void validateFileDialog() { switch (fileType) { case IMAGE: if (imageFilterPanel != null) { imageFilterPanel.validateFields(); } - return; + break; case VIDEO: if (videoFilterPanel != null) { videoFilterPanel.validateFields(); } - return; + break; case DOCUMENTS: if (documentFilterPanel != null) { documentFilterPanel.validateFields(); @@ -220,6 +251,21 @@ final class DiscoveryDialog extends javax.swing.JDialog { } } + /** + * Validate the filter settings for Artifact type filters. + */ + private synchronized void validateArtifactDialog() { + switch (artifactType) { + case DOMAIN: + if (domainFilterPanel != null) { + domainFilterPanel.validateFields(); + } + break; + default: + break; + } + } + /** * 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 @@ -235,6 +281,7 @@ final class DiscoveryDialog extends javax.swing.JDialog { documentsButton = new javax.swing.JButton(); javax.swing.JLabel step1Label = new javax.swing.JLabel(); javax.swing.Box.Filler filler1 = new javax.swing.Box.Filler(new java.awt.Dimension(104, 0), new java.awt.Dimension(104, 0), new java.awt.Dimension(104, 32767)); + domainsButton = new javax.swing.JButton(); javax.swing.JPanel displaySettingsPanel = new javax.swing.JPanel(); searchButton = new javax.swing.JButton(); errorLabel = new javax.swing.JLabel(); @@ -249,6 +296,7 @@ final class DiscoveryDialog extends javax.swing.JDialog { setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); setMinimumSize(new java.awt.Dimension(600, 300)); setPreferredSize(new java.awt.Dimension(1000, 650)); + getContentPane().setLayout(new java.awt.BorderLayout()); imagesButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/pictures-icon.png"))); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(imagesButton, org.openide.util.NbBundle.getMessage(DiscoveryDialog.class, "DiscoveryDialog.imagesButton.text")); // NOI18N @@ -292,6 +340,17 @@ final class DiscoveryDialog extends javax.swing.JDialog { org.openide.awt.Mnemonics.setLocalizedText(step1Label, org.openide.util.NbBundle.getMessage(DiscoveryDialog.class, "DiscoveryDialog.step1Label.text")); // NOI18N + domainsButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/web-file.png"))); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(domainsButton, org.openide.util.NbBundle.getMessage(DiscoveryDialog.class, "DiscoveryDialog.domainsButton.text")); // NOI18N + domainsButton.setDisabledIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/web-file.png"))); // NOI18N + domainsButton.setDisabledSelectedIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/web-file.png"))); // NOI18N + domainsButton.setFocusable(false); + domainsButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + domainsButtonActionPerformed(evt); + } + }); + javax.swing.GroupLayout toolBarPanelLayout = new javax.swing.GroupLayout(toolBarPanel); toolBarPanel.setLayout(toolBarPanelLayout); toolBarPanelLayout.setHorizontalGroup( @@ -306,13 +365,18 @@ final class DiscoveryDialog extends javax.swing.JDialog { .addComponent(videosButton, javax.swing.GroupLayout.PREFERRED_SIZE, 110, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(documentsButton) - .addContainerGap(370, Short.MAX_VALUE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(domainsButton) + .addContainerGap(190, Short.MAX_VALUE)) .addGroup(toolBarPanelLayout.createSequentialGroup() .addComponent(step1Label, javax.swing.GroupLayout.PREFERRED_SIZE, 243, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(filler1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addContainerGap(391, Short.MAX_VALUE)))) ); + + toolBarPanelLayout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {documentsButton, domainsButton, imagesButton, videosButton}); + toolBarPanelLayout.setVerticalGroup( toolBarPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(toolBarPanelLayout.createSequentialGroup() @@ -324,7 +388,8 @@ final class DiscoveryDialog extends javax.swing.JDialog { .addGroup(toolBarPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(videosButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(imagesButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(documentsButton, javax.swing.GroupLayout.PREFERRED_SIZE, 43, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(documentsButton, javax.swing.GroupLayout.PREFERRED_SIZE, 43, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(domainsButton, javax.swing.GroupLayout.PREFERRED_SIZE, 43, javax.swing.GroupLayout.PREFERRED_SIZE)) .addGap(8, 8, 8)) ); @@ -417,16 +482,13 @@ final class DiscoveryDialog extends javax.swing.JDialog { private void imagesButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_imagesButtonActionPerformed removeAllPanels(); add(imageFilterPanel, CENTER); + unselectAllButtons(); imagesButton.setSelected(true); imagesButton.setEnabled(false); imagesButton.setBackground(SELECTED_COLOR); imagesButton.setForeground(Color.BLACK); - videosButton.setSelected(false); - videosButton.setEnabled(true); - videosButton.setBackground(UNSELECTED_COLOR); - documentsButton.setSelected(false); - documentsButton.setEnabled(true); - documentsButton.setBackground(UNSELECTED_COLOR); + resultType = SearchData.ResultType.FILE; + artifactType = null; fileType = FileSearchData.FileType.IMAGE; imageFilterPanel.addPropertyChangeListener(listener); validateDialog(); @@ -437,17 +499,14 @@ final class DiscoveryDialog extends javax.swing.JDialog { private void videosButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_videosButtonActionPerformed removeAllPanels(); add(videoFilterPanel, CENTER); - imagesButton.setSelected(false); - imagesButton.setEnabled(true); - imagesButton.setBackground(UNSELECTED_COLOR); + unselectAllButtons(); videosButton.setSelected(true); videosButton.setEnabled(false); videosButton.setBackground(SELECTED_COLOR); videosButton.setForeground(Color.BLACK); - documentsButton.setSelected(false); - documentsButton.setEnabled(true); - documentsButton.setBackground(UNSELECTED_COLOR); videoFilterPanel.addPropertyChangeListener(listener); + resultType = SearchData.ResultType.FILE; + artifactType = null; fileType = FileSearchData.FileType.VIDEO; validateDialog(); pack(); @@ -457,16 +516,13 @@ final class DiscoveryDialog extends javax.swing.JDialog { private void documentsButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_documentsButtonActionPerformed removeAllPanels(); add(documentFilterPanel, CENTER); + unselectAllButtons(); documentsButton.setSelected(true); documentsButton.setEnabled(false); documentsButton.setBackground(SELECTED_COLOR); documentsButton.setForeground(Color.BLACK); - videosButton.setSelected(false); - videosButton.setEnabled(true); - videosButton.setBackground(UNSELECTED_COLOR); - imagesButton.setSelected(false); - imagesButton.setEnabled(true); - imagesButton.setBackground(UNSELECTED_COLOR); + resultType = SearchData.ResultType.FILE; + artifactType = null; fileType = FileSearchData.FileType.DOCUMENTS; documentFilterPanel.addPropertyChangeListener(listener); validateDialog(); @@ -490,6 +546,10 @@ final class DiscoveryDialog extends javax.swing.JDialog { remove(videoFilterPanel); videoFilterPanel.removePropertyChangeListener(listener); } + if (domainFilterPanel != null) { + remove(domainFilterPanel); + domainFilterPanel.removePropertyChangeListener(listener); + } } private void searchButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_searchButtonActionPerformed @@ -508,10 +568,16 @@ final class DiscoveryDialog extends javax.swing.JDialog { filters = videoFilterPanel.getFilters(); } else if (documentsButton.isSelected()) { filters = documentFilterPanel.getFilters(); - } else { + } else if (imagesButton.isSelected()) { filters = imageFilterPanel.getFilters(); + } else if (domainsButton.isSelected()) { + filters = domainFilterPanel.getFilters(); + } else { + logger.log(Level.SEVERE, "No filter type selected"); + filters = new ArrayList<>(); } - DiscoveryEventUtils.getDiscoveryEventBus().post(new DiscoveryEventUtils.SearchStartedEvent(fileType)); + + DiscoveryEventUtils.getDiscoveryEventBus().post(new DiscoveryEventUtils.SearchStartedEvent(resultType, fileType, artifactType)); // Get the grouping attribute and group sorting method FileSearch.AttributeType groupingAttr = groupByCombobox.getItemAt(groupByCombobox.getSelectedIndex()).getAttributeType(); @@ -534,7 +600,24 @@ final class DiscoveryDialog extends javax.swing.JDialog { tc.toFront(); tc.requestActive(); }//GEN-LAST:event_searchButtonActionPerformed - + + private void domainsButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_domainsButtonActionPerformed + removeAllPanels(); + add(domainFilterPanel, CENTER); + unselectAllButtons(); + domainsButton.setSelected(true); + domainsButton.setEnabled(false); + domainsButton.setBackground(SELECTED_COLOR); + domainsButton.setForeground(Color.BLACK); + resultType = SearchData.ResultType.ARTIFACT; + artifactType = ArtifactSearchData.ArtifactType.DOMAIN; + fileType = null; + documentFilterPanel.addPropertyChangeListener(listener); + validateDialog(); + pack(); + repaint(); + }//GEN-LAST:event_domainsButtonActionPerformed + @Override public void dispose() { setVisible(false); @@ -569,6 +652,7 @@ final class DiscoveryDialog extends javax.swing.JDialog { // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JButton documentsButton; + private javax.swing.JButton domainsButton; private javax.swing.JLabel errorLabel; private javax.swing.JComboBox groupByCombobox; private javax.swing.JComboBox groupSortingComboBox; @@ -583,7 +667,7 @@ final class DiscoveryDialog extends javax.swing.JDialog { * filters available. */ private class CasePropertyChangeListener implements PropertyChangeListener { - + @Override @SuppressWarnings("fallthrough") public void propertyChange(PropertyChangeEvent evt) { diff --git a/Core/src/org/sleuthkit/autopsy/discovery/DiscoveryEventUtils.java b/Core/src/org/sleuthkit/autopsy/discovery/DiscoveryEventUtils.java index 9fb97bc088..735c4ed2cf 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/DiscoveryEventUtils.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/DiscoveryEventUtils.java @@ -22,8 +22,10 @@ import com.google.common.eventbus.EventBus; import java.util.Collections; import java.util.List; import java.util.Map; +import org.sleuthkit.autopsy.discovery.ArtifactSearchData.ArtifactType; import org.sleuthkit.autopsy.discovery.FileSearch.GroupKey; import org.sleuthkit.autopsy.discovery.FileSearchData.FileType; +import org.sleuthkit.autopsy.discovery.SearchData.ResultType; import org.sleuthkit.datamodel.AbstractFile; /** @@ -54,15 +56,28 @@ final class DiscoveryEventUtils { */ static final class SearchStartedEvent { + private final ResultType resultType; private final FileType fileType; + private final ArtifactType artifactType; /** * Construct a new SearchStartedEvent * * @param type The type of file the search event is for. */ - SearchStartedEvent(FileType type) { - this.fileType = type; + SearchStartedEvent(ResultType resultType, FileType fileType, ArtifactType artifactType) { + this.resultType = resultType; + this.fileType = fileType; + this.artifactType = artifactType; + } + + /** + * Get the broad search type. + * + * @return The result type, either FILES, or ARTIFACTS. + */ + ResultType getResultType() { + return resultType; } /** @@ -70,9 +85,18 @@ final class DiscoveryEventUtils { * * @return The type of files being searched for. */ - FileType getType() { + FileType getFileType() { return fileType; } + + /** + * Get the type of artifact the search is being performed for. + * + * @return The type of artifacts being searched for. + */ + ArtifactType getArtifactType() { + return artifactType; + } } /** diff --git a/Core/src/org/sleuthkit/autopsy/discovery/DiscoveryTopComponent.java b/Core/src/org/sleuthkit/autopsy/discovery/DiscoveryTopComponent.java index caef97f838..85fa13c4f2 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/DiscoveryTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/DiscoveryTopComponent.java @@ -36,6 +36,7 @@ import org.openide.windows.RetainLocation; import org.openide.windows.TopComponent; import org.openide.windows.WindowManager; import org.sleuthkit.autopsy.coreutils.ThreadConfined; +import org.sleuthkit.autopsy.discovery.SearchData.ResultType; /** * Create a dialog for displaying the Discovery results. @@ -277,12 +278,19 @@ public final class DiscoveryTopComponent extends TopComponent { */ @Messages({"DiscoveryTopComponent.cancelButton.text=Cancel Search", "# {0} - searchType", - "DiscoveryTopComponent.searchInProgress.text=Performing search for results of type {0}. Please wait."}) + "DiscoveryTopComponent.searchInProgress.text=Performing search for results of type {0}. Please wait.", + "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); - progressMessageTextArea.setText(Bundle.DiscoveryTopComponent_searchInProgress_text(searchStartedEvent.getType().name())); + String text = Bundle.DiscoveryTopComponent_searchError_text(); + if (searchStartedEvent.getResultType() == ResultType.FILE) { + text = Bundle.DiscoveryTopComponent_searchInProgress_text(searchStartedEvent.getFileType().name()); + } else if (searchStartedEvent.getResultType() == ResultType.ARTIFACT) { + text = Bundle.DiscoveryTopComponent_searchInProgress_text(searchStartedEvent.getArtifactType().name()); + } + progressMessageTextArea.setText(text); } /** diff --git a/Core/src/org/sleuthkit/autopsy/discovery/DocumentFilterPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/DocumentFilterPanel.java index 015e14e2ab..c7a17ac917 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/DocumentFilterPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/DocumentFilterPanel.java @@ -103,4 +103,9 @@ final class DocumentFilterPanel extends AbstractFiltersPanel { return SearchData.ResultType.FILE; } + @Override + ArtifactSearchData.ArtifactType getArtifactType() { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + } diff --git a/Core/src/org/sleuthkit/autopsy/discovery/DomainFilterPanel.form b/Core/src/org/sleuthkit/autopsy/discovery/DomainFilterPanel.form index 4f9abb50dc..ae5df7bf5c 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/DomainFilterPanel.form +++ b/Core/src/org/sleuthkit/autopsy/discovery/DomainFilterPanel.form @@ -1,6 +1,11 @@ -
+ + + + + + @@ -11,18 +16,71 @@ + - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/discovery/DomainFilterPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/DomainFilterPanel.java index f25324f43f..580cf10ff5 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/DomainFilterPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/DomainFilterPanel.java @@ -1,10 +1,25 @@ /* - * 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; +import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository; + /** * * @author wschaefer @@ -18,7 +33,13 @@ public class DomainFilterPanel extends AbstractFiltersPanel { * Creates new form DomainFilterPanel */ public DomainFilterPanel() { + super(); initComponents(); + addFilter(new DataSourceFilterPanel(), false, null, 0); + addFilter(new ArtifactTypeFilterPanel(), false, null, 1); + addFilter(new DateFilterPanel(), false, null, 0); + addFilter(new DomainUniquenessFilterPanel(), false, null, 1); + addPanelsToScrollPane(domainFiltersSplitPane); } /** @@ -30,16 +51,37 @@ public class DomainFilterPanel extends AbstractFiltersPanel { // //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) + javax.swing.JScrollPane domainFiltersScrollPane = new javax.swing.JScrollPane(); + javax.swing.JPanel domainFiltersPanel = new javax.swing.JPanel(); + domainFiltersSplitPane = new javax.swing.JSplitPane(); + + setPreferredSize(new java.awt.Dimension(225, 70)); + setLayout(new java.awt.BorderLayout()); + + domainFiltersSplitPane.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(DomainFilterPanel.class, "DomainFilterPanel.domainFiltersSplitPane.border.title"))); // NOI18N + domainFiltersSplitPane.setResizeWeight(0.5); + domainFiltersSplitPane.setToolTipText(org.openide.util.NbBundle.getMessage(DomainFilterPanel.class, "DomainFilterPanel.domainFiltersSplitPane.toolTipText")); // NOI18N + + javax.swing.GroupLayout domainFiltersPanelLayout = new javax.swing.GroupLayout(domainFiltersPanel); + domainFiltersPanel.setLayout(domainFiltersPanelLayout); + domainFiltersPanelLayout.setHorizontalGroup( + domainFiltersPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(domainFiltersPanelLayout.createSequentialGroup() + .addGap(8, 8, 8) + .addComponent(domainFiltersSplitPane) + .addGap(8, 8, 8)) ); - layout.setVerticalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGap(0, 300, Short.MAX_VALUE) + domainFiltersPanelLayout.setVerticalGroup( + domainFiltersPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(domainFiltersPanelLayout.createSequentialGroup() + .addGap(8, 8, 8) + .addComponent(domainFiltersSplitPane) + .addGap(8, 8, 8)) ); + + domainFiltersScrollPane.setViewportView(domainFiltersPanel); + + add(domainFiltersScrollPane, java.awt.BorderLayout.CENTER); }// //GEN-END:initComponents @Override @@ -52,7 +94,13 @@ public class DomainFilterPanel extends AbstractFiltersPanel { return SearchData.ResultType.ARTIFACT; } + @Override + ArtifactSearchData.ArtifactType getArtifactType() { + return ARTIFACT_TYPE; + } + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JSplitPane domainFiltersSplitPane; // End of variables declaration//GEN-END:variables } diff --git a/Core/src/org/sleuthkit/autopsy/discovery/DomainUniquenessFilterPanel.form b/Core/src/org/sleuthkit/autopsy/discovery/DomainUniquenessFilterPanel.form new file mode 100644 index 0000000000..9e1ccd6039 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/discovery/DomainUniquenessFilterPanel.form @@ -0,0 +1,43 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/Core/src/org/sleuthkit/autopsy/discovery/DomainUniquenessFilterPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/DomainUniquenessFilterPanel.java new file mode 100644 index 0000000000..f0bf9a372c --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/discovery/DomainUniquenessFilterPanel.java @@ -0,0 +1,101 @@ +/* + * 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; + +import javax.swing.JCheckBox; +import javax.swing.JLabel; +import javax.swing.JList; + +/** + * + * @author wschaefer + */ +class DomainUniquenessFilterPanel extends AbstractDiscoveryFilterPanel { + + private static final long serialVersionUID = 1L; + + /** + * Creates new form DomainUniquenessFilterPanel + */ + DomainUniquenessFilterPanel() { + 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() { + + domainUniquenessCheckbox = new javax.swing.JCheckBox(); + domainUniqueScrollPane = new javax.swing.JScrollPane(); + + org.openide.awt.Mnemonics.setLocalizedText(domainUniquenessCheckbox, org.openide.util.NbBundle.getMessage(DomainUniquenessFilterPanel.class, "DomainUniquenessFilterPanel.domainUniquenessCheckbox.text")); // NOI18N + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(domainUniqueScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 207, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(domainUniqueScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 48, Short.MAX_VALUE) + ); + }// //GEN-END:initComponents + + @Override + void configurePanel(boolean selected, int[] indicesSelected) { + domainUniquenessCheckbox.setSelected(selected); + } + + @Override + JCheckBox getCheckbox() { + return domainUniquenessCheckbox; + } + + @Override + JList getList() { + return null; + } + + @Override + JLabel getAdditionalLabel() { + return null; + } + + @Override + String checkForError() { + return "Domain search is not implemented."; + } + + @Override + AbstractFilter getFilter() { + return null; + } + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JScrollPane domainUniqueScrollPane; + private javax.swing.JCheckBox domainUniquenessCheckbox; + // End of variables declaration//GEN-END:variables +} diff --git a/Core/src/org/sleuthkit/autopsy/discovery/GroupListPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/GroupListPanel.java index 2fa91c2380..caaacd1d30 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/GroupListPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/GroupListPanel.java @@ -37,7 +37,7 @@ import org.sleuthkit.autopsy.discovery.FileSearchData.FileType; final class GroupListPanel extends javax.swing.JPanel { private static final long serialVersionUID = 1L; - private FileType resultType = null; + private FileType fileType = null; private Map groupMap = null; private List searchfilters; private FileSearch.AttributeType groupingAttribute; @@ -59,7 +59,7 @@ final class GroupListPanel extends javax.swing.JPanel { */ @Subscribe void handleSearchStartedEvent(DiscoveryEventUtils.SearchStartedEvent searchStartedEvent) { - resultType = searchStartedEvent.getType(); + fileType = searchStartedEvent.getFileType(); groupKeyList.setListData(new GroupKey[0]); } @@ -170,7 +170,7 @@ final class GroupListPanel extends javax.swing.JPanel { if (selectedGroup.equals(groupKey)) { selectedGroupKey = groupKey; DiscoveryEventUtils.getDiscoveryEventBus().post(new DiscoveryEventUtils.GroupSelectedEvent( - searchfilters, groupingAttribute, groupSort, fileSortMethod, selectedGroupKey, groupMap.get(selectedGroupKey), resultType)); + searchfilters, groupingAttribute, groupSort, fileSortMethod, selectedGroupKey, groupMap.get(selectedGroupKey), fileType)); break; } } diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ImageFilterPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ImageFilterPanel.java index fc22e7af8f..f59d0da648 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ImageFilterPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ImageFilterPanel.java @@ -108,4 +108,9 @@ final class ImageFilterPanel extends AbstractFiltersPanel { SearchData.ResultType getResultType() { return SearchData.ResultType.FILE; } + + @Override + ArtifactSearchData.ArtifactType getArtifactType() { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } } diff --git a/Core/src/org/sleuthkit/autopsy/discovery/VideoFilterPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/VideoFilterPanel.java index 3cb69f0ff4..e39519c0ee 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/VideoFilterPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/VideoFilterPanel.java @@ -110,4 +110,9 @@ final class VideoFilterPanel extends AbstractFiltersPanel { return SearchData.ResultType.FILE; } + @Override + ArtifactSearchData.ArtifactType getArtifactType() { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + }