diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/AllDataSourcesEamDbCommonFilesAlgorithm.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/AllDataSourcesEamDbCommonFilesAlgorithm.java index ea52971f20..0700d4ae9e 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/AllDataSourcesEamDbCommonFilesAlgorithm.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/AllDataSourcesEamDbCommonFilesAlgorithm.java @@ -19,8 +19,22 @@ */ package org.sleuthkit.autopsy.commonfilesearch; +import java.sql.SQLException; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; import java.util.Map; +import java.util.logging.Level; +import java.util.stream.Collectors; +import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; +import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeCommonInstance; +import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationCase; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException; import static org.sleuthkit.autopsy.commonfilesearch.CommonFilesMetadataBuilder.SELECT_PREFIX; +import static org.sleuthkit.autopsy.timeline.datamodel.eventtype.ArtifactEventType.LOGGER; +import org.sleuthkit.datamodel.HashUtility; +import org.sleuthkit.datamodel.TskCoreException; /** @@ -30,6 +44,8 @@ public class AllDataSourcesEamDbCommonFilesAlgorithm extends CommonFilesMetadat private static final String WHERE_CLAUSE = "%s md5 in (select md5 from tsk_files where (known != 1 OR known IS NULL)%s GROUP BY md5) order by md5"; //NON-NLS + private EamDb dbManager; + /** * Implements the algorithm for getting common files across all data * sources. @@ -38,9 +54,78 @@ public class AllDataSourcesEamDbCommonFilesAlgorithm extends CommonFilesMetadat * @param filterByMediaMimeType match only on files whose mime types can be broadly categorized as media types * @param filterByDocMimeType match only on files whose mime types can be broadly categorized as document types */ - AllDataSourcesEamDbCommonFilesAlgorithm(Map dataSourceIdMap, boolean filterByMediaMimeType, boolean filterByDocMimeType) { + AllDataSourcesEamDbCommonFilesAlgorithm(Map dataSourceIdMap, boolean filterByMediaMimeType, boolean filterByDocMimeType) throws EamDbException { super(dataSourceIdMap, filterByMediaMimeType, filterByDocMimeType); + dbManager = EamDb.getInstance(); + } + + public CommonFilesMetadata findEamDbCommonFiles() throws TskCoreException, NoCurrentCaseException, SQLException, EamDbException { + return this.findEamDbCommonFiles(null); + } + + public CommonFilesMetadata findEamDbCommonFiles(int correlationCaseId) throws TskCoreException, NoCurrentCaseException, SQLException, EamDbException, Exception { + + CorrelationCase cCase = this.getCorrelationCaseFromId(correlationCaseId); + + return this.findEamDbCommonFiles(cCase); + } + + /** + * TODO Refactor, abstract shared code above, call this method via new AllDataSourcesEamDbCommonFilesAlgorithm Class + * @param correlationCase Optionally null, otherwise a case, or could be a CR case ID + * @return + * @throws TskCoreException + * @throws NoCurrentCaseException + * @throws SQLException + * @throws EamDbException + */ + public CommonFilesMetadata findEamDbCommonFiles(CorrelationCase correlationCase) throws TskCoreException, NoCurrentCaseException, SQLException, EamDbException { + CommonFilesMetadata metaData = this.findCommonFiles(); + Map commonFiles = metaData.getMetadata(); + List values = Arrays.asList((String[]) commonFiles.keySet().toArray()); + + Map interCaseCommonFiles = metaData.getMetadata(); + try { + + Collection artifactInstances = dbManager.getArtifactInstancesByCaseValues(correlationCase, values).stream() + .collect(Collectors.toList()); + + + for (CorrelationAttributeCommonInstance instance : artifactInstances) { + //Long objectId = 1L; //TODO, need to retrieve ALL (even count < 2) AbstractFiles from this case to us for objectId for CR matches; + String md5 = instance.getValue(); + String dataSource = instance.getCorrelationDataSource().getName(); + + if (md5 == null || HashUtility.isNoDataMd5(md5)) { + continue; + } + //Builds a 3rd list which contains instances which are in commonFiles map, uses current case objectId + if (commonFiles.containsKey(md5)) { + // TODO sloppy, but we don't *have* all the information for the rows in the CR, so what do we do? + Long objectId = commonFiles.get(md5).getMetadata().iterator().next().getObjectId(); + if(interCaseCommonFiles.containsKey(md5)) { + //Add to intercase metaData + final Md5Metadata md5Metadata = interCaseCommonFiles.get(md5); + md5Metadata.addFileInstanceMetadata(new FileInstanceMetadata(objectId, dataSource)); + + } else { + // Create new intercase metadata + final Md5Metadata md5Metadata = commonFiles.get(md5); + md5Metadata.addFileInstanceMetadata(new FileInstanceMetadata(objectId, dataSource)); + interCaseCommonFiles.put(md5, md5Metadata); + } + } else { + // TODO This should never happen. All current case files with potential matches are in comonFiles Map. + } + } + + } catch (EamDbException ex) { + LOGGER.log(Level.SEVERE, "Error getting artifact instances from database.", ex); // NON-NLS + } + // Builds intercase-only matches metadata + return new CommonFilesMetadata(interCaseCommonFiles); + } @Override @@ -55,4 +140,14 @@ public class AllDataSourcesEamDbCommonFilesAlgorithm extends CommonFilesMetadat final String titleTemplate = Bundle.CommonFilesMetadataBuilder_buildTabTitle_titleEamDb(); return String.format(titleTemplate, new Object[]{buildCategorySelectionString}); } + + private CorrelationCase getCorrelationCaseFromId(int correlationCaseId) throws EamDbException, Exception { + //TODO is there a better way??? + for(CorrelationCase cCase : this.dbManager.getCases()){ + if(cCase.getID() == correlationCaseId){ + return cCase; + } + } + throw new Exception("Cannont locate case."); + } } diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/Bundle.properties b/Core/src/org/sleuthkit/autopsy/commonfilesearch/Bundle.properties index f3ac99e12d..4e44ebd8d3 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/Bundle.properties @@ -1,21 +1,23 @@ CommonFilesPanel.searchButton.text=Search CommonFilesPanel.cancelButton.text=Cancel CommonFilesPanel.cancelButton.actionCommand=Cancel -CommonFilesPanel.selectedFileCategoriesButton.text=Match on the following file categories: +CommonFilesPanel.selectedFileCategoriesButton.text=Only the selected file types: CommonFilesPanel.selectedFileCategoriesButton.toolTipText=Select from the options below... CommonFilesPanel.pictureVideoCheckbox.text=Pictures and Videos CommonFilesPanel.documentsCheckbox.text=Documents CommonFilesPanel.allFileCategoriesRadioButton.toolTipText=No filtering applied to results... -CommonFilesPanel.allFileCategoriesRadioButton.text=Match on all file types +CommonFilesPanel.allFileCategoriesRadioButton.text=All file types CommonFilesPanel.text=Indicate which data sources to consider while searching for duplicates: -CommonFilesPanel.categoriesLabel.text=Indicate which file types to include in results: +CommonFilesPanel.categoriesLabel.text=File Types To Include: CommonFilesPanel.errorText.text=In order to search, you must select a file category. -CommonFilesPanel.commonFilesSearchLabel1.text=Find Common Files. CommonFilesPanel.jRadioButton1.text=jRadioButton1 -CommonFilesPanel.jRadioButton2.text=Correlate amongst external cases (compares files in current case with Central Repo) +CommonFilesPanel.jRadioButton2.text=With previous cases in the Central Repository CommonFilesPanel.intraCaseRadio.label=Correlate within current case only CommonFilesPanel.interCaseRadio.label=Correlate amongst all known cases (uses Central Repo) IntraCasePanel.allDataSourcesRadioButton.text=Matches may be from any data source IntraCasePanel.withinDataSourceRadioButton.text=At least one match must appear in the data source selected below: -InterCasePanel.anCentralRepoCaseRadio.text=Matches may be from any Central Repo case InterCasePanel.specificCentralRepoCaseRadio.text=Matches must be from the following Central Repo case: +InterCasePanel.anyCentralRepoCaseRadio.text=Matches may be from any Central Repo case +CommonFilesPanel.commonFilesSearchLabel1.text=Find common files to correlate data soures or cases. +CommonFilesPanel.commonFilesSearchLabel2.text=Scope of Search +CommonFilesPanel.intraCaseRadio.text=Within current case diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesMetadataBuilder.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesMetadataBuilder.java index 47f477d82a..7e031995e8 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesMetadataBuilder.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesMetadataBuilder.java @@ -210,64 +210,6 @@ abstract class CommonFilesMetadataBuilder { return new CommonFilesMetadata(commonFiles); } - - /** - * TODO Refactor, abstract shared code above, call this method via new AllDataSourcesEamDbCommonFilesAlgorithm Class - * @param correlationCase Optionally null, otherwise a case, or could be a CR case ID - * @return - * @throws TskCoreException - * @throws NoCurrentCaseException - * @throws SQLException - * @throws EamDbException - */ - public CommonFilesMetadata findEamDbCommonFiles(CorrelationCase correlationCase) throws TskCoreException, NoCurrentCaseException, SQLException, EamDbException { - CommonFilesMetadata metaData = this.findCommonFiles(); - Map commonFiles = metaData.getMetadata(); - List values = Arrays.asList((String[]) commonFiles.keySet().toArray()); - - Map interCaseCommonFiles = metaData.getMetadata(); - try { - - EamDb dbManager = EamDb.getInstance(); - Collection artifactInstances = dbManager.getArtifactInstancesByCaseValues(correlationCase, values).stream() - .collect(Collectors.toList()); - - - for (CorrelationAttributeCommonInstance instance : artifactInstances) { - //Long objectId = 1L; //TODO, need to retrieve ALL (even count < 2) AbstractFiles from this case to us for objectId for CR matches; - String md5 = instance.getValue(); - String dataSource = instance.getCorrelationDataSource().getName(); - - if (md5 == null || HashUtility.isNoDataMd5(md5)) { - continue; - } - //Builds a 3rd list which contains instances which are in commonFiles map, uses current case objectId - if (commonFiles.containsKey(md5)) { - // TODO sloppy, but we don't *have* all the information for the rows in the CR, so what do we do? - Long objectId = commonFiles.get(md5).getMetadata().iterator().next().getObjectId(); - if(interCaseCommonFiles.containsKey(md5)) { - //Add to intercase metaData - final Md5Metadata md5Metadata = interCaseCommonFiles.get(md5); - md5Metadata.addFileInstanceMetadata(new FileInstanceMetadata(objectId, dataSource)); - - } else { - // Create new intercase metadata - final Md5Metadata md5Metadata = commonFiles.get(md5); - md5Metadata.addFileInstanceMetadata(new FileInstanceMetadata(objectId, dataSource)); - interCaseCommonFiles.put(md5, md5Metadata); - } - } else { - // TODO This should never happen. All current case files with potential matches are in comonFiles Map. - } - } - - } catch (EamDbException ex) { - LOGGER.log(Level.SEVERE, "Error getting artifact instances from database.", ex); // NON-NLS - } - // Builds intercase-only matches metadata - return new CommonFilesMetadata(interCaseCommonFiles); - - } /** * Should be used by subclasses, in their diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesPanel.form b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesPanel.form index b0f7e26095..d32724abe2 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesPanel.form +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesPanel.form @@ -23,39 +23,39 @@ - + - - + - - - - - - + - + + + + + + + + + + + + + + + - - - - - - - - @@ -65,39 +65,42 @@ + + - - + + - - - - - - - - - - - - - + + + + + + + - + + + + + + + + @@ -145,7 +148,6 @@ - @@ -210,8 +212,9 @@ - - + + + @@ -223,7 +226,6 @@ - @@ -236,13 +238,6 @@ - - - - - - - @@ -250,6 +245,13 @@ + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesPanel.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesPanel.java index 9fae239a88..3700d9450b 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesPanel.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesPanel.java @@ -40,6 +40,7 @@ import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationCase; import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationDataSource; import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException; import org.sleuthkit.autopsy.corecomponentinterfaces.DataResultViewer; import org.sleuthkit.autopsy.corecomponents.DataResultTopComponent; import org.sleuthkit.autopsy.corecomponents.DataResultViewerTable; @@ -76,14 +77,34 @@ public final class CommonFilesPanel extends javax.swing.JPanel { "CommonFilesPanel.exception=Unexpected Exception loading DataSources."}) public CommonFilesPanel() { initComponents(); - + this.errorText.setVisible(false); - + this.intraCasePanel.setParent(this); this.interCasePanel.setParent(this); - + this.setupDataSources(); - this.setupCases(); + + if (CommonFilesPanel.isEamDbAvailable()) { + this.setupCases(); + } else { + this.disableIntercaseSearch(); + } + } + + private void disableIntercaseSearch() { + this.intraCaseRadio.setSelected(true); + this.interCaseRadio.setEnabled(false); + } + + public static boolean isEamDbAvailable() { + boolean isEamDbAvailable = false; + try { + isEamDbAvailable = EamDb.isEnabled() && !EamDb.getInstance().getCases().isEmpty(); + } catch (EamDbException ex) { + LOGGER.log(Level.WARNING, "Error accessing EamDb", ex); + } + return isEamDbAvailable; } @NbBundle.Messages({ @@ -113,25 +134,23 @@ public final class CommonFilesPanel extends javax.swing.JPanel { this.tabTitle = String.format(CommonFilesPanel_search_results_titleSingle, dataSourceName); } - private Long determineDataSourceId() { - Long selectedObjId = CommonFilesPanel.NO_DATA_SOURCE_SELECTED; - if (CommonFilesPanel.this.singleDataSource) { - for (Entry dataSource : CommonFilesPanel.this.intraCasePanel.getDataSourceMap().entrySet()) { - if (dataSource.getValue().equals(CommonFilesPanel.this.selectedDataSource)) { - selectedObjId = dataSource.getKey(); - break; - } - } - } - return selectedObjId; + private void setTitleForAllCases() { + + } + + private void setTitleForSingleCase() { + } @Override @SuppressWarnings({"BoxedValueEquality", "NumberEquality"}) - protected CommonFilesMetadata doInBackground() throws TskCoreException, NoCurrentCaseException, SQLException { - Long dataSourceId = determineDataSourceId(); + protected CommonFilesMetadata doInBackground() throws TskCoreException, NoCurrentCaseException, SQLException, EamDbException { + Long dataSourceId = CommonFilesPanel.this.intraCasePanel.getSelectedDataSourceId(); + Integer caseId = CommonFilesPanel.this.interCasePanel.getSelectedCaseId(); CommonFilesMetadataBuilder builder; + CommonFilesMetadata metadata; + boolean filterByMedia = false; boolean filterByDocuments = false; if (selectedFileCategoriesButton.isSelected()) { @@ -142,23 +161,31 @@ public final class CommonFilesPanel extends javax.swing.JPanel { filterByDocuments = true; } } - if (dataSourceId == CommonFilesPanel.NO_DATA_SOURCE_SELECTED) { - builder = new AllDataSourcesCommonFilesAlgorithm(CommonFilesPanel.this.intraCasePanel.getDataSourceMap(), filterByMedia, filterByDocuments); - setTitleForAllDataSources(); + if (CommonFilesPanel.this.interCaseRadio.isSelected()) { + + builder = new AllDataSourcesEamDbCommonFilesAlgorithm(CommonFilesPanel.this.intraCasePanel.getDataSourceMap(), filterByMedia, filterByDocuments); + + if(caseId == InterCasePanel.NO_CASE_SELECTED){ + metadata = ((AllDataSourcesEamDbCommonFilesAlgorithm)builder).findEamDbCommonFiles(); + } else { + metadata = ((AllDataSourcesEamDbCommonFilesAlgorithm)builder).findEamDbCommonFiles(CommonFilesPanel.this.interCasePanel.getSelectedCaseId()); + } } else { - builder = new SingleDataSource(dataSourceId, CommonFilesPanel.this.intraCasePanel.getDataSourceMap(), filterByMedia, filterByDocuments); + if (dataSourceId == CommonFilesPanel.NO_DATA_SOURCE_SELECTED) { + builder = new AllDataSourcesCommonFilesAlgorithm(CommonFilesPanel.this.intraCasePanel.getDataSourceMap(), filterByMedia, filterByDocuments); - setTitleForSingleSource(dataSourceId); - }// else if(false) { - // TODO, is CR cases, add option chosen CorrelationCase ID lookup - // builder = new AllDataSourcesEamDbCommonFilesAlgorithm(CommonFilesPanel.this.dataSourceMap, filterByMedia, filterByDocuments); - //} + setTitleForAllDataSources(); + } else { + builder = new SingleDataSource(dataSourceId, CommonFilesPanel.this.intraCasePanel.getDataSourceMap(), filterByMedia, filterByDocuments); + setTitleForSingleSource(dataSourceId); + } + metadata = builder.findCommonFiles(); + } + this.tabTitle = builder.buildTabTitle(); - CommonFilesMetadata metadata = builder.findCommonFiles(); - return metadata; } @@ -176,10 +203,10 @@ public final class CommonFilesPanel extends javax.swing.JPanel { TableFilterNode tableFilterWithDescendantsNode = new TableFilterNode(dataResultFilterNode); DataResultViewerTable table = new DataResultViewerTable(); - + Collection viewers = new ArrayList<>(1); viewers.add(table); - + DataResultTopComponent.createInstance(tabTitle, pathText, tableFilterWithDescendantsNode, metadata.size(), viewers); } catch (InterruptedException ex) { @@ -206,17 +233,18 @@ public final class CommonFilesPanel extends javax.swing.JPanel { } }.execute(); } - + /** * Sets up the data sources dropdown and returns the data sources map for * future usage. * - * @return a mapping of data correlationCase ids to data correlationCase names + * @return a mapping of data correlationCase ids to data correlationCase + * names */ @NbBundle.Messages({ "CommonFilesPanel.setupDataSources.done.tskCoreException=Unable to run query against DB.", "CommonFilesPanel.setupDataSources.done.noCurrentCaseException=Unable to open case file.", - "CommonFilesPanel.setupDataSources.done.exception=Unexpected exception building data sources map.", + "CommonFilesPanel.setupDataSources.done.exception=Unexpected exception loading data sources.", "CommonFilesPanel.setupDataSources.done.interupted=Something went wrong building the Common Files Search dialog box.", "CommonFilesPanel.setupDataSources.done.sqlException=Unable to query db for data sources.", "CommonFilesPanel.setupDataSources.updateUi.noDataSources=No data sources were found."}) @@ -229,7 +257,7 @@ public final class CommonFilesPanel extends javax.swing.JPanel { private static final String SELECT_DATA_SOURCES_IMAGE = "select obj_id, name from tsk_image_names where obj_id in (SELECT obj_id FROM tsk_objects WHERE obj_id in (select obj_id from data_source_info))"; private void updateUi() { - + final Map dataSourceMap = CommonFilesPanel.this.intraCasePanel.getDataSourceMap(); String[] dataSourcesNames = new String[dataSourceMap.size()]; @@ -273,7 +301,7 @@ public final class CommonFilesPanel extends javax.swing.JPanel { try ( SleuthkitCase.CaseDbQuery query = tskDb.executeQuery(SELECT_DATA_SOURCES_IMAGE); ResultSet resultSet = query.getResultSet()) { - + while (resultSet.next()) { Long objectId = resultSet.getLong(1); String dataSourceName = resultSet.getString(2); @@ -304,7 +332,6 @@ public final class CommonFilesPanel extends javax.swing.JPanel { try { CommonFilesPanel.this.intraCasePanel.setDataSourceMap(this.get()); - updateUi(); } catch (InterruptedException ex) { @@ -334,56 +361,54 @@ public final class CommonFilesPanel extends javax.swing.JPanel { @NbBundle.Messages({ "CommonFilesPanel.setupCases.done.interruptedException=Something went wrong building the Common Files Search dialog box.", - "CommonFilesPanel.setupCases.done.exeutionException=Unexpected exception building data sources map."}) - private void setupCases(){ - - new SwingWorker, Void>(){ - - private void updateUi(){ - + "CommonFilesPanel.setupCases.done.exeutionException=Unexpected exception loading cases."}) + private void setupCases() { + + new SwingWorker, Void>() { + + private void updateUi() { + final Map caseMap = CommonFilesPanel.this.interCasePanel.getCaseMap(); - + String[] caseNames = new String[caseMap.size()]; - - if(caseNames.length > 0){ + + if (caseNames.length > 0) { caseNames = caseMap.values().toArray(caseNames); CommonFilesPanel.this.interCasePanel.setCaseList(new DataSourceComboBoxModel(caseNames)); - + boolean multipleCases = this.centralRepoHasMultipleCases(); CommonFilesPanel.this.interCasePanel.rigForMultipleCases(multipleCases); - - //TODO need something more specific - //InterCasePanel.this.parent.setSearchButtonEnabled(true); + } else { - //TODO need something more specific + CommonFilesPanel.this.disableIntercaseSearch(); } - } - + private Map mapDataSources(List cases) { Map casemap = new HashMap<>(); - - for (CorrelationCase correlationCase : cases){ + + for (CorrelationCase correlationCase : cases) { casemap.put(correlationCase.getID(), correlationCase.getDisplayName()); } - + return casemap; } - + @Override protected Map doInBackground() throws Exception { - + List dataSources = EamDb.getInstance().getCases(); - + Map caseMap = mapDataSources(dataSources); - + return caseMap; } - + @Override - protected void done(){ - try{ - CommonFilesPanel.this.interCasePanel.setCaseMap(this.get()); + protected void done() { + try { + Map cases = this.get(); + CommonFilesPanel.this.interCasePanel.setCaseMap(cases); this.updateUi(); } catch (InterruptedException ex) { LOGGER.log(Level.SEVERE, "Interrupted while building Common Files Search dialog.", ex); @@ -397,9 +422,10 @@ public final class CommonFilesPanel extends javax.swing.JPanel { private boolean centralRepoHasMultipleCases() { return CommonFilesPanel.this.interCasePanel.centralRepoHasMultipleCases(); } - + }.execute(); } + /** * 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 @@ -411,6 +437,7 @@ public final class CommonFilesPanel extends javax.swing.JPanel { fileTypeFilterButtonGroup = new javax.swing.ButtonGroup(); interIntraButtonGroup = new javax.swing.ButtonGroup(); + commonFilesSearchLabel2 = new javax.swing.JLabel(); searchButton = new javax.swing.JButton(); cancelButton = new javax.swing.JButton(); allFileCategoriesRadioButton = new javax.swing.JRadioButton(); @@ -423,8 +450,11 @@ public final class CommonFilesPanel extends javax.swing.JPanel { intraCaseRadio = new javax.swing.JRadioButton(); interCaseRadio = new javax.swing.JRadioButton(); layoutPanel = new java.awt.Panel(); - interCasePanel = new org.sleuthkit.autopsy.commonfilesearch.InterCasePanel(); intraCasePanel = new org.sleuthkit.autopsy.commonfilesearch.IntraCasePanel(); + interCasePanel = new org.sleuthkit.autopsy.commonfilesearch.InterCasePanel(); + + org.openide.awt.Mnemonics.setLocalizedText(commonFilesSearchLabel2, org.openide.util.NbBundle.getMessage(CommonFilesPanel.class, "CommonFilesPanel.commonFilesSearchLabel2.text")); // NOI18N + commonFilesSearchLabel2.setFocusable(false); org.openide.awt.Mnemonics.setLocalizedText(searchButton, org.openide.util.NbBundle.getMessage(CommonFilesPanel.class, "CommonFilesPanel.searchButton.text")); // NOI18N searchButton.setEnabled(false); @@ -454,7 +484,6 @@ public final class CommonFilesPanel extends javax.swing.JPanel { }); fileTypeFilterButtonGroup.add(selectedFileCategoriesButton); - selectedFileCategoriesButton.setSelected(true); org.openide.awt.Mnemonics.setLocalizedText(selectedFileCategoriesButton, org.openide.util.NbBundle.getMessage(CommonFilesPanel.class, "CommonFilesPanel.selectedFileCategoriesButton.text")); // NOI18N selectedFileCategoriesButton.setToolTipText(org.openide.util.NbBundle.getMessage(CommonFilesPanel.class, "CommonFilesPanel.selectedFileCategoriesButton.toolTipText")); // NOI18N selectedFileCategoriesButton.addActionListener(new java.awt.event.ActionListener() { @@ -489,7 +518,8 @@ public final class CommonFilesPanel extends javax.swing.JPanel { commonFilesSearchLabel1.setFocusable(false); interIntraButtonGroup.add(intraCaseRadio); - intraCaseRadio.setLabel(org.openide.util.NbBundle.getMessage(CommonFilesPanel.class, "CommonFilesPanel.intraCaseRadio.label")); // NOI18N + intraCaseRadio.setSelected(true); + org.openide.awt.Mnemonics.setLocalizedText(intraCaseRadio, org.openide.util.NbBundle.getMessage(CommonFilesPanel.class, "CommonFilesPanel.intraCaseRadio.text")); // NOI18N intraCaseRadio.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { intraCaseRadioActionPerformed(evt); @@ -497,7 +527,6 @@ public final class CommonFilesPanel extends javax.swing.JPanel { }); interIntraButtonGroup.add(interCaseRadio); - interCaseRadio.setSelected(true); org.openide.awt.Mnemonics.setLocalizedText(interCaseRadio, org.openide.util.NbBundle.getMessage(CommonFilesPanel.class, "CommonFilesPanel.jRadioButton2.text")); // NOI18N interCaseRadio.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { @@ -506,40 +535,40 @@ public final class CommonFilesPanel extends javax.swing.JPanel { }); layoutPanel.setLayout(new java.awt.CardLayout()); - layoutPanel.add(interCasePanel, "card2"); layoutPanel.add(intraCasePanel, "card3"); + layoutPanel.add(interCasePanel, "card2"); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() - .addContainerGap() + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(commonFilesSearchLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(categoriesLabel) - .addComponent(intraCaseRadio) - .addComponent(interCaseRadio) - .addGroup(layout.createSequentialGroup() - .addGap(10, 10, 10) - .addComponent(layoutPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 364, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(commonFilesSearchLabel2) .addGroup(layout.createSequentialGroup() .addGap(6, 6, 6) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(allFileCategoriesRadioButton) - .addComponent(selectedFileCategoriesButton) .addGroup(layout.createSequentialGroup() .addGap(21, 21, 21) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(pictureVideoCheckbox) - .addComponent(documentsCheckbox))))) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() - .addComponent(errorText) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(searchButton) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(cancelButton))) - .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addComponent(documentsCheckbox) + .addComponent(pictureVideoCheckbox))) + .addComponent(allFileCategoriesRadioButton) + .addComponent(selectedFileCategoriesButton) + .addComponent(interCaseRadio) + .addComponent(intraCaseRadio) + .addGroup(layout.createSequentialGroup() + .addGap(10, 10, 10) + .addComponent(layoutPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGroup(layout.createSequentialGroup() + .addComponent(errorText) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(searchButton) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(cancelButton)))))) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) @@ -547,30 +576,28 @@ public final class CommonFilesPanel extends javax.swing.JPanel { .addContainerGap() .addComponent(commonFilesSearchLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addGap(18, 18, 18) + .addComponent(commonFilesSearchLabel2) + .addGap(2, 2, 2) .addComponent(intraCaseRadio) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(interCaseRadio) .addGap(0, 0, 0) - .addComponent(layoutPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(layoutPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, 0) .addComponent(categoriesLabel) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addGap(80, 80, 80) - .addComponent(allFileCategoriesRadioButton)) - .addGroup(layout.createSequentialGroup() - .addComponent(selectedFileCategoriesButton) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(pictureVideoCheckbox) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(documentsCheckbox))) + .addComponent(selectedFileCategoriesButton) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(pictureVideoCheckbox) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(documentsCheckbox) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(allFileCategoriesRadioButton) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(cancelButton) .addComponent(searchButton) - .addComponent(errorText)) - .addContainerGap()) + .addComponent(errorText))) ); }// //GEN-END:initComponents @@ -601,13 +628,37 @@ public final class CommonFilesPanel extends javax.swing.JPanel { }//GEN-LAST:event_documentsCheckboxActionPerformed private void intraCaseRadioActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_intraCaseRadioActionPerformed - ((java.awt.CardLayout)this.layoutPanel.getLayout()).last(this.layoutPanel); + ((java.awt.CardLayout) this.layoutPanel.getLayout()).first(this.layoutPanel); + handleIntraCaseSearchCriteriaChanged(); }//GEN-LAST:event_intraCaseRadioActionPerformed + public void handleIntraCaseSearchCriteriaChanged() { + if (this.areIntraCaseSearchCriteriaMet()) { + this.searchButton.setEnabled(true); + this.hideErrorMessages(); + } else { + this.searchButton.setEnabled(false); + this.hideErrorMessages(); + this.showIntraCaseErrorMessage(); + } + } + private void interCaseRadioActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_interCaseRadioActionPerformed - ((java.awt.CardLayout)this.layoutPanel.getLayout()).first(this.layoutPanel); + ((java.awt.CardLayout) this.layoutPanel.getLayout()).last(this.layoutPanel); + handleInterCaseSearchCriteriaChanged(); }//GEN-LAST:event_interCaseRadioActionPerformed + public void handleInterCaseSearchCriteriaChanged() { + if (this.areInterCaseSearchCriteriaMet()) { + this.searchButton.setEnabled(true); + this.hideErrorMessages(); + } else { + this.searchButton.setEnabled(false); + this.hideErrorMessages(); + this.showInterCaseErrorMessage(); + } + } + private void toggleErrorTextAndSearchBox() { if (!this.pictureVideoCheckbox.isSelected() && !this.documentsCheckbox.isSelected() && !this.allFileCategoriesRadioButton.isSelected()) { this.searchButton.setEnabled(false); @@ -636,7 +687,7 @@ public final class CommonFilesPanel extends javax.swing.JPanel { this.pictureVideoCheckbox.setEnabled(true); this.documentsCheckbox.setEnabled(true); - + this.toggleErrorTextAndSearchBox(); } } @@ -646,6 +697,7 @@ public final class CommonFilesPanel extends javax.swing.JPanel { private javax.swing.JButton cancelButton; private javax.swing.JLabel categoriesLabel; private javax.swing.JLabel commonFilesSearchLabel1; + private javax.swing.JLabel commonFilesSearchLabel2; private javax.swing.JCheckBox documentsCheckbox; private javax.swing.JLabel errorText; private javax.swing.ButtonGroup fileTypeFilterButtonGroup; @@ -663,4 +715,26 @@ public final class CommonFilesPanel extends javax.swing.JPanel { void setSearchButtonEnabled(boolean enabled) { this.searchButton.setEnabled(enabled); } + + private boolean areIntraCaseSearchCriteriaMet() { + return this.intraCasePanel.areSearchCriteriaMet(); + } + + private boolean areInterCaseSearchCriteriaMet() { + return this.interCasePanel.areSearchCriteriaMet(); + } + + private void hideErrorMessages() { + this.errorText.setVisible(false); + } + + private void showIntraCaseErrorMessage() { + this.errorText.setText(this.intraCasePanel.getErrorMessage()); + this.errorText.setVisible(true); + } + + private void showInterCaseErrorMessage() { + this.errorText.setText(this.interCasePanel.getErrorMessage()); + this.errorText.setVisible(true); + } } diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesSearchAction.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesSearchAction.java index e470fd16bc..bc5bc6514d 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesSearchAction.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesSearchAction.java @@ -19,17 +19,25 @@ package org.sleuthkit.autopsy.commonfilesearch; import java.awt.event.ActionEvent; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.openide.util.Exceptions; import org.openide.util.HelpCtx; import org.openide.util.NbBundle; import org.openide.util.actions.CallableSystemAction; import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException; import org.sleuthkit.autopsy.core.Installer; +import org.sleuthkit.datamodel.TskCoreException; /** * Encapsulates a menu action which triggers the common files search dialog. */ final public class CommonFilesSearchAction extends CallableSystemAction { + private static final Logger LOGGER = Logger.getLogger(CommonFilesSearchAction.class.getName()); + private static CommonFilesSearchAction instance = null; private static final long serialVersionUID = 1L; @@ -40,7 +48,16 @@ final public class CommonFilesSearchAction extends CallableSystemAction { @Override public boolean isEnabled(){ - return super.isEnabled() && Case.isCaseOpen() && Installer.isJavaFxInited(); + boolean isEamDbAvailable = CommonFilesPanel.isEamDbAvailable(); + + boolean isMultiDataSourceCase = false; + try { + isMultiDataSourceCase = Case.isCaseOpen() && !Case.getCurrentCase().getDataSources().isEmpty(); + } catch (TskCoreException ex) { + Exceptions.printStackTrace(ex); + } + + return super.isEnabled() && Installer.isJavaFxInited() && (isMultiDataSourceCase || isEamDbAvailable); } public static synchronized CommonFilesSearchAction getDefault() { diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/InterCasePanel.form b/Core/src/org/sleuthkit/autopsy/commonfilesearch/InterCasePanel.form index f8060a7df3..8c62356803 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/InterCasePanel.form +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/InterCasePanel.form @@ -20,15 +20,15 @@ - + - - - - + + + + @@ -37,30 +37,28 @@ - - + - - + - + - + diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/InterCasePanel.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/InterCasePanel.java index 667fa1ba56..fefbfb8908 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/InterCasePanel.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/InterCasePanel.java @@ -22,6 +22,7 @@ package org.sleuthkit.autopsy.commonfilesearch; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.concurrent.ExecutionException; import java.util.logging.Level; import javax.swing.ComboBoxModel; @@ -40,29 +41,29 @@ import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; public class InterCasePanel extends javax.swing.JPanel { private static final long serialVersionUID = 1L; + static final int NO_CASE_SELECTED = -1; private static final Logger LOGGER = Logger.getLogger(InterCasePanel.class.getName()); - private String selectedCase; - private boolean singleCase; - private ComboBoxModel casesList = new DataSourceComboBoxModel(); private Map caseMap; private CommonFilesPanel parent; + private String errorMessage; + /** * Creates new form InterCasePanel */ public InterCasePanel() { initComponents(); + this.errorMessage = ""; } private void specificCaseSelected(boolean selected) { this.specificCentralRepoCaseRadio.setEnabled(selected); if (this.specificCentralRepoCaseRadio.isEnabled()) { this.caseComboBox.setSelectedIndex(0); - this.singleCase = true; } } @@ -70,6 +71,10 @@ public class InterCasePanel extends javax.swing.JPanel { this.parent = parent; } + String getErrorMessage(){ + return this.errorMessage; + } + /** * 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 @@ -80,16 +85,16 @@ public class InterCasePanel extends javax.swing.JPanel { private void initComponents() { buttonGroup = new javax.swing.ButtonGroup(); - anCentralRepoCaseRadio = new javax.swing.JRadioButton(); + anyCentralRepoCaseRadio = new javax.swing.JRadioButton(); specificCentralRepoCaseRadio = new javax.swing.JRadioButton(); caseComboBox = new javax.swing.JComboBox<>(); - buttonGroup.add(anCentralRepoCaseRadio); - anCentralRepoCaseRadio.setSelected(true); - org.openide.awt.Mnemonics.setLocalizedText(anCentralRepoCaseRadio, org.openide.util.NbBundle.getMessage(InterCasePanel.class, "InterCasePanel.anCentralRepoCaseRadio.text")); // NOI18N - anCentralRepoCaseRadio.addActionListener(new java.awt.event.ActionListener() { + buttonGroup.add(anyCentralRepoCaseRadio); + anyCentralRepoCaseRadio.setSelected(true); + org.openide.awt.Mnemonics.setLocalizedText(anyCentralRepoCaseRadio, org.openide.util.NbBundle.getMessage(InterCasePanel.class, "InterCasePanel.anyCentralRepoCaseRadio.text")); // NOI18N + anyCentralRepoCaseRadio.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { - anCentralRepoCaseRadioActionPerformed(evt); + anyCentralRepoCaseRadioActionPerformed(evt); } }); @@ -111,37 +116,40 @@ public class InterCasePanel extends javax.swing.JPanel { .addGroup(layout.createSequentialGroup() .addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(anCentralRepoCaseRadio) - .addComponent(specificCentralRepoCaseRadio) + .addComponent(anyCentralRepoCaseRadio) .addGroup(layout.createSequentialGroup() .addGap(21, 21, 21) - .addComponent(caseComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 261, javax.swing.GroupLayout.PREFERRED_SIZE))) + .addComponent(caseComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 261, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(specificCentralRepoCaseRadio)) .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() - .addContainerGap() - .addComponent(anCentralRepoCaseRadio) + .addComponent(anyCentralRepoCaseRadio) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(specificCentralRepoCaseRadio) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(caseComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addComponent(caseComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) ); }// //GEN-END:initComponents private void specificCentralRepoCaseRadioActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_specificCentralRepoCaseRadioActionPerformed this.caseComboBox.setEnabled(true); + if(this.caseComboBox.getSelectedItem() == null){ + this.caseComboBox.setSelectedIndex(0); + } + this.parent.handleInterCaseSearchCriteriaChanged(); }//GEN-LAST:event_specificCentralRepoCaseRadioActionPerformed - private void anCentralRepoCaseRadioActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_anCentralRepoCaseRadioActionPerformed + private void anyCentralRepoCaseRadioActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_anyCentralRepoCaseRadioActionPerformed this.caseComboBox.setEnabled(false); - }//GEN-LAST:event_anCentralRepoCaseRadioActionPerformed + this.parent.handleInterCaseSearchCriteriaChanged(); + }//GEN-LAST:event_anyCentralRepoCaseRadioActionPerformed // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.JRadioButton anCentralRepoCaseRadio; + private javax.swing.JRadioButton anyCentralRepoCaseRadio; private javax.swing.ButtonGroup buttonGroup; private javax.swing.JComboBox caseComboBox; private javax.swing.JRadioButton specificCentralRepoCaseRadio; @@ -157,8 +165,8 @@ public class InterCasePanel extends javax.swing.JPanel { } void rigForMultipleCases(boolean multipleCases) { - this.anCentralRepoCaseRadio.setEnabled(multipleCases); - this.anCentralRepoCaseRadio.setEnabled(multipleCases); + this.anyCentralRepoCaseRadio.setEnabled(multipleCases); + this.anyCentralRepoCaseRadio.setEnabled(multipleCases); if(!multipleCases){ this.specificCentralRepoCaseRadio.setSelected(true); @@ -173,4 +181,26 @@ public class InterCasePanel extends javax.swing.JPanel { boolean centralRepoHasMultipleCases() { return this.caseMap.size() >= 2; } + + Integer getSelectedCaseId(){ + for(Entry entry : this.caseMap.entrySet()){ + if(entry.getValue().equals(this.caseComboBox.getSelectedItem())){ + return entry.getKey(); + } + } + + return InterCasePanel.NO_CASE_SELECTED; + } + + @NbBundle.Messages({ + "InterCasePanel.showInterCaseErrorMessage.message=Cannot run intercase correlation search: no cases in Central Repository." + }) + boolean areSearchCriteriaMet() { + if(this.caseMap.isEmpty()){ + this.errorMessage = Bundle.InterCasePanel_showInterCaseErrorMessage_message(); + return false; + } else { + return true; + } + } } diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/IntraCasePanel.form b/Core/src/org/sleuthkit/autopsy/commonfilesearch/IntraCasePanel.form index b8e270890a..7038ca5926 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/IntraCasePanel.form +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/IntraCasePanel.form @@ -20,13 +20,17 @@ - - + - - + + + + + + + - + @@ -37,13 +41,11 @@ - - diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/IntraCasePanel.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/IntraCasePanel.java index 420e68dd6e..ee90532109 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/IntraCasePanel.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/IntraCasePanel.java @@ -24,6 +24,7 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.util.HashMap; import java.util.Map; +import java.util.Map.Entry; import java.util.concurrent.ExecutionException; import java.util.logging.Level; import javax.swing.ComboBoxModel; @@ -44,6 +45,7 @@ import org.sleuthkit.datamodel.TskCoreException; public class IntraCasePanel extends javax.swing.JPanel { private static final long serialVersionUID = 1L; + static final long NO_DATA_SOURCE_SELECTED = -1; private static final Logger LOGGER = Logger.getLogger(CommonFilesPanel.class.getName()); @@ -52,12 +54,15 @@ public class IntraCasePanel extends javax.swing.JPanel { private ComboBoxModel dataSourcesList = new DataSourceComboBoxModel(); private Map dataSourceMap; private CommonFilesPanel parent; + + private String errorMessage; /** * Creates new form IntraCasePanel */ public IntraCasePanel() { initComponents(); + this.errorMessage = ""; } public void setParent(CommonFilesPanel parent){ @@ -80,7 +85,15 @@ public class IntraCasePanel extends javax.swing.JPanel { return this.dataSourceMap; } - + Long getSelectedDataSourceId(){ + for(Entry entry : this.dataSourceMap.entrySet()){ + if(entry.getValue().equals(this.selectDataSourceComboBox.getSelectedItem())){ + return entry.getKey(); + } + } + + return IntraCasePanel.NO_DATA_SOURCE_SELECTED; + } /** * This method is called from within the constructor to initialize the form. @@ -127,35 +140,37 @@ public class IntraCasePanel extends javax.swing.JPanel { layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() - .addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(withinDataSourceRadioButton) - .addComponent(allDataSourcesRadioButton) .addGroup(layout.createSequentialGroup() - .addGap(20, 20, 20) + .addContainerGap() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(allDataSourcesRadioButton) + .addComponent(withinDataSourceRadioButton))) + .addGroup(layout.createSequentialGroup() + .addGap(27, 27, 27) .addComponent(selectDataSourceComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 261, javax.swing.GroupLayout.PREFERRED_SIZE))) .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() - .addContainerGap() .addComponent(allDataSourcesRadioButton) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(withinDataSourceRadioButton) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(selectDataSourceComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addComponent(selectDataSourceComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) ); }// //GEN-END:initComponents private void allDataSourcesRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_allDataSourcesRadioButtonActionPerformed selectDataSourceComboBox.setEnabled(!allDataSourcesRadioButton.isSelected()); singleDataSource = false; + this.parent.handleIntraCaseSearchCriteriaChanged(); }//GEN-LAST:event_allDataSourcesRadioButtonActionPerformed private void withinDataSourceRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_withinDataSourceRadioButtonActionPerformed withinDataSourceSelected(withinDataSourceRadioButton.isSelected()); + this.parent.handleIntraCaseSearchCriteriaChanged(); }//GEN-LAST:event_withinDataSourceRadioButtonActionPerformed private void selectDataSourceComboBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_selectDataSourceComboBoxActionPerformed @@ -200,4 +215,20 @@ public class IntraCasePanel extends javax.swing.JPanel { void setDataSourceMap(Map dataSourceMap) { this.dataSourceMap = dataSourceMap; } + + @NbBundle.Messages({ + "IntraCasePanel.areSearchCriteriaMet.message=Cannot run intra-case correlation search." + }) + boolean areSearchCriteriaMet() { + if(this.dataSourceMap.isEmpty()){ + this.errorMessage = Bundle.IntraCasePanel_areSearchCriteriaMet_message(); + return false; + } else { + return true; + } + } + + String getErrorMessage() { + return this.errorMessage; + } }