mirror of
https://github.com/elisspace/autopsy.git
synced 2026-09-03 14:30:01 +00:00
4112 resolve merge conflicts remove unused imports
This commit is contained in:
@@ -42,11 +42,13 @@ public abstract class AbstractCommonAttributeSearcher {
|
||||
private final Map<Long, String> dataSourceIdToNameMap;
|
||||
private boolean filterByMedia;
|
||||
private boolean filterByDoc;
|
||||
final int frequencyPercentageThreshold;
|
||||
|
||||
AbstractCommonAttributeSearcher(Map<Long, String> dataSourceIdMap, boolean filterByMedia, boolean filterByDoc){
|
||||
AbstractCommonAttributeSearcher(Map<Long, String> dataSourceIdMap, boolean filterByMedia, boolean filterByDoc, int percentageThreshold){
|
||||
this.filterByDoc = filterByDoc;
|
||||
this.filterByMedia = filterByMedia;
|
||||
this.dataSourceIdToNameMap = dataSourceIdMap;
|
||||
this.frequencyPercentageThreshold = percentageThreshold;
|
||||
}
|
||||
|
||||
Map<Long, String> getDataSourceIdToNameMap(){
|
||||
@@ -100,17 +102,18 @@ public abstract class AbstractCommonAttributeSearcher {
|
||||
}
|
||||
}
|
||||
|
||||
static Map<Integer, List<CommonAttributeValue>> collateMatchesByNumberOfInstances(Map<String, CommonAttributeValue> commonFiles) {
|
||||
static Map<Integer, CommonAttributeValueList> collateMatchesByNumberOfInstances(Map<String, CommonAttributeValue> commonFiles) {
|
||||
//collate matches by number of matching instances - doing this in sql doesnt seem efficient
|
||||
Map<Integer, List<CommonAttributeValue>> instanceCollatedCommonFiles = new TreeMap<>();
|
||||
Map<Integer, CommonAttributeValueList> instanceCollatedCommonFiles = new TreeMap<>();
|
||||
|
||||
for(CommonAttributeValue md5Metadata : commonFiles.values()){
|
||||
Integer size = md5Metadata.getInstanceCount();
|
||||
|
||||
if(instanceCollatedCommonFiles.containsKey(size)){
|
||||
instanceCollatedCommonFiles.get(size).add(md5Metadata);
|
||||
instanceCollatedCommonFiles.get(size).addMetadataToList(md5Metadata);
|
||||
} else {
|
||||
ArrayList<CommonAttributeValue> value = new ArrayList<>();
|
||||
value.add(md5Metadata);
|
||||
CommonAttributeValueList value = new CommonAttributeValueList();
|
||||
value.addMetadataToList(md5Metadata);
|
||||
instanceCollatedCommonFiles.put(size, value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,15 +41,15 @@ public class AllInterCaseCommonAttributeSearcher extends InterCaseCommonAttribut
|
||||
* broadly categorized as document types
|
||||
* @throws EamDbException
|
||||
*/
|
||||
public AllInterCaseCommonAttributeSearcher(Map<Long, String> dataSourceIdMap, boolean filterByMediaMimeType, boolean filterByDocMimeType) throws EamDbException {
|
||||
super(dataSourceIdMap, filterByMediaMimeType, filterByDocMimeType);
|
||||
public AllInterCaseCommonAttributeSearcher(Map<Long, String> dataSourceIdMap, boolean filterByMediaMimeType, boolean filterByDocMimeType, int percentageThreshold) throws EamDbException {
|
||||
super(dataSourceIdMap, filterByMediaMimeType, filterByDocMimeType, percentageThreshold);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonAttributeSearchResults findFiles() throws TskCoreException, NoCurrentCaseException, SQLException, EamDbException {
|
||||
InterCaseSearchResultsProcessor eamDbAttrInst = new InterCaseSearchResultsProcessor(this.getDataSourceIdToNameMap());
|
||||
Map<Integer, List<CommonAttributeValue>> interCaseCommonFiles = eamDbAttrInst.findInterCaseCommonAttributeValues(Case.getCurrentCase());
|
||||
return new CommonAttributeSearchResults(interCaseCommonFiles);
|
||||
Map<Integer, CommonAttributeValueList> interCaseCommonFiles = eamDbAttrInst.findInterCaseCommonAttributeValues(Case.getCurrentCase());
|
||||
return new CommonAttributeSearchResults(interCaseCommonFiles, this.frequencyPercentageThreshold);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -37,8 +37,8 @@ final public class AllIntraCaseCommonAttributeSearcher extends IntraCaseCommonAt
|
||||
* @param filterByMediaMimeType match only on files whose mime types can be broadly categorized as media types
|
||||
* @param filterByDocMimeType match only on files whose mime types can be broadly categorized as document types
|
||||
*/
|
||||
public AllIntraCaseCommonAttributeSearcher(Map<Long, String> dataSourceIdMap, boolean filterByMediaMimeType, boolean filterByDocMimeType) {
|
||||
super(dataSourceIdMap, filterByMediaMimeType, filterByDocMimeType);
|
||||
public AllIntraCaseCommonAttributeSearcher(Map<Long, String> dataSourceIdMap, boolean filterByMediaMimeType, boolean filterByDocMimeType, int percentageThreshold) {
|
||||
super(dataSourceIdMap, filterByMediaMimeType, filterByDocMimeType, percentageThreshold);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,17 @@ IntraCasePanel.withinDataSourceRadioButton.text=At least one match must appear i
|
||||
IntraCasePanel.selectDataSourceComboBox.actionCommand=
|
||||
InterCasePanel.specificCentralRepoCaseRadio.text=Matches must be from the following Central Repo case:
|
||||
InterCasePanel.anyCentralRepoCaseRadio.text=Matches may be from any Central Repo case
|
||||
CommonAttributePanel.jCheckBox1.text=Hide files found in over
|
||||
CommonAttributePanel.jLabel1.text=% of data sources in central repository.
|
||||
CommonAttributePanel.percentageThresholdTextTwo.text_1=% of data sources in central repository.
|
||||
CommonAttributePanel.percentageThresholdTextOne.text=20
|
||||
CommonAttributePanel.percentageThresholdCheck.text_1=Hide files found in over
|
||||
CommonAttributePanel.intraCaseRadio.text=Within current case
|
||||
CommonAttributePanel.commonFilesSearchLabel1.text=<html>Find common files to correlate data soures or cases.</html>
|
||||
CommonAttributePanel.errorText.text=<html>In order to search, you must select a file category.</html>
|
||||
CommonAttributePanel.categoriesLabel.text=File Types To Include:
|
||||
CommonAttributePanel.documentsCheckbox.text=Documents
|
||||
CommonAttributePanel.pictureVideoCheckbox.text=Pictures and Videos
|
||||
CommonAttributePanel.selectedFileCategoriesButton.toolTipText=Select from the options below...
|
||||
CommonAttributePanel.selectedFileCategoriesButton.text=Only the selected file types:
|
||||
CommonAttributePanel.allFileCategoriesRadioButton.toolTipText=No filtering applied to results...
|
||||
@@ -17,9 +28,3 @@ CommonAttributePanel.cancelButton.actionCommand=Cancel
|
||||
CommonAttributePanel.cancelButton.text=Cancel
|
||||
CommonAttributePanel.searchButton.text=Search
|
||||
CommonAttributePanel.commonFilesSearchLabel2.text=Scope of Search
|
||||
CommonAttributePanel.intraCaseRadio.text=Within current case
|
||||
CommonAttributePanel.commonFilesSearchLabel1.text=<html>Find common files to correlate data soures or cases.</html>
|
||||
CommonAttributePanel.errorText.text=In order to search, you must select a file category.
|
||||
CommonAttributePanel.categoriesLabel.text=File Types To Include:
|
||||
CommonAttributePanel.documentsCheckbox.text=Documents
|
||||
CommonAttributePanel.pictureVideoCheckbox.text=Pictures and Videos
|
||||
|
||||
@@ -8,8 +8,11 @@
|
||||
</Component>
|
||||
</NonVisualComponents>
|
||||
<Properties>
|
||||
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[450, 375]"/>
|
||||
</Property>
|
||||
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[412, 350]"/>
|
||||
<Dimension value="[450, 375]"/>
|
||||
</Property>
|
||||
<Property name="resizable" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
@@ -29,16 +32,23 @@
|
||||
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,123,0,0,1,-57"/>
|
||||
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,-81,0,0,2,102"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JPanel" name="jPanel1">
|
||||
<Properties>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[412, 350]"/>
|
||||
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[450, 375]"/>
|
||||
</Property>
|
||||
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[450, 375]"/>
|
||||
</Property>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[450, 375]"/>
|
||||
</Property>
|
||||
<Property name="requestFocusEnabled" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout" value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription">
|
||||
@@ -49,46 +59,56 @@
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<Component id="searchButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="cancelButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="errorText" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="commonFilesSearchLabel2" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="intraCaseRadio" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="interCaseRadio" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="commonFilesSearchLabel1" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="categoriesLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="selectedFileCategoriesButton" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||
<Component id="filler1" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="80" max="-2" attributes="0"/>
|
||||
<Component id="filler2" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="errorText" alignment="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="-2" pref="35" max="-2" attributes="0"/>
|
||||
<Group type="102" attributes="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="documentsCheckbox" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="pictureVideoCheckbox" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="commonFilesSearchLabel2" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="intraCaseRadio" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="interCaseRadio" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="commonFilesSearchLabel1" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="categoriesLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="selectedFileCategoriesButton" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="-2" pref="29" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="documentsCheckbox" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="pictureVideoCheckbox" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<Component id="allFileCategoriesRadioButton" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<EmptySpace min="-2" pref="10" max="-2" attributes="0"/>
|
||||
<Component id="layoutPanel" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="percentageThresholdCheck" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="percentageThresholdTextOne" min="-2" pref="40" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="percentageThresholdTextTwo" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace pref="9" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="allFileCategoriesRadioButton" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="-2" pref="20" max="-2" attributes="0"/>
|
||||
<Component id="layoutPanel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="10" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</Group>
|
||||
@@ -104,7 +124,9 @@
|
||||
<Component id="intraCaseRadio" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="interCaseRadio" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="79" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="2" max="-2" attributes="0"/>
|
||||
<Component id="layoutPanel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="categoriesLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="selectedFileCategoriesButton" min="-2" max="-2" attributes="0"/>
|
||||
@@ -116,18 +138,23 @@
|
||||
<Component id="allFileCategoriesRadioButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="searchButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="cancelButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="errorText" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="percentageThresholdCheck" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="percentageThresholdTextOne" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="percentageThresholdTextTwo" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<EmptySpace min="-2" pref="98" max="-2" attributes="0"/>
|
||||
<Component id="layoutPanel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="180" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="103" groupAlignment="1" attributes="0">
|
||||
<Component id="filler2" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="filler1" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="searchButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="cancelButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="errorText" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
@@ -238,6 +265,7 @@
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/commonfilesearch/Bundle.properties" key="CommonAttributePanel.errorText.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="verticalAlignment" type="int" value="1"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="commonFilesSearchLabel1">
|
||||
@@ -295,6 +323,59 @@
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Component class="javax.swing.JCheckBox" name="percentageThresholdCheck">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/commonfilesearch/Bundle.properties" key="CommonAttributePanel.percentageThresholdCheck.text_1" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="percentageThresholdCheckActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="percentageThresholdTextOne">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/commonfilesearch/Bundle.properties" key="CommonAttributePanel.percentageThresholdTextOne.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[40, 24]"/>
|
||||
</Property>
|
||||
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[40, 24]"/>
|
||||
</Property>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[40, 24]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="percentageThresholdTextTwo">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/commonfilesearch/Bundle.properties" key="CommonAttributePanel.percentageThresholdTextTwo.text_1" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.Box$Filler" name="filler1">
|
||||
<Properties>
|
||||
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[0, 32767]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="classDetails" type="java.lang.String" value="Box.Filler.VerticalGlue"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
<Component class="javax.swing.Box$Filler" name="filler2">
|
||||
<Properties>
|
||||
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[32767, 32767]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="classDetails" type="java.lang.String" value="Box.Filler.Glue"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.commonfilesearch;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
@@ -29,6 +30,8 @@ import java.util.logging.Level;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.SwingWorker;
|
||||
import javax.swing.event.DocumentEvent;
|
||||
import javax.swing.event.DocumentListener;
|
||||
import org.netbeans.api.progress.ProgressHandle;
|
||||
import org.openide.explorer.ExplorerManager;
|
||||
import org.openide.util.NbBundle;
|
||||
@@ -52,16 +55,21 @@ import org.sleuthkit.datamodel.TskCoreException;
|
||||
* logic. Nested within CommonFilesDialog.
|
||||
*/
|
||||
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||
public final class CommonAttributePanel extends javax.swing.JDialog {
|
||||
public final class CommonAttributePanel extends javax.swing.JDialog {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(CommonAttributePanel.class.getName());
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static final Long NO_DATA_SOURCE_SELECTED = -1L;
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(CommonAttributePanel.class.getName());
|
||||
private final UserInputErrorManager errorManager;
|
||||
|
||||
private boolean pictureViewCheckboxState;
|
||||
|
||||
private boolean documentsCheckboxState;
|
||||
|
||||
private int percentageThresholdValue = 20;
|
||||
|
||||
/**
|
||||
* Creates new form CommonFilesPanel
|
||||
*/
|
||||
@@ -74,25 +82,71 @@ public final class CommonAttributePanel extends javax.swing.JDialog {
|
||||
super(new JFrame(Bundle.CommonFilesPanel_frame_title()),
|
||||
Bundle.CommonFilesPanel_frame_msg(), true);
|
||||
initComponents();
|
||||
|
||||
this.setLocationRelativeTo(WindowManager.getDefault().getMainWindow());
|
||||
this.errorText.setVisible(false);
|
||||
this.setupDataSources();
|
||||
|
||||
if (CommonAttributePanel.isEamDbAvailable()) {
|
||||
if (CommonAttributePanel.isEamDbAvailableForIntercaseSearch()) {
|
||||
this.setupCases();
|
||||
} else {
|
||||
this.disableIntercaseSearch();
|
||||
}
|
||||
|
||||
if(CommonAttributePanel.isEamDbAvailableForPercentageFrequencyCalculations()){
|
||||
this.enablePercentageOptions();
|
||||
} else {
|
||||
this.disablePercentageOptions();
|
||||
}
|
||||
|
||||
this.errorManager = new UserInputErrorManager();
|
||||
|
||||
this.percentageThresholdTextOne.getDocument().addDocumentListener(new DocumentListener(){
|
||||
|
||||
private Dimension preferredSize = CommonAttributePanel.this.percentageThresholdTextOne.getPreferredSize();
|
||||
|
||||
private void maintainSize(){
|
||||
CommonAttributePanel.this.percentageThresholdTextOne.setSize(preferredSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void insertUpdate(DocumentEvent event) {
|
||||
this.maintainSize();
|
||||
CommonAttributePanel.this.percentageThresholdChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeUpdate(DocumentEvent event) {
|
||||
this.maintainSize();
|
||||
CommonAttributePanel.this.percentageThresholdChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changedUpdate(DocumentEvent event) {
|
||||
this.maintainSize();
|
||||
CommonAttributePanel.this.percentageThresholdChanged();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static boolean isEamDbAvailable() {
|
||||
private static boolean isEamDbAvailableForIntercaseSearch() {
|
||||
try {
|
||||
return EamDb.isEnabled() &&
|
||||
EamDb.getInstance() != null &&
|
||||
EamDb.getInstance().getCases().size() > 1 &&
|
||||
Case.isCaseOpen() &&
|
||||
Case.getCurrentCase() != null &&
|
||||
EamDb.getInstance().getCase(Case.getCurrentCase()) != null;
|
||||
return EamDb.isEnabled()
|
||||
&& EamDb.getInstance() != null
|
||||
&& EamDb.getInstance().getCases().size() > 1
|
||||
&& Case.isCaseOpen()
|
||||
&& Case.getCurrentCase() != null
|
||||
&& EamDb.getInstance().getCase(Case.getCurrentCase()) != null;
|
||||
} catch (EamDbException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Unexpected exception while checking for EamDB enabled.", ex);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean isEamDbAvailableForPercentageFrequencyCalculations(){
|
||||
try {
|
||||
return EamDb.isEnabled()
|
||||
&& EamDb.getInstance() != null
|
||||
&& EamDb.getInstance().getCases().size() > 0;
|
||||
} catch (EamDbException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Unexpected exception while checking for EamDB enabled.", ex);
|
||||
}
|
||||
@@ -158,20 +212,27 @@ public final class CommonAttributePanel extends javax.swing.JDialog {
|
||||
}
|
||||
}
|
||||
|
||||
int percentageThreshold = CommonAttributePanel.this.percentageThresholdValue;
|
||||
|
||||
if (!CommonAttributePanel.this.percentageThresholdCheck.isSelected()) {
|
||||
//0 has the effect of disabling the feature
|
||||
percentageThreshold = 0;
|
||||
}
|
||||
|
||||
if (CommonAttributePanel.this.interCaseRadio.isSelected()) {
|
||||
|
||||
if (caseId == InterCasePanel.NO_CASE_SELECTED) {
|
||||
builder = new AllInterCaseCommonAttributeSearcher(intraCasePanel.getDataSourceMap(), filterByMedia, filterByDocuments);
|
||||
builder = new AllInterCaseCommonAttributeSearcher(intraCasePanel.getDataSourceMap(), filterByMedia, filterByDocuments, percentageThreshold);
|
||||
} else {
|
||||
builder = new SingleInterCaseCommonAttributeSearcher(caseId, intraCasePanel.getDataSourceMap(), filterByMedia, filterByDocuments);
|
||||
builder = new SingleInterCaseCommonAttributeSearcher(caseId, intraCasePanel.getDataSourceMap(), filterByMedia, filterByDocuments, percentageThreshold);
|
||||
}
|
||||
} else {
|
||||
if (dataSourceId == CommonAttributePanel.NO_DATA_SOURCE_SELECTED) {
|
||||
builder = new AllIntraCaseCommonAttributeSearcher(intraCasePanel.getDataSourceMap(), filterByMedia, filterByDocuments);
|
||||
builder = new AllIntraCaseCommonAttributeSearcher(intraCasePanel.getDataSourceMap(), filterByMedia, filterByDocuments, percentageThreshold);
|
||||
|
||||
setTitleForAllDataSources();
|
||||
} else {
|
||||
builder = new SingleIntraCaseCommonAttributeSearcher(dataSourceId, intraCasePanel.getDataSourceMap(), filterByMedia, filterByDocuments);
|
||||
builder = new SingleIntraCaseCommonAttributeSearcher(dataSourceId, intraCasePanel.getDataSourceMap(), filterByMedia, filterByDocuments, percentageThreshold);
|
||||
|
||||
setTitleForSingleSource(dataSourceId);
|
||||
}
|
||||
@@ -230,7 +291,6 @@ public final class CommonAttributePanel extends javax.swing.JDialog {
|
||||
}.execute();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets up the data sources dropdown and returns the data sources map for
|
||||
* future usage.
|
||||
@@ -263,8 +323,7 @@ public final class CommonAttributePanel extends javax.swing.JDialog {
|
||||
boolean multipleDataSources = this.caseHasMultipleSources();
|
||||
CommonAttributePanel.this.intraCasePanel.rigForMultipleDataSources(multipleDataSources);
|
||||
|
||||
//TODO this should be attached to the intra/inter radio buttons
|
||||
CommonAttributePanel.this.setSearchButtonEnabled(true);
|
||||
CommonAttributePanel.this.updateErrorTextAndSearchBox();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -405,9 +464,14 @@ public final class CommonAttributePanel extends javax.swing.JDialog {
|
||||
layoutPanel = new java.awt.Panel();
|
||||
intraCasePanel = new org.sleuthkit.autopsy.commonfilesearch.IntraCasePanel();
|
||||
interCasePanel = new org.sleuthkit.autopsy.commonfilesearch.InterCasePanel();
|
||||
percentageThresholdCheck = new javax.swing.JCheckBox();
|
||||
percentageThresholdTextOne = new javax.swing.JTextField();
|
||||
percentageThresholdTextTwo = new javax.swing.JLabel();
|
||||
filler1 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 32767));
|
||||
filler2 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(32767, 32767));
|
||||
|
||||
setMinimumSize(new java.awt.Dimension(412, 350));
|
||||
setPreferredSize(new java.awt.Dimension(412, 350));
|
||||
setMaximumSize(new java.awt.Dimension(450, 375));
|
||||
setMinimumSize(new java.awt.Dimension(450, 375));
|
||||
setResizable(false);
|
||||
addWindowListener(new java.awt.event.WindowAdapter() {
|
||||
public void windowClosed(java.awt.event.WindowEvent evt) {
|
||||
@@ -415,7 +479,10 @@ public final class CommonAttributePanel extends javax.swing.JDialog {
|
||||
}
|
||||
});
|
||||
|
||||
jPanel1.setPreferredSize(new java.awt.Dimension(412, 350));
|
||||
jPanel1.setMaximumSize(new java.awt.Dimension(450, 375));
|
||||
jPanel1.setMinimumSize(new java.awt.Dimension(450, 375));
|
||||
jPanel1.setPreferredSize(new java.awt.Dimension(450, 375));
|
||||
jPanel1.setRequestFocusEnabled(false);
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(commonFilesSearchLabel2, org.openide.util.NbBundle.getMessage(CommonAttributePanel.class, "CommonAttributePanel.commonFilesSearchLabel2.text")); // NOI18N
|
||||
commonFilesSearchLabel2.setFocusable(false);
|
||||
@@ -478,6 +545,7 @@ public final class CommonAttributePanel extends javax.swing.JDialog {
|
||||
|
||||
errorText.setForeground(new java.awt.Color(255, 0, 0));
|
||||
org.openide.awt.Mnemonics.setLocalizedText(errorText, org.openide.util.NbBundle.getMessage(CommonAttributePanel.class, "CommonAttributePanel.errorText.text")); // NOI18N
|
||||
errorText.setVerticalAlignment(javax.swing.SwingConstants.TOP);
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(commonFilesSearchLabel1, org.openide.util.NbBundle.getMessage(CommonAttributePanel.class, "CommonAttributePanel.commonFilesSearchLabel1.text")); // NOI18N
|
||||
commonFilesSearchLabel1.setFocusable(false);
|
||||
@@ -503,42 +571,64 @@ public final class CommonAttributePanel extends javax.swing.JDialog {
|
||||
layoutPanel.add(intraCasePanel, "card3");
|
||||
layoutPanel.add(interCasePanel, "card2");
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(percentageThresholdCheck, org.openide.util.NbBundle.getMessage(CommonAttributePanel.class, "CommonAttributePanel.percentageThresholdCheck.text_1")); // NOI18N
|
||||
percentageThresholdCheck.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
percentageThresholdCheckActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
percentageThresholdTextOne.setText(org.openide.util.NbBundle.getMessage(CommonAttributePanel.class, "CommonAttributePanel.percentageThresholdTextOne.text")); // NOI18N
|
||||
percentageThresholdTextOne.setMaximumSize(new java.awt.Dimension(40, 24));
|
||||
percentageThresholdTextOne.setMinimumSize(new java.awt.Dimension(40, 24));
|
||||
percentageThresholdTextOne.setPreferredSize(new java.awt.Dimension(40, 24));
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(percentageThresholdTextTwo, org.openide.util.NbBundle.getMessage(CommonAttributePanel.class, "CommonAttributePanel.percentageThresholdTextTwo.text_1")); // NOI18N
|
||||
|
||||
javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
|
||||
jPanel1.setLayout(jPanel1Layout);
|
||||
jPanel1Layout.setHorizontalGroup(
|
||||
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(jPanel1Layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(jPanel1Layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
|
||||
.addComponent(searchButton)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(cancelButton)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(errorText))
|
||||
.addGroup(jPanel1Layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(commonFilesSearchLabel2)
|
||||
.addComponent(intraCaseRadio)
|
||||
.addComponent(interCaseRadio)
|
||||
.addComponent(commonFilesSearchLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(categoriesLabel)
|
||||
.addComponent(selectedFileCategoriesButton)))
|
||||
.addGroup(jPanel1Layout.createSequentialGroup()
|
||||
.addGap(0, 0, Short.MAX_VALUE)
|
||||
.addComponent(filler1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addGap(80, 80, 80)
|
||||
.addComponent(filler2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addComponent(errorText)))
|
||||
.addGroup(jPanel1Layout.createSequentialGroup()
|
||||
.addGap(35, 35, 35)
|
||||
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(documentsCheckbox)
|
||||
.addComponent(pictureVideoCheckbox)))
|
||||
.addGroup(jPanel1Layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(allFileCategoriesRadioButton)))
|
||||
.addContainerGap())
|
||||
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(jPanel1Layout.createSequentialGroup()
|
||||
.addGap(20, 20, 20)
|
||||
.addComponent(layoutPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addGap(10, 10, 10)))
|
||||
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(commonFilesSearchLabel2)
|
||||
.addComponent(intraCaseRadio)
|
||||
.addComponent(interCaseRadio)
|
||||
.addComponent(commonFilesSearchLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(categoriesLabel)
|
||||
.addComponent(selectedFileCategoriesButton)
|
||||
.addGroup(jPanel1Layout.createSequentialGroup()
|
||||
.addGap(29, 29, 29)
|
||||
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(documentsCheckbox)
|
||||
.addComponent(pictureVideoCheckbox)))
|
||||
.addComponent(allFileCategoriesRadioButton)
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
|
||||
.addGap(10, 10, 10)
|
||||
.addComponent(layoutPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
|
||||
.addGroup(jPanel1Layout.createSequentialGroup()
|
||||
.addComponent(percentageThresholdCheck)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(percentageThresholdTextOne, javax.swing.GroupLayout.PREFERRED_SIZE, 40, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(percentageThresholdTextTwo)))
|
||||
.addContainerGap(9, Short.MAX_VALUE))))
|
||||
);
|
||||
jPanel1Layout.setVerticalGroup(
|
||||
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
@@ -551,7 +641,9 @@ public final class CommonAttributePanel extends javax.swing.JDialog {
|
||||
.addComponent(intraCaseRadio)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(interCaseRadio)
|
||||
.addGap(79, 79, 79)
|
||||
.addGap(2, 2, 2)
|
||||
.addComponent(layoutPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(categoriesLabel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(selectedFileCategoriesButton)
|
||||
@@ -563,85 +655,90 @@ public final class CommonAttributePanel extends javax.swing.JDialog {
|
||||
.addComponent(allFileCategoriesRadioButton)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(searchButton)
|
||||
.addComponent(cancelButton)
|
||||
.addComponent(errorText))
|
||||
.addComponent(percentageThresholdCheck)
|
||||
.addComponent(percentageThresholdTextOne, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(percentageThresholdTextTwo))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
|
||||
.addComponent(filler2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(filler1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(searchButton)
|
||||
.addComponent(cancelButton)
|
||||
.addComponent(errorText, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
|
||||
.addContainerGap())
|
||||
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
|
||||
.addGap(98, 98, 98)
|
||||
.addComponent(layoutPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addGap(180, 180, 180)))
|
||||
);
|
||||
|
||||
getContentPane().add(jPanel1, java.awt.BorderLayout.CENTER);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
private void formWindowClosed(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowClosed
|
||||
SwingUtilities.windowForComponent(this).dispose();
|
||||
}//GEN-LAST:event_formWindowClosed
|
||||
|
||||
private void percentageThresholdCheckActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_percentageThresholdCheckActionPerformed
|
||||
if (this.percentageThresholdCheck.isSelected()) {
|
||||
this.percentageThresholdTextOne.setEnabled(true);
|
||||
} else {
|
||||
this.percentageThresholdTextOne.setEnabled(false);
|
||||
}
|
||||
|
||||
this.handleFrequencyPercentageState();
|
||||
}//GEN-LAST:event_percentageThresholdCheckActionPerformed
|
||||
|
||||
private void interCaseRadioActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_interCaseRadioActionPerformed
|
||||
((java.awt.CardLayout) this.layoutPanel.getLayout()).last(this.layoutPanel);
|
||||
}//GEN-LAST:event_interCaseRadioActionPerformed
|
||||
|
||||
private void intraCaseRadioActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_intraCaseRadioActionPerformed
|
||||
((java.awt.CardLayout) this.layoutPanel.getLayout()).first(this.layoutPanel);
|
||||
}//GEN-LAST:event_intraCaseRadioActionPerformed
|
||||
|
||||
private void documentsCheckboxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_documentsCheckboxActionPerformed
|
||||
this.handleFileTypeCheckBoxState();
|
||||
}//GEN-LAST:event_documentsCheckboxActionPerformed
|
||||
|
||||
private void pictureVideoCheckboxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_pictureVideoCheckboxActionPerformed
|
||||
this.handleFileTypeCheckBoxState();
|
||||
}//GEN-LAST:event_pictureVideoCheckboxActionPerformed
|
||||
|
||||
private void selectedFileCategoriesButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_selectedFileCategoriesButtonActionPerformed
|
||||
this.handleFileTypeCheckBoxState();
|
||||
}//GEN-LAST:event_selectedFileCategoriesButtonActionPerformed
|
||||
|
||||
private void allFileCategoriesRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_allFileCategoriesRadioButtonActionPerformed
|
||||
this.handleFileTypeCheckBoxState();
|
||||
}//GEN-LAST:event_allFileCategoriesRadioButtonActionPerformed
|
||||
|
||||
private void cancelButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelButtonActionPerformed
|
||||
SwingUtilities.windowForComponent(this).dispose();
|
||||
}//GEN-LAST:event_cancelButtonActionPerformed
|
||||
|
||||
private void searchButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_searchButtonActionPerformed
|
||||
search();
|
||||
SwingUtilities.windowForComponent(this).dispose();
|
||||
}//GEN-LAST:event_searchButtonActionPerformed
|
||||
|
||||
private void cancelButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelButtonActionPerformed
|
||||
SwingUtilities.windowForComponent(this).dispose();
|
||||
}//GEN-LAST:event_cancelButtonActionPerformed
|
||||
private void percentageThresholdChanged(){
|
||||
String percentageString = this.percentageThresholdTextOne.getText();
|
||||
|
||||
private void allFileCategoriesRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_allFileCategoriesRadioButtonActionPerformed
|
||||
this.manageCheckBoxState();
|
||||
this.toggleErrorTextAndSearchBox();
|
||||
}//GEN-LAST:event_allFileCategoriesRadioButtonActionPerformed
|
||||
|
||||
private void selectedFileCategoriesButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_selectedFileCategoriesButtonActionPerformed
|
||||
this.manageCheckBoxState();
|
||||
}//GEN-LAST:event_selectedFileCategoriesButtonActionPerformed
|
||||
|
||||
private void pictureVideoCheckboxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_pictureVideoCheckboxActionPerformed
|
||||
this.toggleErrorTextAndSearchBox();
|
||||
}//GEN-LAST:event_pictureVideoCheckboxActionPerformed
|
||||
|
||||
private void documentsCheckboxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_documentsCheckboxActionPerformed
|
||||
this.toggleErrorTextAndSearchBox();
|
||||
}//GEN-LAST:event_documentsCheckboxActionPerformed
|
||||
|
||||
private void intraCaseRadioActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_intraCaseRadioActionPerformed
|
||||
((java.awt.CardLayout) this.layoutPanel.getLayout()).first(this.layoutPanel);
|
||||
handleIntraCaseSearchCriteriaChanged();
|
||||
}//GEN-LAST:event_intraCaseRadioActionPerformed
|
||||
|
||||
public void handleIntraCaseSearchCriteriaChanged() {
|
||||
if (this.areIntraCaseSearchCriteriaMet()) {
|
||||
this.searchButton.setEnabled(true);
|
||||
this.hideErrorMessages();
|
||||
} else {
|
||||
this.searchButton.setEnabled(false);
|
||||
this.hideErrorMessages();
|
||||
this.showIntraCaseErrorMessage();
|
||||
try {
|
||||
this.percentageThresholdValue = Integer.parseInt(percentageString);
|
||||
|
||||
} catch (NumberFormatException exception) {
|
||||
this.percentageThresholdValue = -1;
|
||||
}
|
||||
|
||||
this.handleFrequencyPercentageState();
|
||||
}
|
||||
|
||||
private void updateErrorTextAndSearchBox() {
|
||||
|
||||
private void interCaseRadioActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_interCaseRadioActionPerformed
|
||||
((java.awt.CardLayout) this.layoutPanel.getLayout()).last(this.layoutPanel);
|
||||
handleInterCaseSearchCriteriaChanged();
|
||||
}//GEN-LAST:event_interCaseRadioActionPerformed
|
||||
|
||||
private void formWindowClosed(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowClosed
|
||||
SwingUtilities.windowForComponent(this).dispose();
|
||||
}//GEN-LAST:event_formWindowClosed
|
||||
|
||||
public void handleInterCaseSearchCriteriaChanged() {
|
||||
if (this.areInterCaseSearchCriteriaMet()) {
|
||||
this.searchButton.setEnabled(true);
|
||||
this.hideErrorMessages();
|
||||
} else {
|
||||
this.searchButton.setEnabled(false);
|
||||
this.hideErrorMessages();
|
||||
this.showInterCaseErrorMessage();
|
||||
}
|
||||
}
|
||||
|
||||
private void toggleErrorTextAndSearchBox() {
|
||||
if (!this.pictureVideoCheckbox.isSelected() && !this.documentsCheckbox.isSelected() && !this.allFileCategoriesRadioButton.isSelected()) {
|
||||
if (this.errorManager.anyErrors()) {
|
||||
this.searchButton.setEnabled(false);
|
||||
//grab the first error error and show it
|
||||
this.errorText.setText(this.errorManager.getErrors().get(0));
|
||||
this.errorText.setVisible(true);
|
||||
} else {
|
||||
this.searchButton.setEnabled(true);
|
||||
@@ -649,7 +746,21 @@ public final class CommonAttributePanel extends javax.swing.JDialog {
|
||||
}
|
||||
}
|
||||
|
||||
private void manageCheckBoxState() {
|
||||
private void enablePercentageOptions() {
|
||||
this.percentageThresholdTextOne.setEnabled(true);
|
||||
this.percentageThresholdCheck.setEnabled(true);
|
||||
this.percentageThresholdCheck.setSelected(true);
|
||||
this.percentageThresholdTextTwo.setEnabled(true);
|
||||
}
|
||||
|
||||
private void disablePercentageOptions() {
|
||||
this.percentageThresholdTextOne.setEnabled(false);
|
||||
this.percentageThresholdCheck.setEnabled(false);
|
||||
this.percentageThresholdCheck.setSelected(false);
|
||||
this.percentageThresholdTextTwo.setEnabled(false);
|
||||
}
|
||||
|
||||
private void handleFileTypeCheckBoxState() {
|
||||
|
||||
this.pictureViewCheckboxState = this.pictureVideoCheckbox.isSelected();
|
||||
this.documentsCheckboxState = this.documentsCheckbox.isSelected();
|
||||
@@ -657,6 +768,8 @@ public final class CommonAttributePanel extends javax.swing.JDialog {
|
||||
if (this.allFileCategoriesRadioButton.isSelected()) {
|
||||
this.pictureVideoCheckbox.setEnabled(false);
|
||||
this.documentsCheckbox.setEnabled(false);
|
||||
|
||||
this.errorManager.setError(UserInputErrorManager.NO_FILE_CATEGORIES_SELECTED_KEY, false);
|
||||
}
|
||||
|
||||
if (this.selectedFileCategoriesButton.isSelected()) {
|
||||
@@ -667,8 +780,24 @@ public final class CommonAttributePanel extends javax.swing.JDialog {
|
||||
this.pictureVideoCheckbox.setEnabled(true);
|
||||
this.documentsCheckbox.setEnabled(true);
|
||||
|
||||
this.toggleErrorTextAndSearchBox();
|
||||
if (!this.pictureVideoCheckbox.isSelected() && !this.documentsCheckbox.isSelected() && !this.allFileCategoriesRadioButton.isSelected()) {
|
||||
this.errorManager.setError(UserInputErrorManager.NO_FILE_CATEGORIES_SELECTED_KEY, true);
|
||||
} else {
|
||||
this.errorManager.setError(UserInputErrorManager.NO_FILE_CATEGORIES_SELECTED_KEY, false);
|
||||
}
|
||||
}
|
||||
|
||||
this.updateErrorTextAndSearchBox();
|
||||
}
|
||||
|
||||
private void handleFrequencyPercentageState() {
|
||||
if (this.percentageThresholdValue > 0 && this.percentageThresholdValue <= 100) {
|
||||
this.errorManager.setError(UserInputErrorManager.FREQUENCY_PERCENTAGE_OUT_OF_RANGE_KEY, false);
|
||||
} else {
|
||||
this.errorManager.setError(UserInputErrorManager.FREQUENCY_PERCENTAGE_OUT_OF_RANGE_KEY, true);
|
||||
}
|
||||
|
||||
this.updateErrorTextAndSearchBox();
|
||||
}
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
@@ -680,6 +809,8 @@ public final class CommonAttributePanel extends javax.swing.JDialog {
|
||||
private javax.swing.JCheckBox documentsCheckbox;
|
||||
private javax.swing.JLabel errorText;
|
||||
private javax.swing.ButtonGroup fileTypeFilterButtonGroup;
|
||||
private javax.swing.Box.Filler filler1;
|
||||
private javax.swing.Box.Filler filler2;
|
||||
private org.sleuthkit.autopsy.commonfilesearch.InterCasePanel interCasePanel;
|
||||
private javax.swing.JRadioButton interCaseRadio;
|
||||
private javax.swing.ButtonGroup interIntraButtonGroup;
|
||||
@@ -687,34 +818,11 @@ public final class CommonAttributePanel extends javax.swing.JDialog {
|
||||
private javax.swing.JRadioButton intraCaseRadio;
|
||||
private javax.swing.JPanel jPanel1;
|
||||
private java.awt.Panel layoutPanel;
|
||||
private javax.swing.JCheckBox percentageThresholdCheck;
|
||||
private javax.swing.JTextField percentageThresholdTextOne;
|
||||
private javax.swing.JLabel percentageThresholdTextTwo;
|
||||
private javax.swing.JCheckBox pictureVideoCheckbox;
|
||||
private javax.swing.JButton searchButton;
|
||||
private javax.swing.JRadioButton selectedFileCategoriesButton;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
|
||||
void setSearchButtonEnabled(boolean enabled) {
|
||||
this.searchButton.setEnabled(enabled);
|
||||
}
|
||||
|
||||
private boolean areIntraCaseSearchCriteriaMet() {
|
||||
return this.intraCasePanel.areSearchCriteriaMet();
|
||||
}
|
||||
|
||||
private boolean areInterCaseSearchCriteriaMet() {
|
||||
return this.interCasePanel.areSearchCriteriaMet();
|
||||
}
|
||||
|
||||
private void hideErrorMessages() {
|
||||
this.errorText.setVisible(false);
|
||||
}
|
||||
|
||||
private void showIntraCaseErrorMessage() {
|
||||
this.errorText.setText(this.intraCasePanel.getErrorMessage());
|
||||
this.errorText.setVisible(true);
|
||||
}
|
||||
|
||||
private void showInterCaseErrorMessage() {
|
||||
this.errorText.setText(this.interCasePanel.getErrorMessage());
|
||||
this.errorText.setVisible(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,10 +19,13 @@
|
||||
package org.sleuthkit.autopsy.commonfilesearch;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import org.openide.nodes.ChildFactory;
|
||||
import org.openide.nodes.Children;
|
||||
import org.openide.nodes.Node;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException;
|
||||
import org.sleuthkit.autopsy.datamodel.DisplayableItemNode;
|
||||
import org.sleuthkit.autopsy.datamodel.DisplayableItemNodeVisitor;
|
||||
|
||||
@@ -65,6 +68,8 @@ final public class CommonAttributeSearchResultRootNode extends DisplayableItemNo
|
||||
*/
|
||||
static class InstanceCountNodeFactory extends ChildFactory<Integer>{
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(InstanceCountNodeFactory.class.getName());
|
||||
|
||||
private final CommonAttributeSearchResults searchResults;
|
||||
|
||||
/**
|
||||
@@ -78,13 +83,17 @@ final public class CommonAttributeSearchResultRootNode extends DisplayableItemNo
|
||||
|
||||
@Override
|
||||
protected boolean createKeys(List<Integer> list) {
|
||||
list.addAll(this.searchResults.getMetadata().keySet());
|
||||
try {
|
||||
list.addAll(this.searchResults.getMetadata().keySet());
|
||||
} catch (EamDbException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Unable to create keys.", ex);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Node createNodeForKey(Integer instanceCount){
|
||||
List<CommonAttributeValue> attributeValues = this.searchResults.getAttributeValuesForInstanceCount(instanceCount);
|
||||
CommonAttributeValueList attributeValues = this.searchResults.getAttributeValuesForInstanceCount(instanceCount);
|
||||
return new InstanceCountNode(instanceCount, attributeValues);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,27 +19,37 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.commonfilesearch;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException;
|
||||
|
||||
/**
|
||||
* Stores the results from the various types of common attribute searching
|
||||
* Stores results based on how they are currently displayed in the UI
|
||||
*/
|
||||
final public class CommonAttributeSearchResults {
|
||||
|
||||
|
||||
// maps instance count to list of attribute values.
|
||||
private final Map<Integer, List<CommonAttributeValue>> instanceCountToAttributeValues;
|
||||
private final Map<Integer, CommonAttributeValueList> instanceCountToAttributeValues;
|
||||
|
||||
private final int percentageThreshold;
|
||||
|
||||
/**
|
||||
* Create a values object which can be handed off to the node factories.
|
||||
*
|
||||
* @param values list of CommonAttributeValue indexed by size of
|
||||
*
|
||||
* @param values list of CommonAttributeValue indexed by size of
|
||||
* CommonAttributeValue
|
||||
*/
|
||||
CommonAttributeSearchResults(Map<Integer, List<CommonAttributeValue>> metadata){
|
||||
this.instanceCountToAttributeValues = metadata;
|
||||
CommonAttributeSearchResults(Map<Integer, CommonAttributeValueList> metadata, int percentageThreshold) {
|
||||
//wrap in a new object in case any client code has used an unmodifiable collection
|
||||
this.instanceCountToAttributeValues = new HashMap<>(metadata);
|
||||
this.percentageThreshold = percentageThreshold;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -48,32 +58,103 @@ final public class CommonAttributeSearchResults {
|
||||
* This is a convenience method - you can also iterate over
|
||||
* <code>getValues()</code>.
|
||||
*
|
||||
* @param isntanceCound key
|
||||
* @param instanceCount key
|
||||
* @return list of values which represent matches
|
||||
*/
|
||||
List<CommonAttributeValue> getAttributeValuesForInstanceCount(Integer instanceCount) {
|
||||
CommonAttributeValueList getAttributeValuesForInstanceCount(Integer instanceCount) {
|
||||
return this.instanceCountToAttributeValues.get(instanceCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an unmodifiable collection of values, indexed by number of
|
||||
* grandchildren, which represents the common attributes found in the
|
||||
/**
|
||||
* Get an unmodifiable collection of values, indexed by number of
|
||||
* grandchildren, which represents the common attributes found in the
|
||||
* search.
|
||||
*
|
||||
* @return map of sizes of children to list of matches
|
||||
*/
|
||||
public Map<Integer, List<CommonAttributeValue>> getMetadata() {
|
||||
*/
|
||||
public Map<Integer, CommonAttributeValueList> getMetadata() throws EamDbException {
|
||||
if(this.percentageThreshold == 0){
|
||||
return Collections.unmodifiableMap(this.instanceCountToAttributeValues);
|
||||
} else {
|
||||
return this.getMetadata(this.percentageThreshold);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an unmodifiable collection of values, indexed by number of
|
||||
* grandchildren, which represents the common attributes found in the
|
||||
* search.
|
||||
*
|
||||
* Remove results which are not found in the portion of available data
|
||||
sources described by maximumPercentageThreshold.
|
||||
*
|
||||
* @return metadata
|
||||
*/
|
||||
private Map<Integer, CommonAttributeValueList> getMetadata(int maximumPercentageThreshold) throws EamDbException {
|
||||
|
||||
if(maximumPercentageThreshold == 0){
|
||||
return Collections.unmodifiableMap(this.instanceCountToAttributeValues);
|
||||
}
|
||||
|
||||
CorrelationAttributeInstance.Type fileAttributeType = CorrelationAttributeInstance
|
||||
.getDefaultCorrelationTypes()
|
||||
.stream()
|
||||
.filter(filterType -> filterType.getId() == CorrelationAttributeInstance.FILES_TYPE_ID)
|
||||
.findFirst().get();
|
||||
|
||||
EamDb eamDb = EamDb.getInstance();
|
||||
|
||||
Map<Integer, List<CommonAttributeValue>> itemsToRemove = new HashMap<>();
|
||||
|
||||
for(Entry<Integer, CommonAttributeValueList> listOfValues : Collections.unmodifiableMap(this.instanceCountToAttributeValues).entrySet()){
|
||||
|
||||
final Integer key = listOfValues.getKey();
|
||||
final CommonAttributeValueList values = listOfValues.getValue();
|
||||
|
||||
for(CommonAttributeValue value : values.getDelayedMetadataList()){ // Need the real metadata
|
||||
|
||||
int frequencyPercentage = eamDb.getFrequencyPercentage(new CorrelationAttributeInstance(fileAttributeType, value.getValue()));
|
||||
|
||||
if(frequencyPercentage > maximumPercentageThreshold){
|
||||
if(itemsToRemove.containsKey(key)){
|
||||
itemsToRemove.get(key).add(value);
|
||||
} else {
|
||||
List<CommonAttributeValue> toRemove = new ArrayList<>();
|
||||
toRemove.add(value);
|
||||
itemsToRemove.put(key, toRemove);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(Entry<Integer, List<CommonAttributeValue>> valuesToRemove : itemsToRemove.entrySet()){
|
||||
|
||||
final Integer key = valuesToRemove.getKey();
|
||||
final List<CommonAttributeValue> values = valuesToRemove.getValue();
|
||||
|
||||
for (CommonAttributeValue value : values){
|
||||
final CommonAttributeValueList instanceCountValue = this.instanceCountToAttributeValues.get(key);
|
||||
instanceCountValue.removeMetaData(value);
|
||||
|
||||
if(instanceCountValue.getDelayedMetadataList().isEmpty()){ // Check the real metadata
|
||||
this.instanceCountToAttributeValues.remove(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Collections.unmodifiableMap(this.instanceCountToAttributeValues);
|
||||
}
|
||||
|
||||
/**
|
||||
* How many distinct common files exist for this search results?
|
||||
*
|
||||
* @return number of common files
|
||||
*/
|
||||
public int size() {
|
||||
|
||||
|
||||
int count = 0;
|
||||
for (List<CommonAttributeValue> data : this.instanceCountToAttributeValues.values()) {
|
||||
for(CommonAttributeValue md5 : data){
|
||||
for (CommonAttributeValueList data : this.instanceCountToAttributeValues.values()) {
|
||||
for(CommonAttributeValue md5 : data.getMetadataList()){
|
||||
count += md5.getInstanceCount();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@ final public class CommonAttributeValue {
|
||||
CommonAttributeValue(String md5, List<AbstractCommonAttributeInstance> fileInstances) {
|
||||
this.md5 = md5;
|
||||
this.fileInstances = fileInstances;
|
||||
|
||||
}
|
||||
|
||||
CommonAttributeValue(String md5) {
|
||||
@@ -85,4 +86,7 @@ final public class CommonAttributeValue {
|
||||
public int getInstanceCount() {
|
||||
return this.fileInstances.size();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2018 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> 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.commonfilesearch;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Utility and wrapper model around data required for Common Files Search
|
||||
* results. Subclass this to implement different selections of files from the
|
||||
* case.
|
||||
*/
|
||||
final public class CommonAttributeValueList {
|
||||
|
||||
/**
|
||||
* The list of value nodes, which begins empty.
|
||||
*/
|
||||
private final List<CommonAttributeValue> metadataList;
|
||||
|
||||
/**
|
||||
* The backing list of value nodes, which will be dynamically loaded
|
||||
* when requested.
|
||||
*/
|
||||
private final List<CommonAttributeValue> delayedMetadataList;
|
||||
|
||||
/**
|
||||
* Create a metadata object containing the list of metadata which can be
|
||||
* handed off to the node factories.
|
||||
*
|
||||
* @param metadata list of Md5Metadata indexed by size of Md5Metadata
|
||||
*/
|
||||
CommonAttributeValueList(List<CommonAttributeValue> metadata) {
|
||||
this.metadataList = new ArrayList<>();
|
||||
this.delayedMetadataList = metadata;
|
||||
}
|
||||
|
||||
CommonAttributeValueList() {
|
||||
this.metadataList = new ArrayList<>();
|
||||
this.delayedMetadataList = new ArrayList<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of value nodes. Will be empty if
|
||||
* displayDelayedMetadata() has not been called for the
|
||||
* parent InstanceCountNode
|
||||
* @return metadataList the list of nodes
|
||||
*/
|
||||
public List<CommonAttributeValue> getMetadataList() {
|
||||
return Collections.unmodifiableList(this.metadataList);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the delayed list of value nodes. Only use for
|
||||
* determining how many CommonAttributeValues
|
||||
* actually exist in the list.
|
||||
* @return metadataList the list of nodes
|
||||
*/
|
||||
List<CommonAttributeValue> getDelayedMetadataList() {
|
||||
return Collections.unmodifiableList(this.delayedMetadataList);
|
||||
}
|
||||
|
||||
void removeMetaData(CommonAttributeValue commonVal) {
|
||||
this.delayedMetadataList.remove(commonVal);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the size of the backing list, in case
|
||||
* displayDelayedMetadata() has not be called yet.
|
||||
* @return int the number of matches for this value
|
||||
*/
|
||||
int getCommonAttributeListSize() {
|
||||
return this.delayedMetadataList.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Dynamically load the list CommonAttributeValue when called. Until called
|
||||
* metadataList should be empty. The parent node, InstanceCountNode, will
|
||||
* trigger the factory call and refresh.
|
||||
*/
|
||||
public void displayDelayedMetadata() {
|
||||
if (metadataList.isEmpty()) {
|
||||
this.metadataList.addAll(this.delayedMetadataList);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A a value node to the list, to be loaded later.
|
||||
* @param metadata the node to add
|
||||
*/
|
||||
void addMetadataToList(CommonAttributeValue metadata) {
|
||||
delayedMetadataList.add(metadata);
|
||||
}
|
||||
}
|
||||
@@ -29,6 +29,7 @@ import javax.swing.table.TableColumn;
|
||||
import javax.swing.table.TableColumnModel;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.corecomponents.DataResultViewerTable;
|
||||
import org.sleuthkit.autopsy.corecomponents.DelayedLoadChildNodesOnTreeExpansion;
|
||||
|
||||
/**
|
||||
* <code>DataResultViewerTable</code> which overrides the default column
|
||||
@@ -59,7 +60,19 @@ public class CommonAttributesSearchResultsViewerTable extends DataResultViewerTa
|
||||
|
||||
COLUMN_WIDTHS = Collections.unmodifiableMap(map);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements a DataResultViewerTable which constructs a tabular result viewer that
|
||||
* displays the children of the given root node using an OutlineView. The explorer
|
||||
* manager will be discovered at runtime.
|
||||
*
|
||||
* Adds a TreeExpansionsListener to the outlineView to receive tree expansion events
|
||||
* which dynamically loads children nodes when requested.
|
||||
*/
|
||||
public CommonAttributesSearchResultsViewerTable() {
|
||||
super();
|
||||
outlineView.addTreeExpansionListener(new DelayedLoadChildNodesOnTreeExpansion());
|
||||
}
|
||||
|
||||
@NbBundle.Messages({
|
||||
"CommonFilesSearchResultsViewerTable.noDescText= ",
|
||||
"CommonFilesSearchResultsViewerTable.filesColLbl=Files",
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.commonfilesearch;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
@@ -29,52 +28,68 @@ import org.openide.nodes.Children;
|
||||
import org.openide.nodes.Node;
|
||||
import org.openide.nodes.Sheet;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.datamodel.DisplayableItemNode;
|
||||
import org.sleuthkit.autopsy.datamodel.DisplayableItemNodeVisitor;
|
||||
import org.sleuthkit.autopsy.datamodel.NodeProperty;
|
||||
|
||||
/**
|
||||
* Node used to indicate the number of matches found with the MD5 children
|
||||
* of this Node.
|
||||
* Node used to indicate the number of matches found with the MD5 children of
|
||||
* this Node.
|
||||
*/
|
||||
final public class InstanceCountNode extends DisplayableItemNode {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(InstanceCountNode.class.getName());
|
||||
|
||||
final private int instanceCount;
|
||||
final private List<CommonAttributeValue> attributeValues;
|
||||
final private CommonAttributeValueList attributeValues;
|
||||
|
||||
/**
|
||||
* Create a node with the given number of instances, and the given
|
||||
* selection of metadata.
|
||||
* Create a node with the given number of instances, and the given selection
|
||||
* of metadata.
|
||||
*
|
||||
* @param instanceCount
|
||||
* @param attributeValues
|
||||
* @param attributeValues
|
||||
*/
|
||||
@NbBundle.Messages({
|
||||
"InstanceCountNode.displayName=Files with %s instances (%s)"
|
||||
})
|
||||
public InstanceCountNode(int instanceCount, List<CommonAttributeValue> attributeValues) {
|
||||
super(Children.create(new CommonAttributeValueNodeFactory(attributeValues), true));
|
||||
public InstanceCountNode(int instanceCount, CommonAttributeValueList attributeValues) {
|
||||
super(Children.create(new CommonAttributeValueNodeFactory(attributeValues.getMetadataList()), true));
|
||||
|
||||
this.instanceCount = instanceCount;
|
||||
this.attributeValues = attributeValues;
|
||||
|
||||
this.setDisplayName(String.format(Bundle.InstanceCountNode_displayName(), Integer.toString(instanceCount), attributeValues.size()));
|
||||
|
||||
this.setDisplayName(String.format(Bundle.InstanceCountNode_displayName(), Integer.toString(instanceCount), attributeValues.getCommonAttributeListSize()));
|
||||
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/fileset-icon-16.png"); //NON-NLS
|
||||
}
|
||||
|
||||
/**
|
||||
* Number of matches found for each of the MD5 children.
|
||||
*
|
||||
* @return int match count
|
||||
*/
|
||||
int getInstanceCount() {
|
||||
return this.instanceCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh the node, by dynamically loading in the children when called, and
|
||||
* calling the CommonAttributeValueNodeFactory to generate nodes for the
|
||||
* children in attributeValues.
|
||||
*/
|
||||
public void refresh() {
|
||||
attributeValues.displayDelayedMetadata();
|
||||
setChildren(Children.create(new CommonAttributeValueNodeFactory(attributeValues.getMetadataList()), true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of metadata for the MD5s which are children of this object.
|
||||
*
|
||||
* @return List<Md5Metadata>
|
||||
*/
|
||||
List<CommonAttributeValue> getAttributeValues() {
|
||||
return Collections.unmodifiableList(this.attributeValues);
|
||||
CommonAttributeValueList getAttributeValues() {
|
||||
return this.attributeValues;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -101,17 +116,23 @@ final public class InstanceCountNode extends DisplayableItemNode {
|
||||
sheetSet = Sheet.createPropertiesSet();
|
||||
sheet.put(sheetSet);
|
||||
}
|
||||
|
||||
|
||||
final String NO_DESCR = Bundle.InstanceCountNode_createSheet_noDescription();
|
||||
sheetSet.put(new NodeProperty<>(Bundle.CommonFilesSearchResultsViewerTable_filesColLbl(), Bundle.CommonFilesSearchResultsViewerTable_filesColLbl(), NO_DESCR, ""));
|
||||
sheetSet.put(new NodeProperty<>(Bundle.CommonFilesSearchResultsViewerTable_instancesColLbl(), Bundle.CommonFilesSearchResultsViewerTable_instancesColLbl(), NO_DESCR, this.getInstanceCount()));
|
||||
sheetSet.put(new NodeProperty<>(Bundle.CommonFilesSearchResultsViewerTable_pathColLbl(), Bundle.CommonFilesSearchResultsViewerTable_pathColLbl(), NO_DESCR, ""));
|
||||
sheetSet.put(new NodeProperty<>(Bundle.CommonFilesSearchResultsViewerTable_caseColLbl1(), Bundle.CommonFilesSearchResultsViewerTable_caseColLbl1(), NO_DESCR, ""));
|
||||
sheetSet.put(new NodeProperty<>(Bundle.CommonFilesSearchResultsViewerTable_dataSourceColLbl(), Bundle.CommonFilesSearchResultsViewerTable_dataSourceColLbl(), NO_DESCR, ""));
|
||||
sheetSet.put(new NodeProperty<>(Bundle.CommonFilesSearchResultsViewerTable_hashsetHitsColLbl(), Bundle.CommonFilesSearchResultsViewerTable_hashsetHitsColLbl(), NO_DESCR, ""));
|
||||
sheetSet.put(new NodeProperty<>(Bundle.CommonFilesSearchResultsViewerTable_mimeTypeColLbl(), Bundle.CommonFilesSearchResultsViewerTable_mimeTypeColLbl(), NO_DESCR, ""));
|
||||
sheetSet.put(new NodeProperty<>(Bundle.CommonFilesSearchResultsViewerTable_tagsColLbl1(), Bundle.CommonFilesSearchResultsViewerTable_tagsColLbl1(), NO_DESCR, ""));
|
||||
|
||||
return sheet;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* ChildFactory which builds CommonFileParentNodes from the
|
||||
* CommonFilesMetaaData models.
|
||||
* CommonAttributeValue metadata models.
|
||||
*/
|
||||
static class CommonAttributeValueNodeFactory extends ChildFactory<String> {
|
||||
|
||||
@@ -138,11 +159,11 @@ final public class InstanceCountNode extends DisplayableItemNode {
|
||||
list.addAll(this.metadata.keySet());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected Node createNodeForKey(String attributeValue) {
|
||||
CommonAttributeValue md5Metadata = this.metadata.get(attributeValue);
|
||||
return new CommonAttributeValueNode(md5Metadata);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,8 +43,8 @@ abstract class InterCaseCommonAttributeSearcher extends AbstractCommonAttributeS
|
||||
*
|
||||
* @throws EamDbException
|
||||
*/
|
||||
InterCaseCommonAttributeSearcher(Map<Long, String> dataSourceIdMap, boolean filterByMediaMimeType, boolean filterByDocMimeType) throws EamDbException {
|
||||
super(dataSourceIdMap, filterByMediaMimeType, filterByDocMimeType);
|
||||
InterCaseCommonAttributeSearcher(Map<Long, String> dataSourceIdMap, boolean filterByMediaMimeType, boolean filterByDocMimeType, int percentageThreshold) throws EamDbException {
|
||||
super(dataSourceIdMap, filterByMediaMimeType, filterByDocMimeType, percentageThreshold);
|
||||
dbManager = EamDb.getInstance();
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,6 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import javax.swing.ComboBoxModel;
|
||||
import org.openide.util.NbBundle;
|
||||
|
||||
/**
|
||||
* UI controls for Common Files Search scenario where the user intends to find
|
||||
@@ -39,9 +38,7 @@ public class InterCasePanel extends javax.swing.JPanel {
|
||||
private ComboBoxModel<String> casesList = new DataSourceComboBoxModel();
|
||||
|
||||
private final Map<Integer, String> caseMap;
|
||||
|
||||
private String errorMessage;
|
||||
|
||||
|
||||
//True if we are looking in any or all cases,
|
||||
// false if we must find matches in a given case plus the current case
|
||||
private boolean anyCase;
|
||||
@@ -51,7 +48,6 @@ public class InterCasePanel extends javax.swing.JPanel {
|
||||
*/
|
||||
public InterCasePanel() {
|
||||
initComponents();
|
||||
this.errorMessage = "";
|
||||
this.caseMap = new HashMap<>();
|
||||
this.anyCase = true;
|
||||
}
|
||||
@@ -64,10 +60,6 @@ public class InterCasePanel extends javax.swing.JPanel {
|
||||
}
|
||||
}
|
||||
|
||||
String getErrorMessage(){
|
||||
return this.errorMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called from within the constructor to initialize the form.
|
||||
* WARNING: Do NOT modify this code. The content of this method is always
|
||||
@@ -189,16 +181,4 @@ public class InterCasePanel extends javax.swing.JPanel {
|
||||
|
||||
return InterCasePanel.NO_CASE_SELECTED;
|
||||
}
|
||||
|
||||
@NbBundle.Messages({
|
||||
"InterCasePanel.showInterCaseErrorMessage.message=Cannot run intercase correlation search: no cases in Central Repository."
|
||||
})
|
||||
boolean areSearchCriteriaMet() {
|
||||
if(this.caseMap.isEmpty()){
|
||||
this.errorMessage = Bundle.InterCasePanel_showInterCaseErrorMessage_message();
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,10 +20,8 @@ package org.sleuthkit.autopsy.commonfilesearch;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
@@ -100,7 +98,7 @@ final class InterCaseSearchResultsProcessor {
|
||||
*
|
||||
* @param currentCase The current TSK Case.
|
||||
*/
|
||||
Map<Integer, List<CommonAttributeValue>> findInterCaseCommonAttributeValues(Case currentCase) {
|
||||
Map<Integer, CommonAttributeValueList> findInterCaseCommonAttributeValues(Case currentCase) {
|
||||
try {
|
||||
InterCaseCommonAttributesCallback instancetableCallback = new InterCaseCommonAttributesCallback();
|
||||
EamDb DbManager = EamDb.getInstance();
|
||||
@@ -127,7 +125,7 @@ final class InterCaseSearchResultsProcessor {
|
||||
* @param currentCase The current TSK Case.
|
||||
* @param singleCase The case of interest. Matches must exist in this case.
|
||||
*/
|
||||
Map<Integer, List<CommonAttributeValue>> findSingleInterCaseCommonAttributeValues(Case currentCase, CorrelationCase singleCase) {
|
||||
Map<Integer, CommonAttributeValueList> findSingleInterCaseCommonAttributeValues(Case currentCase, CorrelationCase singleCase) {
|
||||
try {
|
||||
InterCaseCommonAttributesCallback instancetableCallback = new InterCaseCommonAttributesCallback();
|
||||
EamDb DbManager = EamDb.getInstance();
|
||||
@@ -149,7 +147,7 @@ final class InterCaseSearchResultsProcessor {
|
||||
*/
|
||||
private class InterCaseCommonAttributesCallback implements InstanceTableCallback {
|
||||
|
||||
final Map<Integer, List<CommonAttributeValue>> instanceCollatedCommonFiles = new HashMap<>();
|
||||
final Map<Integer, CommonAttributeValueList> instanceCollatedCommonFiles = new HashMap<>();
|
||||
|
||||
private CommonAttributeValue commonAttributeValue = null;
|
||||
private String previousRowMd5 = "";
|
||||
@@ -183,10 +181,10 @@ final class InterCaseSearchResultsProcessor {
|
||||
if (!md5Value.equals(previousRowMd5)) {
|
||||
int size = commonAttributeValue.getInstanceCount();
|
||||
if (instanceCollatedCommonFiles.containsKey(size)) {
|
||||
instanceCollatedCommonFiles.get(size).add(commonAttributeValue);
|
||||
instanceCollatedCommonFiles.get(size).addMetadataToList(commonAttributeValue);
|
||||
} else {
|
||||
ArrayList<CommonAttributeValue> value = new ArrayList<>();
|
||||
value.add(commonAttributeValue);
|
||||
CommonAttributeValueList value = new CommonAttributeValueList();
|
||||
value.addMetadataToList(commonAttributeValue);
|
||||
instanceCollatedCommonFiles.put(size, value);
|
||||
}
|
||||
|
||||
@@ -200,7 +198,7 @@ final class InterCaseSearchResultsProcessor {
|
||||
commonAttributeValue.addInstance(searchResult);
|
||||
}
|
||||
|
||||
Map<Integer, List<CommonAttributeValue>> getInstanceCollatedCommonFiles() {
|
||||
Map<Integer, CommonAttributeValueList> getInstanceCollatedCommonFiles() {
|
||||
return Collections.unmodifiableMap(instanceCollatedCommonFiles);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,8 +55,8 @@ public abstract class IntraCaseCommonAttributeSearcher extends AbstractCommonAtt
|
||||
* @param filterByDocMimeType match only on files whose mime types can be
|
||||
* broadly categorized as document types
|
||||
*/
|
||||
IntraCaseCommonAttributeSearcher(Map<Long, String> dataSourceIdMap, boolean filterByMediaMimeType, boolean filterByDocMimeType) {
|
||||
super(dataSourceIdMap, filterByMediaMimeType, filterByDocMimeType);
|
||||
IntraCaseCommonAttributeSearcher(Map<Long, String> dataSourceIdMap, boolean filterByMediaMimeType, boolean filterByDocMimeType, int percentageThreshold) {
|
||||
super(dataSourceIdMap, filterByMediaMimeType, filterByDocMimeType, percentageThreshold);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -128,9 +128,9 @@ public abstract class IntraCaseCommonAttributeSearcher extends AbstractCommonAtt
|
||||
}
|
||||
}
|
||||
|
||||
Map<Integer, List<CommonAttributeValue>> instanceCollatedCommonFiles = collateMatchesByNumberOfInstances(commonFiles);
|
||||
Map<Integer, CommonAttributeValueList> instanceCollatedCommonFiles = collateMatchesByNumberOfInstances(commonFiles);
|
||||
|
||||
return new CommonAttributeSearchResults(instanceCollatedCommonFiles);
|
||||
return new CommonAttributeSearchResults(instanceCollatedCommonFiles, this.frequencyPercentageThreshold);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -24,8 +24,6 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import javax.swing.ComboBoxModel;
|
||||
import org.openide.util.NbBundle;
|
||||
|
||||
/**
|
||||
* UI controls for Common Files Search scenario where the user intends to find
|
||||
* common files between datasources. It is an inner panel which provides the ability
|
||||
@@ -40,15 +38,12 @@ public class IntraCasePanel extends javax.swing.JPanel {
|
||||
private boolean singleDataSource;
|
||||
private ComboBoxModel<String> dataSourcesList = new DataSourceComboBoxModel();
|
||||
private final Map<Long, String> dataSourceMap;
|
||||
|
||||
private String errorMessage;
|
||||
|
||||
/**
|
||||
* Creates new form IntraCasePanel
|
||||
*/
|
||||
public IntraCasePanel() {
|
||||
initComponents();
|
||||
this.errorMessage = "";
|
||||
this.dataSourceMap = new HashMap<>();
|
||||
this.singleDataSource = true;
|
||||
}
|
||||
@@ -175,20 +170,4 @@ public class IntraCasePanel extends javax.swing.JPanel {
|
||||
this.dataSourceMap.clear();
|
||||
this.dataSourceMap.putAll(dataSourceMap);
|
||||
}
|
||||
|
||||
@NbBundle.Messages({
|
||||
"IntraCasePanel.areSearchCriteriaMet.message=Cannot run intra-case correlation search."
|
||||
})
|
||||
boolean areSearchCriteriaMet() {
|
||||
if(this.dataSourceMap.isEmpty()){
|
||||
this.errorMessage = Bundle.IntraCasePanel_areSearchCriteriaMet_message();
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
String getErrorMessage() {
|
||||
return this.errorMessage;
|
||||
}
|
||||
}
|
||||
@@ -44,8 +44,8 @@ public class SingleInterCaseCommonAttributeSearcher extends InterCaseCommonAttri
|
||||
* @param filterByDocMimeType
|
||||
* @throws EamDbException
|
||||
*/
|
||||
public SingleInterCaseCommonAttributeSearcher(int correlationCaseId, Map<Long, String> dataSourceIdMap, boolean filterByMediaMimeType, boolean filterByDocMimeType) throws EamDbException {
|
||||
super(dataSourceIdMap,filterByMediaMimeType, filterByDocMimeType);
|
||||
public SingleInterCaseCommonAttributeSearcher(int correlationCaseId, Map<Long, String> dataSourceIdMap, boolean filterByMediaMimeType, boolean filterByDocMimeType, int percentageThreshold) throws EamDbException {
|
||||
super(dataSourceIdMap,filterByMediaMimeType, filterByDocMimeType, percentageThreshold);
|
||||
|
||||
this.corrleationCaseId = correlationCaseId;
|
||||
this.correlationCaseName = "";
|
||||
@@ -72,9 +72,9 @@ public class SingleInterCaseCommonAttributeSearcher extends InterCaseCommonAttri
|
||||
|
||||
CommonAttributeSearchResults findFiles(CorrelationCase correlationCase) throws TskCoreException, NoCurrentCaseException, SQLException, EamDbException {
|
||||
InterCaseSearchResultsProcessor eamDbAttrInst = new InterCaseSearchResultsProcessor(this.getDataSourceIdToNameMap());
|
||||
Map<Integer, List<CommonAttributeValue>> interCaseCommonFiles = eamDbAttrInst.findSingleInterCaseCommonAttributeValues(Case.getCurrentCase(), correlationCase);
|
||||
Map<Integer, CommonAttributeValueList> interCaseCommonFiles = eamDbAttrInst.findSingleInterCaseCommonAttributeValues(Case.getCurrentCase(), correlationCase);
|
||||
|
||||
return new CommonAttributeSearchResults(interCaseCommonFiles);
|
||||
return new CommonAttributeSearchResults(interCaseCommonFiles, this.frequencyPercentageThreshold);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -41,8 +41,8 @@ final public class SingleIntraCaseCommonAttributeSearcher extends IntraCaseCommo
|
||||
* @param filterByDocMimeType match only on files whose mime types can be
|
||||
* broadly categorized as document types
|
||||
*/
|
||||
public SingleIntraCaseCommonAttributeSearcher(Long dataSourceId, Map<Long, String> dataSourceIdMap, boolean filterByMediaMimeType, boolean filterByDocMimeType) {
|
||||
super(dataSourceIdMap, filterByMediaMimeType, filterByDocMimeType);
|
||||
public SingleIntraCaseCommonAttributeSearcher(Long dataSourceId, Map<Long, String> dataSourceIdMap, boolean filterByMediaMimeType, boolean filterByDocMimeType, int percentageThreshold) {
|
||||
super(dataSourceIdMap, filterByMediaMimeType, filterByDocMimeType, percentageThreshold);
|
||||
this.selectedDataSourceId = dataSourceId;
|
||||
this.dataSourceName = dataSourceIdMap.get(this.selectedDataSourceId);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2018 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> 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.commonfilesearch;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import org.openide.util.NbBundle;
|
||||
|
||||
/**
|
||||
* Manager for present state of errors on the Common Files Search.
|
||||
*/
|
||||
class UserInputErrorManager {
|
||||
|
||||
static final int FREQUENCY_PERCENTAGE_OUT_OF_RANGE_KEY = 1;
|
||||
static final int NO_FILE_CATEGORIES_SELECTED_KEY = 2;
|
||||
|
||||
private final Map<Integer, ErrorMessage> currentErrors;
|
||||
|
||||
/**
|
||||
* Construct a new ErrorManager which can be used to track the status
|
||||
* of all known error states, retrieve error messages, and determine if
|
||||
* anything is in an error state.
|
||||
*/
|
||||
@NbBundle.Messages({
|
||||
"UserInputErrorManager.frequency=Invalid Frequency Percentage: 0 < % < 100.",
|
||||
"UserInputErrorManager.categories=No file categories are included in the search."})
|
||||
UserInputErrorManager (){
|
||||
|
||||
//when new errors are needed for the dialog, define a key and a value
|
||||
// and add them to the map.
|
||||
|
||||
this.currentErrors = new HashMap<>();
|
||||
this.currentErrors.put(FREQUENCY_PERCENTAGE_OUT_OF_RANGE_KEY, new ErrorMessage(Bundle.UserInputErrorManager_frequency()));
|
||||
this.currentErrors.put(NO_FILE_CATEGORIES_SELECTED_KEY, new ErrorMessage(Bundle.UserInputErrorManager_categories()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle the given error message on, or off
|
||||
* @param errorId the error to toggle
|
||||
* @param errorState true for on, false for off
|
||||
*/
|
||||
void setError(int errorId, boolean errorState){
|
||||
if(this.currentErrors.containsKey(errorId)){
|
||||
this.currentErrors.get(errorId).setStatus(errorState);
|
||||
} else {
|
||||
throw new IllegalArgumentException(String.format("The given errorId is not mapped to an ErrorMessage: %s.", errorId));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Are any user settings presently in an error state?
|
||||
* @return true for yes, else false
|
||||
*/
|
||||
boolean anyErrors(){
|
||||
return this.currentErrors.values().stream().anyMatch(errorMessage -> errorMessage.isErrorSet() == true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of distinct string messages describing the various error states.
|
||||
*/
|
||||
List<String> getErrors(){
|
||||
return this.currentErrors.values().stream()
|
||||
.filter(errorMessage -> errorMessage.isErrorSet() == true)
|
||||
.map(ErrorMessage::getMessage)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents an error message for the CommonFilesSearch panel, it's
|
||||
* uniqueId, and it's status.
|
||||
*/
|
||||
private class ErrorMessage {
|
||||
|
||||
private final String message;
|
||||
private boolean status;
|
||||
|
||||
/**
|
||||
* Create a message with a unique uniqueId. Default status is false (off).
|
||||
* @param uniqueId unique uniqueId
|
||||
* @param message message to display
|
||||
*/
|
||||
ErrorMessage(String message){
|
||||
this.message = message;
|
||||
this.status = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the status of this message
|
||||
* @param status
|
||||
*/
|
||||
void setStatus(boolean status){
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the message
|
||||
* @return
|
||||
*/
|
||||
String getMessage(){
|
||||
return this.message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the status (true for error status, false for no error)
|
||||
* @return
|
||||
*/
|
||||
boolean isErrorSet(){
|
||||
return this.status;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -29,6 +29,7 @@
|
||||
<Container class="org.openide.explorer.view.OutlineView" name="outlineView">
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new OutlineView(DataResultViewerTable.FIRST_COLUMN_LABEL);"/>
|
||||
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="4"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
||||
|
||||
@@ -111,6 +111,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
|
||||
public DataResultViewerTable() {
|
||||
this(null, Bundle.DataResultViewerTable_title());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a tabular result viewer that displays the children of a given
|
||||
@@ -1031,7 +1032,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
|
||||
);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private org.openide.explorer.view.OutlineView outlineView;
|
||||
protected org.openide.explorer.view.OutlineView outlineView;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2018 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> 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.corecomponents;
|
||||
|
||||
import javax.swing.event.TreeExpansionEvent;
|
||||
import javax.swing.event.TreeExpansionListener;
|
||||
import org.openide.explorer.view.Visualizer;
|
||||
import org.openide.nodes.Node;
|
||||
|
||||
/**
|
||||
* A tree expansion listener that will trigger a recreation of childs through
|
||||
* its child factory on re-expansion of a node (causes to recreate the
|
||||
* ChildFactory for this purpose.).
|
||||
*/
|
||||
public final class DelayedLoadChildNodesOnTreeExpansion implements TreeExpansionListener {
|
||||
|
||||
/**
|
||||
* A flag for avoiding endless recursion inside the expansion listener that
|
||||
* could trigger collapsing and (re-)expanding nodes again.
|
||||
* @param event
|
||||
*/
|
||||
|
||||
@Override
|
||||
public synchronized void treeCollapsed(final TreeExpansionEvent event) {
|
||||
// Do nothing on collapse. Netbeans should manage nodes falling out of scope and GC.
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void treeExpanded(final TreeExpansionEvent event) {
|
||||
Node eventNode = Visualizer.findNode(event.getPath().getLastPathComponent());
|
||||
if (eventNode instanceof TableFilterNode) {
|
||||
final TableFilterNode node = (TableFilterNode) eventNode;
|
||||
node.refresh();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -128,6 +128,16 @@ public class TableFilterNode extends FilterNode {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Refreshes the inner node, which depending on the actual node type that was wrapped
|
||||
* could trigger a dynamic refresh of the children, if supported.
|
||||
*/
|
||||
void refresh() {
|
||||
DataResultFilterNode innerNode = getLookup().lookup(DataResultFilterNode.class);
|
||||
innerNode.refresh();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the column order key, which allows custom column ordering to be
|
||||
|
||||
@@ -30,7 +30,6 @@ import java.util.stream.Collectors;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.openide.nodes.Children;
|
||||
import org.openide.nodes.Sheet;
|
||||
import org.openide.util.Exceptions;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.WeakListeners;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
@@ -38,11 +37,8 @@ import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||
import org.sleuthkit.autopsy.casemodule.events.CommentChangedEvent;
|
||||
import org.sleuthkit.autopsy.casemodule.events.ContentTagAddedEvent;
|
||||
import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent;
|
||||
import org.sleuthkit.autopsy.casemodule.services.TagsManager;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamArtifactUtil;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbUtil;
|
||||
import org.sleuthkit.autopsy.corecomponents.DataResultViewerTable.Score;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
|
||||
@@ -49,11 +49,8 @@ import org.sleuthkit.autopsy.casemodule.events.BlackBoardArtifactTagDeletedEvent
|
||||
import org.sleuthkit.autopsy.casemodule.events.CommentChangedEvent;
|
||||
import org.sleuthkit.autopsy.casemodule.events.ContentTagAddedEvent;
|
||||
import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent;
|
||||
import org.sleuthkit.autopsy.casemodule.services.TagsManager;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamArtifactUtil;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbUtil;
|
||||
import org.sleuthkit.autopsy.corecomponents.DataResultViewerTable.Score;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
|
||||
@@ -132,26 +132,38 @@ public class DataResultFilterNode extends FilterNode {
|
||||
* wrapped node and may filter out some of its children.
|
||||
*
|
||||
* @param node The node to wrap.
|
||||
* @param em The ExplorerManager for the component that is creating the
|
||||
* node.
|
||||
* @param em The ExplorerManager for the component that is creating the
|
||||
* node.
|
||||
*/
|
||||
public DataResultFilterNode(Node node, ExplorerManager em) {
|
||||
super(node, new DataResultFilterChildren(node, em));
|
||||
this.sourceEm = em;
|
||||
}
|
||||
|
||||
/**
|
||||
* Refreshes the inner node. If the actual underlying node is an InstanceCountNode,
|
||||
* refresh() that node, which refreshes the children.
|
||||
*
|
||||
*/
|
||||
public void refresh() {
|
||||
if (getOriginal() instanceof InstanceCountNode) {
|
||||
InstanceCountNode innerNode = getLookup().lookup(InstanceCountNode.class);
|
||||
innerNode.refresh();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a node used to wrap another node before passing it to the
|
||||
* result viewers. The wrapper node defines the actions associated with the
|
||||
* wrapped node and may filter out some of its children.
|
||||
*
|
||||
* @param node The node to wrap.
|
||||
* @param em The ExplorerManager for the component that is creating
|
||||
* the node.
|
||||
* @param node The node to wrap.
|
||||
* @param em The ExplorerManager for the component that is creating the
|
||||
* node.
|
||||
* @param filterKnown Whether or not to filter out children that represent
|
||||
* known files.
|
||||
* known files.
|
||||
* @param filterSlack Whether or not to filter out children that represent
|
||||
* virtual slack space files.
|
||||
* virtual slack space files.
|
||||
*/
|
||||
private DataResultFilterNode(Node node, ExplorerManager em, boolean filterKnown, boolean filterSlack) {
|
||||
super(node, new DataResultFilterChildren(node, em, filterKnown, filterSlack));
|
||||
@@ -261,7 +273,7 @@ public class DataResultFilterNode extends FilterNode {
|
||||
* selected.
|
||||
*
|
||||
* @return The child node selection information, or null if no child should
|
||||
* be selected.
|
||||
* be selected.
|
||||
*/
|
||||
public NodeSelectionInfo getChildNodeSelectionInfo() {
|
||||
if (getOriginal() instanceof DisplayableItemNode) {
|
||||
@@ -390,14 +402,14 @@ public class DataResultFilterNode extends FilterNode {
|
||||
NbBundle.getMessage(this.getClass(), "DataResultFilterNode.action.viewFileInDir.text"), c));
|
||||
}
|
||||
// action to go to the source file of the artifact
|
||||
// action to go to the source file of the artifact
|
||||
// action to go to the source file of the artifact
|
||||
Content fileContent = ban.getLookup().lookup(AbstractFile.class);
|
||||
if (fileContent == null) {
|
||||
Content content = ban.getLookup().lookup(Content.class);
|
||||
actionsList.add(new ViewContextAction("View Source Content in Directory", content));
|
||||
} else {
|
||||
actionsList.add(new ViewContextAction(
|
||||
NbBundle.getMessage(this.getClass(), "DataResultFilterNode.action.viewSrcFileInDir.text"), ban));
|
||||
NbBundle.getMessage(this.getClass(), "DataResultFilterNode.action.viewSrcFileInDir.text"), ban));
|
||||
}
|
||||
}
|
||||
Content c = ban.getLookup().lookup(File.class);
|
||||
@@ -524,21 +536,21 @@ public class DataResultFilterNode extends FilterNode {
|
||||
*/
|
||||
private class GetPreferredActionsDisplayableItemNodeVisitor extends DisplayableItemNodeVisitor.Default<AbstractAction> {
|
||||
|
||||
@Override
|
||||
public AbstractAction visit(InstanceCountNode icn){
|
||||
@Override
|
||||
public AbstractAction visit(InstanceCountNode icn) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public AbstractAction visit(CommonAttributeValueNode md5n){
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public AbstractAction visit(CaseDBCommonAttributeInstanceNode fin){
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public AbstractAction visit(CentralRepoCommonAttributeInstanceNode iccan){
|
||||
return null;
|
||||
|
||||
@@ -86,7 +86,7 @@ public class IngestedWithHashAndFileTypeInterCaseTests extends NbTestCase {
|
||||
Map<Long, String> dataSources = this.utils.getDataSourceMap();
|
||||
|
||||
//note that the params false and false are presently meaningless because that feature is not supported yet
|
||||
AbstractCommonAttributeSearcher builder = new AllInterCaseCommonAttributeSearcher(dataSources, false, false);
|
||||
AbstractCommonAttributeSearcher builder = new AllInterCaseCommonAttributeSearcher(dataSources, false, false, 0);
|
||||
|
||||
CommonAttributeSearchResults metadata = builder.findFiles();
|
||||
|
||||
@@ -139,7 +139,7 @@ public class IngestedWithHashAndFileTypeInterCaseTests extends NbTestCase {
|
||||
|
||||
int matchesMustAlsoBeFoundInThisCase = this.utils.getCaseMap().get(CASE2);
|
||||
|
||||
AbstractCommonAttributeSearcher builder = new SingleInterCaseCommonAttributeSearcher(matchesMustAlsoBeFoundInThisCase, dataSources, false, false);
|
||||
AbstractCommonAttributeSearcher builder = new SingleInterCaseCommonAttributeSearcher(matchesMustAlsoBeFoundInThisCase, dataSources, false, false, 0);
|
||||
|
||||
CommonAttributeSearchResults metadata = builder.findFiles();
|
||||
|
||||
@@ -182,4 +182,56 @@ public class IngestedWithHashAndFileTypeInterCaseTests extends NbTestCase {
|
||||
Assert.fail(ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* We should be able to observe that certain files o no longer returned
|
||||
* in the result set since they do not appear frequently enough.
|
||||
*/
|
||||
public void testThree(){
|
||||
try {
|
||||
Map<Long, String> dataSources = this.utils.getDataSourceMap();
|
||||
|
||||
//note that the params false and false are presently meaningless because that feature is not supported yet
|
||||
AbstractCommonAttributeSearcher builder = new AllInterCaseCommonAttributeSearcher(dataSources, false, false, 50);
|
||||
|
||||
CommonAttributeSearchResults metadata = builder.findFiles();
|
||||
|
||||
assertTrue("Results should not be empty", metadata.size() != 0);
|
||||
|
||||
//case 1 data set 1
|
||||
assertTrue(verifyInstanceExistanceAndCount(metadata, HASH_0_DAT, CASE1_DATASET_1, CASE1, 0));
|
||||
assertTrue(verifyInstanceExistanceAndCount(metadata, HASH_A_PDF, CASE1_DATASET_1, CASE1, 1));
|
||||
assertTrue(verifyInstanceExistanceAndCount(metadata, HASH_A_JPG, CASE1_DATASET_1, CASE1, 1));
|
||||
|
||||
//case 1 data set 2
|
||||
assertTrue(verifyInstanceExistanceAndCount(metadata, HASH_0_DAT, CASE1_DATASET_2, CASE1, 0));
|
||||
assertTrue(verifyInstanceExistanceAndCount(metadata, HASH_A_PDF, CASE1_DATASET_2, CASE1, 1));
|
||||
assertTrue(verifyInstanceExistanceAndCount(metadata, HASH_A_JPG, CASE1_DATASET_2, CASE1, 1));
|
||||
|
||||
//case 2 data set 1
|
||||
assertTrue(verifyInstanceExistanceAndCount(metadata, HASH_B_PDF, CASE2_DATASET_1, CASE2, 0));
|
||||
assertTrue(verifyInstanceExistanceAndCount(metadata, HASH_B_JPG, CASE2_DATASET_1, CASE2, 0));
|
||||
|
||||
//case 2 data set 2
|
||||
assertTrue(verifyInstanceExistanceAndCount(metadata, HASH_A_PDF, CASE2_DATASET_2, CASE2, 1));
|
||||
assertTrue(verifyInstanceExistanceAndCount(metadata, HASH_A_JPG, CASE2_DATASET_2, CASE2, 1));
|
||||
assertTrue(verifyInstanceExistanceAndCount(metadata, HASH_D_DOC, CASE2_DATASET_2, CASE2, 0));
|
||||
|
||||
//case 3 data set 1
|
||||
assertTrue(verifyInstanceExistanceAndCount(metadata, HASH_A_JPG, CASE3_DATASET_1, CASE3, 1));
|
||||
assertTrue(verifyInstanceExistanceAndCount(metadata, HASH_A_PDF, CASE3_DATASET_1, CASE3, 1));
|
||||
assertTrue(verifyInstanceExistanceAndCount(metadata, HASH_C_JPG, CASE3_DATASET_1, CASE3, 0));
|
||||
assertTrue(verifyInstanceExistanceAndCount(metadata, HASH_C_PDF, CASE3_DATASET_1, CASE3, 0));
|
||||
assertTrue(verifyInstanceExistanceAndCount(metadata, HASH_D_JPG, CASE3_DATASET_1, CASE3, 0));
|
||||
|
||||
//case 3 data set 2
|
||||
assertTrue(verifyInstanceExistanceAndCount(metadata, HASH_C_JPG, CASE3_DATASET_2, CASE3, 0));
|
||||
assertTrue(verifyInstanceExistanceAndCount(metadata, HASH_C_PDF, CASE3_DATASET_2, CASE3, 0));
|
||||
assertTrue(verifyInstanceExistanceAndCount(metadata, HASH_D_DOC, CASE3_DATASET_2, CASE3, 0));
|
||||
|
||||
} catch (TskCoreException | NoCurrentCaseException | SQLException | EamDbException ex) {
|
||||
Exceptions.printStackTrace(ex);
|
||||
Assert.fail(ex.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,7 +99,7 @@ public class IngestedWithHashAndFileTypeIntraCaseTests extends NbTestCase {
|
||||
try {
|
||||
Map<Long, String> dataSources = this.utils.getDataSourceMap();
|
||||
|
||||
AbstractCommonAttributeSearcher allSourcesBuilder = new AllIntraCaseCommonAttributeSearcher(dataSources, false, false);
|
||||
AbstractCommonAttributeSearcher allSourcesBuilder = new AllIntraCaseCommonAttributeSearcher(dataSources, false, false, 0);
|
||||
CommonAttributeSearchResults metadata = allSourcesBuilder.findFiles();
|
||||
|
||||
Map<Long, String> objectIdToDataSource = IntraCaseTestUtils.mapFileInstancesToDataSources(metadata);
|
||||
@@ -140,7 +140,7 @@ public class IngestedWithHashAndFileTypeIntraCaseTests extends NbTestCase {
|
||||
try {
|
||||
Map<Long, String> dataSources = this.utils.getDataSourceMap();
|
||||
|
||||
AbstractCommonAttributeSearcher allSourcesBuilder = new AllIntraCaseCommonAttributeSearcher(dataSources, true, false);
|
||||
AbstractCommonAttributeSearcher allSourcesBuilder = new AllIntraCaseCommonAttributeSearcher(dataSources, true, false, 0);
|
||||
CommonAttributeSearchResults metadata = allSourcesBuilder.findFiles();
|
||||
|
||||
Map<Long, String> objectIdToDataSource = mapFileInstancesToDataSources(metadata);
|
||||
@@ -181,7 +181,7 @@ public class IngestedWithHashAndFileTypeIntraCaseTests extends NbTestCase {
|
||||
try {
|
||||
Map<Long, String> dataSources = this.utils.getDataSourceMap();
|
||||
|
||||
AbstractCommonAttributeSearcher allSourcesBuilder = new AllIntraCaseCommonAttributeSearcher(dataSources, false, true);
|
||||
AbstractCommonAttributeSearcher allSourcesBuilder = new AllIntraCaseCommonAttributeSearcher(dataSources, false, true, 0);
|
||||
CommonAttributeSearchResults metadata = allSourcesBuilder.findFiles();
|
||||
|
||||
Map<Long, String> objectIdToDataSource = mapFileInstancesToDataSources(metadata);
|
||||
@@ -223,7 +223,7 @@ public class IngestedWithHashAndFileTypeIntraCaseTests extends NbTestCase {
|
||||
Map<Long, String> dataSources = this.utils.getDataSourceMap();
|
||||
Long first = getDataSourceIdByName(SET1, dataSources);
|
||||
|
||||
AbstractCommonAttributeSearcher singleSourceBuilder = new SingleIntraCaseCommonAttributeSearcher(first, dataSources, false, false);
|
||||
AbstractCommonAttributeSearcher singleSourceBuilder = new SingleIntraCaseCommonAttributeSearcher(first, dataSources, false, false, 0);
|
||||
CommonAttributeSearchResults metadata = singleSourceBuilder.findFiles();
|
||||
|
||||
Map<Long, String> objectIdToDataSource = mapFileInstancesToDataSources(metadata);
|
||||
@@ -265,7 +265,7 @@ public class IngestedWithHashAndFileTypeIntraCaseTests extends NbTestCase {
|
||||
Map<Long, String> dataSources = this.utils.getDataSourceMap();
|
||||
Long first = getDataSourceIdByName(SET1, dataSources);
|
||||
|
||||
AbstractCommonAttributeSearcher singleSourceBuilder = new SingleIntraCaseCommonAttributeSearcher(first, dataSources, true, false);
|
||||
AbstractCommonAttributeSearcher singleSourceBuilder = new SingleIntraCaseCommonAttributeSearcher(first, dataSources, true, false, 0);
|
||||
CommonAttributeSearchResults metadata = singleSourceBuilder.findFiles();
|
||||
|
||||
Map<Long, String> objectIdToDataSource = mapFileInstancesToDataSources(metadata);
|
||||
@@ -307,7 +307,7 @@ public class IngestedWithHashAndFileTypeIntraCaseTests extends NbTestCase {
|
||||
Map<Long, String> dataSources = this.utils.getDataSourceMap();
|
||||
Long first = getDataSourceIdByName(SET1, dataSources);
|
||||
|
||||
AbstractCommonAttributeSearcher singleSourceBuilder = new SingleIntraCaseCommonAttributeSearcher(first, dataSources, false, true);
|
||||
AbstractCommonAttributeSearcher singleSourceBuilder = new SingleIntraCaseCommonAttributeSearcher(first, dataSources, false, true, 0);
|
||||
CommonAttributeSearchResults metadata = singleSourceBuilder.findFiles();
|
||||
|
||||
Map<Long, String> objectIdToDataSource = mapFileInstancesToDataSources(metadata);
|
||||
@@ -349,7 +349,7 @@ public class IngestedWithHashAndFileTypeIntraCaseTests extends NbTestCase {
|
||||
Map<Long, String> dataSources = this.utils.getDataSourceMap();
|
||||
Long second = getDataSourceIdByName(SET2, dataSources);
|
||||
|
||||
AbstractCommonAttributeSearcher singleSourceBuilder = new SingleIntraCaseCommonAttributeSearcher(second, dataSources, false, false);
|
||||
AbstractCommonAttributeSearcher singleSourceBuilder = new SingleIntraCaseCommonAttributeSearcher(second, dataSources, false, false, 0);
|
||||
CommonAttributeSearchResults metadata = singleSourceBuilder.findFiles();
|
||||
|
||||
Map<Long, String> objectIdToDataSource = mapFileInstancesToDataSources(metadata);
|
||||
@@ -390,7 +390,7 @@ public class IngestedWithHashAndFileTypeIntraCaseTests extends NbTestCase {
|
||||
Map<Long, String> dataSources = this.utils.getDataSourceMap();
|
||||
Long last = getDataSourceIdByName(SET4, dataSources);
|
||||
|
||||
AbstractCommonAttributeSearcher singleSourceBuilder = new SingleIntraCaseCommonAttributeSearcher(last, dataSources, false, false);
|
||||
AbstractCommonAttributeSearcher singleSourceBuilder = new SingleIntraCaseCommonAttributeSearcher(last, dataSources, false, false, 0);
|
||||
CommonAttributeSearchResults metadata = singleSourceBuilder.findFiles();
|
||||
|
||||
Map<Long, String> objectIdToDataSource = mapFileInstancesToDataSources(metadata);
|
||||
@@ -431,7 +431,7 @@ public class IngestedWithHashAndFileTypeIntraCaseTests extends NbTestCase {
|
||||
Map<Long, String> dataSources = this.utils.getDataSourceMap();
|
||||
Long third = getDataSourceIdByName(SET3, dataSources);
|
||||
|
||||
AbstractCommonAttributeSearcher singleSourceBuilder = new SingleIntraCaseCommonAttributeSearcher(third, dataSources, false, false);
|
||||
AbstractCommonAttributeSearcher singleSourceBuilder = new SingleIntraCaseCommonAttributeSearcher(third, dataSources, false, false, 0);
|
||||
CommonAttributeSearchResults metadata = singleSourceBuilder.findFiles();
|
||||
|
||||
Map<Long, String> objectIdToDataSource = mapFileInstancesToDataSources(metadata);
|
||||
|
||||
@@ -101,7 +101,7 @@ public class IngestedWithNoFileTypesIntraCaseTests extends NbTestCase {
|
||||
try {
|
||||
Map<Long, String> dataSources = this.utils.getDataSourceMap();
|
||||
|
||||
IntraCaseCommonAttributeSearcher allSourcesBuilder = new AllIntraCaseCommonAttributeSearcher(dataSources, true, false);
|
||||
IntraCaseCommonAttributeSearcher allSourcesBuilder = new AllIntraCaseCommonAttributeSearcher(dataSources, true, false, 0);
|
||||
CommonAttributeSearchResults metadata = allSourcesBuilder.findFiles();
|
||||
|
||||
Map<Long, String> objectIdToDataSource = IntraCaseTestUtils.mapFileInstancesToDataSources(metadata);
|
||||
@@ -125,7 +125,7 @@ public class IngestedWithNoFileTypesIntraCaseTests extends NbTestCase {
|
||||
Map<Long, String> dataSources = this.utils.getDataSourceMap();
|
||||
Long third = IntraCaseTestUtils.getDataSourceIdByName(IntraCaseTestUtils.SET3, dataSources);
|
||||
|
||||
IntraCaseCommonAttributeSearcher singleSourceBuilder = new SingleIntraCaseCommonAttributeSearcher(third, dataSources, true, false);
|
||||
IntraCaseCommonAttributeSearcher singleSourceBuilder = new SingleIntraCaseCommonAttributeSearcher(third, dataSources, true, false, 0);
|
||||
CommonAttributeSearchResults metadata = singleSourceBuilder.findFiles();
|
||||
|
||||
Map<Long, String> objectIdToDataSource = IntraCaseTestUtils.mapFileInstancesToDataSources(metadata);
|
||||
|
||||
@@ -57,50 +57,36 @@ import org.sleuthkit.autopsy.commonfilesearch.CentralRepoCommonAttributeInstance
|
||||
import org.sleuthkit.autopsy.commonfilesearch.CommonAttributeSearchResults;
|
||||
import org.sleuthkit.autopsy.commonfilesearch.DataSourceLoader;
|
||||
import org.sleuthkit.autopsy.commonfilesearch.CommonAttributeValue;
|
||||
import org.sleuthkit.autopsy.commonfilesearch.CommonAttributeValueList;
|
||||
import org.sleuthkit.autopsy.datamodel.DisplayableItemNode;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
|
||||
/**
|
||||
* Utilities for testing intercase correlation feature.
|
||||
*
|
||||
* This will be more useful when we add more flush out the intercase
|
||||
* correlation features and need to add more tests. In particular,
|
||||
* testing scenarios where we need different cases to be the current case
|
||||
* will suggest that we create additional test classes, and we will want to
|
||||
* import this utility in each new intercase test file.
|
||||
*
|
||||
* Description of Test Data:
|
||||
(Note: files of the same name and extension are identical;
|
||||
files of the same name and differing extension are not identical.)
|
||||
|
||||
Case 1
|
||||
+Data Set 1
|
||||
- Hash-0.dat [testFile of size 0]
|
||||
- Hash-A.jpg
|
||||
- Hash-A.pdf
|
||||
+Data Set2
|
||||
- Hash-0.dat [testFile of size 0]
|
||||
- Hash-A.jpg
|
||||
- Hash-A.pdf
|
||||
Case 2
|
||||
+Data Set 1
|
||||
- Hash-B.jpg
|
||||
- Hash-B.pdf
|
||||
+Data Set 2
|
||||
- Hash-A.jpg
|
||||
- Hash-A.pdf
|
||||
- Hash_D.doc
|
||||
Case 3
|
||||
+Data Set 1
|
||||
- Hash-A.jpg
|
||||
- Hash-A.pdf
|
||||
- Hash-C.jpg
|
||||
- Hash-C.pdf
|
||||
- Hash-D.jpg
|
||||
+Data Set 2
|
||||
- Hash-C.jpg
|
||||
- Hash-C.pdf
|
||||
- Hash-D.doc
|
||||
*
|
||||
* This will be more useful when we add more flush out the intercase correlation
|
||||
* features and need to add more tests. In particular, testing scenarios where
|
||||
* we need different cases to be the current case will suggest that we create
|
||||
* additional test classes, and we will want to import this utility in each new
|
||||
* intercase test file.
|
||||
*
|
||||
* Description of Test Data: (Note: files of the same name and extension are
|
||||
* identical; files of the same name and differing extension are not identical.)
|
||||
*
|
||||
* Case 1 +Data Set 1 - Hash-0.dat [testFile of size 0] - Hash-A.jpg -
|
||||
* Hash-A.pdf +Data Set2 - Hash-0.dat [testFile of size 0] - Hash-A.jpg -
|
||||
* Hash-A.pdf Case 2 +Data Set 1 - Hash-B.jpg - Hash-B.pdf +Data Set 2 -
|
||||
* Hash-A.jpg - Hash-A.pdf - Hash_D.doc Case 3 +Data Set 1 - Hash-A.jpg -
|
||||
* Hash-A.pdf - Hash-C.jpg - Hash-C.pdf - Hash-D.jpg +Data Set 2 - Hash-C.jpg -
|
||||
* Hash-C.pdf - Hash-D.doc
|
||||
*
|
||||
* Frequency Breakdown (ratio of datasources a given file appears in to total
|
||||
* number of datasources):
|
||||
*
|
||||
* Hash-0.dat - moot; these are always excluded Hash-A.jpg - 4/6 Hash-A.pdf -
|
||||
* 4/6 Hash-B.jpg - 1/6 Hash-B.pdf - 1/6 Hash-C.jpg - 2/6 Hash-C.pdf - 2/6
|
||||
* Hash_D.doc - 2/6 Hash-D.jpg - 1/6
|
||||
*
|
||||
*/
|
||||
class InterCaseTestUtils {
|
||||
|
||||
@@ -173,21 +159,21 @@ class InterCaseTestUtils {
|
||||
this.dataSourceLoader = new DataSourceLoader();
|
||||
}
|
||||
|
||||
void clearTestDir(){
|
||||
if(CASE_DIRECTORY_PATH.toFile().exists()){
|
||||
try{
|
||||
if(EamDb.isEnabled()) {
|
||||
void clearTestDir() {
|
||||
if (CASE_DIRECTORY_PATH.toFile().exists()) {
|
||||
try {
|
||||
if (EamDb.isEnabled()) {
|
||||
EamDb.getInstance().shutdownConnections();
|
||||
}
|
||||
FileUtils.deleteDirectory(CASE_DIRECTORY_PATH.toFile());
|
||||
} catch(IOException | EamDbException ex){
|
||||
} catch (IOException | EamDbException ex) {
|
||||
Exceptions.printStackTrace(ex);
|
||||
Assert.fail(ex.getMessage());
|
||||
}
|
||||
}
|
||||
CASE_DIRECTORY_PATH.toFile().exists();
|
||||
}
|
||||
|
||||
|
||||
Map<Long, String> getDataSourceMap() throws NoCurrentCaseException, TskCoreException, SQLException {
|
||||
return this.dataSourceLoader.getDataSourceMap();
|
||||
}
|
||||
@@ -224,7 +210,7 @@ class InterCaseTestUtils {
|
||||
if (!crSettings.dbDirectoryExists()) {
|
||||
crSettings.createDbDirectory();
|
||||
}
|
||||
|
||||
|
||||
crSettings.initializeDatabaseSchema();
|
||||
crSettings.insertDefaultDatabaseContent();
|
||||
|
||||
@@ -303,70 +289,77 @@ class InterCaseTestUtils {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
static boolean verifyInstanceExistanceAndCount(CommonAttributeSearchResults searchDomain, String fileName, String dataSource, String crCase, int instanceCount){
|
||||
|
||||
int tally = 0;
|
||||
|
||||
for(Map.Entry<Integer, List<CommonAttributeValue>> entry : searchDomain.getMetadata().entrySet()){
|
||||
|
||||
for(CommonAttributeValue value : entry.getValue()){
|
||||
|
||||
for(AbstractCommonAttributeInstance commonAttribute : value.getInstances()){
|
||||
|
||||
if(commonAttribute instanceof CentralRepoCommonAttributeInstance){
|
||||
CentralRepoCommonAttributeInstance results = (CentralRepoCommonAttributeInstance) commonAttribute;
|
||||
for (DisplayableItemNode din : results.generateNodes()){
|
||||
|
||||
if(din instanceof CentralRepoCommonAttributeInstanceNode){
|
||||
|
||||
CentralRepoCommonAttributeInstanceNode node = (CentralRepoCommonAttributeInstanceNode) din;
|
||||
CorrelationAttributeInstance instance = node.getCorrelationAttributeInstance();
|
||||
|
||||
final String fullPath = instance.getFilePath();
|
||||
final File testFile = new File(fullPath);
|
||||
|
||||
final String testCaseName = instance.getCorrelationCase().getDisplayName();
|
||||
static boolean verifyInstanceExistanceAndCount(CommonAttributeSearchResults searchDomain, String fileName, String dataSource, String crCase, int instanceCount) {
|
||||
|
||||
final String testFileName = testFile.getName();
|
||||
try {
|
||||
int tally = 0;
|
||||
|
||||
final String testDataSource = instance.getCorrelationDataSource().getName();
|
||||
for (Map.Entry<Integer, CommonAttributeValueList> entry : searchDomain.getMetadata().entrySet()) {
|
||||
entry.getValue().displayDelayedMetadata();
|
||||
for (CommonAttributeValue value : entry.getValue().getMetadataList()) {
|
||||
|
||||
boolean sameFileName = testFileName.equalsIgnoreCase(fileName);
|
||||
boolean sameDataSource = testDataSource.equalsIgnoreCase(dataSource);
|
||||
boolean sameCrCase = testCaseName.equalsIgnoreCase(crCase);
|
||||
for (AbstractCommonAttributeInstance commonAttribute : value.getInstances()) {
|
||||
|
||||
if( sameFileName && sameDataSource && sameCrCase){
|
||||
tally++;
|
||||
}
|
||||
}
|
||||
|
||||
if(din instanceof CaseDBCommonAttributeInstanceNode){
|
||||
|
||||
CaseDBCommonAttributeInstanceNode node = (CaseDBCommonAttributeInstanceNode) din;
|
||||
AbstractFile file = node.getContent();
|
||||
|
||||
final String testFileName = file.getName();
|
||||
final String testCaseName = node.getCase();
|
||||
final String testDataSource = node.getDataSource();
|
||||
|
||||
boolean sameFileName = testFileName.equalsIgnoreCase(fileName);
|
||||
boolean sameCaseName = testCaseName.equalsIgnoreCase(crCase);
|
||||
boolean sameDataSource = testDataSource.equalsIgnoreCase(dataSource);
|
||||
|
||||
if(sameFileName && sameDataSource && sameCaseName){
|
||||
tally++;
|
||||
if (commonAttribute instanceof CentralRepoCommonAttributeInstance) {
|
||||
CentralRepoCommonAttributeInstance results = (CentralRepoCommonAttributeInstance) commonAttribute;
|
||||
for (DisplayableItemNode din : results.generateNodes()) {
|
||||
|
||||
if (din instanceof CentralRepoCommonAttributeInstanceNode) {
|
||||
|
||||
CentralRepoCommonAttributeInstanceNode node = (CentralRepoCommonAttributeInstanceNode) din;
|
||||
CorrelationAttributeInstance instance = node.getCorrelationAttributeInstance();
|
||||
|
||||
final String fullPath = instance.getFilePath();
|
||||
final File testFile = new File(fullPath);
|
||||
|
||||
final String testCaseName = instance.getCorrelationCase().getDisplayName();
|
||||
|
||||
final String testFileName = testFile.getName();
|
||||
|
||||
final String testDataSource = instance.getCorrelationDataSource().getName();
|
||||
|
||||
boolean sameFileName = testFileName.equalsIgnoreCase(fileName);
|
||||
boolean sameDataSource = testDataSource.equalsIgnoreCase(dataSource);
|
||||
boolean sameCrCase = testCaseName.equalsIgnoreCase(crCase);
|
||||
|
||||
if (sameFileName && sameDataSource && sameCrCase) {
|
||||
tally++;
|
||||
}
|
||||
}
|
||||
|
||||
if (din instanceof CaseDBCommonAttributeInstanceNode) {
|
||||
|
||||
CaseDBCommonAttributeInstanceNode node = (CaseDBCommonAttributeInstanceNode) din;
|
||||
AbstractFile file = node.getContent();
|
||||
|
||||
final String testFileName = file.getName();
|
||||
final String testCaseName = node.getCase();
|
||||
final String testDataSource = node.getDataSource();
|
||||
|
||||
boolean sameFileName = testFileName.equalsIgnoreCase(fileName);
|
||||
boolean sameCaseName = testCaseName.equalsIgnoreCase(crCase);
|
||||
boolean sameDataSource = testDataSource.equalsIgnoreCase(dataSource);
|
||||
|
||||
if (sameFileName && sameDataSource && sameCaseName) {
|
||||
tally++;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Assert.fail("Unable to cast AbstractCommonAttributeInstanceNode to InterCaseCommonAttributeSearchResults.");
|
||||
}
|
||||
} else {
|
||||
Assert.fail("Unable to cast AbstractCommonAttributeInstanceNode to InterCaseCommonAttributeSearchResults.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tally == instanceCount;
|
||||
|
||||
} catch (EamDbException ex) {
|
||||
Exceptions.printStackTrace(ex);
|
||||
Assert.fail(ex.getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
return tally == instanceCount;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -374,13 +367,13 @@ class InterCaseTestUtils {
|
||||
* central repo db.
|
||||
*/
|
||||
void tearDown() {
|
||||
|
||||
|
||||
CaseUtils.closeCurrentCase(false);
|
||||
|
||||
String[] cases = new String[]{CASE1,CASE2,CASE3};
|
||||
|
||||
|
||||
String[] cases = new String[]{CASE1, CASE2, CASE3};
|
||||
|
||||
try {
|
||||
for(String caze : cases){
|
||||
for (String caze : cases) {
|
||||
CaseUtils.deleteCaseDir(new File(caze));
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
|
||||
@@ -33,10 +33,12 @@ import junit.framework.Assert;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.casemodule.ImageDSProcessor;
|
||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException;
|
||||
import org.sleuthkit.autopsy.commonfilesearch.AbstractCommonAttributeInstance;
|
||||
import org.sleuthkit.autopsy.commonfilesearch.CommonAttributeSearchResults;
|
||||
import org.sleuthkit.autopsy.commonfilesearch.DataSourceLoader;
|
||||
import org.sleuthkit.autopsy.commonfilesearch.CommonAttributeValue;
|
||||
import org.sleuthkit.autopsy.commonfilesearch.CommonAttributeValueList;
|
||||
import org.sleuthkit.autopsy.testutils.CaseUtils;
|
||||
import org.sleuthkit.autopsy.testutils.IngestUtils;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
@@ -49,24 +51,14 @@ import org.sleuthkit.datamodel.TskCoreException;
|
||||
*
|
||||
* Data set definitions:
|
||||
*
|
||||
* set 1
|
||||
* + file1
|
||||
* - IMG_6175.jpg
|
||||
* + file2
|
||||
* - IMG_6175.jpg
|
||||
* + file3
|
||||
* - BasicStyleGuide.doc
|
||||
* set 1 + file1 - IMG_6175.jpg + file2 - IMG_6175.jpg + file3 -
|
||||
* BasicStyleGuide.doc
|
||||
*
|
||||
* set 2
|
||||
* - adsf.pdf
|
||||
* - IMG_6175.jpg
|
||||
* set 2 - adsf.pdf - IMG_6175.jpg
|
||||
*
|
||||
* set 3
|
||||
* - BasicStyleGuide.doc
|
||||
* - IMG_6175.jpg
|
||||
* set 3 - BasicStyleGuide.doc - IMG_6175.jpg
|
||||
*
|
||||
* set 4
|
||||
* - file.dat (empty file)
|
||||
* set 4 - file.dat (empty file)
|
||||
*/
|
||||
class IntraCaseTestUtils {
|
||||
|
||||
@@ -91,13 +83,13 @@ class IntraCaseTestUtils {
|
||||
private final DataSourceLoader dataSourceLoader;
|
||||
|
||||
private final String caseName;
|
||||
|
||||
IntraCaseTestUtils(NbTestCase nbTestCase, String caseName){
|
||||
|
||||
IntraCaseTestUtils(NbTestCase nbTestCase, String caseName) {
|
||||
this.imagePath1 = Paths.get(nbTestCase.getDataDir().toString(), SET1);
|
||||
this.imagePath2 = Paths.get(nbTestCase.getDataDir().toString(), SET2);
|
||||
this.imagePath3 = Paths.get(nbTestCase.getDataDir().toString(), SET3);
|
||||
this.imagePath4 = Paths.get(nbTestCase.getDataDir().toString(), SET4);
|
||||
|
||||
|
||||
this.dataSourceLoader = new DataSourceLoader();
|
||||
|
||||
this.caseName = caseName;
|
||||
@@ -196,27 +188,33 @@ class IntraCaseTestUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* 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<Long, String> mapFileInstancesToDataSources(CommonAttributeSearchResults metadata) {
|
||||
Map<Long, String> instanceIdToDataSource = new HashMap<>();
|
||||
|
||||
for (Map.Entry<Integer, List<CommonAttributeValue>> entry : metadata.getMetadata().entrySet()) {
|
||||
for (CommonAttributeValue md : entry.getValue()) {
|
||||
for (AbstractCommonAttributeInstance fim : md.getInstances()) {
|
||||
instanceIdToDataSource.put(fim.getAbstractFileObjectId(), fim.getDataSource());
|
||||
try {
|
||||
for (Map.Entry<Integer, CommonAttributeValueList> entry : metadata.getMetadata().entrySet()) {
|
||||
entry.getValue().displayDelayedMetadata();
|
||||
for (CommonAttributeValue md : entry.getValue().getMetadataList()) {
|
||||
for (AbstractCommonAttributeInstance fim : md.getInstances()) {
|
||||
instanceIdToDataSource.put(fim.getAbstractFileObjectId(), fim.getDataSource());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return instanceIdToDataSource;
|
||||
return instanceIdToDataSource;
|
||||
} catch (EamDbException ex) {
|
||||
Exceptions.printStackTrace(ex);
|
||||
Assert.fail(ex.getMessage());
|
||||
return instanceIdToDataSource;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static List<AbstractFile> getFiles(Set<Long> objectIds) {
|
||||
List<AbstractFile> files = new ArrayList<>(objectIds.size());
|
||||
|
||||
|
||||
@@ -105,7 +105,7 @@ public class MatchesInAtLeastTwoSourcesIntraCaseTests extends NbTestCase {
|
||||
try {
|
||||
Map<Long, String> dataSources = this.utils.getDataSourceMap();
|
||||
|
||||
AbstractCommonAttributeSearcher allSourcesBuilder = new AllIntraCaseCommonAttributeSearcher(dataSources, false, false);
|
||||
AbstractCommonAttributeSearcher allSourcesBuilder = new AllIntraCaseCommonAttributeSearcher(dataSources, false, false, 0);
|
||||
CommonAttributeSearchResults metadata = allSourcesBuilder.findFiles();
|
||||
|
||||
Map<Long, String> objectIdToDataSource = IntraCaseTestUtils.mapFileInstancesToDataSources(metadata);
|
||||
|
||||
@@ -28,7 +28,6 @@ import org.netbeans.junit.NbTestCase;
|
||||
import org.openide.util.Exceptions;
|
||||
import junit.framework.Assert;
|
||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException;
|
||||
import org.sleuthkit.autopsy.commonfilesearch.AllIntraCaseCommonAttributeSearcher;
|
||||
import org.sleuthkit.autopsy.commonfilesearch.CommonAttributeSearchResults;
|
||||
import org.sleuthkit.autopsy.commonfilesearch.IntraCaseCommonAttributeSearcher;
|
||||
@@ -81,7 +80,7 @@ public class UningestedCasesIntraCaseTests extends NbTestCase {
|
||||
try {
|
||||
Map<Long, String> dataSources = this.utils.getDataSourceMap();
|
||||
|
||||
IntraCaseCommonAttributeSearcher allSourcesBuilder = new AllIntraCaseCommonAttributeSearcher(dataSources, false, false);
|
||||
IntraCaseCommonAttributeSearcher allSourcesBuilder = new AllIntraCaseCommonAttributeSearcher(dataSources, false, false, 0);
|
||||
CommonAttributeSearchResults metadata = allSourcesBuilder.findFiles();
|
||||
|
||||
int resultCount = metadata.size();
|
||||
@@ -101,7 +100,7 @@ public class UningestedCasesIntraCaseTests extends NbTestCase {
|
||||
Map<Long, String> dataSources = this.utils.getDataSourceMap();
|
||||
Long first = getDataSourceIdByName(SET1, dataSources);
|
||||
|
||||
IntraCaseCommonAttributeSearcher singleSourceBuilder = new SingleIntraCaseCommonAttributeSearcher(first, dataSources, false, false);
|
||||
IntraCaseCommonAttributeSearcher singleSourceBuilder = new SingleIntraCaseCommonAttributeSearcher(first, dataSources, false, false, 0);
|
||||
CommonAttributeSearchResults metadata = singleSourceBuilder.findFiles();
|
||||
|
||||
int resultCount = metadata.size();
|
||||
|
||||
@@ -1398,10 +1398,6 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen
|
||||
AutoIngestJob job;
|
||||
if (nodeData.getVersion() == AutoIngestJobNodeData.getCurrentVersion()) {
|
||||
job = new AutoIngestJob(nodeData);
|
||||
Path caseDirectory = PathUtils.findCaseDirectory(rootOutputDirectory, manifest.getCaseName());
|
||||
if (null != caseDirectory) {
|
||||
job.setCaseDirectoryPath(caseDirectory);
|
||||
}
|
||||
} else {
|
||||
job = new AutoIngestJob(manifest);
|
||||
job.setPriority(nodeData.getPriority()); // Retain priority, present in all versions of the node data.
|
||||
@@ -1431,10 +1427,6 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen
|
||||
sysLogger.log(Level.SEVERE, String.format("Error attempting to set node data for %s", manifest.getFilePath()), ex);
|
||||
}
|
||||
}
|
||||
Path caseDirectory = PathUtils.findCaseDirectory(rootOutputDirectory, manifest.getCaseName());
|
||||
if (null != caseDirectory) {
|
||||
job.setCaseDirectoryPath(caseDirectory);
|
||||
}
|
||||
newPendingJobsList.add(job);
|
||||
}
|
||||
|
||||
@@ -1595,54 +1587,53 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
private void addCompletedJob(Manifest manifest, AutoIngestJobNodeData nodeData) throws CoordinationServiceException, InterruptedException, AutoIngestJobException {
|
||||
Path caseDirectoryPath = PathUtils.findCaseDirectory(rootOutputDirectory, manifest.getCaseName());
|
||||
if (null != caseDirectoryPath) {
|
||||
AutoIngestJob job;
|
||||
if (nodeData.getVersion() == AutoIngestJobNodeData.getCurrentVersion()) {
|
||||
job = new AutoIngestJob(nodeData);
|
||||
job.setCaseDirectoryPath(caseDirectoryPath);
|
||||
} else {
|
||||
/**
|
||||
* Use the manifest rather than the node data here to create
|
||||
* a new AutoIngestJob instance because the AutoIngestJob
|
||||
* constructor that takes a node data object expects the
|
||||
* node data to have fields that do not exist in earlier
|
||||
* versions.
|
||||
*/
|
||||
job = new AutoIngestJob(manifest);
|
||||
job.setCaseDirectoryPath(caseDirectoryPath);
|
||||
Path caseDirectoryPath = nodeData.getCaseDirectoryPath();
|
||||
if (!caseDirectoryPath.toFile().exists()) {
|
||||
sysLogger.log(Level.WARNING, String.format("Job completed for %s, but cannot find case directory %s, ignoring job", nodeData.getManifestFilePath(), caseDirectoryPath.toString()));
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the job with the fields that exist in all versions
|
||||
* of the nodeData.
|
||||
*/
|
||||
job.setCompletedDate(nodeData.getCompletedDate());
|
||||
job.setErrorsOccurred(nodeData.getErrorsOccurred());
|
||||
job.setPriority(nodeData.getPriority());
|
||||
job.setNumberOfCrashes(nodeData.getNumberOfCrashes());
|
||||
job.setProcessingStage(AutoIngestJob.Stage.COMPLETED, nodeData.getCompletedDate());
|
||||
job.setProcessingStatus(AutoIngestJob.ProcessingStatus.COMPLETED);
|
||||
AutoIngestJob job;
|
||||
if (nodeData.getVersion() == AutoIngestJobNodeData.getCurrentVersion()) {
|
||||
job = new AutoIngestJob(nodeData);
|
||||
job.setCaseDirectoryPath(caseDirectoryPath);
|
||||
} else {
|
||||
/**
|
||||
* Use the manifest rather than the node data here to create a
|
||||
* new AutoIngestJob instance because the AutoIngestJob
|
||||
* constructor that takes a node data object expects the node
|
||||
* data to have fields that do not exist in earlier versions.
|
||||
*/
|
||||
job = new AutoIngestJob(manifest);
|
||||
job.setCaseDirectoryPath(caseDirectoryPath);
|
||||
|
||||
/*
|
||||
/**
|
||||
* Update the job with the fields that exist in all versions of
|
||||
* the nodeData.
|
||||
*/
|
||||
job.setCompletedDate(nodeData.getCompletedDate());
|
||||
job.setErrorsOccurred(nodeData.getErrorsOccurred());
|
||||
job.setPriority(nodeData.getPriority());
|
||||
job.setNumberOfCrashes(nodeData.getNumberOfCrashes());
|
||||
job.setProcessingStage(AutoIngestJob.Stage.COMPLETED, nodeData.getCompletedDate());
|
||||
job.setProcessingStatus(AutoIngestJob.ProcessingStatus.COMPLETED);
|
||||
|
||||
/*
|
||||
* Try to upgrade/update the coordination service manifest
|
||||
* node data for the job. It is possible that two hosts will
|
||||
* both try to obtain the lock to do the upgrade operation
|
||||
* at the same time. If this happens, the host that is
|
||||
* holding the lock will complete the upgrade operation.
|
||||
*/
|
||||
try (Lock manifestLock = coordinationService.tryGetExclusiveLock(CoordinationService.CategoryNode.MANIFESTS, manifest.getFilePath().toString())) {
|
||||
if (null != manifestLock) {
|
||||
updateCoordinationServiceManifestNode(job);
|
||||
}
|
||||
} catch (CoordinationServiceException ex) {
|
||||
sysLogger.log(Level.SEVERE, String.format("Error attempting to set node data for %s", manifest.getFilePath()), ex);
|
||||
*/
|
||||
try (Lock manifestLock = coordinationService.tryGetExclusiveLock(CoordinationService.CategoryNode.MANIFESTS, manifest.getFilePath().toString())) {
|
||||
if (null != manifestLock) {
|
||||
updateCoordinationServiceManifestNode(job);
|
||||
}
|
||||
} catch (CoordinationServiceException ex) {
|
||||
sysLogger.log(Level.SEVERE, String.format("Error attempting to set node data for %s", manifest.getFilePath()), ex);
|
||||
}
|
||||
newCompletedJobsList.add(job);
|
||||
|
||||
} else {
|
||||
sysLogger.log(Level.WARNING, String.format("Job completed for %s, but cannot find case directory, ignoring job", nodeData.getManifestFilePath()));
|
||||
}
|
||||
newCompletedJobsList.add(job);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2456,6 +2447,7 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen
|
||||
Thread.sleep(AutoIngestUserPreferences.getSecondsToSleepBetweenCases() * 1000);
|
||||
}
|
||||
currentJob.setCaseDirectoryPath(caseDirectoryPath);
|
||||
updateCoordinationServiceManifestNode(currentJob); // update case directory path
|
||||
Case caseForJob = Case.getCurrentCase();
|
||||
sysLogger.log(Level.INFO, "Opened case {0} for {1}", new Object[]{caseForJob.getName(), manifest.getFilePath()});
|
||||
return caseForJob;
|
||||
|
||||
Reference in New Issue
Block a user