diff --git a/Core/build.xml b/Core/build.xml index 98644b8cb3..eca218ed5f 100644 --- a/Core/build.xml +++ b/Core/build.xml @@ -100,6 +100,12 @@ + diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.java b/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.java index dd41796f35..4a60696186 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.java @@ -73,7 +73,7 @@ import org.sleuthkit.datamodel.TskData; @Messages({"DataContentViewerOtherCases.title=Other Occurrences", "DataContentViewerOtherCases.toolTip=Displays instances of the selected file/artifact from other occurrences.",}) public class DataContentViewerOtherCases extends javax.swing.JPanel implements DataContentViewer { - + private static final long serialVersionUID = -1L; private final static Logger LOGGER = Logger.getLogger(DataContentViewerOtherCases.class.getName()); @@ -403,7 +403,7 @@ public class DataContentViewerOtherCases extends javax.swing.JPanel implements D // correlate on blackboard artifact attributes if they exist and supported BlackboardArtifact bbArtifact = getBlackboardArtifactFromNode(node); - if (bbArtifact != null) { + if (bbArtifact != null && EamDb.isEnabled()) { ret.addAll(EamArtifactUtil.getCorrelationAttributeFromBlackboardArtifact(bbArtifact, false, false)); } @@ -541,9 +541,15 @@ public class DataContentViewerOtherCases extends javax.swing.JPanel implements D // Is supported if this node // has correlatable content (File, BlackboardArtifact) OR // other common files across datasources. - return this.file != null + + if(EamDb.isEnabled()){ + return this.file != null && this.file.getSize() > 0 && !getCorrelationAttributesFromNode(node).isEmpty(); + } else{ + return this.file != null + && this.file.getSize() > 0; + } } @Override diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java index 1a50f5797e..a322b08d9e 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java @@ -650,7 +650,22 @@ public abstract class AbstractSqlEamDb implements EamDb { } /** - * Retrieves eamArtiifact instances from the database that match the given + * Retrieves eamArtifact instances from the database that match the given + * list of MD5 values; + * + * @param values MD5s to use as search keys + * @return matching files in the form of CentralRepositoryFile + * @throws EamDbException + */ + public List getArtifactInstancesByCaseValues(Collection values) throws EamDbException { + //passing null and -1 here has the effect of making this case agnostic: + // rather than looking for instances that must appear in a certain case + // we accept instances occur in any case + return getArtifactInstancesByCaseValues(null, values, -1); + } + + /** + * Retrieves eamArtifact instances from the database that match the given * list of MD5 values and optionally filters by given case. * * Warning: Does not benefit from PreparedStatement caching to since values @@ -664,7 +679,7 @@ public abstract class AbstractSqlEamDb implements EamDb { * @throws EamDbException if EamDb is inaccessible. */ @Override - public List getArtifactInstancesByCaseValues(CorrelationCase correlationCase, Collection values, int currentCaseId) throws EamDbException { + public List getArtifactInstancesByCaseValues(CorrelationCase correlationCase, Collection values, int currentCaseId) throws EamDbException { CorrelationAttribute.Type aType = CorrelationAttribute.getDefaultCorrelationTypes().get(0); // Files type if (aType == null) { throw new EamDbException("Correlation Type is null"); @@ -676,77 +691,78 @@ public abstract class AbstractSqlEamDb implements EamDb { if (values == null) { values = new ArrayList<>(); } - Connection conn = connect(); - List artifactInstances = new ArrayList<>(); + List artifactInstances = new ArrayList<>(); - // SELECT cases.case_name, cases.case_uid, data_sources.name, device_id, file_path, known_status, comment, data_sources.case_id, value FROM file_instances LEFT JOIN cases ON file_instances.case_id=cases.id LEFT JOIN data_sources ON file_instances.data_source_id=data_sources.id WHERE value IN (SELECT value FROM file_instances WHERE value IN ("59029becd7f830c0478aeb5e67cc3b20","d2b949c51cf3d5721699a6ea500eeba7","b90c8c8fb1c4687780002704b59585fe") GROUP BY value HAVING COUNT(*) > 1) ORDER BY value - CorrelationAttributeCommonInstance artifactInstance; - PreparedStatement preparedStatement = null; - ResultSet resultSet = null; + if (values != null && !values.isEmpty()) { - String tableName = EamDbUtil.correlationTypeToInstanceTableName(aType); - StringBuilder sql = new StringBuilder(10); - sql.append("SELECT cases.case_name, cases.case_uid, data_sources.name, device_id, file_path, known_status, comment, data_sources.case_id, value FROM "); - sql.append(tableName); - sql.append(" LEFT JOIN cases ON "); - sql.append(tableName); - sql.append(".case_id=cases.id"); - sql.append(" LEFT JOIN data_sources ON "); - sql.append(tableName); - sql.append(".data_source_id=data_sources.id"); - sql.append(" WHERE value IN (SELECT value FROM "); - sql.append(tableName); - sql.append(" WHERE value IN ("); - - // Note: PreparedStatement has a limit on ? variable replacement so instead query is built with values appended directly into the string - for (String value : values) { - sql.append("'"); - sql.append(value); - sql.append("',"); - } - if (values.size() > 0) { - sql.deleteCharAt(sql.length() - 1); - } - - - if (singleCase && correlationCase != null) { - sql.append(") AND "); + //we can skip all this if there is nothing to search for + String tableName = EamDbUtil.correlationTypeToInstanceTableName(aType); + StringBuilder sql = new StringBuilder(10); + sql.append("SELECT cases.case_name, cases.case_uid, data_sources.name, device_id, file_path, known_status, comment, data_sources.case_id, value FROM "); sql.append(tableName); - sql.append(".case_id=?)"); // inner select checks for other case results - sql.append(" AND ("); + sql.append(" LEFT JOIN cases ON "); sql.append(tableName); - sql.append(".case_id=?"); - sql.append(" OR "); + sql.append(".case_id=cases.id"); + sql.append(" LEFT JOIN data_sources ON "); sql.append(tableName); - sql.append(".case_id=?)"); + sql.append(".data_source_id=data_sources.id"); + sql.append(" WHERE value IN (SELECT value FROM "); + sql.append(tableName); + sql.append(" WHERE value IN ("); - } else { - sql.append(") GROUP BY value HAVING COUNT(*) > 1)"); // - } + // Note: PreparedStatement has a limit on ? variable replacement so instead query is built with values appended directly into the string + for (String value : values) { + sql.append("'"); + sql.append(value); + sql.append("',"); + } + if (values.size() > 0) { + sql.deleteCharAt(sql.length() - 1); + } - sql.append(" ORDER BY value, cases.case_name, file_path"); - - try { - preparedStatement = conn.prepareStatement(sql.toString()); if (singleCase && correlationCase != null) { - preparedStatement.setInt(1, correlationCase.getID()); - preparedStatement.setInt(2, correlationCase.getID()); - preparedStatement.setInt(3, currentCaseId); + sql.append(") AND "); + sql.append(tableName); + sql.append(".case_id=?)"); // inner select checks for other case results + sql.append(" AND ("); + sql.append(tableName); + sql.append(".case_id=?"); + sql.append(" OR "); + sql.append(tableName); + sql.append(".case_id=?)"); + + } else { + sql.append(") GROUP BY value HAVING COUNT(*) > 1)"); // } - resultSet = preparedStatement.executeQuery(); - while (resultSet.next()) { - artifactInstance = getCommonEamArtifactInstanceFromResultSet(resultSet); - artifactInstances.add(artifactInstance); - } + sql.append(" ORDER BY value, cases.case_name, file_path"); - } catch (SQLException ex) { - throw new EamDbException("Error getting artifact instances by artifactType and artifactValue.", ex); // NON-NLS - } finally { - EamDbUtil.closePreparedStatement(preparedStatement); - EamDbUtil.closeResultSet(resultSet); - EamDbUtil.closeConnection(conn); + Connection conn = connect(); + CentralRepositoryFile artifactInstance; + PreparedStatement preparedStatement = null; + ResultSet resultSet = null; + try { + preparedStatement = conn.prepareStatement(sql.toString()); + if (singleCase && correlationCase != null) { + preparedStatement.setInt(1, correlationCase.getID()); + preparedStatement.setInt(2, correlationCase.getID()); + preparedStatement.setInt(3, currentCaseId); + } + + resultSet = preparedStatement.executeQuery(); + while (resultSet.next()) { + artifactInstance = getCommonEamArtifactInstanceFromResultSet(resultSet); + artifactInstances.add(artifactInstance); + } + + } catch (SQLException ex) { + throw new EamDbException("Error getting artifact instances by artifactType and artifactValue.", ex); // NON-NLS + } finally { + EamDbUtil.closePreparedStatement(preparedStatement); + EamDbUtil.closeResultSet(resultSet); + EamDbUtil.closeConnection(conn); + } } return artifactInstances; @@ -2475,11 +2491,11 @@ public abstract class AbstractSqlEamDb implements EamDb { * * @throws SQLException when an expected column name is not in the resultSet */ - private CorrelationAttributeCommonInstance getCommonEamArtifactInstanceFromResultSet(ResultSet resultSet) throws SQLException, EamDbException { + private CentralRepositoryFile getCommonEamArtifactInstanceFromResultSet(ResultSet resultSet) throws SQLException, EamDbException { if (null == resultSet) { return null; } - CorrelationAttributeCommonInstance eamArtifactInstance = new CorrelationAttributeCommonInstance( + CentralRepositoryFile eamArtifactInstance = new CentralRepositoryFile( new CorrelationCase(resultSet.getInt("case_id"), resultSet.getString("case_uid"), resultSet.getString("case_name")), new CorrelationDataSource(-1, resultSet.getInt("case_id"), resultSet.getString("device_id"), resultSet.getString("name")), resultSet.getString("file_path"), diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeCommonInstance.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepositoryFile.java similarity index 80% rename from Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeCommonInstance.java rename to Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepositoryFile.java index ff03b23f5b..95af456038 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeCommonInstance.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepositoryFile.java @@ -25,7 +25,7 @@ import org.sleuthkit.datamodel.TskData; * Common Files Search usage which extends CorrelationAttributeInstance * by adding the MD5 value to match on for the results table. */ -public class CorrelationAttributeCommonInstance extends CorrelationAttributeInstance { +public class CentralRepositoryFile extends CorrelationAttributeInstance { private static final long serialVersionUID = 1L; @@ -34,7 +34,7 @@ public class CorrelationAttributeCommonInstance extends CorrelationAttributeInst */ private final String value; - public CorrelationAttributeCommonInstance(CorrelationCase eamCase, CorrelationDataSource eamDataSource, String filePath, String comment, TskData.FileKnown knownStatus, String value) throws EamDbException { + public CentralRepositoryFile(CorrelationCase eamCase, CorrelationDataSource eamDataSource, String filePath, String comment, TskData.FileKnown knownStatus, String value) throws EamDbException { super(eamCase, eamDataSource, filePath, comment, knownStatus); this.value = value; } diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDb.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDb.java index 5984e4d074..fc8b269270 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDb.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDb.java @@ -230,11 +230,22 @@ public interface EamDb { * * @param correlationCase Case id to search on * @param values List of ArtifactInstance MD5 values to find matches of. + * @param currentCaseId current case * - * @return List of artifact instances for a given list of MD5 values + * @return matching files in the form of CentralRepositoryFile */ - List getArtifactInstancesByCaseValues(CorrelationCase correlationCase, Collection values, int currentCaseId) throws EamDbException; + List getArtifactInstancesByCaseValues(CorrelationCase correlationCase, Collection values, int currentCaseId) throws EamDbException; + /** + * Retrieves eamArtiifact instances from the database that match the given + * list of MD5 values; + * + * @param values MD5s to use as search keys + * @return matching files in the form of CentralRepositoryFile + * @throws EamDbException + */ + List getArtifactInstancesByCaseValues(Collection values) throws EamDbException; + /** * Retrieves eamArtifact instances from the database that are associated * with the aType and filePath diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDb.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDb.java index 2d181b4be3..dfbfc45b25 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDb.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDb.java @@ -419,6 +419,25 @@ public class SqliteEamDb extends AbstractSqlEamDb { releaseSharedLock(); } } + + /** + * Retrieves eamArtiifact instances from the database that match the given + * list of MD5 values; + * + * @param correlationCase Case id to search on + * @param values List of ArtifactInstance MD5 values to find matches of. + * + * @return List of artifact instances for a given list of MD5 values + */ + @Override + public List getArtifactInstancesByCaseValues(Collection values) throws EamDbException { + try { + acquireSharedLock(); + return super.getArtifactInstancesByCaseValues(null, values, -1); + } finally { + releaseSharedLock(); + } + } /** * Retrieves eamArtiifact instances from the database that match the given @@ -430,7 +449,7 @@ public class SqliteEamDb extends AbstractSqlEamDb { * @return List of artifact instances for a given list of MD5 values */ @Override - public List getArtifactInstancesByCaseValues(CorrelationCase correlationCase, Collection values, int currentCaseId) throws EamDbException { + public List getArtifactInstancesByCaseValues(CorrelationCase correlationCase, Collection values, int currentCaseId) throws EamDbException { try { acquireSharedLock(); return super.getArtifactInstancesByCaseValues(correlationCase, values, currentCaseId); diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/AllCasesEamDbCommonFilesAlgorithm.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/AllCasesEamDbCommonFilesAlgorithm.java index c7a87f5b52..8aad1eb1bb 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/AllCasesEamDbCommonFilesAlgorithm.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/AllCasesEamDbCommonFilesAlgorithm.java @@ -23,7 +23,8 @@ import java.util.Map; import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException; /** - *TODO docs + * Algorithm which finds files anywhere in the Central Repo which also occur in + * present case. */ public class AllCasesEamDbCommonFilesAlgorithm extends EamDbCommonFilesAlgorithm { diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesPanel.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesPanel.java index dace725f5e..07464f138d 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesPanel.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesPanel.java @@ -131,14 +131,6 @@ public final class CommonFilesPanel extends javax.swing.JPanel { this.tabTitle = String.format(CommonFilesPanel_search_results_titleSingle, dataSourceName); } - private void setTitleForAllCases() { - - } - - private void setTitleForSingleCase() { - - } - @Override @SuppressWarnings({"BoxedValueEquality", "NumberEquality"}) protected CommonFilesMetadata doInBackground() throws TskCoreException, NoCurrentCaseException, SQLException, EamDbException, Exception { @@ -270,10 +262,6 @@ public final class CommonFilesPanel extends javax.swing.JPanel { //TODO this should be attached to the intra/inter radio buttons CommonFilesPanel.this.setSearchButtonEnabled(true); - } else { - //TODO error message only? -// MessageNotifyUtil.Message.info(Bundle.IntraCasePanel_setupDataSources_updateUi_noDataSources()); -// SwingUtilities.windowForComponent(IntraCasePanel.this.parent).dispose(); } } diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/EamDbCommonFilesAlgorithm.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/EamDbCommonFilesAlgorithm.java index b137e15c30..a42ea26844 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/EamDbCommonFilesAlgorithm.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/EamDbCommonFilesAlgorithm.java @@ -19,6 +19,7 @@ */ package org.sleuthkit.autopsy.commonfilesearch; +import java.io.File; import java.sql.SQLException; import java.util.ArrayList; import java.util.Collection; @@ -29,7 +30,7 @@ import java.util.logging.Level; import java.util.stream.Collectors; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; -import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeCommonInstance; +import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepositoryFile; import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationCase; import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb; import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException; @@ -43,6 +44,10 @@ import org.sleuthkit.datamodel.TskCoreException; * in the Central Repo. */ public abstract class EamDbCommonFilesAlgorithm extends CommonFilesMetadataBuilder { + //CONSIDER: we should create an interface which specifies the findFiles feature + // instead of an abstract class and then have two abstract classes: + // inter- and intra- which implement the interface and then 4 subclasses + // 2 for each abstract class: singlecase/allcase; singledatasource/all datasource 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 @@ -78,10 +83,15 @@ public abstract class EamDbCommonFilesAlgorithm extends CommonFilesMetadataBuild Map interCaseCommonFiles = new HashMap<>(); try { // Need to include current Cases results for specific case comparison - currentCaseId = dbManager.getCase(Case.getCurrentCase()).getID(); + currentCaseId = dbManager.getCase(Case.getCurrentCase()).getID(); + Collection artifactInstances; + if(this.dbManager == null){ + artifactInstances = new ArrayList<>(0); + } else { + artifactInstances = dbManager.getArtifactInstancesByCaseValues(correlationCase, values, currentCaseId).stream() + .collect(Collectors.toList()); + } - Collection artifactInstances = dbManager.getArtifactInstancesByCaseValues(correlationCase, values, currentCaseId).stream() - .collect(Collectors.toList()); interCaseCommonFiles = gatherIntercaseResults(artifactInstances, currentCaseMetadata); } catch (EamDbException ex) { @@ -98,14 +108,17 @@ public abstract class EamDbCommonFilesAlgorithm extends CommonFilesMetadataBuild return commonFiles; } - private Map gatherIntercaseResults(Collection artifactInstances, Map commonFiles) { + private Map gatherIntercaseResults(Collection artifactInstances, Map commonFiles) { Map interCaseCommonFiles = new HashMap<>(); - for (CorrelationAttributeCommonInstance instance : artifactInstances) { + for (CentralRepositoryFile instance : artifactInstances) { String md5 = instance.getValue(); - String dataSource = String.format("%s: %s", instance.getCorrelationCase().getDisplayName(), instance.getCorrelationDataSource().getName()); + final String correlationCaseDisplayName = instance.getCorrelationCase().getDisplayName(); + String dataSource = String.format("%s: %s", correlationCaseDisplayName, instance.getCorrelationDataSource().getName()); + String path = instance.getFilePath(); + File file = new File(path); if (md5 == null || HashUtility.isNoDataMd5(md5)) { continue; @@ -118,17 +131,19 @@ public abstract class EamDbCommonFilesAlgorithm extends CommonFilesMetadataBuild if(interCaseCommonFiles.containsKey(md5)) { //Add to intercase metaData final Md5Metadata md5Metadata = interCaseCommonFiles.get(md5); - md5Metadata.addFileInstanceMetadata(new FileInstanceMetadata(objectId, dataSource)); + md5Metadata.addFileInstanceMetadata(new FileInstanceMetadata(objectId, dataSource, file), correlationCaseDisplayName); } else { - final List fileInstances = new ArrayList<>(); - fileInstances.add(new FileInstanceMetadata(objectId, dataSource)); - Md5Metadata md5Metadata = new Md5Metadata(md5, fileInstances); + Md5Metadata md5Metadata = new Md5Metadata(md5); + md5Metadata.addFileInstanceMetadata(new FileInstanceMetadata(objectId, dataSource, file), correlationCaseDisplayName); interCaseCommonFiles.put(md5, md5Metadata); } } } + //ideally we would do this step via SQL in EamDb.getArtifactInstancesByCaseValues + removeEntriesWithinOnlyOneCase(interCaseCommonFiles); + return interCaseCommonFiles; } @@ -154,4 +169,18 @@ public abstract class EamDbCommonFilesAlgorithm extends CommonFilesMetadataBuild } throw new Exception("Cannot locate case."); } + + private void removeEntriesWithinOnlyOneCase(Map interCaseCommonFiles) { + Collection toRemove = new ArrayList<>(); + + for(Map.Entry entry : interCaseCommonFiles.entrySet()){ + if(!entry.getValue().isMultiDataSource()){ + toRemove.add(entry.getKey()); + } + } + + for(String bogusEntry : toRemove){ + interCaseCommonFiles.remove(bogusEntry); + } + } } diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/FileInstanceMetadata.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/FileInstanceMetadata.java index 369e6841c2..9064624d05 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/FileInstanceMetadata.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/FileInstanceMetadata.java @@ -19,6 +19,8 @@ */ package org.sleuthkit.autopsy.commonfilesearch; +import java.io.File; + /** * Encapsulates data required to instantiate a FileInstanceNode. */ @@ -26,6 +28,7 @@ final public class FileInstanceMetadata { private final Long objectId; private final String dataSourceName; + private final File file; /** * Create meta data required to find an abstract file and build a FileInstanceNode. @@ -35,6 +38,13 @@ final public class FileInstanceMetadata { FileInstanceMetadata(Long objectId, String dataSourceName) { this.objectId = objectId; this.dataSourceName = dataSourceName; + this.file = null; + } + + FileInstanceMetadata(Long objectId, String dataSourceName, File file){ + this.objectId = objectId; + this.dataSourceName = dataSourceName; + this.file = file; } /** diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/Md5Metadata.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/Md5Metadata.java index 39c2cf8040..916d6950a8 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/Md5Metadata.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/Md5Metadata.java @@ -19,6 +19,7 @@ */ package org.sleuthkit.autopsy.commonfilesearch; +import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashSet; @@ -33,9 +34,18 @@ final public class Md5Metadata { private final String md5; private final List fileInstances; + private final Set distinctCases; + Md5Metadata(String md5, List fileInstances){ this.md5 = md5; this.fileInstances = fileInstances; + this.distinctCases = new HashSet<>(); + } + + Md5Metadata(String md5){ + this.md5 = md5; + this.fileInstances = new ArrayList<>(); + this.distinctCases = new HashSet<>(); } public String getMd5(){ @@ -46,6 +56,13 @@ final public class Md5Metadata { this.fileInstances.add(metadata); } + void addFileInstanceMetadata(FileInstanceMetadata metadata, String caseName){ + this.fileInstances.add(metadata); + if(!this.distinctCases.contains(caseName)){ + this.distinctCases.add(caseName); + } + } + public Collection getMetadata(){ return Collections.unmodifiableCollection(this.fileInstances); } @@ -65,4 +82,8 @@ final public class Md5Metadata { } return String.join(", ", sources); } + + boolean isMultiDataSource() { + return this.distinctCases.size() > 1; + } } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileInstanceNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileInstanceNode.java index dea5535a26..c4ea2fb979 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/FileInstanceNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileInstanceNode.java @@ -18,6 +18,7 @@ */ package org.sleuthkit.autopsy.datamodel; +import java.io.File; import java.util.LinkedHashMap; import java.util.Map; import org.apache.commons.lang3.StringUtils; @@ -32,12 +33,25 @@ import org.sleuthkit.datamodel.AbstractFile; public class FileInstanceNode extends FileNode { private final String dataSource; + private final File file; public FileInstanceNode(AbstractFile fsContent, String dataSource) { super(fsContent); this.content = fsContent; this.dataSource = dataSource; + this.file = null; } + + public FileInstanceNode(AbstractFile fsContent, String dataSource, File file){ + super(fsContent); + this.content = fsContent; + this.dataSource = dataSource; + this.file = file; + } + + //TODO add constructor with correlation attr instance + //TODO override getactions + //TODO use constructor overload that consumes a lookup and pass an instance of this (or a subclas of it) @Override public T accept(DisplayableItemNodeVisitor visitor) { @@ -52,6 +66,14 @@ public class FileInstanceNode extends FileNode { String getDataSource() { return this.dataSource; } + + boolean hasFile(){ + return this.file != null; + } + + File getFile(){ + return this.file; + } @Override protected Sheet createSheet() { @@ -87,8 +109,10 @@ public class FileInstanceNode extends FileNode { */ static private void fillPropertyMap(Map map, FileInstanceNode node) { - map.put(CommonFilePropertyType.File.toString(), node.getName()); - map.put(CommonFilePropertyType.ParentPath.toString(), node.getContent().getParentPath()); + //TODO rather than these ternary operators we should subclass FileInstanceNode or derive an interface + + map.put(CommonFilePropertyType.File.toString(), node.hasFile() ? node.getFile().getName() : node.getName()); + map.put(CommonFilePropertyType.ParentPath.toString(), node.hasFile() ? node.getFile().getParent() : node.getContent().getParentPath()); //TODO this appears to have a bug map.put(CommonFilePropertyType.HashsetHits.toString(), getHashSetHitsForFile(node.getContent())); map.put(CommonFilePropertyType.DataSource.toString(), node.getDataSource()); map.put(CommonFilePropertyType.MimeType.toString(), StringUtils.defaultString(node.content.getMIMEType())); diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java index 055e9a8040..8f2abdb655 100755 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java @@ -845,11 +845,11 @@ public class CentralRepoDatamodelTest extends TestCase { // Test getting common instances with expected results try { - List instances = EamDb.getInstance().getArtifactInstancesByCaseValues(null, Arrays.asList(inAllDataSourcesHash, inDataSource1twiceHash)); + List instances = EamDb.getInstance().getArtifactInstancesByCaseValues(Arrays.asList(inAllDataSourcesHash, inDataSource1twiceHash)); assertTrue("getArtifactInstancesByCaseValues returned " + instances.size() + " results - expected 5", instances.size() == 5); // This test works because all the instances of this hash were set to the same path - for (CorrelationAttributeCommonInstance inst : instances) { + for (CentralRepositoryFile inst : instances) { if(inst.getValue().equals(inAllDataSourcesHash)) { assertTrue("getArtifactInstancesByCaseValues returned instance with unexpected path " + inst.getFilePath(), inAllDataSourcesPath.equalsIgnoreCase(inst.getFilePath())); @@ -867,7 +867,7 @@ public class CentralRepoDatamodelTest extends TestCase { // Test getting instances expecting no results because they are not in the case try { CorrelationCase badCase = new CorrelationCase("badCaseUuid", "badCaseName"); - List instances = EamDb.getInstance().getArtifactInstancesByCaseValues(badCase, Arrays.asList(inAllDataSourcesHash, inDataSource1twiceHash)); + List instances = EamDb.getInstance().getArtifactInstancesByCaseValues(badCase, Arrays.asList(inAllDataSourcesHash, inDataSource1twiceHash), 0); assertTrue("getArtifactInstancesByTypeValue returned " + instances.size() + " results - expected 0", instances.isEmpty()); } catch (EamDbException ex) { @@ -878,7 +878,7 @@ public class CentralRepoDatamodelTest extends TestCase { // Test getting instances expecting no results because of bad hashes try { - List instances = EamDb.getInstance().getArtifactInstancesByCaseValues(null, Arrays.asList("xyz", "123")); + List instances = EamDb.getInstance().getArtifactInstancesByCaseValues(Arrays.asList("xyz", "123")); assertTrue("getArtifactInstancesByTypeValue returned " + instances.size() + " results - expected 0", instances.isEmpty()); } catch (EamDbException ex) { @@ -918,7 +918,7 @@ public class CentralRepoDatamodelTest extends TestCase { // Test getting instances with null value // Should just return nothing try { - List instances = EamDb.getInstance().getArtifactInstancesByCaseValues(null, null); + List instances = EamDb.getInstance().getArtifactInstancesByCaseValues(null); assertTrue("getArtifactInstancesByTypeValue returned non-empty list for null value", instances.isEmpty()); } catch (EamDbException ex) { diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/IngestedWithHashAndFileType.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/IngestedWithHashAndFileType.java deleted file mode 100644 index c44fe079ae..0000000000 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/IngestedWithHashAndFileType.java +++ /dev/null @@ -1,464 +0,0 @@ -/* - * - * Autopsy Forensic Browser - * - * Copyright 2018 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.commonfilessearch; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import junit.framework.Test; -import org.netbeans.junit.NbModuleSuite; -import org.netbeans.junit.NbTestCase; -import org.openide.util.Exceptions; -import org.python.icu.impl.Assert; -import org.sleuthkit.autopsy.casemodule.Case; -import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; -import org.sleuthkit.autopsy.commonfilesearch.AllDataSourcesCommonFilesAlgorithm; -import org.sleuthkit.autopsy.commonfilesearch.CommonFilesMetadata; -import org.sleuthkit.autopsy.commonfilesearch.CommonFilesMetadataBuilder; -import org.sleuthkit.autopsy.commonfilesearch.SingleDataSource; -import static org.sleuthkit.autopsy.commonfilessearch.IntraCaseUtils.*; -import org.sleuthkit.autopsy.ingest.IngestJobSettings; -import org.sleuthkit.autopsy.ingest.IngestJobSettings.IngestType; -import org.sleuthkit.autopsy.ingest.IngestModuleTemplate; -import org.sleuthkit.autopsy.modules.filetypeid.FileTypeIdModuleFactory; -import org.sleuthkit.autopsy.modules.hashdatabase.HashLookupModuleFactory; -import org.sleuthkit.autopsy.testutils.IngestUtils; -import org.sleuthkit.datamodel.AbstractFile; -import org.sleuthkit.datamodel.TskCoreException; - -/** - * Add set 1, set 2, set 3, and set 4 to case and ingest with hash algorithm. - */ -public class IngestedWithHashAndFileType extends NbTestCase { - - public static Test suite() { - NbModuleSuite.Configuration conf = NbModuleSuite.createConfiguration(IngestedWithHashAndFileType.class). - clusters(".*"). - enableModules(".*"); - return conf.suite(); - } - - private final IntraCaseUtils utils; - - public IngestedWithHashAndFileType(String name) { - super(name); - - this.utils = new IntraCaseUtils(this, "IngestedWithHashAndFileTypeTests"); - } - - @Override - public void setUp() { - this.utils.setUp(); - - IngestModuleTemplate hashLookupTemplate = IngestUtils.getIngestModuleTemplate(new HashLookupModuleFactory()); - IngestModuleTemplate mimeTypeLookupTemplate = IngestUtils.getIngestModuleTemplate(new FileTypeIdModuleFactory()); - - ArrayList templates = new ArrayList<>(); - templates.add(hashLookupTemplate); - templates.add(mimeTypeLookupTemplate); - - IngestJobSettings ingestJobSettings = new IngestJobSettings(IngestedWithHashAndFileType.class.getCanonicalName(), IngestType.FILES_ONLY, templates); - - try { - IngestUtils.runIngestJob(Case.getCurrentCaseThrows().getDataSources(), ingestJobSettings); - } catch (NoCurrentCaseException | TskCoreException ex) { - Exceptions.printStackTrace(ex); - Assert.fail(ex); - } - } - - @Override - public void tearDown() { - this.utils.tearDown(); - } - - /** - * Find all matches & all file types. Confirm file.jpg is found on all three - * and file.docx is found on two. - */ - public void testOneA() { - try { - Map dataSources = this.utils.getDataSourceMap(); - - CommonFilesMetadataBuilder allSourcesBuilder = new AllDataSourcesCommonFilesAlgorithm(dataSources, false, false); - CommonFilesMetadata metadata = allSourcesBuilder.findFiles(); - - Map objectIdToDataSource = IntraCaseUtils.mapFileInstancesToDataSources(metadata); - - List files = IntraCaseUtils.getFiles(objectIdToDataSource.keySet()); - - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET1, 2)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET2, 1)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET3, 1)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET4, 0)); - - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET1, 1)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET2, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET3, 1)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET4, 0)); - - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET1, 0)); - assertTrue(IntraCaseUtils.verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET2, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET3, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET4, 0)); - - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET1, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET2, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET3, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET4, 0)); - - } catch (Exception ex) { - Exceptions.printStackTrace(ex); - Assert.fail(ex); - } - } - - /** - * Find all matches & only image types. Confirm file.jpg is found on all - * three. - */ - public void testOneB() { - try { - Map dataSources = this.utils.getDataSourceMap(); - - CommonFilesMetadataBuilder allSourcesBuilder = new AllDataSourcesCommonFilesAlgorithm(dataSources, true, false); - CommonFilesMetadata metadata = allSourcesBuilder.findFiles(); - - Map objectIdToDataSource = mapFileInstancesToDataSources(metadata); - - List files = getFiles(objectIdToDataSource.keySet()); - - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET1, 2)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET2, 1)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET3, 1)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET4, 0)); - - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET1, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET2, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET3, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET4, 0)); - - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET1, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET2, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET3, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET4, 0)); - - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET1, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET2, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET3, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET4, 0)); - - } catch (Exception ex) { - Exceptions.printStackTrace(ex); - Assert.fail(ex); - } - } - - /** - * Find all matches & only image types. Confirm file.jpg is found on all - * three. - */ - public void testOneC() { - try { - Map dataSources = this.utils.getDataSourceMap(); - - CommonFilesMetadataBuilder allSourcesBuilder = new AllDataSourcesCommonFilesAlgorithm(dataSources, false, true); - CommonFilesMetadata metadata = allSourcesBuilder.findFiles(); - - Map objectIdToDataSource = mapFileInstancesToDataSources(metadata); - - List files = getFiles(objectIdToDataSource.keySet()); - - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET1, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET2, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET3, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET4, 0)); - - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET1, 1)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET2, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET3, 1)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET4, 0)); - - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET1, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET2, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET3, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET4, 0)); - - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET1, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET2, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET3, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET4, 0)); - - } catch (Exception ex) { - Exceptions.printStackTrace(ex); - Assert.fail(ex); - } - } - - /** - * Find matches on set 1 & all file types. Confirm same results. - * - */ - public void testTwoA() { - try { - Map dataSources = this.utils.getDataSourceMap(); - Long first = getDataSourceIdByName(SET1, dataSources); - - CommonFilesMetadataBuilder singleSourceBuilder = new SingleDataSource(first, dataSources, false, false); - CommonFilesMetadata metadata = singleSourceBuilder.findFiles(); - - Map objectIdToDataSource = mapFileInstancesToDataSources(metadata); - - List files = getFiles(objectIdToDataSource.keySet()); - - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET1, 2)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET2, 1)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET3, 1)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET4, 0)); - - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET1, 1)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET2, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET3, 1)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET4, 0)); - - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET1, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET2, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET3, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET4, 0)); - - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET1, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET2, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET3, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET4, 0)); - - } catch (Exception ex) { - Exceptions.printStackTrace(ex); - Assert.fail(ex); - } - } - - /** - * Find matches on set 1 & only media types. Confirm same results. - * - */ - public void testTwoB() { - try { - Map dataSources = this.utils.getDataSourceMap(); - Long first = getDataSourceIdByName(SET1, dataSources); - - CommonFilesMetadataBuilder singleSourceBuilder = new SingleDataSource(first, dataSources, true, false); - CommonFilesMetadata metadata = singleSourceBuilder.findFiles(); - - Map objectIdToDataSource = mapFileInstancesToDataSources(metadata); - - List files = getFiles(objectIdToDataSource.keySet()); - - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET1, 2)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET2, 1)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET3, 1)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET4, 0)); - - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET1, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET2, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET3, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET4, 0)); - - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET1, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET2, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET3, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET4, 0)); - - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET1, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET2, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET3, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET4, 0)); - - } catch (Exception ex) { - Exceptions.printStackTrace(ex); - Assert.fail(ex); - } - } - - /** - * Find matches on set 1 & all file types. Confirm same results. - * - */ - public void testTwoC() { - try { - Map dataSources = this.utils.getDataSourceMap(); - Long first = getDataSourceIdByName(SET1, dataSources); - - CommonFilesMetadataBuilder singleSourceBuilder = new SingleDataSource(first, dataSources, false, true); - CommonFilesMetadata metadata = singleSourceBuilder.findFiles(); - - Map objectIdToDataSource = mapFileInstancesToDataSources(metadata); - - List files = getFiles(objectIdToDataSource.keySet()); - - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET1, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET2, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET3, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET4, 0)); - - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET1, 1)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET2, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET3, 1)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET4, 0)); - - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET1, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET2, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET3, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET4, 0)); - - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET1, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET2, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET3, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET4, 0)); - - } catch (Exception ex) { - Exceptions.printStackTrace(ex); - Assert.fail(ex); - } - } - - /** - * Find matches on set 2 & all file types: Confirm file.jpg. - * - */ - public void testThree() { - try { - Map dataSources = this.utils.getDataSourceMap(); - Long second = getDataSourceIdByName(SET2, dataSources); - - CommonFilesMetadataBuilder singleSourceBuilder = new SingleDataSource(second, dataSources, false, false); - CommonFilesMetadata metadata = singleSourceBuilder.findFiles(); - - Map objectIdToDataSource = mapFileInstancesToDataSources(metadata); - - List files = getFiles(objectIdToDataSource.keySet()); - - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET1, 2)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET2, 1)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET3, 1)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET4, 0)); - - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET1, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET2, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET3, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET4, 0)); - - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET1, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET2, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET3, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET4, 0)); - - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET1, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET2, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET3, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET4, 0)); - - } catch (Exception ex) { - Exceptions.printStackTrace(ex); - Assert.fail(ex); - } - } - - /** - * Find matches on set 4 & all file types: Confirm nothing is found. - */ - public void testFour() { - try { - Map dataSources = this.utils.getDataSourceMap(); - Long last = getDataSourceIdByName(SET4, dataSources); - - CommonFilesMetadataBuilder singleSourceBuilder = new SingleDataSource(last, dataSources, false, false); - CommonFilesMetadata metadata = singleSourceBuilder.findFiles(); - - Map objectIdToDataSource = mapFileInstancesToDataSources(metadata); - - List files = getFiles(objectIdToDataSource.keySet()); - - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET1, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET2, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET3, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET4, 0)); - - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET1, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET1, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET3, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET4, 0)); - - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET1, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET2, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET3, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET4, 0)); - - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET1, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET2, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET3, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET4, 0)); - - } catch (Exception ex) { - Exceptions.printStackTrace(ex); - Assert.fail(ex); - } - } - - /** - * Find matches on set 3 & all file types: Confirm file.jpg and file.docx. - */ - public void testFive() { - try { - Map dataSources = this.utils.getDataSourceMap(); - Long third = getDataSourceIdByName(SET3, dataSources); - - CommonFilesMetadataBuilder singleSourceBuilder = new SingleDataSource(third, dataSources, false, false); - CommonFilesMetadata metadata = singleSourceBuilder.findFiles(); - - Map objectIdToDataSource = mapFileInstancesToDataSources(metadata); - - List files = getFiles(objectIdToDataSource.keySet()); - - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET1, 2)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET2, 1)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET3, 1)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET4, 0)); - - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET1, 1)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET2, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET3, 1)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET4, 0)); - - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET1, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET2, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET3, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET4, 0)); - - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET1, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET2, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET3, 0)); - assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET4, 0)); - - } catch (Exception ex) { - Exceptions.printStackTrace(ex); - Assert.fail(ex); - } - } -} diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/IngestedWithHashAndFileTypeInterCaseTests.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/IngestedWithHashAndFileTypeInterCaseTests.java new file mode 100644 index 0000000000..9538fe6549 --- /dev/null +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/IngestedWithHashAndFileTypeInterCaseTests.java @@ -0,0 +1,103 @@ +/* + * + * Autopsy Forensic Browser + * + * Copyright 2018 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.commonfilessearch; + +import java.sql.SQLException; +import java.util.Map; +import junit.framework.Test; +import org.netbeans.junit.NbModuleSuite; +import org.netbeans.junit.NbTestCase; +import org.openide.util.Exceptions; +import org.python.icu.impl.Assert; +import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException; +import org.sleuthkit.autopsy.commonfilesearch.AllCasesEamDbCommonFilesAlgorithm; +import org.sleuthkit.autopsy.commonfilesearch.CommonFilesMetadata; +import org.sleuthkit.autopsy.commonfilesearch.CommonFilesMetadataBuilder; +import org.sleuthkit.datamodel.TskCoreException; + +/** + * If I use the search all cases option: One node for Hash A (1_1_A.jpg, + * 1_2_A.jpg, 3_1_A.jpg) If I search for matches only in Case 1: One node for + * Hash A (1_1_A.jpg, 1_2_A.jpg, 3_1_A.jpg) If I search for matches only in Case + * 2: No matches If I only search in the current case (existing mode), allowing + * all data sources: One node for Hash C (3_1_C.jpg, 3_2_C.jpg) + */ +public class IngestedWithHashAndFileTypeInterCaseTests extends NbTestCase { + + private final InterCaseUtils utils; + + private Case currentCase; + + public static Test suite() { + NbModuleSuite.Configuration conf = NbModuleSuite.createConfiguration(IngestedWithHashAndFileTypeInterCaseTests.class). + clusters(".*"). + enableModules(".*"); + return conf.suite(); + } + + public IngestedWithHashAndFileTypeInterCaseTests(String name) { + super(name); + this.utils = new InterCaseUtils(this); + } + + @Override + public void setUp(){ + this.utils.clearTestDir(); + try { + this.utils.enableCentralRepo(); + this.currentCase = this.utils.createCases(this.utils.getIngestSettingsForHashAndFileType(), InterCaseUtils.CASE3); + } catch (Exception ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + } + + @Override + public void tearDown(){ + this.utils.tearDown(); + } + + /** + * Search All + * + * One node for Hash A (1_1_A.jpg, 1_2_A.jpg, 3_1_A.jpg) + */ + public void testOne() { + try { + //this is proabbly not needed and should be pulled out of the constructor if possible + Map dataSources = this.utils.getDataSourceMap(); + + CommonFilesMetadataBuilder builder = new AllCasesEamDbCommonFilesAlgorithm(dataSources, false, false); + + CommonFilesMetadata metadata = builder.findFiles(); + + assertTrue("Results should not be empty", metadata.size() != 0); + + //assertTrue("") + + + } catch (Exception ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + } +} diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/IngestedWithHashAndFileTypeIntraCaseTests.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/IngestedWithHashAndFileTypeIntraCaseTests.java new file mode 100644 index 0000000000..e9e538c004 --- /dev/null +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/IngestedWithHashAndFileTypeIntraCaseTests.java @@ -0,0 +1,464 @@ +/* + * + * Autopsy Forensic Browser + * + * Copyright 2018 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.commonfilessearch; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import junit.framework.Test; +import org.netbeans.junit.NbModuleSuite; +import org.netbeans.junit.NbTestCase; +import org.openide.util.Exceptions; +import org.python.icu.impl.Assert; +import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; +import org.sleuthkit.autopsy.commonfilesearch.AllDataSourcesCommonFilesAlgorithm; +import org.sleuthkit.autopsy.commonfilesearch.CommonFilesMetadata; +import org.sleuthkit.autopsy.commonfilesearch.CommonFilesMetadataBuilder; +import org.sleuthkit.autopsy.commonfilesearch.SingleDataSource; +import static org.sleuthkit.autopsy.commonfilessearch.IntraCaseUtils.*; +import org.sleuthkit.autopsy.ingest.IngestJobSettings; +import org.sleuthkit.autopsy.ingest.IngestJobSettings.IngestType; +import org.sleuthkit.autopsy.ingest.IngestModuleTemplate; +import org.sleuthkit.autopsy.modules.filetypeid.FileTypeIdModuleFactory; +import org.sleuthkit.autopsy.modules.hashdatabase.HashLookupModuleFactory; +import org.sleuthkit.autopsy.testutils.IngestUtils; +import org.sleuthkit.datamodel.AbstractFile; +import org.sleuthkit.datamodel.TskCoreException; + +/** + * Add set 1, set 2, set 3, and set 4 to case and ingest with hash algorithm. + */ +public class IngestedWithHashAndFileTypeIntraCaseTests extends NbTestCase { + + public static Test suite() { + NbModuleSuite.Configuration conf = NbModuleSuite.createConfiguration(IngestedWithHashAndFileTypeIntraCaseTests.class). + clusters(".*"). + enableModules(".*"); + return conf.suite(); + } + + private final IntraCaseUtils utils; + + public IngestedWithHashAndFileTypeIntraCaseTests(String name) { + super(name); + + this.utils = new IntraCaseUtils(this, "IngestedWithHashAndFileTypeTests"); + } + + @Override + public void setUp() { + this.utils.setUp(); + + IngestModuleTemplate hashLookupTemplate = IngestUtils.getIngestModuleTemplate(new HashLookupModuleFactory()); + IngestModuleTemplate mimeTypeLookupTemplate = IngestUtils.getIngestModuleTemplate(new FileTypeIdModuleFactory()); + + ArrayList templates = new ArrayList<>(); + templates.add(hashLookupTemplate); + templates.add(mimeTypeLookupTemplate); + + IngestJobSettings ingestJobSettings = new IngestJobSettings(IngestedWithHashAndFileTypeIntraCaseTests.class.getCanonicalName(), IngestType.FILES_ONLY, templates); + + try { + IngestUtils.runIngestJob(Case.getCurrentCaseThrows().getDataSources(), ingestJobSettings); + } catch (NoCurrentCaseException | TskCoreException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + } + + @Override + public void tearDown() { + this.utils.tearDown(); + } + + /** + * Find all matches & all file types. Confirm file.jpg is found on all three + * and file.docx is found on two. + */ + public void testOneA() { + try { + Map dataSources = this.utils.getDataSourceMap(); + + CommonFilesMetadataBuilder allSourcesBuilder = new AllDataSourcesCommonFilesAlgorithm(dataSources, false, false); + CommonFilesMetadata metadata = allSourcesBuilder.findFiles(); + + Map objectIdToDataSource = IntraCaseUtils.mapFileInstancesToDataSources(metadata); + + List files = IntraCaseUtils.getFiles(objectIdToDataSource.keySet()); + + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, IMG, SET1, 2)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, IMG, SET2, 1)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, IMG, SET3, 1)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, IMG, SET4, 0)); + + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, DOC, SET1, 1)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, DOC, SET2, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, DOC, SET3, 1)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, DOC, SET4, 0)); + + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, PDF, SET1, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, PDF, SET2, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, PDF, SET3, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, PDF, SET4, 0)); + + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, EMPTY, SET1, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, EMPTY, SET2, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, EMPTY, SET3, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, EMPTY, SET4, 0)); + + } catch (Exception ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + } + + /** + * Find all matches & only image types. Confirm file.jpg is found on all + * three. + */ + public void testOneB() { + try { + Map dataSources = this.utils.getDataSourceMap(); + + CommonFilesMetadataBuilder allSourcesBuilder = new AllDataSourcesCommonFilesAlgorithm(dataSources, true, false); + CommonFilesMetadata metadata = allSourcesBuilder.findFiles(); + + Map objectIdToDataSource = mapFileInstancesToDataSources(metadata); + + List files = getFiles(objectIdToDataSource.keySet()); + + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, IMG, SET1, 2)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, IMG, SET2, 1)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, IMG, SET3, 1)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, IMG, SET4, 0)); + + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, DOC, SET1, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, DOC, SET2, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, DOC, SET3, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, DOC, SET4, 0)); + + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, PDF, SET1, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, PDF, SET2, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, PDF, SET3, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, PDF, SET4, 0)); + + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, EMPTY, SET1, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, EMPTY, SET2, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, EMPTY, SET3, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, EMPTY, SET4, 0)); + + } catch (Exception ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + } + + /** + * Find all matches & only image types. Confirm file.jpg is found on all + * three. + */ + public void testOneC() { + try { + Map dataSources = this.utils.getDataSourceMap(); + + CommonFilesMetadataBuilder allSourcesBuilder = new AllDataSourcesCommonFilesAlgorithm(dataSources, false, true); + CommonFilesMetadata metadata = allSourcesBuilder.findFiles(); + + Map objectIdToDataSource = mapFileInstancesToDataSources(metadata); + + List files = getFiles(objectIdToDataSource.keySet()); + + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, IMG, SET1, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, IMG, SET2, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, IMG, SET3, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, IMG, SET4, 0)); + + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, DOC, SET1, 1)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, DOC, SET2, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, DOC, SET3, 1)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, DOC, SET4, 0)); + + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, PDF, SET1, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, PDF, SET2, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, PDF, SET3, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, PDF, SET4, 0)); + + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, EMPTY, SET1, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, EMPTY, SET2, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, EMPTY, SET3, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, EMPTY, SET4, 0)); + + } catch (Exception ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + } + + /** + * Find matches on set 1 & all file types. Confirm same results. + * + */ + public void testTwoA() { + try { + Map dataSources = this.utils.getDataSourceMap(); + Long first = getDataSourceIdByName(SET1, dataSources); + + CommonFilesMetadataBuilder singleSourceBuilder = new SingleDataSource(first, dataSources, false, false); + CommonFilesMetadata metadata = singleSourceBuilder.findFiles(); + + Map objectIdToDataSource = mapFileInstancesToDataSources(metadata); + + List files = getFiles(objectIdToDataSource.keySet()); + + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, IMG, SET1, 2)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, IMG, SET2, 1)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, IMG, SET3, 1)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, IMG, SET4, 0)); + + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, DOC, SET1, 1)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, DOC, SET2, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, DOC, SET3, 1)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, DOC, SET4, 0)); + + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, PDF, SET1, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, PDF, SET2, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, PDF, SET3, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, PDF, SET4, 0)); + + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, EMPTY, SET1, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, EMPTY, SET2, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, EMPTY, SET3, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, EMPTY, SET4, 0)); + + } catch (Exception ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + } + + /** + * Find matches on set 1 & only media types. Confirm same results. + * + */ + public void testTwoB() { + try { + Map dataSources = this.utils.getDataSourceMap(); + Long first = getDataSourceIdByName(SET1, dataSources); + + CommonFilesMetadataBuilder singleSourceBuilder = new SingleDataSource(first, dataSources, true, false); + CommonFilesMetadata metadata = singleSourceBuilder.findFiles(); + + Map objectIdToDataSource = mapFileInstancesToDataSources(metadata); + + List files = getFiles(objectIdToDataSource.keySet()); + + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, IMG, SET1, 2)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, IMG, SET2, 1)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, IMG, SET3, 1)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, IMG, SET4, 0)); + + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, DOC, SET1, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, DOC, SET2, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, DOC, SET3, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, DOC, SET4, 0)); + + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, PDF, SET1, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, PDF, SET2, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, PDF, SET3, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, PDF, SET4, 0)); + + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, EMPTY, SET1, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, EMPTY, SET2, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, EMPTY, SET3, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, EMPTY, SET4, 0)); + + } catch (Exception ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + } + + /** + * Find matches on set 1 & all file types. Confirm same results. + * + */ + public void testTwoC() { + try { + Map dataSources = this.utils.getDataSourceMap(); + Long first = getDataSourceIdByName(SET1, dataSources); + + CommonFilesMetadataBuilder singleSourceBuilder = new SingleDataSource(first, dataSources, false, true); + CommonFilesMetadata metadata = singleSourceBuilder.findFiles(); + + Map objectIdToDataSource = mapFileInstancesToDataSources(metadata); + + List files = getFiles(objectIdToDataSource.keySet()); + + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, IMG, SET1, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, IMG, SET2, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, IMG, SET3, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, IMG, SET4, 0)); + + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, DOC, SET1, 1)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, DOC, SET2, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, DOC, SET3, 1)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, DOC, SET4, 0)); + + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, PDF, SET1, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, PDF, SET2, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, PDF, SET3, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, PDF, SET4, 0)); + + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, EMPTY, SET1, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, EMPTY, SET2, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, EMPTY, SET3, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, EMPTY, SET4, 0)); + + } catch (Exception ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + } + + /** + * Find matches on set 2 & all file types: Confirm file.jpg. + * + */ + public void testThree() { + try { + Map dataSources = this.utils.getDataSourceMap(); + Long second = getDataSourceIdByName(SET2, dataSources); + + CommonFilesMetadataBuilder singleSourceBuilder = new SingleDataSource(second, dataSources, false, false); + CommonFilesMetadata metadata = singleSourceBuilder.findFiles(); + + Map objectIdToDataSource = mapFileInstancesToDataSources(metadata); + + List files = getFiles(objectIdToDataSource.keySet()); + + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, IMG, SET1, 2)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, IMG, SET2, 1)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, IMG, SET3, 1)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, IMG, SET4, 0)); + + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, DOC, SET1, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, DOC, SET2, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, DOC, SET3, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, DOC, SET4, 0)); + + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, PDF, SET1, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, PDF, SET2, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, PDF, SET3, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, PDF, SET4, 0)); + + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, EMPTY, SET1, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, EMPTY, SET2, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, EMPTY, SET3, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, EMPTY, SET4, 0)); + + } catch (Exception ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + } + + /** + * Find matches on set 4 & all file types: Confirm nothing is found. + */ + public void testFour() { + try { + Map dataSources = this.utils.getDataSourceMap(); + Long last = getDataSourceIdByName(SET4, dataSources); + + CommonFilesMetadataBuilder singleSourceBuilder = new SingleDataSource(last, dataSources, false, false); + CommonFilesMetadata metadata = singleSourceBuilder.findFiles(); + + Map objectIdToDataSource = mapFileInstancesToDataSources(metadata); + + List files = getFiles(objectIdToDataSource.keySet()); + + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, IMG, SET1, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, IMG, SET2, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, IMG, SET3, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, IMG, SET4, 0)); + + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, DOC, SET1, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, DOC, SET1, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, DOC, SET3, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, DOC, SET4, 0)); + + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, PDF, SET1, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, PDF, SET2, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, PDF, SET3, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, PDF, SET4, 0)); + + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, EMPTY, SET1, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, EMPTY, SET2, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, EMPTY, SET3, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, EMPTY, SET4, 0)); + + } catch (Exception ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + } + + /** + * Find matches on set 3 & all file types: Confirm file.jpg and file.docx. + */ + public void testFive() { + try { + Map dataSources = this.utils.getDataSourceMap(); + Long third = getDataSourceIdByName(SET3, dataSources); + + CommonFilesMetadataBuilder singleSourceBuilder = new SingleDataSource(third, dataSources, false, false); + CommonFilesMetadata metadata = singleSourceBuilder.findFiles(); + + Map objectIdToDataSource = mapFileInstancesToDataSources(metadata); + + List files = getFiles(objectIdToDataSource.keySet()); + + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, IMG, SET1, 2)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, IMG, SET2, 1)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, IMG, SET3, 1)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, IMG, SET4, 0)); + + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, DOC, SET1, 1)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, DOC, SET2, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, DOC, SET3, 1)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, DOC, SET4, 0)); + + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, PDF, SET1, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, PDF, SET2, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, PDF, SET3, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, PDF, SET4, 0)); + + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, EMPTY, SET1, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, EMPTY, SET2, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, EMPTY, SET3, 0)); + assertTrue(verifyInstanceExistanceAndCount(files, objectIdToDataSource, EMPTY, SET4, 0)); + + } catch (Exception ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + } +} diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/IngestedWithNoFileTypes.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/IngestedWithNoFileTypesIntraCaseTests.java similarity index 93% rename from Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/IngestedWithNoFileTypes.java rename to Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/IngestedWithNoFileTypesIntraCaseTests.java index 1333ac135f..4d14417efc 100644 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/IngestedWithNoFileTypes.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/IngestedWithNoFileTypesIntraCaseTests.java @@ -50,10 +50,10 @@ import org.sleuthkit.datamodel.TskCoreException; * Add images set 1, set 2, set 3, and set 4 to case. Do not run mime type * module. */ -public class IngestedWithNoFileTypes extends NbTestCase { +public class IngestedWithNoFileTypesIntraCaseTests extends NbTestCase { public static Test suite() { - NbModuleSuite.Configuration conf = NbModuleSuite.createConfiguration(IngestedWithNoFileTypes.class). + NbModuleSuite.Configuration conf = NbModuleSuite.createConfiguration(IngestedWithNoFileTypesIntraCaseTests.class). clusters(".*"). enableModules(".*"); return conf.suite(); @@ -61,7 +61,7 @@ public class IngestedWithNoFileTypes extends NbTestCase { private final IntraCaseUtils utils; - public IngestedWithNoFileTypes(String name) { + public IngestedWithNoFileTypesIntraCaseTests(String name) { super(name); this.utils = new IntraCaseUtils(this, "IngestedWithNoFileTypes"); @@ -76,7 +76,7 @@ public class IngestedWithNoFileTypes extends NbTestCase { ArrayList templates = new ArrayList<>(); templates.add(hashLookupTemplate); - IngestJobSettings ingestJobSettings = new IngestJobSettings(IngestedWithNoFileTypes.class.getCanonicalName(), IngestJobSettings.IngestType.FILES_ONLY, templates); + IngestJobSettings ingestJobSettings = new IngestJobSettings(IngestedWithNoFileTypesIntraCaseTests.class.getCanonicalName(), IngestJobSettings.IngestType.FILES_ONLY, templates); try { IngestUtils.runIngestJob(Case.getCurrentCaseThrows().getDataSources(), ingestJobSettings); @@ -110,6 +110,7 @@ public class IngestedWithNoFileTypes extends NbTestCase { } catch (Exception ex) { Exceptions.printStackTrace(ex); + Assert.fail(ex); } } diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/InterCaseUtils.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/InterCaseUtils.java index ceb587ed8d..4025563d2c 100644 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/InterCaseUtils.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/InterCaseUtils.java @@ -19,13 +19,20 @@ */ package org.sleuthkit.autopsy.commonfilessearch; +import java.io.File; import java.io.IOException; import java.nio.file.Path; import java.nio.file.Paths; import java.sql.SQLException; import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; import java.util.Map; +import java.util.Map.Entry; +import org.apache.commons.io.FileUtils; import org.netbeans.junit.NbTestCase; +import org.openide.util.Exceptions; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.ImageDSProcessor; import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException; @@ -42,7 +49,13 @@ import org.sleuthkit.autopsy.testutils.IngestUtils; import org.sleuthkit.datamodel.TskCoreException; import org.python.icu.impl.Assert; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; +import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationCase; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb; +import org.sleuthkit.autopsy.commonfilesearch.CommonFilesMetadata; import org.sleuthkit.autopsy.commonfilesearch.DataSourceLoader; +import org.sleuthkit.autopsy.commonfilesearch.FileInstanceMetadata; +import org.sleuthkit.autopsy.commonfilesearch.Md5Metadata; +import org.sleuthkit.datamodel.AbstractFile; /** * Utilities for testing intercase correlation feature. @@ -53,11 +66,11 @@ import org.sleuthkit.autopsy.commonfilesearch.DataSourceLoader; * * Case 1 * +Data Set 1 - * - Hash-0.dat [file of size 0] + * - Hash-0.dat [file of size 0] * - Hash-A.jpg * - Hash-A.pdf * +Data Set2 - * - Hash-0.dat [file of size -0] + * - Hash-0.dat [file of size -0] * - Hash-A.jpg * - Hash-A.pdf * Case 2 @@ -72,32 +85,31 @@ import org.sleuthkit.autopsy.commonfilesearch.DataSourceLoader; * +Data Set 1 * - Hash-A.jpg * - Hash-A.pdf - * - Hash-C.jpg - * - Hash-C.pdf + * - Hash-C.jpg [we should never find these!] + * - Hash-C.pdf [we should never find these!] * - Hash-D.jpg * +Data Set 2 - * - Hash-C.jpg + * - Hash-C.jpg [we should never find these!] * - Hash-C.pdf * - Hash.D-doc */ class InterCaseUtils { - - private static final String CASE_NAME = "InterCaseCommonFilesSearchTest"; - private static final Path CASE_DIRECTORY_PATH = Paths.get(System.getProperty("java.io.tmpdir"), CASE_NAME); + + private static final Path CASE_DIRECTORY_PATH = Paths.get(System.getProperty("java.io.tmpdir"), "InterCaseCommonFilesSearchTest"); private static final String CR_DB_NAME = "testcentralrepo.db"; static final String CASE1 = "Case1"; static final String CASE2 = "Case2"; static final String CASE3 = "Case3"; static final String CASE4 = "Case4"; - + final Path case1DataSet1Path; final Path case1DataSet2Path; final Path case2DataSet1Path; final Path case2DataSet2Path; final Path case3DataSet1Path; final Path case3DataSet2Path; - + static final String HASH_0_DAT = "Hash-0.dat"; static final String HASH_A_JPG = "Hash-A.jpg"; static final String HASH_A_PDF = "Hash-A.pdf"; @@ -107,144 +119,220 @@ class InterCaseUtils { static final String HASH_C_PDF = "Hash-C.pdf"; static final String HASH_D_JPG = "Hash-D.jpg"; static final String HASH_D_DOC = "Hash-D.doc"; - - static final String CASE1_DATASET_1 = "c1ds1.vhd"; - static final String CASE1_DATASET_2 = "c1ds2.vhd"; - static final String CASE2_DATASET_1 = "c2ds1.vhd"; - static final String CASE2_DATASET_2 = "c2ds2.vhd"; - static final String CASE3_DATASET_1 = "c3ds1.vhd"; - static final String CASE3_DATASET_2 = "c3ds2.vhd"; - + + static final String CASE1_DATASET_1 = "c1ds1_v1.vhd"; + static final String CASE1_DATASET_2 = "c1ds2_v1.vhd"; + static final String CASE2_DATASET_1 = "c2ds1_v1.vhd"; + static final String CASE2_DATASET_2 = "c2ds2_v1.vhd"; + static final String CASE3_DATASET_1 = "c3ds1_v1.vhd"; + static final String CASE3_DATASET_2 = "c3ds2_v1.vhd"; + private final ImageDSProcessor imageDSProcessor; - + private final IngestJobSettings hashAndFileType; private final IngestJobSettings hashAndNoFileType; - private DataSourceLoader dataSourceLoader; - - - - InterCaseUtils(NbTestCase testCase){ - + private final DataSourceLoader dataSourceLoader; + + InterCaseUtils(NbTestCase testCase) { + this.case1DataSet1Path = Paths.get(testCase.getDataDir().toString(), CASE1_DATASET_1); this.case1DataSet2Path = Paths.get(testCase.getDataDir().toString(), CASE1_DATASET_2); this.case2DataSet1Path = Paths.get(testCase.getDataDir().toString(), CASE1_DATASET_1); this.case2DataSet2Path = Paths.get(testCase.getDataDir().toString(), CASE2_DATASET_2); this.case3DataSet1Path = Paths.get(testCase.getDataDir().toString(), CASE3_DATASET_1); this.case3DataSet2Path = Paths.get(testCase.getDataDir().toString(), CASE3_DATASET_2); - + this.imageDSProcessor = new ImageDSProcessor(); - + final IngestModuleTemplate hashLookupTemplate = IngestUtils.getIngestModuleTemplate(new HashLookupModuleFactory()); final IngestModuleTemplate mimeTypeLookupTemplate = IngestUtils.getIngestModuleTemplate(new FileTypeIdModuleFactory()); - + final IngestModuleTemplate eamDbTemplate = IngestUtils.getIngestModuleTemplate(new org.sleuthkit.autopsy.centralrepository.ingestmodule.IngestModuleFactory()); + ArrayList hashAndMimeTemplate = new ArrayList<>(2); hashAndMimeTemplate.add(hashLookupTemplate); hashAndMimeTemplate.add(mimeTypeLookupTemplate); - + hashAndMimeTemplate.add(eamDbTemplate); + this.hashAndFileType = new IngestJobSettings(InterCaseUtils.class.getCanonicalName(), IngestType.FILES_ONLY, hashAndMimeTemplate); - + ArrayList hashAndNoMimeTemplate = new ArrayList<>(1); hashAndNoMimeTemplate.add(hashLookupTemplate); - + hashAndMimeTemplate.add(eamDbTemplate); + this.hashAndNoFileType = new IngestJobSettings(InterCaseUtils.class.getCanonicalName(), IngestType.FILES_ONLY, hashAndNoMimeTemplate); - + this.dataSourceLoader = new DataSourceLoader(); } - - Map getDataSourceMap() throws NoCurrentCaseException, TskCoreException, SQLException{ + + void clearTestDir(){ + if(CASE_DIRECTORY_PATH.toFile().exists()){ + try{ + FileUtils.deleteDirectory(CASE_DIRECTORY_PATH.toFile()); + } catch(IOException ex){ + Assert.fail(ex); + } + } + CASE_DIRECTORY_PATH.toFile().exists(); + } + + Map getDataSourceMap() throws NoCurrentCaseException, TskCoreException, SQLException { return this.dataSourceLoader.getDataSourceMap(); } - - IngestJobSettings getIngestSettingsForHashAndFileType(){ + + Map getCaseMap() throws EamDbException { + + if (EamDb.isEnabled()) { + Map mapOfCaseIdsToCase = new HashMap<>(); + + for (CorrelationCase caze : EamDb.getInstance().getCases()) { + mapOfCaseIdsToCase.put(caze.getID(), caze.getDisplayName()); + } + return mapOfCaseIdsToCase; + } else { + //it is reasonable that this might happen... + // for example when we test the feature in the absence of an enabled eamdb + return new HashMap(0); + } + } + + IngestJobSettings getIngestSettingsForHashAndFileType() { return this.hashAndFileType; } - - IngestJobSettings getIngestSettingsForHashAndNoFileType(){ + + IngestJobSettings getIngestSettingsForHashAndNoFileType() { return this.hashAndNoFileType; } - - void enableCentralRepo() throws EamDbException{ - + + void enableCentralRepo() throws EamDbException { + SqliteEamDbSettings crSettings = new SqliteEamDbSettings(); crSettings.setDbName(CR_DB_NAME); crSettings.setDbDirectory(CASE_DIRECTORY_PATH.toString()); - if(!crSettings.dbDirectoryExists()){ + if (!crSettings.dbDirectoryExists()) { crSettings.createDbDirectory(); } + crSettings.initializeDatabaseSchema(); + crSettings.insertDefaultDatabaseContent(); + + crSettings.saveSettings(); + EamDbUtil.setUseCentralRepo(true); EamDbPlatformEnum.setSelectedPlatform(EamDbPlatformEnum.SQLITE.name()); EamDbPlatformEnum.saveSelectedPlatform(); } - + /** - * Create 3 cases and ingest each with the given settings. Null settings - * are permitted but IngestUtils will not be run. - * + * Create 3 cases and ingest each with the given settings. Null settings are + * permitted but IngestUtils will not be run. + * * @param ingestJobSettings HashLookup FileType etc... - * @param caseReferenceToStore + * @param caseReferenceToStore */ - Case createCases(IngestJobSettings ingestJobSettings, String caseReferenceToStore) throws TskCoreException{ - + Case createCases(IngestJobSettings ingestJobSettings, String caseReferenceToStore) throws TskCoreException { + Case currentCase = null; - + String[] cases = new String[]{ - CASE1, - CASE2, + CASE1, + CASE2, CASE3}; - + Path[][] paths = { {this.case1DataSet1Path, this.case1DataSet2Path}, {this.case2DataSet1Path, this.case2DataSet2Path}, {this.case3DataSet1Path, this.case3DataSet2Path}}; + String lastCaseName = null; + Path[] lastPathsForCase = null; //iterate over the collecitons above, creating cases, and storing // just one of them for future reference - for(int i = 0; i >= cases.length; i++){ + for (int i = 0; i < cases.length; i++) { String caseName = cases[i]; Path[] pathsForCase = paths[i]; - if(caseName.equals(caseReferenceToStore)){ - //hang onto this caes and dont close it - currentCase = this.createCase(caseName, ingestJobSettings, true, pathsForCase); + if (caseName.equals(caseReferenceToStore)) { + //put aside and do this one last so we can hang onto the case + lastCaseName = caseName; + lastPathsForCase = pathsForCase; } else { //dont hang onto this case; close it this.createCase(caseName, ingestJobSettings, false, pathsForCase); } } - - if(currentCase == null) { + + if (lastCaseName != null && lastPathsForCase != null) { + //hang onto this caes and dont close it + currentCase = this.createCase(lastCaseName, ingestJobSettings, true, lastPathsForCase); + } + + if (currentCase == null) { Assert.fail(new IllegalArgumentException("caseReferenceToStore should be one of: CASE1, CASE2, CASE3")); return null; } else { return currentCase; } } - - private Case createCase(String caseName, IngestJobSettings ingestJobSettings, boolean keepAlive, Path... dataSetPaths) throws TskCoreException{ - + + private Case createCase(String caseName, IngestJobSettings ingestJobSettings, boolean keepAlive, Path... dataSetPaths) throws TskCoreException { + Case caze = CaseUtils.createAsCurrentCase(caseName); - for(Path dataSetPath : dataSetPaths){ + for (Path dataSetPath : dataSetPaths) { IngestUtils.addDataSource(this.imageDSProcessor, dataSetPath); } - if(ingestJobSettings != null){ + if (ingestJobSettings != null) { IngestUtils.runIngestJob(caze.getDataSources(), ingestJobSettings); } - if(keepAlive){ - return caze; + if (keepAlive) { + return caze; } else { CaseUtils.closeCurrentCase(false); return null; } } - /** - * Close the currently open case, delete the case directory, - * delete the central repo db. - */ - void tearDown() throws IOException{ - CaseUtils.closeCurrentCase(false); - CaseUtils.deleteCaseDir(CASE_DIRECTORY_PATH.toFile()); + static boolean verifyInstanceExistanceAndCount(CommonFilesMetadata searchDomain, String fileName, String dataSource, String crCase, int instanceCount){ + + int tally = 0; + + for(Map.Entry file : searchDomain.getMetadata().entrySet()){ + + Collection fileInstances = file.getValue().getMetadata(); + + for(FileInstanceMetadata fileInstance : fileInstances){ + + + } + } + + return false; } + static Map mapFileInstancesToDataSource(CommonFilesMetadata metadata){ + return IntraCaseUtils.mapFileInstancesToDataSources(metadata); + } + +// static List getFiles(Set md5s){ +// +// } + + /** + * Close the currently open case, delete the case directory, delete the + * central repo db. + */ + void tearDown() { + + CaseUtils.closeCurrentCase(false); + + String[] cases = new String[]{CASE1,CASE2,CASE3}; + + try { + for(String caze : cases){ + CaseUtils.deleteCaseDir(new File(caze)); + } + } catch (IOException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + } } diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/IntraCaseUtils.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/IntraCaseUtils.java index 4e23ecffa2..e372cf7af3 100644 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/IntraCaseUtils.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/IntraCaseUtils.java @@ -74,10 +74,10 @@ class IntraCaseUtils { private static final String CASE_NAME = "IntraCaseCommonFilesSearchTest"; static final Path CASE_DIRECTORY_PATH = Paths.get(System.getProperty("java.io.tmpdir"), CASE_NAME); - final Path imagePath1; - final Path imagePath2; - final Path imagePath3; - final Path imagePath4; + private final Path imagePath1; + private final Path imagePath2; + private final Path imagePath3; + private final Path imagePath4; static final String IMG = "IMG_6175.jpg"; static final String DOC = "BasicStyleGuide.doc"; @@ -133,32 +133,32 @@ class IntraCaseUtils { * Verify that the given file appears a precise number times in the given * data source. * - * @param files search domain - * @param objectIdToDataSource mapping of file ids to data source names - * @param name name of file to search for + * @param searchDomain search domain + * @param objectIdToDataSourceMap mapping of file ids to data source names + * @param fileName name of file to search for * @param dataSource name of data source where file should appear - * @param count number of appearances of the given file + * @param instanceCount number of appearances of the given file * @return true if a file with the given name exists the specified number - * of times in the given data source + * of times in the given data source */ - static boolean verifyFileExistanceAndCount(List files, Map objectIdToDataSource, String name, String dataSource, int count) { + static boolean verifyInstanceExistanceAndCount(List searchDomain, Map objectIdToDataSourceMap, String fileName, String dataSource, int instanceCount) { int tally = 0; - for (AbstractFile file : files) { + for (AbstractFile file : searchDomain) { Long objectId = file.getId(); - String fileName = file.getName(); + String name = file.getName(); - String dataSourceName = objectIdToDataSource.get(objectId); + String dataSourceName = objectIdToDataSourceMap.get(objectId); - if (fileName.equals(name) && dataSourceName.equals(dataSource)) { + if (name.equals(name) && dataSourceName.equals(dataSource)) { tally++; } } - return tally == count; + return tally == instanceCount; } /** @@ -172,10 +172,17 @@ class IntraCaseUtils { * @return true if a file with the given name exists once in the given data * source */ - static boolean verifySingularFileExistance(List files, Map objectIdToDataSource, String name, String dataSource) { - return verifyFileExistanceAndCount(files, objectIdToDataSource, name, dataSource, 1); + static boolean verifySingularInstanceExistance(List files, Map objectIdToDataSource, String name, String dataSource) { + return verifyInstanceExistanceAndCount(files, objectIdToDataSource, name, dataSource, 1); } + /** + * Create a convenience lookup table mapping file instance object ids to + * the data source they appear in. + * + * @param metadata object returned by the code under test + * @return mapping of objectId to data source name + */ static Map mapFileInstancesToDataSources(CommonFilesMetadata metadata) { Map instanceIdToDataSource = new HashMap<>(); @@ -188,6 +195,7 @@ class IntraCaseUtils { return instanceIdToDataSource; } + static List getFiles(Set objectIds) { List files = new ArrayList<>(objectIds.size()); diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/NoCentralRepoEnabledTests.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/NoCentralRepoEnabledInterCaseTests.java similarity index 59% rename from Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/NoCentralRepoEnabledTests.java rename to Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/NoCentralRepoEnabledInterCaseTests.java index 7f79c16a8a..276229213a 100644 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/NoCentralRepoEnabledTests.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/NoCentralRepoEnabledInterCaseTests.java @@ -20,6 +20,7 @@ package org.sleuthkit.autopsy.commonfilessearch; import java.io.IOException; +import java.util.Map; import junit.framework.Test; import org.netbeans.junit.NbModuleSuite; import org.netbeans.junit.NbTestCase; @@ -27,35 +28,36 @@ import org.openide.util.Exceptions; import org.sleuthkit.datamodel.TskCoreException; import org.python.icu.impl.Assert; import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.commonfilesearch.AllCasesEamDbCommonFilesAlgorithm; +import org.sleuthkit.autopsy.commonfilesearch.CommonFilesMetadata; +import org.sleuthkit.autopsy.commonfilesearch.CommonFilesMetadataBuilder; /** * - * If I use the search all cases option: One node for Hash A (1_1_A.jpg, - * 1_2_A.jpg, 3_1_A.jpg) If I search for matches only in Case 1: One node for - * Hash A (1_1_A.jpg, 1_2_A.jpg, 3_1_A.jpg) If I search for matches only in Case - * 2: No matches If I only search in the current case (existing mode), allowing - * all data sources: One node for Hash C (3_1_C.jpg, 3_2_C.jpg) + * Just make sure nothing explodes when we run the feature in the absence of + * the Central Repo. This should be considered 'defensive' as it should not be + * possible to even run the feature if the CR is not available. * */ -public class NoCentralRepoEnabledTests extends NbTestCase { +public class NoCentralRepoEnabledInterCaseTests extends NbTestCase { private final InterCaseUtils utils; - private Case currentCase; - + private Case currentCase; //TODO do we need this??? + public static Test suite() { - NbModuleSuite.Configuration conf = NbModuleSuite.createConfiguration(NoCentralRepoEnabledTests.class). + NbModuleSuite.Configuration conf = NbModuleSuite.createConfiguration(NoCentralRepoEnabledInterCaseTests.class). clusters(".*"). enableModules(".*"); return conf.suite(); } - public NoCentralRepoEnabledTests(String name) { + public NoCentralRepoEnabledInterCaseTests(String name) { super(name); this.utils = new InterCaseUtils(this); } - + @Override - public void setUp(){ + public void setUp() { try { this.currentCase = this.utils.createCases(this.utils.getIngestSettingsForHashAndFileType(), InterCaseUtils.CASE1); } catch (TskCoreException ex) { @@ -63,19 +65,24 @@ public class NoCentralRepoEnabledTests extends NbTestCase { Assert.fail(ex); } } - + @Override - public void tearDown(){ + public void tearDown() { + this.utils.tearDown(); + } + + public void testOne() { try { - this.utils.tearDown(); - } catch (IOException ex) { + Map dataSources = this.utils.getDataSourceMap(); + + CommonFilesMetadataBuilder builder = new AllCasesEamDbCommonFilesAlgorithm(dataSources, false, false); + + CommonFilesMetadata metadata = builder.findFiles(); + + assertTrue("Should be no results.", metadata.size() == 0); + } catch (Exception ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); } } - - void testOne(){ - - } - } diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/UningestedCases.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/UningestedCasesIntraCaseTests.java similarity index 95% rename from Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/UningestedCases.java rename to Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/UningestedCasesIntraCaseTests.java index c0e12d2034..2b68f4371e 100644 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/UningestedCases.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/UningestedCasesIntraCaseTests.java @@ -42,10 +42,10 @@ import static org.sleuthkit.autopsy.commonfilessearch.IntraCaseUtils.getDataSour * Add images set 1, set 2, set 3, and set 4 to case. Do not ingest. * */ -public class UningestedCases extends NbTestCase { +public class UningestedCasesIntraCaseTests extends NbTestCase { public static Test suite() { - NbModuleSuite.Configuration conf = NbModuleSuite.createConfiguration(UningestedCases.class). + NbModuleSuite.Configuration conf = NbModuleSuite.createConfiguration(UningestedCasesIntraCaseTests.class). clusters(".*"). enableModules(".*"); return conf.suite(); @@ -53,7 +53,7 @@ public class UningestedCases extends NbTestCase { private final IntraCaseUtils utils; - public UningestedCases(String name) { + public UningestedCasesIntraCaseTests(String name) { super(name); this.utils = new IntraCaseUtils(this, "UningestedCasesTests");