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-Localizing-Bundle: org/sleuthkit/autopsy/core/Bundle.properties
|
||||
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
|
||||
AutoUpdate-Show-In-Client: true
|
||||
AutoUpdate-Essential-Module: true
|
||||
|
@ -83,5 +83,5 @@ nbm.homepage=http://www.sleuthkit.org/
|
||||
nbm.module.author=Brian Carrier
|
||||
nbm.needs.restart=true
|
||||
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
|
||||
*
|
||||
* Copyright 2011-2019 Basis Technology Corp.
|
||||
* Copyright 2016-2019 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -38,7 +38,7 @@ import org.sleuthkit.datamodel.TskCoreException;
|
||||
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
|
||||
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;
|
||||
ingestJobsForSelectedDataSource.clear();
|
||||
if (selectedDataSource != null) {
|
||||
@ -109,7 +109,7 @@ public final class IngestJobInfoPanel extends javax.swing.JPanel {
|
||||
try {
|
||||
SleuthkitCase skCase = Case.getCurrentCaseThrows().getSleuthkitCase();
|
||||
this.ingestJobs = skCase.getIngestJobs();
|
||||
updateIngestHistoryData(selectedDataSource);
|
||||
setDataSource(selectedDataSource);
|
||||
} catch (TskCoreException | NoCurrentCaseException 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);
|
||||
|
@ -69,7 +69,7 @@ final class DataSourceSummaryDialog extends javax.swing.JDialog implements Obser
|
||||
DataSource selectedDataSource = dataSourcesPanel.getSelectedDataSource();
|
||||
countsPanel.updateCountsTableData(selectedDataSource);
|
||||
detailsPanel.updateDetailsPanelData(selectedDataSource);
|
||||
ingestHistoryPanel.updateIngestHistoryData(selectedDataSource);
|
||||
ingestHistoryPanel.setDataSource(selectedDataSource);
|
||||
this.repaint();
|
||||
}
|
||||
});
|
||||
|
@ -43,6 +43,8 @@ import org.sleuthkit.autopsy.casemodule.multiusercasesbrowser.MultiUserCaseBrows
|
||||
public final class MultiUserCasesBrowserPanel extends javax.swing.JPanel implements ExplorerManager.Provider {
|
||||
|
||||
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 MultiUserCaseBrowserCustomizer customizer;
|
||||
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.
|
||||
*/
|
||||
|
@ -26,13 +26,29 @@ DataContentViewerOtherCases.earliestCaseLabel.text=Central Repository Starting D
|
||||
DataContentViewerOtherCases.foundInLabel.text=
|
||||
DataContentViewerOtherCases.title=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.noData=No Data.
|
||||
OtherOccurrencesFilesTableModel.attribute=Matched Attribute
|
||||
OtherOccurrencesFilesTableModel.comment=Comment
|
||||
OtherOccurrencesFilesTableModel.dataSource=Data Source
|
||||
OtherOccurrencesFilesTableModel.device=Device
|
||||
OtherOccurrencesFilesTableModel.known=Known
|
||||
OtherOccurrencesDataSourcesTableModel.dataSourceName=Data Source Name
|
||||
OtherOccurrencesDataSourcesTableModel.noData=No Data.
|
||||
OtherOccurrencesFilesTableModel.fileName=File Name
|
||||
OtherOccurrencesFilesTableModel.noData=No Data.
|
||||
OtherOccurrencesFilesTableModel.path=Path
|
||||
OtherOccurrencesFilesTableModel.value=Attribute Value
|
||||
|
@ -46,11 +46,11 @@
|
||||
</NonVisualComponents>
|
||||
<Properties>
|
||||
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[1500, 10]"/>
|
||||
<Dimension value="[600, 10]"/>
|
||||
</Property>
|
||||
<Property name="opaque" type="boolean" value="false"/>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[1500, 44]"/>
|
||||
<Dimension value="[600, 63]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
@ -68,43 +68,14 @@
|
||||
<Layout>
|
||||
<DimensionLayout dim="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>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="otherCasesPanel" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JPanel" name="otherCasesPanel">
|
||||
<Properties>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[921, 62]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<EmptySpace min="0" pref="921" max="32767" attributes="0"/>
|
||||
<Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="tableContainerPanel" max="32767" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<EmptySpace min="0" pref="62" max="32767" attributes="0"/>
|
||||
<Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="tableContainerPanel" pref="62" max="32767" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="tableContainerPanel" pref="64" max="32767" attributes="0"/>
|
||||
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
@ -113,8 +84,9 @@
|
||||
<Container class="javax.swing.JPanel" name="tableContainerPanel">
|
||||
<Properties>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[1500, 63]"/>
|
||||
<Dimension value="[600, 63]"/>
|
||||
</Property>
|
||||
<Property name="requestFocusEnabled" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
|
||||
<Layout>
|
||||
@ -123,13 +95,13 @@
|
||||
<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"/>
|
||||
<Component id="earliestCaseLabel" min="-2" pref="161" 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="jSplitPane2" alignment="0" pref="911" max="32767" attributes="0"/>
|
||||
<Component id="tablesViewerSplitPane" pref="590" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
@ -137,13 +109,16 @@
|
||||
</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="102" attributes="0">
|
||||
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
|
||||
<Component id="tablesViewerSplitPane" pref="33" max="32767" attributes="0"/>
|
||||
<EmptySpace min="-2" 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"/>
|
||||
<Component id="foundInLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="foundInLabel" min="-2" pref="14" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
@ -175,16 +150,32 @@
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Container class="javax.swing.JSplitPane" name="jSplitPane2">
|
||||
<Container class="javax.swing.JSplitPane" name="tablesViewerSplitPane">
|
||||
<Properties>
|
||||
<Property name="dividerLocation" type="int" value="470"/>
|
||||
<Property name="dividerLocation" type="int" value="450"/>
|
||||
<Property name="resizeWeight" type="double" value="0.5"/>
|
||||
</Properties>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout"/>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JSplitPane" name="jSplitPane3">
|
||||
<Container class="javax.swing.JSplitPane" name="caseDatasourceFileSplitPane">
|
||||
<Properties>
|
||||
<Property name="dividerLocation" type="int" value="300"/>
|
||||
<Property name="resizeWeight" type="double" value="0.6"/>
|
||||
<Property name="toolTipText" type="java.lang.String" value=""/>
|
||||
</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"/>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JSplitPane" name="caseDatasourceSplitPane">
|
||||
<Properties>
|
||||
<Property name="dividerLocation" type="int" value="150"/>
|
||||
<Property name="resizeWeight" type="double" value="0.5"/>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<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"/>
|
||||
<SubComponents>
|
||||
<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>
|
||||
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
|
||||
</AuxValues>
|
||||
@ -217,6 +213,11 @@
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<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>
|
||||
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
|
||||
</AuxValues>
|
||||
@ -231,11 +232,8 @@
|
||||
<Component class="javax.swing.JTable" name="dataSourcesTable">
|
||||
<Properties>
|
||||
<Property name="autoCreateRowSorter" type="boolean" value="true"/>
|
||||
<Property name="model" type="javax.swing.table.TableModel" editor="org.netbeans.modules.form.editors2.TableModelEditor">
|
||||
<Table columnCount="2" rowCount="0">
|
||||
<Column editable="false" title="Data Source Name" type="java.lang.Object"/>
|
||||
<Column editable="false" title="Device ID" type="java.lang.Object"/>
|
||||
</Table>
|
||||
<Property name="model" type="javax.swing.table.TableModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
|
||||
<Connection code="dataSourcesTableModel" type="code"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
@ -243,10 +241,10 @@
|
||||
</Container>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Container class="javax.swing.JScrollPane" name="propertiesTableScrollPane">
|
||||
<Container class="javax.swing.JScrollPane" name="filesTableScrollPane">
|
||||
<Properties>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[1000, 30]"/>
|
||||
<Dimension value="[140, 30]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
@ -261,7 +259,7 @@
|
||||
<Properties>
|
||||
<Property name="autoCreateRowSorter" type="boolean" value="true"/>
|
||||
<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 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}")"/>
|
||||
@ -273,7 +271,7 @@
|
||||
<ComponentRef name="rightClickPopupMenu"/>
|
||||
</Property>
|
||||
<Property name="selectionModel" type="javax.swing.ListSelectionModel" editor="org.netbeans.modules.form.editors2.JTableSelectionModelEditor">
|
||||
<JTableSelectionModel selectionMode="1"/>
|
||||
<JTableSelectionModel selectionMode="0"/>
|
||||
</Property>
|
||||
<Property name="tableHeader" type="javax.swing.table.JTableHeader" editor="org.netbeans.modules.form.editors2.JTableHeaderEditor">
|
||||
<TableHeader reorderingAllowed="true" resizingAllowed="true"/>
|
||||
@ -284,6 +282,21 @@
|
||||
</Container>
|
||||
</SubComponents>
|
||||
</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>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Central Repository
|
||||
*
|
||||
* Copyright 2015-2019 Basis Technology Corp.
|
||||
* Copyright 2017-2019 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* 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.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.ComponentAdapter;
|
||||
import java.awt.event.ComponentEvent;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@ -48,9 +50,6 @@ import static javax.swing.JOptionPane.PLAIN_MESSAGE;
|
||||
import static javax.swing.JOptionPane.ERROR_MESSAGE;
|
||||
import javax.swing.JPanel;
|
||||
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.TableRowSorter;
|
||||
import org.joda.time.DateTimeZone;
|
||||
@ -94,35 +93,44 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
||||
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_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 OtherOccurrencesDataSourcesTableModel dataSourcesTableModel;
|
||||
private OccurrencePanel occurrencePanel;
|
||||
private final Collection<CorrelationAttributeInstance> correlationAttributes;
|
||||
private String dataSourceName = "";
|
||||
private String deviceId = "";
|
||||
private String dataSourceName = ""; //the data source of the file which the content viewer is being populated for
|
||||
private String deviceId = ""; //the device id of the data source for the file which the content viewer is being populated for
|
||||
/**
|
||||
* Could be null.
|
||||
*/
|
||||
private AbstractFile file;
|
||||
private AbstractFile file; //the file which the content viewer is being populated for
|
||||
|
||||
/**
|
||||
* Creates new form DataContentViewerOtherCases
|
||||
*/
|
||||
public DataContentViewerOtherCases() {
|
||||
this.tableModel = new OtherOccurrencesFilesTableModel();
|
||||
this.filesTableModel = new OtherOccurrencesFilesTableModel();
|
||||
this.casesTableModel = new OtherOccurrencesCasesTableModel();
|
||||
this.dataSourcesTableModel = new OtherOccurrencesDataSourcesTableModel();
|
||||
this.correlationAttributes = new ArrayList<>();
|
||||
|
||||
occurrencePanel = new OccurrencePanel();
|
||||
initComponents();
|
||||
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();
|
||||
}
|
||||
|
||||
private void customizeComponents() {
|
||||
ActionListener actList = new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
ActionListener actList = (ActionEvent e) -> {
|
||||
JMenuItem jmi = (JMenuItem) e.getSource();
|
||||
if (jmi.equals(selectAllMenuItem)) {
|
||||
filesTable.selectAll();
|
||||
@ -137,7 +145,6 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
||||
} else if (jmi.equals(showCommonalityMenuItem)) {
|
||||
showCommonalityDetails();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
exportToCSVMenuItem.addActionListener(actList);
|
||||
@ -145,10 +152,6 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
||||
showCaseDetailsMenuItem.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.
|
||||
TableRowSorter<TableModel> sorter = new TableRowSorter<>(filesTable.getModel());
|
||||
filesTable.setRowSorter(sorter);
|
||||
@ -162,8 +165,18 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
||||
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);
|
||||
dataSourcesTable.getRowSorter().toggleSortOrder(0);
|
||||
filesTable.getRowSorter().toggleSortOrder(0);
|
||||
}
|
||||
|
||||
@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.noOpenCase.errMsg=No open case available."})
|
||||
private void showCaseDetails(int selectedRowViewIdx) {
|
||||
|
||||
String caseDisplayName = Bundle.DataContentViewerOtherCases_caseDetailsDialog_noCaseNameError();
|
||||
String details = Bundle.DataContentViewerOtherCases_caseDetailsDialog_noDetails();
|
||||
try {
|
||||
if (-1 != selectedRowViewIdx) {
|
||||
EamDb dbManager = EamDb.getInstance();
|
||||
int selectedRowModelIdx = filesTable.convertRowIndexToModel(selectedRowViewIdx);
|
||||
OtherOccurrenceNodeInstanceData nodeData = (OtherOccurrenceNodeInstanceData) tableModel.getRow(selectedRowModelIdx);
|
||||
CorrelationCase eamCasePartial = nodeData.getCorrelationAttributeInstance().getCorrelationCase();
|
||||
if (eamCasePartial == null) {
|
||||
JOptionPane.showConfirmDialog(showCaseDetailsMenuItem,
|
||||
Bundle.DataContentViewerOtherCases_caseDetailsDialog_noDetailsReference(),
|
||||
caseDisplayName,
|
||||
DEFAULT_OPTION, PLAIN_MESSAGE);
|
||||
return;
|
||||
}
|
||||
List<OtherOccurrenceNodeData> rowList = filesTableModel.getListOfNodesForFile(selectedRowModelIdx);
|
||||
if (!rowList.isEmpty()) {
|
||||
if (rowList.get(0) instanceof OtherOccurrenceNodeInstanceData) {
|
||||
CorrelationCase eamCasePartial = ((OtherOccurrenceNodeInstanceData) rowList.get(0)).getCorrelationAttributeInstance().getCorrelationCase();
|
||||
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);
|
||||
if (eamCase != null) {
|
||||
details = eamCase.getCaseDetailsOptionsPaneDialog();
|
||||
} else {
|
||||
JOptionPane.showConfirmDialog(showCaseDetailsMenuItem,
|
||||
Bundle.DataContentViewerOtherCases_caseDetailsDialog_notSelected(),
|
||||
caseDisplayName,
|
||||
DEFAULT_OPTION, PLAIN_MESSAGE);
|
||||
details = Bundle.DataContentViewerOtherCases_caseDetailsDialog_noDetails();
|
||||
}
|
||||
} else {
|
||||
details = Bundle.DataContentViewerOtherCases_caseDetailsDialog_notSelected();
|
||||
}
|
||||
} else {
|
||||
details = Bundle.DataContentViewerOtherCases_caseDetailsDialog_noDetailsReference();
|
||||
}
|
||||
}
|
||||
} catch (EamDbException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Error loading case details", ex);
|
||||
} finally {
|
||||
JOptionPane.showConfirmDialog(showCaseDetailsMenuItem,
|
||||
Bundle.DataContentViewerOtherCases_caseDetailsDialog_noDetails(),
|
||||
details,
|
||||
caseDisplayName,
|
||||
DEFAULT_OPTION, PLAIN_MESSAGE);
|
||||
}
|
||||
}
|
||||
|
||||
private void saveToCSV() throws NoCurrentCaseException {
|
||||
if (0 != filesTable.getSelectedRowCount()) {
|
||||
if (casesTableModel.getRowCount() > 0) {
|
||||
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);
|
||||
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
|
||||
selectedFile = new File(selectedFile.toString() + ".csv"); // NON-NLS
|
||||
}
|
||||
|
||||
writeSelectedRowsToFileAsCSV(selectedFile);
|
||||
writeOtherOccurrencesToFileAsCSV(selectedFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void writeSelectedRowsToFileAsCSV(File destFile) {
|
||||
StringBuilder content;
|
||||
int[] selectedRowViewIndices = filesTable.getSelectedRows();
|
||||
int colCount = tableModel.getColumnCount();
|
||||
|
||||
@Messages({
|
||||
"DataContentViewerOtherCasesModel.csvHeader.case=Case",
|
||||
"DataContentViewerOtherCasesModel.csvHeader.device=Device",
|
||||
"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())) {
|
||||
|
||||
// write column names
|
||||
content = new StringBuilder("");
|
||||
for (int colIdx = 0; colIdx < colCount; colIdx++) {
|
||||
content.append('"').append(tableModel.getColumnName(colIdx)).append('"');
|
||||
if (colIdx < (colCount - 1)) {
|
||||
content.append(",");
|
||||
//write headers
|
||||
StringBuilder headers = new StringBuilder("\"");
|
||||
headers.append(Bundle.DataContentViewerOtherCasesModel_csvHeader_case())
|
||||
.append(OtherOccurrenceNodeInstanceData.getCsvItemSeparator()).append(Bundle.DataContentViewerOtherCasesModel_csvHeader_dataSource())
|
||||
.append(OtherOccurrenceNodeInstanceData.getCsvItemSeparator()).append(Bundle.DataContentViewerOtherCasesModel_csvHeader_attribute())
|
||||
.append(OtherOccurrenceNodeInstanceData.getCsvItemSeparator()).append(Bundle.DataContentViewerOtherCasesModel_csvHeader_value())
|
||||
.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) {
|
||||
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() {
|
||||
// start with empty table
|
||||
casesTableModel.clearTable();
|
||||
((DefaultTableModel) dataSourcesTable.getModel()).setRowCount(0);
|
||||
tableModel.clearTable();
|
||||
dataSourcesTableModel.clearTable();
|
||||
filesTableModel.clearTable();
|
||||
correlationAttributes.clear();
|
||||
earliestCaseDate.setText(Bundle.DataContentViewerOtherCases_earliestCaseNotAvailable());
|
||||
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
|
||||
@ -364,6 +371,7 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
||||
@Override
|
||||
public int isPreferred(Node node) {
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -558,7 +566,6 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
||||
try {
|
||||
final Case openCase = Case.getCurrentCaseThrows();
|
||||
String caseUUID = openCase.getName();
|
||||
|
||||
HashMap<UniquePathKey, OtherOccurrenceNodeInstanceData> nodeDataMap = new HashMap<>();
|
||||
|
||||
if (EamDb.isEnabled()) {
|
||||
@ -583,7 +590,6 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (corAttr.getCorrelationType().getDisplayName().equals("Files")) {
|
||||
List<AbstractFile> caseDbFiles = getCaseDbMatches(corAttr, openCase);
|
||||
|
||||
@ -591,7 +597,6 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
||||
addOrUpdateNodeData(openCase, nodeDataMap, caseDbFile);
|
||||
}
|
||||
}
|
||||
|
||||
return nodeDataMap;
|
||||
} catch (EamDbException ex) {
|
||||
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()));
|
||||
caseNames.put(nodeData.getCorrelationAttributeInstance().getCorrelationCase().getCaseUUID(), nodeData.getCorrelationAttributeInstance().getCorrelationCase());
|
||||
} 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 {
|
||||
try {
|
||||
dataSources.add(makeDataSourceString(Case.getCurrentCaseThrows().getName(), nodeData.getDeviceID(), nodeData.getDataSourceName()));
|
||||
caseNames.put(Case.getCurrentCaseThrows().getName(), new CorrelationCase(Case.getCurrentCaseThrows().getName(), Case.getCurrentCaseThrows().getDisplayName()));
|
||||
} 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++;
|
||||
@ -770,7 +775,6 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
||||
} else if (caseCount == 0) {
|
||||
casesTableModel.addCorrelationCase(NO_RESULTS_CASE);
|
||||
}
|
||||
setColumnWidths();
|
||||
setEarliestCaseDate();
|
||||
foundInLabel.setText(String.format(Bundle.DataContentViewerOtherCases_foundIn_text(), totalCount, caseCount, dataSources.size()));
|
||||
if (caseCount > 0) {
|
||||
@ -791,9 +795,15 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
||||
*/
|
||||
private void updateOnCaseSelection() {
|
||||
int[] selectedCaseIndexes = casesTable.getSelectedRows();
|
||||
DefaultTableModel dataSourceModel = (DefaultTableModel) dataSourcesTable.getModel();
|
||||
dataSourceModel.setRowCount(0);
|
||||
tableModel.clearTable();
|
||||
dataSourcesTableModel.clearTable();
|
||||
filesTableModel.clearTable();
|
||||
|
||||
if (selectedCaseIndexes.length == 0) {
|
||||
//special case when no cases are selected
|
||||
occurrencePanel = new OccurrencePanel();
|
||||
occurrencePanel.getPreferredSize();
|
||||
detailsPanelScrollPane.setViewportView(occurrencePanel);
|
||||
} else {
|
||||
for (CorrelationAttributeInstance corAttr : correlationAttributes) {
|
||||
Map<UniquePathKey, OtherOccurrenceNodeInstanceData> correlatedNodeDataMap = new HashMap<>(0);
|
||||
|
||||
@ -804,14 +814,14 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
||||
try {
|
||||
if (nodeData.isCentralRepoNode()) {
|
||||
if (casesTableModel.getCorrelationCase(casesTable.convertRowIndexToModel(selectedRow)) != null
|
||||
&& ((CorrelationCase) casesTableModel.getCorrelationCase(casesTable.convertRowIndexToModel(selectedRow))).getCaseUUID().equals(nodeData.getCorrelationAttributeInstance().getCorrelationCase().getCaseUUID())) {
|
||||
dataSourceModel.addRow(new Object[]{nodeData.getDataSourceName(), nodeData.getDeviceID()});
|
||||
&& casesTableModel.getCorrelationCase(casesTable.convertRowIndexToModel(selectedRow)).getCaseUUID().equals(nodeData.getCorrelationAttributeInstance().getCorrelationCase().getCaseUUID())) {
|
||||
dataSourcesTableModel.addNodeData(nodeData);
|
||||
}
|
||||
} else {
|
||||
dataSourceModel.addRow(new Object[]{nodeData.getDataSourceName(), nodeData.getDeviceID()});
|
||||
dataSourcesTableModel.addNodeData(nodeData);
|
||||
}
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -820,6 +830,7 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
||||
dataSourcesTable.setRowSelectionInterval(0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates diplayed information to be correct for the current data source
|
||||
@ -827,9 +838,8 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
||||
*/
|
||||
private void updateOnDataSourceSelection() {
|
||||
int[] selectedCaseIndexes = casesTable.getSelectedRows();
|
||||
DefaultTableModel dataSourceModel = (DefaultTableModel) dataSourcesTable.getModel();
|
||||
int[] selectedDataSources = dataSourcesTable.getSelectedRows();
|
||||
tableModel.clearTable();
|
||||
filesTableModel.clearTable();
|
||||
for (CorrelationAttributeInstance corAttr : correlationAttributes) {
|
||||
Map<UniquePathKey, OtherOccurrenceNodeInstanceData> correlatedNodeDataMap = new HashMap<>(0);
|
||||
|
||||
@ -841,43 +851,94 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
||||
try {
|
||||
if (nodeData.isCentralRepoNode()) {
|
||||
if (casesTableModel.getCorrelationCase(casesTable.convertRowIndexToModel(selectedCaseRow)) != null
|
||||
&& ((CorrelationCase) casesTableModel.getCorrelationCase(casesTable.convertRowIndexToModel(selectedCaseRow))).getCaseUUID().equals(nodeData.getCorrelationAttributeInstance().getCorrelationCase().getCaseUUID())
|
||||
&& dataSourceModel.getValueAt(dataSourcesTable.convertRowIndexToModel(selectedDataSourceRow), 1).toString().equals(nodeData.getDeviceID())) {
|
||||
tableModel.addNodeData(nodeData);
|
||||
&& casesTableModel.getCorrelationCase(casesTable.convertRowIndexToModel(selectedCaseRow)).getCaseUUID().equals(nodeData.getCorrelationAttributeInstance().getCorrelationCase().getCaseUUID())
|
||||
&& dataSourcesTableModel.getDeviceIdForRow(dataSourcesTable.convertRowIndexToModel(selectedDataSourceRow)).equals(nodeData.getDeviceID())) {
|
||||
filesTableModel.addNodeData(nodeData);
|
||||
}
|
||||
} else {
|
||||
if (dataSourceModel.getValueAt(dataSourcesTable.convertRowIndexToModel(selectedDataSourceRow), 1).toString().equals(nodeData.getDeviceID())) {
|
||||
tableModel.addNodeData(nodeData);
|
||||
if (dataSourcesTableModel.getDeviceIdForRow(dataSourcesTable.convertRowIndexToModel(selectedDataSourceRow)).equals(nodeData.getDeviceID())) {
|
||||
filesTableModel.addNodeData(nodeData);
|
||||
}
|
||||
}
|
||||
} 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() {
|
||||
for (int idx = 0; idx < tableModel.getColumnCount(); idx++) {
|
||||
TableColumn column = filesTable.getColumnModel().getColumn(idx);
|
||||
column.setMinWidth(DEFAULT_MIN_CELL_WIDTH);
|
||||
int columnWidth = tableModel.getColumnPreferredWidth(idx);
|
||||
if (columnWidth > 0) {
|
||||
column.setPreferredWidth(columnWidth);
|
||||
private void updateOnFileSelection() {
|
||||
if (filesTable.getSelectedRowCount() == 1) {
|
||||
//if there is one file selected update the deatils to show the data for that file
|
||||
occurrencePanel = new OccurrencePanel(filesTableModel.getListOfNodesForFile(filesTable.convertRowIndexToModel(filesTable.getSelectedRow())));
|
||||
} else if (dataSourcesTable.getSelectedRowCount() == 1) {
|
||||
//if no files were selected and only one data source is selected update the information to reflect the data source
|
||||
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;
|
||||
}
|
||||
}
|
||||
for (int idx = 0; idx < dataSourcesTable.getColumnCount(); idx++) {
|
||||
if (dataSourcesTable.getColumnModel().getColumn(idx).getHeaderValue().toString().equals(Bundle.DataContentViewerOtherCases_dataSources_header_text())) {
|
||||
dataSourcesTable.getColumnModel().getColumn(idx).setPreferredWidth(100);
|
||||
occurrencePanel = new OccurrencePanel(caseName, caseCreatedDate, dsName);
|
||||
} else if (casesTable.getSelectedRowCount() == 1) {
|
||||
//if no files were selected and a number of data source other than 1 are selected
|
||||
//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 {
|
||||
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();
|
||||
showCommonalityMenuItem = new javax.swing.JMenuItem();
|
||||
CSVFileChooser = new javax.swing.JFileChooser();
|
||||
otherCasesPanel = new javax.swing.JPanel();
|
||||
tableContainerPanel = new javax.swing.JPanel();
|
||||
earliestCaseLabel = new javax.swing.JLabel();
|
||||
earliestCaseDate = new javax.swing.JLabel();
|
||||
foundInLabel = new javax.swing.JLabel();
|
||||
jSplitPane2 = new javax.swing.JSplitPane();
|
||||
jSplitPane3 = new javax.swing.JSplitPane();
|
||||
tablesViewerSplitPane = new javax.swing.JSplitPane();
|
||||
caseDatasourceFileSplitPane = new javax.swing.JSplitPane();
|
||||
caseDatasourceSplitPane = new javax.swing.JSplitPane();
|
||||
caseScrollPane = new javax.swing.JScrollPane();
|
||||
casesTable = new javax.swing.JTable();
|
||||
dataSourceScrollPane = new javax.swing.JScrollPane();
|
||||
dataSourcesTable = new javax.swing.JTable();
|
||||
propertiesTableScrollPane = new javax.swing.JScrollPane();
|
||||
filesTableScrollPane = new javax.swing.JScrollPane();
|
||||
filesTable = new javax.swing.JTable();
|
||||
detailsPanelScrollPane = new javax.swing.JScrollPane();
|
||||
|
||||
rightClickPopupMenu.addPopupMenuListener(new javax.swing.event.PopupMenuListener() {
|
||||
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
|
||||
rightClickPopupMenu.add(showCommonalityMenuItem);
|
||||
|
||||
setMinimumSize(new java.awt.Dimension(1500, 10));
|
||||
setMinimumSize(new java.awt.Dimension(600, 10));
|
||||
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(1500, 63));
|
||||
tableContainerPanel.setPreferredSize(new java.awt.Dimension(600, 63));
|
||||
tableContainerPanel.setRequestFocusEnabled(false);
|
||||
|
||||
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
|
||||
@ -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
|
||||
|
||||
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.setModel(casesTableModel);
|
||||
caseScrollPane.setViewportView(casesTable);
|
||||
|
||||
jSplitPane3.setLeftComponent(caseScrollPane);
|
||||
caseDatasourceSplitPane.setLeftComponent(caseScrollPane);
|
||||
|
||||
dataSourceScrollPane.setPreferredSize(new java.awt.Dimension(140, 30));
|
||||
|
||||
dataSourcesTable.setAutoCreateRowSorter(true);
|
||||
dataSourcesTable.setModel(new javax.swing.table.DefaultTableModel(
|
||||
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];
|
||||
}
|
||||
});
|
||||
dataSourcesTable.setModel(dataSourcesTableModel);
|
||||
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.setModel(tableModel);
|
||||
filesTable.setModel(filesTableModel);
|
||||
filesTable.setToolTipText(org.openide.util.NbBundle.getMessage(DataContentViewerOtherCases.class, "DataContentViewerOtherCases.table.toolTip.text")); // NOI18N
|
||||
filesTable.setComponentPopupMenu(rightClickPopupMenu);
|
||||
filesTable.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_INTERVAL_SELECTION);
|
||||
propertiesTableScrollPane.setViewportView(filesTable);
|
||||
filesTable.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
|
||||
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);
|
||||
tableContainerPanel.setLayout(tableContainerPanelLayout);
|
||||
@ -997,65 +1059,49 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
||||
.addGroup(tableContainerPanelLayout.createSequentialGroup()
|
||||
.addGroup(tableContainerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(tableContainerPanelLayout.createSequentialGroup()
|
||||
.addComponent(earliestCaseLabel)
|
||||
.addComponent(earliestCaseLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 161, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(earliestCaseDate)
|
||||
.addGap(66, 66, 66)
|
||||
.addComponent(foundInLabel))
|
||||
.addComponent(jSplitPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 911, Short.MAX_VALUE))
|
||||
.addComponent(earliestCaseDate, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(foundInLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
.addComponent(tablesViewerSplitPane, javax.swing.GroupLayout.DEFAULT_SIZE, 590, Short.MAX_VALUE))
|
||||
.addContainerGap())
|
||||
);
|
||||
tableContainerPanelLayout.setVerticalGroup(
|
||||
tableContainerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, tableContainerPanelLayout.createSequentialGroup()
|
||||
.addComponent(jSplitPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 31, Short.MAX_VALUE)
|
||||
.addGroup(tableContainerPanelLayout.createSequentialGroup()
|
||||
.addGap(0, 0, 0)
|
||||
.addComponent(tablesViewerSplitPane, javax.swing.GroupLayout.DEFAULT_SIZE, 33, Short.MAX_VALUE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(tableContainerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
|
||||
.addGroup(tableContainerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(earliestCaseLabel)
|
||||
.addComponent(earliestCaseDate)
|
||||
.addComponent(foundInLabel))
|
||||
.addComponent(earliestCaseDate))
|
||||
.addComponent(foundInLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.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);
|
||||
this.setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
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.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
|
||||
|
||||
private void rightClickPopupMenuPopupMenuWillBecomeVisible(javax.swing.event.PopupMenuEvent evt) {//GEN-FIRST:event_rightClickPopupMenuPopupMenuWillBecomeVisible
|
||||
boolean enableCentralRepoActions = false;
|
||||
|
||||
if (EamDb.isEnabled() && filesTable.getSelectedRowCount() == 1) {
|
||||
int rowIndex = filesTable.getSelectedRow();
|
||||
OtherOccurrenceNodeData selectedNode = (OtherOccurrenceNodeData) tableModel.getRow(rowIndex);
|
||||
if (selectedNode instanceof OtherOccurrenceNodeInstanceData) {
|
||||
OtherOccurrenceNodeInstanceData instanceData = (OtherOccurrenceNodeInstanceData) selectedNode;
|
||||
List<OtherOccurrenceNodeData> selectedFile = filesTableModel.getListOfNodesForFile(rowIndex);
|
||||
if (!selectedFile.isEmpty() && selectedFile.get(0) instanceof OtherOccurrenceNodeInstanceData) {
|
||||
OtherOccurrenceNodeInstanceData instanceData = (OtherOccurrenceNodeInstanceData) selectedFile.get(0);
|
||||
enableCentralRepoActions = instanceData.isCentralRepoNode();
|
||||
}
|
||||
}
|
||||
@ -1065,24 +1111,25 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JFileChooser CSVFileChooser;
|
||||
private javax.swing.JSplitPane caseDatasourceFileSplitPane;
|
||||
private javax.swing.JSplitPane caseDatasourceSplitPane;
|
||||
private javax.swing.JScrollPane caseScrollPane;
|
||||
private javax.swing.JTable casesTable;
|
||||
private javax.swing.JScrollPane dataSourceScrollPane;
|
||||
private javax.swing.JTable dataSourcesTable;
|
||||
private javax.swing.JScrollPane detailsPanelScrollPane;
|
||||
private javax.swing.JLabel earliestCaseDate;
|
||||
private javax.swing.JLabel earliestCaseLabel;
|
||||
private javax.swing.JMenuItem exportToCSVMenuItem;
|
||||
private javax.swing.JTable filesTable;
|
||||
private javax.swing.JScrollPane filesTableScrollPane;
|
||||
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.JMenuItem selectAllMenuItem;
|
||||
private javax.swing.JMenuItem showCaseDetailsMenuItem;
|
||||
private javax.swing.JMenuItem showCommonalityMenuItem;
|
||||
private javax.swing.JPanel tableContainerPanel;
|
||||
private javax.swing.JSplitPane tablesViewerSplitPane;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
|
||||
/**
|
||||
@ -1119,9 +1166,6 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
//int hash = 7;
|
||||
//hash = 67 * hash + this.dataSourceID.hashCode();
|
||||
//hash = 67 * hash + this.filePath.hashCode();
|
||||
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
|
||||
*
|
||||
* Copyright 2018 Basis Technology Corp.
|
||||
* Copyright 2018-2019 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -35,6 +35,7 @@ class OtherOccurrenceNodeInstanceData implements OtherOccurrenceNodeData {
|
||||
// For now hard code the string for the central repo files type, since
|
||||
// getting it dynamically can fail.
|
||||
private static final String FILE_TYPE_STR = "Files";
|
||||
private static final String CSV_ITEM_SEPARATOR = "\",\"";
|
||||
|
||||
private final String caseName;
|
||||
private String deviceID;
|
||||
@ -50,6 +51,7 @@ class OtherOccurrenceNodeInstanceData implements OtherOccurrenceNodeData {
|
||||
|
||||
/**
|
||||
* Create a node from a central repo instance.
|
||||
*
|
||||
* @param instance The central repo instance
|
||||
* @param type The type of the instance
|
||||
* @param value The value of the instance
|
||||
@ -69,8 +71,10 @@ class OtherOccurrenceNodeInstanceData implements OtherOccurrenceNodeData {
|
||||
|
||||
/**
|
||||
* Create a node from an abstract file.
|
||||
*
|
||||
* @param newFile The abstract file
|
||||
* @param autopsyCase The current case
|
||||
*
|
||||
* @throws EamDbException
|
||||
*/
|
||||
OtherOccurrenceNodeInstanceData(AbstractFile newFile, Case autopsyCase) throws EamDbException {
|
||||
@ -94,6 +98,7 @@ class OtherOccurrenceNodeInstanceData implements OtherOccurrenceNodeData {
|
||||
|
||||
/**
|
||||
* Check if this node is a "file" type
|
||||
*
|
||||
* @return true if it is a file type
|
||||
*/
|
||||
boolean isFileType() {
|
||||
@ -102,6 +107,7 @@ class OtherOccurrenceNodeInstanceData implements OtherOccurrenceNodeData {
|
||||
|
||||
/**
|
||||
* Update the known status for this node
|
||||
*
|
||||
* @param newKnownStatus The new known status
|
||||
*/
|
||||
void updateKnown(TskData.FileKnown newKnownStatus) {
|
||||
@ -110,6 +116,7 @@ class OtherOccurrenceNodeInstanceData implements OtherOccurrenceNodeData {
|
||||
|
||||
/**
|
||||
* Update the comment for this node
|
||||
*
|
||||
* @param newComment The new comment
|
||||
*/
|
||||
void updateComment(String newComment) {
|
||||
@ -118,7 +125,9 @@ class OtherOccurrenceNodeInstanceData implements OtherOccurrenceNodeData {
|
||||
|
||||
/**
|
||||
* 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() {
|
||||
return (originalCorrelationInstance != null);
|
||||
@ -126,6 +135,7 @@ class OtherOccurrenceNodeInstanceData implements OtherOccurrenceNodeData {
|
||||
|
||||
/**
|
||||
* Get the case name
|
||||
*
|
||||
* @return the case name
|
||||
*/
|
||||
String getCaseName() {
|
||||
@ -134,6 +144,7 @@ class OtherOccurrenceNodeInstanceData implements OtherOccurrenceNodeData {
|
||||
|
||||
/**
|
||||
* Get the device ID
|
||||
*
|
||||
* @return the device ID
|
||||
*/
|
||||
String getDeviceID() {
|
||||
@ -142,6 +153,7 @@ class OtherOccurrenceNodeInstanceData implements OtherOccurrenceNodeData {
|
||||
|
||||
/**
|
||||
* Get the data source name
|
||||
*
|
||||
* @return the data source name
|
||||
*/
|
||||
String getDataSourceName() {
|
||||
@ -150,6 +162,7 @@ class OtherOccurrenceNodeInstanceData implements OtherOccurrenceNodeData {
|
||||
|
||||
/**
|
||||
* Get the file path
|
||||
*
|
||||
* @return the file path
|
||||
*/
|
||||
String getFilePath() {
|
||||
@ -158,6 +171,7 @@ class OtherOccurrenceNodeInstanceData implements OtherOccurrenceNodeData {
|
||||
|
||||
/**
|
||||
* Get the type (as a string)
|
||||
*
|
||||
* @return the type
|
||||
*/
|
||||
String getType() {
|
||||
@ -166,6 +180,7 @@ class OtherOccurrenceNodeInstanceData implements OtherOccurrenceNodeData {
|
||||
|
||||
/**
|
||||
* Get the value (MD5 hash for files)
|
||||
*
|
||||
* @return the value
|
||||
*/
|
||||
String getValue() {
|
||||
@ -174,6 +189,7 @@ class OtherOccurrenceNodeInstanceData implements OtherOccurrenceNodeData {
|
||||
|
||||
/**
|
||||
* Get the known status
|
||||
*
|
||||
* @return the known status
|
||||
*/
|
||||
TskData.FileKnown getKnown() {
|
||||
@ -182,6 +198,7 @@ class OtherOccurrenceNodeInstanceData implements OtherOccurrenceNodeData {
|
||||
|
||||
/**
|
||||
* Get the comment
|
||||
*
|
||||
* @return the comment
|
||||
*/
|
||||
String getComment() {
|
||||
@ -189,8 +206,9 @@ class OtherOccurrenceNodeInstanceData implements OtherOccurrenceNodeData {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the backing abstract file.
|
||||
* Should only be called if isCentralRepoNode() is false
|
||||
* Get the backing abstract file. Should only be called if
|
||||
* isCentralRepoNode() is false
|
||||
*
|
||||
* @return the original abstract file
|
||||
*/
|
||||
AbstractFile getAbstractFile() throws EamDbException {
|
||||
@ -201,9 +219,11 @@ class OtherOccurrenceNodeInstanceData implements OtherOccurrenceNodeData {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the backing CorrelationAttributeInstance.
|
||||
* Should only be called if isCentralRepoNode() is true
|
||||
* Get the backing CorrelationAttributeInstance. Should only be called if
|
||||
* isCentralRepoNode() is true
|
||||
*
|
||||
* @return the original CorrelationAttributeInstance
|
||||
*
|
||||
* @throws EamDbException
|
||||
*/
|
||||
CorrelationAttributeInstance getCorrelationAttributeInstance() throws EamDbException {
|
||||
@ -212,4 +232,33 @@ class OtherOccurrenceNodeInstanceData implements OtherOccurrenceNodeData {
|
||||
}
|
||||
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 javax.swing.table.AbstractTableModel;
|
||||
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
|
||||
@ -32,26 +33,16 @@ public class OtherOccurrencesCasesTableModel extends AbstractTableModel {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private final List<CorrelationCaseWrapper> correlationCaseList = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Create a table model for displaying case names
|
||||
*/
|
||||
OtherOccurrencesCasesTableModel() {
|
||||
// This constructor is intentionally empty.
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getColumnCount() {
|
||||
return TableColumns.values().length;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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();
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -59,45 +50,43 @@ public class OtherOccurrencesCasesTableModel extends AbstractTableModel {
|
||||
return correlationCaseList.size();
|
||||
}
|
||||
|
||||
@Messages({"OtherOccurrencesCasesTableModel.case=Case",})
|
||||
@Override
|
||||
public String getColumnName(int colIdx) {
|
||||
return TableColumns.values()[colIdx].columnName();
|
||||
return Bundle.OtherOccurrencesCasesTableModel_case();
|
||||
}
|
||||
|
||||
@Messages({"OtherOccurrencesCasesTableModel.noData=No Data."})
|
||||
@Override
|
||||
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();
|
||||
}
|
||||
|
||||
CorrelationCaseWrapper caseWrapper = correlationCaseList.get(rowIdx);
|
||||
TableColumns columnId = TableColumns.values()[colIdx];
|
||||
return mapCorrelationCase(caseWrapper, columnId);
|
||||
return correlationCaseList.get(rowIdx).getMessage();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 columnId The ID of the cell column.
|
||||
* @param rowIdx the row from the table model which corresponds to the case
|
||||
*
|
||||
* @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."})
|
||||
private Object mapCorrelationCase(CorrelationCaseWrapper correlationCaseWrapper, TableColumns columnId) {
|
||||
String value = Bundle.OtherOccurrencesCasesTableModel_noData();
|
||||
|
||||
switch (columnId) {
|
||||
case CASE_NAME:
|
||||
value = correlationCaseWrapper.getMessage();
|
||||
break;
|
||||
default: //Use default "No data" value.
|
||||
break;
|
||||
CorrelationCase getCorrelationCase(int rowIdx) {
|
||||
//if anything would prevent this from working we will return null
|
||||
if (correlationCaseList.isEmpty() || rowIdx < 0
|
||||
|| rowIdx >= correlationCaseList.size()
|
||||
|| correlationCaseList.get(rowIdx) == null) {
|
||||
return null;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
Object getCorrelationCase(int rowIdx) {
|
||||
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
|
||||
*/
|
||||
@ -123,27 +112,4 @@ public class OtherOccurrencesCasesTableModel extends AbstractTableModel {
|
||||
correlationCaseList.clear();
|
||||
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;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.swing.table.AbstractTableModel;
|
||||
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 {
|
||||
|
||||
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",
|
||||
"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<>();
|
||||
|
||||
/**
|
||||
* Create a table model for displaying file names
|
||||
*/
|
||||
OtherOccurrencesFilesTableModel() {
|
||||
|
||||
// This constructor is intentionally empty.
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getColumnCount() {
|
||||
return TableColumns.values().length;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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();
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRowCount() {
|
||||
return nodeDataList.size();
|
||||
return nodeKeys.size();
|
||||
}
|
||||
|
||||
@Messages({"OtherOccurrencesFilesTableModel.fileName=File Name",
|
||||
"OtherOccurrencesFilesTableModel.noData=No Data."})
|
||||
@Override
|
||||
public String getColumnName(int colIdx) {
|
||||
return TableColumns.values()[colIdx].columnName();
|
||||
return Bundle.OtherOccurrencesFilesTableModel_fileName();
|
||||
}
|
||||
|
||||
@Override
|
||||
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();
|
||||
}
|
||||
|
||||
OtherOccurrenceNodeData nodeData = nodeDataList.get(rowIdx);
|
||||
TableColumns columnId = TableColumns.values()[colIdx];
|
||||
if (nodeData instanceof OtherOccurrenceNodeMessageData) {
|
||||
return mapNodeMessageData((OtherOccurrenceNodeMessageData) nodeData, columnId);
|
||||
}
|
||||
return mapNodeInstanceData((OtherOccurrenceNodeInstanceData) nodeData, columnId);
|
||||
return FilenameUtils.getName(((OtherOccurrenceNodeInstanceData) nodeMap.get(nodeKeys.get(rowIdx)).get(0)).getFilePath());
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 columnId The ID of the cell column.
|
||||
* @param rowIdx the index of the file to get data for
|
||||
*
|
||||
* @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) {
|
||||
if (columnId == TableColumns.ATTRIBUTE) {
|
||||
return nodeData.getDisplayMessage();
|
||||
List<OtherOccurrenceNodeData> getListOfNodesForFile(int rowIdx) {
|
||||
//if anything would prevent this from working return an empty list
|
||||
if (nodeMap.isEmpty() || nodeKeys.isEmpty() || rowIdx < 0
|
||||
|| rowIdx >= nodeKeys.size() || nodeKeys.get(rowIdx) == null
|
||||
|| nodeMap.get(nodeKeys.get(rowIdx)) == null) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
return nodeMap.get(nodeKeys.get(rowIdx));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -176,15 +102,27 @@ public class OtherOccurrencesFilesTableModel extends AbstractTableModel {
|
||||
* @param newNodeData data to add to the table
|
||||
*/
|
||||
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();
|
||||
}
|
||||
|
||||
private String createNodeKey(OtherOccurrenceNodeInstanceData nodeData) {
|
||||
return nodeData.getCaseName() + nodeData.getDataSourceName() + nodeData.getDeviceID() + nodeData.getFilePath();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the node data table.
|
||||
*/
|
||||
void clearTable() {
|
||||
nodeDataList.clear();
|
||||
nodeKeys.clear();
|
||||
nodeMap.clear();
|
||||
fireTableDataChanged();
|
||||
}
|
||||
|
||||
|
@ -44,7 +44,7 @@ public final class ContactDetailsPane extends javax.swing.JPanel implements Expl
|
||||
* @param nodes List of nodes to set
|
||||
*/
|
||||
public void setNode(Node[] nodes) {
|
||||
if (nodes != null) {
|
||||
if (nodes != null && nodes.length > 0) {
|
||||
nameLabel.setText(nodes[0].getDisplayName());
|
||||
} else {
|
||||
nameLabel.setText("");
|
||||
|
@ -18,9 +18,7 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.communications;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.TimeZone;
|
||||
import java.util.logging.Level;
|
||||
import org.openide.nodes.Sheet;
|
||||
@ -31,16 +29,9 @@ import org.sleuthkit.autopsy.datamodel.NodeProperty;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT;
|
||||
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_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 org.sleuthkit.datamodel.Content;
|
||||
import org.sleuthkit.datamodel.TimeUtilities;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
|
@ -100,12 +100,8 @@ public final class ContactsViewer extends JPanel implements RelationshipsViewer,
|
||||
tableEM.addPropertyChangeListener((PropertyChangeEvent evt) -> {
|
||||
if (evt.getPropertyName().equals(ExplorerManager.PROP_SELECTED_NODES)) {
|
||||
final Node[] nodes = tableEM.getSelectedNodes();
|
||||
|
||||
if (nodes != null && nodes.length > 0) {
|
||||
contactPane.setEnabled(true);
|
||||
contactPane.setNode(nodes);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
tableEM.setRootContext(new TableFilterNode(new DataResultFilterNode(new AbstractNode(Children.create(nodeFactory, true)), getExplorerManager()), true));
|
||||
|
@ -98,7 +98,6 @@ import org.apache.commons.lang3.StringUtils;
|
||||
import org.controlsfx.control.Notifications;
|
||||
import org.jdesktop.layout.GroupLayout;
|
||||
import org.jdesktop.layout.LayoutStyle;
|
||||
import org.openide.util.Lookup;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.windows.WindowManager;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
|
@ -59,7 +59,7 @@
|
||||
</Property>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new BeanTreeView()"/>
|
||||
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new ExpansionBeanTreeView()"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2019 Basis Technology Corp.
|
||||
* Copyright 2012-2019 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -26,7 +26,6 @@ import java.beans.PropertyVetoException;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
@ -47,6 +46,7 @@ import javax.swing.tree.TreeSelectionModel;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.openide.explorer.ExplorerManager;
|
||||
import org.openide.explorer.ExplorerUtils;
|
||||
import org.openide.explorer.view.BeanTreeView;
|
||||
import org.openide.explorer.view.Visualizer;
|
||||
import org.openide.nodes.AbstractNode;
|
||||
import org.openide.nodes.Children;
|
||||
@ -128,7 +128,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
||||
getTree().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
|
||||
//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.
|
||||
getTree().addTreeExpansionListener(new TreeExpansionListener() {
|
||||
((ExpansionBeanTreeView )getTree()).addTreeExpansionListener(new TreeExpansionListener() {
|
||||
@Override
|
||||
public void treeExpanded(TreeExpansionEvent event) {
|
||||
//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.
|
||||
*/
|
||||
private void preExpandNodes(Children rootChildren) {
|
||||
ExpansionBeanTreeView tree = getTree();
|
||||
BeanTreeView tree = getTree();
|
||||
|
||||
Node results = rootChildren.findChild(ResultsNode.NAME);
|
||||
if (!Objects.isNull(results)) {
|
||||
@ -930,8 +930,8 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
||||
*
|
||||
* @return tree the BeanTreeView
|
||||
*/
|
||||
public ExpansionBeanTreeView getTree() {
|
||||
return (ExpansionBeanTreeView) this.treeView;
|
||||
BeanTreeView getTree() {
|
||||
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.
|
||||
*/
|
||||
class ExpansionBeanTreeView extends BeanTreeView {
|
||||
final class ExpansionBeanTreeView extends BeanTreeView {
|
||||
public void addTreeExpansionListener(TreeExpansionListener listener) {
|
||||
this.tree.addTreeExpansionListener(listener);
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ FileReportDataTypes.knownStatus.text=Known Status
|
||||
FileReportDataTypes.perms.text=Permissions
|
||||
FileReportDataTypes.path.text=Full Path
|
||||
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.ingestWarning.text=Warning, this report was run before ingest services completed\!
|
||||
ReportBodyFile.progress.loading=Loading files...
|
||||
@ -258,3 +258,5 @@ CreatePortableCasePanel.outputFolderTextField.text=jTextField1
|
||||
CreatePortableCasePanel.chooseOutputFolderButton.text=Choose folder
|
||||
CreatePortableCasePanel.jLabel1.text=Export files tagged as:
|
||||
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.path.text=Full Path
|
||||
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.ingestWarning.text=Warning, this report was run before ingest services completed\!
|
||||
ReportBodyFile.progress.loading=Loading files...
|
||||
@ -306,4 +306,6 @@ CreatePortableCasePanel.outputFolderTextField.text=jTextField1
|
||||
CreatePortableCasePanel.chooseOutputFolderButton.text=Choose folder
|
||||
CreatePortableCasePanel.jLabel1.text=Export files tagged as:
|
||||
CreatePortableCasePanel.jLabel2.text=Select output folder:
|
||||
ReportFileTextConfigurationPanel.tabDelimitedButton.text=Tab delimited
|
||||
ReportFileTextConfigurationPanel.commaDelimitedButton.text=Comma delimited
|
||||
TableReportGenerator.StatusColumn.Header=Review Status
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2013 - 2018 Basis Technology Corp.
|
||||
* Copyright 2013 - 2019 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -19,6 +19,7 @@
|
||||
package org.sleuthkit.autopsy.report;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStreamWriter;
|
||||
@ -27,6 +28,7 @@ import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import javax.swing.JPanel;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
|
||||
import org.openide.util.NbBundle;
|
||||
@ -36,18 +38,18 @@ import org.sleuthkit.datamodel.AbstractFile;
|
||||
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
|
||||
*/
|
||||
class FileReportText implements FileReportModule {
|
||||
|
||||
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 Writer out;
|
||||
private static final String FILE_NAME = "file-report.txt"; //NON-NLS
|
||||
|
||||
private static FileReportText instance;
|
||||
private ReportFileTextConfigurationPanel configPanel;
|
||||
|
||||
// Get the default implementation of this report
|
||||
public static synchronized FileReportText getDefault() {
|
||||
@ -62,7 +64,7 @@ class FileReportText implements FileReportModule {
|
||||
this.reportPath = baseReportDir + FILE_NAME;
|
||||
try {
|
||||
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
|
||||
}
|
||||
}
|
||||
@ -85,11 +87,12 @@ class FileReportText implements FileReportModule {
|
||||
}
|
||||
}
|
||||
|
||||
private String getTabDelimitedList(List<String> list) {
|
||||
StringBuilder output = new StringBuilder();
|
||||
private String getDelimitedList(List<String> list, String delimiter) {
|
||||
StringBuilder output;
|
||||
output = new StringBuilder();
|
||||
Iterator<String> it = list.iterator();
|
||||
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();
|
||||
}
|
||||
@ -101,7 +104,7 @@ class FileReportText implements FileReportModule {
|
||||
titles.add(col.getName());
|
||||
}
|
||||
try {
|
||||
out.write(getTabDelimitedList(titles));
|
||||
out.write(getDelimitedList(titles, configPanel.getDelimiter()));
|
||||
} catch (IOException ex) {
|
||||
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));
|
||||
}
|
||||
try {
|
||||
out.write(getTabDelimitedList(cells));
|
||||
out.write(getDelimitedList(cells, configPanel.getDelimiter()));
|
||||
} catch (IOException ex) {
|
||||
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() {
|
||||
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.monitor</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.builder</package>
|
||||
<package>org.apache.commons.lang.enums</package>
|
||||
|
@ -135,7 +135,7 @@
|
||||
<compile-dependency/>
|
||||
<run-dependency>
|
||||
<release-version>10</release-version>
|
||||
<specification-version>10.14</specification-version>
|
||||
<specification-version>10.15</specification-version>
|
||||
</run-dependency>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@ -153,7 +153,7 @@
|
||||
<compile-dependency/>
|
||||
<run-dependency>
|
||||
<release-version>6</release-version>
|
||||
<specification-version>6.5</specification-version>
|
||||
<specification-version>6.6</specification-version>
|
||||
</run-dependency>
|
||||
</dependency>
|
||||
</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_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 int AID_REFRESH_INTERVAL_SECS = 30;
|
||||
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
|
||||
* that use the models.
|
||||
* Reloads the table models using a RefreshChildrenEvent and refreshes the
|
||||
* JTables that use the models.
|
||||
*
|
||||
*/
|
||||
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() {
|
||||
File f = new File(ADMIN_ACCESS_FILE_PATH);
|
||||
return f.exists();
|
||||
return new File(ADMIN_ACCESS_FILE_PATH).exists() || new File(ADMIN_EXT_ACCESS_FILE_PATH).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
|
||||
* service node for the job.
|
||||
*
|
||||
* @throws AutoIngestJobException If there was an error working
|
||||
* with the node data.
|
||||
* @throws AutoIngestJobException If there was an error working with the
|
||||
* node data.
|
||||
* @throws InterruptedException If the thread running the input
|
||||
* directory scan task is
|
||||
* interrupted while blocked, i.e.,
|
||||
* if auto ingest is shutting down.
|
||||
* directory scan task is interrupted
|
||||
* while blocked, i.e., if auto ingest is
|
||||
* shutting down.
|
||||
*/
|
||||
private void addPendingJob(Manifest manifest, AutoIngestJobNodeData nodeData) throws AutoIngestJobException, InterruptedException {
|
||||
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);
|
||||
}
|
||||
}
|
||||
updateAutoIngestJobData(job);
|
||||
newPendingJobsList.add(job);
|
||||
} else {
|
||||
job.setProcessingStatus(AutoIngestJob.ProcessingStatus.COMPLETED);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
updateAutoIngestJobData(job);
|
||||
newPendingJobsList.add(job);
|
||||
newCompletedJobsList.add(job);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1440,12 +1442,12 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen
|
||||
* @param nodeData The data stored in the manifest file lock
|
||||
* coordination service node for the job.
|
||||
*
|
||||
* @throws AutoIngestJobException If there was an error working
|
||||
* with the node data.
|
||||
* @throws AutoIngestJobException If there was an error working with the
|
||||
* node data.
|
||||
* @throws InterruptedException If the thread running the input
|
||||
* directory scan task is
|
||||
* interrupted while blocked, i.e.,
|
||||
* if auto ingest is shutting down.
|
||||
* directory scan task is interrupted
|
||||
* while blocked, i.e., if auto ingest is
|
||||
* shutting down.
|
||||
*/
|
||||
private void addCompletedJob(Manifest manifest, AutoIngestJobNodeData nodeData) throws AutoIngestJobException, InterruptedException {
|
||||
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()));
|
||||
if (!nodeData.getProcessingStatus().equals(PENDING)) {
|
||||
iterator.remove();
|
||||
manifestLock.release();
|
||||
manifestLock = null;
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ditto for the presence of the manifest file.
|
||||
*/
|
||||
File manifestFile = nodeData.getManifestFilePath().toFile();
|
||||
if (!manifestFile.exists()) {
|
||||
iterator.remove();
|
||||
manifestLock.release();
|
||||
manifestLock = null;
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Finally, check for devoting too many resources to a
|
||||
* single case, if the check is enabled.
|
||||
*/
|
||||
if (enforceMaxJobsPerCase) {
|
||||
int currentJobsForCase = 0;
|
||||
for (AutoIngestJob runningJob : hostNamesToRunningJobs.values()) {
|
||||
|
@ -18,14 +18,11 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.experimental.autoingest;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.swing.Action;
|
||||
import org.sleuthkit.autopsy.casemodule.multiusercases.CaseNodeData;
|
||||
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
|
||||
@ -34,8 +31,6 @@ import org.sleuthkit.autopsy.coreutils.PlatformUtil;
|
||||
*/
|
||||
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 DeleteCaseInputAction deleteCaseInputAction;
|
||||
private final DeleteCaseOutputAction deleteCaseOutputAction;
|
||||
@ -67,7 +62,7 @@ final class CasesDashboardCustomizer implements MultiUserCaseBrowserCustomizer {
|
||||
properties.add(Column.LAST_ACCESS_DATE);
|
||||
properties.add(Column.DIRECTORY);
|
||||
properties.add(Column.MANIFEST_FILE_ZNODES_DELETE_STATUS);
|
||||
if (CasesDashboardCustomizer.extendedFeaturesAreEnabled()) {
|
||||
if (AutoIngestDashboard.extendedFeaturesAreEnabled()) {
|
||||
properties.add(Column.DATA_SOURCES_DELETE_STATUS);
|
||||
}
|
||||
properties.add(Column.TEXT_INDEX_DELETE_STATUS);
|
||||
@ -93,7 +88,7 @@ final class CasesDashboardCustomizer implements MultiUserCaseBrowserCustomizer {
|
||||
List<Action> actions = new ArrayList<>();
|
||||
actions.add(new OpenCaseAction(nodeData));
|
||||
actions.add(new OpenAutoIngestLogAction(nodeData));
|
||||
if (CasesDashboardCustomizer.extendedFeaturesAreEnabled()) {
|
||||
if (AutoIngestDashboard.extendedFeaturesAreEnabled()) {
|
||||
actions.add(deleteCaseInputAction);
|
||||
actions.add(deleteCaseOutputAction);
|
||||
actions.add(deleteCaseInputAndOutputAction);
|
||||
@ -108,15 +103,4 @@ final class CasesDashboardCustomizer implements MultiUserCaseBrowserCustomizer {
|
||||
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
|
||||
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-Localizing-Bundle: org/sleuthkit/autopsy/imagegallery/Bundle.properties
|
||||
|
||||
|
@ -127,7 +127,7 @@
|
||||
<compile-dependency/>
|
||||
<run-dependency>
|
||||
<release-version>10</release-version>
|
||||
<specification-version>10.14</specification-version>
|
||||
<specification-version>10.15</specification-version>
|
||||
</run-dependency>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
@ -646,13 +646,22 @@ public class GroupManager {
|
||||
// reset the hash cache
|
||||
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)
|
||||
Set<GroupKey<?>> groupsForFile = getGroupKeysForCurrentGroupBy(fileId);
|
||||
for (GroupKey<?> gk : groupsForFile) {
|
||||
// see if a group has been created yet for the key
|
||||
DrawableGroup g = getGroupForKey(gk);
|
||||
|
||||
updateCurrentPathGroup(gk);
|
||||
addFileToGroup(g, gk, fileId);
|
||||
}
|
||||
}
|
||||
@ -757,7 +766,9 @@ public class GroupManager {
|
||||
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);
|
||||
sortAnalyzedGroups();
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
Manifest-Version: 1.0
|
||||
AutoUpdate-Show-In-Client: true
|
||||
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-Layer: org/sleuthkit/autopsy/keywordsearch/layer.xml
|
||||
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-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.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.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
|
||||
@ -141,4 +142,4 @@ license.file=../LICENSE-2.0.txt
|
||||
nbm.homepage=http://www.sleuthkit.org/autopsy/
|
||||
nbm.needs.restart=true
|
||||
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/>
|
||||
<run-dependency>
|
||||
<release-version>10</release-version>
|
||||
<specification-version>10.14</specification-version>
|
||||
<specification-version>10.15</specification-version>
|
||||
</run-dependency>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@ -133,9 +133,107 @@
|
||||
</dependency>
|
||||
</module-dependencies>
|
||||
<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.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.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.slf4j</package>
|
||||
<package>org.slf4j.event</package>
|
||||
<package>org.slf4j.helpers</package>
|
||||
<package>org.slf4j.spi</package>
|
||||
</public-packages>
|
||||
<class-path-extension>
|
||||
<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>
|
||||
<binary-origin>release/modules/ext/jmatio-1.2.jar</binary-origin>
|
||||
</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>
|
||||
<runtime-relative-path>ext/commons-csv-1.0.jar</runtime-relative-path>
|
||||
<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
|
||||
* of account number search and may be removed in the future.
|
||||
*/
|
||||
class Keyword {
|
||||
public class Keyword {
|
||||
|
||||
private String searchTerm;
|
||||
private boolean isLiteral;
|
||||
@ -123,7 +123,7 @@ class Keyword {
|
||||
*
|
||||
* @return The search term.
|
||||
*/
|
||||
String getSearchTerm() {
|
||||
public String getSearchTerm() {
|
||||
return searchTerm;
|
||||
}
|
||||
|
||||
@ -133,7 +133,7 @@ class Keyword {
|
||||
*
|
||||
* @return True or false.
|
||||
*/
|
||||
boolean searchTermIsLiteral() {
|
||||
public boolean searchTermIsLiteral() {
|
||||
return isLiteral;
|
||||
}
|
||||
|
||||
@ -144,7 +144,7 @@ class Keyword {
|
||||
*
|
||||
* @return True or false.
|
||||
*/
|
||||
boolean searchTermIsWholeWord() {
|
||||
public boolean searchTermIsWholeWord() {
|
||||
return isWholeWord;
|
||||
}
|
||||
|
||||
|
@ -167,7 +167,7 @@ public class KeywordList {
|
||||
*
|
||||
* @return A colleciton of Keyword objects.
|
||||
*/
|
||||
List<Keyword> getKeywords() {
|
||||
public List<Keyword> getKeywords() {
|
||||
return keywords;
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2014 Basis Technology Corp.
|
||||
* Copyright 2014-2019 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* @return an instance of KeywordListsManager.
|
||||
*/
|
||||
public static synchronized KeywordListsManager getInstance() {
|
||||
if (instance == null) {
|
||||
@ -73,6 +75,17 @@ public class KeywordListsManager extends Observable {
|
||||
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.
|
||||
*/
|
||||
|
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 --------------
|
||||
New Features:
|
||||
- Users can now view information on all cases/data sources in the Central
|
||||
|
@ -1,6 +1,6 @@
|
||||
Manifest-Version: 1.0
|
||||
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-Localizing-Bundle: org/sleuthkit/autopsy/recentactivity/Bundle.properties
|
||||
OpenIDE-Module-Requires:
|
||||
|
@ -60,7 +60,7 @@
|
||||
<compile-dependency/>
|
||||
<run-dependency>
|
||||
<release-version>10</release-version>
|
||||
<specification-version>10.14</specification-version>
|
||||
<specification-version>10.15</specification-version>
|
||||
</run-dependency>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
@ -32,15 +32,15 @@ import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.recentactivity.BinaryCookieReader.Cookie;
|
||||
|
||||
/**
|
||||
* The binary cookie reader encapsulates all the knowledge of how to read the mac
|
||||
* .binarycookie files into one class.
|
||||
* The binary cookie reader encapsulates all the knowledge of how to read the
|
||||
* mac .binarycookie files into one class.
|
||||
*
|
||||
* 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
|
||||
* 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 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());
|
||||
|
||||
/**
|
||||
* The binary cookie reader encapsulates all the knowledge of how to read the mac
|
||||
* .binarycookie files into one class.
|
||||
* The binary cookie reader encapsulates all the knowledge of how to read
|
||||
* the mac .binarycookie files into one class.
|
||||
*
|
||||
*/
|
||||
private BinaryCookieReader(File cookieFile, int[] pageSizeArray) {
|
||||
@ -130,7 +130,7 @@ public final class BinaryCookieReader implements Iterable<Cookie> {
|
||||
* The cookiePageIterator iterates the binarycookie file by page.
|
||||
*/
|
||||
CookiePageIterator() {
|
||||
if(pageSizeArray == null || pageSizeArray.length == 0) {
|
||||
if (pageSizeArray == null || pageSizeArray.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -360,7 +360,7 @@ public final class BinaryCookieReader implements Iterable<Cookie> {
|
||||
* @return Cookie expiration date in milliseconds with java epoch
|
||||
*/
|
||||
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
|
||||
*/
|
||||
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;
|
||||
List<HashMap<String, Object>> list;
|
||||
String connectionString = "jdbc:sqlite:" + path; //NON-NLS
|
||||
SQLiteDBConnect tempdbconnect = null;
|
||||
try {
|
||||
SQLiteDBConnect tempdbconnect = new SQLiteDBConnect("org.sqlite.JDBC", connectionString); //NON-NLS
|
||||
tempdbconnect = new SQLiteDBConnect("org.sqlite.JDBC", connectionString); //NON-NLS
|
||||
temprs = tempdbconnect.executeQry(query);
|
||||
list = this.resultSetToArrayList(temprs);
|
||||
tempdbconnect.closeConnection();
|
||||
} catch (SQLException ex) {
|
||||
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()));
|
||||
return Collections.<HashMap<String, Object>>emptyList();
|
||||
}
|
||||
finally {
|
||||
if (tempdbconnect != null) {
|
||||
tempdbconnect.closeConnection();
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
|
@ -253,6 +253,7 @@ class ExtractRegistry extends Extract {
|
||||
logger.log(Level.WARNING, "Keyword search service not found. Report will not be indexed");
|
||||
} else {
|
||||
searchService.index(report);
|
||||
report.close();
|
||||
}
|
||||
} catch (TskCoreException e) {
|
||||
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
|
||||
boolean found = false;
|
||||
ResultSet temprs;
|
||||
SQLiteDBConnect tempdbconnect = null;
|
||||
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);
|
||||
while (temprs.next()) {
|
||||
if (temprs.getString("name") == null ? column == null : temprs.getString("name").equals(column)) { //NON-NLS
|
||||
@ -159,6 +160,11 @@ class Util {
|
||||
} catch (Exception ex) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -47,7 +47,7 @@
|
||||
<compile-dependency/>
|
||||
<run-dependency>
|
||||
<release-version>10</release-version>
|
||||
<specification-version>10.14</specification-version>
|
||||
<specification-version>10.15</specification-version>
|
||||
</run-dependency>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@ -56,7 +56,7 @@
|
||||
<compile-dependency/>
|
||||
<run-dependency>
|
||||
<release-version>6</release-version>
|
||||
<specification-version>6.3</specification-version>
|
||||
<specification-version>6.6</specification-version>
|
||||
</run-dependency>
|
||||
</dependency>
|
||||
</module-dependencies>
|
||||
|
@ -2,10 +2,13 @@
|
||||
|
||||
\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>
|
||||
<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>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>
|
||||
@ -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.
|
||||
|
||||
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/>
|
||||
<run-dependency>
|
||||
<release-version>10</release-version>
|
||||
<specification-version>10.14</specification-version>
|
||||
<specification-version>10.15</specification-version>
|
||||
</run-dependency>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@ -45,7 +45,7 @@
|
||||
<compile-dependency/>
|
||||
<run-dependency>
|
||||
<release-version>6</release-version>
|
||||
<specification-version>6.5</specification-version>
|
||||
<specification-version>6.6</specification-version>
|
||||
</run-dependency>
|
||||
</dependency>
|
||||
</module-dependencies>
|
||||
|
Loading…
x
Reference in New Issue
Block a user