mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-17 10:17:41 +00:00
Merge branch '1231-contacts-visualizationpane' into 1232-thumbnail-view
This commit is contained in:
commit
1cfa800e8e
@ -2,7 +2,7 @@ Manifest-Version: 1.0
|
|||||||
OpenIDE-Module: org.sleuthkit.autopsy.core/10
|
OpenIDE-Module: org.sleuthkit.autopsy.core/10
|
||||||
OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/core/Bundle.properties
|
OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/core/Bundle.properties
|
||||||
OpenIDE-Module-Layer: org/sleuthkit/autopsy/core/layer.xml
|
OpenIDE-Module-Layer: org/sleuthkit/autopsy/core/layer.xml
|
||||||
OpenIDE-Module-Implementation-Version: 26
|
OpenIDE-Module-Implementation-Version: 27
|
||||||
OpenIDE-Module-Requires: org.openide.windows.WindowManager
|
OpenIDE-Module-Requires: org.openide.windows.WindowManager
|
||||||
AutoUpdate-Show-In-Client: true
|
AutoUpdate-Show-In-Client: true
|
||||||
AutoUpdate-Essential-Module: true
|
AutoUpdate-Essential-Module: true
|
||||||
|
@ -83,5 +83,5 @@ nbm.homepage=http://www.sleuthkit.org/
|
|||||||
nbm.module.author=Brian Carrier
|
nbm.module.author=Brian Carrier
|
||||||
nbm.needs.restart=true
|
nbm.needs.restart=true
|
||||||
source.reference.curator-recipes-2.8.0.jar=release/modules/ext/curator-recipes-2.8.0-sources.jar
|
source.reference.curator-recipes-2.8.0.jar=release/modules/ext/curator-recipes-2.8.0-sources.jar
|
||||||
spec.version.base=10.14
|
spec.version.base=10.15
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2011-2019 Basis Technology Corp.
|
* Copyright 2016-2019 Basis Technology Corp.
|
||||||
* Contact: carrier <at> sleuthkit <dot> org
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -38,7 +38,7 @@ import org.sleuthkit.datamodel.TskCoreException;
|
|||||||
import org.sleuthkit.datamodel.DataSource;
|
import org.sleuthkit.datamodel.DataSource;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Panel for displaying ingest job history.
|
* Panel for displaying ingest job history for a data source.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||||
public final class IngestJobInfoPanel extends javax.swing.JPanel {
|
public final class IngestJobInfoPanel extends javax.swing.JPanel {
|
||||||
@ -79,11 +79,11 @@ public final class IngestJobInfoPanel extends javax.swing.JPanel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the data source which ingest jobs are being displayed for
|
* Changes the data source for which ingest jobs are being displayed.
|
||||||
*
|
*
|
||||||
* @param selectedDataSource the data source to display ingest jobs for
|
* @param selectedDataSource The data source.
|
||||||
*/
|
*/
|
||||||
public void updateIngestHistoryData(DataSource selectedDataSource) {
|
public void setDataSource(DataSource selectedDataSource) {
|
||||||
this.selectedDataSource = selectedDataSource;
|
this.selectedDataSource = selectedDataSource;
|
||||||
ingestJobsForSelectedDataSource.clear();
|
ingestJobsForSelectedDataSource.clear();
|
||||||
if (selectedDataSource != null) {
|
if (selectedDataSource != null) {
|
||||||
@ -109,7 +109,7 @@ public final class IngestJobInfoPanel extends javax.swing.JPanel {
|
|||||||
try {
|
try {
|
||||||
SleuthkitCase skCase = Case.getCurrentCaseThrows().getSleuthkitCase();
|
SleuthkitCase skCase = Case.getCurrentCaseThrows().getSleuthkitCase();
|
||||||
this.ingestJobs = skCase.getIngestJobs();
|
this.ingestJobs = skCase.getIngestJobs();
|
||||||
updateIngestHistoryData(selectedDataSource);
|
setDataSource(selectedDataSource);
|
||||||
} catch (TskCoreException | NoCurrentCaseException ex) {
|
} catch (TskCoreException | NoCurrentCaseException ex) {
|
||||||
logger.log(Level.SEVERE, "Failed to load ingest jobs.", ex);
|
logger.log(Level.SEVERE, "Failed to load ingest jobs.", ex);
|
||||||
JOptionPane.showMessageDialog(this, Bundle.IngestJobInfoPanel_loadIngestJob_error_text(), Bundle.IngestJobInfoPanel_loadIngestJob_error_title(), JOptionPane.ERROR_MESSAGE);
|
JOptionPane.showMessageDialog(this, Bundle.IngestJobInfoPanel_loadIngestJob_error_text(), Bundle.IngestJobInfoPanel_loadIngestJob_error_title(), JOptionPane.ERROR_MESSAGE);
|
||||||
|
@ -69,7 +69,7 @@ final class DataSourceSummaryDialog extends javax.swing.JDialog implements Obser
|
|||||||
DataSource selectedDataSource = dataSourcesPanel.getSelectedDataSource();
|
DataSource selectedDataSource = dataSourcesPanel.getSelectedDataSource();
|
||||||
countsPanel.updateCountsTableData(selectedDataSource);
|
countsPanel.updateCountsTableData(selectedDataSource);
|
||||||
detailsPanel.updateDetailsPanelData(selectedDataSource);
|
detailsPanel.updateDetailsPanelData(selectedDataSource);
|
||||||
ingestHistoryPanel.updateIngestHistoryData(selectedDataSource);
|
ingestHistoryPanel.setDataSource(selectedDataSource);
|
||||||
this.repaint();
|
this.repaint();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -43,6 +43,8 @@ import org.sleuthkit.autopsy.casemodule.multiusercasesbrowser.MultiUserCaseBrows
|
|||||||
public final class MultiUserCasesBrowserPanel extends javax.swing.JPanel implements ExplorerManager.Provider {
|
public final class MultiUserCasesBrowserPanel extends javax.swing.JPanel implements ExplorerManager.Provider {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
private static final int NAME_COLUMN_INDEX = 0;
|
||||||
|
private static final int NAME_COLUMN_WIDTH = 150;
|
||||||
private final ExplorerManager explorerManager;
|
private final ExplorerManager explorerManager;
|
||||||
private final MultiUserCaseBrowserCustomizer customizer;
|
private final MultiUserCaseBrowserCustomizer customizer;
|
||||||
private final OutlineView outlineView;
|
private final OutlineView outlineView;
|
||||||
@ -103,6 +105,11 @@ public final class MultiUserCasesBrowserPanel extends javax.swing.JPanel impleme
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Give the case name column a greater width.
|
||||||
|
*/
|
||||||
|
outline.getColumnModel().getColumn(NAME_COLUMN_INDEX).setPreferredWidth(NAME_COLUMN_WIDTH);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Hide the root node and configure the node selection mode.
|
* Hide the root node and configure the node selection mode.
|
||||||
*/
|
*/
|
||||||
|
@ -26,13 +26,29 @@ DataContentViewerOtherCases.earliestCaseLabel.text=Central Repository Starting D
|
|||||||
DataContentViewerOtherCases.foundInLabel.text=
|
DataContentViewerOtherCases.foundInLabel.text=
|
||||||
DataContentViewerOtherCases.title=Other Occurrences
|
DataContentViewerOtherCases.title=Other Occurrences
|
||||||
DataContentViewerOtherCases.toolTip=Displays instances of the selected file/artifact from other occurrences.
|
DataContentViewerOtherCases.toolTip=Displays instances of the selected file/artifact from other occurrences.
|
||||||
|
DataContentViewerOtherCasesModel.csvHeader.attribute=Matched Attribute
|
||||||
|
DataContentViewerOtherCasesModel.csvHeader.case=Case
|
||||||
|
DataContentViewerOtherCasesModel.csvHeader.comment=Comment
|
||||||
|
DataContentViewerOtherCasesModel.csvHeader.dataSource=Data Source
|
||||||
|
DataContentViewerOtherCasesModel.csvHeader.device=Device
|
||||||
|
DataContentViewerOtherCasesModel.csvHeader.known=Known
|
||||||
|
DataContentViewerOtherCasesModel.csvHeader.path=Path
|
||||||
|
DataContentViewerOtherCasesModel.csvHeader.value=Attribute Value
|
||||||
|
OccurrencePanel.caseCreatedDateLabel.text=Created Date:
|
||||||
|
OccurrencePanel.caseDetails.text=Case Details
|
||||||
|
OccurrencePanel.caseNameLabel.text=Name:
|
||||||
|
OccurrencePanel.commonProperties.text=Common Properties
|
||||||
|
OccurrencePanel.commonPropertyCommentLabel.text=Comment:
|
||||||
|
OccurrencePanel.commonPropertyKnownStatusLabel.text=Known Status:
|
||||||
|
OccurrencePanel.commonPropertyTypeLabel.text=Type:
|
||||||
|
OccurrencePanel.commonPropertyValueLabel.text=Value:
|
||||||
|
OccurrencePanel.dataSourceDetails.text=Data Source Details
|
||||||
|
OccurrencePanel.dataSourceNameLabel.text=Name:
|
||||||
|
OccurrencePanel.fileDetails.text=File Details
|
||||||
|
OccurrencePanel.filePathLabel.text=File Path:
|
||||||
OtherOccurrencesCasesTableModel.case=Case
|
OtherOccurrencesCasesTableModel.case=Case
|
||||||
OtherOccurrencesCasesTableModel.noData=No Data.
|
OtherOccurrencesCasesTableModel.noData=No Data.
|
||||||
OtherOccurrencesFilesTableModel.attribute=Matched Attribute
|
OtherOccurrencesDataSourcesTableModel.dataSourceName=Data Source Name
|
||||||
OtherOccurrencesFilesTableModel.comment=Comment
|
OtherOccurrencesDataSourcesTableModel.noData=No Data.
|
||||||
OtherOccurrencesFilesTableModel.dataSource=Data Source
|
OtherOccurrencesFilesTableModel.fileName=File Name
|
||||||
OtherOccurrencesFilesTableModel.device=Device
|
|
||||||
OtherOccurrencesFilesTableModel.known=Known
|
|
||||||
OtherOccurrencesFilesTableModel.noData=No Data.
|
OtherOccurrencesFilesTableModel.noData=No Data.
|
||||||
OtherOccurrencesFilesTableModel.path=Path
|
|
||||||
OtherOccurrencesFilesTableModel.value=Attribute Value
|
|
||||||
|
@ -46,11 +46,11 @@
|
|||||||
</NonVisualComponents>
|
</NonVisualComponents>
|
||||||
<Properties>
|
<Properties>
|
||||||
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
<Dimension value="[1500, 10]"/>
|
<Dimension value="[600, 10]"/>
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="opaque" type="boolean" value="false"/>
|
<Property name="opaque" type="boolean" value="false"/>
|
||||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
<Dimension value="[1500, 44]"/>
|
<Dimension value="[600, 63]"/>
|
||||||
</Property>
|
</Property>
|
||||||
</Properties>
|
</Properties>
|
||||||
<AuxValues>
|
<AuxValues>
|
||||||
@ -68,123 +68,114 @@
|
|||||||
<Layout>
|
<Layout>
|
||||||
<DimensionLayout dim="0">
|
<DimensionLayout dim="0">
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
<Component id="otherCasesPanel" alignment="0" pref="1500" max="32767" attributes="0"/>
|
<Component id="tableContainerPanel" alignment="0" max="32767" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
</DimensionLayout>
|
</DimensionLayout>
|
||||||
<DimensionLayout dim="1">
|
<DimensionLayout dim="1">
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
<Component id="otherCasesPanel" max="32767" attributes="0"/>
|
<Group type="102" alignment="0" attributes="0">
|
||||||
|
<Component id="tableContainerPanel" pref="64" max="32767" attributes="0"/>
|
||||||
|
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
|
||||||
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
</DimensionLayout>
|
</DimensionLayout>
|
||||||
</Layout>
|
</Layout>
|
||||||
<SubComponents>
|
<SubComponents>
|
||||||
<Container class="javax.swing.JPanel" name="otherCasesPanel">
|
<Container class="javax.swing.JPanel" name="tableContainerPanel">
|
||||||
<Properties>
|
<Properties>
|
||||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
<Dimension value="[921, 62]"/>
|
<Dimension value="[600, 63]"/>
|
||||||
</Property>
|
</Property>
|
||||||
|
<Property name="requestFocusEnabled" type="boolean" value="false"/>
|
||||||
</Properties>
|
</Properties>
|
||||||
|
|
||||||
<Layout>
|
<Layout>
|
||||||
<DimensionLayout dim="0">
|
<DimensionLayout dim="0">
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
<EmptySpace min="0" pref="921" max="32767" attributes="0"/>
|
<Group type="102" attributes="0">
|
||||||
<Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
<Group type="102" alignment="0" attributes="0">
|
<Group type="102" attributes="0">
|
||||||
<Component id="tableContainerPanel" max="32767" attributes="0"/>
|
<Component id="earliestCaseLabel" min="-2" pref="161" max="-2" attributes="0"/>
|
||||||
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
|
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||||
|
<Component id="earliestCaseDate" max="32767" attributes="0"/>
|
||||||
|
<EmptySpace max="32767" attributes="0"/>
|
||||||
|
<Component id="foundInLabel" max="32767" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
<Component id="tablesViewerSplitPane" pref="590" max="32767" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
|
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
</DimensionLayout>
|
</DimensionLayout>
|
||||||
<DimensionLayout dim="1">
|
<DimensionLayout dim="1">
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
<EmptySpace min="0" pref="62" max="32767" attributes="0"/>
|
<Group type="102" attributes="0">
|
||||||
<Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
|
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
|
||||||
<Group type="102" alignment="0" attributes="0">
|
<Component id="tablesViewerSplitPane" pref="33" max="32767" attributes="0"/>
|
||||||
<Component id="tableContainerPanel" pref="62" max="32767" attributes="0"/>
|
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||||
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
|
<Group type="103" groupAlignment="1" attributes="0">
|
||||||
|
<Group type="103" groupAlignment="3" attributes="0">
|
||||||
|
<Component id="earliestCaseLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||||
|
<Component id="earliestCaseDate" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
<Component id="foundInLabel" min="-2" pref="14" max="-2" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
|
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
</DimensionLayout>
|
</DimensionLayout>
|
||||||
</Layout>
|
</Layout>
|
||||||
<SubComponents>
|
<SubComponents>
|
||||||
<Container class="javax.swing.JPanel" name="tableContainerPanel">
|
<Component class="javax.swing.JLabel" name="earliestCaseLabel">
|
||||||
<Properties>
|
<Properties>
|
||||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
<Dimension value="[1500, 63]"/>
|
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/contentviewer/Bundle.properties" key="DataContentViewerOtherCases.earliestCaseLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/contentviewer/Bundle.properties" key="DataContentViewerOtherCases.earliestCaseLabel.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
</Property>
|
</Property>
|
||||||
</Properties>
|
</Properties>
|
||||||
|
</Component>
|
||||||
|
<Component class="javax.swing.JLabel" name="earliestCaseDate">
|
||||||
|
<Properties>
|
||||||
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/contentviewer/Bundle.properties" key="DataContentViewerOtherCases.earliestCaseDate.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
</Component>
|
||||||
|
<Component class="javax.swing.JLabel" name="foundInLabel">
|
||||||
|
<Properties>
|
||||||
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/contentviewer/Bundle.properties" key="DataContentViewerOtherCases.foundInLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
</Component>
|
||||||
|
<Container class="javax.swing.JSplitPane" name="tablesViewerSplitPane">
|
||||||
|
<Properties>
|
||||||
|
<Property name="dividerLocation" type="int" value="450"/>
|
||||||
|
<Property name="resizeWeight" type="double" value="0.5"/>
|
||||||
|
</Properties>
|
||||||
|
|
||||||
<Layout>
|
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout"/>
|
||||||
<DimensionLayout dim="0">
|
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
|
||||||
<Group type="102" attributes="0">
|
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
|
||||||
<Group type="102" attributes="0">
|
|
||||||
<Component id="earliestCaseLabel" min="-2" max="-2" attributes="0"/>
|
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
|
||||||
<Component id="earliestCaseDate" min="-2" max="-2" attributes="0"/>
|
|
||||||
<EmptySpace min="-2" pref="66" max="-2" attributes="0"/>
|
|
||||||
<Component id="foundInLabel" min="-2" max="-2" attributes="0"/>
|
|
||||||
</Group>
|
|
||||||
<Component id="jSplitPane2" alignment="0" pref="911" max="32767" attributes="0"/>
|
|
||||||
</Group>
|
|
||||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
|
||||||
</Group>
|
|
||||||
</Group>
|
|
||||||
</DimensionLayout>
|
|
||||||
<DimensionLayout dim="1">
|
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
|
||||||
<Group type="102" alignment="1" attributes="0">
|
|
||||||
<Component id="jSplitPane2" pref="31" max="32767" attributes="0"/>
|
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
|
||||||
<Group type="103" groupAlignment="3" attributes="0">
|
|
||||||
<Component id="earliestCaseLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
|
||||||
<Component id="earliestCaseDate" alignment="3" min="-2" max="-2" attributes="0"/>
|
|
||||||
<Component id="foundInLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
|
||||||
</Group>
|
|
||||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
|
||||||
</Group>
|
|
||||||
</Group>
|
|
||||||
</DimensionLayout>
|
|
||||||
</Layout>
|
|
||||||
<SubComponents>
|
<SubComponents>
|
||||||
<Component class="javax.swing.JLabel" name="earliestCaseLabel">
|
<Container class="javax.swing.JSplitPane" name="caseDatasourceFileSplitPane">
|
||||||
<Properties>
|
<Properties>
|
||||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
<Property name="dividerLocation" type="int" value="300"/>
|
||||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/contentviewer/Bundle.properties" key="DataContentViewerOtherCases.earliestCaseLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
<Property name="resizeWeight" type="double" value="0.6"/>
|
||||||
</Property>
|
<Property name="toolTipText" type="java.lang.String" value=""/>
|
||||||
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
|
||||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/contentviewer/Bundle.properties" key="DataContentViewerOtherCases.earliestCaseLabel.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
|
||||||
</Property>
|
|
||||||
</Properties>
|
|
||||||
</Component>
|
|
||||||
<Component class="javax.swing.JLabel" name="earliestCaseDate">
|
|
||||||
<Properties>
|
|
||||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
|
||||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/contentviewer/Bundle.properties" key="DataContentViewerOtherCases.earliestCaseDate.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
|
||||||
</Property>
|
|
||||||
</Properties>
|
|
||||||
</Component>
|
|
||||||
<Component class="javax.swing.JLabel" name="foundInLabel">
|
|
||||||
<Properties>
|
|
||||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
|
||||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/contentviewer/Bundle.properties" key="DataContentViewerOtherCases.foundInLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
|
||||||
</Property>
|
|
||||||
</Properties>
|
|
||||||
</Component>
|
|
||||||
<Container class="javax.swing.JSplitPane" name="jSplitPane2">
|
|
||||||
<Properties>
|
|
||||||
<Property name="dividerLocation" type="int" value="470"/>
|
|
||||||
</Properties>
|
</Properties>
|
||||||
|
<Constraints>
|
||||||
|
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
|
||||||
|
<JSplitPaneConstraints position="left"/>
|
||||||
|
</Constraint>
|
||||||
|
</Constraints>
|
||||||
|
|
||||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout"/>
|
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout"/>
|
||||||
<SubComponents>
|
<SubComponents>
|
||||||
<Container class="javax.swing.JSplitPane" name="jSplitPane3">
|
<Container class="javax.swing.JSplitPane" name="caseDatasourceSplitPane">
|
||||||
<Properties>
|
<Properties>
|
||||||
<Property name="dividerLocation" type="int" value="150"/>
|
<Property name="dividerLocation" type="int" value="150"/>
|
||||||
|
<Property name="resizeWeight" type="double" value="0.5"/>
|
||||||
</Properties>
|
</Properties>
|
||||||
<Constraints>
|
<Constraints>
|
||||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
|
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
|
||||||
@ -195,6 +186,11 @@
|
|||||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout"/>
|
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout"/>
|
||||||
<SubComponents>
|
<SubComponents>
|
||||||
<Container class="javax.swing.JScrollPane" name="caseScrollPane">
|
<Container class="javax.swing.JScrollPane" name="caseScrollPane">
|
||||||
|
<Properties>
|
||||||
|
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[140, 30]"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
<AuxValues>
|
<AuxValues>
|
||||||
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
|
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
|
||||||
</AuxValues>
|
</AuxValues>
|
||||||
@ -217,6 +213,11 @@
|
|||||||
</SubComponents>
|
</SubComponents>
|
||||||
</Container>
|
</Container>
|
||||||
<Container class="javax.swing.JScrollPane" name="dataSourceScrollPane">
|
<Container class="javax.swing.JScrollPane" name="dataSourceScrollPane">
|
||||||
|
<Properties>
|
||||||
|
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[140, 30]"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
<AuxValues>
|
<AuxValues>
|
||||||
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
|
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
|
||||||
</AuxValues>
|
</AuxValues>
|
||||||
@ -231,11 +232,8 @@
|
|||||||
<Component class="javax.swing.JTable" name="dataSourcesTable">
|
<Component class="javax.swing.JTable" name="dataSourcesTable">
|
||||||
<Properties>
|
<Properties>
|
||||||
<Property name="autoCreateRowSorter" type="boolean" value="true"/>
|
<Property name="autoCreateRowSorter" type="boolean" value="true"/>
|
||||||
<Property name="model" type="javax.swing.table.TableModel" editor="org.netbeans.modules.form.editors2.TableModelEditor">
|
<Property name="model" type="javax.swing.table.TableModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
|
||||||
<Table columnCount="2" rowCount="0">
|
<Connection code="dataSourcesTableModel" type="code"/>
|
||||||
<Column editable="false" title="Data Source Name" type="java.lang.Object"/>
|
|
||||||
<Column editable="false" title="Device ID" type="java.lang.Object"/>
|
|
||||||
</Table>
|
|
||||||
</Property>
|
</Property>
|
||||||
</Properties>
|
</Properties>
|
||||||
</Component>
|
</Component>
|
||||||
@ -243,10 +241,10 @@
|
|||||||
</Container>
|
</Container>
|
||||||
</SubComponents>
|
</SubComponents>
|
||||||
</Container>
|
</Container>
|
||||||
<Container class="javax.swing.JScrollPane" name="propertiesTableScrollPane">
|
<Container class="javax.swing.JScrollPane" name="filesTableScrollPane">
|
||||||
<Properties>
|
<Properties>
|
||||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
<Dimension value="[1000, 30]"/>
|
<Dimension value="[140, 30]"/>
|
||||||
</Property>
|
</Property>
|
||||||
</Properties>
|
</Properties>
|
||||||
<Constraints>
|
<Constraints>
|
||||||
@ -261,7 +259,7 @@
|
|||||||
<Properties>
|
<Properties>
|
||||||
<Property name="autoCreateRowSorter" type="boolean" value="true"/>
|
<Property name="autoCreateRowSorter" type="boolean" value="true"/>
|
||||||
<Property name="model" type="javax.swing.table.TableModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
|
<Property name="model" type="javax.swing.table.TableModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
|
||||||
<Connection code="tableModel" type="code"/>
|
<Connection code="filesTableModel" type="code"/>
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/contentviewer/Bundle.properties" key="DataContentViewerOtherCases.table.toolTip.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/contentviewer/Bundle.properties" key="DataContentViewerOtherCases.table.toolTip.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
@ -273,7 +271,7 @@
|
|||||||
<ComponentRef name="rightClickPopupMenu"/>
|
<ComponentRef name="rightClickPopupMenu"/>
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="selectionModel" type="javax.swing.ListSelectionModel" editor="org.netbeans.modules.form.editors2.JTableSelectionModelEditor">
|
<Property name="selectionModel" type="javax.swing.ListSelectionModel" editor="org.netbeans.modules.form.editors2.JTableSelectionModelEditor">
|
||||||
<JTableSelectionModel selectionMode="1"/>
|
<JTableSelectionModel selectionMode="0"/>
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="tableHeader" type="javax.swing.table.JTableHeader" editor="org.netbeans.modules.form.editors2.JTableHeaderEditor">
|
<Property name="tableHeader" type="javax.swing.table.JTableHeader" editor="org.netbeans.modules.form.editors2.JTableHeaderEditor">
|
||||||
<TableHeader reorderingAllowed="true" resizingAllowed="true"/>
|
<TableHeader reorderingAllowed="true" resizingAllowed="true"/>
|
||||||
@ -284,6 +282,21 @@
|
|||||||
</Container>
|
</Container>
|
||||||
</SubComponents>
|
</SubComponents>
|
||||||
</Container>
|
</Container>
|
||||||
|
<Container class="javax.swing.JScrollPane" name="detailsPanelScrollPane">
|
||||||
|
<Properties>
|
||||||
|
<Property name="horizontalScrollBarPolicy" type="int" value="31"/>
|
||||||
|
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[200, 100]"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
<Constraints>
|
||||||
|
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
|
||||||
|
<JSplitPaneConstraints position="right"/>
|
||||||
|
</Constraint>
|
||||||
|
</Constraints>
|
||||||
|
|
||||||
|
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
||||||
|
</Container>
|
||||||
</SubComponents>
|
</SubComponents>
|
||||||
</Container>
|
</Container>
|
||||||
</SubComponents>
|
</SubComponents>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Central Repository
|
* Central Repository
|
||||||
*
|
*
|
||||||
* Copyright 2015-2019 Basis Technology Corp.
|
* Copyright 2017-2019 Basis Technology Corp.
|
||||||
* Contact: carrier <at> sleuthkit <dot> org
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -21,6 +21,8 @@ package org.sleuthkit.autopsy.centralrepository.contentviewer;
|
|||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
|
import java.awt.event.ComponentAdapter;
|
||||||
|
import java.awt.event.ComponentEvent;
|
||||||
import java.io.BufferedWriter;
|
import java.io.BufferedWriter;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -48,9 +50,6 @@ import static javax.swing.JOptionPane.PLAIN_MESSAGE;
|
|||||||
import static javax.swing.JOptionPane.ERROR_MESSAGE;
|
import static javax.swing.JOptionPane.ERROR_MESSAGE;
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
import javax.swing.filechooser.FileNameExtensionFilter;
|
import javax.swing.filechooser.FileNameExtensionFilter;
|
||||||
import javax.swing.table.DefaultTableModel;
|
|
||||||
import javax.swing.table.TableCellRenderer;
|
|
||||||
import javax.swing.table.TableColumn;
|
|
||||||
import javax.swing.table.TableModel;
|
import javax.swing.table.TableModel;
|
||||||
import javax.swing.table.TableRowSorter;
|
import javax.swing.table.TableRowSorter;
|
||||||
import org.joda.time.DateTimeZone;
|
import org.joda.time.DateTimeZone;
|
||||||
@ -94,49 +93,57 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
private static final Logger LOGGER = Logger.getLogger(DataContentViewerOtherCases.class.getName());
|
private static final Logger LOGGER = Logger.getLogger(DataContentViewerOtherCases.class.getName());
|
||||||
private static final CorrelationCaseWrapper NO_ARTIFACTS_CASE = new CorrelationCaseWrapper(Bundle.DataContentViewerOtherCases_table_noArtifacts());
|
private static final CorrelationCaseWrapper NO_ARTIFACTS_CASE = new CorrelationCaseWrapper(Bundle.DataContentViewerOtherCases_table_noArtifacts());
|
||||||
private static final CorrelationCaseWrapper NO_RESULTS_CASE = new CorrelationCaseWrapper(Bundle.DataContentViewerOtherCases_table_noResultsFound());
|
private static final CorrelationCaseWrapper NO_RESULTS_CASE = new CorrelationCaseWrapper(Bundle.DataContentViewerOtherCases_table_noResultsFound());
|
||||||
private static final int DEFAULT_MIN_CELL_WIDTH = 15;
|
|
||||||
|
|
||||||
private final OtherOccurrencesFilesTableModel tableModel;
|
private final OtherOccurrencesFilesTableModel filesTableModel;
|
||||||
private final OtherOccurrencesCasesTableModel casesTableModel;
|
private final OtherOccurrencesCasesTableModel casesTableModel;
|
||||||
|
private final OtherOccurrencesDataSourcesTableModel dataSourcesTableModel;
|
||||||
|
private OccurrencePanel occurrencePanel;
|
||||||
private final Collection<CorrelationAttributeInstance> correlationAttributes;
|
private final Collection<CorrelationAttributeInstance> correlationAttributes;
|
||||||
private String dataSourceName = "";
|
private String dataSourceName = ""; //the data source of the file which the content viewer is being populated for
|
||||||
private String deviceId = "";
|
private String deviceId = ""; //the device id of the data source for the file which the content viewer is being populated for
|
||||||
/**
|
/**
|
||||||
* Could be null.
|
* Could be null.
|
||||||
*/
|
*/
|
||||||
private AbstractFile file;
|
private AbstractFile file; //the file which the content viewer is being populated for
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates new form DataContentViewerOtherCases
|
* Creates new form DataContentViewerOtherCases
|
||||||
*/
|
*/
|
||||||
public DataContentViewerOtherCases() {
|
public DataContentViewerOtherCases() {
|
||||||
this.tableModel = new OtherOccurrencesFilesTableModel();
|
this.filesTableModel = new OtherOccurrencesFilesTableModel();
|
||||||
this.casesTableModel = new OtherOccurrencesCasesTableModel();
|
this.casesTableModel = new OtherOccurrencesCasesTableModel();
|
||||||
|
this.dataSourcesTableModel = new OtherOccurrencesDataSourcesTableModel();
|
||||||
this.correlationAttributes = new ArrayList<>();
|
this.correlationAttributes = new ArrayList<>();
|
||||||
|
occurrencePanel = new OccurrencePanel();
|
||||||
initComponents();
|
initComponents();
|
||||||
customizeComponents();
|
customizeComponents();
|
||||||
|
|
||||||
|
detailsPanelScrollPane.addComponentListener(new ComponentAdapter() {
|
||||||
|
@Override
|
||||||
|
public void componentResized(ComponentEvent componentEvent) {
|
||||||
|
//when its resized make sure the width of the panel resizes to match the scroll pane width to avoid a horizontal scroll bar
|
||||||
|
occurrencePanel.setPreferredSize(new java.awt.Dimension(detailsPanelScrollPane.getPreferredSize().width, occurrencePanel.getPreferredSize().height));
|
||||||
|
detailsPanelScrollPane.setViewportView(occurrencePanel);
|
||||||
|
}
|
||||||
|
});
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void customizeComponents() {
|
private void customizeComponents() {
|
||||||
ActionListener actList = new ActionListener() {
|
ActionListener actList = (ActionEvent e) -> {
|
||||||
@Override
|
JMenuItem jmi = (JMenuItem) e.getSource();
|
||||||
public void actionPerformed(ActionEvent e) {
|
if (jmi.equals(selectAllMenuItem)) {
|
||||||
JMenuItem jmi = (JMenuItem) e.getSource();
|
filesTable.selectAll();
|
||||||
if (jmi.equals(selectAllMenuItem)) {
|
} else if (jmi.equals(showCaseDetailsMenuItem)) {
|
||||||
filesTable.selectAll();
|
showCaseDetails(filesTable.getSelectedRow());
|
||||||
} else if (jmi.equals(showCaseDetailsMenuItem)) {
|
} else if (jmi.equals(exportToCSVMenuItem)) {
|
||||||
showCaseDetails(filesTable.getSelectedRow());
|
try {
|
||||||
} else if (jmi.equals(exportToCSVMenuItem)) {
|
saveToCSV();
|
||||||
try {
|
} catch (NoCurrentCaseException ex) {
|
||||||
saveToCSV();
|
LOGGER.log(Level.SEVERE, "Exception while getting open case.", ex); // NON-NLS
|
||||||
} catch (NoCurrentCaseException ex) {
|
|
||||||
LOGGER.log(Level.SEVERE, "Exception while getting open case.", ex); // NON-NLS
|
|
||||||
}
|
|
||||||
} else if (jmi.equals(showCommonalityMenuItem)) {
|
|
||||||
showCommonalityDetails();
|
|
||||||
}
|
}
|
||||||
|
} else if (jmi.equals(showCommonalityMenuItem)) {
|
||||||
|
showCommonalityDetails();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -145,10 +152,6 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
showCaseDetailsMenuItem.addActionListener(actList);
|
showCaseDetailsMenuItem.addActionListener(actList);
|
||||||
showCommonalityMenuItem.addActionListener(actList);
|
showCommonalityMenuItem.addActionListener(actList);
|
||||||
|
|
||||||
// Set background of every nth row as light grey.
|
|
||||||
TableCellRenderer renderer = new OtherOccurrencesFilesTableCellRenderer();
|
|
||||||
filesTable.setDefaultRenderer(Object.class, renderer);
|
|
||||||
|
|
||||||
// Configure column sorting.
|
// Configure column sorting.
|
||||||
TableRowSorter<TableModel> sorter = new TableRowSorter<>(filesTable.getModel());
|
TableRowSorter<TableModel> sorter = new TableRowSorter<>(filesTable.getModel());
|
||||||
filesTable.setRowSorter(sorter);
|
filesTable.setRowSorter(sorter);
|
||||||
@ -162,8 +165,18 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
updateOnDataSourceSelection();
|
updateOnDataSourceSelection();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//alows resizing of the 4th section
|
||||||
|
filesTable.getSelectionModel().addListSelectionListener((e) -> {
|
||||||
|
if (Case.isCaseOpen()) {
|
||||||
|
occurrencePanel = new OccurrencePanel();
|
||||||
|
updateOnFileSelection();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
//sort tables alphabetically initially
|
||||||
casesTable.getRowSorter().toggleSortOrder(0);
|
casesTable.getRowSorter().toggleSortOrder(0);
|
||||||
dataSourcesTable.getRowSorter().toggleSortOrder(0);
|
dataSourcesTable.getRowSorter().toggleSortOrder(0);
|
||||||
|
filesTable.getRowSorter().toggleSortOrder(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Messages({"DataContentViewerOtherCases.correlatedArtifacts.isEmpty=There are no files or artifacts to correlate.",
|
@Messages({"DataContentViewerOtherCases.correlatedArtifacts.isEmpty=There are no files or artifacts to correlate.",
|
||||||
@ -218,54 +231,43 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
"DataContentViewerOtherCases.caseDetailsDialog.noCaseNameError=Error",
|
"DataContentViewerOtherCases.caseDetailsDialog.noCaseNameError=Error",
|
||||||
"DataContentViewerOtherCases.noOpenCase.errMsg=No open case available."})
|
"DataContentViewerOtherCases.noOpenCase.errMsg=No open case available."})
|
||||||
private void showCaseDetails(int selectedRowViewIdx) {
|
private void showCaseDetails(int selectedRowViewIdx) {
|
||||||
|
|
||||||
String caseDisplayName = Bundle.DataContentViewerOtherCases_caseDetailsDialog_noCaseNameError();
|
String caseDisplayName = Bundle.DataContentViewerOtherCases_caseDetailsDialog_noCaseNameError();
|
||||||
|
String details = Bundle.DataContentViewerOtherCases_caseDetailsDialog_noDetails();
|
||||||
try {
|
try {
|
||||||
if (-1 != selectedRowViewIdx) {
|
if (-1 != selectedRowViewIdx) {
|
||||||
EamDb dbManager = EamDb.getInstance();
|
EamDb dbManager = EamDb.getInstance();
|
||||||
int selectedRowModelIdx = filesTable.convertRowIndexToModel(selectedRowViewIdx);
|
int selectedRowModelIdx = filesTable.convertRowIndexToModel(selectedRowViewIdx);
|
||||||
OtherOccurrenceNodeInstanceData nodeData = (OtherOccurrenceNodeInstanceData) tableModel.getRow(selectedRowModelIdx);
|
List<OtherOccurrenceNodeData> rowList = filesTableModel.getListOfNodesForFile(selectedRowModelIdx);
|
||||||
CorrelationCase eamCasePartial = nodeData.getCorrelationAttributeInstance().getCorrelationCase();
|
if (!rowList.isEmpty()) {
|
||||||
if (eamCasePartial == null) {
|
if (rowList.get(0) instanceof OtherOccurrenceNodeInstanceData) {
|
||||||
JOptionPane.showConfirmDialog(showCaseDetailsMenuItem,
|
CorrelationCase eamCasePartial = ((OtherOccurrenceNodeInstanceData) rowList.get(0)).getCorrelationAttributeInstance().getCorrelationCase();
|
||||||
Bundle.DataContentViewerOtherCases_caseDetailsDialog_noDetailsReference(),
|
caseDisplayName = eamCasePartial.getDisplayName();
|
||||||
caseDisplayName,
|
// query case details
|
||||||
DEFAULT_OPTION, PLAIN_MESSAGE);
|
CorrelationCase eamCase = dbManager.getCaseByUUID(eamCasePartial.getCaseUUID());
|
||||||
return;
|
if (eamCase != null) {
|
||||||
|
details = eamCase.getCaseDetailsOptionsPaneDialog();
|
||||||
|
} else {
|
||||||
|
details = Bundle.DataContentViewerOtherCases_caseDetailsDialog_noDetails();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
details = Bundle.DataContentViewerOtherCases_caseDetailsDialog_notSelected();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
details = Bundle.DataContentViewerOtherCases_caseDetailsDialog_noDetailsReference();
|
||||||
}
|
}
|
||||||
caseDisplayName = eamCasePartial.getDisplayName();
|
|
||||||
// query case details
|
|
||||||
CorrelationCase eamCase = dbManager.getCaseByUUID(eamCasePartial.getCaseUUID());
|
|
||||||
if (eamCase == null) {
|
|
||||||
JOptionPane.showConfirmDialog(showCaseDetailsMenuItem,
|
|
||||||
Bundle.DataContentViewerOtherCases_caseDetailsDialog_noDetails(),
|
|
||||||
caseDisplayName,
|
|
||||||
DEFAULT_OPTION, PLAIN_MESSAGE);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// display case details
|
|
||||||
JOptionPane.showConfirmDialog(showCaseDetailsMenuItem,
|
|
||||||
eamCase.getCaseDetailsOptionsPaneDialog(),
|
|
||||||
caseDisplayName,
|
|
||||||
DEFAULT_OPTION, PLAIN_MESSAGE);
|
|
||||||
} else {
|
|
||||||
JOptionPane.showConfirmDialog(showCaseDetailsMenuItem,
|
|
||||||
Bundle.DataContentViewerOtherCases_caseDetailsDialog_notSelected(),
|
|
||||||
caseDisplayName,
|
|
||||||
DEFAULT_OPTION, PLAIN_MESSAGE);
|
|
||||||
}
|
}
|
||||||
} catch (EamDbException ex) {
|
} catch (EamDbException ex) {
|
||||||
LOGGER.log(Level.SEVERE, "Error loading case details", ex);
|
LOGGER.log(Level.SEVERE, "Error loading case details", ex);
|
||||||
|
} finally {
|
||||||
JOptionPane.showConfirmDialog(showCaseDetailsMenuItem,
|
JOptionPane.showConfirmDialog(showCaseDetailsMenuItem,
|
||||||
Bundle.DataContentViewerOtherCases_caseDetailsDialog_noDetails(),
|
details,
|
||||||
caseDisplayName,
|
caseDisplayName,
|
||||||
DEFAULT_OPTION, PLAIN_MESSAGE);
|
DEFAULT_OPTION, PLAIN_MESSAGE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void saveToCSV() throws NoCurrentCaseException {
|
private void saveToCSV() throws NoCurrentCaseException {
|
||||||
if (0 != filesTable.getSelectedRowCount()) {
|
if (casesTableModel.getRowCount() > 0) {
|
||||||
Calendar now = Calendar.getInstance();
|
Calendar now = Calendar.getInstance();
|
||||||
String fileName = String.format("%1$tY%1$tm%1$te%1$tI%1$tM%1$tS_other_data_sources.csv", now);
|
String fileName = String.format("%1$tY%1$tm%1$te%1$tI%1$tM%1$tS_other_data_sources.csv", now);
|
||||||
CSVFileChooser.setCurrentDirectory(new File(Case.getCurrentCaseThrows().getExportDirectory()));
|
CSVFileChooser.setCurrentDirectory(new File(Case.getCurrentCaseThrows().getExportDirectory()));
|
||||||
@ -279,45 +281,46 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
if (!selectedFile.getName().endsWith(".csv")) { // NON-NLS
|
if (!selectedFile.getName().endsWith(".csv")) { // NON-NLS
|
||||||
selectedFile = new File(selectedFile.toString() + ".csv"); // NON-NLS
|
selectedFile = new File(selectedFile.toString() + ".csv"); // NON-NLS
|
||||||
}
|
}
|
||||||
|
writeOtherOccurrencesToFileAsCSV(selectedFile);
|
||||||
writeSelectedRowsToFileAsCSV(selectedFile);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeSelectedRowsToFileAsCSV(File destFile) {
|
@Messages({
|
||||||
StringBuilder content;
|
"DataContentViewerOtherCasesModel.csvHeader.case=Case",
|
||||||
int[] selectedRowViewIndices = filesTable.getSelectedRows();
|
"DataContentViewerOtherCasesModel.csvHeader.device=Device",
|
||||||
int colCount = tableModel.getColumnCount();
|
"DataContentViewerOtherCasesModel.csvHeader.dataSource=Data Source",
|
||||||
|
"DataContentViewerOtherCasesModel.csvHeader.attribute=Matched Attribute",
|
||||||
|
"DataContentViewerOtherCasesModel.csvHeader.value=Attribute Value",
|
||||||
|
"DataContentViewerOtherCasesModel.csvHeader.known=Known",
|
||||||
|
"DataContentViewerOtherCasesModel.csvHeader.path=Path",
|
||||||
|
"DataContentViewerOtherCasesModel.csvHeader.comment=Comment"
|
||||||
|
})
|
||||||
|
/**
|
||||||
|
* Write data for all cases in the content viewer to a CSV file
|
||||||
|
*/
|
||||||
|
private void writeOtherOccurrencesToFileAsCSV(File destFile) {
|
||||||
try (BufferedWriter writer = Files.newBufferedWriter(destFile.toPath())) {
|
try (BufferedWriter writer = Files.newBufferedWriter(destFile.toPath())) {
|
||||||
|
//write headers
|
||||||
// write column names
|
StringBuilder headers = new StringBuilder("\"");
|
||||||
content = new StringBuilder("");
|
headers.append(Bundle.DataContentViewerOtherCasesModel_csvHeader_case())
|
||||||
for (int colIdx = 0; colIdx < colCount; colIdx++) {
|
.append(OtherOccurrenceNodeInstanceData.getCsvItemSeparator()).append(Bundle.DataContentViewerOtherCasesModel_csvHeader_dataSource())
|
||||||
content.append('"').append(tableModel.getColumnName(colIdx)).append('"');
|
.append(OtherOccurrenceNodeInstanceData.getCsvItemSeparator()).append(Bundle.DataContentViewerOtherCasesModel_csvHeader_attribute())
|
||||||
if (colIdx < (colCount - 1)) {
|
.append(OtherOccurrenceNodeInstanceData.getCsvItemSeparator()).append(Bundle.DataContentViewerOtherCasesModel_csvHeader_value())
|
||||||
content.append(",");
|
.append(OtherOccurrenceNodeInstanceData.getCsvItemSeparator()).append(Bundle.DataContentViewerOtherCasesModel_csvHeader_known())
|
||||||
|
.append(OtherOccurrenceNodeInstanceData.getCsvItemSeparator()).append(Bundle.DataContentViewerOtherCasesModel_csvHeader_path())
|
||||||
|
.append(OtherOccurrenceNodeInstanceData.getCsvItemSeparator()).append(Bundle.DataContentViewerOtherCasesModel_csvHeader_comment())
|
||||||
|
.append('"').append(System.getProperty("line.separator"));
|
||||||
|
writer.write(headers.toString());
|
||||||
|
//write content
|
||||||
|
for (CorrelationAttributeInstance corAttr : correlationAttributes) {
|
||||||
|
Map<UniquePathKey, OtherOccurrenceNodeInstanceData> correlatedNodeDataMap = new HashMap<>(0);
|
||||||
|
// get correlation and reference set instances from DB
|
||||||
|
correlatedNodeDataMap.putAll(getCorrelatedInstances(corAttr, dataSourceName, deviceId));
|
||||||
|
for (OtherOccurrenceNodeInstanceData nodeData : correlatedNodeDataMap.values()) {
|
||||||
|
writer.write(nodeData.toCsvString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
content.append(System.getProperty("line.separator"));
|
|
||||||
writer.write(content.toString());
|
|
||||||
|
|
||||||
// write rows
|
|
||||||
for (int rowViewIdx : selectedRowViewIndices) {
|
|
||||||
content = new StringBuilder("");
|
|
||||||
for (int colIdx = 0; colIdx < colCount; colIdx++) {
|
|
||||||
int rowModelIdx = filesTable.convertRowIndexToModel(rowViewIdx);
|
|
||||||
content.append('"').append(tableModel.getValueAt(rowModelIdx, colIdx)).append('"');
|
|
||||||
if (colIdx < (colCount - 1)) {
|
|
||||||
content.append(",");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
content.append(System.getProperty("line.separator"));
|
|
||||||
writer.write(content.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
LOGGER.log(Level.SEVERE, "Error writing selected rows to CSV.", ex);
|
LOGGER.log(Level.SEVERE, "Error writing selected rows to CSV.", ex);
|
||||||
}
|
}
|
||||||
@ -329,11 +332,15 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
private void reset() {
|
private void reset() {
|
||||||
// start with empty table
|
// start with empty table
|
||||||
casesTableModel.clearTable();
|
casesTableModel.clearTable();
|
||||||
((DefaultTableModel) dataSourcesTable.getModel()).setRowCount(0);
|
dataSourcesTableModel.clearTable();
|
||||||
tableModel.clearTable();
|
filesTableModel.clearTable();
|
||||||
correlationAttributes.clear();
|
correlationAttributes.clear();
|
||||||
earliestCaseDate.setText(Bundle.DataContentViewerOtherCases_earliestCaseNotAvailable());
|
earliestCaseDate.setText(Bundle.DataContentViewerOtherCases_earliestCaseNotAvailable());
|
||||||
foundInLabel.setText("");
|
foundInLabel.setText("");
|
||||||
|
//calling getPreferredSize has a side effect of ensuring it has a preferred size which reflects the contents which are visible
|
||||||
|
occurrencePanel = new OccurrencePanel();
|
||||||
|
occurrencePanel.getPreferredSize();
|
||||||
|
detailsPanelScrollPane.setViewportView(occurrencePanel);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -364,6 +371,7 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
@Override
|
@Override
|
||||||
public int isPreferred(Node node) {
|
public int isPreferred(Node node) {
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -558,7 +566,6 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
try {
|
try {
|
||||||
final Case openCase = Case.getCurrentCaseThrows();
|
final Case openCase = Case.getCurrentCaseThrows();
|
||||||
String caseUUID = openCase.getName();
|
String caseUUID = openCase.getName();
|
||||||
|
|
||||||
HashMap<UniquePathKey, OtherOccurrenceNodeInstanceData> nodeDataMap = new HashMap<>();
|
HashMap<UniquePathKey, OtherOccurrenceNodeInstanceData> nodeDataMap = new HashMap<>();
|
||||||
|
|
||||||
if (EamDb.isEnabled()) {
|
if (EamDb.isEnabled()) {
|
||||||
@ -583,7 +590,6 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (corAttr.getCorrelationType().getDisplayName().equals("Files")) {
|
if (corAttr.getCorrelationType().getDisplayName().equals("Files")) {
|
||||||
List<AbstractFile> caseDbFiles = getCaseDbMatches(corAttr, openCase);
|
List<AbstractFile> caseDbFiles = getCaseDbMatches(corAttr, openCase);
|
||||||
|
|
||||||
@ -591,7 +597,6 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
addOrUpdateNodeData(openCase, nodeDataMap, caseDbFile);
|
addOrUpdateNodeData(openCase, nodeDataMap, caseDbFile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nodeDataMap;
|
return nodeDataMap;
|
||||||
} catch (EamDbException ex) {
|
} catch (EamDbException ex) {
|
||||||
LOGGER.log(Level.SEVERE, "Error getting artifact instances from database.", ex); // NON-NLS
|
LOGGER.log(Level.SEVERE, "Error getting artifact instances from database.", ex); // NON-NLS
|
||||||
@ -748,14 +753,14 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
dataSources.add(makeDataSourceString(nodeData.getCorrelationAttributeInstance().getCorrelationCase().getCaseUUID(), nodeData.getDeviceID(), nodeData.getDataSourceName()));
|
dataSources.add(makeDataSourceString(nodeData.getCorrelationAttributeInstance().getCorrelationCase().getCaseUUID(), nodeData.getDeviceID(), nodeData.getDataSourceName()));
|
||||||
caseNames.put(nodeData.getCorrelationAttributeInstance().getCorrelationCase().getCaseUUID(), nodeData.getCorrelationAttributeInstance().getCorrelationCase());
|
caseNames.put(nodeData.getCorrelationAttributeInstance().getCorrelationCase().getCaseUUID(), nodeData.getCorrelationAttributeInstance().getCorrelationCase());
|
||||||
} catch (EamDbException ex) {
|
} catch (EamDbException ex) {
|
||||||
LOGGER.log(Level.WARNING, "Unable to get correlation case for displaying other occurrence for case: " + nodeData.getCaseName());
|
LOGGER.log(Level.WARNING, "Unable to get correlation case for displaying other occurrence for case: " + nodeData.getCaseName(), ex);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
dataSources.add(makeDataSourceString(Case.getCurrentCaseThrows().getName(), nodeData.getDeviceID(), nodeData.getDataSourceName()));
|
dataSources.add(makeDataSourceString(Case.getCurrentCaseThrows().getName(), nodeData.getDeviceID(), nodeData.getDataSourceName()));
|
||||||
caseNames.put(Case.getCurrentCaseThrows().getName(), new CorrelationCase(Case.getCurrentCaseThrows().getName(), Case.getCurrentCaseThrows().getDisplayName()));
|
caseNames.put(Case.getCurrentCaseThrows().getName(), new CorrelationCase(Case.getCurrentCaseThrows().getName(), Case.getCurrentCaseThrows().getDisplayName()));
|
||||||
} catch (NoCurrentCaseException ex) {
|
} catch (NoCurrentCaseException ex) {
|
||||||
LOGGER.log(Level.WARNING, "No current case open for other occurrences");
|
LOGGER.log(Level.WARNING, "No current case open for other occurrences", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
totalCount++;
|
totalCount++;
|
||||||
@ -770,7 +775,6 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
} else if (caseCount == 0) {
|
} else if (caseCount == 0) {
|
||||||
casesTableModel.addCorrelationCase(NO_RESULTS_CASE);
|
casesTableModel.addCorrelationCase(NO_RESULTS_CASE);
|
||||||
}
|
}
|
||||||
setColumnWidths();
|
|
||||||
setEarliestCaseDate();
|
setEarliestCaseDate();
|
||||||
foundInLabel.setText(String.format(Bundle.DataContentViewerOtherCases_foundIn_text(), totalCount, caseCount, dataSources.size()));
|
foundInLabel.setText(String.format(Bundle.DataContentViewerOtherCases_foundIn_text(), totalCount, caseCount, dataSources.size()));
|
||||||
if (caseCount > 0) {
|
if (caseCount > 0) {
|
||||||
@ -791,33 +795,40 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
*/
|
*/
|
||||||
private void updateOnCaseSelection() {
|
private void updateOnCaseSelection() {
|
||||||
int[] selectedCaseIndexes = casesTable.getSelectedRows();
|
int[] selectedCaseIndexes = casesTable.getSelectedRows();
|
||||||
DefaultTableModel dataSourceModel = (DefaultTableModel) dataSourcesTable.getModel();
|
dataSourcesTableModel.clearTable();
|
||||||
dataSourceModel.setRowCount(0);
|
filesTableModel.clearTable();
|
||||||
tableModel.clearTable();
|
|
||||||
for (CorrelationAttributeInstance corAttr : correlationAttributes) {
|
|
||||||
Map<UniquePathKey, OtherOccurrenceNodeInstanceData> correlatedNodeDataMap = new HashMap<>(0);
|
|
||||||
|
|
||||||
// get correlation and reference set instances from DB
|
if (selectedCaseIndexes.length == 0) {
|
||||||
correlatedNodeDataMap.putAll(getCorrelatedInstances(corAttr, dataSourceName, deviceId));
|
//special case when no cases are selected
|
||||||
for (OtherOccurrenceNodeInstanceData nodeData : correlatedNodeDataMap.values()) {
|
occurrencePanel = new OccurrencePanel();
|
||||||
for (int selectedRow : selectedCaseIndexes) {
|
occurrencePanel.getPreferredSize();
|
||||||
try {
|
detailsPanelScrollPane.setViewportView(occurrencePanel);
|
||||||
if (nodeData.isCentralRepoNode()) {
|
} else {
|
||||||
if (casesTableModel.getCorrelationCase(casesTable.convertRowIndexToModel(selectedRow)) != null
|
for (CorrelationAttributeInstance corAttr : correlationAttributes) {
|
||||||
&& ((CorrelationCase) casesTableModel.getCorrelationCase(casesTable.convertRowIndexToModel(selectedRow))).getCaseUUID().equals(nodeData.getCorrelationAttributeInstance().getCorrelationCase().getCaseUUID())) {
|
Map<UniquePathKey, OtherOccurrenceNodeInstanceData> correlatedNodeDataMap = new HashMap<>(0);
|
||||||
dataSourceModel.addRow(new Object[]{nodeData.getDataSourceName(), nodeData.getDeviceID()});
|
|
||||||
|
// get correlation and reference set instances from DB
|
||||||
|
correlatedNodeDataMap.putAll(getCorrelatedInstances(corAttr, dataSourceName, deviceId));
|
||||||
|
for (OtherOccurrenceNodeInstanceData nodeData : correlatedNodeDataMap.values()) {
|
||||||
|
for (int selectedRow : selectedCaseIndexes) {
|
||||||
|
try {
|
||||||
|
if (nodeData.isCentralRepoNode()) {
|
||||||
|
if (casesTableModel.getCorrelationCase(casesTable.convertRowIndexToModel(selectedRow)) != null
|
||||||
|
&& casesTableModel.getCorrelationCase(casesTable.convertRowIndexToModel(selectedRow)).getCaseUUID().equals(nodeData.getCorrelationAttributeInstance().getCorrelationCase().getCaseUUID())) {
|
||||||
|
dataSourcesTableModel.addNodeData(nodeData);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
dataSourcesTableModel.addNodeData(nodeData);
|
||||||
}
|
}
|
||||||
} else {
|
} catch (EamDbException ex) {
|
||||||
dataSourceModel.addRow(new Object[]{nodeData.getDataSourceName(), nodeData.getDeviceID()});
|
LOGGER.log(Level.WARNING, "Unable to get correlation attribute instance from OtherOccurrenceNodeInstanceData for case " + nodeData.getCaseName(), ex);
|
||||||
}
|
}
|
||||||
} catch (EamDbException ex) {
|
|
||||||
LOGGER.log(Level.WARNING, "Unable to get correlation attribute instance from OtherOccurrenceNodeInstanceData for case " + nodeData.getCaseName());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
if (dataSourcesTable.getRowCount() > 0) {
|
||||||
if (dataSourcesTable.getRowCount() > 0) {
|
dataSourcesTable.setRowSelectionInterval(0, 0);
|
||||||
dataSourcesTable.setRowSelectionInterval(0, 0);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -827,9 +838,8 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
*/
|
*/
|
||||||
private void updateOnDataSourceSelection() {
|
private void updateOnDataSourceSelection() {
|
||||||
int[] selectedCaseIndexes = casesTable.getSelectedRows();
|
int[] selectedCaseIndexes = casesTable.getSelectedRows();
|
||||||
DefaultTableModel dataSourceModel = (DefaultTableModel) dataSourcesTable.getModel();
|
|
||||||
int[] selectedDataSources = dataSourcesTable.getSelectedRows();
|
int[] selectedDataSources = dataSourcesTable.getSelectedRows();
|
||||||
tableModel.clearTable();
|
filesTableModel.clearTable();
|
||||||
for (CorrelationAttributeInstance corAttr : correlationAttributes) {
|
for (CorrelationAttributeInstance corAttr : correlationAttributes) {
|
||||||
Map<UniquePathKey, OtherOccurrenceNodeInstanceData> correlatedNodeDataMap = new HashMap<>(0);
|
Map<UniquePathKey, OtherOccurrenceNodeInstanceData> correlatedNodeDataMap = new HashMap<>(0);
|
||||||
|
|
||||||
@ -841,43 +851,94 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
try {
|
try {
|
||||||
if (nodeData.isCentralRepoNode()) {
|
if (nodeData.isCentralRepoNode()) {
|
||||||
if (casesTableModel.getCorrelationCase(casesTable.convertRowIndexToModel(selectedCaseRow)) != null
|
if (casesTableModel.getCorrelationCase(casesTable.convertRowIndexToModel(selectedCaseRow)) != null
|
||||||
&& ((CorrelationCase) casesTableModel.getCorrelationCase(casesTable.convertRowIndexToModel(selectedCaseRow))).getCaseUUID().equals(nodeData.getCorrelationAttributeInstance().getCorrelationCase().getCaseUUID())
|
&& casesTableModel.getCorrelationCase(casesTable.convertRowIndexToModel(selectedCaseRow)).getCaseUUID().equals(nodeData.getCorrelationAttributeInstance().getCorrelationCase().getCaseUUID())
|
||||||
&& dataSourceModel.getValueAt(dataSourcesTable.convertRowIndexToModel(selectedDataSourceRow), 1).toString().equals(nodeData.getDeviceID())) {
|
&& dataSourcesTableModel.getDeviceIdForRow(dataSourcesTable.convertRowIndexToModel(selectedDataSourceRow)).equals(nodeData.getDeviceID())) {
|
||||||
tableModel.addNodeData(nodeData);
|
filesTableModel.addNodeData(nodeData);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (dataSourceModel.getValueAt(dataSourcesTable.convertRowIndexToModel(selectedDataSourceRow), 1).toString().equals(nodeData.getDeviceID())) {
|
if (dataSourcesTableModel.getDeviceIdForRow(dataSourcesTable.convertRowIndexToModel(selectedDataSourceRow)).equals(nodeData.getDeviceID())) {
|
||||||
tableModel.addNodeData(nodeData);
|
filesTableModel.addNodeData(nodeData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (EamDbException ex) {
|
} catch (EamDbException ex) {
|
||||||
LOGGER.log(Level.WARNING, "Unable to get correlation attribute instance from OtherOccurrenceNodeInstanceData for case " + nodeData.getCaseName());
|
LOGGER.log(Level.WARNING, "Unable to get correlation attribute instance from OtherOccurrenceNodeInstanceData for case " + nodeData.getCaseName(), ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (filesTable.getRowCount() > 0) {
|
||||||
|
filesTable.setRowSelectionInterval(0, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adjust column widths to their preferred values.
|
* Update the data displayed in the details section to be correct for the
|
||||||
|
* currently selected File
|
||||||
*/
|
*/
|
||||||
private void setColumnWidths() {
|
private void updateOnFileSelection() {
|
||||||
for (int idx = 0; idx < tableModel.getColumnCount(); idx++) {
|
if (filesTable.getSelectedRowCount() == 1) {
|
||||||
TableColumn column = filesTable.getColumnModel().getColumn(idx);
|
//if there is one file selected update the deatils to show the data for that file
|
||||||
column.setMinWidth(DEFAULT_MIN_CELL_WIDTH);
|
occurrencePanel = new OccurrencePanel(filesTableModel.getListOfNodesForFile(filesTable.convertRowIndexToModel(filesTable.getSelectedRow())));
|
||||||
int columnWidth = tableModel.getColumnPreferredWidth(idx);
|
} else if (dataSourcesTable.getSelectedRowCount() == 1) {
|
||||||
if (columnWidth > 0) {
|
//if no files were selected and only one data source is selected update the information to reflect the data source
|
||||||
column.setPreferredWidth(columnWidth);
|
String caseName = dataSourcesTableModel.getCaseNameForRow(dataSourcesTable.convertRowIndexToModel(dataSourcesTable.getSelectedRow()));
|
||||||
|
String dsName = dataSourcesTableModel.getValueAt(dataSourcesTable.convertRowIndexToModel(dataSourcesTable.getSelectedRow()), 0).toString();
|
||||||
|
String caseCreatedDate = "";
|
||||||
|
for (int row : casesTable.getSelectedRows()) {
|
||||||
|
if (casesTableModel.getValueAt(casesTable.convertRowIndexToModel(row), 0).toString().equals(caseName)) {
|
||||||
|
caseCreatedDate = getCaseCreatedDate(row);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
occurrencePanel = new OccurrencePanel(caseName, caseCreatedDate, dsName);
|
||||||
for (int idx = 0; idx < dataSourcesTable.getColumnCount(); idx++) {
|
} else if (casesTable.getSelectedRowCount() == 1) {
|
||||||
if (dataSourcesTable.getColumnModel().getColumn(idx).getHeaderValue().toString().equals(Bundle.DataContentViewerOtherCases_dataSources_header_text())) {
|
//if no files were selected and a number of data source other than 1 are selected
|
||||||
dataSourcesTable.getColumnModel().getColumn(idx).setPreferredWidth(100);
|
//update the information to reflect the case
|
||||||
|
String createdDate = "";
|
||||||
|
String caseName = "";
|
||||||
|
if (casesTable.getRowCount() > 0) {
|
||||||
|
caseName = casesTableModel.getValueAt(casesTable.convertRowIndexToModel(casesTable.getSelectedRow()), 0).toString();
|
||||||
|
}
|
||||||
|
if (caseName.isEmpty()) {
|
||||||
|
occurrencePanel = new OccurrencePanel();
|
||||||
} else {
|
} else {
|
||||||
dataSourcesTable.getColumnModel().getColumn(idx).setPreferredWidth(210);
|
createdDate = getCaseCreatedDate(casesTable.getSelectedRow());
|
||||||
|
occurrencePanel = new OccurrencePanel(caseName, createdDate);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
//else display an empty details area
|
||||||
|
occurrencePanel = new OccurrencePanel();
|
||||||
}
|
}
|
||||||
|
//calling getPreferredSize has a side effect of ensuring it has a preferred size which reflects the contents which are visible
|
||||||
|
occurrencePanel.getPreferredSize();
|
||||||
|
detailsPanelScrollPane.setViewportView(occurrencePanel);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the date a case was created
|
||||||
|
*
|
||||||
|
* @param caseTableRowIdx the row from the casesTable representing the case
|
||||||
|
*
|
||||||
|
* @return A string representing the date the case was created or an empty
|
||||||
|
* string if the date could not be determined
|
||||||
|
*/
|
||||||
|
private String getCaseCreatedDate(int caseTableRowIdx) {
|
||||||
|
try {
|
||||||
|
if (EamDb.isEnabled()) {
|
||||||
|
CorrelationCase partialCase;
|
||||||
|
partialCase = casesTableModel.getCorrelationCase(casesTable.convertRowIndexToModel(caseTableRowIdx));
|
||||||
|
if (partialCase == null){
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return EamDb.getInstance().getCaseByUUID(partialCase.getCaseUUID()).getCreationDate();
|
||||||
|
} else {
|
||||||
|
return Case.getCurrentCase().getCreatedDate();
|
||||||
|
}
|
||||||
|
} catch (EamDbException ex) {
|
||||||
|
LOGGER.log(Level.WARNING, "Error getting case created date for row: " + caseTableRowIdx, ex);
|
||||||
|
}
|
||||||
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -895,19 +956,20 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
showCaseDetailsMenuItem = new javax.swing.JMenuItem();
|
showCaseDetailsMenuItem = new javax.swing.JMenuItem();
|
||||||
showCommonalityMenuItem = new javax.swing.JMenuItem();
|
showCommonalityMenuItem = new javax.swing.JMenuItem();
|
||||||
CSVFileChooser = new javax.swing.JFileChooser();
|
CSVFileChooser = new javax.swing.JFileChooser();
|
||||||
otherCasesPanel = new javax.swing.JPanel();
|
|
||||||
tableContainerPanel = new javax.swing.JPanel();
|
tableContainerPanel = new javax.swing.JPanel();
|
||||||
earliestCaseLabel = new javax.swing.JLabel();
|
earliestCaseLabel = new javax.swing.JLabel();
|
||||||
earliestCaseDate = new javax.swing.JLabel();
|
earliestCaseDate = new javax.swing.JLabel();
|
||||||
foundInLabel = new javax.swing.JLabel();
|
foundInLabel = new javax.swing.JLabel();
|
||||||
jSplitPane2 = new javax.swing.JSplitPane();
|
tablesViewerSplitPane = new javax.swing.JSplitPane();
|
||||||
jSplitPane3 = new javax.swing.JSplitPane();
|
caseDatasourceFileSplitPane = new javax.swing.JSplitPane();
|
||||||
|
caseDatasourceSplitPane = new javax.swing.JSplitPane();
|
||||||
caseScrollPane = new javax.swing.JScrollPane();
|
caseScrollPane = new javax.swing.JScrollPane();
|
||||||
casesTable = new javax.swing.JTable();
|
casesTable = new javax.swing.JTable();
|
||||||
dataSourceScrollPane = new javax.swing.JScrollPane();
|
dataSourceScrollPane = new javax.swing.JScrollPane();
|
||||||
dataSourcesTable = new javax.swing.JTable();
|
dataSourcesTable = new javax.swing.JTable();
|
||||||
propertiesTableScrollPane = new javax.swing.JScrollPane();
|
filesTableScrollPane = new javax.swing.JScrollPane();
|
||||||
filesTable = new javax.swing.JTable();
|
filesTable = new javax.swing.JTable();
|
||||||
|
detailsPanelScrollPane = new javax.swing.JScrollPane();
|
||||||
|
|
||||||
rightClickPopupMenu.addPopupMenuListener(new javax.swing.event.PopupMenuListener() {
|
rightClickPopupMenu.addPopupMenuListener(new javax.swing.event.PopupMenuListener() {
|
||||||
public void popupMenuCanceled(javax.swing.event.PopupMenuEvent evt) {
|
public void popupMenuCanceled(javax.swing.event.PopupMenuEvent evt) {
|
||||||
@ -931,13 +993,12 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
org.openide.awt.Mnemonics.setLocalizedText(showCommonalityMenuItem, org.openide.util.NbBundle.getMessage(DataContentViewerOtherCases.class, "DataContentViewerOtherCases.showCommonalityMenuItem.text")); // NOI18N
|
org.openide.awt.Mnemonics.setLocalizedText(showCommonalityMenuItem, org.openide.util.NbBundle.getMessage(DataContentViewerOtherCases.class, "DataContentViewerOtherCases.showCommonalityMenuItem.text")); // NOI18N
|
||||||
rightClickPopupMenu.add(showCommonalityMenuItem);
|
rightClickPopupMenu.add(showCommonalityMenuItem);
|
||||||
|
|
||||||
setMinimumSize(new java.awt.Dimension(1500, 10));
|
setMinimumSize(new java.awt.Dimension(600, 10));
|
||||||
setOpaque(false);
|
setOpaque(false);
|
||||||
setPreferredSize(new java.awt.Dimension(1500, 44));
|
setPreferredSize(new java.awt.Dimension(600, 63));
|
||||||
|
|
||||||
otherCasesPanel.setPreferredSize(new java.awt.Dimension(921, 62));
|
tableContainerPanel.setPreferredSize(new java.awt.Dimension(600, 63));
|
||||||
|
tableContainerPanel.setRequestFocusEnabled(false);
|
||||||
tableContainerPanel.setPreferredSize(new java.awt.Dimension(1500, 63));
|
|
||||||
|
|
||||||
org.openide.awt.Mnemonics.setLocalizedText(earliestCaseLabel, org.openide.util.NbBundle.getMessage(DataContentViewerOtherCases.class, "DataContentViewerOtherCases.earliestCaseLabel.text")); // NOI18N
|
org.openide.awt.Mnemonics.setLocalizedText(earliestCaseLabel, org.openide.util.NbBundle.getMessage(DataContentViewerOtherCases.class, "DataContentViewerOtherCases.earliestCaseLabel.text")); // NOI18N
|
||||||
earliestCaseLabel.setToolTipText(org.openide.util.NbBundle.getMessage(DataContentViewerOtherCases.class, "DataContentViewerOtherCases.earliestCaseLabel.toolTipText")); // NOI18N
|
earliestCaseLabel.setToolTipText(org.openide.util.NbBundle.getMessage(DataContentViewerOtherCases.class, "DataContentViewerOtherCases.earliestCaseLabel.toolTipText")); // NOI18N
|
||||||
@ -946,49 +1007,50 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
|
|
||||||
org.openide.awt.Mnemonics.setLocalizedText(foundInLabel, org.openide.util.NbBundle.getMessage(DataContentViewerOtherCases.class, "DataContentViewerOtherCases.foundInLabel.text")); // NOI18N
|
org.openide.awt.Mnemonics.setLocalizedText(foundInLabel, org.openide.util.NbBundle.getMessage(DataContentViewerOtherCases.class, "DataContentViewerOtherCases.foundInLabel.text")); // NOI18N
|
||||||
|
|
||||||
jSplitPane2.setDividerLocation(470);
|
tablesViewerSplitPane.setDividerLocation(450);
|
||||||
|
tablesViewerSplitPane.setResizeWeight(0.5);
|
||||||
|
|
||||||
jSplitPane3.setDividerLocation(150);
|
caseDatasourceFileSplitPane.setDividerLocation(300);
|
||||||
|
caseDatasourceFileSplitPane.setResizeWeight(0.6);
|
||||||
|
caseDatasourceFileSplitPane.setToolTipText("");
|
||||||
|
|
||||||
|
caseDatasourceSplitPane.setDividerLocation(150);
|
||||||
|
caseDatasourceSplitPane.setResizeWeight(0.5);
|
||||||
|
|
||||||
|
caseScrollPane.setPreferredSize(new java.awt.Dimension(140, 30));
|
||||||
|
|
||||||
casesTable.setAutoCreateRowSorter(true);
|
casesTable.setAutoCreateRowSorter(true);
|
||||||
casesTable.setModel(casesTableModel);
|
casesTable.setModel(casesTableModel);
|
||||||
caseScrollPane.setViewportView(casesTable);
|
caseScrollPane.setViewportView(casesTable);
|
||||||
|
|
||||||
jSplitPane3.setLeftComponent(caseScrollPane);
|
caseDatasourceSplitPane.setLeftComponent(caseScrollPane);
|
||||||
|
|
||||||
|
dataSourceScrollPane.setPreferredSize(new java.awt.Dimension(140, 30));
|
||||||
|
|
||||||
dataSourcesTable.setAutoCreateRowSorter(true);
|
dataSourcesTable.setAutoCreateRowSorter(true);
|
||||||
dataSourcesTable.setModel(new javax.swing.table.DefaultTableModel(
|
dataSourcesTable.setModel(dataSourcesTableModel);
|
||||||
new Object [][] {
|
|
||||||
|
|
||||||
},
|
|
||||||
new String [] {
|
|
||||||
"Data Source Name", "Device ID"
|
|
||||||
}
|
|
||||||
) {
|
|
||||||
boolean[] canEdit = new boolean [] {
|
|
||||||
false, false
|
|
||||||
};
|
|
||||||
|
|
||||||
public boolean isCellEditable(int rowIndex, int columnIndex) {
|
|
||||||
return canEdit [columnIndex];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
dataSourceScrollPane.setViewportView(dataSourcesTable);
|
dataSourceScrollPane.setViewportView(dataSourcesTable);
|
||||||
|
|
||||||
jSplitPane3.setRightComponent(dataSourceScrollPane);
|
caseDatasourceSplitPane.setRightComponent(dataSourceScrollPane);
|
||||||
|
|
||||||
jSplitPane2.setLeftComponent(jSplitPane3);
|
caseDatasourceFileSplitPane.setLeftComponent(caseDatasourceSplitPane);
|
||||||
|
|
||||||
propertiesTableScrollPane.setPreferredSize(new java.awt.Dimension(1000, 30));
|
filesTableScrollPane.setPreferredSize(new java.awt.Dimension(140, 30));
|
||||||
|
|
||||||
filesTable.setAutoCreateRowSorter(true);
|
filesTable.setAutoCreateRowSorter(true);
|
||||||
filesTable.setModel(tableModel);
|
filesTable.setModel(filesTableModel);
|
||||||
filesTable.setToolTipText(org.openide.util.NbBundle.getMessage(DataContentViewerOtherCases.class, "DataContentViewerOtherCases.table.toolTip.text")); // NOI18N
|
filesTable.setToolTipText(org.openide.util.NbBundle.getMessage(DataContentViewerOtherCases.class, "DataContentViewerOtherCases.table.toolTip.text")); // NOI18N
|
||||||
filesTable.setComponentPopupMenu(rightClickPopupMenu);
|
filesTable.setComponentPopupMenu(rightClickPopupMenu);
|
||||||
filesTable.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_INTERVAL_SELECTION);
|
filesTable.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
|
||||||
propertiesTableScrollPane.setViewportView(filesTable);
|
filesTableScrollPane.setViewportView(filesTable);
|
||||||
|
|
||||||
jSplitPane2.setRightComponent(propertiesTableScrollPane);
|
caseDatasourceFileSplitPane.setRightComponent(filesTableScrollPane);
|
||||||
|
|
||||||
|
tablesViewerSplitPane.setLeftComponent(caseDatasourceFileSplitPane);
|
||||||
|
|
||||||
|
detailsPanelScrollPane.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
|
||||||
|
detailsPanelScrollPane.setPreferredSize(new java.awt.Dimension(200, 100));
|
||||||
|
tablesViewerSplitPane.setRightComponent(detailsPanelScrollPane);
|
||||||
|
|
||||||
javax.swing.GroupLayout tableContainerPanelLayout = new javax.swing.GroupLayout(tableContainerPanel);
|
javax.swing.GroupLayout tableContainerPanelLayout = new javax.swing.GroupLayout(tableContainerPanel);
|
||||||
tableContainerPanel.setLayout(tableContainerPanelLayout);
|
tableContainerPanel.setLayout(tableContainerPanelLayout);
|
||||||
@ -997,65 +1059,49 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
.addGroup(tableContainerPanelLayout.createSequentialGroup()
|
.addGroup(tableContainerPanelLayout.createSequentialGroup()
|
||||||
.addGroup(tableContainerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
.addGroup(tableContainerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
.addGroup(tableContainerPanelLayout.createSequentialGroup()
|
.addGroup(tableContainerPanelLayout.createSequentialGroup()
|
||||||
.addComponent(earliestCaseLabel)
|
.addComponent(earliestCaseLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 161, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
.addComponent(earliestCaseDate)
|
.addComponent(earliestCaseDate, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||||
.addGap(66, 66, 66)
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||||
.addComponent(foundInLabel))
|
.addComponent(foundInLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||||
.addComponent(jSplitPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 911, Short.MAX_VALUE))
|
.addComponent(tablesViewerSplitPane, javax.swing.GroupLayout.DEFAULT_SIZE, 590, Short.MAX_VALUE))
|
||||||
.addContainerGap())
|
.addContainerGap())
|
||||||
);
|
);
|
||||||
tableContainerPanelLayout.setVerticalGroup(
|
tableContainerPanelLayout.setVerticalGroup(
|
||||||
tableContainerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
tableContainerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, tableContainerPanelLayout.createSequentialGroup()
|
.addGroup(tableContainerPanelLayout.createSequentialGroup()
|
||||||
.addComponent(jSplitPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 31, Short.MAX_VALUE)
|
.addGap(0, 0, 0)
|
||||||
|
.addComponent(tablesViewerSplitPane, javax.swing.GroupLayout.DEFAULT_SIZE, 33, Short.MAX_VALUE)
|
||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
.addGroup(tableContainerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
.addGroup(tableContainerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
|
||||||
.addComponent(earliestCaseLabel)
|
.addGroup(tableContainerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||||
.addComponent(earliestCaseDate)
|
.addComponent(earliestCaseLabel)
|
||||||
.addComponent(foundInLabel))
|
.addComponent(earliestCaseDate))
|
||||||
|
.addComponent(foundInLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||||
.addContainerGap())
|
.addContainerGap())
|
||||||
);
|
);
|
||||||
|
|
||||||
javax.swing.GroupLayout otherCasesPanelLayout = new javax.swing.GroupLayout(otherCasesPanel);
|
|
||||||
otherCasesPanel.setLayout(otherCasesPanelLayout);
|
|
||||||
otherCasesPanelLayout.setHorizontalGroup(
|
|
||||||
otherCasesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
|
||||||
.addGap(0, 921, Short.MAX_VALUE)
|
|
||||||
.addGroup(otherCasesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
|
||||||
.addGroup(otherCasesPanelLayout.createSequentialGroup()
|
|
||||||
.addComponent(tableContainerPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
|
||||||
.addGap(0, 0, 0)))
|
|
||||||
);
|
|
||||||
otherCasesPanelLayout.setVerticalGroup(
|
|
||||||
otherCasesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
|
||||||
.addGap(0, 62, Short.MAX_VALUE)
|
|
||||||
.addGroup(otherCasesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
|
||||||
.addGroup(otherCasesPanelLayout.createSequentialGroup()
|
|
||||||
.addComponent(tableContainerPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 62, Short.MAX_VALUE)
|
|
||||||
.addGap(0, 0, 0)))
|
|
||||||
);
|
|
||||||
|
|
||||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
||||||
this.setLayout(layout);
|
this.setLayout(layout);
|
||||||
layout.setHorizontalGroup(
|
layout.setHorizontalGroup(
|
||||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
.addComponent(otherCasesPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 1500, Short.MAX_VALUE)
|
.addComponent(tableContainerPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||||
);
|
);
|
||||||
layout.setVerticalGroup(
|
layout.setVerticalGroup(
|
||||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
.addComponent(otherCasesPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
.addGroup(layout.createSequentialGroup()
|
||||||
|
.addComponent(tableContainerPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 64, Short.MAX_VALUE)
|
||||||
|
.addGap(0, 0, 0))
|
||||||
);
|
);
|
||||||
}// </editor-fold>//GEN-END:initComponents
|
}// </editor-fold>//GEN-END:initComponents
|
||||||
|
|
||||||
private void rightClickPopupMenuPopupMenuWillBecomeVisible(javax.swing.event.PopupMenuEvent evt) {//GEN-FIRST:event_rightClickPopupMenuPopupMenuWillBecomeVisible
|
private void rightClickPopupMenuPopupMenuWillBecomeVisible(javax.swing.event.PopupMenuEvent evt) {//GEN-FIRST:event_rightClickPopupMenuPopupMenuWillBecomeVisible
|
||||||
boolean enableCentralRepoActions = false;
|
boolean enableCentralRepoActions = false;
|
||||||
|
|
||||||
if (EamDb.isEnabled() && filesTable.getSelectedRowCount() == 1) {
|
if (EamDb.isEnabled() && filesTable.getSelectedRowCount() == 1) {
|
||||||
int rowIndex = filesTable.getSelectedRow();
|
int rowIndex = filesTable.getSelectedRow();
|
||||||
OtherOccurrenceNodeData selectedNode = (OtherOccurrenceNodeData) tableModel.getRow(rowIndex);
|
List<OtherOccurrenceNodeData> selectedFile = filesTableModel.getListOfNodesForFile(rowIndex);
|
||||||
if (selectedNode instanceof OtherOccurrenceNodeInstanceData) {
|
if (!selectedFile.isEmpty() && selectedFile.get(0) instanceof OtherOccurrenceNodeInstanceData) {
|
||||||
OtherOccurrenceNodeInstanceData instanceData = (OtherOccurrenceNodeInstanceData) selectedNode;
|
OtherOccurrenceNodeInstanceData instanceData = (OtherOccurrenceNodeInstanceData) selectedFile.get(0);
|
||||||
enableCentralRepoActions = instanceData.isCentralRepoNode();
|
enableCentralRepoActions = instanceData.isCentralRepoNode();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1065,24 +1111,25 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
|
|
||||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||||
private javax.swing.JFileChooser CSVFileChooser;
|
private javax.swing.JFileChooser CSVFileChooser;
|
||||||
|
private javax.swing.JSplitPane caseDatasourceFileSplitPane;
|
||||||
|
private javax.swing.JSplitPane caseDatasourceSplitPane;
|
||||||
private javax.swing.JScrollPane caseScrollPane;
|
private javax.swing.JScrollPane caseScrollPane;
|
||||||
private javax.swing.JTable casesTable;
|
private javax.swing.JTable casesTable;
|
||||||
private javax.swing.JScrollPane dataSourceScrollPane;
|
private javax.swing.JScrollPane dataSourceScrollPane;
|
||||||
private javax.swing.JTable dataSourcesTable;
|
private javax.swing.JTable dataSourcesTable;
|
||||||
|
private javax.swing.JScrollPane detailsPanelScrollPane;
|
||||||
private javax.swing.JLabel earliestCaseDate;
|
private javax.swing.JLabel earliestCaseDate;
|
||||||
private javax.swing.JLabel earliestCaseLabel;
|
private javax.swing.JLabel earliestCaseLabel;
|
||||||
private javax.swing.JMenuItem exportToCSVMenuItem;
|
private javax.swing.JMenuItem exportToCSVMenuItem;
|
||||||
private javax.swing.JTable filesTable;
|
private javax.swing.JTable filesTable;
|
||||||
|
private javax.swing.JScrollPane filesTableScrollPane;
|
||||||
private javax.swing.JLabel foundInLabel;
|
private javax.swing.JLabel foundInLabel;
|
||||||
private javax.swing.JSplitPane jSplitPane2;
|
|
||||||
private javax.swing.JSplitPane jSplitPane3;
|
|
||||||
private javax.swing.JPanel otherCasesPanel;
|
|
||||||
private javax.swing.JScrollPane propertiesTableScrollPane;
|
|
||||||
private javax.swing.JPopupMenu rightClickPopupMenu;
|
private javax.swing.JPopupMenu rightClickPopupMenu;
|
||||||
private javax.swing.JMenuItem selectAllMenuItem;
|
private javax.swing.JMenuItem selectAllMenuItem;
|
||||||
private javax.swing.JMenuItem showCaseDetailsMenuItem;
|
private javax.swing.JMenuItem showCaseDetailsMenuItem;
|
||||||
private javax.swing.JMenuItem showCommonalityMenuItem;
|
private javax.swing.JMenuItem showCommonalityMenuItem;
|
||||||
private javax.swing.JPanel tableContainerPanel;
|
private javax.swing.JPanel tableContainerPanel;
|
||||||
|
private javax.swing.JSplitPane tablesViewerSplitPane;
|
||||||
// End of variables declaration//GEN-END:variables
|
// End of variables declaration//GEN-END:variables
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1119,9 +1166,6 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
//int hash = 7;
|
|
||||||
//hash = 67 * hash + this.dataSourceID.hashCode();
|
|
||||||
//hash = 67 * hash + this.filePath.hashCode();
|
|
||||||
return Objects.hash(getDataSourceID(), getFilePath(), getType());
|
return Objects.hash(getDataSourceID(), getFilePath(), getType());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,23 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
|
||||||
|
<Form version="1.4" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
||||||
|
<Properties>
|
||||||
|
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[50, 30]"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
<AuxValues>
|
||||||
|
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
|
||||||
|
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
|
||||||
|
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
|
||||||
|
<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,0,68,0,0,0,-116"/>
|
||||||
|
</AuxValues>
|
||||||
|
|
||||||
|
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||||
|
</Form>
|
@ -0,0 +1,370 @@
|
|||||||
|
/*
|
||||||
|
* Central Repository
|
||||||
|
*
|
||||||
|
* Copyright 2019 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.centralrepository.contentviewer;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.Font;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import org.openide.util.NbBundle.Messages;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
|
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationCase;
|
||||||
|
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb;
|
||||||
|
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
|
import org.sleuthkit.datamodel.TskData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Panel for displaying other occurrence details.
|
||||||
|
*/
|
||||||
|
final class OccurrencePanel extends javax.swing.JPanel {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = Logger.getLogger(OccurrencePanel.class.getName());
|
||||||
|
private static final int LEFT_INSET = 10;
|
||||||
|
private static final int RIGHT_INSET = 10;
|
||||||
|
private static final int TOP_INSET = 10;
|
||||||
|
private static final int BOTTOM_INSET = 10;
|
||||||
|
private static final int VERTICAL_GAP = 6;
|
||||||
|
private static final int HORIZONTAL_GAP = 4;
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private int gridY = 0;
|
||||||
|
private final List<OtherOccurrenceNodeData> nodeDataList;
|
||||||
|
private final Map<String, String> caseNamesAndDates = new HashMap<>();
|
||||||
|
private final Set<String> dataSourceNames = new HashSet<>();
|
||||||
|
private final Set<String> filePaths = new HashSet<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct an empty OccurrencePanel
|
||||||
|
*/
|
||||||
|
OccurrencePanel() {
|
||||||
|
nodeDataList = new ArrayList<>();
|
||||||
|
customizeComponents();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct an OccurrencePanel which will display only Case information
|
||||||
|
*
|
||||||
|
* @param caseName the name of the case
|
||||||
|
* @param caseCreatedDate the date the case was created
|
||||||
|
*/
|
||||||
|
OccurrencePanel(String caseName, String caseCreatedDate) {
|
||||||
|
nodeDataList = new ArrayList<>();
|
||||||
|
caseNamesAndDates.put(caseName, caseCreatedDate);
|
||||||
|
customizeComponents();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct an OccurrencePanel which will display only case and data source
|
||||||
|
* information
|
||||||
|
*
|
||||||
|
* @param caseName the name of the case
|
||||||
|
* @param caseCreatedDate the date the case was created
|
||||||
|
* @param dataSourceName the name of the data source
|
||||||
|
*/
|
||||||
|
OccurrencePanel(String caseName, String caseCreatedDate, String dataSourceName) {
|
||||||
|
nodeDataList = new ArrayList<>();
|
||||||
|
caseNamesAndDates.put(caseName, caseCreatedDate);
|
||||||
|
dataSourceNames.add(dataSourceName);
|
||||||
|
customizeComponents();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a OccurrencePanel which will display details for all other
|
||||||
|
* occurrences associated with a file
|
||||||
|
*
|
||||||
|
* @param nodeDataList the list of OtherOccurrenceNodeData representing
|
||||||
|
* common properties for the file
|
||||||
|
*/
|
||||||
|
OccurrencePanel(List<OtherOccurrenceNodeData> nodeDataList) {
|
||||||
|
this.nodeDataList = nodeDataList;
|
||||||
|
customizeComponents();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do all the construction of gui elements and adding of the appropriate
|
||||||
|
* elements to the gridbaglayout
|
||||||
|
*/
|
||||||
|
private void customizeComponents() {
|
||||||
|
initComponents();
|
||||||
|
if (!this.nodeDataList.isEmpty()) {
|
||||||
|
//if addInstanceDetails is going to be called it should be called
|
||||||
|
// before addFileDetails, addDataSourceDetails, and addCaseDetails
|
||||||
|
//because it also collects the information they display
|
||||||
|
addInstanceDetails();
|
||||||
|
if (!filePaths.isEmpty()) {
|
||||||
|
addFileDetails();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!dataSourceNames.isEmpty()) {
|
||||||
|
addDataSourceDetails();
|
||||||
|
}
|
||||||
|
if (!caseNamesAndDates.keySet().isEmpty()) {
|
||||||
|
addCaseDetails();
|
||||||
|
}
|
||||||
|
//add filler to keep everything else at the top
|
||||||
|
addItemToBag(gridY, 0, 0, 0, new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 32767)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Messages({
|
||||||
|
"OccurrencePanel.commonProperties.text=Common Properties",
|
||||||
|
"OccurrencePanel.commonPropertyTypeLabel.text=Type:",
|
||||||
|
"OccurrencePanel.commonPropertyValueLabel.text=Value:",
|
||||||
|
"OccurrencePanel.commonPropertyKnownStatusLabel.text=Known Status:",
|
||||||
|
"OccurrencePanel.commonPropertyCommentLabel.text=Comment:"
|
||||||
|
})
|
||||||
|
/**
|
||||||
|
* Add the Common Property instance details to the gridbaglayout supports
|
||||||
|
* adding multiple common properties
|
||||||
|
*
|
||||||
|
* Also collects the case, data source, and file path information to be
|
||||||
|
* displayed
|
||||||
|
*/
|
||||||
|
private void addInstanceDetails() {
|
||||||
|
javax.swing.JLabel commonPropertiesLabel = new javax.swing.JLabel();
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(commonPropertiesLabel, Bundle.OccurrencePanel_commonProperties_text());
|
||||||
|
commonPropertiesLabel.setFont(commonPropertiesLabel.getFont().deriveFont(Font.BOLD, commonPropertiesLabel.getFont().getSize()));
|
||||||
|
addItemToBag(gridY, 0, TOP_INSET, 0, commonPropertiesLabel);
|
||||||
|
gridY++;
|
||||||
|
//for each other occurrence
|
||||||
|
for (OtherOccurrenceNodeData occurrence : nodeDataList) {
|
||||||
|
if (occurrence instanceof OtherOccurrenceNodeInstanceData) {
|
||||||
|
String type = ((OtherOccurrenceNodeInstanceData) occurrence).getType();
|
||||||
|
if (!type.isEmpty()) {
|
||||||
|
javax.swing.JLabel typeLabel = new javax.swing.JLabel();
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(typeLabel, Bundle.OccurrencePanel_commonPropertyTypeLabel_text());
|
||||||
|
addItemToBag(gridY, 0, VERTICAL_GAP, 0, typeLabel);
|
||||||
|
javax.swing.JLabel typeFieldValue = new javax.swing.JLabel();
|
||||||
|
typeFieldValue.setText(type);
|
||||||
|
addItemToBag(gridY, 1, VERTICAL_GAP, 0, typeFieldValue);
|
||||||
|
gridY++;
|
||||||
|
}
|
||||||
|
String value = ((OtherOccurrenceNodeInstanceData) occurrence).getValue();
|
||||||
|
if (!value.isEmpty()) {
|
||||||
|
javax.swing.JLabel valueLabel = new javax.swing.JLabel();
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(valueLabel, Bundle.OccurrencePanel_commonPropertyValueLabel_text());
|
||||||
|
addItemToBag(gridY, 0, 0, 0, valueLabel);
|
||||||
|
javax.swing.JLabel valueFieldValue = new javax.swing.JLabel();
|
||||||
|
valueFieldValue.setText(value);
|
||||||
|
addItemToBag(gridY, 1, 0, 0, valueFieldValue);
|
||||||
|
gridY++;
|
||||||
|
}
|
||||||
|
TskData.FileKnown knownStatus = ((OtherOccurrenceNodeInstanceData) occurrence).getKnown();
|
||||||
|
javax.swing.JLabel knownStatusLabel = new javax.swing.JLabel();
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(knownStatusLabel, Bundle.OccurrencePanel_commonPropertyKnownStatusLabel_text());
|
||||||
|
addItemToBag(gridY, 0, 0, 0, knownStatusLabel);
|
||||||
|
javax.swing.JLabel knownStatusValue = new javax.swing.JLabel();
|
||||||
|
knownStatusValue.setText(knownStatus.toString());
|
||||||
|
if (knownStatus == TskData.FileKnown.BAD) {
|
||||||
|
knownStatusValue.setForeground(Color.RED);
|
||||||
|
}
|
||||||
|
addItemToBag(gridY, 1, 0, 0, knownStatusValue);
|
||||||
|
gridY++;
|
||||||
|
String comment = ((OtherOccurrenceNodeInstanceData) occurrence).getComment();
|
||||||
|
if (!comment.isEmpty()) {
|
||||||
|
javax.swing.JLabel commentLabel = new javax.swing.JLabel();
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(commentLabel, Bundle.OccurrencePanel_commonPropertyCommentLabel_text());
|
||||||
|
addItemToBag(gridY, 0, 0, VERTICAL_GAP, commentLabel);
|
||||||
|
javax.swing.JTextArea commentValue = new javax.swing.JTextArea();
|
||||||
|
commentValue.setText(comment);
|
||||||
|
commentValue.setEditable(false);
|
||||||
|
commentValue.setColumns(20);
|
||||||
|
commentValue.setLineWrap(true);
|
||||||
|
commentValue.setRows(3);
|
||||||
|
commentValue.setTabSize(4);
|
||||||
|
commentValue.setWrapStyleWord(true);
|
||||||
|
commentValue.setBorder(javax.swing.BorderFactory.createEtchedBorder());
|
||||||
|
commentValue.setBackground(javax.swing.UIManager.getDefaults().getColor("TextArea.disabledBackground"));
|
||||||
|
addItemToBag(gridY, 1, 0, VERTICAL_GAP, commentValue);
|
||||||
|
gridY++;
|
||||||
|
}
|
||||||
|
String caseDate = "";
|
||||||
|
try {
|
||||||
|
OtherOccurrenceNodeInstanceData nodeData = ((OtherOccurrenceNodeInstanceData) occurrence);
|
||||||
|
if (nodeData.isCentralRepoNode()) {
|
||||||
|
if (EamDb.isEnabled()) {
|
||||||
|
CorrelationCase partialCase = nodeData.getCorrelationAttributeInstance().getCorrelationCase();
|
||||||
|
caseDate = EamDb.getInstance().getCaseByUUID(partialCase.getCaseUUID()).getCreationDate();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
caseDate = Case.getCurrentCase().getCreatedDate();
|
||||||
|
}
|
||||||
|
} catch (EamDbException ex) {
|
||||||
|
LOGGER.log(Level.WARNING, "Error getting case created date for other occurrence content viewer", ex);
|
||||||
|
}
|
||||||
|
//Collect the data that is necessary for the other sections
|
||||||
|
caseNamesAndDates.put(((OtherOccurrenceNodeInstanceData) occurrence).getCaseName(), caseDate);
|
||||||
|
dataSourceNames.add(((OtherOccurrenceNodeInstanceData) occurrence).getDataSourceName());
|
||||||
|
filePaths.add(((OtherOccurrenceNodeInstanceData) occurrence).getFilePath());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//end for each
|
||||||
|
}
|
||||||
|
|
||||||
|
@Messages({
|
||||||
|
"OccurrencePanel.fileDetails.text=File Details",
|
||||||
|
"OccurrencePanel.filePathLabel.text=File Path:"
|
||||||
|
})
|
||||||
|
/**
|
||||||
|
* Add the File specific details such as file path to the gridbaglayout
|
||||||
|
*/
|
||||||
|
private void addFileDetails() {
|
||||||
|
String filePath = filePaths.size() > 1 ? "" : filePaths.iterator().next();
|
||||||
|
if (!filePath.isEmpty()) {
|
||||||
|
javax.swing.JLabel fileDetailsLabel = new javax.swing.JLabel();
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(fileDetailsLabel, Bundle.OccurrencePanel_fileDetails_text());
|
||||||
|
fileDetailsLabel.setFont(fileDetailsLabel.getFont().deriveFont(Font.BOLD, fileDetailsLabel.getFont().getSize()));
|
||||||
|
addItemToBag(gridY, 0, TOP_INSET, 0, fileDetailsLabel);
|
||||||
|
gridY++;
|
||||||
|
javax.swing.JLabel filePathLabel = new javax.swing.JLabel();
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(filePathLabel, Bundle.OccurrencePanel_filePathLabel_text());
|
||||||
|
addItemToBag(gridY, 0, VERTICAL_GAP, VERTICAL_GAP, filePathLabel);
|
||||||
|
javax.swing.JTextArea filePathValue = new javax.swing.JTextArea();
|
||||||
|
filePathValue.setText(filePath);
|
||||||
|
filePathValue.setEditable(false);
|
||||||
|
filePathValue.setColumns(20);
|
||||||
|
filePathValue.setLineWrap(true);
|
||||||
|
filePathValue.setRows(3);
|
||||||
|
filePathValue.setTabSize(4);
|
||||||
|
filePathValue.setWrapStyleWord(true);
|
||||||
|
filePathValue.setBorder(javax.swing.BorderFactory.createEtchedBorder());
|
||||||
|
filePathValue.setBackground(javax.swing.UIManager.getDefaults().getColor("TextArea.disabledBackground"));
|
||||||
|
addItemToBag(gridY, 1, VERTICAL_GAP, VERTICAL_GAP, filePathValue);
|
||||||
|
gridY++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Messages({
|
||||||
|
"OccurrencePanel.dataSourceDetails.text=Data Source Details",
|
||||||
|
"OccurrencePanel.dataSourceNameLabel.text=Name:"
|
||||||
|
})
|
||||||
|
/**
|
||||||
|
* Add the data source specific details such as data source name to the
|
||||||
|
* gridbaglayout
|
||||||
|
*/
|
||||||
|
private void addDataSourceDetails() {
|
||||||
|
String dataSourceName = dataSourceNames.size() > 1 ? "" : dataSourceNames.iterator().next();
|
||||||
|
if (!dataSourceName.isEmpty()) {
|
||||||
|
javax.swing.JLabel dataSourceDetailsLabel = new javax.swing.JLabel();
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(dataSourceDetailsLabel, Bundle.OccurrencePanel_dataSourceDetails_text());
|
||||||
|
dataSourceDetailsLabel.setFont(dataSourceDetailsLabel.getFont().deriveFont(Font.BOLD, dataSourceDetailsLabel.getFont().getSize()));
|
||||||
|
addItemToBag(gridY, 0, TOP_INSET, 0, dataSourceDetailsLabel);
|
||||||
|
gridY++;
|
||||||
|
javax.swing.JLabel dataSourceNameLabel = new javax.swing.JLabel();
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(dataSourceNameLabel, Bundle.OccurrencePanel_dataSourceNameLabel_text());
|
||||||
|
addItemToBag(gridY, 0, VERTICAL_GAP, VERTICAL_GAP, dataSourceNameLabel);
|
||||||
|
javax.swing.JLabel dataSourceNameValue = new javax.swing.JLabel();
|
||||||
|
dataSourceNameValue.setText(dataSourceName);
|
||||||
|
addItemToBag(gridY, 1, VERTICAL_GAP, VERTICAL_GAP, dataSourceNameValue);
|
||||||
|
gridY++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Messages({
|
||||||
|
"OccurrencePanel.caseDetails.text=Case Details",
|
||||||
|
"OccurrencePanel.caseNameLabel.text=Name:",
|
||||||
|
"OccurrencePanel.caseCreatedDateLabel.text=Created Date:"
|
||||||
|
})
|
||||||
|
/**
|
||||||
|
* Add the case specific details such as case name to the gridbaglayout
|
||||||
|
*/
|
||||||
|
private void addCaseDetails() {
|
||||||
|
javax.swing.JLabel caseDetailsLabel = new javax.swing.JLabel();
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(caseDetailsLabel, Bundle.OccurrencePanel_caseDetails_text());
|
||||||
|
caseDetailsLabel.setFont(caseDetailsLabel.getFont().deriveFont(Font.BOLD, caseDetailsLabel.getFont().getSize()));
|
||||||
|
addItemToBag(gridY, 0, TOP_INSET, 0, caseDetailsLabel);
|
||||||
|
gridY++;
|
||||||
|
String caseName = caseNamesAndDates.keySet().size() > 1 ? "" : caseNamesAndDates.keySet().iterator().next();
|
||||||
|
if (!caseName.isEmpty()) {
|
||||||
|
javax.swing.JLabel caseNameLabel = new javax.swing.JLabel();
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(caseNameLabel, Bundle.OccurrencePanel_caseNameLabel_text());
|
||||||
|
addItemToBag(gridY, 0, VERTICAL_GAP, 0, caseNameLabel);
|
||||||
|
javax.swing.JLabel caseNameValue = new javax.swing.JLabel();
|
||||||
|
caseNameValue.setText(caseName);
|
||||||
|
addItemToBag(gridY, 1, VERTICAL_GAP, 0, caseNameValue);
|
||||||
|
gridY++;
|
||||||
|
}
|
||||||
|
String caseCreatedDate = caseNamesAndDates.keySet().size() > 1 ? "" : caseNamesAndDates.get(caseName);
|
||||||
|
if (caseCreatedDate != null && !caseCreatedDate.isEmpty()) {
|
||||||
|
javax.swing.JLabel caseCreatedLabel = new javax.swing.JLabel();
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(caseCreatedLabel, Bundle.OccurrencePanel_caseCreatedDateLabel_text());
|
||||||
|
addItemToBag(gridY, 0, 0, BOTTOM_INSET, caseCreatedLabel);
|
||||||
|
javax.swing.JLabel caseCreatedValue = new javax.swing.JLabel();
|
||||||
|
caseCreatedValue.setText(caseCreatedDate);
|
||||||
|
addItemToBag(gridY, 1, 0, BOTTOM_INSET, caseCreatedValue);
|
||||||
|
gridY++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a JComponent to the gridbaglayout
|
||||||
|
*
|
||||||
|
* @param gridYLocation the row number the item should be added at
|
||||||
|
* @param gridXLocation the column number the item should be added at
|
||||||
|
* @param topInset the gap from the top of the cell which should exist
|
||||||
|
* @param bottomInset the gap from the bottom of the cell which should
|
||||||
|
* exist
|
||||||
|
* @param item the JComponent to add to the gridbaglayout
|
||||||
|
*/
|
||||||
|
private void addItemToBag(int gridYLocation, int gridXLocation, int topInset, int bottomInset, javax.swing.JComponent item) {
|
||||||
|
java.awt.GridBagConstraints gridBagConstraints;
|
||||||
|
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||||
|
gridBagConstraints.gridx = gridXLocation;
|
||||||
|
gridBagConstraints.gridy = gridYLocation;
|
||||||
|
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
|
||||||
|
gridBagConstraints.anchor = java.awt.GridBagConstraints.FIRST_LINE_START;
|
||||||
|
int leftInset = LEFT_INSET;
|
||||||
|
int rightInset = HORIZONTAL_GAP;
|
||||||
|
//change formating a bit if it is the value instead of the label
|
||||||
|
if (gridXLocation == 1) {
|
||||||
|
leftInset = 0;
|
||||||
|
rightInset = RIGHT_INSET;
|
||||||
|
gridBagConstraints.weightx = 0.1;
|
||||||
|
gridBagConstraints.gridwidth = 2;
|
||||||
|
}
|
||||||
|
gridBagConstraints.insets = new java.awt.Insets(topInset, leftInset, bottomInset, rightInset);
|
||||||
|
//if the item is a filler item ensure it will resize vertically
|
||||||
|
if (item instanceof javax.swing.Box.Filler) {
|
||||||
|
gridBagConstraints.weighty = 0.1;
|
||||||
|
}
|
||||||
|
add(item, gridBagConstraints);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is called from within the constructor to initialize the form.
|
||||||
|
* WARNING: Do NOT modify this code. The content of this method is always
|
||||||
|
* regenerated by the Form Editor.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||||
|
private void initComponents() {
|
||||||
|
|
||||||
|
setMinimumSize(new java.awt.Dimension(50, 30));
|
||||||
|
setPreferredSize(null);
|
||||||
|
setLayout(new java.awt.GridBagLayout());
|
||||||
|
}// </editor-fold>//GEN-END:initComponents
|
||||||
|
|
||||||
|
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||||
|
// End of variables declaration//GEN-END:variables
|
||||||
|
}
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Central Repository
|
* Central Repository
|
||||||
*
|
*
|
||||||
* Copyright 2018 Basis Technology Corp.
|
* Copyright 2018-2019 Basis Technology Corp.
|
||||||
* Contact: carrier <at> sleuthkit <dot> org
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -31,11 +31,12 @@ import org.sleuthkit.datamodel.TskDataException;
|
|||||||
* Class for populating the Other Occurrences tab
|
* Class for populating the Other Occurrences tab
|
||||||
*/
|
*/
|
||||||
class OtherOccurrenceNodeInstanceData implements OtherOccurrenceNodeData {
|
class OtherOccurrenceNodeInstanceData implements OtherOccurrenceNodeData {
|
||||||
|
|
||||||
// For now hard code the string for the central repo files type, since
|
// For now hard code the string for the central repo files type, since
|
||||||
// getting it dynamically can fail.
|
// getting it dynamically can fail.
|
||||||
private static final String FILE_TYPE_STR = "Files";
|
private static final String FILE_TYPE_STR = "Files";
|
||||||
|
private static final String CSV_ITEM_SEPARATOR = "\",\"";
|
||||||
|
|
||||||
private final String caseName;
|
private final String caseName;
|
||||||
private String deviceID;
|
private String deviceID;
|
||||||
private String dataSourceName;
|
private String dataSourceName;
|
||||||
@ -44,12 +45,13 @@ class OtherOccurrenceNodeInstanceData implements OtherOccurrenceNodeData {
|
|||||||
private final String value;
|
private final String value;
|
||||||
private TskData.FileKnown known;
|
private TskData.FileKnown known;
|
||||||
private String comment;
|
private String comment;
|
||||||
|
|
||||||
private AbstractFile originalAbstractFile = null;
|
private AbstractFile originalAbstractFile = null;
|
||||||
private CorrelationAttributeInstance originalCorrelationInstance = null;
|
private CorrelationAttributeInstance originalCorrelationInstance = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a node from a central repo instance.
|
* Create a node from a central repo instance.
|
||||||
|
*
|
||||||
* @param instance The central repo instance
|
* @param instance The central repo instance
|
||||||
* @param type The type of the instance
|
* @param type The type of the instance
|
||||||
* @param value The value of the instance
|
* @param value The value of the instance
|
||||||
@ -63,15 +65,17 @@ class OtherOccurrenceNodeInstanceData implements OtherOccurrenceNodeData {
|
|||||||
this.value = value;
|
this.value = value;
|
||||||
known = instance.getKnownStatus();
|
known = instance.getKnownStatus();
|
||||||
comment = instance.getComment();
|
comment = instance.getComment();
|
||||||
|
|
||||||
originalCorrelationInstance = instance;
|
originalCorrelationInstance = instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a node from an abstract file.
|
* Create a node from an abstract file.
|
||||||
|
*
|
||||||
* @param newFile The abstract file
|
* @param newFile The abstract file
|
||||||
* @param autopsyCase The current case
|
* @param autopsyCase The current case
|
||||||
* @throws EamDbException
|
*
|
||||||
|
* @throws EamDbException
|
||||||
*/
|
*/
|
||||||
OtherOccurrenceNodeInstanceData(AbstractFile newFile, Case autopsyCase) throws EamDbException {
|
OtherOccurrenceNodeInstanceData(AbstractFile newFile, Case autopsyCase) throws EamDbException {
|
||||||
caseName = autopsyCase.getDisplayName();
|
caseName = autopsyCase.getDisplayName();
|
||||||
@ -82,115 +86,129 @@ class OtherOccurrenceNodeInstanceData implements OtherOccurrenceNodeData {
|
|||||||
} catch (TskDataException | TskCoreException ex) {
|
} catch (TskDataException | TskCoreException ex) {
|
||||||
throw new EamDbException("Error loading data source for abstract file ID " + newFile.getId(), ex);
|
throw new EamDbException("Error loading data source for abstract file ID " + newFile.getId(), ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
filePath = newFile.getParentPath() + newFile.getName();
|
filePath = newFile.getParentPath() + newFile.getName();
|
||||||
typeStr = FILE_TYPE_STR;
|
typeStr = FILE_TYPE_STR;
|
||||||
value = newFile.getMd5Hash();
|
value = newFile.getMd5Hash();
|
||||||
known = newFile.getKnown();
|
known = newFile.getKnown();
|
||||||
comment = "";
|
comment = "";
|
||||||
|
|
||||||
originalAbstractFile = newFile;
|
originalAbstractFile = newFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if this node is a "file" type
|
* Check if this node is a "file" type
|
||||||
|
*
|
||||||
* @return true if it is a file type
|
* @return true if it is a file type
|
||||||
*/
|
*/
|
||||||
boolean isFileType() {
|
boolean isFileType() {
|
||||||
return FILE_TYPE_STR.equals(typeStr);
|
return FILE_TYPE_STR.equals(typeStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the known status for this node
|
* Update the known status for this node
|
||||||
|
*
|
||||||
* @param newKnownStatus The new known status
|
* @param newKnownStatus The new known status
|
||||||
*/
|
*/
|
||||||
void updateKnown(TskData.FileKnown newKnownStatus) {
|
void updateKnown(TskData.FileKnown newKnownStatus) {
|
||||||
known = newKnownStatus;
|
known = newKnownStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the comment for this node
|
* Update the comment for this node
|
||||||
|
*
|
||||||
* @param newComment The new comment
|
* @param newComment The new comment
|
||||||
*/
|
*/
|
||||||
void updateComment(String newComment) {
|
void updateComment(String newComment) {
|
||||||
comment = newComment;
|
comment = newComment;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if this is a central repo node.
|
* Check if this is a central repo node.
|
||||||
* @return true if this node was created from a central repo instance, false otherwise
|
*
|
||||||
|
* @return true if this node was created from a central repo instance, false
|
||||||
|
* otherwise
|
||||||
*/
|
*/
|
||||||
boolean isCentralRepoNode() {
|
boolean isCentralRepoNode() {
|
||||||
return (originalCorrelationInstance != null);
|
return (originalCorrelationInstance != null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the case name
|
* Get the case name
|
||||||
|
*
|
||||||
* @return the case name
|
* @return the case name
|
||||||
*/
|
*/
|
||||||
String getCaseName() {
|
String getCaseName() {
|
||||||
return caseName;
|
return caseName;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the device ID
|
* Get the device ID
|
||||||
|
*
|
||||||
* @return the device ID
|
* @return the device ID
|
||||||
*/
|
*/
|
||||||
String getDeviceID() {
|
String getDeviceID() {
|
||||||
return deviceID;
|
return deviceID;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the data source name
|
* Get the data source name
|
||||||
|
*
|
||||||
* @return the data source name
|
* @return the data source name
|
||||||
*/
|
*/
|
||||||
String getDataSourceName() {
|
String getDataSourceName() {
|
||||||
return dataSourceName;
|
return dataSourceName;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the file path
|
* Get the file path
|
||||||
|
*
|
||||||
* @return the file path
|
* @return the file path
|
||||||
*/
|
*/
|
||||||
String getFilePath() {
|
String getFilePath() {
|
||||||
return filePath;
|
return filePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the type (as a string)
|
* Get the type (as a string)
|
||||||
|
*
|
||||||
* @return the type
|
* @return the type
|
||||||
*/
|
*/
|
||||||
String getType() {
|
String getType() {
|
||||||
return typeStr;
|
return typeStr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the value (MD5 hash for files)
|
* Get the value (MD5 hash for files)
|
||||||
|
*
|
||||||
* @return the value
|
* @return the value
|
||||||
*/
|
*/
|
||||||
String getValue() {
|
String getValue() {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the known status
|
* Get the known status
|
||||||
|
*
|
||||||
* @return the known status
|
* @return the known status
|
||||||
*/
|
*/
|
||||||
TskData.FileKnown getKnown() {
|
TskData.FileKnown getKnown() {
|
||||||
return known;
|
return known;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the comment
|
* Get the comment
|
||||||
|
*
|
||||||
* @return the comment
|
* @return the comment
|
||||||
*/
|
*/
|
||||||
String getComment() {
|
String getComment() {
|
||||||
return comment;
|
return comment;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the backing abstract file.
|
* Get the backing abstract file. Should only be called if
|
||||||
* Should only be called if isCentralRepoNode() is false
|
* isCentralRepoNode() is false
|
||||||
|
*
|
||||||
* @return the original abstract file
|
* @return the original abstract file
|
||||||
*/
|
*/
|
||||||
AbstractFile getAbstractFile() throws EamDbException {
|
AbstractFile getAbstractFile() throws EamDbException {
|
||||||
@ -199,12 +217,14 @@ class OtherOccurrenceNodeInstanceData implements OtherOccurrenceNodeData {
|
|||||||
}
|
}
|
||||||
return originalAbstractFile;
|
return originalAbstractFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the backing CorrelationAttributeInstance.
|
* Get the backing CorrelationAttributeInstance. Should only be called if
|
||||||
* Should only be called if isCentralRepoNode() is true
|
* isCentralRepoNode() is true
|
||||||
|
*
|
||||||
* @return the original CorrelationAttributeInstance
|
* @return the original CorrelationAttributeInstance
|
||||||
* @throws EamDbException
|
*
|
||||||
|
* @throws EamDbException
|
||||||
*/
|
*/
|
||||||
CorrelationAttributeInstance getCorrelationAttributeInstance() throws EamDbException {
|
CorrelationAttributeInstance getCorrelationAttributeInstance() throws EamDbException {
|
||||||
if (originalCorrelationInstance == null) {
|
if (originalCorrelationInstance == null) {
|
||||||
@ -212,4 +232,33 @@ class OtherOccurrenceNodeInstanceData implements OtherOccurrenceNodeData {
|
|||||||
}
|
}
|
||||||
return originalCorrelationInstance;
|
return originalCorrelationInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the string to append between elements when writing the node instance
|
||||||
|
* data to a CSV
|
||||||
|
*
|
||||||
|
* @return the CSV_ITEM_SEPARATOR string
|
||||||
|
*/
|
||||||
|
static String getCsvItemSeparator() {
|
||||||
|
return CSV_ITEM_SEPARATOR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a string representation of the node's data comma separated with a
|
||||||
|
* line separator ending
|
||||||
|
*
|
||||||
|
* @return a comma separated string representation of the node's data
|
||||||
|
*/
|
||||||
|
String toCsvString() {
|
||||||
|
StringBuilder line = new StringBuilder("\"");
|
||||||
|
line.append(getCaseName()).append(CSV_ITEM_SEPARATOR)
|
||||||
|
.append(getDataSourceName()).append(CSV_ITEM_SEPARATOR)
|
||||||
|
.append(getType()).append(CSV_ITEM_SEPARATOR)
|
||||||
|
.append(getValue()).append(CSV_ITEM_SEPARATOR)
|
||||||
|
.append(getKnown().toString()).append(CSV_ITEM_SEPARATOR)
|
||||||
|
.append(getFilePath()).append(CSV_ITEM_SEPARATOR)
|
||||||
|
.append(getComment()).append('"')
|
||||||
|
.append(System.getProperty("line.separator"));
|
||||||
|
return line.toString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import javax.swing.table.AbstractTableModel;
|
import javax.swing.table.AbstractTableModel;
|
||||||
import org.openide.util.NbBundle.Messages;
|
import org.openide.util.NbBundle.Messages;
|
||||||
|
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationCase;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Model for cells in the cases section of the other occurrences data content
|
* Model for cells in the cases section of the other occurrences data content
|
||||||
@ -32,26 +33,16 @@ public class OtherOccurrencesCasesTableModel extends AbstractTableModel {
|
|||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
private final List<CorrelationCaseWrapper> correlationCaseList = new ArrayList<>();
|
private final List<CorrelationCaseWrapper> correlationCaseList = new ArrayList<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a table model for displaying case names
|
||||||
|
*/
|
||||||
OtherOccurrencesCasesTableModel() {
|
OtherOccurrencesCasesTableModel() {
|
||||||
|
// This constructor is intentionally empty.
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getColumnCount() {
|
public int getColumnCount() {
|
||||||
return TableColumns.values().length;
|
return 1;
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the preferred width that has been configured for this column.
|
|
||||||
*
|
|
||||||
* A value of 0 means that no preferred width has been defined for this
|
|
||||||
* column.
|
|
||||||
*
|
|
||||||
* @param colIdx Column index
|
|
||||||
*
|
|
||||||
* @return preferred column width >= 0
|
|
||||||
*/
|
|
||||||
public int getColumnPreferredWidth(int colIdx) {
|
|
||||||
return TableColumns.values()[colIdx].columnWidth();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -59,45 +50,43 @@ public class OtherOccurrencesCasesTableModel extends AbstractTableModel {
|
|||||||
return correlationCaseList.size();
|
return correlationCaseList.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Messages({"OtherOccurrencesCasesTableModel.case=Case",})
|
||||||
@Override
|
@Override
|
||||||
public String getColumnName(int colIdx) {
|
public String getColumnName(int colIdx) {
|
||||||
return TableColumns.values()[colIdx].columnName();
|
return Bundle.OtherOccurrencesCasesTableModel_case();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Messages({"OtherOccurrencesCasesTableModel.noData=No Data."})
|
||||||
@Override
|
@Override
|
||||||
public Object getValueAt(int rowIdx, int colIdx) {
|
public Object getValueAt(int rowIdx, int colIdx) {
|
||||||
if (0 == correlationCaseList.size()) {
|
//if anything would prevent this from working we will consider it no data for the sake of simplicity
|
||||||
|
if (correlationCaseList.isEmpty() || rowIdx < 0
|
||||||
|
|| rowIdx >= correlationCaseList.size()
|
||||||
|
|| correlationCaseList.get(rowIdx) == null
|
||||||
|
|| correlationCaseList.get(rowIdx).getMessage() == null
|
||||||
|
|| correlationCaseList.get(rowIdx).getMessage().isEmpty()) {
|
||||||
return Bundle.OtherOccurrencesCasesTableModel_noData();
|
return Bundle.OtherOccurrencesCasesTableModel_noData();
|
||||||
}
|
}
|
||||||
|
return correlationCaseList.get(rowIdx).getMessage();
|
||||||
CorrelationCaseWrapper caseWrapper = correlationCaseList.get(rowIdx);
|
|
||||||
TableColumns columnId = TableColumns.values()[colIdx];
|
|
||||||
return mapCorrelationCase(caseWrapper, columnId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Map a column ID to the value in that cell for correlation case wrapper.
|
* Get a correlation case for the selected index. Does not query the Central
|
||||||
|
* Repository so CorrelationCase will be partial missing CR case ID and
|
||||||
|
* other information that is stored in the CR.
|
||||||
*
|
*
|
||||||
* @param correlationCaseWrapper The correlation case wrapper
|
* @param rowIdx the row from the table model which corresponds to the case
|
||||||
* @param columnId The ID of the cell column.
|
|
||||||
*
|
*
|
||||||
* @return The value in the cell.
|
* @return CorrelationCase for the table item specified or null if no
|
||||||
|
* correlation could be found for any reason
|
||||||
*/
|
*/
|
||||||
@Messages({"OtherOccurrencesCasesTableModel.noData=No Data."})
|
CorrelationCase getCorrelationCase(int rowIdx) {
|
||||||
private Object mapCorrelationCase(CorrelationCaseWrapper correlationCaseWrapper, TableColumns columnId) {
|
//if anything would prevent this from working we will return null
|
||||||
String value = Bundle.OtherOccurrencesCasesTableModel_noData();
|
if (correlationCaseList.isEmpty() || rowIdx < 0
|
||||||
|
|| rowIdx >= correlationCaseList.size()
|
||||||
switch (columnId) {
|
|| correlationCaseList.get(rowIdx) == null) {
|
||||||
case CASE_NAME:
|
return null;
|
||||||
value = correlationCaseWrapper.getMessage();
|
|
||||||
break;
|
|
||||||
default: //Use default "No data" value.
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
Object getCorrelationCase(int rowIdx) {
|
|
||||||
return correlationCaseList.get(rowIdx).getCorrelationCase();
|
return correlationCaseList.get(rowIdx).getCorrelationCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,7 +96,7 @@ public class OtherOccurrencesCasesTableModel extends AbstractTableModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add one correlated instance object to the table
|
* Add one correlation case wrapper object to the table
|
||||||
*
|
*
|
||||||
* @param newCorrelationCaseWrapper data to add to the table
|
* @param newCorrelationCaseWrapper data to add to the table
|
||||||
*/
|
*/
|
||||||
@ -123,27 +112,4 @@ public class OtherOccurrencesCasesTableModel extends AbstractTableModel {
|
|||||||
correlationCaseList.clear();
|
correlationCaseList.clear();
|
||||||
fireTableDataChanged();
|
fireTableDataChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Messages({"OtherOccurrencesCasesTableModel.case=Case",})
|
|
||||||
enum TableColumns {
|
|
||||||
// Ordering here determines displayed column order in Content Viewer.
|
|
||||||
// If order is changed, update the CellRenderer to ensure correct row coloring.
|
|
||||||
CASE_NAME(Bundle.OtherOccurrencesCasesTableModel_case(), 100);
|
|
||||||
|
|
||||||
private final String columnName;
|
|
||||||
private final int columnWidth;
|
|
||||||
|
|
||||||
TableColumns(String columnName, int columnWidth) {
|
|
||||||
this.columnName = columnName;
|
|
||||||
this.columnWidth = columnWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String columnName() {
|
|
||||||
return columnName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int columnWidth() {
|
|
||||||
return columnWidth;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,206 @@
|
|||||||
|
/*
|
||||||
|
* Central Repository
|
||||||
|
*
|
||||||
|
* Copyright 2019 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.centralrepository.contentviewer;
|
||||||
|
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
|
import javax.swing.table.AbstractTableModel;
|
||||||
|
import org.openide.util.NbBundle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Model for cells in the data sources section of the other occurrences data
|
||||||
|
* content viewer
|
||||||
|
*/
|
||||||
|
final class OtherOccurrencesDataSourcesTableModel extends AbstractTableModel {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
private final Set<DataSourceColumnItem> dataSourceSet = new LinkedHashSet<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a table model for displaying data source names
|
||||||
|
*/
|
||||||
|
OtherOccurrencesDataSourcesTableModel() {
|
||||||
|
// This constructor is intentionally empty.
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getColumnCount() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getRowCount() {
|
||||||
|
return dataSourceSet.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NbBundle.Messages({"OtherOccurrencesDataSourcesTableModel.dataSourceName=Data Source Name",
|
||||||
|
"OtherOccurrencesDataSourcesTableModel.noData=No Data."})
|
||||||
|
@Override
|
||||||
|
public String getColumnName(int colIdx) {
|
||||||
|
return Bundle.OtherOccurrencesDataSourcesTableModel_dataSourceName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getValueAt(int rowIdx, int colIdx) {
|
||||||
|
//if anything would prevent this from working we will consider it no data for the sake of simplicity
|
||||||
|
if (dataSourceSet.isEmpty() || rowIdx < 0
|
||||||
|
|| rowIdx >= dataSourceSet.size()
|
||||||
|
|| !(dataSourceSet.toArray()[rowIdx] instanceof DataSourceColumnItem)) {
|
||||||
|
return Bundle.OtherOccurrencesDataSourcesTableModel_noData();
|
||||||
|
}
|
||||||
|
return ((DataSourceColumnItem) dataSourceSet.toArray()[rowIdx]).getDataSourceName();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the device id of the data source shown at the specified row index
|
||||||
|
*
|
||||||
|
* @param rowIdx the row index of the data source you want the device id for
|
||||||
|
*
|
||||||
|
* @return the device id of the specified data source or an empty string if
|
||||||
|
* a device id could not be retrieved
|
||||||
|
*/
|
||||||
|
String getDeviceIdForRow(int rowIdx) {
|
||||||
|
//if anything would prevent this from working we will return an empty string
|
||||||
|
if (dataSourceSet.isEmpty() || rowIdx < 0
|
||||||
|
|| rowIdx >= dataSourceSet.size()
|
||||||
|
|| !(dataSourceSet.toArray()[rowIdx] instanceof DataSourceColumnItem)) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return ((DataSourceColumnItem) dataSourceSet.toArray()[rowIdx]).getDeviceId();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the case name of the data source shown at the specified row index
|
||||||
|
*
|
||||||
|
* @param rowIdx the row index of the data source you want the case name for
|
||||||
|
*
|
||||||
|
* @return the case name of the specified data source or an empty string if
|
||||||
|
* a case name could not be retrieved
|
||||||
|
*/
|
||||||
|
String getCaseNameForRow(int rowIdx) {
|
||||||
|
//if anything would prevent this from working we will return an empty string
|
||||||
|
if (dataSourceSet.isEmpty() || rowIdx < 0
|
||||||
|
|| rowIdx >= dataSourceSet.size()
|
||||||
|
|| !(dataSourceSet.toArray()[rowIdx] instanceof DataSourceColumnItem)) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return ((DataSourceColumnItem) dataSourceSet.toArray()[rowIdx]).getCaseName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<String> getColumnClass(int colIdx) {
|
||||||
|
return String.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add data source information to the table of unique data sources
|
||||||
|
*
|
||||||
|
* @param newNodeData data to add to the table
|
||||||
|
*/
|
||||||
|
void addNodeData(OtherOccurrenceNodeData newNodeData) {
|
||||||
|
dataSourceSet.add(new DataSourceColumnItem((OtherOccurrenceNodeInstanceData) newNodeData));
|
||||||
|
fireTableDataChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear the node data table.
|
||||||
|
*/
|
||||||
|
void clearTable() {
|
||||||
|
dataSourceSet.clear();
|
||||||
|
fireTableDataChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Private class for storing data source information in a way that
|
||||||
|
* facilitates de-duping.
|
||||||
|
*/
|
||||||
|
private final class DataSourceColumnItem {
|
||||||
|
|
||||||
|
private final String caseName;
|
||||||
|
private final String deviceId;
|
||||||
|
private final String dataSourceName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a DataSourceColumnItem given an
|
||||||
|
* OtherOccurrenceNodeInstanceData object
|
||||||
|
*
|
||||||
|
* @param nodeData the OtherOccurrenceNodeInstanceData which contains
|
||||||
|
* the data source information
|
||||||
|
*/
|
||||||
|
private DataSourceColumnItem(OtherOccurrenceNodeInstanceData nodeData) {
|
||||||
|
this(nodeData.getCaseName(), nodeData.getDeviceID(), nodeData.getDataSourceName());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a DataSourceColumnItem given a case name, device id, and data
|
||||||
|
* source name
|
||||||
|
*
|
||||||
|
* @param caseName the name of the case the data source exists in
|
||||||
|
* @param deviceId the name of the device id for the data source
|
||||||
|
* @param dataSourceName the name of the data source
|
||||||
|
*/
|
||||||
|
private DataSourceColumnItem(String caseName, String deviceId, String dataSourceName) {
|
||||||
|
this.caseName = caseName;
|
||||||
|
this.deviceId = deviceId;
|
||||||
|
this.dataSourceName = dataSourceName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the device id
|
||||||
|
*
|
||||||
|
* @return the data source's device id
|
||||||
|
*/
|
||||||
|
private String getDeviceId() {
|
||||||
|
return deviceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the data source name
|
||||||
|
*
|
||||||
|
* @return the data source's name
|
||||||
|
*/
|
||||||
|
private String getDataSourceName() {
|
||||||
|
return dataSourceName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the name of the case the data source exists in
|
||||||
|
*
|
||||||
|
* @return the name of the case the data source is in
|
||||||
|
*/
|
||||||
|
private String getCaseName() {
|
||||||
|
return caseName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object other) {
|
||||||
|
return other instanceof DataSourceColumnItem
|
||||||
|
&& caseName.equals(((DataSourceColumnItem) other).getCaseName())
|
||||||
|
&& dataSourceName.equals(((DataSourceColumnItem) other).getDataSourceName())
|
||||||
|
&& deviceId.equals(((DataSourceColumnItem) other).getDeviceId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(caseName, deviceId, dataSourceName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,69 +0,0 @@
|
|||||||
/*
|
|
||||||
* Central Repository
|
|
||||||
*
|
|
||||||
* Copyright 2015-2019 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.centralrepository.contentviewer;
|
|
||||||
|
|
||||||
import java.awt.Color;
|
|
||||||
import java.awt.Component;
|
|
||||||
import javax.swing.JComponent;
|
|
||||||
import javax.swing.JTable;
|
|
||||||
import javax.swing.table.DefaultTableCellRenderer;
|
|
||||||
import javax.swing.table.TableCellRenderer;
|
|
||||||
import org.sleuthkit.datamodel.TskData;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Renderer for cells in the files section of the other occurrences data content viewer
|
|
||||||
*/
|
|
||||||
public class OtherOccurrencesFilesTableCellRenderer implements TableCellRenderer {
|
|
||||||
|
|
||||||
public static final DefaultTableCellRenderer DEFAULT_RENDERER = new DefaultTableCellRenderer();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Component getTableCellRendererComponent(
|
|
||||||
JTable table,
|
|
||||||
Object value,
|
|
||||||
boolean isSelected,
|
|
||||||
boolean hasFocus,
|
|
||||||
int row,
|
|
||||||
int column) {
|
|
||||||
Component renderer = DEFAULT_RENDERER.getTableCellRendererComponent(
|
|
||||||
table, value, isSelected, hasFocus, row, column);
|
|
||||||
((JComponent) renderer).setOpaque(true);
|
|
||||||
Color foreground, background;
|
|
||||||
if (isSelected) {
|
|
||||||
foreground = Color.WHITE;
|
|
||||||
background = new Color(51,153,255);
|
|
||||||
} else {
|
|
||||||
String known_status = (String) table.getModel().getValueAt(table.convertRowIndexToModel(row),
|
|
||||||
table.getColumn(OtherOccurrencesFilesTableModel.TableColumns.KNOWN.columnName()).getModelIndex());
|
|
||||||
if (known_status.equals(TskData.FileKnown.BAD.getName())) {
|
|
||||||
foreground = Color.WHITE;
|
|
||||||
background = Color.RED;
|
|
||||||
} else if (known_status.equals(TskData.FileKnown.UNKNOWN.getName())) {
|
|
||||||
foreground = Color.BLACK;
|
|
||||||
background = Color.WHITE;
|
|
||||||
} else {
|
|
||||||
foreground = Color.BLACK;
|
|
||||||
background = Color.WHITE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
renderer.setForeground(foreground);
|
|
||||||
renderer.setBackground(background);
|
|
||||||
return renderer;
|
|
||||||
}
|
|
||||||
}
|
|
@ -19,150 +19,76 @@
|
|||||||
package org.sleuthkit.autopsy.centralrepository.contentviewer;
|
package org.sleuthkit.autopsy.centralrepository.contentviewer;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import javax.swing.table.AbstractTableModel;
|
import javax.swing.table.AbstractTableModel;
|
||||||
import org.openide.util.NbBundle.Messages;
|
import org.openide.util.NbBundle.Messages;
|
||||||
|
import org.apache.commons.io.FilenameUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Model for cells in the files section of the other occurrences data content viewer
|
* Model for cells in the files section of the other occurrences data content
|
||||||
|
* viewer
|
||||||
*/
|
*/
|
||||||
public class OtherOccurrencesFilesTableModel extends AbstractTableModel {
|
public class OtherOccurrencesFilesTableModel extends AbstractTableModel {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
private final List<String> nodeKeys = new ArrayList<>();
|
||||||
|
private final Map<String, List<OtherOccurrenceNodeData>> nodeMap = new HashMap<>();
|
||||||
|
|
||||||
@Messages({"OtherOccurrencesFilesTableModel.device=Device",
|
/**
|
||||||
"OtherOccurrencesFilesTableModel.dataSource=Data Source",
|
* Create a table model for displaying file names
|
||||||
"OtherOccurrencesFilesTableModel.path=Path",
|
*/
|
||||||
"OtherOccurrencesFilesTableModel.attribute=Matched Attribute",
|
|
||||||
"OtherOccurrencesFilesTableModel.value=Attribute Value",
|
|
||||||
"OtherOccurrencesFilesTableModel.known=Known",
|
|
||||||
"OtherOccurrencesFilesTableModel.comment=Comment",
|
|
||||||
"OtherOccurrencesFilesTableModel.noData=No Data.",})
|
|
||||||
enum TableColumns {
|
|
||||||
// Ordering here determines displayed column order in Content Viewer.
|
|
||||||
// If order is changed, update the CellRenderer to ensure correct row coloring.
|
|
||||||
ATTRIBUTE(Bundle.OtherOccurrencesFilesTableModel_attribute(), 75),
|
|
||||||
VALUE(Bundle.OtherOccurrencesFilesTableModel_value(), 190),
|
|
||||||
KNOWN(Bundle.OtherOccurrencesFilesTableModel_known(), 25),
|
|
||||||
FILE_PATH(Bundle.OtherOccurrencesFilesTableModel_path(), 470),
|
|
||||||
COMMENT(Bundle.OtherOccurrencesFilesTableModel_comment(), 190);
|
|
||||||
|
|
||||||
private final String columnName;
|
|
||||||
private final int columnWidth;
|
|
||||||
|
|
||||||
TableColumns(String columnName, int columnWidth) {
|
|
||||||
this.columnName = columnName;
|
|
||||||
this.columnWidth = columnWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String columnName() {
|
|
||||||
return columnName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int columnWidth() {
|
|
||||||
return columnWidth;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private final List<OtherOccurrenceNodeData> nodeDataList = new ArrayList<>();
|
|
||||||
|
|
||||||
OtherOccurrencesFilesTableModel() {
|
OtherOccurrencesFilesTableModel() {
|
||||||
|
// This constructor is intentionally empty.
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getColumnCount() {
|
public int getColumnCount() {
|
||||||
return TableColumns.values().length;
|
return 1;
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the preferred width that has been configured for this column.
|
|
||||||
*
|
|
||||||
* A value of 0 means that no preferred width has been defined for this
|
|
||||||
* column.
|
|
||||||
*
|
|
||||||
* @param colIdx Column index
|
|
||||||
*
|
|
||||||
* @return preferred column width >= 0
|
|
||||||
*/
|
|
||||||
public int getColumnPreferredWidth(int colIdx) {
|
|
||||||
return TableColumns.values()[colIdx].columnWidth();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getRowCount() {
|
public int getRowCount() {
|
||||||
return nodeDataList.size();
|
return nodeKeys.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Messages({"OtherOccurrencesFilesTableModel.fileName=File Name",
|
||||||
|
"OtherOccurrencesFilesTableModel.noData=No Data."})
|
||||||
@Override
|
@Override
|
||||||
public String getColumnName(int colIdx) {
|
public String getColumnName(int colIdx) {
|
||||||
return TableColumns.values()[colIdx].columnName();
|
return Bundle.OtherOccurrencesFilesTableModel_fileName();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object getValueAt(int rowIdx, int colIdx) {
|
public Object getValueAt(int rowIdx, int colIdx) {
|
||||||
if (0 == nodeDataList.size()) {
|
//if anything would prevent this from working we will consider it no data for the sake of simplicity
|
||||||
|
if (nodeMap.isEmpty() || nodeKeys.isEmpty() || rowIdx < 0
|
||||||
|
|| rowIdx >= nodeKeys.size() || nodeKeys.get(rowIdx) == null
|
||||||
|
|| nodeMap.get(nodeKeys.get(rowIdx)) == null
|
||||||
|
|| nodeMap.get(nodeKeys.get(rowIdx)).isEmpty()) {
|
||||||
return Bundle.OtherOccurrencesFilesTableModel_noData();
|
return Bundle.OtherOccurrencesFilesTableModel_noData();
|
||||||
}
|
}
|
||||||
|
return FilenameUtils.getName(((OtherOccurrenceNodeInstanceData) nodeMap.get(nodeKeys.get(rowIdx)).get(0)).getFilePath());
|
||||||
OtherOccurrenceNodeData nodeData = nodeDataList.get(rowIdx);
|
|
||||||
TableColumns columnId = TableColumns.values()[colIdx];
|
|
||||||
if (nodeData instanceof OtherOccurrenceNodeMessageData) {
|
|
||||||
return mapNodeMessageData((OtherOccurrenceNodeMessageData) nodeData, columnId);
|
|
||||||
}
|
|
||||||
return mapNodeInstanceData((OtherOccurrenceNodeInstanceData) nodeData, columnId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Map a column ID to the value in that cell for node message data.
|
* Get a list of OtherOccurrenceNodeData that exist for the file which
|
||||||
|
* corresponds to the Index
|
||||||
*
|
*
|
||||||
* @param nodeData The node message data.
|
* @param rowIdx the index of the file to get data for
|
||||||
* @param columnId The ID of the cell column.
|
|
||||||
*
|
*
|
||||||
* @return The value in the cell.
|
* @return a list of OtherOccurrenceNodeData for the specified index or an
|
||||||
|
* empty list if no data was found
|
||||||
*/
|
*/
|
||||||
private Object mapNodeMessageData(OtherOccurrenceNodeMessageData nodeData, TableColumns columnId) {
|
List<OtherOccurrenceNodeData> getListOfNodesForFile(int rowIdx) {
|
||||||
if (columnId == TableColumns.ATTRIBUTE) {
|
//if anything would prevent this from working return an empty list
|
||||||
return nodeData.getDisplayMessage();
|
if (nodeMap.isEmpty() || nodeKeys.isEmpty() || rowIdx < 0
|
||||||
|
|| rowIdx >= nodeKeys.size() || nodeKeys.get(rowIdx) == null
|
||||||
|
|| nodeMap.get(nodeKeys.get(rowIdx)) == null) {
|
||||||
|
return new ArrayList<>();
|
||||||
}
|
}
|
||||||
return "";
|
return nodeMap.get(nodeKeys.get(rowIdx));
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Map a column ID to the value in that cell for node instance data.
|
|
||||||
*
|
|
||||||
* @param nodeData The node instance data.
|
|
||||||
* @param columnId The ID of the cell column.
|
|
||||||
*
|
|
||||||
* @return The value in the cell.
|
|
||||||
*/
|
|
||||||
private Object mapNodeInstanceData(OtherOccurrenceNodeInstanceData nodeData, TableColumns columnId) {
|
|
||||||
String value = Bundle.OtherOccurrencesFilesTableModel_noData();
|
|
||||||
|
|
||||||
switch (columnId) {
|
|
||||||
case FILE_PATH:
|
|
||||||
value = nodeData.getFilePath();
|
|
||||||
break;
|
|
||||||
case ATTRIBUTE:
|
|
||||||
value = nodeData.getType();
|
|
||||||
break;
|
|
||||||
case VALUE:
|
|
||||||
value = nodeData.getValue();
|
|
||||||
break;
|
|
||||||
case KNOWN:
|
|
||||||
value = nodeData.getKnown().getName();
|
|
||||||
break;
|
|
||||||
case COMMENT:
|
|
||||||
value = nodeData.getComment();
|
|
||||||
break;
|
|
||||||
default: //Use default "No data" value.
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
Object getRow(int rowIdx) {
|
|
||||||
return nodeDataList.get(rowIdx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -176,15 +102,27 @@ public class OtherOccurrencesFilesTableModel extends AbstractTableModel {
|
|||||||
* @param newNodeData data to add to the table
|
* @param newNodeData data to add to the table
|
||||||
*/
|
*/
|
||||||
void addNodeData(OtherOccurrenceNodeData newNodeData) {
|
void addNodeData(OtherOccurrenceNodeData newNodeData) {
|
||||||
nodeDataList.add(newNodeData);
|
String newNodeKey = createNodeKey((OtherOccurrenceNodeInstanceData) newNodeData);//FilenameUtils.getName(((OtherOccurrenceNodeInstanceData)newNodeData).getFilePath());
|
||||||
|
List<OtherOccurrenceNodeData> nodeList = nodeMap.get(newNodeKey);
|
||||||
|
if (nodeList == null) {
|
||||||
|
nodeKeys.add(newNodeKey);
|
||||||
|
nodeList = new ArrayList<>();
|
||||||
|
}
|
||||||
|
nodeList.add(newNodeData);
|
||||||
|
nodeMap.put(newNodeKey, nodeList);
|
||||||
fireTableDataChanged();
|
fireTableDataChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String createNodeKey(OtherOccurrenceNodeInstanceData nodeData) {
|
||||||
|
return nodeData.getCaseName() + nodeData.getDataSourceName() + nodeData.getDeviceID() + nodeData.getFilePath();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clear the node data table.
|
* Clear the node data table.
|
||||||
*/
|
*/
|
||||||
void clearTable() {
|
void clearTable() {
|
||||||
nodeDataList.clear();
|
nodeKeys.clear();
|
||||||
|
nodeMap.clear();
|
||||||
fireTableDataChanged();
|
fireTableDataChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ public final class ContactDetailsPane extends javax.swing.JPanel implements Expl
|
|||||||
* @param nodes List of nodes to set
|
* @param nodes List of nodes to set
|
||||||
*/
|
*/
|
||||||
public void setNode(Node[] nodes) {
|
public void setNode(Node[] nodes) {
|
||||||
if (nodes != null) {
|
if (nodes != null && nodes.length > 0) {
|
||||||
nameLabel.setText(nodes[0].getDisplayName());
|
nameLabel.setText(nodes[0].getDisplayName());
|
||||||
} else {
|
} else {
|
||||||
nameLabel.setText("");
|
nameLabel.setText("");
|
||||||
|
@ -18,9 +18,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.communications;
|
package org.sleuthkit.autopsy.communications;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import org.openide.nodes.Sheet;
|
import org.openide.nodes.Sheet;
|
||||||
@ -31,16 +29,9 @@ import org.sleuthkit.autopsy.datamodel.NodeProperty;
|
|||||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||||
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT;
|
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT;
|
||||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||||
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL;
|
|
||||||
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME;
|
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME;
|
||||||
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME_PERSON;
|
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME_PERSON;
|
||||||
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER;
|
|
||||||
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_HOME;
|
|
||||||
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_MOBILE;
|
|
||||||
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_OFFICE;
|
|
||||||
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL;
|
|
||||||
import static org.sleuthkit.datamodel.BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.DATETIME;
|
import static org.sleuthkit.datamodel.BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.DATETIME;
|
||||||
import org.sleuthkit.datamodel.Content;
|
|
||||||
import org.sleuthkit.datamodel.TimeUtilities;
|
import org.sleuthkit.datamodel.TimeUtilities;
|
||||||
import org.sleuthkit.datamodel.TskCoreException;
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
|
|
||||||
|
@ -100,11 +100,7 @@ public final class ContactsViewer extends JPanel implements RelationshipsViewer,
|
|||||||
tableEM.addPropertyChangeListener((PropertyChangeEvent evt) -> {
|
tableEM.addPropertyChangeListener((PropertyChangeEvent evt) -> {
|
||||||
if (evt.getPropertyName().equals(ExplorerManager.PROP_SELECTED_NODES)) {
|
if (evt.getPropertyName().equals(ExplorerManager.PROP_SELECTED_NODES)) {
|
||||||
final Node[] nodes = tableEM.getSelectedNodes();
|
final Node[] nodes = tableEM.getSelectedNodes();
|
||||||
|
contactPane.setNode(nodes);
|
||||||
if (nodes != null && nodes.length > 0) {
|
|
||||||
contactPane.setEnabled(true);
|
|
||||||
contactPane.setNode(nodes);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -98,7 +98,6 @@ import org.apache.commons.lang3.StringUtils;
|
|||||||
import org.controlsfx.control.Notifications;
|
import org.controlsfx.control.Notifications;
|
||||||
import org.jdesktop.layout.GroupLayout;
|
import org.jdesktop.layout.GroupLayout;
|
||||||
import org.jdesktop.layout.LayoutStyle;
|
import org.jdesktop.layout.LayoutStyle;
|
||||||
import org.openide.util.Lookup;
|
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
import org.openide.windows.WindowManager;
|
import org.openide.windows.WindowManager;
|
||||||
import org.sleuthkit.autopsy.casemodule.Case;
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
|
@ -59,7 +59,7 @@
|
|||||||
</Property>
|
</Property>
|
||||||
</Properties>
|
</Properties>
|
||||||
<AuxValues>
|
<AuxValues>
|
||||||
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new BeanTreeView()"/>
|
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new ExpansionBeanTreeView()"/>
|
||||||
</AuxValues>
|
</AuxValues>
|
||||||
|
|
||||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2011-2019 Basis Technology Corp.
|
* Copyright 2012-2019 Basis Technology Corp.
|
||||||
* Contact: carrier <at> sleuthkit <dot> org
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -26,7 +26,6 @@ import java.beans.PropertyVetoException;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -47,6 +46,7 @@ import javax.swing.tree.TreeSelectionModel;
|
|||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.openide.explorer.ExplorerManager;
|
import org.openide.explorer.ExplorerManager;
|
||||||
import org.openide.explorer.ExplorerUtils;
|
import org.openide.explorer.ExplorerUtils;
|
||||||
|
import org.openide.explorer.view.BeanTreeView;
|
||||||
import org.openide.explorer.view.Visualizer;
|
import org.openide.explorer.view.Visualizer;
|
||||||
import org.openide.nodes.AbstractNode;
|
import org.openide.nodes.AbstractNode;
|
||||||
import org.openide.nodes.Children;
|
import org.openide.nodes.Children;
|
||||||
@ -128,7 +128,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
|||||||
getTree().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
|
getTree().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
|
||||||
//Hook into the JTree and pre-expand the Views Node and Results node when a user
|
//Hook into the JTree and pre-expand the Views Node and Results node when a user
|
||||||
//expands an item in the tree that makes these nodes visible.
|
//expands an item in the tree that makes these nodes visible.
|
||||||
getTree().addTreeExpansionListener(new TreeExpansionListener() {
|
((ExpansionBeanTreeView )getTree()).addTreeExpansionListener(new TreeExpansionListener() {
|
||||||
@Override
|
@Override
|
||||||
public void treeExpanded(TreeExpansionEvent event) {
|
public void treeExpanded(TreeExpansionEvent event) {
|
||||||
//Bail immediately if we are not in the Group By view.
|
//Bail immediately if we are not in the Group By view.
|
||||||
@ -192,7 +192,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
|||||||
* @param rootChildren Children node containing Results node and Views node.
|
* @param rootChildren Children node containing Results node and Views node.
|
||||||
*/
|
*/
|
||||||
private void preExpandNodes(Children rootChildren) {
|
private void preExpandNodes(Children rootChildren) {
|
||||||
ExpansionBeanTreeView tree = getTree();
|
BeanTreeView tree = getTree();
|
||||||
|
|
||||||
Node results = rootChildren.findChild(ResultsNode.NAME);
|
Node results = rootChildren.findChild(ResultsNode.NAME);
|
||||||
if (!Objects.isNull(results)) {
|
if (!Objects.isNull(results)) {
|
||||||
@ -930,8 +930,8 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
|||||||
*
|
*
|
||||||
* @return tree the BeanTreeView
|
* @return tree the BeanTreeView
|
||||||
*/
|
*/
|
||||||
public ExpansionBeanTreeView getTree() {
|
BeanTreeView getTree() {
|
||||||
return (ExpansionBeanTreeView) this.treeView;
|
return (BeanTreeView) this.treeView;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -24,7 +24,7 @@ import org.openide.explorer.view.BeanTreeView;
|
|||||||
/**
|
/**
|
||||||
* Adds the ability to listen to user-driven JTree expansion events.
|
* Adds the ability to listen to user-driven JTree expansion events.
|
||||||
*/
|
*/
|
||||||
class ExpansionBeanTreeView extends BeanTreeView {
|
final class ExpansionBeanTreeView extends BeanTreeView {
|
||||||
public void addTreeExpansionListener(TreeExpansionListener listener) {
|
public void addTreeExpansionListener(TreeExpansionListener listener) {
|
||||||
this.tree.addTreeExpansionListener(listener);
|
this.tree.addTreeExpansionListener(listener);
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@ FileReportDataTypes.knownStatus.text=Known Status
|
|||||||
FileReportDataTypes.perms.text=Permissions
|
FileReportDataTypes.perms.text=Permissions
|
||||||
FileReportDataTypes.path.text=Full Path
|
FileReportDataTypes.path.text=Full Path
|
||||||
FileReportText.getName.text=Files - Text
|
FileReportText.getName.text=Files - Text
|
||||||
FileReportText.getDesc.text=A tab delimited text file containing information about individual files in the case.
|
FileReportText.getDesc.text=A delimited text file containing information about individual files in the case.
|
||||||
ReportBodyFile.progress.querying=Querying files...
|
ReportBodyFile.progress.querying=Querying files...
|
||||||
ReportBodyFile.ingestWarning.text=Warning, this report was run before ingest services completed\!
|
ReportBodyFile.ingestWarning.text=Warning, this report was run before ingest services completed\!
|
||||||
ReportBodyFile.progress.loading=Loading files...
|
ReportBodyFile.progress.loading=Loading files...
|
||||||
@ -258,3 +258,5 @@ CreatePortableCasePanel.outputFolderTextField.text=jTextField1
|
|||||||
CreatePortableCasePanel.chooseOutputFolderButton.text=Choose folder
|
CreatePortableCasePanel.chooseOutputFolderButton.text=Choose folder
|
||||||
CreatePortableCasePanel.jLabel1.text=Export files tagged as:
|
CreatePortableCasePanel.jLabel1.text=Export files tagged as:
|
||||||
CreatePortableCasePanel.jLabel2.text=Select output folder:
|
CreatePortableCasePanel.jLabel2.text=Select output folder:
|
||||||
|
ReportFileTextConfigurationPanel.tabDelimitedButton.text=Tab delimited
|
||||||
|
ReportFileTextConfigurationPanel.commaDelimitedButton.text=Comma delimited
|
||||||
|
@ -85,7 +85,7 @@ FileReportDataTypes.knownStatus.text=Known Status
|
|||||||
FileReportDataTypes.perms.text=Permissions
|
FileReportDataTypes.perms.text=Permissions
|
||||||
FileReportDataTypes.path.text=Full Path
|
FileReportDataTypes.path.text=Full Path
|
||||||
FileReportText.getName.text=Files - Text
|
FileReportText.getName.text=Files - Text
|
||||||
FileReportText.getDesc.text=A tab delimited text file containing information about individual files in the case.
|
FileReportText.getDesc.text=A delimited text file containing information about individual files in the case.
|
||||||
ReportBodyFile.progress.querying=Querying files...
|
ReportBodyFile.progress.querying=Querying files...
|
||||||
ReportBodyFile.ingestWarning.text=Warning, this report was run before ingest services completed\!
|
ReportBodyFile.ingestWarning.text=Warning, this report was run before ingest services completed\!
|
||||||
ReportBodyFile.progress.loading=Loading files...
|
ReportBodyFile.progress.loading=Loading files...
|
||||||
@ -306,4 +306,6 @@ CreatePortableCasePanel.outputFolderTextField.text=jTextField1
|
|||||||
CreatePortableCasePanel.chooseOutputFolderButton.text=Choose folder
|
CreatePortableCasePanel.chooseOutputFolderButton.text=Choose folder
|
||||||
CreatePortableCasePanel.jLabel1.text=Export files tagged as:
|
CreatePortableCasePanel.jLabel1.text=Export files tagged as:
|
||||||
CreatePortableCasePanel.jLabel2.text=Select output folder:
|
CreatePortableCasePanel.jLabel2.text=Select output folder:
|
||||||
|
ReportFileTextConfigurationPanel.tabDelimitedButton.text=Tab delimited
|
||||||
|
ReportFileTextConfigurationPanel.commaDelimitedButton.text=Comma delimited
|
||||||
TableReportGenerator.StatusColumn.Header=Review Status
|
TableReportGenerator.StatusColumn.Header=Review Status
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2013 - 2018 Basis Technology Corp.
|
* Copyright 2013 - 2019 Basis Technology Corp.
|
||||||
* Contact: carrier <at> sleuthkit <dot> org
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -19,6 +19,7 @@
|
|||||||
package org.sleuthkit.autopsy.report;
|
package org.sleuthkit.autopsy.report;
|
||||||
|
|
||||||
import java.io.BufferedWriter;
|
import java.io.BufferedWriter;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStreamWriter;
|
import java.io.OutputStreamWriter;
|
||||||
@ -27,6 +28,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
import javax.swing.JPanel;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
|
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
@ -36,18 +38,18 @@ import org.sleuthkit.datamodel.AbstractFile;
|
|||||||
import org.sleuthkit.datamodel.TskCoreException;
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Tab-delimited text report of the files in the case.
|
* A delimited text report of the files in the case.
|
||||||
*
|
*
|
||||||
* @author jwallace
|
* @author jwallace
|
||||||
*/
|
*/
|
||||||
class FileReportText implements FileReportModule {
|
class FileReportText implements FileReportModule {
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(FileReportText.class.getName());
|
private static final Logger logger = Logger.getLogger(FileReportText.class.getName());
|
||||||
|
private static final String FILE_NAME = "file-report.txt"; //NON-NLS
|
||||||
|
private static FileReportText instance;
|
||||||
private String reportPath;
|
private String reportPath;
|
||||||
private Writer out;
|
private Writer out;
|
||||||
private static final String FILE_NAME = "file-report.txt"; //NON-NLS
|
private ReportFileTextConfigurationPanel configPanel;
|
||||||
|
|
||||||
private static FileReportText instance;
|
|
||||||
|
|
||||||
// Get the default implementation of this report
|
// Get the default implementation of this report
|
||||||
public static synchronized FileReportText getDefault() {
|
public static synchronized FileReportText getDefault() {
|
||||||
@ -62,7 +64,7 @@ class FileReportText implements FileReportModule {
|
|||||||
this.reportPath = baseReportDir + FILE_NAME;
|
this.reportPath = baseReportDir + FILE_NAME;
|
||||||
try {
|
try {
|
||||||
out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(this.reportPath)));
|
out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(this.reportPath)));
|
||||||
} catch (IOException ex) {
|
} catch (FileNotFoundException ex) {
|
||||||
logger.log(Level.WARNING, "Failed to create report text file", ex); //NON-NLS
|
logger.log(Level.WARNING, "Failed to create report text file", ex); //NON-NLS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -85,11 +87,12 @@ class FileReportText implements FileReportModule {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getTabDelimitedList(List<String> list) {
|
private String getDelimitedList(List<String> list, String delimiter) {
|
||||||
StringBuilder output = new StringBuilder();
|
StringBuilder output;
|
||||||
|
output = new StringBuilder();
|
||||||
Iterator<String> it = list.iterator();
|
Iterator<String> it = list.iterator();
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
output.append(it.next()).append((it.hasNext() ? "\t" : System.lineSeparator()));
|
output.append('"').append(it.next()).append('"').append((it.hasNext() ? delimiter : System.lineSeparator()));
|
||||||
}
|
}
|
||||||
return output.toString();
|
return output.toString();
|
||||||
}
|
}
|
||||||
@ -101,7 +104,7 @@ class FileReportText implements FileReportModule {
|
|||||||
titles.add(col.getName());
|
titles.add(col.getName());
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
out.write(getTabDelimitedList(titles));
|
out.write(getDelimitedList(titles, configPanel.getDelimiter()));
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
logger.log(Level.WARNING, "Error when writing headers to report file: {0}", ex); //NON-NLS
|
logger.log(Level.WARNING, "Error when writing headers to report file: {0}", ex); //NON-NLS
|
||||||
}
|
}
|
||||||
@ -114,7 +117,7 @@ class FileReportText implements FileReportModule {
|
|||||||
cells.add(type.getValue(toAdd));
|
cells.add(type.getValue(toAdd));
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
out.write(getTabDelimitedList(cells));
|
out.write(getDelimitedList(cells, configPanel.getDelimiter()));
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
logger.log(Level.WARNING, "Error when writing row to report file: {0}", ex); //NON-NLS
|
logger.log(Level.WARNING, "Error when writing row to report file: {0}", ex); //NON-NLS
|
||||||
}
|
}
|
||||||
@ -143,4 +146,12 @@ class FileReportText implements FileReportModule {
|
|||||||
public String getRelativeFilePath() {
|
public String getRelativeFilePath() {
|
||||||
return FILE_NAME;
|
return FILE_NAME;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JPanel getConfigurationPanel() {
|
||||||
|
if (configPanel == null) {
|
||||||
|
configPanel = new ReportFileTextConfigurationPanel();
|
||||||
|
}
|
||||||
|
return configPanel;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,68 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
|
||||||
|
<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
||||||
|
<NonVisualComponents>
|
||||||
|
<Component class="javax.swing.ButtonGroup" name="delimiterGroup">
|
||||||
|
</Component>
|
||||||
|
</NonVisualComponents>
|
||||||
|
<AuxValues>
|
||||||
|
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
|
||||||
|
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
|
||||||
|
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
|
||||||
|
<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"/>
|
||||||
|
</AuxValues>
|
||||||
|
|
||||||
|
<Layout>
|
||||||
|
<DimensionLayout dim="0">
|
||||||
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
|
<Group type="102" alignment="0" attributes="0">
|
||||||
|
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||||
|
<Component id="tabDelimitedButton" min="-2" pref="116" max="-2" attributes="0"/>
|
||||||
|
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||||
|
<Component id="commaDelimitedButton" min="-2" pref="133" max="-2" attributes="0"/>
|
||||||
|
<EmptySpace pref="166" max="32767" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
</Group>
|
||||||
|
</DimensionLayout>
|
||||||
|
<DimensionLayout dim="1">
|
||||||
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
|
<Group type="102" alignment="0" attributes="0">
|
||||||
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
|
<Group type="103" groupAlignment="3" attributes="0">
|
||||||
|
<Component id="tabDelimitedButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||||
|
<Component id="commaDelimitedButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
<EmptySpace pref="78" max="32767" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
</Group>
|
||||||
|
</DimensionLayout>
|
||||||
|
</Layout>
|
||||||
|
<SubComponents>
|
||||||
|
<Component class="javax.swing.JRadioButton" name="tabDelimitedButton">
|
||||||
|
<Properties>
|
||||||
|
<Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor">
|
||||||
|
<ComponentRef name="delimiterGroup"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="selected" type="boolean" value="true"/>
|
||||||
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="org/sleuthkit/autopsy/report/Bundle.properties" key="ReportFileTextConfigurationPanel.tabDelimitedButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
</Component>
|
||||||
|
<Component class="javax.swing.JRadioButton" name="commaDelimitedButton">
|
||||||
|
<Properties>
|
||||||
|
<Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor">
|
||||||
|
<ComponentRef name="delimiterGroup"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="org/sleuthkit/autopsy/report/Bundle.properties" key="ReportFileTextConfigurationPanel.commaDelimitedButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
</Component>
|
||||||
|
</SubComponents>
|
||||||
|
</Form>
|
@ -0,0 +1,99 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2019 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.report;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Panel for configuring settings for the file text report
|
||||||
|
*/
|
||||||
|
class ReportFileTextConfigurationPanel extends javax.swing.JPanel {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
private static final String TAB_DELIMITER = "\t"; //NON-NLS
|
||||||
|
private static final String COMMA_DELIMITER = ","; //NON-NLS
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates new form ReportFileTextConfigurationPanel
|
||||||
|
*/
|
||||||
|
ReportFileTextConfigurationPanel() {
|
||||||
|
initComponents();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the delimiter that was selected on this panel
|
||||||
|
*
|
||||||
|
* @return the selected delimiter
|
||||||
|
*/
|
||||||
|
String getDelimiter() {
|
||||||
|
if (commaDelimitedButton.isSelected()) {
|
||||||
|
return COMMA_DELIMITER;
|
||||||
|
} else {
|
||||||
|
//if the comma button is not selected default to tab since it was previously the only option
|
||||||
|
return TAB_DELIMITER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is called from within the constructor to initialize the form.
|
||||||
|
* WARNING: Do NOT modify this code. The content of this method is always
|
||||||
|
* regenerated by the Form Editor.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||||
|
private void initComponents() {
|
||||||
|
|
||||||
|
delimiterGroup = new javax.swing.ButtonGroup();
|
||||||
|
tabDelimitedButton = new javax.swing.JRadioButton();
|
||||||
|
commaDelimitedButton = new javax.swing.JRadioButton();
|
||||||
|
|
||||||
|
delimiterGroup.add(tabDelimitedButton);
|
||||||
|
tabDelimitedButton.setSelected(true);
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(tabDelimitedButton, org.openide.util.NbBundle.getMessage(ReportFileTextConfigurationPanel.class, "ReportFileTextConfigurationPanel.tabDelimitedButton.text")); // NOI18N
|
||||||
|
|
||||||
|
delimiterGroup.add(commaDelimitedButton);
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(commaDelimitedButton, org.openide.util.NbBundle.getMessage(ReportFileTextConfigurationPanel.class, "ReportFileTextConfigurationPanel.commaDelimitedButton.text")); // NOI18N
|
||||||
|
|
||||||
|
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
||||||
|
this.setLayout(layout);
|
||||||
|
layout.setHorizontalGroup(
|
||||||
|
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addGroup(layout.createSequentialGroup()
|
||||||
|
.addContainerGap()
|
||||||
|
.addComponent(tabDelimitedButton, javax.swing.GroupLayout.PREFERRED_SIZE, 116, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||||
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||||
|
.addComponent(commaDelimitedButton, javax.swing.GroupLayout.PREFERRED_SIZE, 133, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||||
|
.addContainerGap(166, Short.MAX_VALUE))
|
||||||
|
);
|
||||||
|
layout.setVerticalGroup(
|
||||||
|
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addGroup(layout.createSequentialGroup()
|
||||||
|
.addContainerGap()
|
||||||
|
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||||
|
.addComponent(tabDelimitedButton)
|
||||||
|
.addComponent(commaDelimitedButton))
|
||||||
|
.addContainerGap(78, Short.MAX_VALUE))
|
||||||
|
);
|
||||||
|
}// </editor-fold>//GEN-END:initComponents
|
||||||
|
|
||||||
|
|
||||||
|
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||||
|
private javax.swing.JRadioButton commaDelimitedButton;
|
||||||
|
private javax.swing.ButtonGroup delimiterGroup;
|
||||||
|
private javax.swing.JRadioButton tabDelimitedButton;
|
||||||
|
// End of variables declaration//GEN-END:variables
|
||||||
|
}
|
@ -243,6 +243,7 @@
|
|||||||
<package>org.apache.commons.io.input</package>
|
<package>org.apache.commons.io.input</package>
|
||||||
<package>org.apache.commons.io.monitor</package>
|
<package>org.apache.commons.io.monitor</package>
|
||||||
<package>org.apache.commons.io.output</package>
|
<package>org.apache.commons.io.output</package>
|
||||||
|
<package>org.apache.commons.io.serialization</package>
|
||||||
<package>org.apache.commons.lang</package>
|
<package>org.apache.commons.lang</package>
|
||||||
<package>org.apache.commons.lang.builder</package>
|
<package>org.apache.commons.lang.builder</package>
|
||||||
<package>org.apache.commons.lang.enums</package>
|
<package>org.apache.commons.lang.enums</package>
|
||||||
|
@ -135,7 +135,7 @@
|
|||||||
<compile-dependency/>
|
<compile-dependency/>
|
||||||
<run-dependency>
|
<run-dependency>
|
||||||
<release-version>10</release-version>
|
<release-version>10</release-version>
|
||||||
<specification-version>10.14</specification-version>
|
<specification-version>10.15</specification-version>
|
||||||
</run-dependency>
|
</run-dependency>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
@ -153,7 +153,7 @@
|
|||||||
<compile-dependency/>
|
<compile-dependency/>
|
||||||
<run-dependency>
|
<run-dependency>
|
||||||
<release-version>6</release-version>
|
<release-version>6</release-version>
|
||||||
<specification-version>6.5</specification-version>
|
<specification-version>6.6</specification-version>
|
||||||
</run-dependency>
|
</run-dependency>
|
||||||
</dependency>
|
</dependency>
|
||||||
</module-dependencies>
|
</module-dependencies>
|
||||||
|
@ -53,6 +53,8 @@ final class AutoIngestDashboard extends JPanel implements Observer {
|
|||||||
|
|
||||||
private final static String ADMIN_ACCESS_FILE_NAME = "admin"; // NON-NLS
|
private final static String ADMIN_ACCESS_FILE_NAME = "admin"; // NON-NLS
|
||||||
private final static String ADMIN_ACCESS_FILE_PATH = Paths.get(PlatformUtil.getUserConfigDirectory(), ADMIN_ACCESS_FILE_NAME).toString();
|
private final static String ADMIN_ACCESS_FILE_PATH = Paths.get(PlatformUtil.getUserConfigDirectory(), ADMIN_ACCESS_FILE_NAME).toString();
|
||||||
|
private final static String ADMIN_EXT_ACCESS_FILE_NAME = "adminext"; // NON-NLS
|
||||||
|
private final static String ADMIN_EXT_ACCESS_FILE_PATH = Paths.get(PlatformUtil.getUserConfigDirectory(), ADMIN_EXT_ACCESS_FILE_NAME).toString();
|
||||||
private final static String AID_REFRESH_THREAD_NAME = "AID-refresh-jobs-%d";
|
private final static String AID_REFRESH_THREAD_NAME = "AID-refresh-jobs-%d";
|
||||||
private final static int AID_REFRESH_INTERVAL_SECS = 30;
|
private final static int AID_REFRESH_INTERVAL_SECS = 30;
|
||||||
private final static int AID_DELAY_BEFORE_FIRST_REFRESH = 0;
|
private final static int AID_DELAY_BEFORE_FIRST_REFRESH = 0;
|
||||||
@ -277,8 +279,8 @@ final class AutoIngestDashboard extends JPanel implements Observer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reloads the table models using a RefreshChildrenEvent and refreshes the JTables
|
* Reloads the table models using a RefreshChildrenEvent and refreshes the
|
||||||
* that use the models.
|
* JTables that use the models.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void refreshTables() {
|
void refreshTables() {
|
||||||
@ -318,9 +320,24 @@ final class AutoIngestDashboard extends JPanel implements Observer {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines whether or not system adminstrator features of the dashboard
|
||||||
|
* are enabled.
|
||||||
|
*
|
||||||
|
* @return True or false.
|
||||||
|
*/
|
||||||
static boolean isAdminAutoIngestDashboard() {
|
static boolean isAdminAutoIngestDashboard() {
|
||||||
File f = new File(ADMIN_ACCESS_FILE_PATH);
|
return new File(ADMIN_ACCESS_FILE_PATH).exists() || new File(ADMIN_EXT_ACCESS_FILE_PATH).exists();
|
||||||
return f.exists();
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines whether the extended system administrator features of the
|
||||||
|
* cases dashboard are enabled.
|
||||||
|
*
|
||||||
|
* @return True or false.
|
||||||
|
*/
|
||||||
|
static boolean extendedFeaturesAreEnabled() {
|
||||||
|
return new File(ADMIN_EXT_ACCESS_FILE_PATH).exists();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1271,12 +1271,12 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen
|
|||||||
* @param nodeData The data stored in the manifest file coordination
|
* @param nodeData The data stored in the manifest file coordination
|
||||||
* service node for the job.
|
* service node for the job.
|
||||||
*
|
*
|
||||||
* @throws AutoIngestJobException If there was an error working
|
* @throws AutoIngestJobException If there was an error working with the
|
||||||
* with the node data.
|
* node data.
|
||||||
* @throws InterruptedException If the thread running the input
|
* @throws InterruptedException If the thread running the input
|
||||||
* directory scan task is
|
* directory scan task is interrupted
|
||||||
* interrupted while blocked, i.e.,
|
* while blocked, i.e., if auto ingest is
|
||||||
* if auto ingest is shutting down.
|
* shutting down.
|
||||||
*/
|
*/
|
||||||
private void addPendingJob(Manifest manifest, AutoIngestJobNodeData nodeData) throws AutoIngestJobException, InterruptedException {
|
private void addPendingJob(Manifest manifest, AutoIngestJobNodeData nodeData) throws AutoIngestJobException, InterruptedException {
|
||||||
AutoIngestJob job;
|
AutoIngestJob job;
|
||||||
@ -1415,6 +1415,8 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen
|
|||||||
sysLogger.log(Level.SEVERE, String.format("Error writing case auto ingest log entry for crashed job for %s", manifestPath), ex);
|
sysLogger.log(Level.SEVERE, String.format("Error writing case auto ingest log entry for crashed job for %s", manifestPath), ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
updateAutoIngestJobData(job);
|
||||||
|
newPendingJobsList.add(job);
|
||||||
} else {
|
} else {
|
||||||
job.setProcessingStatus(AutoIngestJob.ProcessingStatus.COMPLETED);
|
job.setProcessingStatus(AutoIngestJob.ProcessingStatus.COMPLETED);
|
||||||
job.setCompletedDate(Date.from(Instant.now()));
|
job.setCompletedDate(Date.from(Instant.now()));
|
||||||
@ -1425,9 +1427,9 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen
|
|||||||
sysLogger.log(Level.SEVERE, String.format("Error writing case auto ingest log entry for crashed job for %s", manifestPath), ex);
|
sysLogger.log(Level.SEVERE, String.format("Error writing case auto ingest log entry for crashed job for %s", manifestPath), ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
updateAutoIngestJobData(job);
|
||||||
|
newCompletedJobsList.add(job);
|
||||||
}
|
}
|
||||||
updateAutoIngestJobData(job);
|
|
||||||
newPendingJobsList.add(job);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1440,12 +1442,12 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen
|
|||||||
* @param nodeData The data stored in the manifest file lock
|
* @param nodeData The data stored in the manifest file lock
|
||||||
* coordination service node for the job.
|
* coordination service node for the job.
|
||||||
*
|
*
|
||||||
* @throws AutoIngestJobException If there was an error working
|
* @throws AutoIngestJobException If there was an error working with the
|
||||||
* with the node data.
|
* node data.
|
||||||
* @throws InterruptedException If the thread running the input
|
* @throws InterruptedException If the thread running the input
|
||||||
* directory scan task is
|
* directory scan task is interrupted
|
||||||
* interrupted while blocked, i.e.,
|
* while blocked, i.e., if auto ingest is
|
||||||
* if auto ingest is shutting down.
|
* shutting down.
|
||||||
*/
|
*/
|
||||||
private void addCompletedJob(Manifest manifest, AutoIngestJobNodeData nodeData) throws AutoIngestJobException, InterruptedException {
|
private void addCompletedJob(Manifest manifest, AutoIngestJobNodeData nodeData) throws AutoIngestJobException, InterruptedException {
|
||||||
Path caseDirectoryPath = nodeData.getCaseDirectoryPath();
|
Path caseDirectoryPath = nodeData.getCaseDirectoryPath();
|
||||||
@ -1995,15 +1997,26 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen
|
|||||||
AutoIngestJobNodeData nodeData = new AutoIngestJobNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.MANIFESTS, manifestPath.toString()));
|
AutoIngestJobNodeData nodeData = new AutoIngestJobNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.MANIFESTS, manifestPath.toString()));
|
||||||
if (!nodeData.getProcessingStatus().equals(PENDING)) {
|
if (!nodeData.getProcessingStatus().equals(PENDING)) {
|
||||||
iterator.remove();
|
iterator.remove();
|
||||||
|
manifestLock.release();
|
||||||
|
manifestLock = null;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Ditto for the presence of the manifest file.
|
||||||
|
*/
|
||||||
File manifestFile = nodeData.getManifestFilePath().toFile();
|
File manifestFile = nodeData.getManifestFilePath().toFile();
|
||||||
if (!manifestFile.exists()) {
|
if (!manifestFile.exists()) {
|
||||||
iterator.remove();
|
iterator.remove();
|
||||||
|
manifestLock.release();
|
||||||
|
manifestLock = null;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Finally, check for devoting too many resources to a
|
||||||
|
* single case, if the check is enabled.
|
||||||
|
*/
|
||||||
if (enforceMaxJobsPerCase) {
|
if (enforceMaxJobsPerCase) {
|
||||||
int currentJobsForCase = 0;
|
int currentJobsForCase = 0;
|
||||||
for (AutoIngestJob runningJob : hostNamesToRunningJobs.values()) {
|
for (AutoIngestJob runningJob : hostNamesToRunningJobs.values()) {
|
||||||
|
@ -18,14 +18,11 @@
|
|||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.experimental.autoingest;
|
package org.sleuthkit.autopsy.experimental.autoingest;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.nio.file.Paths;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import javax.swing.Action;
|
import javax.swing.Action;
|
||||||
import org.sleuthkit.autopsy.casemodule.multiusercases.CaseNodeData;
|
import org.sleuthkit.autopsy.casemodule.multiusercases.CaseNodeData;
|
||||||
import org.sleuthkit.autopsy.casemodule.multiusercasesbrowser.MultiUserCaseBrowserCustomizer;
|
import org.sleuthkit.autopsy.casemodule.multiusercasesbrowser.MultiUserCaseBrowserCustomizer;
|
||||||
import org.sleuthkit.autopsy.coreutils.PlatformUtil;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A customizer for the multi-user case browser panel used in the administrative
|
* A customizer for the multi-user case browser panel used in the administrative
|
||||||
@ -34,8 +31,6 @@ import org.sleuthkit.autopsy.coreutils.PlatformUtil;
|
|||||||
*/
|
*/
|
||||||
final class CasesDashboardCustomizer implements MultiUserCaseBrowserCustomizer {
|
final class CasesDashboardCustomizer implements MultiUserCaseBrowserCustomizer {
|
||||||
|
|
||||||
private final static String ADMIN_EXT_ACCESS_FILE_NAME = "adminext"; // NON-NLS
|
|
||||||
private final static String ADMIN_EXT_ACCESS_FILE_PATH = Paths.get(PlatformUtil.getUserConfigDirectory(), ADMIN_EXT_ACCESS_FILE_NAME).toString();
|
|
||||||
private final DeleteCaseAction deleteCaseAction;
|
private final DeleteCaseAction deleteCaseAction;
|
||||||
private final DeleteCaseInputAction deleteCaseInputAction;
|
private final DeleteCaseInputAction deleteCaseInputAction;
|
||||||
private final DeleteCaseOutputAction deleteCaseOutputAction;
|
private final DeleteCaseOutputAction deleteCaseOutputAction;
|
||||||
@ -67,7 +62,7 @@ final class CasesDashboardCustomizer implements MultiUserCaseBrowserCustomizer {
|
|||||||
properties.add(Column.LAST_ACCESS_DATE);
|
properties.add(Column.LAST_ACCESS_DATE);
|
||||||
properties.add(Column.DIRECTORY);
|
properties.add(Column.DIRECTORY);
|
||||||
properties.add(Column.MANIFEST_FILE_ZNODES_DELETE_STATUS);
|
properties.add(Column.MANIFEST_FILE_ZNODES_DELETE_STATUS);
|
||||||
if (CasesDashboardCustomizer.extendedFeaturesAreEnabled()) {
|
if (AutoIngestDashboard.extendedFeaturesAreEnabled()) {
|
||||||
properties.add(Column.DATA_SOURCES_DELETE_STATUS);
|
properties.add(Column.DATA_SOURCES_DELETE_STATUS);
|
||||||
}
|
}
|
||||||
properties.add(Column.TEXT_INDEX_DELETE_STATUS);
|
properties.add(Column.TEXT_INDEX_DELETE_STATUS);
|
||||||
@ -93,7 +88,7 @@ final class CasesDashboardCustomizer implements MultiUserCaseBrowserCustomizer {
|
|||||||
List<Action> actions = new ArrayList<>();
|
List<Action> actions = new ArrayList<>();
|
||||||
actions.add(new OpenCaseAction(nodeData));
|
actions.add(new OpenCaseAction(nodeData));
|
||||||
actions.add(new OpenAutoIngestLogAction(nodeData));
|
actions.add(new OpenAutoIngestLogAction(nodeData));
|
||||||
if (CasesDashboardCustomizer.extendedFeaturesAreEnabled()) {
|
if (AutoIngestDashboard.extendedFeaturesAreEnabled()) {
|
||||||
actions.add(deleteCaseInputAction);
|
actions.add(deleteCaseInputAction);
|
||||||
actions.add(deleteCaseOutputAction);
|
actions.add(deleteCaseOutputAction);
|
||||||
actions.add(deleteCaseInputAndOutputAction);
|
actions.add(deleteCaseInputAndOutputAction);
|
||||||
@ -108,15 +103,4 @@ final class CasesDashboardCustomizer implements MultiUserCaseBrowserCustomizer {
|
|||||||
return new OpenCaseAction(nodeData);
|
return new OpenCaseAction(nodeData);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Determines whether the extended system administrator features of the
|
|
||||||
* cases dashboard are enabled.
|
|
||||||
*
|
|
||||||
* @return True or false.
|
|
||||||
*/
|
|
||||||
static boolean extendedFeaturesAreEnabled() {
|
|
||||||
File f = new File(ADMIN_EXT_ACCESS_FILE_PATH);
|
|
||||||
return f.exists();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
Manifest-Version: 1.0
|
Manifest-Version: 1.0
|
||||||
OpenIDE-Module: org.sleuthkit.autopsy.imagegallery/2
|
OpenIDE-Module: org.sleuthkit.autopsy.imagegallery/2
|
||||||
OpenIDE-Module-Implementation-Version: 5
|
OpenIDE-Module-Implementation-Version: 6
|
||||||
OpenIDE-Module-Layer: org/sleuthkit/autopsy/imagegallery/layer.xml
|
OpenIDE-Module-Layer: org/sleuthkit/autopsy/imagegallery/layer.xml
|
||||||
OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/imagegallery/Bundle.properties
|
OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/imagegallery/Bundle.properties
|
||||||
|
|
||||||
|
@ -127,7 +127,7 @@
|
|||||||
<compile-dependency/>
|
<compile-dependency/>
|
||||||
<run-dependency>
|
<run-dependency>
|
||||||
<release-version>10</release-version>
|
<release-version>10</release-version>
|
||||||
<specification-version>10.14</specification-version>
|
<specification-version>10.15</specification-version>
|
||||||
</run-dependency>
|
</run-dependency>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
|
@ -646,13 +646,22 @@ public class GroupManager {
|
|||||||
// reset the hash cache
|
// reset the hash cache
|
||||||
controller.getHashSetManager().invalidateHashSetsCacheForFile(fileId);
|
controller.getHashSetManager().invalidateHashSetsCacheForFile(fileId);
|
||||||
|
|
||||||
|
// first of all, update the current path group, regardless of what grouping is in view
|
||||||
|
try {
|
||||||
|
DrawableFile file = getDrawableDB().getFileFromID(fileId);
|
||||||
|
String pathVal = file.getDrawablePath();
|
||||||
|
GroupKey<?> pathGroupKey = new GroupKey<>(DrawableAttribute.PATH,pathVal, file.getDataSource());
|
||||||
|
|
||||||
|
updateCurrentPathGroup(pathGroupKey);
|
||||||
|
} catch (TskCoreException | TskDataException ex) {
|
||||||
|
Exceptions.printStackTrace(ex);
|
||||||
|
}
|
||||||
|
|
||||||
// Update the current groups (if it is visible)
|
// Update the current groups (if it is visible)
|
||||||
Set<GroupKey<?>> groupsForFile = getGroupKeysForCurrentGroupBy(fileId);
|
Set<GroupKey<?>> groupsForFile = getGroupKeysForCurrentGroupBy(fileId);
|
||||||
for (GroupKey<?> gk : groupsForFile) {
|
for (GroupKey<?> gk : groupsForFile) {
|
||||||
// see if a group has been created yet for the key
|
// see if a group has been created yet for the key
|
||||||
DrawableGroup g = getGroupForKey(gk);
|
DrawableGroup g = getGroupForKey(gk);
|
||||||
|
|
||||||
updateCurrentPathGroup(gk);
|
|
||||||
addFileToGroup(g, gk, fileId);
|
addFileToGroup(g, gk, fileId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -756,8 +765,10 @@ public class GroupManager {
|
|||||||
controller.getCategoryManager().registerListener(group);
|
controller.getCategoryManager().registerListener(group);
|
||||||
groupMap.put(groupKey, group);
|
groupMap.put(groupKey, group);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (analyzedGroups.contains(group) == false) {
|
// Add to analyzedGroups only if it's the same group type as the one in view
|
||||||
|
if ((analyzedGroups.contains(group) == false) &&
|
||||||
|
(getGroupBy() == group.getGroupKey().getAttribute())) {
|
||||||
analyzedGroups.add(group);
|
analyzedGroups.add(group);
|
||||||
sortAnalyzedGroups();
|
sortAnalyzedGroups();
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
Manifest-Version: 1.0
|
Manifest-Version: 1.0
|
||||||
AutoUpdate-Show-In-Client: true
|
AutoUpdate-Show-In-Client: true
|
||||||
OpenIDE-Module: org.sleuthkit.autopsy.keywordsearch/6
|
OpenIDE-Module: org.sleuthkit.autopsy.keywordsearch/6
|
||||||
OpenIDE-Module-Implementation-Version: 20
|
OpenIDE-Module-Implementation-Version: 21
|
||||||
OpenIDE-Module-Install: org/sleuthkit/autopsy/keywordsearch/Installer.class
|
OpenIDE-Module-Install: org/sleuthkit/autopsy/keywordsearch/Installer.class
|
||||||
OpenIDE-Module-Layer: org/sleuthkit/autopsy/keywordsearch/layer.xml
|
OpenIDE-Module-Layer: org/sleuthkit/autopsy/keywordsearch/layer.xml
|
||||||
OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/keywordsearch/Bundle.properties
|
OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/keywordsearch/Bundle.properties
|
||||||
|
@ -131,6 +131,7 @@ file.reference.uimaj-tools-2.6.0.jar=release/modules/ext/uimaj-tools-2.6.0.jar
|
|||||||
file.reference.vorbis-java-core-0.8.jar=release/modules/ext/vorbis-java-core-0.8.jar
|
file.reference.vorbis-java-core-0.8.jar=release/modules/ext/vorbis-java-core-0.8.jar
|
||||||
file.reference.vorbis-java-tika-0.8.jar=release/modules/ext/vorbis-java-tika-0.8.jar
|
file.reference.vorbis-java-tika-0.8.jar=release/modules/ext/vorbis-java-tika-0.8.jar
|
||||||
file.reference.woodstox-core-asl-4.4.1.jar=release/modules/ext/woodstox-core-asl-4.4.1.jar
|
file.reference.woodstox-core-asl-4.4.1.jar=release/modules/ext/woodstox-core-asl-4.4.1.jar
|
||||||
|
file.reference.wstx-asl-3.2.7.jar=release\\modules\\ext\\wstx-asl-3.2.7.jar
|
||||||
file.reference.xmlbeans-2.6.0.jar=release/modules/ext/xmlbeans-2.6.0.jar
|
file.reference.xmlbeans-2.6.0.jar=release/modules/ext/xmlbeans-2.6.0.jar
|
||||||
file.reference.xmpcore-5.1.3.jar=release/modules/ext/xmpcore-5.1.3.jar
|
file.reference.xmpcore-5.1.3.jar=release/modules/ext/xmpcore-5.1.3.jar
|
||||||
file.reference.zookeeper-3.4.6.jar=release/modules/ext/zookeeper-3.4.6.jar
|
file.reference.zookeeper-3.4.6.jar=release/modules/ext/zookeeper-3.4.6.jar
|
||||||
@ -141,4 +142,4 @@ license.file=../LICENSE-2.0.txt
|
|||||||
nbm.homepage=http://www.sleuthkit.org/autopsy/
|
nbm.homepage=http://www.sleuthkit.org/autopsy/
|
||||||
nbm.needs.restart=true
|
nbm.needs.restart=true
|
||||||
source.reference.commons-validator-1.5.1.jar=release/modules/ext/commons-validator-1.5.1-sources.jar
|
source.reference.commons-validator-1.5.1.jar=release/modules/ext/commons-validator-1.5.1-sources.jar
|
||||||
spec.version.base=6.5
|
spec.version.base=6.6
|
||||||
|
@ -119,7 +119,7 @@
|
|||||||
<compile-dependency/>
|
<compile-dependency/>
|
||||||
<run-dependency>
|
<run-dependency>
|
||||||
<release-version>10</release-version>
|
<release-version>10</release-version>
|
||||||
<specification-version>10.14</specification-version>
|
<specification-version>10.15</specification-version>
|
||||||
</run-dependency>
|
</run-dependency>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
@ -133,9 +133,107 @@
|
|||||||
</dependency>
|
</dependency>
|
||||||
</module-dependencies>
|
</module-dependencies>
|
||||||
<public-packages>
|
<public-packages>
|
||||||
|
<package>com.ctc.wstx.api</package>
|
||||||
|
<package>com.ctc.wstx.cfg</package>
|
||||||
|
<package>com.ctc.wstx.compat</package>
|
||||||
|
<package>com.ctc.wstx.dom</package>
|
||||||
|
<package>com.ctc.wstx.dtd</package>
|
||||||
|
<package>com.ctc.wstx.ent</package>
|
||||||
|
<package>com.ctc.wstx.evt</package>
|
||||||
|
<package>com.ctc.wstx.exc</package>
|
||||||
|
<package>com.ctc.wstx.io</package>
|
||||||
|
<package>com.ctc.wstx.msv</package>
|
||||||
|
<package>com.ctc.wstx.sax</package>
|
||||||
|
<package>com.ctc.wstx.sr</package>
|
||||||
|
<package>com.ctc.wstx.stax</package>
|
||||||
|
<package>com.ctc.wstx.sw</package>
|
||||||
|
<package>com.ctc.wstx.util</package>
|
||||||
<package>org.apache.commons.logging.impl</package>
|
<package>org.apache.commons.logging.impl</package>
|
||||||
|
<package>org.apache.http</package>
|
||||||
|
<package>org.apache.http.annotation</package>
|
||||||
|
<package>org.apache.http.auth</package>
|
||||||
|
<package>org.apache.http.auth.params</package>
|
||||||
|
<package>org.apache.http.client</package>
|
||||||
|
<package>org.apache.http.client.config</package>
|
||||||
|
<package>org.apache.http.client.entity</package>
|
||||||
|
<package>org.apache.http.client.methods</package>
|
||||||
|
<package>org.apache.http.client.params</package>
|
||||||
|
<package>org.apache.http.client.protocol</package>
|
||||||
|
<package>org.apache.http.client.utils</package>
|
||||||
|
<package>org.apache.http.concurrent</package>
|
||||||
|
<package>org.apache.http.config</package>
|
||||||
|
<package>org.apache.http.conn</package>
|
||||||
|
<package>org.apache.http.conn.params</package>
|
||||||
|
<package>org.apache.http.conn.routing</package>
|
||||||
|
<package>org.apache.http.conn.scheme</package>
|
||||||
|
<package>org.apache.http.conn.socket</package>
|
||||||
|
<package>org.apache.http.conn.ssl</package>
|
||||||
|
<package>org.apache.http.conn.util</package>
|
||||||
|
<package>org.apache.http.cookie</package>
|
||||||
|
<package>org.apache.http.cookie.params</package>
|
||||||
|
<package>org.apache.http.entity</package>
|
||||||
|
<package>org.apache.http.entity.mime</package>
|
||||||
|
<package>org.apache.http.entity.mime.content</package>
|
||||||
|
<package>org.apache.http.impl</package>
|
||||||
|
<package>org.apache.http.impl.auth</package>
|
||||||
|
<package>org.apache.http.impl.bootstrap</package>
|
||||||
|
<package>org.apache.http.impl.client</package>
|
||||||
|
<package>org.apache.http.impl.conn</package>
|
||||||
|
<package>org.apache.http.impl.conn.tsccm</package>
|
||||||
|
<package>org.apache.http.impl.cookie</package>
|
||||||
|
<package>org.apache.http.impl.entity</package>
|
||||||
|
<package>org.apache.http.impl.execchain</package>
|
||||||
|
<package>org.apache.http.impl.io</package>
|
||||||
|
<package>org.apache.http.impl.pool</package>
|
||||||
|
<package>org.apache.http.io</package>
|
||||||
|
<package>org.apache.http.message</package>
|
||||||
|
<package>org.apache.http.params</package>
|
||||||
|
<package>org.apache.http.pool</package>
|
||||||
|
<package>org.apache.http.protocol</package>
|
||||||
|
<package>org.apache.http.ssl</package>
|
||||||
|
<package>org.apache.http.util</package>
|
||||||
|
<package>org.apache.jute</package>
|
||||||
|
<package>org.apache.jute.compiler</package>
|
||||||
|
<package>org.apache.jute.compiler.generated</package>
|
||||||
|
<package>org.apache.solr.client.solrj</package>
|
||||||
|
<package>org.apache.solr.client.solrj.beans</package>
|
||||||
|
<package>org.apache.solr.client.solrj.impl</package>
|
||||||
|
<package>org.apache.solr.client.solrj.request</package>
|
||||||
|
<package>org.apache.solr.client.solrj.response</package>
|
||||||
|
<package>org.apache.solr.client.solrj.util</package>
|
||||||
|
<package>org.apache.solr.common</package>
|
||||||
|
<package>org.apache.solr.common.cloud</package>
|
||||||
|
<package>org.apache.solr.common.luke</package>
|
||||||
|
<package>org.apache.solr.common.params</package>
|
||||||
|
<package>org.apache.solr.common.util</package>
|
||||||
<package>org.apache.tika.parser.txt</package>
|
<package>org.apache.tika.parser.txt</package>
|
||||||
|
<package>org.apache.zookeeper</package>
|
||||||
|
<package>org.apache.zookeeper.client</package>
|
||||||
|
<package>org.apache.zookeeper.common</package>
|
||||||
|
<package>org.apache.zookeeper.data</package>
|
||||||
|
<package>org.apache.zookeeper.jmx</package>
|
||||||
|
<package>org.apache.zookeeper.proto</package>
|
||||||
|
<package>org.apache.zookeeper.server</package>
|
||||||
|
<package>org.apache.zookeeper.server.auth</package>
|
||||||
|
<package>org.apache.zookeeper.server.persistence</package>
|
||||||
|
<package>org.apache.zookeeper.server.quorum</package>
|
||||||
|
<package>org.apache.zookeeper.server.quorum.flexible</package>
|
||||||
|
<package>org.apache.zookeeper.server.upgrade</package>
|
||||||
|
<package>org.apache.zookeeper.server.util</package>
|
||||||
|
<package>org.apache.zookeeper.txn</package>
|
||||||
|
<package>org.apache.zookeeper.version</package>
|
||||||
|
<package>org.apache.zookeeper.version.util</package>
|
||||||
|
<package>org.codehaus.stax2</package>
|
||||||
|
<package>org.codehaus.stax2.evt</package>
|
||||||
|
<package>org.codehaus.stax2.io</package>
|
||||||
|
<package>org.codehaus.stax2.ri</package>
|
||||||
|
<package>org.codehaus.stax2.validation</package>
|
||||||
|
<package>org.noggit</package>
|
||||||
<package>org.sleuthkit.autopsy.keywordsearch</package>
|
<package>org.sleuthkit.autopsy.keywordsearch</package>
|
||||||
|
<package>org.slf4j</package>
|
||||||
|
<package>org.slf4j.event</package>
|
||||||
|
<package>org.slf4j.helpers</package>
|
||||||
|
<package>org.slf4j.spi</package>
|
||||||
</public-packages>
|
</public-packages>
|
||||||
<class-path-extension>
|
<class-path-extension>
|
||||||
<runtime-relative-path>ext/commons-validator-1.5.1-sources.jar</runtime-relative-path>
|
<runtime-relative-path>ext/commons-validator-1.5.1-sources.jar</runtime-relative-path>
|
||||||
@ -409,6 +507,10 @@
|
|||||||
<runtime-relative-path>ext/jmatio-1.2.jar</runtime-relative-path>
|
<runtime-relative-path>ext/jmatio-1.2.jar</runtime-relative-path>
|
||||||
<binary-origin>release/modules/ext/jmatio-1.2.jar</binary-origin>
|
<binary-origin>release/modules/ext/jmatio-1.2.jar</binary-origin>
|
||||||
</class-path-extension>
|
</class-path-extension>
|
||||||
|
<class-path-extension>
|
||||||
|
<runtime-relative-path>ext/wstx-asl-3.2.7.jar</runtime-relative-path>
|
||||||
|
<binary-origin>release\modules\ext\wstx-asl-3.2.7.jar</binary-origin>
|
||||||
|
</class-path-extension>
|
||||||
<class-path-extension>
|
<class-path-extension>
|
||||||
<runtime-relative-path>ext/commons-csv-1.0.jar</runtime-relative-path>
|
<runtime-relative-path>ext/commons-csv-1.0.jar</runtime-relative-path>
|
||||||
<binary-origin>release/modules/ext/commons-csv-1.0.jar</binary-origin>
|
<binary-origin>release/modules/ext/commons-csv-1.0.jar</binary-origin>
|
||||||
|
@ -31,7 +31,7 @@ import org.sleuthkit.datamodel.BlackboardAttribute;
|
|||||||
* with a keyword. This feature was added to support an initial implementation
|
* with a keyword. This feature was added to support an initial implementation
|
||||||
* of account number search and may be removed in the future.
|
* of account number search and may be removed in the future.
|
||||||
*/
|
*/
|
||||||
class Keyword {
|
public class Keyword {
|
||||||
|
|
||||||
private String searchTerm;
|
private String searchTerm;
|
||||||
private boolean isLiteral;
|
private boolean isLiteral;
|
||||||
@ -123,7 +123,7 @@ class Keyword {
|
|||||||
*
|
*
|
||||||
* @return The search term.
|
* @return The search term.
|
||||||
*/
|
*/
|
||||||
String getSearchTerm() {
|
public String getSearchTerm() {
|
||||||
return searchTerm;
|
return searchTerm;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,7 +133,7 @@ class Keyword {
|
|||||||
*
|
*
|
||||||
* @return True or false.
|
* @return True or false.
|
||||||
*/
|
*/
|
||||||
boolean searchTermIsLiteral() {
|
public boolean searchTermIsLiteral() {
|
||||||
return isLiteral;
|
return isLiteral;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,7 +144,7 @@ class Keyword {
|
|||||||
*
|
*
|
||||||
* @return True or false.
|
* @return True or false.
|
||||||
*/
|
*/
|
||||||
boolean searchTermIsWholeWord() {
|
public boolean searchTermIsWholeWord() {
|
||||||
return isWholeWord;
|
return isWholeWord;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,7 +167,7 @@ public class KeywordList {
|
|||||||
*
|
*
|
||||||
* @return A colleciton of Keyword objects.
|
* @return A colleciton of Keyword objects.
|
||||||
*/
|
*/
|
||||||
List<Keyword> getKeywords() {
|
public List<Keyword> getKeywords() {
|
||||||
return keywords;
|
return keywords;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2014 Basis Technology Corp.
|
* Copyright 2014-2019 Basis Technology Corp.
|
||||||
* Contact: carrier <at> sleuthkit <dot> org
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -52,6 +52,8 @@ public class KeywordListsManager extends Observable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the singleton instance of the keyword lists manager.
|
* Gets the singleton instance of the keyword lists manager.
|
||||||
|
*
|
||||||
|
* @return an instance of KeywordListsManager.
|
||||||
*/
|
*/
|
||||||
public static synchronized KeywordListsManager getInstance() {
|
public static synchronized KeywordListsManager getInstance() {
|
||||||
if (instance == null) {
|
if (instance == null) {
|
||||||
@ -73,6 +75,17 @@ public class KeywordListsManager extends Observable {
|
|||||||
return names;
|
return names;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get keyword list by name.
|
||||||
|
*
|
||||||
|
* @param name id of the list
|
||||||
|
*
|
||||||
|
* @return keyword list representation, null if no list by that name
|
||||||
|
*/
|
||||||
|
public KeywordList getList(String name) {
|
||||||
|
return XmlKeywordSearchList.getCurrent().getList(name);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Force reload of the keyword lists XML file.
|
* Force reload of the keyword lists XML file.
|
||||||
*/
|
*/
|
||||||
|
47
NEWS.txt
47
NEWS.txt
@ -1,3 +1,50 @@
|
|||||||
|
---------------- VERSION 4.11.0 --------------
|
||||||
|
New Features:
|
||||||
|
|
||||||
|
Adding Data:
|
||||||
|
- Hashes can optionally be entered when adding a disk image data source to a case.
|
||||||
|
- Acquisition details can be stored when the data source is added.
|
||||||
|
|
||||||
|
|
||||||
|
Ingest Modules:
|
||||||
|
- Added support for Microsoft Edge browser (cookies, history, and bookmarks)
|
||||||
|
- Added support for Safari web browser (downloads, cookies, history, and bookmarks)
|
||||||
|
- Expanded Chrome browser support to include cache parsing and form/auto fill.
|
||||||
|
- Expanded Firefox browser support to extract form/auto fill fields.
|
||||||
|
- Parse Zone.Identifier files to identify the source of files.
|
||||||
|
- Added a TSK_SOURCE artifact to downloaded files to help users trace back to where it came from.
|
||||||
|
- Added support for parsing vCards (virtual cards).
|
||||||
|
- Extract more information about Windows user accounts (number of logins, creation date, and last login)
|
||||||
|
- Detect more operating system types, which get saved as a TSK_OS_INFO artifact.
|
||||||
|
- Detect Android media cards, which gets saved as a TSK_DATA_SOURCE_USAGE artifact.
|
||||||
|
|
||||||
|
|
||||||
|
UI:
|
||||||
|
- The Application content viewer now displays HTML files.
|
||||||
|
- Video playback now uses gstreamer on 64-bit systems, which supports more video formats.
|
||||||
|
- Pictures can be rotated and zoomed in the Application content viewer.
|
||||||
|
- The Other Occurrences content viewer layout was reorganized to make viewing the data easier.
|
||||||
|
- New "Data Source Summary" panel shows high-level statistics and details about the data sources in the case.
|
||||||
|
- Data sources are now listed in the data sources tree in alphabetical order.
|
||||||
|
- The presentation of finding common properties within a case was revised to group results in a more helpful way.
|
||||||
|
|
||||||
|
|
||||||
|
Report / Export:
|
||||||
|
- Portable Cases can be created based on tagged data. These cases contain a subset of the case data and can be opened anywhere.
|
||||||
|
- Users can now choose tabs or commas as the delimiter for a files report.
|
||||||
|
- Case notes are included in the HTML report.
|
||||||
|
|
||||||
|
|
||||||
|
Other:
|
||||||
|
- Added a new file type that allows module writers to specify a file based on its byte range.
|
||||||
|
- Data sources can be analyzed and have a CASE/UCO report generated using only the command line.
|
||||||
|
|
||||||
|
|
||||||
|
Bug Fixes:
|
||||||
|
- Decreased the time required to execute inter-case common properties searches of the Central Repository.
|
||||||
|
- Assorted small bug fixes are included.
|
||||||
|
|
||||||
|
|
||||||
---------------- VERSION 4.10.0 --------------
|
---------------- VERSION 4.10.0 --------------
|
||||||
New Features:
|
New Features:
|
||||||
- Users can now view information on all cases/data sources in the Central
|
- Users can now view information on all cases/data sources in the Central
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
Manifest-Version: 1.0
|
Manifest-Version: 1.0
|
||||||
OpenIDE-Module: org.sleuthkit.autopsy.recentactivity/6
|
OpenIDE-Module: org.sleuthkit.autopsy.recentactivity/6
|
||||||
OpenIDE-Module-Implementation-Version: 16
|
OpenIDE-Module-Implementation-Version: 17
|
||||||
OpenIDE-Module-Layer: org/sleuthkit/autopsy/recentactivity/layer.xml
|
OpenIDE-Module-Layer: org/sleuthkit/autopsy/recentactivity/layer.xml
|
||||||
OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/recentactivity/Bundle.properties
|
OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/recentactivity/Bundle.properties
|
||||||
OpenIDE-Module-Requires:
|
OpenIDE-Module-Requires:
|
||||||
|
@ -60,7 +60,7 @@
|
|||||||
<compile-dependency/>
|
<compile-dependency/>
|
||||||
<run-dependency>
|
<run-dependency>
|
||||||
<release-version>10</release-version>
|
<release-version>10</release-version>
|
||||||
<specification-version>10.14</specification-version>
|
<specification-version>10.15</specification-version>
|
||||||
</run-dependency>
|
</run-dependency>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
|
@ -32,15 +32,15 @@ import org.sleuthkit.autopsy.coreutils.Logger;
|
|||||||
import org.sleuthkit.autopsy.recentactivity.BinaryCookieReader.Cookie;
|
import org.sleuthkit.autopsy.recentactivity.BinaryCookieReader.Cookie;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The binary cookie reader encapsulates all the knowledge of how to read the mac
|
* The binary cookie reader encapsulates all the knowledge of how to read the
|
||||||
* .binarycookie files into one class.
|
* mac .binarycookie files into one class.
|
||||||
*
|
*
|
||||||
* The binarycookie file has a header which describes how many pages of cookies
|
* The binarycookie file has a header which describes how many pages of cookies
|
||||||
* and where they are located. Each cookie page has a header and a list of
|
* and where they are located. Each cookie page has a header and a list of
|
||||||
* cookies.
|
* cookies.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public final class BinaryCookieReader implements Iterable<Cookie> {
|
final class BinaryCookieReader implements Iterable<Cookie> {
|
||||||
|
|
||||||
private static final int MAGIC_SIZE = 4;
|
private static final int MAGIC_SIZE = 4;
|
||||||
private static final int SIZEOF_INT_BYTES = 4;
|
private static final int SIZEOF_INT_BYTES = 4;
|
||||||
@ -56,8 +56,8 @@ public final class BinaryCookieReader implements Iterable<Cookie> {
|
|||||||
private static final Logger LOG = Logger.getLogger(BinaryCookieReader.class.getName());
|
private static final Logger LOG = Logger.getLogger(BinaryCookieReader.class.getName());
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The binary cookie reader encapsulates all the knowledge of how to read the mac
|
* The binary cookie reader encapsulates all the knowledge of how to read
|
||||||
* .binarycookie files into one class.
|
* the mac .binarycookie files into one class.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
private BinaryCookieReader(File cookieFile, int[] pageSizeArray) {
|
private BinaryCookieReader(File cookieFile, int[] pageSizeArray) {
|
||||||
@ -96,7 +96,7 @@ public final class BinaryCookieReader implements Iterable<Cookie> {
|
|||||||
for (int cnt = 0; cnt < pageCount; cnt++) {
|
for (int cnt = 0; cnt < pageCount; cnt++) {
|
||||||
sizeArray[cnt] = dataStream.readInt();
|
sizeArray[cnt] = dataStream.readInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG.log(Level.INFO, "No cookies found in {0}", cookieFile.getName()); //NON-NLS
|
LOG.log(Level.INFO, "No cookies found in {0}", cookieFile.getName()); //NON-NLS
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,16 +130,16 @@ public final class BinaryCookieReader implements Iterable<Cookie> {
|
|||||||
* The cookiePageIterator iterates the binarycookie file by page.
|
* The cookiePageIterator iterates the binarycookie file by page.
|
||||||
*/
|
*/
|
||||||
CookiePageIterator() {
|
CookiePageIterator() {
|
||||||
if(pageSizeArray == null || pageSizeArray.length == 0) {
|
if (pageSizeArray == null || pageSizeArray.length == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
dataStream = new DataInputStream(new FileInputStream(cookieFile));
|
dataStream = new DataInputStream(new FileInputStream(cookieFile));
|
||||||
// skip to the first page
|
// skip to the first page
|
||||||
dataStream.skipBytes((2 * SIZEOF_INT_BYTES) + (pageSizeArray.length * SIZEOF_INT_BYTES));
|
dataStream.skipBytes((2 * SIZEOF_INT_BYTES) + (pageSizeArray.length * SIZEOF_INT_BYTES));
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
|
|
||||||
String errorMessage = String.format("An error occurred creating an input stream for %s", cookieFile.getName());
|
String errorMessage = String.format("An error occurred creating an input stream for %s", cookieFile.getName());
|
||||||
LOG.log(Level.WARNING, errorMessage, ex); //NON-NLS
|
LOG.log(Level.WARNING, errorMessage, ex); //NON-NLS
|
||||||
closeStream(); // Just incase the error was from skip
|
closeStream(); // Just incase the error was from skip
|
||||||
@ -147,7 +147,7 @@ public final class BinaryCookieReader implements Iterable<Cookie> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if there are more cookies in the binarycookie file.
|
* Returns true if there are more cookies in the binarycookie file.
|
||||||
*
|
*
|
||||||
* @return True if there are more cookies
|
* @return True if there are more cookies
|
||||||
*/
|
*/
|
||||||
@ -157,7 +157,7 @@ public final class BinaryCookieReader implements Iterable<Cookie> {
|
|||||||
if (dataStream == null) {
|
if (dataStream == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentIterator == null || !currentIterator.hasNext()) {
|
if (currentIterator == null || !currentIterator.hasNext()) {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
@ -360,7 +360,7 @@ public final class BinaryCookieReader implements Iterable<Cookie> {
|
|||||||
* @return Cookie expiration date in milliseconds with java epoch
|
* @return Cookie expiration date in milliseconds with java epoch
|
||||||
*/
|
*/
|
||||||
public final Long getExpirationDate() {
|
public final Long getExpirationDate() {
|
||||||
return ((long)expirationDate) + MAC_EPOC_FIX;
|
return ((long) expirationDate) + MAC_EPOC_FIX;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -370,7 +370,7 @@ public final class BinaryCookieReader implements Iterable<Cookie> {
|
|||||||
* @return Cookie creation date in milliseconds with java epoch
|
* @return Cookie creation date in milliseconds with java epoch
|
||||||
*/
|
*/
|
||||||
public final Long getCreationDate() {
|
public final Long getCreationDate() {
|
||||||
return ((long)creationDate) + MAC_EPOC_FIX;
|
return ((long) creationDate) + MAC_EPOC_FIX;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -170,16 +170,21 @@ abstract class Extract {
|
|||||||
ResultSet temprs;
|
ResultSet temprs;
|
||||||
List<HashMap<String, Object>> list;
|
List<HashMap<String, Object>> list;
|
||||||
String connectionString = "jdbc:sqlite:" + path; //NON-NLS
|
String connectionString = "jdbc:sqlite:" + path; //NON-NLS
|
||||||
|
SQLiteDBConnect tempdbconnect = null;
|
||||||
try {
|
try {
|
||||||
SQLiteDBConnect tempdbconnect = new SQLiteDBConnect("org.sqlite.JDBC", connectionString); //NON-NLS
|
tempdbconnect = new SQLiteDBConnect("org.sqlite.JDBC", connectionString); //NON-NLS
|
||||||
temprs = tempdbconnect.executeQry(query);
|
temprs = tempdbconnect.executeQry(query);
|
||||||
list = this.resultSetToArrayList(temprs);
|
list = this.resultSetToArrayList(temprs);
|
||||||
tempdbconnect.closeConnection();
|
|
||||||
} catch (SQLException ex) {
|
} catch (SQLException ex) {
|
||||||
logger.log(Level.SEVERE, "Error while trying to read into a sqlite db." + connectionString, ex); //NON-NLS
|
logger.log(Level.SEVERE, "Error while trying to read into a sqlite db." + connectionString, ex); //NON-NLS
|
||||||
errorMessages.add(NbBundle.getMessage(this.getClass(), "Extract.dbConn.errMsg.failedToQueryDb", getName()));
|
errorMessages.add(NbBundle.getMessage(this.getClass(), "Extract.dbConn.errMsg.failedToQueryDb", getName()));
|
||||||
return Collections.<HashMap<String, Object>>emptyList();
|
return Collections.<HashMap<String, Object>>emptyList();
|
||||||
}
|
}
|
||||||
|
finally {
|
||||||
|
if (tempdbconnect != null) {
|
||||||
|
tempdbconnect.closeConnection();
|
||||||
|
}
|
||||||
|
}
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -253,6 +253,7 @@ class ExtractRegistry extends Extract {
|
|||||||
logger.log(Level.WARNING, "Keyword search service not found. Report will not be indexed");
|
logger.log(Level.WARNING, "Keyword search service not found. Report will not be indexed");
|
||||||
} else {
|
} else {
|
||||||
searchService.index(report);
|
searchService.index(report);
|
||||||
|
report.close();
|
||||||
}
|
}
|
||||||
} catch (TskCoreException e) {
|
} catch (TskCoreException e) {
|
||||||
this.addErrorMessage("Error adding regripper output as Autopsy report: " + e.getLocalizedMessage()); //NON-NLS
|
this.addErrorMessage("Error adding regripper output as Autopsy report: " + e.getLocalizedMessage()); //NON-NLS
|
||||||
|
@ -148,8 +148,9 @@ class Util {
|
|||||||
String query = "PRAGMA table_info(" + tablename + ")"; //NON-NLS
|
String query = "PRAGMA table_info(" + tablename + ")"; //NON-NLS
|
||||||
boolean found = false;
|
boolean found = false;
|
||||||
ResultSet temprs;
|
ResultSet temprs;
|
||||||
|
SQLiteDBConnect tempdbconnect = null;
|
||||||
try {
|
try {
|
||||||
SQLiteDBConnect tempdbconnect = new SQLiteDBConnect("org.sqlite.JDBC", "jdbc:sqlite:" + connection); //NON-NLS
|
tempdbconnect = new SQLiteDBConnect("org.sqlite.JDBC", "jdbc:sqlite:" + connection); //NON-NLS
|
||||||
temprs = tempdbconnect.executeQry(query);
|
temprs = tempdbconnect.executeQry(query);
|
||||||
while (temprs.next()) {
|
while (temprs.next()) {
|
||||||
if (temprs.getString("name") == null ? column == null : temprs.getString("name").equals(column)) { //NON-NLS
|
if (temprs.getString("name") == null ? column == null : temprs.getString("name").equals(column)) { //NON-NLS
|
||||||
@ -159,6 +160,11 @@ class Util {
|
|||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
logger.log(Level.WARNING, "Error while trying to get columns from sqlite db." + connection, ex); //NON-NLS
|
logger.log(Level.WARNING, "Error while trying to get columns from sqlite db." + connection, ex); //NON-NLS
|
||||||
}
|
}
|
||||||
|
finally{
|
||||||
|
if (tempdbconnect != null) {
|
||||||
|
tempdbconnect.closeConnection();
|
||||||
|
}
|
||||||
|
}
|
||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@
|
|||||||
<compile-dependency/>
|
<compile-dependency/>
|
||||||
<run-dependency>
|
<run-dependency>
|
||||||
<release-version>10</release-version>
|
<release-version>10</release-version>
|
||||||
<specification-version>10.14</specification-version>
|
<specification-version>10.15</specification-version>
|
||||||
</run-dependency>
|
</run-dependency>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
@ -56,7 +56,7 @@
|
|||||||
<compile-dependency/>
|
<compile-dependency/>
|
||||||
<run-dependency>
|
<run-dependency>
|
||||||
<release-version>6</release-version>
|
<release-version>6</release-version>
|
||||||
<specification-version>6.3</specification-version>
|
<specification-version>6.6</specification-version>
|
||||||
</run-dependency>
|
</run-dependency>
|
||||||
</dependency>
|
</dependency>
|
||||||
</module-dependencies>
|
</module-dependencies>
|
||||||
|
@ -2,10 +2,13 @@
|
|||||||
|
|
||||||
\section portable_case_overview Overview
|
\section portable_case_overview Overview
|
||||||
|
|
||||||
A portable case is a partial copy of a normal Autopsy case that can be opened from anywhere. The general use case is as follows:
|
A portable case is a partial copy of a normal Autopsy case that can be opened from anywhere. It contains a subset of the data from its original case and has been designed to make it easy to share relevant data with other examiners.
|
||||||
|
|
||||||
|
|
||||||
|
The general use case is as follows:
|
||||||
<ol>
|
<ol>
|
||||||
<li>Alice is analyzing one or more data sources using Autopsy. She tags files and results that are of particular interest.
|
<li>Alice is analyzing one or more data sources using Autopsy. She tags files and results that are of particular interest.
|
||||||
<li>Alice wants to share her findings with Bob but is unable to send him the original data sources.
|
<li>Alice wants to share her findings with Bob but is unable to send him the original data sources because he shouldn't see them or the originals are too big.
|
||||||
<li>Alice creates a portable case which will contain only her tagged files and results, plus any files associated with those results, and sends it to Bob.
|
<li>Alice creates a portable case which will contain only her tagged files and results, plus any files associated with those results, and sends it to Bob.
|
||||||
<li>Bob can open the portable case in Autopsy and view all files and results Alice tagged, and run any of the normal Autopsy features.
|
<li>Bob can open the portable case in Autopsy and view all files and results Alice tagged, and run any of the normal Autopsy features.
|
||||||
</ol>
|
</ol>
|
||||||
@ -43,6 +46,14 @@ Portable cases generally behave like any other Autopsy case. You can run ingest,
|
|||||||
|
|
||||||
This may cause warning or error messages when using ingest modules that run on the full image, such as the \ref data_source_integrity_page. You will also not be able to view the data sources in the content viewer.
|
This may cause warning or error messages when using ingest modules that run on the full image, such as the \ref data_source_integrity_page. You will also not be able to view the data sources in the content viewer.
|
||||||
|
|
||||||
You can also add additonal data sources to the portable case if you wish. The case will no longer be portable, but if desired you could generate a new portable case that will include tagged files and results from the new data sources as well as the original case.
|
You can also add additional data sources to the portable case if you wish. The case will no longer be portable, but if desired you could generate a new portable case that will include tagged files and results from the new data sources as well as the original case.
|
||||||
|
|
||||||
*/
|
\section portable_case_inside Inside a Portable Case
|
||||||
|
|
||||||
|
A portable case is a folder, just like any other Autopsy case. It contains a SQLite database (just like a normal Autopsy case) with rows for only the items that the user selected to be in the portable case. For example, if a user tagged a file and included that in the portable case, the database will have a row for the tag, a row for the file, a row for the file system the file was in, a row for the volume system, a row for the image etc. Everything assocated with the tag is in there and you should see those items in Autopsy.
|
||||||
|
|
||||||
|
A copy of any tagged file is made into the case folder and the SQLite database will refer to it. This allows you to examine the file contents without the original data source.
|
||||||
|
|
||||||
|
Because a portable case is really just a subset of the original case, nearly all other Autopsy operations work as normal.
|
||||||
|
|
||||||
|
*/
|
||||||
|
@ -36,7 +36,7 @@
|
|||||||
<compile-dependency/>
|
<compile-dependency/>
|
||||||
<run-dependency>
|
<run-dependency>
|
||||||
<release-version>10</release-version>
|
<release-version>10</release-version>
|
||||||
<specification-version>10.14</specification-version>
|
<specification-version>10.15</specification-version>
|
||||||
</run-dependency>
|
</run-dependency>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
@ -45,7 +45,7 @@
|
|||||||
<compile-dependency/>
|
<compile-dependency/>
|
||||||
<run-dependency>
|
<run-dependency>
|
||||||
<release-version>6</release-version>
|
<release-version>6</release-version>
|
||||||
<specification-version>6.5</specification-version>
|
<specification-version>6.6</specification-version>
|
||||||
</run-dependency>
|
</run-dependency>
|
||||||
</dependency>
|
</dependency>
|
||||||
</module-dependencies>
|
</module-dependencies>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user