diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesMetaDataBuilder.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesMetaDataBuilder.java index 94b7906538..d53e9f403f 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesMetaDataBuilder.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesMetaDataBuilder.java @@ -35,21 +35,17 @@ import org.sleuthkit.datamodel.TskCoreException; /** * - * Generates a List when collateFiles() is called, which organizes - * AbstractFiles by md5 to prepare to display in viewer. - * + * Generates a List when collateFiles() is called, which + * organizes AbstractFiles by md5 to prepare to display in viewer. + * * This entire thing runs on a background thread where exceptions are handled. */ -class CommonFilesMetaDataBuilder { +abstract class CommonFilesMetaDataBuilder { - private final Long selectedDataSourceId; private final Map dataSourceIdToNameMap; //TODO subclass this class to specify where clause and/or additional algorithms. - private final String singleDataSourceWhereClause = "md5 in (select md5 from tsk_files where data_source_obj_id=%s and (known != 1 OR known IS NULL) GROUP BY md5 HAVING COUNT(*) > 1) AND data_source_obj_id=%s order by md5"; - private final String allDataSourcesWhereClause = "md5 in (select md5 from tsk_files where (known != 1 OR known IS NULL) GROUP BY md5 HAVING COUNT(*) > 1) order by md5"; - CommonFilesMetaDataBuilder(Long dataSourceId, Map dataSourceIdMap) { - selectedDataSourceId = dataSourceId; + CommonFilesMetaDataBuilder(Map dataSourceIdMap) { dataSourceIdToNameMap = dataSourceIdMap; } @@ -85,18 +81,25 @@ class CommonFilesMetaDataBuilder { return metaDataModels; } + + /** + * Should build a SQL WHERE clause to be passed to SleuthkitCase.findAllFilesWhere(sql) + * which will select the desired common files ordered by MD5. + * @return sql string where clause + */ + protected abstract String buildSqlWhereClause(); private void collateParentChildRelationships(List files, Map> parentNodes, Map> md5ToDataSourcesStringMap) { for (AbstractFile file : files) { - + String currentMd5 = file.getMd5Hash(); - + if (parentNodes.containsKey(currentMd5)) { parentNodes.get(currentMd5).add(file); Set currentDataSources = md5ToDataSourcesStringMap.get(currentMd5); addDataSource(currentDataSources, file, dataSourceIdToNameMap); md5ToDataSourcesStringMap.put(currentMd5, currentDataSources); - + } else { List children = new ArrayList<>(); Set dataSources = new HashSet<>(); @@ -105,20 +108,47 @@ class CommonFilesMetaDataBuilder { addDataSource(dataSources, file, dataSourceIdToNameMap); md5ToDataSourcesStringMap.put(currentMd5, dataSources); } - + } } private List findCommonFiles() throws TskCoreException, NoCurrentCaseException { SleuthkitCase sleuthkitCase; sleuthkitCase = Case.getOpenCase().getSleuthkitCase(); - String whereClause = allDataSourcesWhereClause; - if (selectedDataSourceId != 0L) { - Object[] args = new String[]{Long.toString(selectedDataSourceId), Long.toString(selectedDataSourceId)}; - whereClause = String.format(singleDataSourceWhereClause, args); - } + String whereClause = this.buildSqlWhereClause(); List files = sleuthkitCase.findAllFilesWhere(whereClause); return files; } - +} + +class SingleDataSource extends CommonFilesMetaDataBuilder { + + private static final String allDataSourcesWhereClause = "md5 in (select md5 from tsk_files where (known != 1 OR known IS NULL) GROUP BY md5 HAVING COUNT(*) > 1) order by md5"; + + private final Long selectedDataSourceId; + + public SingleDataSource(Long dataSourceId, Map dataSourceIdMap) { + super(dataSourceIdMap); + this.selectedDataSourceId = dataSourceId; + } + + @Override + protected String buildSqlWhereClause() { + Object[] args = new String[]{Long.toString(this.selectedDataSourceId), Long.toString(this.selectedDataSourceId)}; + return String.format(SingleDataSource.allDataSourcesWhereClause, args); + } +} + +class AllDataSources extends CommonFilesMetaDataBuilder { + + private static final String singleDataSourceWhereClause = "md5 in (select md5 from tsk_files where data_source_obj_id=%s and (known != 1 OR known IS NULL) GROUP BY md5 HAVING COUNT(*) > 1) AND data_source_obj_id=%s order by md5"; + + public AllDataSources(Map dataSourceIdMap) { + super(dataSourceIdMap); + } + + @Override + protected String buildSqlWhereClause() { + return AllDataSources.singleDataSourceWhereClause; + } } diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesPanel.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesPanel.java index 3ef5e626df..511585c67e 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesPanel.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesPanel.java @@ -52,6 +52,8 @@ public final class CommonFilesPanel extends javax.swing.JPanel { private static final long serialVersionUID = 1L; + public static final Long NO_DATA_SOURCE_SELECTED = -1L; + private ComboBoxModel dataSourcesList = new DataSourceComboBoxModel(); private Map dataSourceMap; @@ -182,7 +184,7 @@ public final class CommonFilesPanel extends javax.swing.JPanel { new SwingWorker, Void>() { private Long determineDataSourceId() { - Long selectedObjId = 0L; + Long selectedObjId = CommonFilesPanel.NO_DATA_SOURCE_SELECTED; if (CommonFilesPanel.this.singleDataSource) { for (Entry dataSource : CommonFilesPanel.this.dataSourceMap.entrySet()) { if (dataSource.getValue().equals(CommonFilesPanel.this.selectedDataSource)) { @@ -196,8 +198,17 @@ public final class CommonFilesPanel extends javax.swing.JPanel { @Override protected List doInBackground() throws TskCoreException, NoCurrentCaseException, SQLException { - Long selectedObjId = determineDataSourceId(); - return new CommonFilesMetaDataBuilder(selectedObjId, CommonFilesPanel.this.dataSourceMap).collateFiles(); + Long dataSourceId = determineDataSourceId(); + + CommonFilesMetaDataBuilder builder; + + if (dataSourceId == CommonFilesPanel.NO_DATA_SOURCE_SELECTED) { + builder = new AllDataSources(dataSourceMap); + } else { + builder = new SingleDataSource(dataSourceId, dataSourceMap); + } + + return builder.collateFiles(); } @Override